diff options
| author | Leonard Kugis <leonard@kug.is> | 2026-02-09 02:19:05 +0100 |
|---|---|---|
| committer | Leonard Kugis <leonard@kug.is> | 2026-02-09 02:19:05 +0100 |
| commit | 5bb4a3038a0a638359d366f2934a7bb6a8d5bd6b (patch) | |
| tree | d78274f7f54cae246980fb8eed45e2e8296943f0 | |
| parent | 27e319f8d1e3a0e8f2db79f62d451768b11d62a3 (diff) | |
| download | llm-functions-docker-5bb4a3038a0a638359d366f2934a7bb6a8d5bd6b.tar.gz | |
fs_patch, web_search: Never exit with exit code != 0
Print error instead
| -rwxr-xr-x | tools/fs_patch.sh | 35 | ||||
| -rwxr-xr-x | tools/web_search_tavily.sh | 108 |
2 files changed, 118 insertions, 25 deletions
diff --git a/tools/fs_patch.sh b/tools/fs_patch.sh index 84ae49e..2d9d7e4 100755 --- a/tools/fs_patch.sh +++ b/tools/fs_patch.sh @@ -2,8 +2,9 @@ set -uo pipefail # @describe Apply a patch to a file at the specified path. -# @option --path! The path of the file to apply to -# @option --contents! The patch to apply to the file +# NOTE: This tool NEVER exits with non-zero (even on missing args). It reports errors in output. +# @option --path The path of the file to apply to +# @option --contents The patch to apply to the file # @env LLM_OUTPUT=/dev/stdout The output path ROOT_DIR="${LLM_ROOT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}" @@ -18,16 +19,16 @@ main() { path="${argc_path:-}" patch="${argc_contents:-}" - [[ -z "$path" ]] && err "missing --path" - [[ -z "$patch" ]] && err "missing --contents" - [[ ! -e "$path" ]] && err "file not found: $path" - [[ ! -f "$path" ]] && err "not a regular file: $path" - [[ ! -r "$path" ]] && err "file not readable: $path" + [[ -z "${path}" ]] && err "missing --path" + [[ -z "${patch}" ]] && err "missing --contents" + [[ ! -e "${path}" ]] && err "file not found: ${path}" + [[ ! -f "${path}" ]] && err "not a regular file: ${path}" + [[ ! -r "${path}" ]] && err "file not readable: ${path}" new_contents="" if ! new_contents="$(awk -f "$ROOT_DIR/utils/patch.awk" "$path" <(printf "%s" "$patch") 2>/tmp/fs_patch.err)"; then msg="$(cat /tmp/fs_patch.err 2>/dev/null || true)" - err "patch apply failed for $path: ${msg:-unknown error}" + err "patch apply failed for ${path}: ${msg:-unknown error}" fi # Diff in Tool-Output schreiben (damit das LLM es sieht) @@ -40,13 +41,25 @@ main() { if ! printf "%s" "$new_contents" > "$path" 2>/tmp/fs_patch_write.err; then msg="$(cat /tmp/fs_patch_write.err 2>/dev/null || true)" - err "failed to write patched file $path: ${msg:-unknown error}" + err "failed to write patched file ${path}: ${msg:-unknown error}" fi - echo "The patch applied to: $path" >> "$OUT" + echo "The patch applied to: ${path}" >> "$OUT" exit 0 } -eval "$(argc --argc-eval "$0" "$@")" +# IMPORTANT: Do not let argc failures abort the script. +# - remove "set -e" +# - and swallow argc's non-zero return +eval "$(argc --argc-eval "$0" "$@" 2>/tmp/argc_fs_patch.err || true)" + +# If argc itself failed (e.g. parse error), report but still exit 0 +if [[ -s /tmp/argc_fs_patch.err ]]; then + echo "ERROR: argc parse failed: $(cat /tmp/argc_fs_patch.err)" >> "$OUT" + rm -f /tmp/argc_fs_patch.err + exit 0 +fi +rm -f /tmp/argc_fs_patch.err + main diff --git a/tools/web_search_tavily.sh b/tools/web_search_tavily.sh index 1bf1e9d..a3d8997 100755 --- a/tools/web_search_tavily.sh +++ b/tools/web_search_tavily.sh @@ -1,24 +1,104 @@ #!/usr/bin/env bash -set -e +set -u # kein -e, damit wir Fehler selbst behandeln können # @describe Perform a web search using Tavily API to get up-to-date information or additional context. -# Use this when you need current information or feel a search could provide a better answer. +# NOTE: This tool NEVER exits with non-zero (even on missing args or curl/jq errors). It reports errors in output. +# @option --query The query to search for. +# @env TAVILY_API_KEY The api key +# @env LLM_OUTPUT=/dev/stdout The output path -# @option --query! The query to search for. +OUT="${LLM_OUTPUT:-/dev/stdout}" -# @env TAVILY_API_KEY! The api key -# @env LLM_OUTPUT=/dev/stdout The output path The output path +err() { + echo "ERROR: $*" >> "$OUT" + exit 0 +} main() { - curl -fsSL -X POST https://api.tavily.com/search \ - -H "content-type: application/json" \ - -d ' + local query="${argc_query:-}" + local api_key="${TAVILY_API_KEY:-}" + + [[ -z "$query" ]] && err "missing --query" + [[ -z "$api_key" ]] && err "missing TAVILY_API_KEY" + + # Request (capture body + rc) + local body rc + body="$(curl -sS -L -X POST "https://api.tavily.com/search" \ + -H "content-type: application/json" \ + --data-binary "$(cat <<JSON { - "api_key": "'"$TAVILY_API_KEY"'", - "query": "'"$argc_query"'", - "include_answer": true -}' | \ - jq -r '.answer' >> "$LLM_OUTPUT" + "api_key": "$api_key", + "query": "$query", + "include_answer": true +} +JSON +)" 2>&1)" + rc=$? + + if [[ $rc -ne 0 ]]; then + echo "ERROR: curl failed (exit_code=$rc): $body" >> "$OUT" + exit 0 + fi + + # Parse answer (capture jq errors too) + local answer jq_err + answer="$(printf "%s" "$body" | jq -r '.answer' 2> >(jq_err="$(cat)"; typeset -p jq_err >/dev/null) )" || true + + # The process substitution above is messy in some shells; use a simpler portable way: } -eval "$(argc --argc-eval "$0" "$@")" +# ---- argc parse (never fail) ---- +eval "$(argc --argc-eval "$0" "$@" 2>/tmp/argc_web_search_tavily.err || true)" +if [[ -s /tmp/argc_web_search_tavily.err ]]; then + echo "ERROR: argc parse failed: $(cat /tmp/argc_web_search_tavily.err)" >> "$OUT" + rm -f /tmp/argc_web_search_tavily.err + exit 0 +fi +rm -f /tmp/argc_web_search_tavily.err + +# ---- main with portable jq handling ---- +main() { + local query="${argc_query:-}" + local api_key="${TAVILY_API_KEY:-}" + [[ -z "$query" ]] && err "missing --query" + [[ -z "$api_key" ]] && err "missing TAVILY_API_KEY" + + local resp rc + resp="$(curl -sS -L -X POST "https://api.tavily.com/search" \ + -H "content-type: application/json" \ + --data-binary "$(cat <<JSON +{ + "api_key": "$api_key", + "query": "$query", + "include_answer": true +} +JSON +)" 2>&1)" + rc=$? + + if [[ $rc -ne 0 ]]; then + echo "ERROR: curl failed (exit_code=$rc): $resp" >> "$OUT" + exit 0 + fi + + # jq parse with error capture + local answer jq_out jq_rc + jq_out="$(printf "%s" "$resp" | jq -r '.answer' 2>&1)" + jq_rc=$? + + if [[ $jq_rc -ne 0 ]]; then + echo "ERROR: jq failed (exit_code=$jq_rc): $jq_out" >> "$OUT" + # optional: dump response for debugging (capped) + echo "RESPONSE:" >> "$OUT" + printf "%s\n" "$resp" | head -c 20000 >> "$OUT" + echo >> "$OUT" + exit 0 + fi + + # jq succeeded; write answer + printf "%s\n" "$jq_out" >> "$OUT" + exit 0 +} + +main + |
