summaryrefslogtreecommitdiffhomepage
path: root/bin
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-31 22:32:34 +0900
committerAdam Malczewski <[email protected]>2026-05-31 22:32:34 +0900
commit1853dd1d40308deb829bc621beb79c5d39b9c57f (patch)
treeee5657560480130f3056694c31cdcc27c9430c5a /bin
parentcb640f25b577a68ceea76b7c9a95a198e5e91441 (diff)
downloaddispatch-1853dd1d40308deb829bc621beb79c5d39b9c57f.tar.gz
dispatch-1853dd1d40308deb829bc621beb79c5d39b9c57f.zip
feat(debug): wire LLM debug logger end-to-end
The debug-logger.ts module existed but was completely orphaned — none of its functions had any callsites, so DISPATCH_DEBUG_LLM=1 did nothing. Wires it in across the stack: - llm/debug-logger.ts: add wrapFetchWithLogging() that tees SSE bodies via TransformStream + response.clone() so we capture every chunk without draining the body the AI SDK consumes. Redacts authorization / x-api-key / cookie headers in logs. Also exports nextDebugSeq() so requests and log files share an id. - llm/provider.ts: all 3 factories (Claude OAuth, plain-API-key Anthropic, OpenAI-compatible) now pass fetch: wrapFetchWithLogging(globalThis.fetch). For Claude OAuth the wrap goes on the inner base fetch so logged bodies reflect the post-transform shape + Claude-Code session headers. Added tabId to ProviderConfig for log labelling. - agent/agent.ts: threads tabId through createProvider and emits logAgentLoop / logStepLifecycle / logStreamEvent at every meaningful point in the run loop — step start/end, tool count, every fullStream event. All are no-ops when DISPATCH_DEBUG_LLM is unset. - core/index.ts: re-exports the debug helpers. - tests/llm/provider.test.ts: switch one full-object equality assertion to property assertions so the test survives the new fetch: wrapper. Plumbing the env var into the container required three more fixes: - bin/up: re-export DISPATCH_DEBUG_LLM* so docker compose forwards them (compose only forwards vars referenced in the environment: block). Also pre-creates /tmp/dispatch/llm-debug and chowns it on first run so the container's UID-1000 bun process can write into it without EACCES. - docker-compose.yml: declare the debug vars on api.environment and bind-mount /tmp/dispatch/llm-debug:/tmp/dispatch/llm-debug so logs are inspectable from the host without docker exec. - docker/entrypoint.dev.sh: explicitly forward DISPATCH_DEBUG_* through the 'su -' login-shell barrier — su - resets the environment to TERM/ PATH/HOME/SHELL/USER/LOGNAME only, silently stripping everything else. This is why the vars appeared via 'docker exec env' (which spawns a new process inheriting the container env) but were absent from the actual bun process's /proc/<pid>/environ. bin/build: drop stray sudo for consistency with bin/up and bin/down.
Diffstat (limited to 'bin')
-rwxr-xr-xbin/build2
-rwxr-xr-xbin/up31
2 files changed, 32 insertions, 1 deletions
diff --git a/bin/build b/bin/build
index 3952364..cd0dabb 100755
--- a/bin/build
+++ b/bin/build
@@ -4,4 +4,4 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
-sudo docker compose -f "$PROJECT_DIR/docker-compose.yml" build "$@"
+docker compose -f "$PROJECT_DIR/docker-compose.yml" build "$@"
diff --git a/bin/up b/bin/up
index 2e67857..6f9c3ed 100755
--- a/bin/up
+++ b/bin/up
@@ -9,5 +9,36 @@ export HOST_UID="$(id -u)"
export HOST_GID="$(id -g)"
export HOST_USER="$(whoami)"
+# Debug-logger pass-through. docker-compose only forwards env vars that are
+# (a) set in the parent shell AND (b) referenced in docker-compose.yml's
+# `environment:` block — so without this `export` step the variables would
+# be invisible to the container even when the user prefixes the command with
+# DISPATCH_DEBUG_LLM=1. We re-export here (rather than relying on the shell's
+# inline `VAR=… cmd` syntax) so it works whether the user sets them inline,
+# in their shell rc, or via `.env`.
+#
+# All variables default to empty — when unset, the logger short-circuits and
+# does nothing.
+export DISPATCH_DEBUG_LLM="${DISPATCH_DEBUG_LLM:-}"
+export DISPATCH_DEBUG_LLM_VERBOSITY="${DISPATCH_DEBUG_LLM_VERBOSITY:-}"
+export DISPATCH_DEBUG_USAGE="${DISPATCH_DEBUG_USAGE:-}"
+
+# Pre-create the LLM debug log directory owned by the host user. Without
+# this, docker auto-creates the bind-mount source as root on first start,
+# and the container's bun process (running as host UID) then gets EACCES
+# on every log write — silent except for `[dispatch-debug] Failed to
+# write ...: EACCES` lines drowned in stderr.
+#
+# If the directory already exists and is NOT owned by us (likely from a
+# prior root-mkdir by docker), fix it with sudo. This prompts once and
+# then never again — files we write afterwards are owned correctly.
+LOG_DIR=/tmp/dispatch/llm-debug
+mkdir -p "$LOG_DIR" 2>/dev/null || true
+if [ ! -O "$LOG_DIR" ]; then
+ current_owner=$(stat -c '%U' "$LOG_DIR" 2>/dev/null || echo "unknown")
+ echo "bin/up: $LOG_DIR is owned by '$current_owner', fixing ownership to '$HOST_USER'..."
+ sudo chown -R "$HOST_UID:$HOST_GID" "$LOG_DIR"
+fi
+
# Start all services
docker compose -f "$PROJECT_DIR/docker-compose.yml" up "$@"