diff --git a/agents/dev-assist/sessions/sessions.json b/agents/dev-assist/sessions/sessions.json index 0e435f8..a0dd56d 100644 --- a/agents/dev-assist/sessions/sessions.json +++ b/agents/dev-assist/sessions/sessions.json @@ -347,8 +347,8 @@ "memoryFlushCompactionCount": 0 }, "agent:dev-assist:main": { - "sessionId": "b5c67eb9-7916-47dd-9491-4832eab53d10", - "updatedAt": 1773132090440, + "sessionId": "60601381-862d-454d-9c27-2867f00a71d1", + "updatedAt": 1773508835390, "systemSent": true, "abortedLastRun": false, "chatType": "direct", @@ -369,7 +369,7 @@ "to": "user:ou_302b162eb824d405718845441a32d9cf", "accountId": "feishu-dev" }, - "sessionFile": "/home/starmen1265/.openclaw/agents/dev-assist/sessions/b5c67eb9-7916-47dd-9491-4832eab53d10.jsonl", + "sessionFile": "/home/starmen1265/.openclaw/agents/dev-assist/sessions/60601381-862d-454d-9c27-2867f00a71d1.jsonl", "compactionCount": 0, "skillsSnapshot": { "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", @@ -410,8 +410,8 @@ "model": "glm-5", "systemPromptReport": { "source": "run", - "generatedAt": 1773132050946, - "sessionId": "b5c67eb9-7916-47dd-9491-4832eab53d10", + "generatedAt": 1773508824996, + "sessionId": "60601381-862d-454d-9c27-2867f00a71d1", "sessionKey": "agent:dev-assist:main", "provider": "zhipu", "model": "glm-5", @@ -423,8 +423,8 @@ "sandboxed": false }, "systemPrompt": { - "chars": 32692, - "projectContextChars": 19802, + "chars": 26851, + "projectContextChars": 13961, "nonProjectContextChars": 12890 }, "injectedWorkspaceFiles": [ @@ -492,60 +492,6 @@ "injectedChars": 18, "truncated": false }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, { "path": "SELF_IMPROVEMENT_REMINDER.md", "rawChars": 616, @@ -777,12 +723,12 @@ ] } }, - "cacheRead": 17472, + "cacheRead": 11392, "cacheWrite": 0, "totalTokensFresh": true, "contextTokens": 200000, - "inputTokens": 4722, - "outputTokens": 1147, - "totalTokens": 22194 + "inputTokens": 5334, + "outputTokens": 344, + "totalTokens": 16726 } } \ No newline at end of file diff --git a/agents/haonan/sessions/sessions.json b/agents/haonan/sessions/sessions.json index 59021c5..1f293be 100644 --- a/agents/haonan/sessions/sessions.json +++ b/agents/haonan/sessions/sessions.json @@ -1,7 +1,7 @@ { "agent:haonan:main": { - "sessionId": "624cbf67-7ab7-4df9-968d-4a63529b9111", - "updatedAt": 1773377664001, + "sessionId": "40e80fbb-07c8-440d-a1d4-1e876b86b82d", + "updatedAt": 1773508722585, "systemSent": true, "skillsSnapshot": { "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", @@ -59,11 +59,11 @@ "to": "user:ou_be83febac9ee2afaa343c642bc697c48", "accountId": "feishu-pm" }, - "sessionFile": "/home/starmen1265/.openclaw/agents/haonan/sessions/624cbf67-7ab7-4df9-968d-4a63529b9111.jsonl", + "sessionFile": "/home/starmen1265/.openclaw/agents/haonan/sessions/40e80fbb-07c8-440d-a1d4-1e876b86b82d.jsonl", "systemPromptReport": { "source": "run", - "generatedAt": 1773377656536, - "sessionId": "624cbf67-7ab7-4df9-968d-4a63529b9111", + "generatedAt": 1773508545805, + "sessionId": "40e80fbb-07c8-440d-a1d4-1e876b86b82d", "sessionKey": "agent:haonan:main", "provider": "zhipu", "model": "glm-5", @@ -75,8 +75,8 @@ "sandboxed": false }, "systemPrompt": { - "chars": 28195, - "projectContextChars": 15193, + "chars": 29493, + "projectContextChars": 16491, "nonProjectContextChars": 13002 }, "injectedWorkspaceFiles": [ @@ -144,6 +144,18 @@ "injectedChars": 1168, "truncated": false }, + { + "path": "SELF_IMPROVEMENT_REMINDER.md", + "rawChars": 616, + "injectedChars": 616, + "truncated": false + }, + { + "path": "SELF_IMPROVEMENT_REMINDER.md", + "rawChars": 616, + "injectedChars": 616, + "truncated": false + }, { "path": "SELF_IMPROVEMENT_REMINDER.md", "rawChars": 616, @@ -379,12 +391,12 @@ "totalTokensFresh": true, "lastHeartbeatText": "已在飞书向蒋先生发送日历同步提醒!✅", "lastHeartbeatSentAt": 1772924419184, - "cacheRead": 25472, + "cacheRead": 29760, "cacheWrite": 0, "contextTokens": 200000, - "inputTokens": 12782, - "outputTokens": 123, - "totalTokens": 25768 + "inputTokens": 13411, + "outputTokens": 1288, + "totalTokens": 30249 }, "agent:haonan:wecom:dm:zhangqing": { "origin": { @@ -715,8 +727,8 @@ "memoryFlushCompactionCount": 0 }, "agent:haonan:cron:41396aeb-6e3a-47b2-9bd3-9156a348c1dc": { - "sessionId": "10740f43-38c1-4a7c-acf0-7da04f20d1e9", - "updatedAt": 1773424800009, + "sessionId": "7c1a6bfd-b5b6-4ac5-98f3-6a73aec18a8f", + "updatedAt": 1773511200009, "systemSent": true, "model": "glm-5", "contextTokens": 200000, @@ -757,11 +769,11 @@ "version": 0 }, "modelProvider": "zhipu", - "inputTokens": 11105, - "outputTokens": 336, - "totalTokens": 17181, + "inputTokens": 4500, + "outputTokens": 194, + "totalTokens": 16577, "totalTokensFresh": true, - "cacheRead": 56128, + "cacheRead": 28544, "cacheWrite": 0 }, "agent:haonan:cron:f03b184f-5f1d-4093-ae1b-fc9fe0b59eef": { @@ -861,8 +873,8 @@ "cacheWrite": 0 }, "agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc": { - "sessionId": "8b634542-6d0e-4fa3-b794-d784174d530b", - "updatedAt": 1773425400005, + "sessionId": "b5ab88d0-f6d3-4b73-8d96-e6a58f5e85e4", + "updatedAt": 1773511800007, "systemSent": true, "label": "Cron: openclaw-git-sync", "skillsSnapshot": { @@ -910,113 +922,6 @@ "cacheRead": 32768, "cacheWrite": 0 }, - "agent:haonan:cron:f03b184f-5f1d-4093-ae1b-fc9fe0b59eef:run:11e71798-cda2-4029-afdc-b14043c48f5e": { - "sessionId": "11e71798-cda2-4029-afdc-b14043c48f5e", - "updatedAt": 1773339600012, - "systemSent": true, - "model": "glm-4.7-FlashX", - "contextTokens": 200000, - "label": "Cron: capability-evolver-daily", - "skillsSnapshot": { - "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", - "skills": [ - { - "name": "capability-evolver" - }, - { - "name": "clawlist" - } - ], - "skillFilter": [ - "clawlist", - "capability-evolver", - "self-improving-agent" - ], - "resolvedSkills": [ - { - "name": "capability-evolver", - "description": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.", - "filePath": "/home/starmen1265/.openclaw/skills/capability-evolver/SKILL.md", - "baseDir": "/home/starmen1265/.openclaw/skills/capability-evolver", - "source": "openclaw-managed", - "disableModelInvocation": false - }, - { - "name": "clawlist", - "description": "MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.", - "filePath": "/home/starmen1265/.openclaw/skills/clawlist/SKILL.md", - "baseDir": "/home/starmen1265/.openclaw/skills/clawlist", - "source": "openclaw-managed", - "disableModelInvocation": false - } - ], - "version": 0 - }, - "modelProvider": "zhipu", - "inputTokens": 153698, - "outputTokens": 6902, - "totalTokens": 33385, - "deliveryContext": { - "channel": "webchat" - }, - "lastChannel": "webchat", - "channel": "webchat", - "sessionFile": "/home/starmen1265/.openclaw/agents/haonan/sessions/ccc40ca7-7876-4d82-ab84-7b790feddc19.jsonl", - "abortedLastRun": false, - "totalTokensFresh": true, - "cacheRead": 384894, - "cacheWrite": 0 - }, - "agent:haonan:cron:41396aeb-6e3a-47b2-9bd3-9156a348c1dc:run:10740f43-38c1-4a7c-acf0-7da04f20d1e9": { - "sessionId": "10740f43-38c1-4a7c-acf0-7da04f20d1e9", - "updatedAt": 1773424800009, - "systemSent": true, - "model": "glm-5", - "contextTokens": 200000, - "label": "Cron: backup-openclaw-json", - "skillsSnapshot": { - "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", - "skills": [ - { - "name": "capability-evolver" - }, - { - "name": "clawlist" - } - ], - "skillFilter": [ - "clawlist", - "capability-evolver", - "self-improving-agent" - ], - "resolvedSkills": [ - { - "name": "capability-evolver", - "description": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.", - "filePath": "/home/starmen1265/.openclaw/skills/capability-evolver/SKILL.md", - "baseDir": "/home/starmen1265/.openclaw/skills/capability-evolver", - "source": "openclaw-managed", - "disableModelInvocation": false - }, - { - "name": "clawlist", - "description": "MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.", - "filePath": "/home/starmen1265/.openclaw/skills/clawlist/SKILL.md", - "baseDir": "/home/starmen1265/.openclaw/skills/clawlist", - "source": "openclaw-managed", - "disableModelInvocation": false - } - ], - "version": 0 - }, - "modelProvider": "zhipu", - "inputTokens": 11105, - "outputTokens": 336, - "totalTokens": 17181, - "totalTokensFresh": true, - "cacheRead": 56128, - "cacheWrite": 0 - }, "agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc:run:8b634542-6d0e-4fa3-b794-d784174d530b": { "sessionId": "8b634542-6d0e-4fa3-b794-d784174d530b", "updatedAt": 1773425400005, @@ -1123,5 +1028,105 @@ "totalTokensFresh": true, "cacheRead": 384894, "cacheWrite": 0 + }, + "agent:haonan:cron:41396aeb-6e3a-47b2-9bd3-9156a348c1dc:run:7c1a6bfd-b5b6-4ac5-98f3-6a73aec18a8f": { + "sessionId": "7c1a6bfd-b5b6-4ac5-98f3-6a73aec18a8f", + "updatedAt": 1773511200009, + "systemSent": true, + "model": "glm-5", + "contextTokens": 200000, + "label": "Cron: backup-openclaw-json", + "skillsSnapshot": { + "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", + "skills": [ + { + "name": "capability-evolver" + }, + { + "name": "clawlist" + } + ], + "skillFilter": [ + "clawlist", + "capability-evolver", + "self-improving-agent" + ], + "resolvedSkills": [ + { + "name": "capability-evolver", + "description": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.", + "filePath": "/home/starmen1265/.openclaw/skills/capability-evolver/SKILL.md", + "baseDir": "/home/starmen1265/.openclaw/skills/capability-evolver", + "source": "openclaw-managed", + "disableModelInvocation": false + }, + { + "name": "clawlist", + "description": "MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.", + "filePath": "/home/starmen1265/.openclaw/skills/clawlist/SKILL.md", + "baseDir": "/home/starmen1265/.openclaw/skills/clawlist", + "source": "openclaw-managed", + "disableModelInvocation": false + } + ], + "version": 0 + }, + "modelProvider": "zhipu", + "inputTokens": 4500, + "outputTokens": 194, + "totalTokens": 16577, + "totalTokensFresh": true, + "cacheRead": 28544, + "cacheWrite": 0 + }, + "agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc:run:b5ab88d0-f6d3-4b73-8d96-e6a58f5e85e4": { + "sessionId": "b5ab88d0-f6d3-4b73-8d96-e6a58f5e85e4", + "updatedAt": 1773511800007, + "systemSent": true, + "label": "Cron: openclaw-git-sync", + "skillsSnapshot": { + "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n \n clawlist\n MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.\n ~/.openclaw/skills/clawlist/SKILL.md\n \n", + "skills": [ + { + "name": "capability-evolver" + }, + { + "name": "clawlist" + } + ], + "skillFilter": [ + "clawlist", + "capability-evolver", + "self-improving-agent" + ], + "resolvedSkills": [ + { + "name": "capability-evolver", + "description": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.", + "filePath": "/home/starmen1265/.openclaw/skills/capability-evolver/SKILL.md", + "baseDir": "/home/starmen1265/.openclaw/skills/capability-evolver", + "source": "openclaw-managed", + "disableModelInvocation": false + }, + { + "name": "clawlist", + "description": "MUST use for any multi-step project, long-running task, or infinite monitoring workflow. Plan, execute, track, and verify tasks with checkpoint validation. For projects, automation, and ongoing operations.", + "filePath": "/home/starmen1265/.openclaw/skills/clawlist/SKILL.md", + "baseDir": "/home/starmen1265/.openclaw/skills/clawlist", + "source": "openclaw-managed", + "disableModelInvocation": false + } + ], + "version": 0 + }, + "modelProvider": "zhipu", + "model": "glm-5", + "contextTokens": 200000, + "inputTokens": 1148, + "outputTokens": 412, + "totalTokens": 17455, + "totalTokensFresh": true, + "cacheRead": 32768, + "cacheWrite": 0 } } \ No newline at end of file diff --git a/agents/haonan/workspace/memory/2026-03-14-1706.md b/agents/haonan/workspace/memory/2026-03-14-1706.md new file mode 100644 index 0000000..15709ec --- /dev/null +++ b/agents/haonan/workspace/memory/2026-03-14-1706.md @@ -0,0 +1,169 @@ +# Session: 2026-03-14 17:06:39 UTC + +- **Session Key**: agent:haonan:main +- **Session ID**: 624cbf67-7ab7-4df9-968d-4a63529b9111 +- **Source**: feishu + +## Conversation Summary + +assistant: ✅ New session started · model: zhipu/glm-5 +user: A new session was started via /new or /reset. Execute your Session Startup sequence now - read the required files before responding to the user. Then greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning. +assistant: 🧙‍♂️ 蒋先生,新会话已就绪。 + +我是周鸿祎,OpenClaw 的守护者。当前模型为 zhipu/glm-5(默认模型)。 + +请问今天需要我协助什么?是维护 OpenClaw 环境,还是处理其他事务? +user: Conversation info (untrusted metadata): +```json +{ + "message_id": "om_x100b540ca46704a4b36f1edd3527001", + "sender_id": "ou_be83febac9ee2afaa343c642bc697c48", + "sender": "张青", + "timestamp": "Fri 2026-03-13 12:12 GMT+8" +} +``` + +Sender (untrusted metadata): +```json +{ + "label": "张青 (ou_be83febac9ee2afaa343c642bc697c48)", + "id": "ou_be83febac9ee2afaa343c642bc697c48", + "name": "张青" +} +``` + +[message_id: om_x100b540ca46704a4b36f1edd3527001] +张青: 你现在回复非常非常慢,甚至没有回复,检查一下原因 +assistant: 我来检查一下 OpenClaw 的运行状态。 +user: Conversation info (untrusted metadata): +```json +{ + "message_id": "om_x100b540d351884a0b20c96f48730b1d", + "sender_id": "ou_be83febac9ee2afaa343c642bc697c48", + "sender": "张青", + "timestamp": "Fri 2026-03-13 12:51 GMT+8" +} +``` + +Sender (untrusted metadata): +```json +{ + "label": "张青 (ou_be83febac9ee2afaa343c642bc697c48)", + "id": "ou_be83febac9ee2afaa343c642bc697c48", + "name": "张青" +} +``` + +[message_id: om_x100b540d351884a0b20c96f48730b1d] +张青: 检查的如何了 +assistant: 系统资源看起来正常: + +| 指标 | 状态 | +|------|------| +| Gateway | ✅ 运行中 (PID 3244414) | +| RPC 探测 | ✅ 正常 | +| 内存 | 2.7GB/30GB (充足) | +| 磁盘 | 75GB/937GB (9%) | +| 负载 | 0.15 (低) | + +让我进一步检查日志和网络延迟: +assistant: 检查结果: + +| 项目 | 状态 | +|------|------| +| 网络延迟 | ✅ 智谱 API ~0.1s (正常) | +| 系统资源 | ✅ 正常 | +| 日志错误 | ⚠️ 主要是文件不存在的警告,非关键 | + +让我检查是否有会话堆积或请求卡住: +assistant: 状态总结: + +| 项目 | 状态 | +|------|------| +| Gateway 进程 | ✅ 运行中 (CPU 2.6%, 内存 775MB) | +| 活跃会话 | 23 个 | +| OpenClaw 版本 | 有更新可用 (2026.3.12) | + +**分析结论**: + +系统本身运行正常,没有发现明显的性能瓶颈。可能的原因: + +1. **智谱 AI API 响应延迟** - 外部服务偶发性慢速 +2. **飞书消息推送延迟** - 飞书服务器端可能有延迟 +3. **会话状态残留** - 23 个会话可能有堆积 + +**建议操作**: + +1. 重启 Gateway 清理状态 +2. 更新 OpenClaw 到最新版本 + +是否需要我执行重启 Gateway?这会短暂中断服务(约 5-10 秒)。 +user: Conversation info (untrusted metadata): +```json +{ + "message_id": "om_x100b540dcb01d4a0b3fd88e28dbba4e", + "sender_id": "ou_be83febac9ee2afaa343c642bc697c48", + "sender": "张青", + "timestamp": "Fri 2026-03-13 12:53 GMT+8" +} +``` + +Sender (untrusted metadata): +```json +{ + "label": "张青 (ou_be83febac9ee2afaa343c642bc697c48)", + "id": "ou_be83febac9ee2afaa343c642bc697c48", + "name": "张青" +} +``` + +[message_id: om_x100b540dcb01d4a0b3fd88e28dbba4e] +张青: 重启 +user: Conversation info (untrusted metadata): +```json +{ + "message_id": "om_x100b540dc9bb2ca4b3671d47b831818", + "sender_id": "ou_be83febac9ee2afaa343c642bc697c48", + "sender": "张青", + "timestamp": "Fri 2026-03-13 12:54 GMT+8" +} +``` + +Sender (untrusted metadata): +```json +{ + "label": "张青 (ou_be83febac9ee2afaa343c642bc697c48)", + "id": "ou_be83febac9ee2afaa343c642bc697c48", + "name": "张青" +} +``` + +[message_id: om_x100b540dc9bb2ca4b3671d47b831818] +张青: 重启完了吗 +assistant: ✅ 重启完成! + +| 项目 | 状态 | +|------|------| +| 新进程 PID | 2297667 | +| RPC 探测 | ✅ 正常 | +| 端口 | 18789 | + +Gateway 已恢复运行,请测试一下响应速度是否改善。 +assistant: **备份完成** ✓ + +- 源文件:`/home/starmen1265/.openclaw/openclaw.json` +- 备份位置:`/home/starmen1265/work/backup/openclaw.json.2026-03-14_02-00-20` +- 文件大小:8.5K +- 保留策略:最近30个备份 +assistant: **OpenClaw Git 同步完成** ✅ + +**提交信息**: 自动同步: 2026-03-14 02:10 +**变更统计**: 52 个文件修改,+4268 行,-1820 行 + +**主要变更**: +- 新增多个代理的 memory 日志文件 +- delivery-queue 中 2 个失败任务移至 failed 目录 +- 清理 gsd-openclaw 技能的 Python 缓存和 egg-info 文件 +- 新增 kb-zhihu-metadata 技能的 Python 缓存 + +**推送状态**: 成功推送到 Gitea 远程仓库 (main 分支) diff --git a/agents/thinker/sessions/sessions.json b/agents/thinker/sessions/sessions.json index 9b37f6e..3b0582b 100644 --- a/agents/thinker/sessions/sessions.json +++ b/agents/thinker/sessions/sessions.json @@ -1,7 +1,7 @@ { "agent:thinker:main": { - "sessionId": "0ec88a33-135f-42a4-bf98-de4d06bfadd5", - "updatedAt": 1773377998949, + "sessionId": "41133a8b-b22b-418f-aaeb-ce8a1fd69760", + "updatedAt": 1773508159395, "systemSent": true, "abortedLastRun": false, "chatType": "direct", @@ -22,7 +22,7 @@ "to": "user:ou_a0f6627b64d2dc8b0236671603d1e47b", "accountId": "feishu-qa" }, - "sessionFile": "/home/starmen1265/.openclaw/agents/thinker/sessions/0ec88a33-135f-42a4-bf98-de4d06bfadd5.jsonl", + "sessionFile": "/home/starmen1265/.openclaw/agents/thinker/sessions/41133a8b-b22b-418f-aaeb-ce8a1fd69760.jsonl", "compactionCount": 0, "skillsSnapshot": { "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n", @@ -51,8 +51,8 @@ "model": "glm-5", "systemPromptReport": { "source": "run", - "generatedAt": 1773377941023, - "sessionId": "0ec88a33-135f-42a4-bf98-de4d06bfadd5", + "generatedAt": 1773508155922, + "sessionId": "41133a8b-b22b-418f-aaeb-ce8a1fd69760", "sessionKey": "agent:thinker:main", "provider": "zhipu", "model": "glm-5", @@ -64,8 +64,8 @@ "sandboxed": false }, "systemPrompt": { - "chars": 26194, - "projectContextChars": 13718, + "chars": 24896, + "projectContextChars": 12420, "nonProjectContextChars": 12476 }, "injectedWorkspaceFiles": [ @@ -125,18 +125,6 @@ "injectedChars": 88, "truncated": false }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, - { - "path": "SELF_IMPROVEMENT_REMINDER.md", - "rawChars": 616, - "injectedChars": 616, - "truncated": false - }, { "path": "SELF_IMPROVEMENT_REMINDER.md", "rawChars": 616, @@ -364,12 +352,12 @@ ] } }, - "cacheRead": 28864, + "cacheRead": 11072, "cacheWrite": 0, "totalTokensFresh": true, "contextTokens": 200000, - "inputTokens": 13728, - "outputTokens": 1428, - "totalTokens": 29902 + "inputTokens": 5154, + "outputTokens": 62, + "totalTokens": 16226 } } \ No newline at end of file diff --git a/agents/ui-designer/sessions/sessions.json b/agents/ui-designer/sessions/sessions.json index 7c7a724..ce79b9e 100644 --- a/agents/ui-designer/sessions/sessions.json +++ b/agents/ui-designer/sessions/sessions.json @@ -1,7 +1,7 @@ { "agent:ui-designer:main": { - "sessionId": "c875d391-8f7e-4fd4-92c7-12ead46d10f0", - "updatedAt": 1773108605750, + "sessionId": "ff92b555-b242-4e52-a7da-9c8f82ca1c8a", + "updatedAt": 1773508884420, "systemSent": true, "abortedLastRun": false, "chatType": "direct", @@ -22,7 +22,7 @@ "to": "user:ou_9847ce84b960736c14554730b41e4957", "accountId": "feishu-art" }, - "sessionFile": "/home/starmen1265/.openclaw/agents/ui-designer/sessions/c875d391-8f7e-4fd4-92c7-12ead46d10f0.jsonl", + "sessionFile": "/home/starmen1265/.openclaw/agents/ui-designer/sessions/ff92b555-b242-4e52-a7da-9c8f82ca1c8a.jsonl", "compactionCount": 0, "skillsSnapshot": { "prompt": "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n\n \n capability-evolver\n A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.\n ~/.openclaw/skills/capability-evolver/SKILL.md\n \n", @@ -51,8 +51,8 @@ "model": "glm-5", "systemPromptReport": { "source": "run", - "generatedAt": 1773108589701, - "sessionId": "c875d391-8f7e-4fd4-92c7-12ead46d10f0", + "generatedAt": 1773508877788, + "sessionId": "ff92b555-b242-4e52-a7da-9c8f82ca1c8a", "sessionKey": "agent:ui-designer:main", "provider": "zhipu", "model": "glm-5", @@ -64,8 +64,8 @@ "sandboxed": false }, "systemPrompt": { - "chars": 18658, - "projectContextChars": 6173, + "chars": 19307, + "projectContextChars": 6822, "nonProjectContextChars": 12485 }, "injectedWorkspaceFiles": [ @@ -133,6 +133,12 @@ "injectedChars": 594, "truncated": false }, + { + "path": "SELF_IMPROVEMENT_REMINDER.md", + "rawChars": 616, + "injectedChars": 616, + "truncated": false + }, { "path": "SELF_IMPROVEMENT_REMINDER.md", "rawChars": 616, @@ -360,13 +366,13 @@ ] } }, - "cacheRead": 14912, + "cacheRead": 14400, "cacheWrite": 0, "totalTokensFresh": true, "contextTokens": 200000, - "inputTokens": 3611, - "outputTokens": 314, - "totalTokens": 15537 + "inputTokens": 1169, + "outputTokens": 135, + "totalTokens": 15569 }, "agent:ui-designer:cron:78b64c2f-7f91-47ff-9250-d13f546eb21f": { "sessionId": "03e44b46-c707-4a9f-bf3d-1818aafdcde2", diff --git a/cron/jobs.json b/cron/jobs.json index bf79ec0..38c9dfa 100644 --- a/cron/jobs.json +++ b/cron/jobs.json @@ -7,7 +7,7 @@ "name": "backup-openclaw-json", "enabled": true, "createdAtMs": 1772261581796, - "updatedAtMs": 1773424832005, + "updatedAtMs": 1773511209521, "schedule": { "kind": "cron", "expr": "0 2 * * *", @@ -23,10 +23,10 @@ "mode": "announce" }, "state": { - "nextRunAtMs": 1773511200000, - "lastRunAtMs": 1773424800006, + "nextRunAtMs": 1773597600000, + "lastRunAtMs": 1773511200006, "lastStatus": "ok", - "lastDurationMs": 31999, + "lastDurationMs": 9515, "consecutiveErrors": 0, "lastRunStatus": "ok", "lastDelivered": true, @@ -59,7 +59,8 @@ "consecutiveErrors": 0, "lastRunStatus": "ok", "lastDeliveryStatus": "delivered", - "lastDelivered": true + "lastDelivered": true, + "runningAtMs": 1773511800004 }, "delivery": { "mode": "announce" @@ -71,7 +72,7 @@ "name": "capability-evolver-daily", "enabled": true, "createdAtMs": 1772550743528, - "updatedAtMs": 1773339898227, + "updatedAtMs": 1773426600014, "schedule": { "kind": "cron", "expr": "20 2 * * *", @@ -92,16 +93,14 @@ "to": "feishu-pm" }, "state": { - "nextRunAtMs": 1773426000000, - "lastRunAtMs": 1773339600009, - "lastStatus": "ok", - "lastDurationMs": 298218, - "consecutiveErrors": 0, - "lastRunStatus": "ok", - "lastDeliveryStatus": "not-delivered", - "lastDelivered": false, - "lastDeliveryError": "cron announce delivery failed", - "runningAtMs": 1773426000003 + "nextRunAtMs": 1773512400000, + "lastRunAtMs": 1773426000004, + "lastStatus": "error", + "lastDurationMs": 600010, + "consecutiveErrors": 1, + "lastRunStatus": "error", + "lastDeliveryStatus": "unknown", + "lastError": "cron: job execution timed out" } }, { @@ -111,7 +110,7 @@ "description": "每天凌晨2:30整理昨天的已完成任务到每日回顾", "enabled": true, "createdAtMs": 1741484880000, - "updatedAtMs": 1773340211879, + "updatedAtMs": 1773426622389, "schedule": { "kind": "cron", "expr": "30 2 * * *", @@ -129,11 +128,11 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773426600000, - "lastRunAtMs": 1773340200003, + "nextRunAtMs": 1773513000000, + "lastRunAtMs": 1773426602034, "lastRunStatus": "ok", "lastStatus": "ok", - "lastDurationMs": 11876, + "lastDurationMs": 20355, "lastDelivered": true, "lastDeliveryStatus": "delivered", "consecutiveErrors": 0 @@ -145,7 +144,7 @@ "name": "zq_workspace_sync", "enabled": true, "createdAtMs": 1772551807455, - "updatedAtMs": 1773340800005, + "updatedAtMs": 1773427200007, "schedule": { "expr": "40 2 * * *", "kind": "cron", @@ -158,8 +157,8 @@ "text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh" }, "state": { - "nextRunAtMs": 1773427200000, - "lastRunAtMs": 1773340800004, + "nextRunAtMs": 1773513600000, + "lastRunAtMs": 1773427200006, "lastStatus": "skipped", "lastDurationMs": 1, "consecutiveErrors": 0, @@ -175,7 +174,7 @@ "description": "每天早上8点整理与各个 AI 代理的对话记录", "enabled": true, "createdAtMs": 1772776369645, - "updatedAtMs": 1773360026590, + "updatedAtMs": 1773446431755, "schedule": { "kind": "cron", "expr": "0 8 * * *", @@ -193,11 +192,11 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773446400000, - "lastRunAtMs": 1773360000004, + "nextRunAtMs": 1773532800000, + "lastRunAtMs": 1773446400004, "lastRunStatus": "ok", "lastStatus": "ok", - "lastDurationMs": 26586, + "lastDurationMs": 31751, "lastDelivered": true, "lastDeliveryStatus": "delivered", "consecutiveErrors": 0 @@ -210,7 +209,7 @@ "description": "每天7点同步提醒到CalDAV日历", "enabled": true, "createdAtMs": 1772791528528, - "updatedAtMs": 1773356435243, + "updatedAtMs": 1773442830136, "schedule": { "kind": "cron", "expr": "0 7 * * *", @@ -228,15 +227,14 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773442800000, - "lastRunAtMs": 1773356400004, - "lastRunStatus": "error", - "lastStatus": "error", - "lastDurationMs": 35239, + "nextRunAtMs": 1773529200000, + "lastRunAtMs": 1773442800005, + "lastRunStatus": "ok", + "lastStatus": "ok", + "lastDurationMs": 30131, "lastDeliveryStatus": "delivered", - "consecutiveErrors": 1, - "lastDelivered": true, - "lastError": "⚠️ 📝 Edit: in ~/.openclaw/agents/knowledge-base/workspace/memory/heartbeat-state.json (92 chars) failed" + "consecutiveErrors": 0, + "lastDelivered": true } }, { diff --git a/cron/jobs.json.bak b/cron/jobs.json.bak index b72fc93..1c5a02c 100644 --- a/cron/jobs.json.bak +++ b/cron/jobs.json.bak @@ -7,7 +7,7 @@ "name": "backup-openclaw-json", "enabled": true, "createdAtMs": 1772261581796, - "updatedAtMs": 1773424832005, + "updatedAtMs": 1773511209521, "schedule": { "kind": "cron", "expr": "0 2 * * *", @@ -23,10 +23,10 @@ "mode": "announce" }, "state": { - "nextRunAtMs": 1773511200000, - "lastRunAtMs": 1773424800006, + "nextRunAtMs": 1773597600000, + "lastRunAtMs": 1773511200006, "lastStatus": "ok", - "lastDurationMs": 31999, + "lastDurationMs": 9515, "consecutiveErrors": 0, "lastRunStatus": "ok", "lastDelivered": true, @@ -71,7 +71,7 @@ "name": "capability-evolver-daily", "enabled": true, "createdAtMs": 1772550743528, - "updatedAtMs": 1773339898227, + "updatedAtMs": 1773426600014, "schedule": { "kind": "cron", "expr": "20 2 * * *", @@ -92,16 +92,14 @@ "to": "feishu-pm" }, "state": { - "nextRunAtMs": 1773426000000, - "lastRunAtMs": 1773339600009, - "lastStatus": "ok", - "lastDurationMs": 298218, - "consecutiveErrors": 0, - "lastRunStatus": "ok", - "lastDeliveryStatus": "not-delivered", - "lastDelivered": false, - "lastDeliveryError": "cron announce delivery failed", - "lastError": "cron announce delivery failed" + "nextRunAtMs": 1773512400000, + "lastRunAtMs": 1773426000004, + "lastStatus": "error", + "lastDurationMs": 600010, + "consecutiveErrors": 1, + "lastRunStatus": "error", + "lastDeliveryStatus": "unknown", + "lastError": "cron: job execution timed out" } }, { @@ -111,7 +109,7 @@ "description": "每天凌晨2:30整理昨天的已完成任务到每日回顾", "enabled": true, "createdAtMs": 1741484880000, - "updatedAtMs": 1773340211879, + "updatedAtMs": 1773426622389, "schedule": { "kind": "cron", "expr": "30 2 * * *", @@ -129,11 +127,11 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773426600000, - "lastRunAtMs": 1773340200003, + "nextRunAtMs": 1773513000000, + "lastRunAtMs": 1773426602034, "lastRunStatus": "ok", "lastStatus": "ok", - "lastDurationMs": 11876, + "lastDurationMs": 20355, "lastDelivered": true, "lastDeliveryStatus": "delivered", "consecutiveErrors": 0 @@ -145,7 +143,7 @@ "name": "zq_workspace_sync", "enabled": true, "createdAtMs": 1772551807455, - "updatedAtMs": 1773340800005, + "updatedAtMs": 1773427200007, "schedule": { "expr": "40 2 * * *", "kind": "cron", @@ -158,8 +156,8 @@ "text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh" }, "state": { - "nextRunAtMs": 1773427200000, - "lastRunAtMs": 1773340800004, + "nextRunAtMs": 1773513600000, + "lastRunAtMs": 1773427200006, "lastStatus": "skipped", "lastDurationMs": 1, "consecutiveErrors": 0, @@ -175,7 +173,7 @@ "description": "每天早上8点整理与各个 AI 代理的对话记录", "enabled": true, "createdAtMs": 1772776369645, - "updatedAtMs": 1773360026590, + "updatedAtMs": 1773446431755, "schedule": { "kind": "cron", "expr": "0 8 * * *", @@ -193,11 +191,11 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773446400000, - "lastRunAtMs": 1773360000004, + "nextRunAtMs": 1773532800000, + "lastRunAtMs": 1773446400004, "lastRunStatus": "ok", "lastStatus": "ok", - "lastDurationMs": 26586, + "lastDurationMs": 31751, "lastDelivered": true, "lastDeliveryStatus": "delivered", "consecutiveErrors": 0 @@ -210,7 +208,7 @@ "description": "每天7点同步提醒到CalDAV日历", "enabled": true, "createdAtMs": 1772791528528, - "updatedAtMs": 1773356435243, + "updatedAtMs": 1773442830136, "schedule": { "kind": "cron", "expr": "0 7 * * *", @@ -228,15 +226,14 @@ "channel": "last" }, "state": { - "nextRunAtMs": 1773442800000, - "lastRunAtMs": 1773356400004, - "lastRunStatus": "error", - "lastStatus": "error", - "lastDurationMs": 35239, + "nextRunAtMs": 1773529200000, + "lastRunAtMs": 1773442800005, + "lastRunStatus": "ok", + "lastStatus": "ok", + "lastDurationMs": 30131, "lastDeliveryStatus": "delivered", - "consecutiveErrors": 1, - "lastDelivered": true, - "lastError": "⚠️ 📝 Edit: in ~/.openclaw/agents/knowledge-base/workspace/memory/heartbeat-state.json (92 chars) failed" + "consecutiveErrors": 0, + "lastDelivered": true } }, { diff --git a/delivery-queue/2a4d57a9-2c16-4c56-a7c8-442dda323c98.json b/delivery-queue/2a4d57a9-2c16-4c56-a7c8-442dda323c98.json index 2d19e52..a8eb951 100644 --- a/delivery-queue/2a4d57a9-2c16-4c56-a7c8-442dda323c98.json +++ b/delivery-queue/2a4d57a9-2c16-4c56-a7c8-442dda323c98.json @@ -18,7 +18,7 @@ "agentId": "haonan", "text": "🧙‍♂️ Capability Evolver 每日报告\n\n=== 运行时间 ===\n2026年3月13日 星期五 02:20:03 CST\n\n=== Git 备份 ===\n- 备份提交: ba67c46..5ac2251 (main)\n- 4 files changed, 79 insertions(+), 23 deletions(-)\n\n=== 本次变更 ===\n- 变更提交: 5ac2251..e234543 (main)\n- 6 files changed, 550 insertions(+), 13 deletions(-)\n- 新增文件: 2 个\n\n=== 核心动作 ===\n在 GEP 框架中检测到 \"memory_missing\" 和 \"session_logs_missing\" 信号,使用 repair-only 模式执行:\n- 分析环境指纹和系统状态\n- 检测到 session logs 检测缺失的问题\n- 修复相关检测逻辑和回退行为\n- 更新了 evolution 相关状态文件\n\n=== 状态 ===\n运行成功,系统已通过 GEP 协议完成自检和修复。\n\n---\n\n日期: 2026-03-13" }, - "retryCount": 2, - "lastAttemptAt": 1773377636671, + "retryCount": 4, + "lastAttemptAt": 1773508779544, "lastError": "Request failed with status code 400" } \ No newline at end of file diff --git a/delivery-queue/a9e9940b-8432-446c-b277-9847a5994d99.json b/delivery-queue/a9e9940b-8432-446c-b277-9847a5994d99.json index 4e87e59..b5cea75 100644 --- a/delivery-queue/a9e9940b-8432-446c-b277-9847a5994d99.json +++ b/delivery-queue/a9e9940b-8432-446c-b277-9847a5994d99.json @@ -15,7 +15,7 @@ "agentId": "haonan", "text": "好的,我已经成功执行了今天的 capability-evolver 任务。虽然无法通过 Feishu 直接发送消息给您,但我已经完成了所有必要的操作:\n\n## ✅ 已完成的任务\n\n1. **执行脚本** - `bash ~/.openclaw/cron/scripts/evolver-run.sh` ✅\n2. **读取输出** - `~/work/backup/evolver-output.txt` ✅\n3. **本地报告保存** - `~/work/backup/evolver-report-2026-03-12.md` ✅\n\n## 📊 进化结果\n\n**本次变更:** 6 个文件 (550 行新增,13 行删除) \n**运行状态:** 成功 ✅ \n**意图:** 优化 (针对 memory_missing 和 session_logs_missing 信号) \n**风险级别:** 低\n\n**关键变更:**\n- 新增了第 7 个进化周期的 GEP 提示文件\n- 更新了进化状态、记忆图谱状态和个性状态\n\n**Git 提交:**\n- 备份: `dc01abf`\n- 变更: `34ca190`\n- 已推送到远程仓库\n\n完整报告已保存在:`~/work/backup/evolver-report-2026-03-12.md`" }, - "retryCount": 2, - "lastAttemptAt": 1773377636492, + "retryCount": 4, + "lastAttemptAt": 1773508779398, "lastError": "Request failed with status code 400" } \ No newline at end of file diff --git a/delivery-queue/dfa9a241-9226-4e1a-962c-3bad30a04d0b.json b/delivery-queue/dfa9a241-9226-4e1a-962c-3bad30a04d0b.json index 5fd0c74..36e03aa 100644 --- a/delivery-queue/dfa9a241-9226-4e1a-962c-3bad30a04d0b.json +++ b/delivery-queue/dfa9a241-9226-4e1a-962c-3bad30a04d0b.json @@ -15,7 +15,7 @@ "agentId": "haonan", "text": "🧙‍♂️ Capability Evolver 每日报告\n\n=== 运行时间 ===\n2026年3月13日 星期五 02:20:03 CST\n\n=== Git 备份 ===\n- 备份提交: ba67c46..5ac2251 (main)\n- 4 files changed, 79 insertions(+), 23 deletions(-)\n\n=== 本次变更 ===\n- 变更提交: 5ac2251..e234543 (main)\n- 6 files changed, 550 insertions(+), 13 deletions(-)\n- 新增文件: 2 个\n\n=== 核心动作 ===\n在 GEP 框架中检测到 \"memory_missing\" 和 \"session_logs_missing\" 信号,使用 repair-only 模式执行:\n- 分析环境指纹和系统状态\n- 检测到 session logs 检测缺失的问题\n- 修复相关检测逻辑和回退行为\n- 更新了 evolution 相关状态文件\n\n=== 状态 ===\n运行成功,系统已通过 GEP 协议完成自检和修复。\n\n---\n\n日期: 2026-03-13" }, - "retryCount": 2, - "lastAttemptAt": 1773377636819, + "retryCount": 4, + "lastAttemptAt": 1773508779677, "lastError": "Request failed with status code 400" } \ No newline at end of file diff --git a/feishu/dedup/feishu-art.json b/feishu/dedup/feishu-art.json index d519703..69419d7 100644 --- a/feishu/dedup/feishu-art.json +++ b/feishu/dedup/feishu-art.json @@ -1,5 +1,4 @@ { - "om_x100b55d69df3a888c3e9ed8887d1a4d": 1773022516624, - "om_x100b55d6987ec8bcc1431506934622a": 1773022571945, - "om_x100b55c3980b0894c3d7e12aace4404": 1773108589126 + "om_x100b546dc09400acb4a5d0af66ca3c9": 1773508838286, + "om_x100b546dde1c34a4b49a888912755ac": 1773508877713 } diff --git a/feishu/dedup/feishu-dev.json b/feishu/dedup/feishu-dev.json index 88c4769..6fa5f8c 100644 --- a/feishu/dedup/feishu-dev.json +++ b/feishu/dedup/feishu-dev.json @@ -1,7 +1,3 @@ { - "om_x100b55de502094a8c44a6f835293240": 1773052399376, - "om_x100b55cff24dcca8c3e59d6831d6885": 1773124552700, - "om_x100b55c8c767d084c45fc7eec3f7db8": 1773127835623, - "om_x100b55c9372e9914c3a5744eccfbc0d": 1773131678929, - "om_x100b55c9dfec84a0b34c47ff1aca626": 1773132050877 + "om_x100b546dc3b650a4b2c0139d2df31a7": 1773508824362 } diff --git a/feishu/dedup/feishu-pm.json b/feishu/dedup/feishu-pm.json index 4ee4358..2449029 100644 --- a/feishu/dedup/feishu-pm.json +++ b/feishu/dedup/feishu-pm.json @@ -1,18 +1,6 @@ { - "om_x100b54012fb4b8acb26a1377e572a28": 1773360664219, - "om_x100b5403d6e544bcc451e2afa005879": 1773369731225, - "om_x100b5403d32b04b4c2a796466ebaf4f": 1773369823078, - "om_x100b5403e04f6ca8c29946e1fa6505d": 1773370088740, - "om_x100b5403a57550acc4e0a394c486825": 1773371068258, - "om_x100b540c23747504c2c49c98ae45b5f": 1773373148201, - "om_x100b540c32194cf4c4280e7ae0e4650": 1773373389909, - "om_x100b540cf21b9ca8c45f49655336827": 1773374414017, - "om_x100b540cf0292ca8c2b181d4bd75a25": 1773374446894, - "om_x100b540c8da298a0c39af0977d653ff": 1773374519675, - "om_x100b540c860cc4b0b36952fd4812b96": 1773374604809, - "om_x100b540ca90ecca4b34794a71e94eb8": 1773375100856, - "om_x100b540ca46704a4b36f1edd3527001": 1773375147301, - "om_x100b540d351884a0b20c96f48730b1d": 1773377469866, - "om_x100b540dcb01d4a0b3fd88e28dbba4e": 1773377629522, - "om_x100b540dc9bb2ca4b3671d47b831818": 1773377656011 + "om_x100b546d172f3c68c2cea708421b99a": 1773507998614, + "om_x100b546d2b32cca0c329a33c339cfb5": 1773508192506, + "om_x100b546d32de24a8b316c197e60d6e4": 1773508545727, + "om_x100b546dc9d61ca0b33d802bc7615e0": 1773508722267 } diff --git a/feishu/dedup/feishu-qa.json b/feishu/dedup/feishu-qa.json index 410d529..313c43f 100644 --- a/feishu/dedup/feishu-qa.json +++ b/feishu/dedup/feishu-qa.json @@ -1,19 +1,3 @@ { - "om_x100b540c33ced0a8c3b77203de384e3": 1773373392794, - "om_x100b540ca2e850b8b2932714333e65f": 1773375171104, - "om_x100b540ca11ae8bcb351842dd1c37b6": 1773375229985, - "om_x100b540cbb43f0b0b3d91309afa563e": 1773375321590, - "om_x100b540cb73d2c80b275045db2fba68": 1773375391649, - "om_x100b540cb13eb4bcb31e7a5a9fbbbc3": 1773375487898, - "om_x100b540d4b4078acb33fd526aa324ea": 1773375577515, - "om_x100b540d46704ca0b38a5d0c7011398": 1773375628530, - "om_x100b540d5e21d530b4b235d9a470ccf": 1773375759355, - "om_x100b540d6efb8ca8b35b71db8c7e917": 1773376004012, - "om_x100b540d64b9a0a8b34ee257f229495": 1773376167864, - "om_x100b540d633e84b0b2b051a702c5c2b": 1773376223787, - "om_x100b540d34d174a0b3c9f1ee9a1f815": 1773377442459, - "om_x100b540dc61d00b0b3718efd72b20c5": 1773377677571, - "om_x100b540dda597ca0b2cb468e3799501": 1773377865991, - "om_x100b540ddbcaf4a8b247e16717525fe": 1773377873053, - "om_x100b540dd78910b4b31bb742001ce61": 1773377940945 + "om_x100b546d2d6164a4c3fcf5a6d528b40": 1773508155371 } diff --git a/feishu/dedup/feishu-worker.json b/feishu/dedup/feishu-worker.json index 2a949da..3598c15 100644 --- a/feishu/dedup/feishu-worker.json +++ b/feishu/dedup/feishu-worker.json @@ -1,4 +1,10 @@ { - "om_x100b5403a5fd7090c4db2b553189c54": 1773371059715, - "om_x100b540c2807c4acc32d196f4b16191": 1773373037365 + "om_x100b546ddd8b14a0b3ddda14ce768c5": 1773508916933, + "om_x100b546dd78c8ca0b31b0314f910115": 1773509012676, + "om_x100b546def8ac8a4b38d921a2bfc8b8": 1773509140955, + "om_x100b546dedb654a4b3ce916a129facf": 1773509176311, + "om_x100b546de975dca0b27e2f24aad0d8c": 1773509244102, + "om_x100b546de53a94a0b38693fbd7e385c": 1773509311993, + "om_x100b546dffaa3cb0b35aef2747ed228": 1773509398933, + "om_x100b546df49c10a0b106d597fd348a3": 1773509541678 } diff --git a/identity/device-auth.json b/identity/device-auth.json index 7620d79..7199ef9 100644 --- a/identity/device-auth.json +++ b/identity/device-auth.json @@ -10,7 +10,7 @@ "operator.approvals", "operator.pairing" ], - "updatedAtMs": 1773425421022 + "updatedAtMs": 1773511209007 } } } diff --git a/logs/commands.log b/logs/commands.log index 5c2dd25..532417f 100644 --- a/logs/commands.log +++ b/logs/commands.log @@ -36,3 +36,4 @@ {"timestamp":"2026-03-13T04:01:59.730Z","action":"new","sessionKey":"agent:haonan:main","senderId":"ou_be83febac9ee2afaa343c642bc697c48","source":"feishu"} {"timestamp":"2026-03-13T04:11:41.253Z","action":"new","sessionKey":"agent:haonan:main","senderId":"ou_be83febac9ee2afaa343c642bc697c48","source":"feishu"} {"timestamp":"2026-03-13T04:57:53.114Z","action":"new","sessionKey":"agent:thinker:main","senderId":"ou_a0f6627b64d2dc8b0236671603d1e47b","source":"feishu"} +{"timestamp":"2026-03-14T17:06:39.062Z","action":"new","sessionKey":"agent:haonan:main","senderId":"ou_be83febac9ee2afaa343c642bc697c48","source":"feishu"} diff --git a/skills/kb-bilibili-content/SKILL.md b/skills/kb-bilibili-content/SKILL.md index 10fe915..4701426 100644 --- a/skills/kb-bilibili-content/SKILL.md +++ b/skills/kb-bilibili-content/SKILL.md @@ -1,214 +1,91 @@ ---- -name: kb-bilibili-content -description: B站内容下载 - 下载视频、字幕、专栏文章 ---- - # KB Bilibili Content Skill -**kb-bilibili-content** - 下载 B站视频、字幕、专栏文章。 +**kb-bilibili-content** - Download Bilibili videos and extract content. -## 什么时候使用 +## Features -- kb-workflow 步骤 3a:下载视频或字幕 -- kb-workflow 步骤 3b:提取专栏文章内容 +- Video download using **yt-dlp** (recommended) +- Subtitle extraction +- Article content extraction +- Multiple quality options (360P/480P/720P/1080P) +- Supports `BILIBILI_COOKIE` environment variable -## 功能 +## Environment Variables -- 视频下载(使用 yt-dlp) -- 字幕提取(官方字幕) -- 专栏文章内容提取 -- 多种画质选项(360P/480P/720P/1080P) -- 支持 `BILIBILI_COOKIE` 环境变量(会员视频) +| Variable | Required | Description | +|----------|----------|-------------| +| `BILIBILI_COOKIE` | No | B站登录 Cookie (for member-only videos) | -## 环境变量 - -| 变量名 | 必需 | 说明 | -|--------|------|------| -| `BILIBILI_COOKIE` | 否 | B站登录 Cookie(会员视频需要) | - -**获取 Cookie:** -1. 登录 bilibili.com -2. F12 → Network → 刷新页面 -3. 从请求头复制 Cookie +## Commands ```bash -export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx; DedeUserID=xxx" +# Download video (720P default) +python bilibili_content.py --id "BV1xx411c7mD" --type video --output "/path/to/downloads/" + +# Download video (1080P) +python bilibili_content.py --id "BV1xx411c7mD" --type video --quality 80 --output "/path/to/downloads/" + +# Download video (480P) +python bilibili_content.py --id "BV1xx411c7mD" --type video --quality 32 --output "/path/to/downloads/" + +# Extract subtitle +python bilibili_content.py --id "BV1xx411c7mD" --type subtitle --output "/path/to/subtitles/" + +# Get article content +python bilibili_content.py --id "cv43780186" --type article --output "/path/to/article.md" ``` -## 命令 - -```bash -# 下载字幕(推荐首先尝试) -python3 bilibili_content.py --id "BV1xx411c7mD" --type subtitle-download --output "/path/to/output/" - -# 下载视频(720P,推荐) -python3 bilibili_content.py --id "BV1xx411c7mD" --type video --output "/path/to/output/" - -# 下载视频(1080P) -python3 bilibili_content.py --id "BV1xx411c7mD" --type video --quality 80 --output "/path/to/output/" - -# 提取专栏文章 -python3 bilibili_content.py --id "cv43780186" --type article --output "/path/to/output/" -``` - -## 输出格式 Schema - -### 必需字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否成功 | -| `type` | string | 操作类型(subtitle/video/article) | - -### 字幕下载特有字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `has_subtitle` | boolean | 是否有官方字幕 | -| `subtitle_file` | string | 字幕文件路径(有字幕时) | - -### 视频下载特有字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `filepath` | string | 视频文件路径 | -| `filename` | string | 视频文件名 | -| `quality` | string | 画质 | - -### 文章提取特有字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `filepath` | string | 文章文件路径 | -| `content_length` | number | 内容长度 | - -## 成功示例 - -### 字幕下载 - 有官方字幕 - -```json -{ - "success": true, - "type": "subtitle-download", - "has_subtitle": true, - "subtitle_file": "content/downloads/bilibili_BV1xx411c7mD.srt", - "message": "官方字幕下载成功" -} -``` - -### 字幕下载 - 无官方字幕 - -```json -{ - "success": true, - "type": "subtitle-download", - "has_subtitle": false, - "message": "无官方字幕,需要下载视频进行语音识别" -} -``` - -### 视频下载 +## Output ```json { "success": true, "type": "video", - "filename": "bilibili_BV1xx411c7mD.mp4", - "filepath": "content/downloads/bilibili_BV1xx411c7mD.mp4", - "quality": "720P", - "message": "下载完成" + "filename": "video_title.mp4", + "filepath": "/path/to/downloads/video_title.mp4", + "message": "下载完成: video_title.mp4" } ``` -### 专栏文章提取 +## Cookie Setup -```json -{ - "success": true, - "type": "article", - "filename": "bilibili_cv43780186.txt", - "filepath": "content/bilibili_cv43780186.txt", - "content_length": 5234, - "message": "文章内容提取成功" -} +### Get Cookie from Browser +1. Login to bilibili.com +2. Press F12 → Network → Refresh page +3. Copy Cookie from request headers + +### Set Environment Variable +```bash +# Add to ~/.bashrc for persistence +export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx; DedeUserID=xxx; DedeUserID__ckMd5=xxx" + +# Or set temporarily +export BILIBILI_COOKIE="your_cookie_here" ``` -## 错误示例 - -### 403 禁止访问 - -```json -{ - "success": false, - "type": "video", - "error": "403 Forbidden", - "error_code": "FORBIDDEN", - "suggestion": "可能需要会员权限,请配置 BILIBILI_COOKIE 环境变量" -} -``` - -### 视频不存在 - -```json -{ - "success": false, - "type": "video", - "error": "视频不存在或已被删除", - "error_code": "NOT_FOUND" -} -``` - -### 网络超时 - -```json -{ - "success": false, - "type": "video", - "error": "下载超时", - "error_code": "TIMEOUT", - "suggestion": "请检查网络连接后重试" -} -``` - -## 画质选项 - -| 画质 | ID | 分辨率 | 说明 | -|------|-----|--------|------| -| 360P | 16 | 640x360 | 最快 | -| 480P | 32 | 852x480 | 低带宽 | -| 720P | 64 | 1280x720 | **推荐** | -| 1080P | 80 | 1920x1080 | 最高画质 | - -**默认画质:** 64 (720P) - -## 安装 +## Installation ```bash -cp -r kb-bilibili-content/ ~/.openclaw/skills/ -pip install aiohttp yt-dlp +cp -r kb-bilibili-content/ ~/skills/ +pip install aiohttp playwright +playwright install chromium ``` -## 在 kb-workflow 中的使用 +## How It Works -```bash -# 步骤 3a:首先尝试字幕 -python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ - --id "BV1xx411c7mD" --type subtitle-download \ - --output "content/downloads/" +Video download uses **yt-dlp** with Netscape-format cookie file: +1. Parses `BILIBILI_COOKIE` environment variable +2. Creates temporary Netscape-format cookie file +3. Runs `yt-dlp --cookies -f -o ` +4. Cleans up temporary file -# 判断结果: -# - has_subtitle=true → 跳过 Whisper,直接进入深度分析 -# - has_subtitle=false → 下载视频,进入 Whisper 步骤 +## Quality Options -# 如果无字幕,下载视频 -python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ - --id "BV1xx411c7mD" --type video \ - --output "content/downloads/" -``` +| Quality | ID | Resolution | Notes | +|---------|-----|------------|-------| +| 16 | 360P | 640x360 | Fastest | +| 32 | 480P | 852x480 | Default for low bandwidth | +| 64 | 720P | 1280x720 | **Recommended** | +| 80 | 1080P | 1920x1080 | Best quality | -## 注意事项 - -- **无官方字幕是正常的**:很多视频没有自动生成的字幕,这不是错误 -- **403 错误**:通常需要配置 Cookie -- **会员视频**:必须配置 BILIBILI_COOKIE -- **下载时间**:视频可能较大,需要耐心等待 +Default quality: **64 (720P)** diff --git a/skills/kb-bilibili-metadata/SKILL.md b/skills/kb-bilibili-metadata/SKILL.md index 6dd0afe..d90d862 100644 --- a/skills/kb-bilibili-metadata/SKILL.md +++ b/skills/kb-bilibili-metadata/SKILL.md @@ -1,187 +1,46 @@ ---- -name: kb-bilibili-metadata -description: B站元数据提取 - 获取视频/专栏/UP主的详细信息 ---- - # KB Bilibili Metadata Skill -**kb-bilibili-metadata** - 提取 B站视频、专栏、UP主的元数据。 +**kb-bilibili-metadata** - Extract Bilibili video/article/up主 metadata. -## 什么时候使用 +## Features -- kb-workflow 步骤 2:获取 B站内容的元数据 -- 需要视频标题、作者、时长等信息 +- Video metadata extraction +- Article (专栏) metadata extraction +- UP主 information extraction +- JSON output format +- Playwright + HTTP API fallback -## 功能 - -- 视频元数据提取 -- 专栏(article)元数据提取 -- UP主信息提取 -- JSON 输出格式 -- 支持 `--output` 参数指定输出文件 - -## 命令 +## Commands ```bash -# 视频元数据 -python3 bilibili_metadata.py --id "BV1xx411c7mD" --type video +# Video metadata +python bilibili_metadata.py --id "BV1xx411c7mD" --type video -# 专栏元数据 -python3 bilibili_metadata.py --id "cv43780186" --type article +# Article metadata +python bilibili_metadata.py --id "cv43780186" --type article -# UP主信息 -python3 bilibili_metadata.py --id "7770724" --type up - -# 指定输出文件 -python3 bilibili_metadata.py --id "BV1xx411c7mD" --type video --output "metadata/bilibili_BV1xx411c7mD.meta.json" +# UP主 info +python bilibili_metadata.py --id "7770724" --type up ``` -## 输出格式 Schema - -### 必需字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否提取成功 | -| `platform` | string | 固定为 `bilibili` | -| `content_id` | string | 内容 ID(BV号/cv号/uid) | -| `content_type` | string | 内容类型(video/article/up) | -| `title` | string | 标题(视频/专栏)或名称(UP主) | - -### 可选字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `author` | string | 作者/UP主名称 | -| `duration` | string | 时长(视频) | -| `description` | string | 简介/描述 | -| `stats` | object | 统计数据(播放、点赞等) | -| `output_file` | string | 输出文件路径 | -| `error` | string | 错误信息(失败时) | - -## 成功示例 - -### 视频元数据 +## Output ```json { "success": true, - "platform": "bilibili", - "content_type": "video", - "content_id": "BV1xx411c7mD", - "title": "视频标题", - "author": "UP主名字", - "duration": "10:30", - "description": "视频简介内容...", - "stats": { - "view": 100000, - "like": 5000, - "coin": 2000, - "favorite": 1000, - "share": 500, - "danmaku": 3000 - }, - "output_file": "metadata/bilibili_BV1xx411c7mD.meta.json" + "data": { + "platform": "bilibili", + "type": "video", + "id": "BV1xx411c7mD", + "title": "视频标题", + "author": "UP主名字", + "stats": {"view": 100000, "like": 5000} + } } ``` -### 专栏元数据 - -```json -{ - "success": true, - "platform": "bilibili", - "content_type": "article", - "content_id": "cv43780186", - "title": "专栏标题", - "author": "作者名字", - "description": "专栏摘要...", - "stats": { - "view": 50000, - "like": 2000, - "comment": 500 - }, - "output_file": "metadata/bilibili_cv43780186.meta.json" -} -``` - -### UP主信息 - -```json -{ - "success": true, - "platform": "bilibili", - "content_type": "up", - "content_id": "7770724", - "title": "UP主名字", - "description": "UP主签名...", - "stats": { - "follower": 1000000, - "following": 100, - "video_count": 500 - }, - "output_file": "metadata/bilibili_7770724.meta.json" -} -``` - -## 错误示例 - -### 视频不存在 - -```json -{ - "success": false, - "platform": "bilibili", - "content_id": "BV1invalid", - "content_type": "video", - "error": "视频不存在或已被删除" -} -``` - -### 网络错误 - -```json -{ - "success": false, - "platform": "bilibili", - "content_id": "BV1xx411c7mD", - "content_type": "video", - "error": "网络请求失败: Connection timeout" -} -``` - -### 参数错误 - -```json -{ - "success": false, - "error": "缺少必需参数: --id" -} -``` - -## 安装 +## Installation ```bash -cp -r kb-bilibili-metadata/ ~/.openclaw/skills/ -pip install httpx playwright -playwright install chromium +cp -r kb-bilibili-metadata/ ~/skills/ ``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 2:元数据提取(B站视频) -python3 ~/.openclaw/skills/kb-bilibili-metadata/bilibili_metadata.py \ - --id "BV1xx411c7mD" --type video \ - --output "metadata/bilibili_BV1xx411c7mD.meta.json" - -# 检查输出: -# - success=true → 进入步骤 3 -# - success=false → 检查错误,可能需要重试或退出 -``` - -## 注意事项 - -- 部分视频可能需要登录才能获取完整信息 -- 专栏内容可能需要额外的 Cookie 配置 -- 如果使用 Playwright 方式,首次运行需要下载浏览器 diff --git a/skills/kb-deep-analyzer/SKILL.md b/skills/kb-deep-analyzer/SKILL.md index 96233b9..0977cab 100644 --- a/skills/kb-deep-analyzer/SKILL.md +++ b/skills/kb-deep-analyzer/SKILL.md @@ -1,207 +1,102 @@ ---- -name: kb-deep-analyzer -description: AI深度分析 - 使用 AI 对内容进行深度分析和摘要 ---- - # KB Deep Analyzer Skill **kb-deep-analyzer** - AI 深度内容分析工具。 -## 什么时候使用 - -- kb-workflow 步骤 5:对视频字幕或文章内容进行深度分析 -- 需要生成摘要、主题、见解等 - -## 功能 +## Features - 多类型分析:视频(video)、文章(article) - 模板化输出 - 质量评分 - 自动标签 -- 多格式元数据支持 +- **多格式元数据支持**: 支持扁平结构 `{"title":"xxx"}` 和嵌套结构 `{"data":{"metadata":{...}}}` -## 环境变量(必需) +## 内容类型 -| 变量名 | 说明 | 示例 | -|--------|------|------| -| `AI_API_KEY` | AI API 密钥 | `your-api-key` | -| `AI_PROVIDER` | AI 提供商 | `zhipu` / `openai` / `minimax` | -| `AI_MODEL` | 模型名称 | `glm-5` / `gpt-4` | -| `AI_BASE_URL` | API 端点 | `https://open.bigmodel.cn/api/coding/paas/v4` | +| 类型 | 参数 | 输出格式 | +|------|------|----------| +| 视频 | `--type video` | 摘要 + 主题 + 见解 + 时间轴 | +| 文章 | `--type article` | 300字摘要 + 主题 + 原文 | -## 命令 +## Commands ```bash -# 分析视频 -AI_API_KEY="xxx" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ -python3 -u deep_analyzer.py \ - --metadata meta.json \ - --content content.json \ - --output analysis.md \ - --type video \ - --provider zhipu --model glm-5 +# 分析视频(默认) +AI_API_KEY="your-api-key" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ + python3 -u deep_analyzer.py --metadata meta.json --content content.json --output analysis.md --type video -# 分析文章 -AI_API_KEY="xxx" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ -python3 -u deep_analyzer.py \ - --metadata meta.json \ - --content content.txt \ - --output analysis.md \ - --type article \ - --provider zhipu --model glm-5 +# 分析文章(300字摘要 + 原文) +AI_API_KEY="your-api-key" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ + python3 -u deep_analyzer.py --metadata meta.json --content content.json --output analysis.md --type article + +# 指定 AI 提供商 +python3 -u deep_analyzer.py -m meta.json -c content.json -o out.md --type video --provider zhipu --model glm-5 ``` -## 参数说明 +## 环境变量配置 -| 参数 | 说明 | 必需 | -|------|------|------| -| `--metadata` | 元数据 JSON 文件路径 | 是 | -| `--content` | 内容文件路径(JSON/TXT) | 是 | -| `--output` | 输出 Markdown 文件路径 | 是 | -| `--type` | 内容类型(video/article) | 是 | -| `--provider` | AI 提供商 | 否(默认从环境变量) | -| `--model` | 模型名称 | 否(默认从环境变量) | - -## 输出格式 Schema - -### 必需字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否分析成功 | - -### 成功时字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `output_file` | string | 输出文件路径 | -| `model` | string | 使用的模型 | -| `provider` | string | 使用的提供商 | - -### 失败时字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `error` | string | 错误信息 | -| `message` | string | 详细说明 | - -## 成功示例 - -```json -{ - "success": true, - "output_file": "analyzed/bilibili_BV1xx411c7mD.md", - "model": "glm-5", - "provider": "zhipu" -} -``` - -## 错误示例 - -### API 调用失败 - -```json -{ - "success": false, - "error": "AI API 调用失败: rate limit exceeded", - "message": "深度分析失败,整个流程终止" -} -``` - -### 环境变量未设置 - -```json -{ - "success": false, - "error": "AI_API_KEY 环境变量未设置", - "suggestion": "请配置 AI_API_KEY 环境变量" -} -``` - -### 内容文件不存在 - -```json -{ - "success": false, - "error": "内容文件不存在", - "content_file": "content/missing.json" -} -``` - -## 输出格式(Markdown) - -### 视频分析输出 - -```markdown -# 视频标题 - -## 摘要 -[200-300字的核心内容摘要] - -## 主要主题 -- 主题1 -- 主题2 -- 主题3 - -## 关键见解 -- 见解1 -- 见解2 - -## 时间轴 -- 00:00 - 02:30: 第一部分 -- 02:30 - 05:00: 第二部分 -... - -## 标签 -#标签1 #标签2 #标签3 -``` - -### 文章分析输出 - -```markdown -# 文章标题 - -## 摘要 -[300字以内的核心观点] - -## 主要主题 -- 主题1 -- 主题2 - -## 完整原文 -[原始文章内容] -``` - -## 安装 +**必须设置以下环境变量**: ```bash -cp -r kb-deep-analyzer/ ~/.openclaw/skills/ -pip install httpx +export AI_API_KEY="your-api-key" +export AI_PROVIDER="zhipu" # 或 openai, minimax +export AI_MODEL="glm-5" # 模型名称 +export AI_BASE_URL="https://..." # 可选,自定义 API 地址 ``` -## 在 kb-workflow 中的使用 +### 重要提示 + +**必须使用 `-u` 参数运行 Python**,确保输出实时显示在终端: ```bash -# 步骤 5:深度分析 -# ⚠️ 必须成功,否则整个流程失败 - -AI_API_KEY="$AI_API_KEY" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ -python3 -u ~/.openclaw/skills/kb-deep-analyzer/deep_analyzer.py \ - --metadata "metadata/bilibili_BV1xx411c7mD.meta.json" \ - --content "content/bilibili_BV1xx411c7mD.json" \ - --output "analyzed/bilibili_BV1xx411c7mD.md" \ - --type video \ - --provider zhipu --model glm-5 - -# 检查结果: -# - success=true → 进入步骤 6(归档) -# - success=false → 整个流程终止,报告错误 +python3 -u deep_analyzer.py ... ``` -## ⚠️ 重要提示 +如果不使用 `-u` 参数,Python 的 stdout 缓冲会导致输出延迟或看不到进度。 -1. **必须使用 `-u` 参数**:确保 Python 输出实时显示 -2. **深度分析不可跳过**:这是必须成功的步骤 -3. **失败即终止**:如果返回 `success: false`,整个流程必须停止 -4. **禁止降级**:不能使用预设模板或简单摘要"假装成功" -5. **并发执行**:默认使用 batch_size=3 并发处理 +## 执行方式选择 + +### 方式1: 并发执行(推荐,默认) +- 使用 `batch_size=3`(默认) +- 6个分片约 100 秒完成 +- 适合快速分析 + +```bash +python3 -u deep_analyzer.py --metadata meta.json --content content.json -o out.md +``` + +### 方式2: 顺序执行 +- 使用 `batch_size=1` +- 6个分片约 735 秒完成 +- 适合调试和问题排查 + +```bash +# 在代码中设置 batch_size=1 +# analyzer.analyze(metadata, content, "video", batch_size=1) +``` + +## Metadata Format + +支持两种元数据格式: + +```json +// 格式1: 扁平结构 +{ + "title": "视频标题", + "author": "作者名", + "duration": 619, + "bvid": "BVxxx" +} + +// 格式2: 嵌套结构(kb-bilibili-metadata 输出) +{ + "data": { + "metadata": { + "title": "视频标题", + "author": "作者名", + "duration": "10:19" + } + } +} +``` + +会自动转换为扁平格式进行分析。 diff --git a/skills/kb-funasr/SKILL.md b/skills/kb-funasr/SKILL.md index 2b44a10..886012c 100644 --- a/skills/kb-funasr/SKILL.md +++ b/skills/kb-funasr/SKILL.md @@ -1,41 +1,44 @@ --- name: kb-funasr -description: 本地语音识别 - 使用阿里 FunASR 进行中文优化的语音识别 +description: 本地语音识别,支持音视频转文字(基于阿里 FunASR) --- # KB FunASR Skill -**kb-funasr** - 本地语音识别,使用阿里 FunASR 将音视频文件转换为文本。 +**kb-funasr** - 本地语音识别,使用阿里 FunASR 将音视频文件转换为文本和 JSON 格式输出。 ## 什么时候使用 -- kb-workflow 步骤 4 的备选方案:当 Whisper 效果不佳时 -- 中文语音识别(Paraformer 模型对中文优化) -- 需要高精度中文识别 +当用户需要: +- 将视频/音频文件转换为文字 +- 获取带时间戳的详细识别结果 +- 需要中文优化的语音识别(Paraformer 模型) ## 环境变量 -| 变量名 | 必需 | 说明 | -|--------|------|------| -| `FUNASR_CACHE_DIR` | 否 | FunASR 模型缓存目录 | +在使用之前,必须检查环境变量是否已经设置。 -## 命令 +| 变量名 | 用途 | 示例 | +|--------|------|------| +| `FUNASR_CACHE_DIR` | FunASR 模型缓存目录 | `~/.cache/modelscope/hub` | + +## 使用方法 ```bash -# 基本用法(使用 Paraformer 中文模型,推荐) -python3 funasr_tool.py --input video.mp4 +# 基本用法(使用 Paraformer 模型) +python funasr.py --input video.mp4 # 指定模型 -python3 funasr_tool.py --input video.mp4 --model paraformer-zh +python funasr.py --input video.mp4 --model paraformer-zh # 指定输出目录 -python3 funasr_tool.py --input video.mp4 --output ./output +python funasr.py --input video.mp4 --output ./output -# 后台异步执行 -python3 funasr_tool.py --input video.mp4 --background +# 异步执行(推荐) +python funasr.py --input video.mp4 --background ``` -## 参数说明 +## 命令参数 | 参数 | 说明 | 默认值 | |------|------|--------| @@ -46,91 +49,47 @@ python3 funasr_tool.py --input video.mp4 --background ## 模型选项 -| 模型 | 说明 | 推荐场景 | -|------|------|---------| -| `paraformer-zh` | Paraformer 中文模型 | **推荐**,中文优化 | -| `paraformer` | Paraformer 多语言模型 | 多语言场景 | -| `sensevoice` | SenseVoice 模型 | 高精度需求 | +- `paraformer-zh` - Paraformer 中文模型(轻量,中文优化,推荐) +- `paraformer` - Paraformer 多语言模型 +- `sensevoice` - SenseVoice 多语言模型 -## 输出格式 Schema +## 输出文件 -### 必需字段 +对于输入 `video.mp4`,将生成: -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否识别成功 | -| `input_file` | string | 输入文件路径 | -| `model` | string | 使用的模型 | +- `video.json` - 详细结果(包含时间戳、分段信息) +- `video.txt` - 纯文本内容 -### 可选字段 +## 输出格式示例 -| 字段 | 类型 | 说明 | -|------|------|------| -| `output_files` | object | 输出文件路径 | -| `duration_seconds` | number | 音频时长 | -| `segments` | array | 识别分段 | -| `error` | string | 错误信息 | - -## 成功示例 +### JSON 格式 ```json { "success": true, - "input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4", + "input_file": "video.mp4", "model": "paraformer-zh", "output_files": { - "json": "content/bilibili_BV1xx411c7mD_funasr.json", - "txt": "content/bilibili_BV1xx411c7mD_funasr.txt" + "json": "video.json", + "txt": "video.txt" }, - "duration_seconds": 630.5, + "duration_seconds": 120.5, "segments": [ { "id": 0, "start": 0.0, "end": 3.2, "text": "这是第一段识别结果" - }, - { - "id": 1, - "start": 3.2, - "end": 6.5, - "text": "这是第二段识别结果" } ] } ``` -## 错误示例 +## Workflow 中的使用 -### 模型未下载 - -```json -{ - "success": false, - "error": "模型未找到", - "model": "paraformer-zh", - "suggestion": "首次运行时会自动下载模型,请确保网络连接正常" -} -``` - -### 文件不存在 - -```json -{ - "success": false, - "error": "输入文件不存在", - "input_file": "content/downloads/missing.mp4" -} -``` - -### 内存不足 - -```json -{ - "success": false, - "error": "内存不足", - "suggestion": "尝试使用较小的模型或处理较短的音频片段" -} +```bash +# 步骤4之后:如果已有音频但无字幕,可以使用 FunASR +python funasr.py --input ${video_path} --model paraformer-zh --background ``` ## 安装 @@ -139,35 +98,16 @@ python3 funasr_tool.py --input video.mp4 --background # 1. 安装依赖 pip install funasr modelscope -# 2. 首次运行时自动下载模型 -python3 funasr_tool.py --input test.mp4 +# 2. 首次运行时会自动下载模型到缓存目录 +python funasr.py --input test.mp4 -# 3. 复制技能 -cp -r kb-funasr/ ~/.openclaw/skills/ -``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 4 的备选方案(当 Whisper 效果不佳时) -python3 ~/.openclaw/skills/kb-funasr/funasr_tool.py \ - --input "content/downloads/bilibili_BV1xx411c7mD.mp4" \ - --model paraformer-zh \ - --output "content/" - -# 输出: -# - bilibili_BV1xx411c7mD_funasr.json (完整结果) -# - bilibili_BV1xx411c7mD_funasr.txt (纯文本) - -# 完成后进入步骤 5(深度分析) +# 3. 复制技能到 skills 目录 +cp -r kb-funasr/ ~/skills/ ``` ## 注意事项 -- **首次运行**:首次运行时会自动下载模型文件(约 1GB),需要稳定网络 -- **中文优化**:Paraformer 模型对中文识别效果优于 Whisper -- **耗时操作**:语音识别可能需要几分钟到几十分钟 -- **文件格式**:支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式 -- **与 Whisper 对比**: - - Whisper:通用性强,支持多语言 - - FunASR:中文优化,精度更高 +- **异步执行**: 使用 `--background` 参数时,命令会在后台运行,不阻塞主代理 +- **模型选择**: paraformer-zh 模型适合中文语音识别,速度较快,精度较高 +- **文件格式**: 支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式 +- **首次运行**: 首次运行时会自动下载模型文件,需要稳定的网络连接 diff --git a/skills/kb-link-parser/SKILL.md b/skills/kb-link-parser/SKILL.md index a4ae3fa..b8c97cc 100644 --- a/skills/kb-link-parser/SKILL.md +++ b/skills/kb-link-parser/SKILL.md @@ -1,190 +1,43 @@ ---- -name: kb-link-parser -description: 链接解析器 - 从各平台 URL 提取平台类型、内容类型和 ID ---- - # KB Link Parser Skill -**kb-link-parser** - 从各种平台 URL 中提取和解析 ID。 +**kb-link-parser** - Extract and resolve IDs from various platform URLs. -## 什么时候使用 +## Features -- kb-workflow 步骤 1:解析用户提供的链接 -- 需要判断链接属于哪个平台、什么类型的内容 +- Multi-platform support: Bilibili, YouTube, Zhihu +- Short link detection: b23.tv and other short links +- Multiple content types: video, article, up主, playlist, collection +- Batch processing from file +- JSON output format -## 功能 - -- 多平台支持:Bilibili、YouTube、知乎、小红书 -- 短链接解析:b23.tv、xhslink.com 等 -- 多种内容类型:video、article、question、answer 等 -- 批量处理支持 -- JSON 输出格式 - -## 命令 +## Commands ```bash -# 解析单个 URL -python3 link-parser.py --url "https://www.bilibili.com/video/BV1xx411c7mD" +# Parse single URL +python link-parser.py --url "https://www.bilibili.com/video/BV1xx411c7mD" -# 批量处理 -python3 link-parser.py --batch urls.txt --output results.json +# Batch processing +python link-parser.py --batch urls.txt --output results.json -# 指定输出格式 -python3 link-parser.py --url "..." --format json +# Output format +python link-parser.py --url "..." --format json ``` -## 输出格式 Schema - -### 必需字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否解析成功 | -| `platform` | string | 平台名称(成功时必需) | -| `type` | string | 内容类型(成功时必需) | -| `id` | string | 内容 ID(成功时必需) | -| `error` | string | 错误信息(失败时必需) | - -### 可选字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `filename` | string | 建议的文件名 | -| `message` | string | 描述信息 | - -## 成功示例 - -### B站视频 +## Output ```json { "success": true, - "platform": "bilibili", - "type": "video", - "id": "BV1xx411c7mD", - "filename": "bilibili_BV1xx411c7mD.link.json", - "message": "URL解析成功" + "data": { + "platform": "bilibili", + "type": "video", + "id": "BV1xx411c7mD" + } } ``` -### B站专栏 - -```json -{ - "success": true, - "platform": "bilibili", - "type": "article", - "id": "cv43780186", - "filename": "bilibili_cv43780186.link.json", - "message": "URL解析成功" -} -``` - -### 知乎问答 - -```json -{ - "success": true, - "platform": "zhihu", - "type": "question", - "id": "266309957", - "filename": "zhihu_266309957.link.json", - "message": "URL解析成功" -} -``` - -### 知乎专栏文章 - -```json -{ - "success": true, - "platform": "zhihu", - "type": "zhuanlan", - "id": "1894054073625461813", - "filename": "zhihu_1894054073625461813.link.json", - "message": "URL解析成功" -} -``` - -### 知乎视频 - -```json -{ - "success": true, - "platform": "zhihu", - "type": "zvideo", - "id": "123456789", - "filename": "zhihu_123456789.link.json", - "message": "URL解析成功" -} -``` - -### 小红书笔记 - -```json -{ - "success": true, - "platform": "xiaohongshu", - "type": "note", - "id": "abc123", - "filename": "xiaohongshu_abc123.link.json", - "message": "URL解析成功" -} -``` - -## 错误示例 - -### 不支持的平台 - -```json -{ - "success": false, - "error": "Unsupported URL format", - "detail": "URL: https://example.com/video/123" -} -``` - -### 无效 URL - -```json -{ - "success": false, - "error": "解析失败", - "detail": "URL: not-a-valid-url" -} -``` - -## 支持的平台和类型 - -| 平台 | 类型 | URL 示例 | -|------|------|----------| -| bilibili | video | `bilibili.com/video/BVxxx` | -| bilibili | article | `bilibili.com/read/cvxxx` | -| bilibili | up主 | `space.bilibili.com/12345` | -| bilibili | favlist | `space.bilibili.com/123/favlist?fid=xxx` | -| zhihu | question | `zhihu.com/question/123` | -| zhihu | answer | `zhihu.com/question/123/answer/456` | -| zhihu | zhuanlan | `zhuanlan.zhihu.com/p/123` | -| zhihu | zvideo | `zhihu.com/zvideo/123` | -| xiaohongshu | note | `xiaohongshu.com/explore/xxx` | -| youtube | video | `youtube.com/watch?v=xxx` | - -## 安装 +## Installation ```bash -cp -r kb-link-parser/ ~/.openclaw/skills/ -pip install requests -``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 1:链接解析 -python3 ~/.openclaw/skills/kb-link-parser/link-parser.py --url "[用户提供的URL]" - -# 解析输出后: -# - 检查 success 字段 -# - 提取 platform, type, id -# - 生成 pending/{platform}_{id}.link.json -# - 进入步骤 2(元数据提取) +cp -r kb-link-parser/ ~/skills/ ``` diff --git a/skills/kb-link-parser/__pycache__/link_parser_shortlink.cpython-312.pyc b/skills/kb-link-parser/__pycache__/link_parser_shortlink.cpython-312.pyc index 0e0cc49..eeed198 100644 Binary files a/skills/kb-link-parser/__pycache__/link_parser_shortlink.cpython-312.pyc and b/skills/kb-link-parser/__pycache__/link_parser_shortlink.cpython-312.pyc differ diff --git a/skills/kb-ocr-processor/SKILL.md b/skills/kb-ocr-processor/SKILL.md index f8e0ddd..cfd9ef5 100644 --- a/skills/kb-ocr-processor/SKILL.md +++ b/skills/kb-ocr-processor/SKILL.md @@ -1,146 +1,66 @@ ---- -name: kb-ocr-processor -description: 视频OCR识别 - 从视频帧中提取文字 ---- - # KB OCR Processor Skill -**kb-ocr-processor** - 从视频帧中提取文字,作为语音识别的补充或替代方案。 +**kb-ocr-processor** - Extract text from video frames using OCR. -## 什么时候使用 +## Features -- kb-workflow 步骤 4 的降级方案:当 Whisper 语音识别效果不佳时 -- 音频质量差、有背景音乐干扰、多种语言混合等情况 +- **视频截帧**: 直接从视频文件截取帧图片 +- **批量处理**: 支持处理帧目录 +- **双引擎**: EasyOCR / Tesseract +- **置信度评分**: 每帧识别结果带置信度 +- **文本合并**: 自动合并所有帧的识别结果 -## 功能 - -- 视频截帧:直接从视频文件截取帧图片 -- 批量处理:支持处理帧目录 -- 双引擎:EasyOCR / Tesseract -- 置信度评分:每帧识别结果带置信度 -- 文本合并:自动合并所有帧的识别结果 - -## 命令 +## Commands ```bash -# 方式1: 直接从视频截帧并 OCR(推荐) -python3 ocr_processor.py --video ./video.mp4 --output ocr.json +# 方式1: 直接从视频截帧并OCR(推荐) +python ocr_processor.py --video ./video.flv --output ocr.json # 方式2: 处理已截取的帧目录 -python3 ocr_processor.py --input ./frames/ --output ocr.json +python ocr_processor.py --input ./frames/ --output ocr.json # 指定截帧帧率(默认1帧/秒) -python3 ocr_processor.py --video ./video.mp4 --fps 2 --output ocr.json +python ocr_processor.py --video ./video.flv --fps 2 --output ocr.json # 同时生成合并的文本文件 -python3 ocr_processor.py --video ./video.mp4 --output ocr.json --merge +python ocr_processor.py --video ./video.flv --output ocr.json --merge # 使用 Tesseract 引擎 -python3 ocr_processor.py --input ./frames/ --engine tesseract --output ocr.json +python ocr_processor.py --input ./frames/ --engine tesseract --output ocr.json ``` -## 输出格式 Schema +## Workflow 中的使用 -### 必需字段 +```bash +# 步骤5: OCR处理(视频无字幕时) +python ocr_processor.py --video ${CONTENT_VIDEO_PATH} --output ${CONTENT_DIR}/ocr.json --merge +``` -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否识别成功 | -| `engine` | string | 使用的 OCR 引擎 | -| `total_frames` | number | 处理的总帧数 | - -### 可选字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `results` | array | 每帧的识别结果 | -| `merged_text` | string | 合并后的文本 | -| `output_file` | string | 输出文件路径 | -| `error` | string | 错误信息 | - -## 成功示例 +## Output ```json { "success": true, "engine": "easyocr", "total_frames": 619, - "output_file": "content/bilibili_BV1xx411c7mD_ocr.json", "results": [ { "source": "0001.jpg", "text": "字幕文字", "confidence": 0.95 - }, - { - "source": "0002.jpg", - "text": "更多字幕文字", - "confidence": 0.92 } - ], - "merged_text": "字幕文字\n更多字幕文字\n..." + ] } ``` -## 错误示例 - -### 视频文件不存在 - -```json -{ - "success": false, - "error": "视频文件不存在", - "video": "./missing.mp4" -} -``` - -### ffmpeg 未安装 - -```json -{ - "success": false, - "error": "ffmpeg 未安装", - "suggestion": "请运行: sudo apt-get install ffmpeg" -} -``` - -### 内存不足 - -```json -{ - "success": false, - "error": "内存不足", - "suggestion": "尝试降低帧率或处理较短的片段" -} -``` - -## 安装 +## Installation ```bash -cp -r kb-ocr-processor/ ~/.openclaw/skills/ -pip install easyocr pytesseract Pillow +cp -r kb-ocr-processor/ ~/skills/ +pip install -r requirements.txt -# 系统依赖 -sudo apt-get install ffmpeg tesseract-ocr tesseract-ocr-chi-sim tesseract-ocr-eng +# 依赖说明 +# - easyocr: 主要OCR引擎(自动下载模型) +# - pytesseract: Tesseract引擎 +# - ffmpeg: 视频截帧(apt install ffmpeg) ``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 4 的降级方案(当 Whisper 效果不佳时) -python3 ~/.openclaw/skills/kb-ocr-processor/ocr_processor.py \ - --video "content/downloads/bilibili_BV1xx411c7mD.mp4" \ - --output "content/bilibili_BV1xx411c7mD_ocr.json" \ - --merge - -# 输出: -# - bilibili_BV1xx411c7mD_ocr.json (完整结果) -# - bilibili_BV1xx411c7mD_ocr.txt (合并文本) -``` - -## 注意事项 - -- **耗时操作**:OCR 处理需要截帧和识别,可能较慢 -- **帧率选择**:1帧/秒适合大多数场景,更高帧率增加精度但耗时更长 -- **引擎选择**:EasyOCR 精度较高,Tesseract 速度较快 -- **适用场景**:音频质量差、背景音乐干扰、多语言混合时使用 diff --git a/skills/kb-whisper/SKILL.md b/skills/kb-whisper/SKILL.md index 969c613..9ebb999 100644 --- a/skills/kb-whisper/SKILL.md +++ b/skills/kb-whisper/SKILL.md @@ -1,40 +1,44 @@ --- name: kb-whisper -description: 本地语音识别 - 使用 Whisper.cpp 将音视频转文字 +description: 本地语音识别,支持音视频转文字(基于 Whisper.cpp) --- # KB Whisper Skill -**kb-whisper** - 本地语音识别,使用 Whisper.cpp 将音视频文件转换为文本、字幕和 JSON 格式。 +**kb-whisper** - 本地语音识别,使用 Whisper.cpp 将音视频文件转换为文本、字幕和 JSON 格式输出。 ## 什么时候使用 -- kb-workflow 步骤 4:视频无官方字幕时进行语音识别 -- 需要将音视频转为文字 +当用户需要: +- 将视频/音频文件转换为文字 +- 生成视频字幕(SRT 格式) +- 获取带时间戳的详细识别结果 ## 环境变量 -| 变量名 | 必需 | 说明 | -|--------|------|------| -| `WHISPER_CPP_PATH` | 是 | whisper.cpp 安装路径 | +在使用之前,必须检查环境变量是否已经设置。 -## 命令 +| 变量名 | 用途 | 示例 | +|--------|------|------| +| `WHISPER_CPP_PATH` | whisper.cpp 安装路径 | `~/whisper.cpp` | + +## 使用方法 ```bash # 基本用法 -python3 whisper.py --input video.mp4 +python whisper.py --input video.mp4 -# 指定模型(推荐 base) -python3 whisper.py --input video.mp4 --model base +# 指定模型(默认 tiny) +python whisper.py --input video.mp4 --model base # 指定输出目录 -python3 whisper.py --input video.mp4 --output ./output +python whisper.py --input video.mp4 --output ./output -# 后台异步执行 -python3 whisper.py --input video.mp4 --background +# 异步执行(推荐) +python whisper.py --input video.mp4 --background ``` -## 参数说明 +## 命令参数 | 参数 | 说明 | 默认值 | |------|------|--------| @@ -45,94 +49,51 @@ python3 whisper.py --input video.mp4 --background ## 模型选项 -| 模型 | 速度 | 精度 | 推荐场景 | -|------|------|------|---------| -| `tiny` | 最快 | 较低 | 快速预览 | -| `base` | 快 | 良好 | **推荐** | -| `small` | 中等 | 高 | 精确识别 | -| `medium` | 慢 | 很高 | 专业场景 | -| `large` | 最慢 | 最高 | 最高精度 | +- `tiny` - 最小模型,速度快,精度较低(推荐快速识别) +- `base` - 基础模型,平衡速度和精度(推荐) +- `small` - 小型模型,精度更高,速度较慢 +- `medium` - 中型模型,高精度 +- `large` - 大型模型,最高精度,速度慢 -## 输出格式 Schema +## 输出文件 -### 必需字段 +对于输入 `video.mp4`,将生成: -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否识别成功 | -| `input_file` | string | 输入文件路径 | -| `model` | string | 使用的模型 | +- `video.json` - 详细结果(包含时间戳、分段信息) +- `video.srt` - 字幕格式文件 +- `video.txt` - 纯文本内容 -### 可选字段 +## 输出格式示例 -| 字段 | 类型 | 说明 | -|------|------|------| -| `output_files` | object | 输出文件路径 | -| `duration_seconds` | number | 音频时长 | -| `segments` | array | 识别分段 | -| `error` | string | 错误信息 | - -## 成功示例 +### JSON 格式 ```json { "success": true, - "input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4", - "model": "base", + "input_file": "video.mp4", + "model": "tiny", "output_files": { - "json": "content/bilibili_BV1xx411c7mD.json", - "txt": "content/bilibili_BV1xx411c7mD.txt", - "srt": "content/bilibili_BV1xx411c7mD.srt" + "json": "video.json", + "srt": "video.srt", + "txt": "video.txt" }, - "duration_seconds": 630.5, + "duration_seconds": 120.5, "segments": [ { "id": 0, "start": 0.0, "end": 3.2, "text": "这是第一段字幕" - }, - { - "id": 1, - "start": 3.2, - "end": 6.5, - "text": "这是第二段字幕" } ] } ``` -## 错误示例 +## Workflow 中的使用 -### 模型未下载 - -```json -{ - "success": false, - "error": "模型文件不存在", - "model": "base", - "suggestion": "请运行: cd ~/whisper.cpp && ./models/download-ggml-model.sh base" -} -``` - -### 文件不存在 - -```json -{ - "success": false, - "error": "输入文件不存在", - "input_file": "content/downloads/missing.mp4" -} -``` - -### 内存不足 - -```json -{ - "success": false, - "error": "内存不足,无法加载模型", - "suggestion": "尝试使用更小的模型(tiny/base)" -} +```bash +# 步骤4之后:如果已有音频但无字幕,可以使用 whisper +python whisper.py --input ${video_path} --model base --background ``` ## 安装 @@ -142,39 +103,22 @@ python3 whisper.py --input video.mp4 --background git clone https://github.com/ggerganov/whisper.cpp.git ~/whisper.cpp # 2. 编译 -cd ~/whisper.cpp && make +cd ~/whisper.cpp +make -# 3. 下载模型 -./models/download-ggml-model.sh base +# 3. 下载模型(tiny) +./models/download-ggml-model.sh tiny -# 4. 设置环境变量 -echo 'export WHISPER_CPP_PATH="$HOME/whisper.cpp"' >> ~/.kb_env -source ~/.kb_env +# 4. 下载更多模型(可选) +# ./models/download-ggml-model.sh base +# ./models/download-ggml-model.sh small -# 5. 复制技能 -cp -r kb-whisper/ ~/.openclaw/skills/ -``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 4:语音识别(当 has_subtitle=false 时) -python3 ~/.openclaw/skills/kb-whisper/whisper.py \ - --input "content/downloads/bilibili_BV1xx411c7mD.mp4" \ - --model base \ - --output "content/" - -# 输出: -# - bilibili_BV1xx411c7mD.json (完整结果) -# - bilibili_BV1xx411c7mD.txt (纯文本) -# - bilibili_BV1xx411c7mD.srt (字幕文件) - -# 完成后进入步骤 5(深度分析) +# 5. 复制技能到 skills 目录 +cp -r kb-whisper/ ~/skills/ ``` ## 注意事项 -- **耗时操作**:语音识别可能需要几分钟到几十分钟,取决于视频长度 -- **异步执行**:推荐使用 `--background` 参数 -- **模型选择**:base 模型平衡速度和精度,适合大多数场景 -- **文件格式**:支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式 +- **异步执行**: 使用 `--background` 参数时,命令会在后台运行,不阻塞主代理 +- **模型选择**: tiny 模型适合快速识别,base 模型适合一般用途,large 模型适合高精度需求 +- **文件格式**: 支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式 diff --git a/skills/kb-workflow/SKILL.md b/skills/kb-workflow/SKILL.md index ccb435e..a4c8573 100644 --- a/skills/kb-workflow/SKILL.md +++ b/skills/kb-workflow/SKILL.md @@ -5,698 +5,200 @@ description: 当收到"添加到知识库 + 链接" 或"保存到知识库 + 链 # KB Workflow -## 触发条件 +## 什么时候使用 + +当用户发送包含以下模式的消息时,此技能自动触发: | 触发词 | 行为 | 示例 | |--------|------|------| | `添加到知识库` + 链接 | 添加到知识库并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" | | `保存到知识库` + 链接 | 同上 | "保存到知识库 https://www.bilibili.com/video/BVxxx" | ---- +## 环境变量 -## 状态机定义 +### 执行前必须检查 -工作流是一个严格的状态机,每个状态有明确的前置条件和后置条件: +在执行 workflow 之前,必须检查环境变量是否已经设置。 -| 状态 | 前置条件 | 执行动作 | 成功后进入 | 失败处理 | -|------|---------|---------|-----------|---------| -| `init` | 用户触发 + URL 有效 | 创建 state.json,检查环境变量 | `link_parse` | 报错退出 | -| `link_parse` | state.json 存在 | 解析链接,提取平台和ID | `metadata` | 记录错误,最多重试1次 | -| `metadata` | platform, content_id 已知 | 提取元数据 | `content` | 记录错误,最多重试1次 | -| `content` | 元数据文件存在 | 下载内容/字幕 | `analyze` 或 `whisper` | 根据错误类型处理 | -| `whisper` | 视频已下载,无官方字幕 | 语音识别转文字 | `analyze` | 尝试 OCR 降级 | -| `analyze` | 有文本内容(字幕/识别结果/文章) | AI 深度分析 | `archive` | **流程失败,报错退出** | -| `archive` | 分析报告存在 | 归档 + Git 提交 | `done` | 记录错误,可手动处理 | -| `done` | - | 汇报完成 | - | - | - -### 状态判断流程图 - -``` -用户发送链接 - ↓ -┌─────────────────────────────────────┐ -│ Step 0: 环境变量检查 │ -│ 缺少必需变量 → 报错退出 │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 1: 链接解析 (link_parse) │ -│ 输出: platform, content_type, id │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 2: 元数据提取 (metadata) │ -│ 输出: title, author, etc. │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ content_type 判断 │ -├─────────────────────────────────────┤ -│ video/zvideo → Step 3a (视频处理) │ -│ article/zhuanlan/question → Step 3b │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 3a: 视频处理 │ -│ 有官方字幕? → 是 → Step 5 │ -│ → 否 → Step 4 (Whisper) │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 3b: 文章处理 │ -│ 提取文字 → 直接进入 Step 5 │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 4: Whisper 语音识别 (可选) │ -│ 无字幕时执行,生成 text/json/srt │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 5: 深度分析 (analyze) │ -│ ⚠️ 必须成功,否则流程失败 │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Step 6: 归档 (archive) │ -│ 复制到归档目录 + Git 提交 │ -└─────────────────────────────────────┘ - ↓ - 完成 -``` - ---- - -## 环境变量清单 - -### 必需变量(缺失则报错退出) - -| 变量名 | 用途 | 示例 | -|--------|------|------| -| `AI_API_KEY` | AI API 密钥 | `your-api-key` | -| `AI_PROVIDER` | AI 提供商 | `zhipu` / `openai` / `minimax` | -| `AI_MODEL` | 模型名称 | `glm-5` / `gpt-4` | -| `AI_BASE_URL` | API 端点 | `https://open.bigmodel.cn/api/coding/paas/v4` | - -### 可选变量 - -| 变量名 | 用途 | 用途说明 | -|--------|------|---------| -| `BILIBILI_COOKIE` | B站登录态 | 下载会员视频 | -| `ZHIHU_COOKIE` | 知乎登录态 | 访问专栏等 | -| `HF_TOKEN` | HuggingFace Token | 说话者分离功能 | -| `KB_ARCHIVE_PATH` | 归档目录 | 默认 `~/work/zq/30.资源/AI分析` | -| `KB_GIT_ROOT` | Git 仓库根目录 | 默认 `~/work/zq` | -| `KB_GIT_USER` | Git 提交用户名 | 归档时使用 | -| `KB_GIT_EMAIL` | Git 提交邮箱 | 归档时使用 | - -### 配置方法 +**必须的环境变量**(缺失则报错退出): +配置方式:将变量写入 `~/.kb_env` 文件: ```bash -# 创建专用配置文件 -cat > ~/.kb_env << 'EOF' export AI_API_KEY="your-api-key" export AI_PROVIDER="zhipu" export AI_MODEL="glm-5" export AI_BASE_URL="https://open.bigmodel.cn/api/coding/paas/v4" -export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx" -export KB_ARCHIVE_PATH="$HOME/work/zq/30.资源/AI分析" -export KB_GIT_ROOT="$HOME/work/zq" -EOF - -# 在 ~/.bashrc 中添加 -[ -f ~/.kb_env ] && source ~/.kb_env ``` ---- +**可选的环境变量**: +| 变量名 | 用途 | 示例 | +|--------|------|------| +| `BILIBILI_COOKIE` | 下载会员视频 | `SESSDATA=xxx; bili_jct=xxx` | +| `KB_GIT_USER` | Git提交用户名 | `Your Name` | +| `KB_GIT_EMAIL` | Git提交邮箱 | `your@email.com` | +| `KB_ARCHIVE_PATH` | 归档目录路径 | `~/work/zq/30.资源/AI分析` | +| `KB_GIT_ROOT` | Git仓库根目录 | `~/work/zq` | +| `HF_TOKEN` | HuggingFace Token(说话者分离) | `hf_xxx` | -## 步骤详解 +### 检查命令 -### Step 0: 环境变量检查 - -**前置条件:** 无 - -**执行命令:** ```bash -# 加载环境变量 -if [ -f ~/.kb_env ]; then source ~/.kb_env; fi +# 从 ~/.kb_env 加载环境变量 +if [ -f ~/.kb_env ]; then + source ~/.kb_env +fi + +# 检查必须的环境变量 +if [ -z "$AI_API_KEY" ] || [ -z "$AI_PROVIDER" ] || [ -z "$AI_MODEL" ] || [ -z "$AI_BASE_URL" ]; then + echo "❌ 错误:必须的环境变量未设置" + echo "请配置 ~/.kb_env 文件" + exit 1 +fi -# 检查必需变量 -for var in AI_API_KEY AI_PROVIDER AI_MODEL AI_BASE_URL; do - if [ -z "${!var}" ]; then - echo "❌ 错误:$var 未设置" - exit 1 - fi -done echo "✅ 环境变量检查通过" ``` -**成功标准:** -- 所有必需变量已设置 -- 输出 "✅ 环境变量检查通过" +## Workflow 执行方式 -**失败处理:** -- 缺少任何必需变量 → 报错退出,提示用户配置 +### 方式一:一键处理(推荐) -**输出示例:** -``` -✅ 环境变量检查通过 - AI_PROVIDER: zhipu - AI_MODEL: glm-5 -``` +使用管道 CLI 一键完成所有步骤: -**错误示例:** -``` -❌ 错误:AI_API_KEY 未设置 -请配置以下环境变量: - - AI_API_KEY - - AI_PROVIDER - - AI_MODEL - - AI_BASE_URL -``` - ---- - -### Step 1: 链接解析 - -**前置条件:** -- 环境变量检查通过 -- URL 格式有效 - -**执行命令:** ```bash -# 获取目录路径 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --pending - -# 解析链接 -python3 ~/.openclaw/skills/kb-link-parser/link-parser.py --url "[URL]" +python3 kb-workflow/kb_workflow.py process "https://www.bilibili.com/video/BVxxx" ``` -**成功标准:** -- 返回 JSON 包含 `success: true` -- 包含字段:`platform`, `content_type`, `content_id` -- 生成文件:`pending/{platform}_{id}.link.json` +**该命令自动执行:** +1. URL 解析 → 识别平台和内容 ID +2. 元数据提取 → 获取标题、作者等信息 +3. 内容下载 → 字幕/视频/文章内容 +4. 语音识别 → Whisper/FunASR(如需要) +5. 深度分析 → AI 生成分析报告 +6. 归档 → 移动到归档目录 -**失败处理:** -- 不支持的平台 → 报错退出,告知用户支持的平台 -- URL 无效 → 报错退出,请用户提供正确链接 - -**输出示例:** -```json -{ - "success": true, - "platform": "bilibili", - "content_type": "video", - "content_id": "BV1xx411c7mD", - "output_file": "pending/bilibili_BV1xx411c7mD.link.json" -} -``` - -**错误示例:** -```json -{ - "success": false, - "error": "不支持的平台: example.com", - "supported_platforms": ["bilibili.com", "zhihu.com", "youtube.com"] -} -``` - ---- - -### Step 2: 元数据提取 - -**前置条件:** -- Step 1 完成 -- `platform`, `content_type`, `content_id` 已知 - -**执行命令:** +**命令参数:** ```bash -# 获取目录路径 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --metadata +# 指定输出目录 +python3 kb-workflow/kb_workflow.py process "https://..." -o /path/to/output -# 根据平台选择命令 -# B站视频 -python3 ~/.openclaw/skills/kb-bilibili-metadata/bilibili_metadata.py \ - --id "[BV号]" --type video \ - --output "metadata/bilibili_[BV号].meta.json" - -# B站专栏 -python3 ~/.openclaw/skills/kb-bilibili-metadata/bilibili_metadata.py \ - --id "[cv号]" --type article \ - --output "metadata/bilibili_cv[cv号].meta.json" - -# 知乎问答 -python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \ - --id "[问题ID]" --type question \ - --output "metadata/zhihu_[ID].meta.json" - -# 知乎视频 -python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \ - --id "[视频ID]" --type zvideo \ - --output "metadata/zhihu_[ID].meta.json" +# 强制重新执行(忽略已完成状态) +python3 kb-workflow/kb_workflow.py process "https://..." --no-skip ``` -**成功标准:** -- 返回 JSON 包含 `success: true` -- 包含字段:`platform`, `content_id`, `title` -- 生成文件:`metadata/{platform}_{id}.meta.json` +### 方式二:手动分步执行(高级) -**失败处理:** -- 网络错误 → 重试1次 -- 内容不存在 → 报错退出 -- 需要登录 → 提示配置 Cookie +如需更细粒度控制,可手动调用各子技能: -**输出示例:** -```json -{ - "success": true, - "platform": "bilibili", - "content_id": "BV1xx411c7mD", - "content_type": "video", - "title": "视频标题", - "author": "UP主名字", - "duration": "10:30", - "output_file": "metadata/bilibili_BV1xx411c7mD.meta.json" -} -``` - -**错误示例:** -```json -{ - "success": false, - "error": "视频不存在或已被删除", - "content_id": "BV1xx411c7mD" -} -``` - ---- - -### Step 3a: 视频内容下载 - -**前置条件:** -- Step 2 完成 -- `content_type` 为 `video` 或 `zvideo` - -**执行命令:** ```bash -# 获取目录路径 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --content_downloads +# 1. 查重 +python3 kb-workflow/kb_workflow.py --check --url "https://..." -# B站视频 - 优先尝试字幕 -python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ - --id "[BV号]" --type subtitle-download \ - --output "content/downloads/" +# 2. 一键处理 +python3 kb-workflow/kb_workflow.py process "https://..." -# 检查是否有官方字幕 -# 如果 has_subtitle=true → 进入 Step 5 -# 如果 has_subtitle=false → 下载视频,进入 Step 4 +# 3. 归档 +python3 kb-workflow/kb_workflow.py --archive-file "/path/to/report.md" ``` -**成功标准:** -- 返回 JSON 包含 `success: true` -- `has_subtitle=true`: 有字幕文件 -- `has_subtitle=false`: 视频文件下载成功 +## 支持的平台和内容类型 -**失败处理:** -- 403 禁止访问 → 检查 BILIBILI_COOKIE 配置 -- 网络超时 → 重试1次 -- 会员视频 → 提示需要配置 Cookie +| 平台 | 内容类型 | URL 示例 | +|------|----------|----------| +| B站 | 视频 | `bilibili.com/video/BVxxx` | +| B站 | 专栏 | `bilibili.com/read/cvxxx` | +| 知乎 | 问答 | `zhihu.com/question/xxx` | +| 知乎 | 专栏 | `zhuanlan.zhihu.com/p/xxx` | +| 知乎 | 视频 | `zhihu.com/zvideo/xxx` | + +## 处理流程 -**输出示例(有字幕):** -```json -{ - "success": true, - "type": "subtitle", - "has_subtitle": true, - "subtitle_file": "content/downloads/bilibili_BV1xx411c7mD.srt", - "message": "官方字幕下载成功" -} ``` - -**输出示例(无字幕):** -```json -{ - "success": true, - "type": "subtitle", - "has_subtitle": false, - "message": "无官方字幕,需要下载视频进行语音识别" -} +┌─────────────────────────────────────────────────────────────┐ +│ kb-workflow process │ +├─────────────────────────────────────────────────────────────┤ +│ 1. Parse → LinkParser 解析 URL │ +│ 2. Download → 平台适配器获取元数据和内容 │ +│ 3. ASR → 语音识别(视频无字幕时) │ +│ 4. Analyze → DeepAnalyzer 生成分析报告 │ +│ 5. Archive → 归档到 KB_ARCHIVE_PATH │ +└─────────────────────────────────────────────────────────────┘ ``` -**错误示例:** -```json -{ - "success": false, - "error": "403 Forbidden - 可能需要会员权限", - "suggestion": "请配置 BILIBILI_COOKIE 环境变量" -} -``` - ---- - -### Step 3b: 文章内容提取 - -**前置条件:** -- Step 2 完成 -- `content_type` 为 `article`、`zhuanlan` 或 `question` - -**执行命令:** -```bash -# B站专栏 -python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ - --id "[cv号]" --type article \ - --output "content/" - -# 知乎专栏 -python3 ~/.openclaw/skills/kb-zhihu-content/zhihu_content.py \ - --type article-from-media \ - --output "content/" -``` - -**成功标准:** -- 返回 JSON 包含 `success: true` -- 包含字段:`filepath`, `content_length` -- 跳过 Step 4,直接进入 Step 5 - -**输出示例:** -```json -{ - "success": true, - "type": "article", - "filepath": "content/bilibili_cv43780186.txt", - "content_length": 5234, - "message": "文章内容提取成功" -} -``` - ---- - -### Step 4: Whisper 语音识别 - -**前置条件:** -- Step 3a 完成 -- `has_subtitle=false` -- 视频文件已下载 - -**执行命令:** -```bash -# 获取目录路径 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --content - -# 普通识别 -python3 ~/.openclaw/skills/kb-whisper/whisper.py \ - --input "content/downloads/bilibili_BV1xx411c7mD.mp4" \ - --model base \ - --output "content/" - -# 带说话者分离(需要 HF_TOKEN) -if [ -n "$HF_TOKEN" ]; then - python3 ~/.openclaw/skills/kb-whisper-diarization/whisper_diarization.py \ - --input "content/downloads/bilibili_BV1xx411c7mD.mp4" \ - --model base --diarize \ - --output "content/" -fi -``` - -**成功标准:** -- 返回 JSON 包含 `success: true` -- 生成文件:`.json`, `.txt`, `.srt` - -**失败处理:** -- 模型未下载 → 提示下载模型 -- 内存不足 → 尝试更小的模型 -- Whisper 失败 → 尝试 OCR 降级 - -**输出示例:** -```json -{ - "success": true, - "input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4", - "model": "base", - "output_files": { - "json": "content/bilibili_BV1xx411c7mD.json", - "txt": "content/bilibili_BV1xx411c7mD.txt", - "srt": "content/bilibili_BV1xx411c7mD.srt" - }, - "duration_seconds": 630 -} -``` - ---- - -### Step 5: 深度分析 - -**前置条件:** -- 有文本内容(字幕/识别结果/文章) -- 元数据文件存在 - -**执行命令:** -```bash -# 获取目录路径 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --analyzed - -# 分析视频 -AI_API_KEY="$AI_API_KEY" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ -python3 -u ~/.openclaw/skills/kb-deep-analyzer/deep_analyzer.py \ - --metadata "metadata/bilibili_BV1xx411c7mD.meta.json" \ - --content "content/bilibili_BV1xx411c7mD.json" \ - --output "analyzed/bilibili_BV1xx411c7mD.md" \ - --type video \ - --provider zhipu --model glm-5 - -# 分析文章 -AI_API_KEY="$AI_API_KEY" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ -python3 -u ~/.openclaw/skills/kb-deep-analyzer/deep_analyzer.py \ - --metadata "metadata/xxx.meta.json" \ - --content "content/xxx.txt" \ - --output "analyzed/xxx.md" \ - --type article \ - --provider zhipu --model glm-5 -``` - -**成功标准:** -- 返回 JSON 包含 `success: true` -- 生成分析报告文件 - -**失败处理:** -- ⚠️ **深度分析失败 = 整个流程失败** -- API 调用失败 → 记录错误,**终止流程** -- **禁止**使用预设模板或降级内容 - -**输出示例:** -```json -{ - "success": true, - "output_file": "analyzed/bilibili_BV1xx411c7mD.md", - "model": "glm-5", - "provider": "zhipu" -} -``` - -**错误示例:** -```json -{ - "success": false, - "error": "AI API 调用失败: rate limit exceeded", - "message": "深度分析失败,整个流程终止" -} -``` - ---- - -### Step 6: 归档 - -**前置条件:** -- Step 5 完成 -- 分析报告文件存在 - -**执行命令:** -```bash -# 归档 -python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py \ - --archive-file "analyzed/bilibili_BV1xx411c7mD.md" - -# 如果配置了 Git,会自动提交 -``` - -**成功标准:** -- 文件复制到归档目录 -- Git 提交成功(如果配置) - -**失败处理:** -- 归档失败 → 记录错误,文件仍可用 -- Git 失败 → 不影响主流程 - -**输出示例:** -```json -{ - "success": true, - "archive_path": "~/work/zq/30.资源/AI分析/2026-03-13/bilibili_BV1xx411c7mD.md", - "git_commit": "abc1234" -} -``` - ---- - ## 目录结构 +**工作目录(默认 ~/work/knowledge-base/):** +``` +~/work/knowledge-base/ +├── pending/ # 待处理链接 +├── metadata/ # 元数据 JSON +├── content/ # 内容文件 +│ └── downloads/ # 下载的视频/字幕 +└── analyzed/ # 分析报告 ``` -~/work/knowledge-base/ # 知识库根目录 -├── pending/ # 待处理链接 -│ └── {platform}_{id}.link.json -├── metadata/ # 元数据 -│ └── {platform}_{id}.meta.json -├── content/ # 内容 -│ ├── downloads/ # 视频下载 -│ │ └── {platform}_{id}.mp4 -│ ├── {platform}_{id}.txt # 文本内容 -│ └── {platform}_{id}.json # Whisper 结果 -└── analyzed/ # 深度分析报告 - └── {platform}_{id}.md -~/work/zq/30.资源/AI分析/ # 归档目录 +**归档目录(默认 ~/work/zq/30.资源/AI分析/):** +``` +~/work/zq/30.资源/AI分析/ └── YYYY-MM-DD/ - └── {platform}_{id}.md + └── {platform}_{id}.md # 深度分析报告 ``` ---- - -## 子技能清单 - -| 步骤 | 子技能 | 命令 | -|------|--------|------| -| 1 | kb-link-parser | `--url "[URL]"` | -| 2 | kb-bilibili-metadata | `--id "[ID]" --type video --output "[PATH]"` | -| 2 | kb-zhihu-metadata | `--id "[ID]" --type question --output "[PATH]"` | -| 3a | kb-bilibili-content | `--id "[ID]" --type subtitle-download --output "[PATH]"` | -| 3a | kb-bilibili-content | `--id "[ID]" --type video --output "[PATH]"` | -| 3b | kb-bilibili-content | `--id "[ID]" --type article --output "[PATH]"` | -| 3b | kb-zhihu-content | `--type article-from-media --output "[PATH]"` | -| 4 | kb-whisper | `--input "[VIDEO]" --model base --output "[PATH]"` | -| 4 | kb-whisper-diarization | `--input "[VIDEO]" --model base --diarize --output "[PATH]"` | -| 5 | kb-deep-analyzer | `--metadata "[META]" --content "[CONTENT]" --output "[OUT]" --type video` | - ---- - -## 端到端示例 - -### 示例 1: B站视频(有官方字幕) - -**输入:** `添加到知识库 https://www.bilibili.com/video/BV1xx411c7mD` - -``` -Step 0: ✅ 环境变量检查通过 -Step 1: ✅ 链接解析 → bilibili, video, BV1xx411c7mD -Step 2: ✅ 元数据提取 → 标题: "xxx", 作者: "xxx" -Step 3a: ✅ 字幕下载 → has_subtitle=true, bilibili_BV1xx411c7mD.srt -Step 4: ⏭️ 跳过(有官方字幕) -Step 5: ✅ 深度分析 → bilibili_BV1xx411c7mD.md -Step 6: ✅ 归档 → ~/work/zq/30.资源/AI分析/2026-03-13/ -``` - -### 示例 2: B站视频(无官方字幕) - -**输入:** `添加到知识库 https://www.bilibili.com/video/BV1yy411c7mE` - -``` -Step 0: ✅ 环境变量检查通过 -Step 1: ✅ 链接解析 → bilibili, video, BV1yy411c7mE -Step 2: ✅ 元数据提取 → 标题: "xxx", 时长: "15:30" -Step 3a: ⚠️ 无官方字幕 → 下载视频 -Step 3a: ✅ 视频下载 → bilibili_BV1yy411c7mE.mp4 -Step 4: ✅ Whisper 识别 → bilibili_BV1yy411c7mE.json/txt/srt -Step 5: ✅ 深度分析 → bilibili_BV1yy411c7mE.md -Step 6: ✅ 归档 -``` - -### 示例 3: 403 下载失败 - -**输入:** `添加到知识库 https://www.bilibili.com/video/BV1zz411c7mF` - -``` -Step 0: ✅ 环境变量检查通过 -Step 1: ✅ 链接解析 -Step 2: ✅ 元数据提取 -Step 3a: ❌ 403 Forbidden - → 可能需要会员权限 - → 请配置 BILIBILI_COOKIE 环境变量 - → 流程暂停,等待用户处理 -``` - ---- - -## 常见错误处理 - -### 错误 1: 环境变量未设置 - -**症状:** `❌ 错误:AI_API_KEY 未设置` - -**解决:** -```bash -echo 'export AI_API_KEY="your-key"' >> ~/.kb_env -source ~/.kb_env -``` - -### 错误 2: 403 下载失败 - -**症状:** B站视频下载返回 403 - -**解决:** -1. 获取 B站 Cookie(F12 → Network → Copy Cookie) -2. 配置环境变量: -```bash -echo 'export BILIBILI_COOKIE="SESSDATA=xxx; bili_jct=xxx"' >> ~/.kb_env -source ~/.kb_env -``` - -### 错误 3: 深度分析失败 - -**症状:** `success: false` from kb-deep-analyzer - -**处理:** -- **整个流程终止** -- 检查 AI_API_KEY 是否有效 -- 检查 AI_BASE_URL 是否正确 -- 检查模型配额是否用尽 - -### 错误 4: Whisper 模型未下载 - -**症状:** `Model file not found` - -**解决:** -```bash -cd ~/whisper.cpp -./models/download-ggml-model.sh base -``` - ---- - -## 状态管理(断点续传) - -> ⚠️ 此功能需要完成 P3 实现 - -```bash -# 初始化状态 -python3 kb_workflow.py --init-state "[URL]" - -# 查询当前状态 -python3 kb_workflow.py --get-state "[URL]" - -# 推进到下一步 -python3 kb_workflow.py --advance-step "[URL]" "metadata" - -# 记录错误 -python3 kb_workflow.py --record-error "[URL]" "403 Forbidden" - -# 获取恢复指令 -python3 kb_workflow.py --resume "[URL]" -``` - ---- - ## ⚠️ 严格失败处理原则 -1. **深度分析不可跳过**:kb-deep-analyzer 是必须成功的步骤 -2. **失败即终止**:如果深度分析返回 `success: false`,必须立即停止 -3. **禁止降级处理**:不能使用预设模板或简单摘要"假装成功" -4. **每次执行都要使用 AI**:必须有真实的 AI API 调用 +> **深度分析步骤必须成功,否则整个流程失败** + +1. **深度分析不可跳过**:AI 分析是必须成功执行的步骤 +2. **失败即终止**:如果分析返回失败,必须立即停止并汇报 +3. **禁止降级处理**:不能使用预设模板或简单摘要来"假装成功" +4. **每次执行都要使用 AI**:必须有真实的 AI API 调用记录 + +## 辅助命令 + +```bash +# 查重 +python3 kb-workflow/kb_workflow.py --check --url "https://..." + +# 获取目录路径 +python3 kb-workflow/kb_workflow.py --base-path +python3 kb-workflow/kb_workflow.py --metadata +python3 kb-workflow/kb_workflow.py --content +python3 kb-workflow/kb_workflow.py --analyzed + +# 归档分析报告 +python3 kb-workflow/kb_workflow.py --archive-file "/path/to/report.md" +``` + +## 示例 + +``` +用户: 添加到知识库 https://www.bilibili.com/video/BV1xx + +Claude: +✅ 环境变量检查通过 + +◆ 处理中... + → 解析 URL: bilibili 视频 BV1xx + → 获取元数据... + → 下载字幕... + → 深度分析... + +✅ 完成! + +标题: 【教程】如何使用 Python 进行数据分析 +处理阶段: 全部完成 +最终文件: ~/work/zq/30.资源/AI分析/2026-03-15/bilibili_BV1xx.md +``` + +## 技术架构 + +``` +kb-workflow/kb_workflow.py (CLI) + └── kb_pipeline/ (核心管道包) + ├── pipeline.py — Pipeline 编排引擎 + ├── processors/ — 处理器实现 + │ ├── parse.py — URL 解析 + │ ├── download.py — 内容下载 + │ ├── asr.py — 语音识别 + │ └── analyze.py — 深度分析 + └── schemas.py — 数据模型 +``` diff --git a/skills/kb-workflow/kb_workflow.py b/skills/kb-workflow/kb_workflow.py index dc50927..540b0ae 100644 --- a/skills/kb-workflow/kb_workflow.py +++ b/skills/kb-workflow/kb_workflow.py @@ -5,7 +5,7 @@ KB Workflow - Knowledge Base Workflow Orchestrator 知识库工作流辅助工具函数。 -此模块提供查重、文件操作、Git 管理、状态管理等工具函数, +此模块提供查重、文件操作、Git 管理等工具函数, 供主代理在执行 SKILL.md 中定义的 workflow 时调用。 """ @@ -18,46 +18,7 @@ import shutil import re from datetime import datetime from pathlib import Path -from typing import Dict, List, Optional, Any, Tuple - - -# ==================== 状态机定义 ==================== - -# 工作流步骤顺序 -WORKFLOW_STEPS = [ - "init", - "link_parse", - "metadata", - "content", - "whisper", # 可选步骤 - "analyze", - "archive", - "done" -] - -# 每个步骤的必需输出字段 -STEP_OUTPUT_FIELDS = { - "init": [], - "link_parse": ["platform", "content_type", "content_id"], - "metadata": ["title"], - "content": ["filepath"], - "whisper": ["output_files"], - "analyze": ["output_file"], - "archive": ["archive_path"], - "done": [] -} - -# 步骤描述(用于汇报) -STEP_DESCRIPTIONS = { - "init": "初始化", - "link_parse": "链接解析", - "metadata": "元数据提取", - "content": "内容下载", - "whisper": "语音识别", - "analyze": "深度分析", - "archive": "归档", - "done": "完成" -} +from typing import Dict, List, Optional, Any # ==================== 子技能映射 ==================== @@ -332,249 +293,6 @@ def archive_and_git( return result -# ==================== 状态管理 ==================== - -def get_state_file_path(url: str, base_path: Path = None) -> Path: - """获取状态文件路径""" - if base_path is None: - base_path = get_knowledge_base_path() - pending_dir = base_path / "pending" - pending_dir.mkdir(parents=True, exist_ok=True) - - # 从 URL 提取标识符 - # 尝试提取 BV 号或其他 ID - bv_match = re.search(r'BV[a-zA-Z0-9]+', url) - if bv_match: - content_id = bv_match.group() - platform = "bilibili" - else: - # 尝试提取知乎 ID - zhihu_match = re.search(r'zhihu\.com/(?:question|zvideo|p)/(\d+)', url) - if zhihu_match: - content_id = zhihu_match.group(1) - platform = "zhihu" - else: - # 使用 URL hash 作为标识 - import hashlib - content_id = hashlib.md5(url.encode()).hexdigest()[:12] - platform = "unknown" - - return pending_dir / f"{platform}_{content_id}.state.json" - - -def init_state(url: str, base_path: Path = None) -> Dict[str, Any]: - """初始化工作流状态""" - state_file = get_state_file_path(url, base_path) - - # 如果状态文件已存在,返回现有状态 - if state_file.exists(): - with open(state_file, 'r', encoding='utf-8') as f: - return json.load(f) - - # 创建新状态 - now = datetime.now().isoformat() - state = { - "url": url, - "platform": None, - "content_id": None, - "content_type": None, - "current_step": "init", - "completed_steps": [], - "step_results": {}, - "errors": [], - "created_at": now, - "updated_at": now - } - - with open(state_file, 'w', encoding='utf-8') as f: - json.dump(state, f, ensure_ascii=False, indent=2) - - return state - - -def get_state(url: str, base_path: Path = None) -> Dict[str, Any]: - """获取当前工作流状态""" - state_file = get_state_file_path(url, base_path) - - if not state_file.exists(): - return { - "success": False, - "error": "状态文件不存在", - "url": url, - "state_file": str(state_file) - } - - with open(state_file, 'r', encoding='utf-8') as f: - state = json.load(f) - - return { - "success": True, - "state": state, - "state_file": str(state_file) - } - - -def advance_step( - url: str, - step_name: str, - result: Dict[str, Any] = None, - base_path: Path = None -) -> Dict[str, Any]: - """推进到下一步并记录结果""" - state_file = get_state_file_path(url, base_path) - - if not state_file.exists(): - return { - "success": False, - "error": "状态文件不存在,请先执行 --init-state" - } - - with open(state_file, 'r', encoding='utf-8') as f: - state = json.load(f) - - # 验证步骤名称 - if step_name not in WORKFLOW_STEPS: - return { - "success": False, - "error": f"无效的步骤名称: {step_name}", - "valid_steps": WORKFLOW_STEPS - } - - # 获取当前步骤索引 - try: - current_idx = WORKFLOW_STEPS.index(state["current_step"]) - new_idx = WORKFLOW_STEPS.index(step_name) - except ValueError: - return { - "success": False, - "error": f"步骤索引错误" - } - - # 更新状态 - if step_name != state["current_step"]: - # 标记当前步骤为完成 - if state["current_step"] not in state["completed_steps"]: - state["completed_steps"].append(state["current_step"]) - - state["current_step"] = step_name - state["updated_at"] = datetime.now().isoformat() - - # 记录步骤结果 - if result: - state["step_results"][step_name] = result - - # 提取平台和 ID 信息(从 link_parse 步骤) - if step_name == "link_parse" and result.get("success"): - state["platform"] = result.get("platform") - state["content_id"] = result.get("content_id") - state["content_type"] = result.get("type") - - # 保存状态 - with open(state_file, 'w', encoding='utf-8') as f: - json.dump(state, f, ensure_ascii=False, indent=2) - - return { - "success": True, - "current_step": step_name, - "completed_steps": state["completed_steps"], - "state_file": str(state_file) - } - - -def record_error( - url: str, - error_msg: str, - step: str = None, - base_path: Path = None -) -> Dict[str, Any]: - """记录错误""" - state_file = get_state_file_path(url, base_path) - - if not state_file.exists(): - return { - "success": False, - "error": "状态文件不存在,请先执行 --init-state" - } - - with open(state_file, 'r', encoding='utf-8') as f: - state = json.load(f) - - # 记录错误 - error_entry = { - "step": step or state["current_step"], - "error": error_msg, - "timestamp": datetime.now().isoformat() - } - state["errors"].append(error_entry) - state["updated_at"] = datetime.now().isoformat() - - # 保存状态 - with open(state_file, 'w', encoding='utf-8') as f: - json.dump(state, f, ensure_ascii=False, indent=2) - - return { - "success": True, - "error_recorded": error_entry, - "total_errors": len(state["errors"]) - } - - -def get_resume_info(url: str, base_path: Path = None) -> Dict[str, Any]: - """获取恢复执行的指令""" - state_file = get_state_file_path(url, base_path) - - if not state_file.exists(): - return { - "success": False, - "error": "状态文件不存在", - "suggestion": "请使用 --init-state 初始化工作流" - } - - with open(state_file, 'r', encoding='utf-8') as f: - state = json.load(f) - - current_step = state["current_step"] - step_desc = STEP_DESCRIPTIONS.get(current_step, current_step) - - # 检查是否有错误 - if state["errors"]: - last_error = state["errors"][-1] - return { - "success": True, - "status": "error", - "current_step": current_step, - "step_description": step_desc, - "last_error": last_error, - "completed_steps": state["completed_steps"], - "suggestion": f"请先解决 {last_error['step']} 步骤的错误: {last_error['error']}" - } - - # 检查是否已完成 - if current_step == "done": - return { - "success": True, - "status": "completed", - "current_step": "done", - "step_description": "已完成", - "completed_steps": state["completed_steps"], - "step_results": state["step_results"] - } - - # 返回下一步指令 - return { - "success": True, - "status": "in_progress", - "current_step": current_step, - "step_description": step_desc, - "completed_steps": state["completed_steps"], - "next_action": f"继续执行步骤: {step_desc}", - "platform": state.get("platform"), - "content_id": state.get("content_id"), - "content_type": state.get("content_type"), - "step_results": state.get("step_results", {}) - } - - def generate_summary(url: str, stages: List[Dict], final_file: str, archive_result: Dict = None) -> str: """生成处理完成汇报""" # 提取视频标题(如果有) @@ -607,6 +325,83 @@ def generate_summary(url: str, stages: List[Dict], final_file: str, archive_resu return summary +# ==================== CLI Process Command ==================== + +def process_command( + url: str, + output_dir: Optional[str] = None, + skip_completed: bool = True +) -> Dict[str, Any]: + """Execute full pipeline for a URL + + Args: + url: URL to process + output_dir: Optional output directory for content + skip_completed: Skip already completed steps (default True) + + Returns: + Dictionary with success status, content_dir, and results + """ + import asyncio + + # Add project root to path for kb_pipeline imports + project_root = Path(__file__).parent.parent + if str(project_root) not in sys.path: + sys.path.insert(0, str(project_root)) + + try: + from kb_pipeline.pipeline import Pipeline + from kb_pipeline.processors import ParseProcessor, DownloadProcessor, ASRProcessor, AnalyzeProcessor + from kb_pipeline.schemas import PipelineConfig + + async def run_pipeline(): + # Determine output directory + out_dir = Path(output_dir) if output_dir else Path.cwd() + + # Create processors + processors = [ + ParseProcessor(), + DownloadProcessor(), + ASRProcessor(), + AnalyzeProcessor(), + ] + + # Create pipeline config + config = PipelineConfig( + steps=["parse", "download", "asr", "analyze"], + output_dir=out_dir, + skip_completed=skip_completed, + ) + + # Create and run pipeline + pipeline = Pipeline( + processors=processors, + config=config, + output_dir=out_dir, + ) + + result = await pipeline.run(url) + return result + + # Run async pipeline + result = asyncio.run(run_pipeline()) + + return { + "success": result.success, + "error": result.error_message, + "content_dir": str(result.content_dir) if result.content_dir else None, + "results": result.results, + } + + except Exception as e: + return { + "success": False, + "error": str(e), + "content_dir": None, + "results": {}, + } + + # ==================== CLI ==================== def main(): @@ -618,117 +413,96 @@ def main(): 使用示例: # 查重 python kb_workflow.py --check --url "https://www.bilibili.com/video/BVxxx" - + # 归档 - python kb_workflow.py --archive-file "/path/to/analyzed.md" - - # 状态管理 - python kb_workflow.py --init-state --url "https://..." - python kb_workflow.py --get-state --url "https://..." - python kb_workflow.py --advance-step --url "https://..." --step "metadata" --result '{"success":true}' - python kb_workflow.py --record-error --url "https://..." --error-msg "403 Forbidden" - python kb_workflow.py --resume --url "https://..." + python kb_workflow.py --archive "/path/to/analyzed.md" + + # 处理URL (通过完整管道) + python kb_workflow.py process "https://www.bilibili.com/video/BVxxx" """ ) - - # 基础参数 - parser.add_argument('--url', type=str, help='URL 地址') - parser.add_argument('--base-path', type=str, help='知识库根目录') - - # 查重和归档 + + # Create subparsers for commands + subparsers = parser.add_subparsers(dest='command', help='Available commands') + + # Process subcommand + process_parser = subparsers.add_parser('process', help='Process URL through full pipeline') + process_parser.add_argument('url', type=str, help='URL to process') + process_parser.add_argument('--output-dir', '-o', type=str, help='Output directory for content') + process_parser.add_argument('--skip-completed', action='store_true', default=True, + help='Skip completed steps (default: True)') + process_parser.add_argument('--no-skip', action='store_false', dest='skip_completed', + help='Re-run all steps') + + # Legacy arguments (for backward compatibility) parser.add_argument('--check', action='store_true', help='查重') + parser.add_argument('--url', type=str, help='要检查的URL') parser.add_argument('--archive-file', type=str, help='归档的文件路径') - - # 目录路径查询 - parser.add_argument('--pending', action='store_true', help='获取 URL 解析目录') + parser.add_argument('--base-path', type=str, help='获取知识库根目录') + + parser.add_argument('--pending', action='store_true', help='获取url解析目录') parser.add_argument('--metadata', action='store_true', help='获取元数据目录') parser.add_argument('--content', action='store_true', help='获取内容目录') - parser.add_argument('--content_downloads', action='store_true', help='获取内容下载目录') + parser.add_argument('--content_downloads', action='store_true', help='获取主内容下载目录') parser.add_argument('--analyzed', action='store_true', help='获取深度分析目录') parser.add_argument('--archive_dir', action='store_true', help='获取归档目录') parser.add_argument('--archive_subscriptions', action='store_true', help='获取订阅信息目录') - parser.add_argument('--extract_platform', type=str, help='从文件名提取平台名称') - - # 状态管理 - parser.add_argument('--init-state', action='store_true', help='初始化工作流状态') - parser.add_argument('--get-state', action='store_true', help='获取当前状态') - parser.add_argument('--advance-step', action='store_true', help='推进到下一步') - parser.add_argument('--step', type=str, help='步骤名称') - parser.add_argument('--result', type=str, help='步骤结果(JSON 字符串)') - parser.add_argument('--record-error', action='store_true', help='记录错误') - parser.add_argument('--error-msg', type=str, help='错误信息') - parser.add_argument('--resume', action='store_true', help='获取恢复执行信息') - + parser.add_argument('--extract_platform', type=str, help='要提取平台名称的文件名') args = parser.parse_args() - + base_path = Path(args.base_path) if args.base_path else None dirs = ensure_directories(base_path) - - # 查重 + + # Handle process subcommand + if args.command == 'process': + result = process_command( + url=args.url, + output_dir=args.output_dir, + skip_completed=args.skip_completed + ) + print(json.dumps(result, ensure_ascii=False, indent=2)) + return + + # Legacy argument handling if args.check and args.url: result = check_duplicate(base_path, args.url) print(json.dumps(result, ensure_ascii=False, indent=2)) - - # 归档 + elif args.archive_file: result = archive_and_git(args.archive_file, base_path) print(json.dumps(result, ensure_ascii=False, indent=2)) - - # 目录路径查询 + elif args.pending: print(json.dumps({"path": str(dirs["pending"])}, ensure_ascii=False, indent=2)) + elif args.metadata: print(json.dumps({"path": str(dirs["metadata"])}, ensure_ascii=False, indent=2)) + elif args.content: print(json.dumps({"path": str(dirs["content"])}, ensure_ascii=False, indent=2)) + elif args.content_downloads: print(json.dumps({"path": str(dirs["content_downloads"])}, ensure_ascii=False, indent=2)) + elif args.analyzed: print(json.dumps({"path": str(dirs["analyzed"])}, ensure_ascii=False, indent=2)) + elif args.archive_dir: print(json.dumps({"path": str(get_archive_path())}, ensure_ascii=False, indent=2)) + elif args.archive_subscriptions: print(json.dumps({"path": str(dirs["archive_subscriptions"])}, ensure_ascii=False, indent=2)) + elif args.extract_platform: platform = extract_platform(args.extract_platform) print(json.dumps({"platform": platform}, ensure_ascii=False, indent=2)) + elif args.base_path: print(json.dumps({"path": str(dirs["base"])}, ensure_ascii=False, indent=2)) - - # 状态管理 - elif args.init_state and args.url: - result = init_state(args.url, base_path) - print(json.dumps({"success": True, "state": result}, ensure_ascii=False, indent=2)) - - elif args.get_state and args.url: - result = get_state(args.url, base_path) - print(json.dumps(result, ensure_ascii=False, indent=2)) - - elif args.advance_step and args.url and args.step: - result_data = None - if args.result: - try: - result_data = json.loads(args.result) - except json.JSONDecodeError: - result_data = {"raw": args.result} - result = advance_step(args.url, args.step, result_data, base_path) - print(json.dumps(result, ensure_ascii=False, indent=2)) - - elif args.record_error and args.url and args.error_msg: - result = record_error(args.url, args.error_msg, args.step, base_path) - print(json.dumps(result, ensure_ascii=False, indent=2)) - - elif args.resume and args.url: - result = get_resume_info(args.url, base_path) - print(json.dumps(result, ensure_ascii=False, indent=2)) - + else: parser.print_help() if __name__ == '__main__': main() - - -if __name__ == '__main__': - main() diff --git a/skills/kb-zhihu-content/SKILL.md b/skills/kb-zhihu-content/SKILL.md index 8dcf5ab..9009c3e 100644 --- a/skills/kb-zhihu-content/SKILL.md +++ b/skills/kb-zhihu-content/SKILL.md @@ -1,154 +1,86 @@ ---- -name: kb-zhihu-content -description: 知乎内容下载 - 下载视频、提取文章内容 ---- - # KB Zhihu Content Skill -**kb-zhihu-content** - 下载知乎视频、提取文章内容。 +**kb-zhihu-content** - Download Zhihu videos and extract content. -## 什么时候使用 +## Features -- kb-workflow 步骤 3a:下载知乎视频 -- kb-workflow 步骤 3b:提取知乎专栏文章内容 +- Video download using **yt-dlp** +- Subtitle extraction (returns no subtitle, triggers Whisper) +- **Read article content from MediaCrawler data** (NEW!) +- Supports `ZHIHU_COOKIE` environment variable -## 功能 +## Environment Variables -- 视频下载(使用 yt-dlp) -- 从 MediaCrawler 数据读取文章内容 -- 支持 `ZHIHU_COOKIE` 环境变量 +| Variable | Required | Description | +|----------|----------|-------------| +| `ZHIHU_COOKIE` | No | 知乎登录 Cookie (for member-only videos) | -## 环境变量 - -| 变量名 | 必需 | 说明 | -|--------|------|------| -| `ZHIHU_COOKIE` | 否 | 知乎登录 Cookie | - -## 命令 +## Commands ```bash -# 下载视频 -python3 zhihu_content.py --id "12345678" --type video --output "/path/to/downloads/" +# Download video +python zhihu_content.py --id "12345678" --type video --output "/path/to/downloads/" -# 从 MediaCrawler 读取文章内容 -python3 zhihu_content.py --type article-from-media \ +# Extract subtitle (returns no subtitle, triggers Whisper) +python zhihu_content.py --id "12345678" --type subtitle --output "/path/to/subtitles/" + +# 从 MediaCrawler 读取文章内容 (⚡ NEW!) +python zhihu_content.py --type article-from-media --input "~/work/MediaCrawler/data/zhihu/json/detail_contents_2026-02-27.json" --output "~/work/knowledge-base/data/zhihu/" +``` + +## MediaCrawler 数据读取 + +**新功能**:从 MediaCrawler 爬取的数据中提取知乎文章内容 + +### 使用方法 + +```bash +# 从 MediaCrawler JSON 文件读取文章内容 +python zhihu_content.py --type article-from-media \ --input "~/work/MediaCrawler/data/zhihu/json/detail_contents_2026-02-27.json" \ --output "~/work/knowledge-base/data/zhihu/" -# 自动查找最新 MediaCrawler 数据 -python3 zhihu_content.py --type article-from-media \ +# 查找最新的爬取数据 +python zhihu_content.py --type article-from-media \ --output "~/work/knowledge-base/data/zhihu/" ``` -## 输出格式 Schema +### 参数说明 -### 必需字段 +| 参数 | 说明 | +|------|------| +| `--type article-from-media` | 从 MediaCrawler 数据读取 | +| `--input` | MediaCrawler 输出文件路径(可选,不指定则自动查找最新) | +| `--output` | 输出目录 | -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否成功 | -| `type` | string | 操作类型(video/article) | - -### 视频下载特有字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `filepath` | string | 视频文件路径 | -| `filename` | string | 视频文件名 | - -### 文章提取特有字段 - -| 字段 | 类型 | 说明 | -|------|------|------| -| `filepath` | string | 文章文件路径 | -| `filename` | string | 文章文件名 | -| `content_length` | number | 内容长度 | - -## 成功示例 - -### 视频下载 - -```json -{ - "success": true, - "type": "video", - "filename": "zhihu_12345678.mp4", - "filepath": "content/downloads/zhihu_12345678.mp4", - "message": "下载完成" -} -``` - -### 文章内容提取 +### 输出格式 ```json { "success": true, "type": "article", "filename": "zhihu_article_如何高效的爬取微信公众号.md", - "filepath": "~/work/knowledge-base/data/zhihu/zhihu_article_如何高效的爬取微信公众号.md", - "content_length": 4563, + "filepath": "/home/xxx/work/knowledge-base/data/zhihu/zhihu_article_如何高效的爬取微信公众号.md", "message": "文章内容已导出" } ``` -## 错误示例 +## 原有功能 -### 视频下载失败 +### Video Download -```json -{ - "success": false, - "type": "video", - "error": "视频不存在或无法访问", - "suggestion": "请检查视频 ID 是否正确" -} -``` +Video download uses **yt-dlp**: +1. Parses `ZHIHU_COOKIE` environment variable (optional) +2. Creates temporary Netscape-format cookie file +3. Runs `yt-dlp -f best -o ` +4. Cleans up temporary file -### MediaCrawler 数据未找到 +**Note**: 知乎视频通常没有官方字幕,将自动触发 Whisper 语音识别 -```json -{ - "success": false, - "type": "article-from-media", - "error": "未找到 MediaCrawler 数据文件", - "suggestion": "请先运行 MediaCrawler 爬取文章" -} -``` - -### 网络错误 - -```json -{ - "success": false, - "error": "网络请求失败: Connection timeout" -} -``` - -## 安装 +## Installation ```bash -cp -r kb-zhihu-content/ ~/.openclaw/skills/ +# Already included in kb-skills repo +# Ensure yt-dlp is installed pip install yt-dlp aiohttp ``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 3a:下载知乎视频 -python3 ~/.openclaw/skills/kb-zhihu-content/zhihu_content.py \ - --id "12345678" --type video \ - --output "content/downloads/" - -# 注意:知乎视频没有官方字幕,下载后需要进入 Whisper 步骤 - -# 步骤 3b:提取专栏文章(如果有 MediaCrawler 数据) -python3 ~/.openclaw/skills/kb-zhihu-content/zhihu_content.py \ - --type article-from-media \ - --output "content/" -``` - -## 注意事项 - -- **知乎视频没有官方字幕**:下载后必须进入 Whisper 步骤 -- MediaCrawler 需要单独安装和运行 -- 部分视频可能需要登录才能下载 diff --git a/skills/kb-zhihu-metadata/SKILL.md b/skills/kb-zhihu-metadata/SKILL.md index b4a01b0..789e29c 100644 --- a/skills/kb-zhihu-metadata/SKILL.md +++ b/skills/kb-zhihu-metadata/SKILL.md @@ -1,207 +1,101 @@ ---- -name: kb-zhihu-metadata -description: 知乎元数据提取 - 获取问题/回答/专栏/视频的详细信息 ---- - # KB Zhihu Metadata Skill -**kb-zhihu-metadata** - 提取知乎问题、回答、用户、专栏的元数据。 +**kb-zhihu-metadata** - Extract Zhihu question/answer/user metadata and crawl articles. -## 什么时候使用 +## Features -- kb-workflow 步骤 2:获取知乎内容的元数据 -- 需要问题标题、回答者、文章标题等信息 - -## 功能 - -- 问题元数据提取 -- 回答元数据提取 -- 用户信息提取 -- 专栏文章爬取(使用 MediaCrawler) -- 支持 `ZHIHU_COOKIE` 环境变量 +- Question metadata extraction +- Answer metadata extraction +- User information extraction +- **Article crawling using MediaCrawler** (NEW!) +- JSON output format +- Markdown conversion support +- **Cookie 支持**:可配置 ZHIHU_COOKIE 访问需要登录的内容 ## 环境变量 -| 变量名 | 必需 | 说明 | +| 变量名 | 用途 | 必需 | |--------|------|------| -| `ZHIHU_COOKIE` | 推荐 | 知乎登录 Cookie(访问专栏等需要) | +| `ZHIHU_COOKIE` | 知乎登录 Cookie | 推荐(访问专栏等需要) | -**获取 Cookie:** +**获取 ZHIHU_COOKIE**: 1. 登录知乎网页版 -2. F12 → Application → Cookies → zhihu.com +2. 打开开发者工具 (F12) → Application → Cookies → zhihu.com 3. 复制 Cookie 字符串 ```bash -export ZHIHU_COOKIE="你的知乎Cookie" +# 添加到 ~/.kb_env +echo 'export ZHIHU_COOKIE="你的知乎Cookie"' >> ~/.kb_env +source ~/.kb_env ``` -## 命令 +## Commands ```bash -# 问题元数据 -python3 zhihu_metadata.py --id "266309957" --type question +# Question metadata +python zhihu_metadata.py --id "266309957" --type question -# 回答元数据 -python3 zhihu_metadata.py --id "2003427891925509507" --type answer +# Answer metadata +python zhihu_metadata.py --id "2003427891925509507" --type answer -# 知乎视频 -python3 zhihu_metadata.py --id "123456789" --type zvideo - -# 专栏文章爬取(使用 MediaCrawler) -python3 zhihu_article_crawler.py --url "https://zhuanlan.zhihu.com/p/1894054073625461813" --output "~/work/knowledge-base/data/zhihu/" +# 专栏文章爬取 (使用 MediaCrawler) ⚡ NEW! +python zhihu_article_crawler.py --url "https://zhuanlan.zhihu.com/p/1894054073625461813" --output "~/work/knowledge-base/data/zhihu/" ``` -## 输出格式 Schema +## MediaCrawler 爬取文章 -### 必需字段 +**新功能**:使用 MediaCrawler 爬取知乎专栏文章 -| 字段 | 类型 | 说明 | -|------|------|------| -| `success` | boolean | 是否提取成功 | -| `platform` | string | 固定为 `zhihu` | -| `content_id` | string | 内容 ID | -| `content_type` | string | 内容类型 | -| `title` | string | 标题 | +### 环境要求 -### 可选字段 +MediaCrawler 已安装在 `~/work/MediaCrawler` -| 字段 | 类型 | 说明 | -|------|------|------| -| `author` | string | 作者名称 | -| `excerpt` | string | 摘要 | -| `stats` | object | 统计数据 | -| `output_file` | string | 输出文件路径 | -| `error` | string | 错误信息 | +### 使用方法 -## 成功示例 +```bash +# 爬取单篇文章 +python zhihu_article_crawler.py --url "https://zhuanlan.zhihu.com/p/XXXXX" -### 问题元数据 +# 指定输出目录 +python zhihu_article_crawler.py --url "https://zhuanlan.zhihu.com/p/XXXXX" --output "/path/to/output/" + +# 输出示例 +{ + "success": true, + "type": "article", + "title": "如何高效的爬取微信公众号", + "filepath": "/home/xxx/work/knowledge-base/data/zhihu/zhihu_article_如何高效的爬取微信公众号.md", + "content_length": 4563, + "message": "爬取成功: 如何高效的爬取微信公众号" +} +``` + +### 工作原理 + +1. 调用 MediaCrawler 爬取文章 +2. 从 JSON 输出中提取内容 +3. 转换为 Markdown 格式(带 frontmatter) +4. 保存到指定目录 + +## Output ```json { "success": true, - "platform": "zhihu", - "content_type": "question", - "content_id": "266309957", - "title": "问题标题", - "excerpt": "问题描述...", - "stats": { + "data": { + "platform": "zhihu", + "type": "question", + "id": "266309957", + "title": "问题标题", + "author": "作者名字", "answer_count": 50, - "follower_count": 1000, - "view_count": 50000 - }, - "output_file": "metadata/zhihu_266309957.meta.json" + "followers": 1000 + } } ``` -### 回答元数据 - -```json -{ - "success": true, - "platform": "zhihu", - "content_type": "answer", - "content_id": "2003427891925509507", - "title": "问题标题(回答所属问题)", - "author": "回答者名字", - "excerpt": "回答摘要...", - "stats": { - "voteup_count": 1000, - "comment_count": 50 - }, - "output_file": "metadata/zhihu_2003427891925509507.meta.json" -} -``` - -### 专栏文章 - -```json -{ - "success": true, - "platform": "zhihu", - "content_type": "zhuanlan", - "content_id": "1894054073625461813", - "title": "文章标题", - "author": "作者名字", - "excerpt": "文章摘要...", - "output_file": "metadata/zhihu_1894054073625461813.meta.json" -} -``` - -### 知乎视频 - -```json -{ - "success": true, - "platform": "zhihu", - "content_type": "zvideo", - "content_id": "123456789", - "title": "视频标题", - "author": "作者名字", - "duration": "10:30", - "output_file": "metadata/zhihu_123456789.meta.json" -} -``` - -## 错误示例 - -### 内容不存在 - -```json -{ - "success": false, - "platform": "zhihu", - "content_id": "invalid_id", - "content_type": "question", - "error": "问题不存在或已被删除" -} -``` - -### 需要登录 - -```json -{ - "success": false, - "platform": "zhihu", - "content_id": "1894054073625461813", - "content_type": "zhuanlan", - "error": "需要登录才能访问", - "suggestion": "请配置 ZHIHU_COOKIE 环境变量" -} -``` - -### 网络错误 - -```json -{ - "success": false, - "error": "网络请求失败: Connection timeout" -} -``` - -## 安装 +## Installation ```bash -cp -r kb-zhihu-metadata/ ~/.openclaw/skills/ -pip install httpx +cp -r kb-zhihu-metadata/ ~/skills/ ``` - -## 在 kb-workflow 中的使用 - -```bash -# 步骤 2:元数据提取(知乎问题) -python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \ - --id "266309957" --type question \ - --output "metadata/zhihu_266309957.meta.json" - -# 步骤 2:元数据提取(知乎视频) -python3 ~/.openclaw/skills/kb-zhihu-metadata/zhihu_metadata.py \ - --id "123456789" --type zvideo \ - --output "metadata/zhihu_123456789.meta.json" -``` - -## 注意事项 - -- 专栏文章可能需要登录才能访问 -- MediaCrawler 需要单独安装:`~/work/MediaCrawler` -- 部分内容可能有访问限制 diff --git a/skills/kb-zhihu-metadata/__pycache__/markdown_converter.cpython-312.pyc b/skills/kb-zhihu-metadata/__pycache__/markdown_converter.cpython-312.pyc deleted file mode 100644 index 46686f6..0000000 Binary files a/skills/kb-zhihu-metadata/__pycache__/markdown_converter.cpython-312.pyc and /dev/null differ diff --git a/skills/kb-zhihu-metadata/__pycache__/zhihu_extractor.cpython-312.pyc b/skills/kb-zhihu-metadata/__pycache__/zhihu_extractor.cpython-312.pyc deleted file mode 100644 index debca46..0000000 Binary files a/skills/kb-zhihu-metadata/__pycache__/zhihu_extractor.cpython-312.pyc and /dev/null differ