61 lines
2.2 KiB
Bash
Executable File
61 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Call one tool by hand, the way Open WebUI would.
|
|
#
|
|
# ./tests/try-tool.sh is the server up?
|
|
# ./tests/try-tool.sh web_search '{"query":"systemd socket activation"}'
|
|
# ./tests/try-tool.sh subnet_calc '{"network":"192.168.1.0/24"}'
|
|
#
|
|
# WHY THIS IS NOT `curl http://localhost:8000/...`
|
|
#
|
|
# Because that does not work, and worse, it can appear to. NOTHING in
|
|
# this stack publishes a port to the host: the app container has no
|
|
# default route and the gateway is only on Open WebUI's docker network.
|
|
# A curl to localhost:8000 reaches whatever else happens to be listening
|
|
# there - on the machine this was written on, something answered "OK" and
|
|
# looked for all the world like a healthy tool server.
|
|
#
|
|
# So the call is made from inside the api container, which is where the
|
|
# token already is. Same code path a real tool call takes, minus nginx.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
TOOL="${1:-}"
|
|
BODY="${2:-{\}}"
|
|
|
|
if [ -z "$TOOL" ]; then
|
|
docker compose exec -T api python -c \
|
|
"import urllib.request;print(urllib.request.urlopen('http://127.0.0.1:8000/health').read().decode())"
|
|
exit 0
|
|
fi
|
|
|
|
docker compose exec -T -e TOOL="$TOOL" -e BODY="$BODY" api python - <<'PY'
|
|
import json, os, sys, urllib.error, urllib.request
|
|
|
|
tool, body = os.environ["TOOL"], os.environ["BODY"]
|
|
try:
|
|
json.loads(body)
|
|
except ValueError as exc:
|
|
sys.exit(f"the second argument is not valid JSON: {exc}")
|
|
|
|
request = urllib.request.Request(
|
|
f"http://127.0.0.1:8000/tools/{tool}",
|
|
data=body.encode(),
|
|
headers={"Authorization": "Bearer " + os.environ["OWUITOOLS_AUTH_TOKEN"],
|
|
"Content-Type": "application/json"},
|
|
)
|
|
try:
|
|
answer = urllib.request.urlopen(request, timeout=120).read().decode()
|
|
except urllib.error.HTTPError as exc:
|
|
if exc.code == 404:
|
|
sys.exit(f"there is no tool called {tool!r}. It may be switched off in "
|
|
"configs/tools.toml - see docs/tools.md.")
|
|
sys.exit(f"HTTP {exc.code}: {exc.read().decode()[:400]}")
|
|
|
|
# Tools return a JSON string; print what the model would actually read.
|
|
try:
|
|
answer = json.loads(answer)
|
|
except ValueError:
|
|
pass
|
|
print(answer if isinstance(answer, str) else json.dumps(answer, indent=2))
|
|
PY
|