{
  "markdown": "# AgentPrism\n\n> 同一个问题，多条管线受控并行，差异可量化、可复现。\n\n**AgentPrism** 是一个 Agent 对比实验台（Arena）。用户输入一个问题或任务，系统同时启动多条 Agent 管线并行运行，实时流式展示每个 Agent 的推理过程、工具调用、中间结果，最终汇总对比报告。\n\n就像一束白光穿过棱镜折射出光谱——一个问题，折射出 Agent 的万千可能。\n\n## 为什么需要 AgentPrism\n\n学 Agent 开发最大的痛点：**框架太多，不知道选哪个；模式太多，不知道差在哪。**\n\n- LangChain、LangGraph、AutoGen、CrewAI……文档各看一遍，还是不会选\n- ReAct、CoT、ToT、Reflexion……概念都懂，但跑起来到底有什么区别？\n- Harness Engineering、Loop Engineering……2026 最前沿的概念，没有项目实践过\n\nAgentPrism 的答案：**同一个问题，多条管线并行跑，差异一目了然。**\n\n## 核心功能\n\n### Arena 实验台\n\n- **5 主对比维度 + 5 扩展控制变量**：主对比 — 框架 / 提示词 / 推理模式 / 上下文策略 / Harness；扩展 — temperature / model / thinking / max_steps / toolset\n- **共享多轮对话**：各列共用 `messages` 续聊；跑完可「用作续聊」，Trace / TraceDiff 按 `turn` 分段\n- **实时流式输出**：打字机效果渲染 Agent 推理过程，支持 Markdown\n- **工具调用展示**：文件操作折叠预览、代码执行代码块、参数格式化\n- **对比报告**：耗时 / Token / 工具调用 / 步骤数硬指标对比表格 + 最快/最省标记\n- **Trace 对比**：按 step（多轮时按 `turn*10000+step`）对齐各列事件，差异高亮（TraceDiff）\n- **Agent 工作空间**：每个 Agent 独立文件系统（路径规范化 + TTL/LRU），实时文件浏览器侧栏\n- **项目管理**：从 Arena 运行结果一键创建项目，保存工作空间和对比结果\n- **维度说明 / 学习路径**：`/guide` 说明对比维度与多轮形态；`/learn` 八周引导一键预填 Arena\n\n### 对比维度\n\n| 维度 | 列数 | 实现位置 | 说明 |\n|------|------|----------|------|\n| 框架 | 2 | `arena/router.py` + `adapters/{langchain,langgraph}_adapter.py` | LangChain (`create_agent`) vs LangGraph (`StateGraph`) |\n| 提示词 | 4 | `arena/prompts.py` | Zero-shot / Few-shot / CoT Prompt / Structured |\n| 推理模式 | 4 | `arena/reasoning/registry.py` | ReAct / CoT+Tool / ToT / Reflexion（4 张独立图） |\n| 上下文 | 4 | `arena/context.py` + `workspaces/rag.py` | 滑动窗口 / 摘要 / 向量检索（TF-IDF）/ 混合 |\n| Harness | 4 | `arena/harness.py` | 裸运行 / 验证 / 反思 / 自进化（HarnessRunner `astream_events` 拦截） |\n\n### Agent 能力\n\n每个 Agent 拥有独立工作空间，支持 11 个工具（`arena/tools/toolkit.py`）：\n\n| 类别 | 工具 |\n|------|------|\n| 基础 | `get_current_time` / `calculate`（AST 白名单） |\n| 工作空间 | `write_file` / `append_file` / `create_file` / `read_file` / `list_files` / `file_tree` / `delete_file` |\n| 代码执行 | `run_code`（**独立进程沙箱 + AST 静态校验 + 1-10s 超时强制 terminate/kill**） |\n| 文本 | `summarize_text` |\n\n## 技术栈\n\n| 层 | 技术 |\n|----|------|\n| 前端 | Next.js **16.2.10** + React 19.2.4 + TypeScript 5.9 + Tailwind v4 |\n| 后端 | FastAPI + Python 3.11+ + SSE (sse-starlette) + Pydantic v2 |\n| LLM | LangChain `ChatAnthropic` / `ChatOpenAI`，BYOK |\n| 实时通信 | SSE（`EventSourceResponse`） |\n| 数据 | 文件级 JSON（`data/provider_config.json` + `data/projects.json`），**无 SQL/ORM** |\n| 前端状态 | 仅 React 内置 hooks |\n\n> ⚠️ **Next.js 16 与训练数据差异较大**，写代码前务必读 `frontend/AGENTS.md` 与 `node_modules/next/dist/docs/`，已弃用 API 与旧文档可能不一致。\n\n## 快速开始\n\n### 环境要求\n\n- Python 3.11+（`pyproject.toml` `requires-python = \">=3.11\"`；CI 使用 3.14）\n- Node.js 20+\n- npm\n\n### 后端启动\n\n```bash\ncd backend\npython -m venv .venv\n# Windows: .venv\\Scripts\\activate\n# macOS/Linux: source .venv/bin/activate\npip install -e \".[dev]\"   # 运行依赖 + ruff/pytest/mypy（依赖清单唯一来源：backend/pyproject.toml）\ncp .env.example .env  # 配置 API Key（可选，UI 也可配）\npython -m app.main     # 监听 8281（配置在 .env BACKEND_PORT），默认带热重载；生产入口加 --no-reload\n```\n\n> 注意：裸跑 `uvicorn app.main:app` 不指定 `--port` 会落在 uvicorn 默认 8000\n> （uvicorn CLI 不读取 .env 的 BACKEND_PORT），请使用 `python -m app.main` 或显式 `--port`。\n\n### 前端启动\n\n```bash\ncd frontend\nnpm install\nnpm run dev   # 默认端口 8280（package.json dev 脚本经 scripts/dev.mjs 启动器预检端口）\n```\n\n> `dev` 脚本经 `frontend/scripts/dev.mjs` 启动器运行：端口被占用时先于\n> Next.js 给出友好提示并以非零码退出（Next.js 16 自身对端口占用只会打印\n> 假 \"✓ Ready\"，不会报错）。\n\n### API 文档\n\nAPI 文档由 FastAPI 内置 Swagger UI 提供，**挂在后端端口**（默认\nhttp://127.0.0.1:8281/docs，ReDoc 在 /redoc），**无独立端口**。\n\n健康检查：\n\n- `GET http://127.0.0.1:8281/health` — 判断后端是否正常运行（返回 `{\"status\":\"ok\",\"service\":\"arena\"}`）\n- `GET http://127.0.0.1:8281/api/health` — 同上，历史兼容\n\n### 显式指定端口\n\n各服务直接运行时的默认端口如上，也支持命令行参数或环境变量显式指定：\n\n| 服务 | 命令行参数 | 环境变量 |\n|------|-----------|---------|\n| 后端 | `python -m app.main --port 3333` | `BACKEND_PORT=3333` |\n| 前端 | `npm run dev -- -p 5555` | —（默认 8280，见 package.json） |\n\n> 传参时放在 `--` 之后，npm 才会把参数透传给 `next`：`npm run dev -- -p 5555`。\n> 前端 dev 端口由 `frontend/scripts/dev.mjs` 预检后启动，端口被占用时友好提示并退出。\n\n**端口改动的全链路联动（单一配置源）**：\n\n- 改 **后端端口**：只需改仓库根 `.env` 的 `BACKEND_PORT`，重启后端。\n  `frontend/next.config.ts` 会自动读取该值作为代理目标，API 文档也\n  自动跟随（挂在后端端口 /docs）。**无需手工同步。**\n  - 若仅临时用 `--port` 指定后端端口（不改 .env），前端代理不会自动\n    跟随——需同步修改 .env 的 `BACKEND_PORT`，或以 `BACKEND_PORT=3333 npm run dev`\n    启动前端（该进程环境变量优先级最高）。\n- 改 **前端端口**：直接 `npm run dev -- -p <port>`。CORS 白名单由\n  `frontend_port` 自动派生（localhost 与 127.0.0.1 双变体），改端口后\n  同源代理架构不受影响；直连模式下需将新 origin 追加到 `CORS_ORIGINS`。\n- `CORS_ORIGINS` 现在仅作**额外追加**（默认白名单为端口自动派生），如追加\n  局域网 IP 直连 origin；不再需要手工维护默认端口。\n- CORS 白名单含通配符 `*` 时后端启动即 fail-fast（与 `allow_credentials=True`\n  冲突，浏览器会静默拒绝）。\n\n### 端口占用策略\n\n端口被占用时**不会自动顺延**，而是给出友好提示后退出（原因见下）。\n\n- 后端：`python -m app.main` 启动前用 bind + connect 双检测预检端口；\n  被占用则提示「占用确认命令 + 处理方式（释放进程或 `--port` 显式指定）」并以非零码退出。\n- 前端：`npm run dev` 经 `frontend/scripts/dev.mjs` 启动器预检（同构双检测），\n  被占用时先于 Next.js 给出友好提示并以非零码退出。\n\n为什么不做自动顺延：本项目是多服务联动架构——前端代理与 CORS 白名单\n都与端口强绑定。后端若自动顺延，前端代理会静默断链，且 Windows 上 uvicorn\n端口被占用时可能「静默共存」（显示启动成功、实际连接被旧进程接收），比显式\n报错更危险。因此保持端口固定、失败时明确提示，是更安全的默认。\n\n打开 http://localhost:8280 进入 Arena（根路径 `/` 会自动重定向）。\n\n### 端口约定\n\n| 端口 | 服务 |\n|------|------|\n| 8280 | 前端 Next.js |\n| 8281 | 后端 FastAPI + API 文档（/docs、/redoc、/openapi.json）+ 健康检查（/health、/api/health） |\n\n新增服务从 8282 开始依次顺延。\n\n### 配置 Provider\n\n首次使用需要在 Settings 页面配置 LLM Provider（BYOK）：\n1. 填写 API Key\n2. 配置 Base URL（默认 `https://api.stepfun.com/step_plan`，anthropic_messages 兼容）\n3. 选择模型（默认 `step-3.7-flash`）\n4. 点击「管理与测试」验证连接\n\nAPI Key 保存在本地 `data/provider_config.json`，**仅本地保存，不会提交到 Git**。\n\n### 可选鉴权（API Token）\n\n默认无鉴权（仅限本机使用）。需要对外暴露时，可通过环境变量或 `.env` 设置\n`API_TOKEN=<token>` 启用共享密钥认证：除 `/health` 与 `/api/health` 两个\n健康检查外，所有请求（含 `/docs`、`/openapi.json`）需携带\n`Authorization: Bearer <token>` 或 `X-API-Token: <token>`。\n\n> 注意：实际生效的环境变量名是 `API_TOKEN`（pydantic-settings 默认大小写不敏感、\n> 无 AGENTPRISM 前缀）。\n\n### 对外暴露安全指引\n\n本项目默认绑定 `127.0.0.1`（仅本机访问），适合本地开发。若需部署到\n**局域网 / 公网**：\n\n- **后端**：默认 127.0.0.1 是安全的；确需对外时改为 `BACKEND_HOST=0.0.0.0`\n  前，请先设置 `API_TOKEN`（见上），并通过防火墙 / 反向代理（nginx 等）限制访问。\n- **前端**：`next dev` 默认监听 0.0.0.0，局域网内他人可直接访问开发服务器，\n  属正常 dev 行为；生产部署请使用 `npm run build && npm run start`。\n  后端设置 `BACKEND_HOST=0.0.0.0` 且未设 `API_TOKEN` 时，启动会打印\n  局域网暴露警告（lifespan 启动日志）。\n- **建议**：生产环境置于反向代理之后（HTTPS + 鉴权），并收紧\n  `frontend/next.config.ts` 的 CSP（当前 `'unsafe-inline'/'unsafe-eval'`\n  为 dev 模式所需，注释已注明生产前应收紧）。\n\n### 直连模式（可选，实验性）\n\n默认架构为**同源代理**：浏览器请求 `/api/*` 由 Next.js 转发到后端（8281），\n无需 CORS、不受 CSP `connect-src` 影响。如确需浏览器**直连**后端\n（例如后端独立部署、前端跨源访问），需同时满足：\n\n1. 设置 `NEXT_PUBLIC_API_BASE=http://<host>:<port>`（前端构建时读入）；\n2. 将后端地址加入根 `.env` 的 `CORS_ORIGINS`（前端页面 origin 的精确端口）；\n3. 放宽 `frontend/next.config.ts` 的 CSP `connect-src`（当前为 `'self'`，\n   默认会静默拦截直连请求，含 SSE 流式）。\n\n> 注意：直连模式下 SSE（`/api/arena/run`）同样受 CSP `connect-src` 约束。\n> 同源代理架构无此问题，除非有跨源部署需求，否则保持默认即可。\n\n### 已知依赖漏洞（2026-08-10）\n\n- 后端：`pip-audit` **未发现已知漏洞**。\n- 前端：`npm audit` 报告 **4 个 high 级**漏洞（postcss XSS/路径遍历、\n  sharp/libvips CVE），修复需将 next 升级到 16.3.0（超出当前 16.2.10 声明范围），\n  尚未执行。CI 已加 `npm audit --audit-level=critical` 门禁（high 不阻塞、\n  critical 硬拦）；升级 next 的决定待定（见「依赖审计」小节末尾）。\n- 依赖审计命令：`pip-audit`（后端）、`npm audit --omit=dev`（前端）。\n\n支持的 API 格式：\n- `anthropic_messages`（默认，Anthropic 兼容）\n- `openai_chat`（OpenAI Chat 兼容，Settings 高级选项切换）\n\n## 测试\n\n```bash\n# 后端测试 — 37 个测试文件 / 344 个 test_ 函数\nPYTHONPATH=backend pytest tests/ -v\n\n# 仅 lint\ncd backend && ruff check app/\n\n# 类型检查\ncd backend && mypy app/ --ignore-missing-imports\n\n# 前端类型检查 + 构建\ncd frontend && npx tsc --noEmit\ncd frontend && npm run build\n```\n\n> 测试根目录为仓库根 `tests/`（`backend/tests/` 仅保留迁移说明）。\n\n## 开发约束\n\n详见 [CLAUDE.md](./CLAUDE.md)。前端额外约束见 `frontend/AGENTS.md`（Next.js 16 警示）。\n\n**当前开发进度报告**：[docs/product/PROGRESS.md](./docs/product/PROGRESS.md)。\n\n## 最近改进\n\n### 后端\n- **任务模板库 + 自动判分器**（Phase 9）：`arena/templates.py` 8 个预置模板 + `arena/judging.py`（json / keyword / code / numeric / exclude / regex）；`GET /api/arena/templates` + `POST /api/arena/judge`\n- **消息消毒 / 工具守卫**：`message_sanitize.py` + `tool_guard.py`，拦截跑题 tool_calls 与异常消息块\n- **错误脱敏**：`errors.sanitize_error_message`（SSE / API 仅暴露异常类型名）\n- **原子写统一**：`storage._atomic_write_json`（config / projects 共用）\n- **安全加固**：self_evolve prompt 注入脱敏；`run_code` 输出截断 + Queue 清理；`calculate` 大指数拦截；向量片段 fence；LRU 保护运行中工作空间\n- **WorkspaceManager**：TTL 1h + LRU 32\n- **HarnessRunner**：`astream_events` 真实拦截 verify/reflect/harness_edit\n- **run_code**：独立进程沙箱 + AST + terminate/kill\n- **类型严谨**：Literal 化 PipelineConfig 维度字段；`mypy app/` 零错误\n\n### 项目管理\n- **精确 workspace 匹配**：`create_from_run` 用 `workspace_names`，避免同 label 覆盖\n- **落盘失败显式失败**：`_save` 抛错，API 返回 HTTP 500（不再静默 200）\n- **ID 唯一**：微秒时间戳 + UUID 后缀\n\n### 前端\n- **Vercel 风格 UI**：Geist 字体 + 设计 token；配置摘要三栏铺满；运行条任务模板 / 输入 / 运行同高\n- **共享多轮对话**：`chatHistory` +「用作续聊」/「新对话」；按轮 Trace；对比形态为 Trace 分段而非新维度\n- **学习路径引导页 `/learn`**（Phase 8）：八周计划（含多轮续聊与按轮对比），一键预填 Arena\n- **维度说明 `/guide`**：含多轮与对比形态说明\n- **可判分任务模板**：判分方式徽章 + 跑后自动判分（列徽章 / 对比报告列）\n- **URL 参数预填**：`/arena?template=...&q=...&dimension=...&selections=...`\n- **路由错误边界**：`error.tsx` + `global-error.tsx`\n- **TraceDiff 长文本展开**：>300 字符可展开/收起\n- **「保存为项目」**：跑完后一键入库\n- **ExperimentPanel**：多滑块合并为单一 PUT\n\n### 测试\n- **判分器 + 模板库**：`tests/test_judging.py` + `tests/test_templates.py`\n- **多轮历史契约**：`tests/test_chat_history.py`（成对交替、长度上限、`turn` 戳记）\n- **基线覆盖**：`tests/test_baseline_overrides.py`\n- **消息消毒 / tool_guard**：`tests/test_message_sanitize.py`\n- **ContextVar 取消路径**、前端契约（模板/判分/学习路径）、Workspace TTL/LRU\n- **统计**：37 文件 / 344 个 `test_`（仓库根 `tests/`）\n\n## 路线图\n\n- [x] Phase 1: 双框架对比 + SSE 流式输出\n- [x] Phase 2: 工具集扩充 + 工作空间 + 提示词维度 + 项目管理\n- [x] Phase 3: 三栏 UI + 对比报告 + 真流式 thought_delta\n- [x] Phase 4: 全维度启用（推理/上下文/Harness 引擎 + LangGraph 图）\n- [x] Phase 5: Harness 引擎完善（Verify/Reflect/Self-Evolve + 真实验证循环）\n- [x] Phase 8: 学习路径引导 UI（`/learn`）\n- [x] Phase 9: 任务模板库 + 确定性判分器\n- [x] Phase 11: CI mypy 硬性门槛\n- [ ] Phase 6: AutoGen / CrewAI Adapter 实装（预留条目，Python 3.14 环境暂不可装）\n- [ ] Phase 7: MCP Server / Client 集成\n- [ ] Phase 10: Harness Lab（独立 YAML 编辑器 + Primitive 组合）\n\n详见 [docs/product/PROGRESS.md](./docs/product/PROGRESS.md) §5。\n\n## License\n\nMIT",
  "bytes": 9866,
  "sha": "94052145807ec9f9e7982c86a5c395f25686bcec8f37e5f8e97cf5818e5b1141",
  "repo_slug": "daftpunkwav/agent-prism-beta",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_daftpunkwav_agent_prism_beta_openwiki_in_aa7cb07b/readme"
}