feat: media API (video/bbox/thumbnail), UUID unification, dot matrix text, portal fixes, API dictionary V1.3

This commit is contained in:
Warren
2026-05-06 13:34:49 +08:00
parent e75c4d6f07
commit 74b6182eba
197 changed files with 17511 additions and 8759 deletions

220
tests_api.sh Executable file
View File

@@ -0,0 +1,220 @@
#!/usr/bin/env bash
# Momentry Core API 全端點測試 — 完整輸入輸出記錄
# 用法: ./tests_api.sh [host] [port]
# 預設: http://localhost:3003
HOST="${1:-localhost}"
PORT="${2:-3003}"
BASE="http://${HOST}:${PORT}"
API_KEY="${MOMENTRY_API_KEY:-muser_test_001}"
OUTDIR="docs_v1.0/API_V1.0.0/TEST_RESULTS"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTFILE="${OUTDIR}/api_test_${TIMESTAMP}.md"
LOGDIR="${OUTDIR}/api_responses_${TIMESTAMP}"
mkdir -p "$LOGDIR" "$OUTDIR"
PASS=0; FAIL=0
log_resp() { echo -n ""; }
call_api() {
local method="$1" url="$2" desc="$3" section="$4" body="${5:-}"
local safe_name
safe_name=$(echo "${desc}" | sed 's/[^a-zA-Z0-9_]/_/g' | cut -c1-40)
local resp_file="${LOGDIR}/${section}_${safe_name}.json"
local http_code
http_code=$(curl -s -o "${resp_file}" -w "%{http_code}" \
-X "${method}" \
-H "Content-Type: application/json" \
-H "X-API-Key: ${API_KEY}" \
${body:+-d "${body}"} \
"${BASE}${url}" 2>/dev/null)
local resp_size=$(wc -c < "${resp_file}" 2>/dev/null | tr -d ' ')
local resp_preview=$(head -c 200 "${resp_file}" 2>/dev/null | tr '\n' ' ')
if [ "${http_code}" -ge 200 ] && [ "${http_code}" -lt 500 ]; then
PASS=$((PASS+1))
else
FAIL=$((FAIL+1))
fi
cat >> "${OUTFILE}" << ENTRY
### ${method} ${url}
**說明**: ${desc}
**HTTP 狀態**: ${http_code}
**回應大小**: ${resp_size} bytes
**Request**:
\`\`\`bash
curl -X ${method} \\
-H "Content-Type: application/json" \\
-H "X-API-Key: YOUR_API_KEY" \\
${body:+-d '${body}' \\}
${BASE}${url}
\`\`\`
**Response**:
\`\`\`json
$(cat "${resp_file}" 2>/dev/null)
\`\`\`
---
ENTRY
printf " %-4s %-50s %s\n" "${http_code}" "${desc}" "${resp_preview:0:80}"
}
# ==== Test Execution ====
cat > "${OUTFILE}" << HEAD
# Momentry Core API 全端點測試報告 (完整 I/O)
**測試時間**: $(date '+%Y-%m-%d %H:%M:%S')
**伺服器**: ${BASE}
**API Key**: ${API_KEY:0:10}...
**API 版本**: V4.0 / API V1
**端點總數**: 46
---
HEAD
echo "=== Momentry Core API Test ==="
echo "Server: ${BASE}"
echo ""
# 1. Health
echo "--- 1. Health ---"
SECTION="01_health"
call_api GET "/health" "Health check" "$SECTION"
call_api GET "/health/detailed" "Health detailed" "$SECTION"
# 2. Auth
echo "--- 2. Auth ---"
SECTION="02_auth"
call_api POST "/api/v1/auth/login" "Login" "$SECTION" '{"username":"demo","password":"demo"}'
call_api POST "/api/v1/auth/logout" "Logout" "$SECTION"
# 3. Files
echo "--- 3. Files ---"
SECTION="03_files"
call_api GET "/api/v1/files" "List files" "$SECTION"
call_api GET "/api/v1/files/scan" "Scan files" "$SECTION"
call_api POST "/api/v1/files/register" "Register file" "$SECTION" '{"path":"/Users/accusys/test_video/charade_sample.mp4"}'
call_api POST "/api/v1/files/unregister" "Unregister file" "$SECTION" '{"file_uuid":"00000000000000000000000000000000"}'
DEMO_FILE="417a7e93860d70c87aee6c4c1b715d70"
call_api GET "/api/v1/file/${DEMO_FILE}" "File detail" "$SECTION"
call_api GET "/api/v1/file/${DEMO_FILE}/probe" "File probe" "$SECTION"
call_api GET "/api/v1/file/${DEMO_FILE}/identities" "File identities" "$SECTION"
call_api GET "/api/v1/file/${DEMO_FILE}/chunks" "File chunks" "$SECTION"
call_api POST "/api/v1/file/${DEMO_FILE}/process" "Trigger processing" "$SECTION" '{"processors":["story"]}'
# 4. Identity
echo "--- 4. Identity ---"
SECTION="04_identity"
call_api GET "/api/v1/identities" "List identities" "$SECTION"
call_api POST "/api/v1/identity" "Create identity" "$SECTION" '{"face_json_path":"test","identity_name":"Test Identity"}'
DEMO_ID="a9a90105-6d6b-46ff-92da-0c3c1a57dff4"
call_api GET "/api/v1/identity/${DEMO_ID}" "Identity detail" "$SECTION"
call_api GET "/api/v1/identity/${DEMO_ID}/files" "Identity files" "$SECTION"
call_api GET "/api/v1/identity/${DEMO_ID}/chunks" "Identity chunks" "$SECTION"
call_api POST "/api/v1/identity/${DEMO_ID}/bind" "Bind face" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\",\"face_id\":\"face_100\"}"
call_api POST "/api/v1/identity/${DEMO_ID}/unbind" "Unbind face" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\",\"face_id\":\"face_100\"}"
call_api POST "/api/v1/identity/00000000-0000-0000-0000-000000000001/mergeinto" "Merge into" "$SECTION" '{"into_uuid":"00000000-0000-0000-0000-000000000002"}'
call_api DELETE "/api/v1/identity/00000000-0000-0000-0000-000000000003" "Delete identity" "$SECTION"
# 5. Faces
echo "--- 5. Faces ---"
SECTION="05_faces"
call_api GET "/api/v1/faces/candidates" "Face candidates" "$SECTION"
# 6. Search
echo "--- 6. Search ---"
SECTION="06_search"
call_api POST "/api/v1/search" "Vector search" "$SECTION" '{"query":"Cary Grant as mysterious stranger","limit":5}'
call_api POST "/api/v1/search/bm25" "BM25 search" "$SECTION" '{"query":"stolen fortune thriller","limit":5}'
call_api POST "/api/v1/search/hybrid" "Hybrid search" "$SECTION" '{"query":"Paris apartment scene","limit":5}'
call_api POST "/api/v1/search/smart" "Smart search" "$SECTION" '{"uuid":"'${DEMO_FILE}'","query":"Audrey Hepburn","limit":5}'
call_api POST "/api/v1/search/universal" "Universal search" "$SECTION" '{"query":"stamp","uuid":"'${DEMO_FILE}'","limit":5}'
call_api POST "/api/v1/search/frames" "Frame search" "$SECTION" '{"query":"passport","uuid":"'${DEMO_FILE}'","limit":5}'
call_api POST "/api/v1/search/visual" "Visual search" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"criteria\":{}}"
call_api POST "/api/v1/search/visual/class" "Visual by class" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"object_class\":\"person\"}"
call_api POST "/api/v1/search/visual/density" "Visual by density" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"min_density\":0.5}"
call_api POST "/api/v1/search/visual/combination" "Visual combination" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\",\"combination\":[[\"person\",1]]}"
call_api POST "/api/v1/search/visual/stats" "Visual stats" "$SECTION" "{\"uuid\":\"${DEMO_FILE}\"}"
# 7. Jobs
echo "--- 7. Jobs ---"
SECTION="07_jobs"
call_api GET "/api/v1/jobs" "List jobs" "$SECTION"
call_api GET "/api/v1/job/00000000-0000-0000-0000-000000000000" "Job detail" "$SECTION"
call_api GET "/api/v1/rule/story/status" "Rule status" "$SECTION"
call_api GET "/api/v1/progress/${DEMO_FILE}" "Progress" "$SECTION"
# 8. Resources
echo "--- 8. Resources ---"
SECTION="08_resources"
call_api GET "/api/v1/resources" "List resources" "$SECTION"
call_api POST "/api/v1/resource/register" "Register resource" "$SECTION" '{"name":"demo_worker","type":"worker","host":"localhost","port":9000}'
call_api POST "/api/v1/resource/heartbeat" "Resource heartbeat" "$SECTION" '{"name":"demo_worker"}'
# 9. Agents
echo "--- 9. Agents ---"
SECTION="09_agents"
call_api POST "/api/v1/agents/translate" "Translate" "$SECTION" '{"text":"Hello world","target_language":"zh-TW"}'
call_api POST "/api/v1/agents/identity/analyze" "Identity analyze" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
call_api POST "/api/v1/agents/identity/suggest" "Identity suggest" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
call_api GET "/api/v1/agents/identity/status" "Identity agent status" "$SECTION"
call_api POST "/api/v1/agents/suggest/merge" "Suggest merge" "$SECTION" "{\"file_uuid\":\"${DEMO_FILE}\"}"
call_api POST "/api/v1/agents/5w1h/analyze" "5W1H analyze" "$SECTION" '{"chunk_id":"chunk_1"}'
call_api POST "/api/v1/agents/5w1h/batch" "5W1H batch" "$SECTION" '{"chunk_ids":["chunk_1","chunk_2"]}'
call_api GET "/api/v1/agents/5w1h/status" "5W1H status" "$SECTION"
# 10. Stats & Admin
echo "--- 10. Stats & Admin ---"
SECTION="10_stats"
call_api GET "/api/v1/stats/sftpgo" "SFTPGo status" "$SECTION"
call_api GET "/api/v1/stats/inference" "Inference health" "$SECTION"
call_api POST "/api/v1/config/cache" "Cache toggle" "$SECTION" '{"enable":true}'
# ---- Summary ----
TOTAL=$((PASS + FAIL))
cat >> "${OUTFILE}" << SUMMARY
---
## 測試摘要
| 結果 | 數量 | 佔比 |
|------|------|------|
| ✅ 通過 (2xx/3xx/4xx) | ${PASS} | $(awk "BEGIN {printf \"%.0f\", ${PASS}/${TOTAL}*100}")% |
| ❌ 失敗 (5xx) | ${FAIL} | $(awk "BEGIN {printf \"%.0f\", ${FAIL}/${TOTAL}*100}")% |
| **合計** | **${TOTAL}** | **100%** |
> 註: 4xx 回應(如 404 Not Found、422 Unprocessable視為「通過」因為端點正常回應只是請求參數未能完整比對到資料。5xx 表示伺服器內部錯誤,需修復。
## 示範數據
| 資源 | UUID |
|------|------|
| Demo File (Charade) | \`${DEMO_FILE}\` |
| Demo Identity (Cary Grant) | \`${DEMO_ID}\` |
## 完整回應檔案
${LOGDIR}/
SUMMARY
echo ""
echo "============================================"
echo " Test Complete"
echo " PASS: ${PASS} FAIL: ${FAIL} TOTAL: ${TOTAL}"
echo " Report: ${OUTFILE}"
echo " Responses: ${LOGDIR}/"
echo "============================================"