Files

135 lines
5.0 KiB
Python
Raw Permalink Normal View History

2026-08-04 14:02:45 +08:00
#!/usr/bin/env python3
"""
query_tasks.py 列出 Holy Crab 所有任务
用法: python3 query_tasks.py [任务ID 关键词]
Examples:
python3 query_tasks.py
python3 query_tasks.py HC-20260727-ABC12
"""
import json
import os
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
DEFAULT_BACKEND = "http://localhost:8000"
def load_cookie() -> str | None:
# 优先级:环境变量 > ~/.holy_crab_env > ~/.holy_crab_cookie
env = os.environ.get("HC_SESSION")
if env:
return env
env_file = Path.home() / ".holy_crab_env"
if env_file.exists():
for line in env_file.read_text().strip().splitlines():
line = line.strip()
if line.startswith("HC_SESSION=") or line.startswith("hc_session="):
val = line.split("=", 1)[1].strip().strip('"').strip("'")
if val:
return val
cookie_file = Path.home() / ".holy_crab_cookie"
if cookie_file.exists():
return cookie_file.read_text().strip()
return None
def api_get(path: str, params: dict | None = None) -> dict:
backend = os.environ.get("HC_BACKEND_URL", DEFAULT_BACKEND).rstrip("/")
url = f"{backend}/api/v1{path}"
cookie = load_cookie()
headers = {}
if cookie:
headers["Cookie"] = f"hc_session={cookie}"
import urllib.request
req = urllib.request.Request(url, headers=headers)
if params:
import urllib.parse
req.full_url = f"{url}?{urllib.parse.urlencode(params)}"
try:
with urllib.request.urlopen(req, timeout=15) as resp:
return json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
try:
err = json.loads(body)
print(f"❌ API错误 {exc.code}: {err}", file=sys.stderr)
except Exception:
print(f"❌ HTTP {exc.code}: {body[:300]}", file=sys.stderr)
sys.exit(1)
def format_status(status: str) -> str:
mapping = {
"completed": "✅ 完成",
"failed": "❌ 失败",
"cancelled": "🚫 取消",
"partial": "⚠️ 部分",
"running": "⏳ 进行中",
"waiting": "⏳ 等待中",
}
return mapping.get(status, status)
def main() -> None:
task_id_filter = sys.argv[1] if len(sys.argv) > 1 else None
if task_id_filter:
# 精确查单个任务
data = api_get(f"/tasks/{task_id_filter}")
task = data.get("data", {})
print(f"\n{''*60}")
print(f" 任务ID : {task.get('task_id')}")
print(f" 名称 : {task.get('name')}")
print(f" 关键词 : {', '.join(task.get('keywords', []))}")
print(f" 状态 : {format_status(task.get('status'))}")
print(f" 进度 : {task.get('progress_percent')}%")
print(f" 模式 : {task.get('mode')}")
print(f" 创建时间 : {task.get('created_at')}")
print(f" 完成时间 : {task.get('completed_at') or ''}")
if task.get("error"):
print(f" 错误 : [{task['error'].get('code')}] {task['error'].get('message')}")
# 检查 extracted
result = task.get("result", {})
extracted = result.get("extracted")
if extracted:
meta = extracted.get("提取元数据", {})
stats = meta.get("召回统计", {})
print(f"\n 📊 数据清洗结果:")
print(f" schema : {extracted.get('schema_version')}")
print(f" 标签总数 : {stats.get('标签总数', 'N/A')}")
print(f" 召回总数 : {stats.get('实际召回内容总数', 'N/A')}")
print(f" 榜单数量 : {len(extracted.get('榜单', []))}")
print(f" 产品数量 : {len(extracted.get('产品详情', []))}")
src = extracted.get("参考来源笔记总量", {})
print(f" 笔记总量 : {src.get('原始文本', 'N/A')}")
else:
print(f"\n ⏳ 任务尚未完成或无 extracted 数据")
print(f"{''*60}\n")
else:
# 列表
data = api_get("/tasks", {"page_size": 50})
items = data.get("data", {}).get("items", [])
total = data.get("data", {}).get("total", 0)
print(f"\n{''*60}")
print(f" Holy Crab 任务列表 (共 {total} 个)")
print(f"{''*60}")
print(f" {'任务ID':<22} {'状态':<14} {'关键词':<16} {'创建时间':<12} {'文件'}")
print(f" {''*60}")
for t in items:
keywords = ",".join(t.get("keywords", [])[:2])
if len(",".join(t.get("keywords", []))) > 16:
keywords += "..."
status = format_status(t.get("status", ""))
files = len(t.get("files", []))
ts = (t.get("created_at") or "")[:10]
print(f" {t.get('task_id'):<22} {status:<14} {keywords:<16} {ts:<12} {files}f")
print(f"{''*60}\n")
if __name__ == "__main__":
main()