#!/usr/bin/env bash
# kg-first.sh — pre_tool_call hook for Hermes.
# Installed by `olam hermes bootstrap` / `olam kg install-hook --for hermes`.
# Routes search-shape tool calls through olam-kg-service /classify first.
# Blocks with kg-first reason when route=kg; allows (exit 0) otherwise.
#
# Portability notes:
#   - KG_URL defaults to http://127.0.0.1:9997 — override via env.
#   - LOG defaults to $HOME/.hermes/logs/kg-first-hook.log.
#   - OLAM_KG_HOOK (sentinel) is referenced by audit tooling — do not rename.
#   - Requires: bash, jq, curl, python3 (all standard on macOS / Linux).
#
# OLAM_KG_HOOK — sentinel used by olam to detect if this hook is installed.

set -u
KG_URL="${KG_URL:-http://127.0.0.1:9997}"
LOG="${LOG:-$HOME/.hermes/logs/kg-first-hook.log}"

input="$(cat)"
log() { printf '[%s] %s\n' "$(date -u +%FT%TZ)" "$*" >>"$LOG"; }

# Ensure log dir exists (may be missing on fresh install)
mkdir -p "$(dirname "$LOG")" 2>/dev/null || true

command -v jq   >/dev/null 2>&1 || { log "jq missing — fail open"; exit 0; }
command -v curl >/dev/null 2>&1 || { log "curl missing — fail open"; exit 0; }

tool_name="$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
query=""

extract_find_name() {
  # Match -name X, -iname X, -path X (handles single/double-quoted values)
  python3 -c '
import re, sys
cmd = sys.argv[1]
m = re.search(r"-(?:i?name|i?path)\s+([\x27\x22]?)([^\x27\x22\s]+)\1", cmd)
if m:
    print(m.group(2).strip("*"))
' "$1"
}

extract_grep_pattern() {
  # First positional arg after token[0], strip wildcards/quotes
  python3 -c '
import shlex, sys
try:
    toks = shlex.split(sys.argv[1])
except ValueError:
    toks = sys.argv[1].split()
for t in toks[1:]:
    if t.startswith("-"):
        continue
    print(t.strip("*\x27\x22"))
    break
' "$1"
}

case "$tool_name" in
  terminal|bash|shell)
    cmd="$(echo "$input" | jq -r '.tool_input.command // .tool_input.cmd // empty' 2>/dev/null)"
    if ! echo "$cmd" | grep -qE '^\s*(grep|rg|ripgrep|ag|ack|find|fd|locate)\b'; then
      log "tool=$tool_name cmd=$(echo "$cmd" | head -c 80) — not search-shape, allow"
      exit 0
    fi
    if echo "$cmd" | grep -qE '^\s*(find|fd|locate)\b'; then
      query="$(extract_find_name "$cmd")"
      [ -z "$query" ] && query="$(extract_grep_pattern "$cmd")"
    else
      query="$(extract_grep_pattern "$cmd")"
    fi
    ;;
  search_files|grep|ripgrep)
    query="$(echo "$input" | jq -r '.tool_input.query // .tool_input.pattern // .tool_input.search // empty' 2>/dev/null)"
    ;;
  *)
    exit 0
    ;;
esac

query="$(echo "$query" | tr -d '\n' | head -c 200)"
[ -z "$query" ] && { log "tool=$tool_name no query extracted — allow"; exit 0; }

response="$(curl -fsS --max-time 2 \
  -H 'Content-Type: application/json' \
  -X POST "$KG_URL/classify" \
  -d "$(jq -nc --arg q "$query" '{question:$q}')" 2>>"$LOG")" || {
  log "tool=$tool_name kg-service unreachable — fail open"
  exit 0
}

route="$(echo "$response" | jq -r '.route // empty' 2>/dev/null)"
log "tool=$tool_name query=\"$query\" route=$route"

if [ "$route" = "kg" ]; then
  reason="KG-first policy: this question is symbol-shaped and the knowledge graph is the right tool. Call \`mcp_olam_olam_kg_classify\` with question=\"$query\" — it will give you the routing decision and pointers."
  jq -nc --arg r "$reason" '{decision:"block", reason:$r}'
  exit 0
fi

exit 0
