ai-chatbot/scripts/smoke-pascal-agent.sh

101 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
if [ "${PASCAL_SMOKE_CONFIRM:-}" != "1" ]; then
printf '%s\n' \
'This check makes one real model request and then deletes its temporary scene.' \
'Run with PASCAL_SMOKE_CONFIRM=1 after confirming provider usage is acceptable.' >&2
exit 2
fi
command -v curl >/dev/null 2>&1 || { printf 'curl is required.\n' >&2; exit 1; }
command -v node >/dev/null 2>&1 || { printf 'node is required.\n' >&2; exit 1; }
PASCAL_ENV_FILE="${PASCAL_ENV_FILE:-/opt/pascal-editor/.env.production}"
PASCAL_PORT="${PASCAL_PORT:-3002}"
PASCAL_BASE_PATH="/${PASCAL_BASE_PATH#/}"
PASCAL_BASE_PATH="${PASCAL_BASE_PATH%/}"
BASE_URL="${PASCAL_INTERNAL_URL:-http://127.0.0.1:${PASCAL_PORT}}${PASCAL_BASE_PATH}"
USER_ID="deployment-smoke-test"
SCENE_ID="deployment-smoke-scene"
read_env_value() {
sed -n "s/^${1}=//p" "$PASCAL_ENV_FILE" | tail -n 1
}
SECRET="${PASCAL_PROXY_SECRET:-$(read_env_value PASCAL_AGENT_PROXY_SECRET)}"
[ -n "$SECRET" ] || {
printf 'PASCAL proxy secret is not configured.\n' >&2
exit 1
}
stream_file="$(mktemp)"
scene_file="$(mktemp)"
prompt="${PASCAL_SMOKE_PROMPT:-创建一个4米乘4米的简单房间,添加一扇门和一扇窗,检查结构后保存。}"
cleanup() {
curl -sS -o /dev/null -X DELETE \
-H "X-Pascal-Scene-Token: $SECRET" \
-H "X-Pascal-User-Id: $USER_ID" \
"$BASE_URL/api/scenes/$SCENE_ID" || true
rm -f "$stream_file" "$scene_file"
}
trap cleanup EXIT
cleanup
payload="$(node -e '
const sceneId = process.argv[1];
const prompt = process.argv[2];
process.stdout.write(JSON.stringify({
sceneId,
messages: [{
id: "deployment-smoke-message",
role: "user",
parts: [{ type: "text", text: prompt }],
}],
}));
' "$SCENE_ID" "$prompt")"
curl -fsS -X POST \
-H 'Content-Type: application/json' \
-H "X-Pascal-Scene-Token: $SECRET" \
-H "X-Pascal-User-Id: $USER_ID" \
--data "{\"id\":\"$SCENE_ID\",\"name\":\"Deployment smoke test\",\"graph\":{\"nodes\":{},\"rootNodeIds\":[]}}" \
"$BASE_URL/api/scenes" >/dev/null
http_code="$(curl -sS --max-time "${PASCAL_SMOKE_TIMEOUT_SECONDS:-360}" \
-o "$stream_file" \
-w '%{http_code}' \
-X POST \
-H 'Content-Type: application/json' \
-H "X-Pascal-Agent-Proxy-Secret: $SECRET" \
-H "X-Pascal-User-Id: $USER_ID" \
--data "$payload" \
"$BASE_URL/api/agent/chat")"
[ "$http_code" = "200" ] || {
printf 'Agent smoke request returned HTTP %s.\n' "$http_code" >&2
exit 1
}
if grep -q '"type":"error"' "$stream_file"; then
printf 'Agent smoke stream reported an error.\n' >&2
exit 1
fi
curl -fsS \
-H "X-Pascal-Scene-Token: $SECRET" \
-H "X-Pascal-User-Id: $USER_ID" \
"$BASE_URL/api/scenes/$SCENE_ID" >"$scene_file"
node -e '
const fs = require("node:fs");
const scene = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
const expectedOwner = process.argv[2];
if (!(scene.nodeCount > 0)) throw new Error("Agent did not persist scene nodes");
if (scene.ownerId !== expectedOwner) throw new Error("Scene owner mismatch");
console.log(JSON.stringify({ nodeCount: scene.nodeCount, ownerId: scene.ownerId, version: scene.version }));
' "$scene_file" "$USER_ID"
printf '[pascal-smoke] Real model and MCP persistence check passed.\n'