#!/bin/bash
# M3 v15：upstream 改为公网 LLM 网关，重下发 llm-proxy 配置并验证全链路
BASE=http://10.168.3.36:19088
INST=friend-48beca9b
C=friend-deploy-0acc642d-5c1
AUTH="Authorization: Bearer dev-admin-token"
CT="Content-Type: application/json"

echo "=== 1. 重下发 llm-proxy 配置（upstream=llm.zhengcloud.ltd, base_gen=2）==="
PAYLOAD='{"base_generation":2,"issued_by":"yunwo-m3","changes":[{"operation":"set","kind":"plugin.config","resource_uid":"llm-proxy","value":{"api_key":"sk-1K64cmiw1jl2XVydF7u6PGATe66GJinAJgZfSSTtiDuKCpjJ","upstream_base":"https://llm.zhengcloud.ltd/v1","listen_addr":"127.0.0.1:39527"}}]}'
RESP=$(curl -sS --max-time 15 -X POST -H "$AUTH" -H "$CT" -d "$PAYLOAD" "$BASE/api/v1/instances/$INST/config-transactions")
echo "$RESP" | head -c 300; echo

echo "=== 2. 等 12s 后直连 39527 验证代理 ==="
sleep 12
docker exec $C sh -c "wget -S -T 30 -O- --header='Content-Type: application/json' --post-data='{\"model\":\"glm-5-2\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"max_tokens\":20}' http://127.0.0.1:39527/v1/chat/completions 2>&1 | tail -6"

echo "=== 3. probe 模型恢复健康 ==="
ITOK=$(docker exec $C sh -c "grep api_auth_token /app/config/config.yaml" | awk '{print $2}')
TTOK=$(curl -sS --max-time 10 -X POST -H "$AUTH" -H "$CT" -d '{}' "$BASE/api/v1/instances/$INST/tunnels" | python3 -c "
import sys,json,urllib.parse as u
print(u.parse_qs(u.urlparse(json.load(sys.stdin)['url']).query)['__friend_tunnel'][0])")
api() { local p=$1; shift; curl -sS --max-time 30 -H "Cookie: friend_cluster_tunnel=$TTOK" -H "Authorization: Bearer $ITOK" "$BASE/panel/$INST$p" "$@"; }
for id in 1 2; do api "/api/llm/models/$id/probe" -X POST | head -c 200; echo; done

echo "=== 4. 模型状态 ==="
api /api/llm/models | python3 -c "
import sys,json
for m in json.load(sys.stdin):
    r=m.get('runtime') or {}
    print(m.get('model_key'),'|',r.get('state'),'|',(r.get('last_error') or '')[:100])"

echo "=== 5. 若 healthy 则 ingest 注入并等 LLM 回复 ==="
STATE=$(api /api/llm/models | python3 -c "
import sys,json
models=json.load(sys.stdin)
print(any((m.get('runtime') or {}).get('state')=='healthy' for m in models))")
if [ "$STATE" = "True" ]; then
  TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
  docker exec $C sh -c "wget -qO- --header='Authorization: Bearer $ITOK' --header='Content-Type: application/json' --post-data='{\"platform\":\"yunwo\",\"platform_user_id\":\"u97\",\"platform_chat_id\":\"chat97\",\"message_type\":\"text\",\"content\":{\"parts\":[{\"type\":\"text\",\"text\":\"请用一句话介绍你自己\"}]},\"timestamp\":\"$TS\"}' http://127.0.0.1:8787/ingest 2>&1"
  MAINID=c89441e6-1962-4048-807c-db4f011f9336
  for i in 1 2 3 4 5 6 7 8; do
    sleep 15
    OUT=$(api "/api/chains/$MAINID/nodes")
    INFO=$(echo "$OUT" | python3 -c "
import sys,json
nodes=json.load(sys.stdin)
print(len(nodes),'|',','.join(n.get('type') for n in nodes))" 2>/dev/null)
    echo "[poll $i] nodes=$INFO"
    echo "$INFO" | grep -qE "transmission|tool_call|assistant" && { echo "--- 最后节点 ---"; echo "$OUT" | python3 -c "
import sys,json
for n in json.load(sys.stdin)[-3:]:
    print(n.get('seq'),n.get('type'),str(n.get('payload') or {})[:250])"; break; }
  done
else
  echo "MODELS_STILL_NOT_HEALTHY"
fi

echo "=== 6. brain 日志尾部 ==="
docker exec $C sh -c 'grep -E "brain.think|llm\." /var/lib/friend/logs/friend.log 2>/dev/null' | tail -6
echo DONE
