aboutsummaryrefslogtreecommitdiffstats
path: root/tools/web_search_tavily.sh
blob: a3d8997810e711bcb783dbf84f7ada34d580c774 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env bash
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.
# 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

OUT="${LLM_OUTPUT:-/dev/stdout}"

err() {
  echo "ERROR: $*" >> "$OUT"
  exit 0
}

main() {
  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": "$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:
}

# ---- 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