Commit 5454b2cdaf6b1aa6c7f1550db3aadcecb09903bc

Authored by yibo
1 parent 2d4783a2

chore: update agents, server routes, start script, and views

server/routes/agent-chat.js
@@ -664,6 +664,13 @@ async function getOrCreateProtocol(agentId, convId) { @@ -664,6 +664,13 @@ async function getOrCreateProtocol(agentId, convId) {
664 } 664 }
665 665
666 const protocol = new ClaudeCliProtocol({ name: identity.name }, cliOptions); 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 await protocol.connect(null, agentDir); 674 await protocol.connect(null, agentDir);
668 await protocol.initialize(); 675 await protocol.initialize();
669 await protocol.newSession({ cwd: agentDir }); 676 await protocol.newSession({ cwd: agentDir });
server/routes/company.js
@@ -713,7 +713,7 @@ router.get('/:companyId/status', (req, res) => { @@ -713,7 +713,7 @@ router.get('/:companyId/status', (req, res) => {
713 const heartbeatService = require('../services/heartbeat-service'); 713 const heartbeatService = require('../services/heartbeat-service');
714 const path = require('path'); 714 const path = require('path');
715 const fs = require('fs'); 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 const uptimeMs = company.status === 'running' && company.startedAt 719 const uptimeMs = company.status === 'running' && company.startedAt
@@ -776,7 +776,7 @@ router.put('/:companyId/agents/:agentId/heartbeat', (req, res) => { @@ -776,7 +776,7 @@ router.put('/:companyId/agents/:agentId/heartbeat', (req, res) => {
776 const { intervalMinutes, enabled } = req.body; 776 const { intervalMinutes, enabled } = req.body;
777 const path = require('path'); 777 const path = require('path');
778 const fs = require('fs'); 778 const fs = require('fs');
779 - const DATA_DIR = path.resolve(__dirname, '../../data'); 779 + const DATA_DIR = path.resolve(__dirname, '../../data/companies');
780 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); 780 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json');
781 781
782 if (!fs.existsSync(configPath)) { 782 if (!fs.existsSync(configPath)) {
@@ -816,7 +816,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/start', (req, res) => { @@ -816,7 +816,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/start', (req, res) => {
816 try { 816 try {
817 const path = require('path'); 817 const path = require('path');
818 const fs = require('fs'); 818 const fs = require('fs');
819 - const DATA_DIR = path.resolve(__dirname, '../../data'); 819 + const DATA_DIR = path.resolve(__dirname, '../../data/companies');
820 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); 820 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json');
821 821
822 if (!fs.existsSync(configPath)) { 822 if (!fs.existsSync(configPath)) {
@@ -846,7 +846,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/stop', (req, res) => { @@ -846,7 +846,7 @@ router.post('/:companyId/agents/:agentId/heartbeat/stop', (req, res) => {
846 try { 846 try {
847 const path = require('path'); 847 const path = require('path');
848 const fs = require('fs'); 848 const fs = require('fs');
849 - const DATA_DIR = path.resolve(__dirname, '../../data'); 849 + const DATA_DIR = path.resolve(__dirname, '../../data/companies');
850 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json'); 850 const configPath = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'config.json');
851 851
852 if (!fs.existsSync(configPath)) { 852 if (!fs.existsSync(configPath)) {
@@ -883,7 +883,7 @@ router.get('/:companyId/agents/:agentId/skills', (req, res) => { @@ -883,7 +883,7 @@ router.get('/:companyId/agents/:agentId/skills', (req, res) => {
883 try { 883 try {
884 const path = require('path'); 884 const path = require('path');
885 const fs = require('fs'); 885 const fs = require('fs');
886 - const DATA_DIR = path.resolve(__dirname, '../../data'); 886 + const DATA_DIR = path.resolve(__dirname, '../../data/companies');
887 const skillsDir = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'skills'); 887 const skillsDir = path.join(DATA_DIR, req.params.companyId, 'agents', req.params.agentId, 'skills');
888 888
889 if (!fs.existsSync(skillsDir)) { 889 if (!fs.existsSync(skillsDir)) {
start.sh
@@ -5,6 +5,10 @@ @@ -5,6 +5,10 @@
5 5
6 set -e 6 set -e
7 7
  8 +# Load NVM to ensure node is available in non-interactive shell
  9 +export NVM_DIR="$HOME/.nvm"
  10 +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  11 +
8 echo "🧬 LemonBoss 启动中..." 12 echo "🧬 LemonBoss 启动中..."
9 echo "═══════════════════════════════════" 13 echo "═══════════════════════════════════"
10 14
system/agents/digester-youtube-crawler/todo.md
@@ -12,3 +12,4 @@ @@ -12,3 +12,4 @@
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 | - | 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 | 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 | - | 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 | 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 | - | 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,9 +104,9 @@ try {
104 104
105 105
106 ## 经验教训 (自动沉淀) 106 ## 经验教训 (自动沉淀)
107 -  
108 -> 以下经验由系统自动从历史对话中提取沉淀,帮助你避免重复犯错。  
109 -  
110 - ✅ [2026-03-31] 成功创建/修改了 3 个文件: workspace/evolve/skill_youtube_crawler.md`, workspace/evolve/evolution_log.json`, workspace/evolve/test_results.json` 107 - ✅ [2026-03-31] 成功创建/修改了 3 个文件: workspace/evolve/skill_youtube_crawler.md`, workspace/evolve/evolution_log.json`, workspace/evolve/test_results.json`
111 - ✅ [2026-03-31] 完成了 36 步工具调用的复杂任务 (931秒) 108 - ✅ [2026-03-31] 完成了 36 步工具调用的复杂任务 (931秒)
112 - ✅ [2026-03-31] 涉及技能训练/评分/进化流程 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,3 +14,4 @@
14 - [x] 基础技能注入完成 (evolving + mock-env + code-refactor) 14 - [x] 基础技能注入完成 (evolving + mock-env + code-refactor)
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 | - | 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 | 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 | - | 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,3 +45,4 @@
45 - T-mnext40u、T-mnexx9w8 (abc:trend-hunter 相关): ⚠️ 已取消 — abc 公司已于 2026-04-01 删除,目标 Agent 不存在。 45 - T-mnext40u、T-mnexx9w8 (abc:trend-hunter 相关): ⚠️ 已取消 — abc 公司已于 2026-04-01 删除,目标 Agent 不存在。
46 - T-mncue787 (hook-editor)、T-mncuebf1 (strategy-reflector): ⚠️ 已取消 — 目标 Agent 不存在。 46 - T-mncue787 (hook-editor)、T-mncuebf1 (strategy-reflector): ⚠️ 已取消 — 目标 Agent 不存在。
47 - T-mncz867y (idearrun-create)、T-mnexldk1 (lemonv:trend-hunter)、T-mnexpuii (lemonv:screenwriter): ⏸️ 暂停 — hunter 处于系统维护暂停状态,待恢复后处理。 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 "tasks": [ 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 "id": "40f74b6a", 4 "id": "40f74b6a",
13 "cron": "*/10 * * * *", 5 "cron": "*/10 * * * *",
14 "prompt": "读取 /mnt/lemonboss/system/agents/innovator/todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", 6 "prompt": "读取 /mnt/lemonboss/system/agents/innovator/todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。",
15 "createdAt": 1774979269375, 7 "createdAt": 1774979269375,
16 - "lastFiredAt": 1774981073706, 8 + "lastFiredAt": 1775234477093,
17 "recurring": true 9 "recurring": true
18 }, 10 },
19 { 11 {
@@ -21,22 +13,23 @@ @@ -21,22 +13,23 @@
21 "cron": "*/10 * * * *", 13 "cron": "*/10 * * * *",
22 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", 14 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。",
23 "createdAt": 1774980403987, 15 "createdAt": 1774980403987,
24 - "recurring": true,  
25 - "lastFiredAt": 1774981073706 16 + "lastFiredAt": 1775234593197,
  17 + "recurring": true
26 }, 18 },
27 { 19 {
28 "id": "b1b5867b", 20 "id": "b1b5867b",
29 "cron": "*/10 * * * *", 21 "cron": "*/10 * * * *",
30 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", 22 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。",
31 "createdAt": 1774980489432, 23 "createdAt": 1774980489432,
32 - "recurring": true,  
33 - "lastFiredAt": 1774981073706 24 + "lastFiredAt": 1775234613218,
  25 + "recurring": true
34 }, 26 },
35 { 27 {
36 "id": "a6cda320", 28 "id": "a6cda320",
37 "cron": "*/10 * * * *", 29 "cron": "*/10 * * * *",
38 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", 30 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。",
39 "createdAt": 1774980660311, 31 "createdAt": 1774980660311,
  32 + "lastFiredAt": 1775234603208,
40 "recurring": true 33 "recurring": true
41 }, 34 },
42 { 35 {
@@ -44,6 +37,7 @@ @@ -44,6 +37,7 @@
44 "cron": "*/10 * * * *", 37 "cron": "*/10 * * * *",
45 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。", 38 "prompt": "读取 todo.md,检查是否有未完成的任务。如果有,按优先级执行。完成后更新状态。",
46 "createdAt": 1774981030401, 39 "createdAt": 1774981030401,
  40 + "lastFiredAt": 1775234493105,
47 "recurring": true 41 "recurring": true
48 } 42 }
49 ] 43 ]
system/agents/innovator/agent.md
@@ -24,11 +24,11 @@ @@ -24,11 +24,11 @@
24 │ 24 │
25 ▼ Layer 1: HUNT (调研) 25 ▼ Layer 1: HUNT (调研)
26 dispatch → Hunter: 深度调研 + 数据源发现 + 爬虫 + 首次爬取 26 dispatch → Hunter: 深度调研 + 数据源发现 + 爬虫 + 首次爬取
27 - 产出: knowhow 基础数据、crawl_config、种子数据集 27 + 产出: knowhow_vX.md 基础数据、crawl_config、种子数据集(若是重训,产出文件需递增版本后缀防覆盖)
28 │ 28 │
29 ▼ Layer 2: DIGEST (消化) 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 ▼ Layer 3: EVOLVING (进化) 33 ▼ Layer 3: EVOLVING (进化)
34 dispatch → Evolver: 双循环训练直到 score ≥ industry_avg 34 dispatch → Evolver: 双循环训练直到 score ≥ industry_avg
@@ -67,6 +67,7 @@ @@ -67,6 +67,7 @@
67 67
68 ## ✅ 始终要做 68 ## ✅ 始终要做
69 - 先检查 Hunter/Digester/Evolver 是否存在,不存在先通过 agent-creator 创建 69 - 先检查 Hunter/Digester/Evolver 是否存在,不存在先通过 agent-creator 创建
70 -- 每个 Phase 完成后验证产出质量 70 +- **切实验收产出质量**:当子 Agent 汇报某个 Phase 结束,你绝不能按目录有无文件就放行,**必须亲自调用读取工具**检视文件内容,并判定文件是否携带了新一版的后缀字样(如 `_v2`),达标后才能在 `plan.md` 打 `✅`
  71 +- 任何 **Retrain(重训)** 第一步:进 `plan.md` 将它的所有 Phase 全部强制重置为 `⬚`!
71 - 训练完成后更新 skill_list 并向上级汇报最终分数 72 - 训练完成后更新 skill_list 并向上级汇报最终分数
72 - 参考 docs/ 目录中的模板文件 73 - 参考 docs/ 目录中的模板文件
system/agents/innovator/soul.md
@@ -18,4 +18,6 @@ @@ -18,4 +18,6 @@
18 - **双循环** — Small Loop 优化技能,Large Loop 修正基准,永不停止学习 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 - **DEPLOY 不可跳过** — 训练达标后,必须将 SKILL.md 复制到 agents/{agent}/ 目录、更新 config.json status、更新 agent.md。如果跳过这步,训练成果等于白费。 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,6 +697,44 @@
697 </div> 697 </div>
698 </div> 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 <!-- ═══ Templates Panel ═══ --> 738 <!-- ═══ Templates Panel ═══ -->
701 <div v-if="showTemplates" class="templates-panel"> 739 <div v-if="showTemplates" class="templates-panel">
702 <div class="panel-header"> 740 <div class="panel-header">
@@ -751,6 +789,10 @@ const agentSkills = ref([]) @@ -751,6 +789,10 @@ const agentSkills = ref([])
751 789
752 const showHireModal = ref(false) 790 const showHireModal = ref(false)
753 const hiring = ref(false) 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 const hireSearchQuery = ref('') 796 const hireSearchQuery = ref('')
755 const hireFilterType = ref('') 797 const hireFilterType = ref('')
756 const hireSortBy = ref('score') 798 const hireSortBy = ref('score')
@@ -1143,18 +1185,46 @@ async function toggleAgentSkills(agentId) { @@ -1143,18 +1185,46 @@ async function toggleAgentSkills(agentId) {
1143 expandedAgent.value = agentId 1185 expandedAgent.value = agentId
1144 } 1186 }
1145 1187
1146 -async function triggerTrain(agentId) { 1188 +function triggerTrain(agentId) {
1147 if (!selectedCompany.value) return 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 const namespacedId = `${selectedCompany.value.id}:${agentId}` 1199 const namespacedId = `${selectedCompany.value.id}:${agentId}`
1149 - if (!confirm(`确定要对 ${agentId} 发起 Innovator 训练?这将触发 agent-creator 重新定义并由 Innovator 训练该 Agent。`)) return 1200 +
  1201 + training.value = true
1150 try { 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 } catch (e) { 1224 } catch (e) {
1157 alert(`❌ 发送训练指令失败: ${e.message}`) 1225 alert(`❌ 发送训练指令失败: ${e.message}`)
  1226 + } finally {
  1227 + training.value = false
1158 } 1228 }
1159 } 1229 }
1160 1230