Commit 5454b2cdaf6b1aa6c7f1550db3aadcecb09903bc
1 parent
2d4783a2
chore: update agents, server routes, start script, and views
Showing
12 changed files
with
128 additions
and
32 deletions
server/routes/agent-chat.js
| ... | ... | @@ -664,6 +664,13 @@ async function getOrCreateProtocol(agentId, convId) { |
| 664 | 664 | } |
| 665 | 665 | |
| 666 | 666 | const protocol = new ClaudeCliProtocol({ name: identity.name }, cliOptions); |
| 667 | + | |
| 668 | + // 绑定错误监听器,防止 EventEmitter 抛出未捕获异常导致整个 Node 进程奔溃 (例如 spawn claude ENOENT) | |
| 669 | + protocol.on('error', (err) => { | |
| 670 | + console.error(`[AgentChat] 🚨 ${identity.name} 协议级异常:`, err.message); | |
| 671 | + sessions.delete(key); // 下次提问将重建进程 | |
| 672 | + }); | |
| 673 | + | |
| 667 | 674 | await protocol.connect(null, agentDir); |
| 668 | 675 | await protocol.initialize(); |
| 669 | 676 | await protocol.newSession({ cwd: agentDir }); | ... | ... |
server/routes/company.js
| ... | ... | @@ -713,7 +713,7 @@ router.get('/:companyId/status', (req, res) => { |
| 713 | 713 | const heartbeatService = require('../services/heartbeat-service'); |
| 714 | 714 | const path = require('path'); |
| 715 | 715 | const fs = require('fs'); |
| 716 | - const DATA_DIR = path.resolve(__dirname, '../../data'); | |
| 716 | + const DATA_DIR = path.resolve(__dirname, '../../data/companies'); | |
| 717 | 717 | |
| 718 | 718 | // 计算运行时长 |
| 719 | 719 | const uptimeMs = company.status === 'running' && company.startedAt |
| ... | ... | @@ -776,7 +776,7 @@ router.put('/:companyId/agents/:agentId/heartbeat', (req, res) => { |
| 776 | 776 | const { intervalMinutes, enabled } = req.body; |
| 777 | 777 | const path = require('path'); |
| 778 | 778 | const fs = require('fs'); |
| 779 | - const DATA_DIR = path.resolve(__dirname, '../../data'); | |
| 779 | + const DATA_DIR = path.resolve(__dirname, '../../data/companies'); | |
| 780 | 780 | const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); |
| 781 | 781 | |
| 782 | 782 | if (!fs.existsSync(configPath)) { |
| ... | ... | @@ -816,7 +816,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/start', (req, res) => { |
| 816 | 816 | try { |
| 817 | 817 | const path = require('path'); |
| 818 | 818 | const fs = require('fs'); |
| 819 | - const DATA_DIR = path.resolve(__dirname, '../../data'); | |
| 819 | + const DATA_DIR = path.resolve(__dirname, '../../data/companies'); | |
| 820 | 820 | const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); |
| 821 | 821 | |
| 822 | 822 | if (!fs.existsSync(configPath)) { |
| ... | ... | @@ -846,7 +846,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/stop', (req, res) => { |
| 846 | 846 | try { |
| 847 | 847 | const path = require('path'); |
| 848 | 848 | const fs = require('fs'); |
| 849 | - const DATA_DIR = path.resolve(__dirname, '../../data'); | |
| 849 | + const DATA_DIR = path.resolve(__dirname, '../../data/companies'); | |
| 850 | 850 | const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); |
| 851 | 851 | |
| 852 | 852 | if (!fs.existsSync(configPath)) { |
| ... | ... | @@ -883,7 +883,7 @@ router.get('/:companyId/agents/:agentId/skills', (req, res) => { |
| 883 | 883 | try { |
| 884 | 884 | const path = require('path'); |
| 885 | 885 | const fs = require('fs'); |
| 886 | - const DATA_DIR = path.resolve(__dirname, '../../data'); | |
| 886 | + const DATA_DIR = path.resolve(__dirname, '../../data/companies'); | |
| 887 | 887 | const skillsDir = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'skills'); |
| 888 | 888 | |
| 889 | 889 | if (!fs.existsSync(skillsDir)) { | ... | ... |
start.sh
system/agents/digester-youtube-crawler/todo.md
| ... | ... | @@ -12,3 +12,4 @@ |
| 12 | 12 | | T-mnevj3i8 | 消化 youtube-crawler 的 knowhow.md,为 youtube-crawler Agent 模板生成 benchmark 与训练数据集。\n\n## 输入\n- knowhow.md 路径: system/templates/youtube-crawler/workspace/hunt/knowhow.md\n\n## 产出要求(写入以下目录)\n- 输出目录: system/templates/youtube-crawler/workspace/digest/\n- benchmark.md: 设计 5-8 个可量化维度,权重总和 100%,定义 0-100 分评分细则,设定及格/良好/优秀阈值,目标设计标准达到 90 分以上。\n- train.json: 训练数据集 ≥40 条样本,每条标注各维度得分与总分。\n- test.json: 测试数据集 ≥10 条样本。\n- industry_avg.json: 行业基线(设定 industry_avg_score 和 elite_avg_score)。\n\n## 验收标准\n1. JSON 文件必须合法可解析\n2. benchmark.md 中权重总和 = 100%\n3. train + test 总样本数 ≥ 50\n4. 完成后汇报文件路径和 benchmark 设计摘要 | ✅ 完成 | innovator | P1 | 2026-03-31 17:11 | - | |
| 13 | 13 | | T-mnevwogv | 执行 DIGEST 阶段:消化 youtube-crawler 的 knowhow.md,生成 benchmark.md、train.json、test.json 和 industry_avg.json。输入文件: /mnt/lemonboss/system/templates/youtube-crawler/workspace/hunt/knowhow.md。产出目录: /mnt/lemonboss/system/templates/youtube-crawler/workspace/digest/。要求: 1) benchmark.md 设计 5-8 个可量化维度,权重总和100%,定义0-100分评分细则,设定及格/良好/优秀阈值,目标总分90+;2) train.json ≥40条样本,test.json ≥10条样本;3) industry_avg.json 包含 industry_avg_score 和 elite_avg_score。完成后更新任务状态并汇报。 | ✅ 完成 | innovator | P1 | 2026-03-31 17:22 | - | |
| 14 | 14 | | T-mnevyvaz | 执行 DIGEST 阶段:消化 youtube-crawler 的 knowhow.md,生成 benchmark.md、train.json、test.json 和 industry_avg.json。输入文件: /mnt/lemonboss/system/templates/youtube-crawler/workspace/hunt/knowhow.md。产出目录: /mnt/lemonboss/system/templates/youtube-crawler/workspace/digest/。要求: 1) benchmark.md 设计 5-8 个可量化维度,权重总和100%,定义0-100分评分细则,设定及格/良好/优秀阈值,目标总分90+;2) train.json ≥40条样本,test.json ≥10条样本;3) industry_avg.json 包含 industry_avg_score 和 elite_avg_score。完成后更新任务状态并汇报。 | ✅ 完成 | innovator | P1 | 2026-03-31 17:23 | - | |
| 15 | +| T-mnj3nimu | 【FDE Phase 2: DIGEST】对 YouTube Data API v3 爬取技能进行知识消化与 Benchmark 生成。<br><br>## 目标<br>为 youtube-trending-crawler 技能生成 benchmark 评分标准和训练数据集。<br><br>## 输入文件<br>Hunter 产出的文件位于: /Users/yibo/Documents/lemonAI/lemonboss/system/agents/hunter/workspace/youtube-trending/<br>- knowhow_v2.md<br>- crawl_config.json<br><br>## 目标 Agent<br>- company: test<br>- agent: claude-youtube-skills<br><br>## Digest 任务要求<br>1. **解析 knowhow_v2.md** - 提取核心知识点和 API 调用方法论<br>2. **生成 benchmark_v2.md** - 可量化的评分标准,包含:<br> - API 调用准确性<br> - 数据字段完整性<br> - 多地区/多分类支持<br> - 错误处理健壮性<br> - 输出格式正确性<br> - 配额管理合理性<br>3. **生成训练数据集** (如可能):<br> - train.json: 训练样本<br> - test.json: 测试样本<br>4. **计算行业基线分**: industry_avg_score (建议 85-90 分)<br><br>## 输出路径<br>必须写入: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/digest/<br>- benchmark_v2.md - 量化评分标准<br>- train.json - 训练数据集<br>- test.json - 测试数据集<br>- industry_avg.json - 行业基线分数<br><br>## 重要提醒<br>- 读取已有的旧版本 benchmark.md (如存在),合并并输出新版本 benchmark_v2.md<br>- 保留所有已有内容,追加新的评分维度 | ⬚ 未开始 | innovator | P0 | 2026-04-03 16:09 | - | | ... | ... |
system/agents/evolver-youtube-crawler/SKILL.md
| ... | ... | @@ -104,9 +104,9 @@ try { |
| 104 | 104 | |
| 105 | 105 | |
| 106 | 106 | ## 经验教训 (自动沉淀) |
| 107 | - | |
| 108 | -> 以下经验由系统自动从历史对话中提取沉淀,帮助你避免重复犯错。 | |
| 109 | - | |
| 110 | 107 | - ✅ [2026-03-31] 成功创建/修改了 3 个文件: workspace/evolve/skill_youtube_crawler.md`, workspace/evolve/evolution_log.json`, workspace/evolve/test_results.json` |
| 111 | 108 | - ✅ [2026-03-31] 完成了 36 步工具调用的复杂任务 (931秒) |
| 112 | 109 | - ✅ [2026-03-31] 涉及技能训练/评分/进化流程 |
| 110 | +- ✅ [2026-04-03] 成功创建/修改了 2 个文件: workspace/evolve/evolve_report.md`, workspace/evolve/optimized_skill.md` | |
| 111 | +- ✅ [2026-04-03] 完成了 16 步工具调用的复杂任务 (149秒) | |
| 112 | +- ✅ [2026-04-03] 涉及技能训练/评分/进化流程 | ... | ... |
system/agents/evolver-youtube-crawler/todo.md
| ... | ... | @@ -14,3 +14,4 @@ |
| 14 | 14 | - [x] 基础技能注入完成 (evolving + mock-env + code-refactor) |
| 15 | 15 | | T-mnew8cq0 | 【自我进化任务】测试并优化你的三个核心技能(evolving、mock-env、code-refactor),确保综合 benchmark 达到 90 分以上。<br><br>## 执行步骤<br>1. **Code-Refactor 阶段**: 运行 code-refactor 技能分析 youtube_crawler.js,生成 refactor_report.md<br>2. **Mock-Env 阶段**: 运行 mock-env 技能搭建测试环境,生成 mock 数据<br>3. **Evolving 阶段**: 运行 evolving 技能执行双循环进化<br><br>## 测试目标<br>- 对 system/templates/youtube-crawler/code/youtube_crawler.js 进行代码质量分析<br>- 搭建 mock 测试环境覆盖 API/yt-dlp/异常场景<br>- 执行 benchmark 测试,目标总分 ≥ 90 分<br><br>## 输出要求<br>- workspace/evolver-youtube-crawler/refactor_report.md<br>- workspace/evolver-youtube-crawler/mock/<br>- workspace/evolver-youtube-crawler/evolution_log.md<br>- workspace/evolver-youtube-crawler/benchmark_result.json<br><br>完成后汇报最终得分和改进摘要。 | ⬚ 未开始 | innovator | P1 | 2026-03-31 17:31 | - | |
| 16 | 16 | | T-mnew9pn1 | 【Phase 3 EVOLVING】youtube-crawler 技能双循环进化训练<br><br>## 任务背景<br>- Phase 1 (Hunt): ✅ 已完成,knowhow.md 位于 system/templates/youtube-crawler/workspace/hunt/<br>- Phase 2 (Digest): ✅ 已完成,benchmark.md 和 train_dataset.json 位于 system/templates/youtube-crawler/workspace/digest/<br>- 目标:训练 youtube-crawler 技能达到 90+ 分<br><br>## 输入资料<br>1. benchmark.md: system/templates/youtube-crawler/workspace/digest/benchmark.md<br>2. train_dataset.json: system/templates/youtube-crawler/workspace/digest/train_dataset.json<br>3. test_dataset.json: system/templates/youtube-crawler/workspace/digest/test_dataset.json<br>4. knowhow.md: system/templates/youtube-crawler/workspace/hunt/knowhow.md<br>5. 目标 Agent 技能目录: system/agents/youtube-crawler/.claude/skills/<br><br>## 训练要求<br>1. 执行 Small Loop(技能迭代)最多 10 轮,直到 benchmark score >= 90<br>2. 每轮分析弱维度,针对性修改 Skill 定义<br>3. 使用 mock-env 搭建测试环境<br>4. 使用 code-refactor 优化代码质量<br><br>## 产出要求<br>- 输出目录: system/templates/youtube-crawler/workspace/evolve/<br>- skill_youtube_crawler.md (最终技能定义)<br>- evolution_log.json (进化记录)<br>- test_results.json (测试结果)<br><br>## 完成标准<br>- Benchmark score >= 90 分<br>- 技能文件部署到 system/agents/youtube-crawler/.claude/skills/<br><br>完成后请调用 report_task 向 innovator 汇报。 | ✅ 完成 | innovator | P1 | 2026-03-31 17:32 | - | |
| 17 | +| T-mnj3s7bi | 【FDE Phase 3: EVOLVE】对 YouTube Data API v3 爬取技能进行 RL 进化训练。<br><br>## 目标<br>优化 youtube-trending-crawler 技能,使其 benchmark 得分 ≥ 90 分。<br><br>## 输入文件<br>- Benchmark: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/digest/benchmark_v2.md<br>- Train: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/digest/train.json<br>- Test: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/digest/test.json<br>- Industry Avg: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/digest/industry_avg.json<br><br>## 目标 Agent<br>- company: test<br>- agent: claude-youtube-skills<br><br>## Evolve 任务要求<br>1. **读取现有技能**: 查看 test:claude-youtube-skills 的现有 SKILL.md<br>2. **分析 benchmark**: 理解评分维度和弱项<br>3. **Small Loop 训练**: 逐个修复弱维度:<br> - 错误处理健壮性 (当前 60分)<br> - 配额管理合理性 (当前 65分)<br> - 多地区多分类支持 (当前 68分)<br>4. **运行测试**: 使用 test.json 验证修复效果<br>5. **循环优化**: 直到 score ≥ 90<br><br>## 输出路径<br>必须写入: /Users/yibo/Documents/lemonAI/lemonboss/data/companies/test/agents/claude-youtube-skills/workspace/evolve/<br>- evolve_report.md - 训练报告 (包含每轮迭代的修改和得分)<br>- optimized_skill.md - 优化后的技能定义<br><br>## 验收标准<br>- 最终 benchmark 得分 ≥ 90<br>- 通过 test.json 的全部测试用例<br>- 产出优化的 SKILL.md | ✅ 完成 | innovator | P0 | 2026-04-03 16:13 | - | | ... | ... |
system/agents/hunter/todo.md
| ... | ... | @@ -45,3 +45,4 @@ |
| 45 | 45 | - T-mnext40u、T-mnexx9w8 (abc:trend-hunter 相关): ⚠️ 已取消 — abc 公司已于 2026-04-01 删除,目标 Agent 不存在。 |
| 46 | 46 | - T-mncue787 (hook-editor)、T-mncuebf1 (strategy-reflector): ⚠️ 已取消 — 目标 Agent 不存在。 |
| 47 | 47 | - T-mncz867y (idearrun-create)、T-mnexldk1 (lemonv:trend-hunter)、T-mnexpuii (lemonv:screenwriter): ⏸️ 暂停 — hunter 处于系统维护暂停状态,待恢复后处理。 |
| 48 | +| T-mnj3emdx | 对 YouTube Data API v3 爬取技能进行深度调研。<br><br>## 目标<br>训练一个能够通过 Google YouTube Data API v3 抓取最热最新视频列表并输出 JSON 的技能。<br><br>## 任务要求<br>1. 调研 YouTube Data API v3 的以下端点:<br> - 趋势视频 (trending videos)<br> - 热门视频 (most popular videos)<br> - 按国家/地区筛选的视频<br> - 搜索结果 (search)<br> - 视频详情 (videos)<br> - 频道详情 (channels)<br><br>2. 输出数据格式要求包含:<br> - 视频名称<br> - 发布博主名称<br> - 博主粉丝数<br> - 视频热度/热度趋势<br> - 播放量<br> - 视频简介<br> - 视频URL<br> - 其他相关元数据<br><br>3. 查找现有参考 skills 文档 (参考路径: .claude/skills/)<br><br>## 产出要求<br>输出到以下路径: /Users/yibo/Documents/lemonAI/lemonboss/system/agents/hunter/workspace/youtube-trending/<br>- knowhow_v2.md - 数据源清单和技术调研报告<br>- crawl_config.json - API 爬取配置<br>- seed_data.json - 首次采集的种子数据 (≥50条)<br><br>## 重要提醒<br>- 必须读取已有的旧版本 knowhow.md (如存在),合并并输出新版本 knowhow_v2.md<br>- 保留所有已有内容,追加新的调研发现 | ⬚ 未开始 | innovator | P0 | 2026-04-03 16:03 | - | | ... | ... |
system/agents/innovator/.claude/scheduled_tasks.json
| 1 | 1 | { |
| 2 | 2 | "tasks": [ |
| 3 | 3 | { |
| 4 | - "id": "5547b5b6", | |
| 5 | - "cron": "*/10 * * * *", | |
| 6 | - "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", | |
| 7 | - "createdAt": 1774543358106, | |
| 8 | - "lastFiredAt": 1774981073706, | |
| 9 | - "recurring": true | |
| 10 | - }, | |
| 11 | - { | |
| 12 | 4 | "id": "40f74b6a", |
| 13 | 5 | "cron": "*/10 * * * *", |
| 14 | 6 | "prompt": "读取 /mnt/lemonboss/system/agents/innovator/todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", |
| 15 | 7 | "createdAt": 1774979269375, |
| 16 | - "lastFiredAt": 1774981073706, | |
| 8 | + "lastFiredAt": 1775234477093, | |
| 17 | 9 | "recurring": true |
| 18 | 10 | }, |
| 19 | 11 | { |
| ... | ... | @@ -21,22 +13,23 @@ |
| 21 | 13 | "cron": "*/10 * * * *", |
| 22 | 14 | "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", |
| 23 | 15 | "createdAt": 1774980403987, |
| 24 | - "recurring": true, | |
| 25 | - "lastFiredAt": 1774981073706 | |
| 16 | + "lastFiredAt": 1775234593197, | |
| 17 | + "recurring": true | |
| 26 | 18 | }, |
| 27 | 19 | { |
| 28 | 20 | "id": "b1b5867b", |
| 29 | 21 | "cron": "*/10 * * * *", |
| 30 | 22 | "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", |
| 31 | 23 | "createdAt": 1774980489432, |
| 32 | - "recurring": true, | |
| 33 | - "lastFiredAt": 1774981073706 | |
| 24 | + "lastFiredAt": 1775234613218, | |
| 25 | + "recurring": true | |
| 34 | 26 | }, |
| 35 | 27 | { |
| 36 | 28 | "id": "a6cda320", |
| 37 | 29 | "cron": "*/10 * * * *", |
| 38 | 30 | "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", |
| 39 | 31 | "createdAt": 1774980660311, |
| 32 | + "lastFiredAt": 1775234603208, | |
| 40 | 33 | "recurring": true |
| 41 | 34 | }, |
| 42 | 35 | { |
| ... | ... | @@ -44,6 +37,7 @@ |
| 44 | 37 | "cron": "*/10 * * * *", |
| 45 | 38 | "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", |
| 46 | 39 | "createdAt": 1774981030401, |
| 40 | + "lastFiredAt": 1775234493105, | |
| 47 | 41 | "recurring": true |
| 48 | 42 | } |
| 49 | 43 | ] | ... | ... |
system/agents/innovator/agent.md
| ... | ... | @@ -24,11 +24,11 @@ |
| 24 | 24 | │ |
| 25 | 25 | ▼ Layer 1: HUNT (调研) |
| 26 | 26 | dispatch → Hunter: 深度调研 + 数据源发现 + 爬虫 + 首次爬取 |
| 27 | - 产出: knowhow 基础数据、crawl_config、种子数据集 | |
| 27 | + 产出: knowhow_vX.md 基础数据、crawl_config、种子数据集(若是重训,产出文件需递增版本后缀防覆盖) | |
| 28 | 28 | │ |
| 29 | 29 | ▼ Layer 2: DIGEST (消化) |
| 30 | - dispatch → Digester: 构建 knowhow.md + benchmark.md + 标注数据集 + 行业基准 | |
| 31 | - 产出: 结构化知识、评分标准、train/test 数据集、industry_avg_score | |
| 30 | + dispatch → Digester: 构建最新版 benchmark_vX.md + 标注数据集 + 行业基准 | |
| 31 | + 产出: 融合更新的结构化知识、新版评分标准、train/test 数据集、industry_avg_score | |
| 32 | 32 | │ |
| 33 | 33 | ▼ Layer 3: EVOLVING (进化) |
| 34 | 34 | dispatch → Evolver: 双循环训练直到 score ≥ industry_avg |
| ... | ... | @@ -67,6 +67,7 @@ |
| 67 | 67 | |
| 68 | 68 | ## ✅ 始终要做 |
| 69 | 69 | - 先检查 Hunter/Digester/Evolver 是否存在,不存在先通过 agent-creator 创建 |
| 70 | -- 每个 Phase 完成后验证产出质量 | |
| 70 | +- **切实验收产出质量**:当子 Agent 汇报某个 Phase 结束,你绝不能按目录有无文件就放行,**必须亲自调用读取工具**检视文件内容,并判定文件是否携带了新一版的后缀字样(如 `_v2`),达标后才能在 `plan.md` 打 `✅` | |
| 71 | +- 任何 **Retrain(重训)** 第一步:进 `plan.md` 将它的所有 Phase 全部强制重置为 `⬚`! | |
| 71 | 72 | - 训练完成后更新 skill_list 并向上级汇报最终分数 |
| 72 | 73 | - 参考 docs/ 目录中的模板文件 | ... | ... |
system/agents/innovator/soul.md
| ... | ... | @@ -18,4 +18,6 @@ |
| 18 | 18 | - **双循环** — Small Loop 优化技能,Large Loop 修正基准,永不停止学习 |
| 19 | 19 | |
| 20 | 20 | ## ⚠️ 绝对规则 |
| 21 | +- **重置复位法则(针对 Retrain)** — 一旦接收到“重新训练 (Retrain)”的指令,第一件事必定是将被重训对象的在 `plan.md` 中的旧状态全部打回未完成(例如改回 `⬚`)。决不允许再参考先前的 `✅` 状态!历史战绩必须清零,所有阶段从头踏实地跑一遍。 | |
| 22 | +- **杜绝形式主义的校验** — 每当 Hunt 或 Digest 阶段结束向你汇报时,**绝对禁止**只通过 `ls` 查验目录里是否有文件!你必须使用文件读取命令实际**查看生成的文件内容**并确认:(1)它满足本阶段要求的内容架构;(2)它的存盘名称拥有全新的迭代版本号(例如原来是 `.md` 或 `_v1.md`,本次重训必须新写了带有 `_v2.md` 后缀的全新文件)。只有满足这二者,才能将改阶段标记为 `✅`。 | |
| 21 | 23 | - **DEPLOY 不可跳过** — 训练达标后,必须将 SKILL.md 复制到 agents/{agent}/ 目录、更新 config.json status、更新 agent.md。如果跳过这步,训练成果等于白费。 | ... | ... |
system/agents/master/.claude/scheduled_tasks.json
| 1 | 1 | { |
| 2 | - "tasks": [] | |
| 2 | + "tasks": [ | |
| 3 | + { | |
| 4 | + "id": "fe1208ce", | |
| 5 | + "cron": "*/5 * * * *", | |
| 6 | + "prompt": "执行系统巡检:读取 plan.md 和 todo.md,检查所有任务状态。已完成的更新标记,卡住的分析原因后自主处理(重新分发或修复),未开始的按优先级立即分发。不要请示用户,直接行动。", | |
| 7 | + "createdAt": 1775231859266, | |
| 8 | + "recurring": true | |
| 9 | + }, | |
| 10 | + { | |
| 11 | + "id": "8bff9147", | |
| 12 | + "cron": "*/30 * * * *", | |
| 13 | + "prompt": "生成系统状态日报,统计所有 Agent 任务完成率和异常情况,写入 memory/daily/ 今日文件。", | |
| 14 | + "createdAt": 1775231859272, | |
| 15 | + "recurring": true | |
| 16 | + } | |
| 17 | + ] | |
| 3 | 18 | } | ... | ... |
web/src/views/CompanyDashboard.vue
| ... | ... | @@ -697,6 +697,44 @@ |
| 697 | 697 | </div> |
| 698 | 698 | </div> |
| 699 | 699 | |
| 700 | + <!-- P0 FIX: Train Modal Overlay --> | |
| 701 | + <div v-if="showTrainModal" class="hire-modal-overlay" @click.self="showTrainModal = false"> | |
| 702 | + <div class="hire-modal"> | |
| 703 | + <div class="hire-modal-header"> | |
| 704 | + <div class="hire-header-title"> | |
| 705 | + <span class="emoji">🎓</span> | |
| 706 | + <div> | |
| 707 | + <h3>发起 Innovator 重新训练</h3> | |
| 708 | + <p class="subtitle">针对 {{ targetTrainAgent }} 执行 FDE 训练流程</p> | |
| 709 | + </div> | |
| 710 | + </div> | |
| 711 | + <button class="btn-close-fancy" @click="showTrainModal = false">✕</button> | |
| 712 | + </div> | |
| 713 | + | |
| 714 | + <div class="hire-modal-body" style="padding: 24px; display: flex; flex-direction: column; gap: 16px;"> | |
| 715 | + <p style="font-size: 14px; color: var(--text-secondary); line-height: 1.5;"> | |
| 716 | + 系统级 Innovator 将基于下方指令和原数据,重新进行完整的 Hunt -> Digest -> Evolve 三循环步骤,并保留迭代版本。 | |
| 717 | + </p> | |
| 718 | + <textarea | |
| 719 | + v-model="trainInstructions" | |
| 720 | + placeholder="请输入想要强化的技能要求、需要增补的数据源说明等..." | |
| 721 | + style="width: 100%; height: 160px; padding: 12px; border: 1px solid var(--border-primary); border-radius: 8px; background: var(--bg-overlay); color: var(--text-primary); font-size: 14px; resize: vertical;" | |
| 722 | + ></textarea> | |
| 723 | + </div> | |
| 724 | + | |
| 725 | + <div class="hire-modal-footer"> | |
| 726 | + <div class="hire-selection-info"> | |
| 727 | + </div> | |
| 728 | + <div class="hire-actions"> | |
| 729 | + <button class="btn-fancy-cancel" @click="showTrainModal = false">取消</button> | |
| 730 | + <button class="btn-fancy-submit" :disabled="!trainInstructions.trim() || training" @click="submitRetrain"> | |
| 731 | + {{ training ? '⏳ 提交中...' : `🚀 开始重新训练` }} | |
| 732 | + </button> | |
| 733 | + </div> | |
| 734 | + </div> | |
| 735 | + </div> | |
| 736 | + </div> | |
| 737 | + | |
| 700 | 738 | <!-- ═══ Templates Panel ═══ --> |
| 701 | 739 | <div v-if="showTemplates" class="templates-panel"> |
| 702 | 740 | <div class="panel-header"> |
| ... | ... | @@ -751,6 +789,10 @@ const agentSkills = ref([]) |
| 751 | 789 | |
| 752 | 790 | const showHireModal = ref(false) |
| 753 | 791 | const hiring = ref(false) |
| 792 | +const showTrainModal = ref(false) | |
| 793 | +const targetTrainAgent = ref(null) | |
| 794 | +const trainInstructions = ref('') | |
| 795 | +const training = ref(false) | |
| 754 | 796 | const hireSearchQuery = ref('') |
| 755 | 797 | const hireFilterType = ref('') |
| 756 | 798 | const hireSortBy = ref('score') |
| ... | ... | @@ -1143,18 +1185,46 @@ async function toggleAgentSkills(agentId) { |
| 1143 | 1185 | expandedAgent.value = agentId |
| 1144 | 1186 | } |
| 1145 | 1187 | |
| 1146 | -async function triggerTrain(agentId) { | |
| 1188 | +function triggerTrain(agentId) { | |
| 1147 | 1189 | if (!selectedCompany.value) return |
| 1190 | + targetTrainAgent.value = agentId | |
| 1191 | + trainInstructions.value = '' | |
| 1192 | + showTrainModal.value = true | |
| 1193 | +} | |
| 1194 | + | |
| 1195 | +async function submitRetrain() { | |
| 1196 | + if (!selectedCompany.value || !targetTrainAgent.value) return | |
| 1197 | + | |
| 1198 | + const agentId = targetTrainAgent.value | |
| 1148 | 1199 | const namespacedId = `${selectedCompany.value.id}:${agentId}` |
| 1149 | - if (!confirm(`确定要对 ${agentId} 发起 Innovator 训练?这将触发 agent-creator 重新定义并由 Innovator 训练该 Agent。`)) return | |
| 1200 | + | |
| 1201 | + training.value = true | |
| 1150 | 1202 | try { |
| 1151 | - await axios.post(`/api/agent/${selectedCompany.value.id}:ceo/chat`, { | |
| 1152 | - message: `请安排 Innovator 对 ${namespacedId} 进行一次完整的技能训练/再训练。要求:1)评估当前技能缺口 2)使用 Innovator 进行 FDE 训练 3)训练完成后汇报结果`, | |
| 1153 | - conversationId: `train-${agentId}-${Date.now().toString(36)}`, | |
| 1203 | + const message = `请使用 FDE pipeline 对公司 ${selectedCompany.value.id} 的员工 ${agentId} (ID: ${namespacedId}) 进行**完整的重新训练 (Retrain)**。 | |
| 1204 | +用户的重新训练补充要求/提示词如下: | |
| 1205 | +""" | |
| 1206 | +${trainInstructions.value} | |
| 1207 | +""" | |
| 1208 | +核心要求: | |
| 1209 | +1. 你必须结合该 Agent 已有的训练数据,重新开启 Hunt -> Digest -> Evolve 的全新三步流程。不要偷懒跳过前面的阶段。 | |
| 1210 | +2. 在委派给 Hunter 和 Digester 时,明确告诉他们读取旧版本文件,并输出带有新版本后缀的合并文件(务必保留 hunt、digest 所有内容的版本号,例如输出为 knowhow_v2.md, benchmark_v2.md 等,不要直接覆盖现有文件)。 | |
| 1211 | +3. 使用更新后的标准调用 Evolver 进行训练。完成全部 FDE 后向上级汇报最终结果。` | |
| 1212 | + | |
| 1213 | + // 发送请求,但不阻塞 UI | |
| 1214 | + axios.post(`/api/agent/innovator/chat`, { | |
| 1215 | + message, | |
| 1216 | + conversationId: `train-${selectedCompany.value.id}-${agentId}-${Date.now().toString(36)}`, | |
| 1217 | + }).catch(e => { | |
| 1218 | + console.error('Retrain task error:', e) | |
| 1219 | + alert(`❌ 训练任务异常结束: ${e.message}`) | |
| 1154 | 1220 | }) |
| 1155 | - alert(`✅ 训练指令已发送给 CEO,CEO 将安排 Innovator 训练 ${agentId}`) | |
| 1221 | + | |
| 1222 | + alert(`✅ 训练指令已发送给 Innovator,将开始在后台进行自动评估和重训 ${agentId}\n您可以在 Agent 的实时状态面板中观察进展。`) | |
| 1223 | + showTrainModal.value = false | |
| 1156 | 1224 | } catch (e) { |
| 1157 | 1225 | alert(`❌ 发送训练指令失败: ${e.message}`) |
| 1226 | + } finally { | |
| 1227 | + training.value = false | |
| 1158 | 1228 | } |
| 1159 | 1229 | } |
| 1160 | 1230 | ... | ... |