aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2026-02-09 02:19:05 +0100
committerLeonard Kugis <leonard@kug.is>2026-02-09 02:19:05 +0100
commit5bb4a3038a0a638359d366f2934a7bb6a8d5bd6b (patch)
treed78274f7f54cae246980fb8eed45e2e8296943f0
parent27e319f8d1e3a0e8f2db79f62d451768b11d62a3 (diff)
downloadllm-functions-docker-5bb4a3038a0a638359d366f2934a7bb6a8d5bd6b.tar.gz
fs_patch, web_search: Never exit with exit code != 0
Print error instead
-rwxr-xr-xtools/fs_patch.sh35
-rwxr-xr-xtools/web_search_tavily.sh108
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
+