From 0ebaacd221d400ebeef9f19b101233573c850133 Mon Sep 17 00:00:00 2001 From: Bryan Johnson Date: Wed, 27 May 2026 11:58:38 -0700 Subject: [PATCH] v0.6.2: fix Cygwin argv overflow when passing TOOLS_JSON to jq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bryan hit this on every chat turn from MobaXterm: jq: Argument list too long error: OAuth token unavailable; ... error: empty response from API warn: turn ended with error Root cause: agent_turn was building the API payload with jq -n ... --argjson tools "$TOOLS_JSON" ... which puts all 21KB of tool-definition JSON on the jq command line as argv. Cygwin/Windows argv limit is ~32KB total — combined with the other args this exceeded it and jq failed with E2BIG. Linux/macOS have a much larger limit (256KB+) so this never showed in local testing. The downstream errors were cascade noise: jq fails to write payload → call_api runs with empty/partial payload → various error paths fire. Fix: write TOOLS_JSON to a tempfile once per agent_turn and reference it via --slurpfile (same pattern already used for $MESSAGES_FILE). Tempfile is cleaned up at every return path. Verified locally — payload now builds cleanly with no argv warnings. Co-Authored-By: Claude Opus 4.7 --- VERSION | 2 +- larry.sh | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/VERSION b/VERSION index ee6cdce..b616048 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.1 +0.6.2 diff --git a/larry.sh b/larry.sh index 5bc9b64..ca5ec07 100755 --- a/larry.sh +++ b/larry.sh @@ -36,7 +36,7 @@ set -o pipefail # ───────────────────────────────────────────────────────────────────────────── # Config # ───────────────────────────────────────────────────────────────────────────── -LARRY_VERSION="0.6.1" +LARRY_VERSION="0.6.2" LARRY_HOME="${LARRY_HOME:-$HOME/.larry}" LARRY_BASE_URL="${LARRY_BASE_URL:-https://raw.githubusercontent.com/bojj27/cloverleaf-larry/main}" LARRY_UPDATE_URL="${LARRY_UPDATE_URL:-${LARRY_BASE_URL}/larry.sh}" @@ -1040,6 +1040,11 @@ build_system_prompt() { # ───────────────────────────────────────────────────────────────────────────── agent_turn() { local system_prompt="$1" + # Write the TOOLS_JSON to a file ONCE per agent_turn rather than passing it + # via --argjson (which puts the full 21KB blob on the jq command line and + # blows up Cygwin/Windows argv limits with E2BIG / "Argument list too long"). + local tools_file; tools_file=$(mktemp) + printf '%s' "$TOOLS_JSON" > "$tools_file" while true; do local payload_file; payload_file=$(mktemp) jq -n \ @@ -1047,18 +1052,19 @@ agent_turn() { --argjson max_tokens "$LARRY_MAX_TOKENS" \ --arg system "$system_prompt" \ --slurpfile messages "$MESSAGES_FILE" \ - --argjson tools "$TOOLS_JSON" \ - '{model:$model, max_tokens:$max_tokens, system:$system, messages:$messages[0], tools:$tools}' \ + --slurpfile tools "$tools_file" \ + '{model:$model, max_tokens:$max_tokens, system:$system, messages:$messages[0], tools:$tools[0]}' \ > "$payload_file" local resp; resp=$(call_api "$payload_file") rm -f "$payload_file" - if [ -z "$resp" ]; then err "empty response from API (timeout or network?)"; return 1; fi + if [ -z "$resp" ]; then err "empty response from API (timeout or network?)"; rm -f "$tools_file"; return 1; fi local err_type; err_type=$(printf '%s' "$resp" | jq -r '.error.type // empty' 2>/dev/null) if [ -n "$err_type" ]; then err "API error: $err_type — $(printf '%s' "$resp" | jq -r '.error.message // "no message"')" + rm -f "$tools_file" return 1 fi @@ -1101,6 +1107,7 @@ agent_turn() { add_user_tool_results "$results" done + rm -f "$tools_file" } # ─────────────────────────────────────────────────────────────────────────────