v0.6.2: fix Cygwin argv overflow when passing TOOLS_JSON to jq

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 <noreply@anthropic.com>
This commit is contained in:
Bryan Johnson 2026-05-27 11:58:38 -07:00
parent 99f0b03c8c
commit 0ebaacd221
2 changed files with 12 additions and 5 deletions

View File

@ -1 +1 @@
0.6.1 0.6.2

View File

@ -36,7 +36,7 @@ set -o pipefail
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# Config # Config
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
LARRY_VERSION="0.6.1" LARRY_VERSION="0.6.2"
LARRY_HOME="${LARRY_HOME:-$HOME/.larry}" LARRY_HOME="${LARRY_HOME:-$HOME/.larry}"
LARRY_BASE_URL="${LARRY_BASE_URL:-https://raw.githubusercontent.com/bojj27/cloverleaf-larry/main}" 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}" LARRY_UPDATE_URL="${LARRY_UPDATE_URL:-${LARRY_BASE_URL}/larry.sh}"
@ -1040,6 +1040,11 @@ build_system_prompt() {
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
agent_turn() { agent_turn() {
local system_prompt="$1" 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 while true; do
local payload_file; payload_file=$(mktemp) local payload_file; payload_file=$(mktemp)
jq -n \ jq -n \
@ -1047,18 +1052,19 @@ agent_turn() {
--argjson max_tokens "$LARRY_MAX_TOKENS" \ --argjson max_tokens "$LARRY_MAX_TOKENS" \
--arg system "$system_prompt" \ --arg system "$system_prompt" \
--slurpfile messages "$MESSAGES_FILE" \ --slurpfile messages "$MESSAGES_FILE" \
--argjson tools "$TOOLS_JSON" \ --slurpfile tools "$tools_file" \
'{model:$model, max_tokens:$max_tokens, system:$system, messages:$messages[0], tools:$tools}' \ '{model:$model, max_tokens:$max_tokens, system:$system, messages:$messages[0], tools:$tools[0]}' \
> "$payload_file" > "$payload_file"
local resp; resp=$(call_api "$payload_file") local resp; resp=$(call_api "$payload_file")
rm -f "$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) local err_type; err_type=$(printf '%s' "$resp" | jq -r '.error.type // empty' 2>/dev/null)
if [ -n "$err_type" ]; then if [ -n "$err_type" ]; then
err "API error: $err_type$(printf '%s' "$resp" | jq -r '.error.message // "no message"')" err "API error: $err_type$(printf '%s' "$resp" | jq -r '.error.message // "no message"')"
rm -f "$tools_file"
return 1 return 1
fi fi
@ -1101,6 +1107,7 @@ agent_turn() {
add_user_tool_results "$results" add_user_tool_results "$results"
done done
rm -f "$tools_file"
} }
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────