v0.6.4: cygpath -w wrap on every --rawfile/--slurpfile argv path
Bryan hit this on MobaXterm immediately after v0.6.3 shipped:
C:\Users\...\bin\jq.exe: Bad JSON in --rawfile c /tmp/tmp.AlsIcdX9aO:
Could not open /tmp/tmp.AlsIcdX9aO: No such file or directory
error: OAuth token unavailable; run 'larry-auth.sh login' to re-authenticate
error: empty response from API (timeout or network?)
Root cause is the same one v0.5.4 fixed for the OAuth file reads, but now
biting the new tempfile pipeline introduced for argv-overflow avoidance.
The Windows-native jq.exe shipped to MobaXterm via install-larry.sh
cannot resolve Cygwin paths like /tmp/tmp.X or /home/mobaxterm/.larry/...
when they come in as argv arguments to --rawfile / --slurpfile — it
interprets them as Windows paths and the open() fails.
v0.5.4 fixed this for stdin-read cases by piping via bash redirection
(`< "$file"`), since bash handles the cygwin→windows path open before
jq sees a file descriptor. But --rawfile / --slurpfile DO want a path
argument, so the stdin trick doesn't apply — we must give jq a path it
can actually open.
Fix: new jqpath() helper translates a cygwin path to its real Windows
equivalent via `cygpath -w` when cygpath exists (Cygwin / MobaXterm / MSYS).
On Linux and macOS cygpath is absent and the helper echoes the path
unchanged — true cross-platform no-op outside Cygwin.
Wrapped every --rawfile / --slurpfile argv path in larry.sh:
add_user_text --rawfile c ←
add_assistant_blocks --slurpfile b ←
add_user_tool_results --slurpfile b ←
agent_turn payload --rawfile system, --slurpfile messages,
--slurpfile tools ←
agent_turn tool-result aggregation --rawfile c ←
Verified on macOS: jqpath echoes paths unchanged, the 40KB prompt
smoke test from v0.6.3 still works end-to-end.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
38d1eeede4
commit
47452d3910
31
larry.sh
31
larry.sh
@ -36,7 +36,7 @@ set -o pipefail
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Config
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
LARRY_VERSION="0.6.3"
|
||||
LARRY_VERSION="0.6.4"
|
||||
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}"
|
||||
@ -95,6 +95,21 @@ if ! command -v jq >/dev/null 2>&1; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# jqpath PATH — translate a path for jq's argv consumption.
|
||||
# On MobaXterm/Cygwin/MSYS the bundled jq is a Windows-native jq.exe that
|
||||
# rejects Cygwin paths like /tmp/tmp.X or /home/mobaxterm/.larry/... when
|
||||
# they come in as argv arguments (it tries to open them as Windows paths
|
||||
# and fails). cygpath -w translates Cygwin → Windows; jq.exe can then open
|
||||
# the file. On Linux/macOS cygpath does not exist and we echo the path
|
||||
# unchanged. Wrap EVERY --rawfile / --slurpfile path with $(jqpath "$p").
|
||||
jqpath() {
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
cygpath -w "$1"
|
||||
else
|
||||
printf '%s' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Bootstrap LARRY_HOME and API key
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@ -467,7 +482,7 @@ add_user_text() {
|
||||
local cfile tmp
|
||||
cfile=$(mktemp); tmp=$(mktemp)
|
||||
printf '%s' "$content" > "$cfile"
|
||||
jq --rawfile c "$cfile" '. + [{"role":"user","content":[{"type":"text","text":$c}]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
jq --rawfile c "$(jqpath "$cfile")" '. + [{"role":"user","content":[{"type":"text","text":$c}]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
&& mv "$tmp" "$MESSAGES_FILE"
|
||||
rm -f "$cfile"
|
||||
}
|
||||
@ -476,7 +491,7 @@ add_assistant_blocks() {
|
||||
local bfile tmp
|
||||
bfile=$(mktemp); tmp=$(mktemp)
|
||||
printf '%s' "$blocks" > "$bfile"
|
||||
jq --slurpfile b "$bfile" '. + [{"role":"assistant","content":$b[0]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
jq --slurpfile b "$(jqpath "$bfile")" '. + [{"role":"assistant","content":$b[0]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
&& mv "$tmp" "$MESSAGES_FILE"
|
||||
rm -f "$bfile"
|
||||
}
|
||||
@ -485,7 +500,7 @@ add_user_tool_results() {
|
||||
local bfile tmp
|
||||
bfile=$(mktemp); tmp=$(mktemp)
|
||||
printf '%s' "$blocks" > "$bfile"
|
||||
jq --slurpfile b "$bfile" '. + [{"role":"user","content":$b[0]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
jq --slurpfile b "$(jqpath "$bfile")" '. + [{"role":"user","content":$b[0]}]' < "$MESSAGES_FILE" > "$tmp" \
|
||||
&& mv "$tmp" "$MESSAGES_FILE"
|
||||
rm -f "$bfile"
|
||||
}
|
||||
@ -1066,9 +1081,9 @@ agent_turn() {
|
||||
jq -n \
|
||||
--arg model "$LARRY_MODEL" \
|
||||
--argjson max_tokens "$LARRY_MAX_TOKENS" \
|
||||
--rawfile system "$system_file" \
|
||||
--slurpfile messages "$MESSAGES_FILE" \
|
||||
--slurpfile tools "$tools_file" \
|
||||
--rawfile system "$(jqpath "$system_file")" \
|
||||
--slurpfile messages "$(jqpath "$MESSAGES_FILE")" \
|
||||
--slurpfile tools "$(jqpath "$tools_file")" \
|
||||
'{model:$model, max_tokens:$max_tokens, system:$system, messages:$messages[0], tools:$tools[0]}' \
|
||||
> "$payload_file"
|
||||
|
||||
@ -1122,7 +1137,7 @@ agent_turn() {
|
||||
local result_file; result_file=$(mktemp)
|
||||
printf '%s' "$result" > "$result_file"
|
||||
results=$(printf '%s' "$results" | jq \
|
||||
--arg id "$tu_id" --rawfile c "$result_file" \
|
||||
--arg id "$tu_id" --rawfile c "$(jqpath "$result_file")" \
|
||||
'. + [{"type":"tool_result","tool_use_id":$id,"content":$c}]')
|
||||
rm -f "$result_file"
|
||||
done < <(printf '%s' "$resp" | jq -c '.content[] | select(.type=="tool_use")')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user