#!/bin/bash # ============================================================ # Open API 人工测试脚本 # 用法: ./start.sh & 然后运行 bash scripts/test-open-api.sh # ============================================================ BASE="http://localhost:3000/api/open" KEY="sk-test-key-001" H="-H X-API-Key:$KEY" GREEN='\033[0;32m'; RED='\033[0;31m'; CYAN='\033[0;36m'; NC='\033[0m' PASS=0; FAIL=0 check() { if [ $1 -eq 0 ]; then echo -e "${GREEN}✓ PASS${NC} — $2"; PASS=$((PASS+1)) else echo -e "${RED}✗ FAIL${NC} — $2"; FAIL=$((FAIL+1)); fi } echo "" echo "════════════════════════════════════════" echo " Open API Integration Test" echo "════════════════════════════════════════" # ── T1: 无 Key → 401 ── echo -e "\n${CYAN}T1: 认证 — 无 Key${NC}" STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE/skills/search?q=test") [ "$STATUS" = "401" ]; check $? "无 Key 返回 401 (got $STATUS)" # ── T2: 错误 Key → 401 ── echo -e "${CYAN}T2: 认证 — 错误 Key${NC}" STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "X-API-Key: wrong" "$BASE/skills/search?q=test") [ "$STATUS" = "401" ]; check $? "错误 Key 返回 401 (got $STATUS)" # ── T3: 搜索命中 ── echo -e "\n${CYAN}T3: 搜索命中 — writer${NC}" RESP=$(curl -s -H "X-API-Key: $KEY" "$BASE/skills/search?q=writer") TOTAL=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin)['total'])" 2>/dev/null) [ "$TOTAL" -gt 0 ] 2>/dev/null; check $? "搜索 'writer' 命中 $TOTAL 个 Skill" # ── T4: 搜索中文 ── echo -e "${CYAN}T4: 搜索中文 — 诗歌${NC}" RESP=$(curl -s -G -H "X-API-Key: $KEY" --data-urlencode "q=诗歌" "$BASE/skills/search") TOTAL=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin)['total'])" 2>/dev/null) [ "$TOTAL" -gt 0 ] 2>/dev/null; check $? "搜索 '诗歌' 命中 $TOTAL 个 Skill" # ── T5: Skill 详情 ── echo -e "\n${CYAN}T5: Skill 详情 — novel_writer${NC}" RESP=$(curl -s -H "X-API-Key: $KEY" "$BASE/skills/novel_writer") NAME=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin).get('skillName',''))" 2>/dev/null) DIR=$(echo "$RESP" | python3 -c "import json,sys; print('directory' in json.load(sys.stdin))" 2>/dev/null) [ "$NAME" = "novel_writer" ]; check $? "返回 skillName=novel_writer" [ "$DIR" = "False" ]; check $? "不泄露 directory 字段" # ── T6: 404 Skill ── echo -e "${CYAN}T6: 不存在的 Skill${NC}" STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "X-API-Key: $KEY" "$BASE/skills/nonexistent_xyz") [ "$STATUS" = "404" ]; check $? "返回 404 (got $STATUS)" # ── T7: 下载 .zip ── echo -e "\n${CYAN}T7: 下载 Skill — novel_writer.zip${NC}" TMPZIP="/tmp/test_novel_writer_$$.zip" curl -s -H "X-API-Key: $KEY" -o "$TMPZIP" "$BASE/skills/novel_writer/download" FILETYPE=$(file "$TMPZIP" 2>/dev/null) echo "$FILETYPE" | grep -qi "zip"; check $? "返回的是 Zip 文件" FILECOUNT=$(unzip -l "$TMPZIP" 2>/dev/null | tail -1 | awk '{print $2}') [ "$FILECOUNT" -gt 1 ] 2>/dev/null; check $? "Zip 包含 $FILECOUNT 个文件" # 检查内部结构 unzip -l "$TMPZIP" 2>/dev/null | grep -q "SKILL.md"; check $? "Zip 包含 SKILL.md" unzip -l "$TMPZIP" 2>/dev/null | grep -q "manifest.json"; check $? "Zip 包含 manifest.json" rm -f "$TMPZIP" # ── T8: Job 列表 ── echo -e "\n${CYAN}T8: Job 列表${NC}" RESP=$(curl -s -H "X-API-Key: $KEY" "$BASE/jobs") echo "$RESP" | python3 -c "import json,sys; json.load(sys.stdin)['total']" >/dev/null 2>&1 check $? "Job 列表返回正常" # ── T9: 搜索未命中 → 自动创建 ── echo -e "\n${CYAN}T9: 搜索未命中 → autoCreate${NC}" RESP=$(curl -s -G -H "X-API-Key: $KEY" --data-urlencode "q=量子计算模拟器XYZ" "$BASE/skills/search") TOTAL=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin)['total'])" 2>/dev/null) JOBID=$(echo "$RESP" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('autoCreate',{}).get('jobId',''))" 2>/dev/null) [ "$TOTAL" = "0" ]; check $? "搜索结果为空 (total=0)" [ -n "$JOBID" ] && [ "$JOBID" != "" ]; check $? "自动创建返回 jobId=$JOBID" # 查询 job 状态 if [ -n "$JOBID" ] && [ "$JOBID" != "" ]; then echo -e "${CYAN} → 查询 Job 状态${NC}" JOB_STATUS=$(curl -s -H "X-API-Key: $KEY" "$BASE/jobs/$JOBID" | python3 -c "import json,sys; print(json.load(sys.stdin).get('status',''))" 2>/dev/null) [ -n "$JOB_STATUS" ]; check $? "Job 状态: $JOB_STATUS" fi # ── T10: API 日志 ── echo -e "\n${CYAN}T10: API 访问日志${NC}" LOGFILE="apiconversation/$(date +%Y-%m-%d).jsonl" [ -f "$LOGFILE" ]; check $? "日志文件存在: $LOGFILE" if [ -f "$LOGFILE" ]; then LINES=$(wc -l < "$LOGFILE" | tr -d '[:space:]') [ "$LINES" -gt 0 ] 2>/dev/null; check $? "日志已记录 $LINES 条请求" fi # ── 结果 ── echo "" echo "════════════════════════════════════════" echo -e " 结果: ${GREEN}$PASS PASS${NC} / ${RED}$FAIL FAIL${NC}" echo "════════════════════════════════════════" echo ""