# 总任务: blog-app 加 "AI Agent 升级迭代日报" (daily agent watchdog) 你是 manager, 严格按你的工作流: plan 拆任务 -> build 串行执行 -> review 给正式 verdict. 自己不写代码. ## Goal 给 Flask 博客应用 (workspace = /home/yi/opencode-blog-showcase/blog-app) 加一个后台日报功能: 每天自动抓 6 个 AI agent 项目的最新版本/发布/commit, 用 Exa web search 补充资料, 用本地 litellm 智能总结, 写 markdown 报告 + SQLite 存档, Flask /watchdog 页面展示最近 7 天报告并支持手动触发. ## 已验证的环境事实 (build agent 直接用, 不要重新探索) 1. **GitHub API** (无需 token, 剩余额度充足): - latest release: `GET https://api.github.com/repos/{owner}/{repo}/releases/latest` (6 个 repo 全部 200) - commits: `GET https://api.github.com/repos/{owner}/{repo}/commits?per_page=5` - 注意: `sst/opencode` 返回 301 (已改名 anomalyco/opencode), requests 默认跟随重定向即可, 但报告里 repo 名仍写 sst/opencode 2. **npm registry**: `GET https://registry.npmjs.org/{pkg}/latest` 已验证 200 的包: `opencode-ai`, `@anthropic-ai/claude-code`, `@openai/codex`, `hermes-agent`, `oh-my-openagent`. `hindsight` 包存在但可能不是 vectorize-io/hindsight 那个项目 — 取回后检查 description 相关性, 不相关就跳过该项目的 npm 源 (单源失败不得中断整体). 3. **RSS/Atom**: `https://github.com/{owner}/{repo}/releases.atom` (sst/opencode 的 atom 也 301, requests 跟随即可). 用标准库 xml.etree.ElementTree 解析, **禁止装 feedparser**. 4. **Web search = Exa 托管 MCP** (omo websearch 同款, 免 API key, 已实测可用): - 端点: `POST https://mcp.exa.ai/mcp?tools=web_search_exa` - 协议: MCP streamable HTTP / JSON-RPC. 流程: a. POST `initialize` (params: protocolVersion "2025-03-26", capabilities {}, clientInfo) — 响应头 `Mcp-Session-Id` 必须保存 b. POST `notifications/initialized` (带 Mcp-Session-Id 头) c. POST `tools/call`, name=`web_search_exa`, arguments=`{"query": "...", "numResults": 3}` (带 Mcp-Session-Id 头) - 请求头: `Content-Type: application/json`, `Accept: application/json, text/event-stream` - 响应是 SSE 格式 (`event: message\ndata: {json}`), 解析 data 行的 JSON 取 `result.content[0].text` - 参考实现: workspace 里 `.probe/exa_mcp_probe.sh` 有我实测通过的 curl 版 5. **LLM 总结 = litellm 本地代理**: `POST http://127.0.0.1:4000/v1/chat/completions`, json=`{"model": "analysis", "messages": [...], "max_tokens": 1024}`, **无需 Authorization 头**, timeout=300. model 名就是字符串 "analysis" (Qwen3.7 Plus). 发给 LLM 的单项目数据截断 (release body ≤500 字符, commit message ≤200 字符), 总 prompt <12KB. 中文输出. 6. **系统时区 Asia/Shanghai (UTC+8)** — cron `0 9 * * *` 即每天早 9 点. 7. **Flask app 现状**: app.py (561 行) 已有 get_db() (projects.db 只读), /analyze SSE 流式等. 运行方式: `/usr/bin/python3 app.py`, host 0.0.0.0 port 8090. 现有模板在 templates/, 静态在 static/. 部署脚本 scripts/deploy.sh 已存在 (kill + 重启 + 健康检查), 不要重写它, 但需要时可以读它参考. 8. **opencode 写文件权限**: agent 的 write/edit 工具只能写 workspace (/home/yi/opencode-blog-showcase/blog-app) 内部. 所有代码文件都必须落在 workspace 里. 运行时目录 (data/, logs/) 由 python 脚本运行时 os.makedirs 创建, 不是 agent 用 write 工具创建. 任何临时/测试文件落到 workspace 内 `./.review-tmp/`. ## 架构决策 (已定, 不许改) - **新文件 `scripts/daily_watchdog.py`**: 独立可执行脚本 (`/usr/bin/python3 scripts/daily_watchdog.py`), 做全部 抓取->web search 补充->LLM 总结->写报告->存 SQLite. 退出码: 全失败=1, 部分失败=0 但报告里标注. - **SQLite**: `~/opencode-blog-showcase/data/watchdog.db` (脚本运行时创建目录). 表自己设计 (建议 reports 表: date, markdown, meta_json, created_at + 唯一索引). **绝对不许碰 projects.db**. - **报告文件**: `~/opencode-blog-showcase/logs/daily-agent-watchdog-YYYY-MM-DD.md`, 同时内容存 watchdog.db. - **Flask 路由** (加在 app.py, 风格与现有路由一致): - `GET /watchdog` — 从 watchdog.db 读最近 7 天报告渲染 templates/watchdog.html (base.html extend, 导航与现有页面一致); 没有报告时显示空态 + 立即跑按钮 - `POST /watchdog/run` — subprocess 后台起 daily_watchdog.py (不等结果), redirect 回 /watchdog 并 flash "已触发, 约 1-2 分钟后刷新". 简单防重: 60 秒内重复 POST 返回 429. - base.html 导航加 "日报" 链接 - **cron**: `scripts/install_watchdog_cron.sh` — 幂等地往当前用户 crontab 加 `0 9 * * * cd /home/yi/opencode-blog-showcase/blog-app && /usr/bin/python3 scripts/daily_watchdog.py >> /home/yi/opencode-blog-showcase/logs/daily-agent-watchdog.log 2>&1` (先 crontab -l 检查已存在则跳过). 脚本由 build agent 写好, **由 review agent 或上层 worker 执行**, build 阶段不执行. - **失败告警**: 单项目/单源失败 -> 报告里该项标 "⚠️ 抓取失败: 原因", 继续其他项目. 整体失败 (如 LLM 挂) -> 仍写一份含错误说明的报告 + log 里 ERROR 行. 任何情况下脚本不得因单个源失败而崩溃退出非零 (除非连一个项目都没抓到). ## 监控项目 (6 个, ★ = 当前 setup 装了) | repo | npm 包 | ★ | 备注 | |---|---|---|---| | sst/opencode | opencode-ai | ★ | 已装 1.18.14 (301->anomalyco/opencode) | | anthropics/claude-code | @anthropic-ai/claude-code | ★ | | | openai/codex | @openai/codex | | | | NousResearch/hermes-agent | hermes-agent | ★ | | | code-yeongyu/oh-my-openagent | oh-my-openagent | ★ | | | vectorize-io/hindsight | hindsight (需验证相关性, 不相关则跳过 npm) | ★ | | ## 报告格式 (每项目必须有) - latest version, last release date, 1 句中文 changelog 摘要 (LLM 生成), breaking change 标记 (LLM 判断 true/false + 依据), ★ 相关性说明 - 报告头部: 日期, 数据源清单 (实际成功用了哪几个), 各项目一节 - **≥30% 的报告内容必须来自 web search 补充** (每项目至少 1 条 Exa 搜索结果摘要进报告, 标注来源 URL) ## Acceptance (review 必须逐项验证, 全过才 PASS) 1. cron 安装脚本存在且幂等, 安装后 `crontab -l` 能看到 9:00 条目 (review 时实际执行安装脚本验证) 2. 数据源 ≥5: GitHub Releases API / GitHub commits API / npm registry / Exa web search / GitHub releases.atom — 报告头部的数据源清单要真列出 3. 监控 6 项目, 报告每项含 version/date/中文摘要/breaking 标记/★ 4. `scripts/daily_watchdog.py` 真实跑一遍 (review agent 执行), 生成真报告 (禁止 mock), review 报告里必须附至少 1 段真实 curl/脚本输出证据 5. Flask /watchdog 渲染最近 7 天 + POST /watchdog/run 手动触发可用 (review agent 用 deploy.sh 重启后 curl 验证 127.0.0.1:8090 和 192.168.2.25:8090) 6. 无新 pip 依赖 (只用 flask/requests/sqlite3/标准库) ## 禁止 (越界=FAIL) - 禁止改 litellm 配置 / restart litellm-proxy / llama-server - 禁止改 projects.db schema, 禁止改 scripts/fetch_data.py - 禁止碰 /home/yi/wxhook, /home/yi/.litellm, /home/yi/opencode, omo 安装目录和配置 - 禁止 mock 数据 / 预生成报告 / 用云端 LLM 替代 litellm analysis - 禁止 pip install 任何新包 - 禁止删改 .probe/ 目录外的现有文件 (app.py 只做新增式修改: 加路由加导航, 不动现有路由逻辑) ## 输出 按你的 STEP/FINAL 格式汇报. FINAL 里 deliverable_path 指向 workspace 根.