#!/usr/bin/env bash
# Fronset cookbook 1: which model answered, and why (own-key path), in curl.
# The same steps as cb1_which_model_answered.py. Needs curl and jq.
#
#   export FRONSET_INFERENCE_KEY=llmb_i_...  FRONSET_MANAGEMENT_KEY=llmb_m_...
#   export FRONSET_PORTAL_TOKEN=llmbp_...                 # optional, step 5
#   export PROVIDER_SLUG=openai PROVIDER_API_KEY=sk-...   # optional, step 3a
#   export TASK=cookbook-1-summary                        # optional, step 3b
#   bash cb1_which_model_answered.sh
set -euo pipefail
API="${FRONSET_API_BASE:-https://api.fronset.ai}"
PORTAL="${FRONSET_PORTAL_BASE:-https://fronset.ai}"
TASK="${TASK:-cookbook-1-summary-$(date -u +%Y%m%d)}"
TEXT="Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal."

# Step 3a. Vault one provider key (management key). The key is read from the
# environment and sent in the body; it is never echoed.
if [ -n "${PROVIDER_API_KEY:-}" ]; then
  [ -n "${PROVIDER_SLUG:-}" ] || { echo "set PROVIDER_SLUG too" >&2; exit 1; }
  jq -n --arg k "$PROVIDER_API_KEY" '{api_key: $k, config: {}}' |
  curl -sS -X PUT "$API/api/inference/v1/vault/providers/$PROVIDER_SLUG" \
    -H "Authorization: Bearer $FRONSET_MANAGEMENT_KEY" \
    -H "Content-Type: application/json" --data @- |
  jq '{provider_slug, is_active, verified}'
fi
curl -sS "$API/api/inference/v1/vault/providers" \
  -H "Authorization: Bearer $FRONSET_MANAGEMENT_KEY" | jq '[.[] | {provider_slug, is_active, verified}]'

# Step 3b. Create your task, or reuse it if it exists and is active (management
# key). /v1 only calls tasks that exist, by the slug the create returns; a
# paused task is never reused. -s without -f, so a 404 is read, not fatal.
PREFIX=$(curl -sSf "$API/api/inference/v1/management/account" \
  -H "Authorization: Bearer $FRONSET_MANAGEMENT_KEY" | jq -r .task_prefix)
CODE=$(curl -sS "$API/api/inference/v1/management/capabilities/$PREFIX$TASK" \
  -H "Authorization: Bearer $FRONSET_MANAGEMENT_KEY" -o cap.json -w '%{http_code}')
if [ "$CODE" = 404 ]; then
  # The task says what it is at birth: its template (two prompt texts and the
  # variable they read), its output schema, and the models it may run (a new
  # group named after the task; group names are at most 48 characters).
  CODE=$(jq -n --arg n "$TASK" --arg g "${TASK:0:41}-models" '{slug: $n,
      display_name: "Cookbook 1: one-sentence summary",
      description: "Summarise a text in one sentence.", pricing_mode: "byok",
      templates: [{key: "default", system: "Summarise the text in one sentence.",
                   user: "{text}",
                   variables: [{name: "text", required: true,
                                description: "The text to summarise."}]}],
      output_format: "json_schema",
      output_schema: {type: "object", properties: {summary: {type: "string"}},
                      required: ["summary"], additionalProperties: false},
      model_group: {name: $g, models: ["gpt-6-sol", "gpt-6-luna"]}}' |
    curl -sS -X POST "$API/api/inference/v1/management/capabilities/" \
      -H "Authorization: Bearer $FRONSET_MANAGEMENT_KEY" \
      -H "Content-Type: application/json" --data @- -o cap.json -w '%{http_code}')
  if [ "$CODE" != 201 ]; then
    echo "task create refused: HTTP $CODE $(jq -c '{code, error}' cap.json)" >&2; exit 1
  fi
elif [ "$CODE" != 200 ]; then
  echo "task lookup refused: HTTP $CODE $(jq -c '{code, error}' cap.json)" >&2; exit 1
elif [ "$(jq -r .is_active cap.json)" = false ]; then
  echo "task $(jq -r .slug cap.json) exists but is paused; set TASK to a new name" >&2; exit 1
fi
SLUG=$(jq -r .slug cap.json)
echo "task: $SLUG"

# Step 3c. One call on your task, by its slug (inference key), in template mode:
# the task's template builds the prompt from the variable `text`, so `messages`
# is empty. A call to a task that is still exploring can take minutes; curl
# waits and does not retry (a retried call runs again and bills again). -D keeps
# the response headers, where Fronset puts which model answered.
jq -n --arg t "$SLUG" --arg x "$TEXT" '{model: $t, messages: [],
  llmbench: {prompt_vars: {text: $x}}}' |
CODE=$(curl -sS --max-time 900 "$API/v1/chat/completions" -D headers.txt -o body.json \
  -H "Authorization: Bearer $FRONSET_INFERENCE_KEY" \
  -H "Content-Type: application/json" --data @- -w '%{http_code}')
grep -i '^x-llmbench-' headers.txt
if [ "$CODE" != 200 ]; then
  echo "call failed: HTTP $CODE $(jq -c '.error // .' body.json)" >&2; exit 1
fi

# Step 4. The same values, mirrored into the body.
jq '.llmbench' body.json

# Step 5. The route detail: every model call behind your one call (portal token).
REQ=$(grep -i '^x-llmbench-request-id:' headers.txt | cut -d' ' -f2 | tr -d '\r')
if [ -n "${FRONSET_PORTAL_TOKEN:-}" ] && [ -n "$REQ" ]; then
  curl -sS "$PORTAL/portal/api/v1/routes/$REQ" \
    -H "Authorization: Bearer $FRONSET_PORTAL_TOKEN" |
  jq '{attempts, route_cost_usd, attempts_detail: [.attempts_detail[] |
       {model_slug, provider_slug, list_cost_usd, status, fanout_role, purpose,
        delivered}]}'
fi
