自动同步: 2026-03-15 02:10

This commit is contained in:
2026-03-15 02:10:07 +08:00
parent c8c4b780c8
commit b1476136aa
31 changed files with 1119 additions and 2646 deletions
+11 -65
View File
@@ -347,8 +347,8 @@
"memoryFlushCompactionCount": 0 "memoryFlushCompactionCount": 0
}, },
"agent:dev-assist:main": { "agent:dev-assist:main": {
"sessionId": "b5c67eb9-7916-47dd-9491-4832eab53d10", "sessionId": "60601381-862d-454d-9c27-2867f00a71d1",
"updatedAt": 1773132090440, "updatedAt": 1773508835390,
"systemSent": true, "systemSent": true,
"abortedLastRun": false, "abortedLastRun": false,
"chatType": "direct", "chatType": "direct",
@@ -369,7 +369,7 @@
"to": "user:ou_302b162eb824d405718845441a32d9cf", "to": "user:ou_302b162eb824d405718845441a32d9cf",
"accountId": "feishu-dev" "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, "compactionCount": 0,
"skillsSnapshot": { "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>", "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
@@ -410,8 +410,8 @@
"model": "glm-5", "model": "glm-5",
"systemPromptReport": { "systemPromptReport": {
"source": "run", "source": "run",
"generatedAt": 1773132050946, "generatedAt": 1773508824996,
"sessionId": "b5c67eb9-7916-47dd-9491-4832eab53d10", "sessionId": "60601381-862d-454d-9c27-2867f00a71d1",
"sessionKey": "agent:dev-assist:main", "sessionKey": "agent:dev-assist:main",
"provider": "zhipu", "provider": "zhipu",
"model": "glm-5", "model": "glm-5",
@@ -423,8 +423,8 @@
"sandboxed": false "sandboxed": false
}, },
"systemPrompt": { "systemPrompt": {
"chars": 32692, "chars": 26851,
"projectContextChars": 19802, "projectContextChars": 13961,
"nonProjectContextChars": 12890 "nonProjectContextChars": 12890
}, },
"injectedWorkspaceFiles": [ "injectedWorkspaceFiles": [
@@ -492,60 +492,6 @@
"injectedChars": 18, "injectedChars": 18,
"truncated": false "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", "path": "SELF_IMPROVEMENT_REMINDER.md",
"rawChars": 616, "rawChars": 616,
@@ -777,12 +723,12 @@
] ]
} }
}, },
"cacheRead": 17472, "cacheRead": 11392,
"cacheWrite": 0, "cacheWrite": 0,
"totalTokensFresh": true, "totalTokensFresh": true,
"contextTokens": 200000, "contextTokens": 200000,
"inputTokens": 4722, "inputTokens": 5334,
"outputTokens": 1147, "outputTokens": 344,
"totalTokens": 22194 "totalTokens": 16726
} }
} }
+131 -126
View File
@@ -1,7 +1,7 @@
{ {
"agent:haonan:main": { "agent:haonan:main": {
"sessionId": "624cbf67-7ab7-4df9-968d-4a63529b9111", "sessionId": "40e80fbb-07c8-440d-a1d4-1e876b86b82d",
"updatedAt": 1773377664001, "updatedAt": 1773508722585,
"systemSent": true, "systemSent": true,
"skillsSnapshot": { "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>", "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
@@ -59,11 +59,11 @@
"to": "user:ou_be83febac9ee2afaa343c642bc697c48", "to": "user:ou_be83febac9ee2afaa343c642bc697c48",
"accountId": "feishu-pm" "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": { "systemPromptReport": {
"source": "run", "source": "run",
"generatedAt": 1773377656536, "generatedAt": 1773508545805,
"sessionId": "624cbf67-7ab7-4df9-968d-4a63529b9111", "sessionId": "40e80fbb-07c8-440d-a1d4-1e876b86b82d",
"sessionKey": "agent:haonan:main", "sessionKey": "agent:haonan:main",
"provider": "zhipu", "provider": "zhipu",
"model": "glm-5", "model": "glm-5",
@@ -75,8 +75,8 @@
"sandboxed": false "sandboxed": false
}, },
"systemPrompt": { "systemPrompt": {
"chars": 28195, "chars": 29493,
"projectContextChars": 15193, "projectContextChars": 16491,
"nonProjectContextChars": 13002 "nonProjectContextChars": 13002
}, },
"injectedWorkspaceFiles": [ "injectedWorkspaceFiles": [
@@ -144,6 +144,18 @@
"injectedChars": 1168, "injectedChars": 1168,
"truncated": false "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", "path": "SELF_IMPROVEMENT_REMINDER.md",
"rawChars": 616, "rawChars": 616,
@@ -379,12 +391,12 @@
"totalTokensFresh": true, "totalTokensFresh": true,
"lastHeartbeatText": "已在飞书向蒋先生发送日历同步提醒!✅", "lastHeartbeatText": "已在飞书向蒋先生发送日历同步提醒!✅",
"lastHeartbeatSentAt": 1772924419184, "lastHeartbeatSentAt": 1772924419184,
"cacheRead": 25472, "cacheRead": 29760,
"cacheWrite": 0, "cacheWrite": 0,
"contextTokens": 200000, "contextTokens": 200000,
"inputTokens": 12782, "inputTokens": 13411,
"outputTokens": 123, "outputTokens": 1288,
"totalTokens": 25768 "totalTokens": 30249
}, },
"agent:haonan:wecom:dm:zhangqing": { "agent:haonan:wecom:dm:zhangqing": {
"origin": { "origin": {
@@ -715,8 +727,8 @@
"memoryFlushCompactionCount": 0 "memoryFlushCompactionCount": 0
}, },
"agent:haonan:cron:41396aeb-6e3a-47b2-9bd3-9156a348c1dc": { "agent:haonan:cron:41396aeb-6e3a-47b2-9bd3-9156a348c1dc": {
"sessionId": "10740f43-38c1-4a7c-acf0-7da04f20d1e9", "sessionId": "7c1a6bfd-b5b6-4ac5-98f3-6a73aec18a8f",
"updatedAt": 1773424800009, "updatedAt": 1773511200009,
"systemSent": true, "systemSent": true,
"model": "glm-5", "model": "glm-5",
"contextTokens": 200000, "contextTokens": 200000,
@@ -757,11 +769,11 @@
"version": 0 "version": 0
}, },
"modelProvider": "zhipu", "modelProvider": "zhipu",
"inputTokens": 11105, "inputTokens": 4500,
"outputTokens": 336, "outputTokens": 194,
"totalTokens": 17181, "totalTokens": 16577,
"totalTokensFresh": true, "totalTokensFresh": true,
"cacheRead": 56128, "cacheRead": 28544,
"cacheWrite": 0 "cacheWrite": 0
}, },
"agent:haonan:cron:f03b184f-5f1d-4093-ae1b-fc9fe0b59eef": { "agent:haonan:cron:f03b184f-5f1d-4093-ae1b-fc9fe0b59eef": {
@@ -861,8 +873,8 @@
"cacheWrite": 0 "cacheWrite": 0
}, },
"agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc": { "agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc": {
"sessionId": "8b634542-6d0e-4fa3-b794-d784174d530b", "sessionId": "b5ab88d0-f6d3-4b73-8d96-e6a58f5e85e4",
"updatedAt": 1773425400005, "updatedAt": 1773511800007,
"systemSent": true, "systemSent": true,
"label": "Cron: openclaw-git-sync", "label": "Cron: openclaw-git-sync",
"skillsSnapshot": { "skillsSnapshot": {
@@ -910,113 +922,6 @@
"cacheRead": 32768, "cacheRead": 32768,
"cacheWrite": 0 "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
"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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
"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": { "agent:haonan:cron:aa4d2de9-79be-4262-83ee-af8824793bfc:run:8b634542-6d0e-4fa3-b794-d784174d530b": {
"sessionId": "8b634542-6d0e-4fa3-b794-d784174d530b", "sessionId": "8b634542-6d0e-4fa3-b794-d784174d530b",
"updatedAt": 1773425400005, "updatedAt": 1773425400005,
@@ -1123,5 +1028,105 @@
"totalTokensFresh": true, "totalTokensFresh": true,
"cacheRead": 384894, "cacheRead": 384894,
"cacheWrite": 0 "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
"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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n <skill>\n <name>clawlist</name>\n <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.</description>\n <location>~/.openclaw/skills/clawlist/SKILL.md</location>\n </skill>\n</available_skills>",
"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
} }
} }
@@ -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 分支)
+11 -23
View File
@@ -1,7 +1,7 @@
{ {
"agent:thinker:main": { "agent:thinker:main": {
"sessionId": "0ec88a33-135f-42a4-bf98-de4d06bfadd5", "sessionId": "41133a8b-b22b-418f-aaeb-ce8a1fd69760",
"updatedAt": 1773377998949, "updatedAt": 1773508159395,
"systemSent": true, "systemSent": true,
"abortedLastRun": false, "abortedLastRun": false,
"chatType": "direct", "chatType": "direct",
@@ -22,7 +22,7 @@
"to": "user:ou_a0f6627b64d2dc8b0236671603d1e47b", "to": "user:ou_a0f6627b64d2dc8b0236671603d1e47b",
"accountId": "feishu-qa" "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, "compactionCount": 0,
"skillsSnapshot": { "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n</available_skills>", "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n</available_skills>",
@@ -51,8 +51,8 @@
"model": "glm-5", "model": "glm-5",
"systemPromptReport": { "systemPromptReport": {
"source": "run", "source": "run",
"generatedAt": 1773377941023, "generatedAt": 1773508155922,
"sessionId": "0ec88a33-135f-42a4-bf98-de4d06bfadd5", "sessionId": "41133a8b-b22b-418f-aaeb-ce8a1fd69760",
"sessionKey": "agent:thinker:main", "sessionKey": "agent:thinker:main",
"provider": "zhipu", "provider": "zhipu",
"model": "glm-5", "model": "glm-5",
@@ -64,8 +64,8 @@
"sandboxed": false "sandboxed": false
}, },
"systemPrompt": { "systemPrompt": {
"chars": 26194, "chars": 24896,
"projectContextChars": 13718, "projectContextChars": 12420,
"nonProjectContextChars": 12476 "nonProjectContextChars": 12476
}, },
"injectedWorkspaceFiles": [ "injectedWorkspaceFiles": [
@@ -125,18 +125,6 @@
"injectedChars": 88, "injectedChars": 88,
"truncated": false "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", "path": "SELF_IMPROVEMENT_REMINDER.md",
"rawChars": 616, "rawChars": 616,
@@ -364,12 +352,12 @@
] ]
} }
}, },
"cacheRead": 28864, "cacheRead": 11072,
"cacheWrite": 0, "cacheWrite": 0,
"totalTokensFresh": true, "totalTokensFresh": true,
"contextTokens": 200000, "contextTokens": 200000,
"inputTokens": 13728, "inputTokens": 5154,
"outputTokens": 1428, "outputTokens": 62,
"totalTokens": 29902 "totalTokens": 16226
} }
} }
+17 -11
View File
@@ -1,7 +1,7 @@
{ {
"agent:ui-designer:main": { "agent:ui-designer:main": {
"sessionId": "c875d391-8f7e-4fd4-92c7-12ead46d10f0", "sessionId": "ff92b555-b242-4e52-a7da-9c8f82ca1c8a",
"updatedAt": 1773108605750, "updatedAt": 1773508884420,
"systemSent": true, "systemSent": true,
"abortedLastRun": false, "abortedLastRun": false,
"chatType": "direct", "chatType": "direct",
@@ -22,7 +22,7 @@
"to": "user:ou_9847ce84b960736c14554730b41e4957", "to": "user:ou_9847ce84b960736c14554730b41e4957",
"accountId": "feishu-art" "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, "compactionCount": 0,
"skillsSnapshot": { "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n</available_skills>", "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<available_skills>\n <skill>\n <name>capability-evolver</name>\n <description>A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.</description>\n <location>~/.openclaw/skills/capability-evolver/SKILL.md</location>\n </skill>\n</available_skills>",
@@ -51,8 +51,8 @@
"model": "glm-5", "model": "glm-5",
"systemPromptReport": { "systemPromptReport": {
"source": "run", "source": "run",
"generatedAt": 1773108589701, "generatedAt": 1773508877788,
"sessionId": "c875d391-8f7e-4fd4-92c7-12ead46d10f0", "sessionId": "ff92b555-b242-4e52-a7da-9c8f82ca1c8a",
"sessionKey": "agent:ui-designer:main", "sessionKey": "agent:ui-designer:main",
"provider": "zhipu", "provider": "zhipu",
"model": "glm-5", "model": "glm-5",
@@ -64,8 +64,8 @@
"sandboxed": false "sandboxed": false
}, },
"systemPrompt": { "systemPrompt": {
"chars": 18658, "chars": 19307,
"projectContextChars": 6173, "projectContextChars": 6822,
"nonProjectContextChars": 12485 "nonProjectContextChars": 12485
}, },
"injectedWorkspaceFiles": [ "injectedWorkspaceFiles": [
@@ -133,6 +133,12 @@
"injectedChars": 594, "injectedChars": 594,
"truncated": false "truncated": false
}, },
{
"path": "SELF_IMPROVEMENT_REMINDER.md",
"rawChars": 616,
"injectedChars": 616,
"truncated": false
},
{ {
"path": "SELF_IMPROVEMENT_REMINDER.md", "path": "SELF_IMPROVEMENT_REMINDER.md",
"rawChars": 616, "rawChars": 616,
@@ -360,13 +366,13 @@
] ]
} }
}, },
"cacheRead": 14912, "cacheRead": 14400,
"cacheWrite": 0, "cacheWrite": 0,
"totalTokensFresh": true, "totalTokensFresh": true,
"contextTokens": 200000, "contextTokens": 200000,
"inputTokens": 3611, "inputTokens": 1169,
"outputTokens": 314, "outputTokens": 135,
"totalTokens": 15537 "totalTokens": 15569
}, },
"agent:ui-designer:cron:78b64c2f-7f91-47ff-9250-d13f546eb21f": { "agent:ui-designer:cron:78b64c2f-7f91-47ff-9250-d13f546eb21f": {
"sessionId": "03e44b46-c707-4a9f-bf3d-1818aafdcde2", "sessionId": "03e44b46-c707-4a9f-bf3d-1818aafdcde2",
+34 -36
View File
@@ -7,7 +7,7 @@
"name": "backup-openclaw-json", "name": "backup-openclaw-json",
"enabled": true, "enabled": true,
"createdAtMs": 1772261581796, "createdAtMs": 1772261581796,
"updatedAtMs": 1773424832005, "updatedAtMs": 1773511209521,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 2 * * *", "expr": "0 2 * * *",
@@ -23,10 +23,10 @@
"mode": "announce" "mode": "announce"
}, },
"state": { "state": {
"nextRunAtMs": 1773511200000, "nextRunAtMs": 1773597600000,
"lastRunAtMs": 1773424800006, "lastRunAtMs": 1773511200006,
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 31999, "lastDurationMs": 9515,
"consecutiveErrors": 0, "consecutiveErrors": 0,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastDelivered": true, "lastDelivered": true,
@@ -59,7 +59,8 @@
"consecutiveErrors": 0, "consecutiveErrors": 0,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"lastDelivered": true "lastDelivered": true,
"runningAtMs": 1773511800004
}, },
"delivery": { "delivery": {
"mode": "announce" "mode": "announce"
@@ -71,7 +72,7 @@
"name": "capability-evolver-daily", "name": "capability-evolver-daily",
"enabled": true, "enabled": true,
"createdAtMs": 1772550743528, "createdAtMs": 1772550743528,
"updatedAtMs": 1773339898227, "updatedAtMs": 1773426600014,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "20 2 * * *", "expr": "20 2 * * *",
@@ -92,16 +93,14 @@
"to": "feishu-pm" "to": "feishu-pm"
}, },
"state": { "state": {
"nextRunAtMs": 1773426000000, "nextRunAtMs": 1773512400000,
"lastRunAtMs": 1773339600009, "lastRunAtMs": 1773426000004,
"lastStatus": "ok", "lastStatus": "error",
"lastDurationMs": 298218, "lastDurationMs": 600010,
"consecutiveErrors": 0, "consecutiveErrors": 1,
"lastRunStatus": "ok", "lastRunStatus": "error",
"lastDeliveryStatus": "not-delivered", "lastDeliveryStatus": "unknown",
"lastDelivered": false, "lastError": "cron: job execution timed out"
"lastDeliveryError": "cron announce delivery failed",
"runningAtMs": 1773426000003
} }
}, },
{ {
@@ -111,7 +110,7 @@
"description": "每天凌晨2:30整理昨天的已完成任务到每日回顾", "description": "每天凌晨2:30整理昨天的已完成任务到每日回顾",
"enabled": true, "enabled": true,
"createdAtMs": 1741484880000, "createdAtMs": 1741484880000,
"updatedAtMs": 1773340211879, "updatedAtMs": 1773426622389,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "30 2 * * *", "expr": "30 2 * * *",
@@ -129,11 +128,11 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773426600000, "nextRunAtMs": 1773513000000,
"lastRunAtMs": 1773340200003, "lastRunAtMs": 1773426602034,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 11876, "lastDurationMs": 20355,
"lastDelivered": true, "lastDelivered": true,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 0 "consecutiveErrors": 0
@@ -145,7 +144,7 @@
"name": "zq_workspace_sync", "name": "zq_workspace_sync",
"enabled": true, "enabled": true,
"createdAtMs": 1772551807455, "createdAtMs": 1772551807455,
"updatedAtMs": 1773340800005, "updatedAtMs": 1773427200007,
"schedule": { "schedule": {
"expr": "40 2 * * *", "expr": "40 2 * * *",
"kind": "cron", "kind": "cron",
@@ -158,8 +157,8 @@
"text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh" "text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh"
}, },
"state": { "state": {
"nextRunAtMs": 1773427200000, "nextRunAtMs": 1773513600000,
"lastRunAtMs": 1773340800004, "lastRunAtMs": 1773427200006,
"lastStatus": "skipped", "lastStatus": "skipped",
"lastDurationMs": 1, "lastDurationMs": 1,
"consecutiveErrors": 0, "consecutiveErrors": 0,
@@ -175,7 +174,7 @@
"description": "每天早上8点整理与各个 AI 代理的对话记录", "description": "每天早上8点整理与各个 AI 代理的对话记录",
"enabled": true, "enabled": true,
"createdAtMs": 1772776369645, "createdAtMs": 1772776369645,
"updatedAtMs": 1773360026590, "updatedAtMs": 1773446431755,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 8 * * *", "expr": "0 8 * * *",
@@ -193,11 +192,11 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773446400000, "nextRunAtMs": 1773532800000,
"lastRunAtMs": 1773360000004, "lastRunAtMs": 1773446400004,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 26586, "lastDurationMs": 31751,
"lastDelivered": true, "lastDelivered": true,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 0 "consecutiveErrors": 0
@@ -210,7 +209,7 @@
"description": "每天7点同步提醒到CalDAV日历", "description": "每天7点同步提醒到CalDAV日历",
"enabled": true, "enabled": true,
"createdAtMs": 1772791528528, "createdAtMs": 1772791528528,
"updatedAtMs": 1773356435243, "updatedAtMs": 1773442830136,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 7 * * *", "expr": "0 7 * * *",
@@ -228,15 +227,14 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773442800000, "nextRunAtMs": 1773529200000,
"lastRunAtMs": 1773356400004, "lastRunAtMs": 1773442800005,
"lastRunStatus": "error", "lastRunStatus": "ok",
"lastStatus": "error", "lastStatus": "ok",
"lastDurationMs": 35239, "lastDurationMs": 30131,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 1, "consecutiveErrors": 0,
"lastDelivered": true, "lastDelivered": true
"lastError": "⚠️ 📝 Edit: in ~/.openclaw/agents/knowledge-base/workspace/memory/heartbeat-state.json (92 chars) failed"
} }
}, },
{ {
+32 -35
View File
@@ -7,7 +7,7 @@
"name": "backup-openclaw-json", "name": "backup-openclaw-json",
"enabled": true, "enabled": true,
"createdAtMs": 1772261581796, "createdAtMs": 1772261581796,
"updatedAtMs": 1773424832005, "updatedAtMs": 1773511209521,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 2 * * *", "expr": "0 2 * * *",
@@ -23,10 +23,10 @@
"mode": "announce" "mode": "announce"
}, },
"state": { "state": {
"nextRunAtMs": 1773511200000, "nextRunAtMs": 1773597600000,
"lastRunAtMs": 1773424800006, "lastRunAtMs": 1773511200006,
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 31999, "lastDurationMs": 9515,
"consecutiveErrors": 0, "consecutiveErrors": 0,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastDelivered": true, "lastDelivered": true,
@@ -71,7 +71,7 @@
"name": "capability-evolver-daily", "name": "capability-evolver-daily",
"enabled": true, "enabled": true,
"createdAtMs": 1772550743528, "createdAtMs": 1772550743528,
"updatedAtMs": 1773339898227, "updatedAtMs": 1773426600014,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "20 2 * * *", "expr": "20 2 * * *",
@@ -92,16 +92,14 @@
"to": "feishu-pm" "to": "feishu-pm"
}, },
"state": { "state": {
"nextRunAtMs": 1773426000000, "nextRunAtMs": 1773512400000,
"lastRunAtMs": 1773339600009, "lastRunAtMs": 1773426000004,
"lastStatus": "ok", "lastStatus": "error",
"lastDurationMs": 298218, "lastDurationMs": 600010,
"consecutiveErrors": 0, "consecutiveErrors": 1,
"lastRunStatus": "ok", "lastRunStatus": "error",
"lastDeliveryStatus": "not-delivered", "lastDeliveryStatus": "unknown",
"lastDelivered": false, "lastError": "cron: job execution timed out"
"lastDeliveryError": "cron announce delivery failed",
"lastError": "cron announce delivery failed"
} }
}, },
{ {
@@ -111,7 +109,7 @@
"description": "每天凌晨2:30整理昨天的已完成任务到每日回顾", "description": "每天凌晨2:30整理昨天的已完成任务到每日回顾",
"enabled": true, "enabled": true,
"createdAtMs": 1741484880000, "createdAtMs": 1741484880000,
"updatedAtMs": 1773340211879, "updatedAtMs": 1773426622389,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "30 2 * * *", "expr": "30 2 * * *",
@@ -129,11 +127,11 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773426600000, "nextRunAtMs": 1773513000000,
"lastRunAtMs": 1773340200003, "lastRunAtMs": 1773426602034,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 11876, "lastDurationMs": 20355,
"lastDelivered": true, "lastDelivered": true,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 0 "consecutiveErrors": 0
@@ -145,7 +143,7 @@
"name": "zq_workspace_sync", "name": "zq_workspace_sync",
"enabled": true, "enabled": true,
"createdAtMs": 1772551807455, "createdAtMs": 1772551807455,
"updatedAtMs": 1773340800005, "updatedAtMs": 1773427200007,
"schedule": { "schedule": {
"expr": "40 2 * * *", "expr": "40 2 * * *",
"kind": "cron", "kind": "cron",
@@ -158,8 +156,8 @@
"text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh" "text": "执行 zq 工作区同步:bash ~/.openclaw/cron/scripts/zq_workspace_sync.sh"
}, },
"state": { "state": {
"nextRunAtMs": 1773427200000, "nextRunAtMs": 1773513600000,
"lastRunAtMs": 1773340800004, "lastRunAtMs": 1773427200006,
"lastStatus": "skipped", "lastStatus": "skipped",
"lastDurationMs": 1, "lastDurationMs": 1,
"consecutiveErrors": 0, "consecutiveErrors": 0,
@@ -175,7 +173,7 @@
"description": "每天早上8点整理与各个 AI 代理的对话记录", "description": "每天早上8点整理与各个 AI 代理的对话记录",
"enabled": true, "enabled": true,
"createdAtMs": 1772776369645, "createdAtMs": 1772776369645,
"updatedAtMs": 1773360026590, "updatedAtMs": 1773446431755,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 8 * * *", "expr": "0 8 * * *",
@@ -193,11 +191,11 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773446400000, "nextRunAtMs": 1773532800000,
"lastRunAtMs": 1773360000004, "lastRunAtMs": 1773446400004,
"lastRunStatus": "ok", "lastRunStatus": "ok",
"lastStatus": "ok", "lastStatus": "ok",
"lastDurationMs": 26586, "lastDurationMs": 31751,
"lastDelivered": true, "lastDelivered": true,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 0 "consecutiveErrors": 0
@@ -210,7 +208,7 @@
"description": "每天7点同步提醒到CalDAV日历", "description": "每天7点同步提醒到CalDAV日历",
"enabled": true, "enabled": true,
"createdAtMs": 1772791528528, "createdAtMs": 1772791528528,
"updatedAtMs": 1773356435243, "updatedAtMs": 1773442830136,
"schedule": { "schedule": {
"kind": "cron", "kind": "cron",
"expr": "0 7 * * *", "expr": "0 7 * * *",
@@ -228,15 +226,14 @@
"channel": "last" "channel": "last"
}, },
"state": { "state": {
"nextRunAtMs": 1773442800000, "nextRunAtMs": 1773529200000,
"lastRunAtMs": 1773356400004, "lastRunAtMs": 1773442800005,
"lastRunStatus": "error", "lastRunStatus": "ok",
"lastStatus": "error", "lastStatus": "ok",
"lastDurationMs": 35239, "lastDurationMs": 30131,
"lastDeliveryStatus": "delivered", "lastDeliveryStatus": "delivered",
"consecutiveErrors": 1, "consecutiveErrors": 0,
"lastDelivered": true, "lastDelivered": true
"lastError": "⚠️ 📝 Edit: in ~/.openclaw/agents/knowledge-base/workspace/memory/heartbeat-state.json (92 chars) failed"
} }
}, },
{ {
@@ -18,7 +18,7 @@
"agentId": "haonan", "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" "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, "retryCount": 4,
"lastAttemptAt": 1773377636671, "lastAttemptAt": 1773508779544,
"lastError": "Request failed with status code 400" "lastError": "Request failed with status code 400"
} }
@@ -15,7 +15,7 @@
"agentId": "haonan", "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`" "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, "retryCount": 4,
"lastAttemptAt": 1773377636492, "lastAttemptAt": 1773508779398,
"lastError": "Request failed with status code 400" "lastError": "Request failed with status code 400"
} }
@@ -15,7 +15,7 @@
"agentId": "haonan", "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" "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, "retryCount": 4,
"lastAttemptAt": 1773377636819, "lastAttemptAt": 1773508779677,
"lastError": "Request failed with status code 400" "lastError": "Request failed with status code 400"
} }
+2 -3
View File
@@ -1,5 +1,4 @@
{ {
"om_x100b55d69df3a888c3e9ed8887d1a4d": 1773022516624, "om_x100b546dc09400acb4a5d0af66ca3c9": 1773508838286,
"om_x100b55d6987ec8bcc1431506934622a": 1773022571945, "om_x100b546dde1c34a4b49a888912755ac": 1773508877713
"om_x100b55c3980b0894c3d7e12aace4404": 1773108589126
} }
+1 -5
View File
@@ -1,7 +1,3 @@
{ {
"om_x100b55de502094a8c44a6f835293240": 1773052399376, "om_x100b546dc3b650a4b2c0139d2df31a7": 1773508824362
"om_x100b55cff24dcca8c3e59d6831d6885": 1773124552700,
"om_x100b55c8c767d084c45fc7eec3f7db8": 1773127835623,
"om_x100b55c9372e9914c3a5744eccfbc0d": 1773131678929,
"om_x100b55c9dfec84a0b34c47ff1aca626": 1773132050877
} }
+4 -16
View File
@@ -1,18 +1,6 @@
{ {
"om_x100b54012fb4b8acb26a1377e572a28": 1773360664219, "om_x100b546d172f3c68c2cea708421b99a": 1773507998614,
"om_x100b5403d6e544bcc451e2afa005879": 1773369731225, "om_x100b546d2b32cca0c329a33c339cfb5": 1773508192506,
"om_x100b5403d32b04b4c2a796466ebaf4f": 1773369823078, "om_x100b546d32de24a8b316c197e60d6e4": 1773508545727,
"om_x100b5403e04f6ca8c29946e1fa6505d": 1773370088740, "om_x100b546dc9d61ca0b33d802bc7615e0": 1773508722267
"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
} }
+1 -17
View File
@@ -1,19 +1,3 @@
{ {
"om_x100b540c33ced0a8c3b77203de384e3": 1773373392794, "om_x100b546d2d6164a4c3fcf5a6d528b40": 1773508155371
"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
} }
+8 -2
View File
@@ -1,4 +1,10 @@
{ {
"om_x100b5403a5fd7090c4db2b553189c54": 1773371059715, "om_x100b546ddd8b14a0b3ddda14ce768c5": 1773508916933,
"om_x100b540c2807c4acc32d196f4b16191": 1773373037365 "om_x100b546dd78c8ca0b31b0314f910115": 1773509012676,
"om_x100b546def8ac8a4b38d921a2bfc8b8": 1773509140955,
"om_x100b546dedb654a4b3ce916a129facf": 1773509176311,
"om_x100b546de975dca0b27e2f24aad0d8c": 1773509244102,
"om_x100b546de53a94a0b38693fbd7e385c": 1773509311993,
"om_x100b546dffaa3cb0b35aef2747ed228": 1773509398933,
"om_x100b546df49c10a0b106d597fd348a3": 1773509541678
} }
+1 -1
View File
@@ -10,7 +10,7 @@
"operator.approvals", "operator.approvals",
"operator.pairing" "operator.pairing"
], ],
"updatedAtMs": 1773425421022 "updatedAtMs": 1773511209007
} }
} }
} }
+1
View File
@@ -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: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: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-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"}
+61 -184
View File
@@ -1,214 +1,91 @@
---
name: kb-bilibili-content
description: B站内容下载 - 下载视频、字幕、专栏文章
---
# KB Bilibili Content Skill # KB Bilibili Content Skill
**kb-bilibili-content** - 下载 B站视频、字幕、专栏文章。 **kb-bilibili-content** - Download Bilibili videos and extract content.
## 什么时候使用 ## Features
- kb-workflow 步骤 3a:下载视频或字幕 - Video download using **yt-dlp** (recommended)
- kb-workflow 步骤 3b:提取专栏文章内容 - Subtitle extraction
- Article content extraction
- Multiple quality options (360P/480P/720P/1080P)
- Supports `BILIBILI_COOKIE` environment variable
## 功能 ## Environment Variables
- 视频下载(使用 yt-dlp) | Variable | Required | Description |
- 字幕提取(官方字幕) |----------|----------|-------------|
- 专栏文章内容提取 | `BILIBILI_COOKIE` | No | B站登录 Cookie (for member-only videos) |
- 多种画质选项(360P/480P/720P/1080P)
- 支持 `BILIBILI_COOKIE` 环境变量(会员视频)
## 环境变量 ## Commands
| 变量名 | 必需 | 说明 |
|--------|------|------|
| `BILIBILI_COOKIE` | 否 | B站登录 Cookie(会员视频需要) |
**获取 Cookie:**
1. 登录 bilibili.com
2. F12 → Network → 刷新页面
3. 从请求头复制 Cookie
```bash ```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"
``` ```
## 命令 ## Output
```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": "无官方字幕,需要下载视频进行语音识别"
}
```
### 视频下载
```json ```json
{ {
"success": true, "success": true,
"type": "video", "type": "video",
"filename": "bilibili_BV1xx411c7mD.mp4", "filename": "video_title.mp4",
"filepath": "content/downloads/bilibili_BV1xx411c7mD.mp4", "filepath": "/path/to/downloads/video_title.mp4",
"quality": "720P", "message": "下载完成: video_title.mp4"
"message": "下载完成"
} }
``` ```
### 专栏文章提取 ## Cookie Setup
```json ### Get Cookie from Browser
{ 1. Login to bilibili.com
"success": true, 2. Press F12 → Network → Refresh page
"type": "article", 3. Copy Cookie from request headers
"filename": "bilibili_cv43780186.txt",
"filepath": "content/bilibili_cv43780186.txt", ### Set Environment Variable
"content_length": 5234, ```bash
"message": "文章内容提取成功" # 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"
``` ```
## 错误示例 ## Installation
### 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)
## 安装
```bash ```bash
cp -r kb-bilibili-content/ ~/.openclaw/skills/ cp -r kb-bilibili-content/ ~/skills/
pip install aiohttp yt-dlp pip install aiohttp playwright
playwright install chromium
``` ```
## 在 kb-workflow 中的使用 ## How It Works
```bash Video download uses **yt-dlp** with Netscape-format cookie file:
# 步骤 3a:首先尝试字幕 1. Parses `BILIBILI_COOKIE` environment variable
python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ 2. Creates temporary Netscape-format cookie file
--id "BV1xx411c7mD" --type subtitle-download \ 3. Runs `yt-dlp --cookies <file> -f <format> -o <output>`
--output "content/downloads/" 4. Cleans up temporary file
# 判断结果: ## Quality Options
# - has_subtitle=true → 跳过 Whisper,直接进入深度分析
# - has_subtitle=false → 下载视频,进入 Whisper 步骤
# 如果无字幕,下载视频 | Quality | ID | Resolution | Notes |
python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ |---------|-----|------------|-------|
--id "BV1xx411c7mD" --type video \ | 16 | 360P | 640x360 | Fastest |
--output "content/downloads/" | 32 | 480P | 852x480 | Default for low bandwidth |
``` | 64 | 720P | 1280x720 | **Recommended** |
| 80 | 1080P | 1920x1080 | Best quality |
## 注意事项 Default quality: **64 (720P)**
- **无官方字幕是正常的**:很多视频没有自动生成的字幕,这不是错误
- **403 错误**:通常需要配置 Cookie
- **会员视频**:必须配置 BILIBILI_COOKIE
- **下载时间**:视频可能较大,需要耐心等待
+25 -166
View File
@@ -1,187 +1,46 @@
---
name: kb-bilibili-metadata
description: B站元数据提取 - 获取视频/专栏/UP主的详细信息
---
# KB Bilibili Metadata Skill # 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
## 功能 ## Commands
- 视频元数据提取
- 专栏(article)元数据提取
- UP主信息提取
- JSON 输出格式
- 支持 `--output` 参数指定输出文件
## 命令
```bash ```bash
# 视频元数据 # Video metadata
python3 bilibili_metadata.py --id "BV1xx411c7mD" --type video python bilibili_metadata.py --id "BV1xx411c7mD" --type video
# 专栏元数据 # Article metadata
python3 bilibili_metadata.py --id "cv43780186" --type article python bilibili_metadata.py --id "cv43780186" --type article
# UP主信息 # UP主 info
python3 bilibili_metadata.py --id "7770724" --type up python bilibili_metadata.py --id "7770724" --type up
# 指定输出文件
python3 bilibili_metadata.py --id "BV1xx411c7mD" --type video --output "metadata/bilibili_BV1xx411c7mD.meta.json"
``` ```
## 输出格式 Schema ## Output
### 必需字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `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 | 错误信息(失败时) |
## 成功示例
### 视频元数据
```json ```json
{ {
"success": true, "success": true,
"platform": "bilibili", "data": {
"content_type": "video", "platform": "bilibili",
"content_id": "BV1xx411c7mD", "type": "video",
"title": "视频标题", "id": "BV1xx411c7mD",
"author": "UP主名字", "title": "视频标题",
"duration": "10:30", "author": "UP主名字",
"description": "视频简介内容...", "stats": {"view": 100000, "like": 5000}
"stats": { }
"view": 100000,
"like": 5000,
"coin": 2000,
"favorite": 1000,
"share": 500,
"danmaku": 3000
},
"output_file": "metadata/bilibili_BV1xx411c7mD.meta.json"
} }
``` ```
### 专栏元数据 ## Installation
```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"
}
```
## 安装
```bash ```bash
cp -r kb-bilibili-metadata/ ~/.openclaw/skills/ cp -r kb-bilibili-metadata/ ~/skills/
pip install httpx playwright
playwright install chromium
``` ```
## 在 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 方式,首次运行需要下载浏览器
+75 -180
View File
@@ -1,207 +1,102 @@
---
name: kb-deep-analyzer
description: AI深度分析 - 使用 AI 对内容进行深度分析和摘要
---
# KB Deep Analyzer Skill # KB Deep Analyzer Skill
**kb-deep-analyzer** - AI 深度内容分析工具。 **kb-deep-analyzer** - AI 深度内容分析工具。
## 什么时候使用 ## Features
- kb-workflow 步骤 5:对视频字幕或文章内容进行深度分析
- 需要生成摘要、主题、见解等
## 功能
- 多类型分析:视频(video)、文章(article) - 多类型分析:视频(video)、文章(article)
- 模板化输出 - 模板化输出
- 质量评分 - 质量评分
- 自动标签 - 自动标签
- 多格式元数据支持 - **多格式元数据支持**: 支持扁平结构 `{"title":"xxx"}` 和嵌套结构 `{"data":{"metadata":{...}}}`
## 环境变量(必需) ## 内容类型
| 变量名 | 说明 | 示例 | | 类型 | 参数 | 输出格式 |
|--------|------|------| |------|------|----------|
| `AI_API_KEY` | AI API 密钥 | `your-api-key` | | 视频 | `--type video` | 摘要 + 主题 + 见解 + 时间轴 |
| `AI_PROVIDER` | AI 提供商 | `zhipu` / `openai` / `minimax` | | 文章 | `--type article` | 300字摘要 + 主题 + 原文 |
| `AI_MODEL` | 模型名称 | `glm-5` / `gpt-4` |
| `AI_BASE_URL` | API 端点 | `https://open.bigmodel.cn/api/coding/paas/v4` |
## 命令 ## Commands
```bash ```bash
# 分析视频 # 分析视频(默认)
AI_API_KEY="xxx" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ AI_API_KEY="your-api-key" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \
python3 -u deep_analyzer.py \ python3 -u deep_analyzer.py --metadata meta.json --content content.json --output analysis.md --type video
--metadata meta.json \
--content content.json \
--output analysis.md \
--type video \
--provider zhipu --model glm-5
# 分析文章 # 分析文章(300字摘要 + 原文)
AI_API_KEY="xxx" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \ AI_API_KEY="your-api-key" AI_PROVIDER="zhipu" AI_MODEL="glm-5" \
python3 -u deep_analyzer.py \ python3 -u deep_analyzer.py --metadata meta.json --content content.json --output analysis.md --type article
--metadata meta.json \
--content content.txt \ # 指定 AI 提供商
--output analysis.md \ python3 -u deep_analyzer.py -m meta.json -c content.json -o out.md --type video --provider zhipu --model glm-5
--type article \
--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 ```bash
cp -r kb-deep-analyzer/ ~/.openclaw/skills/ export AI_API_KEY="your-api-key"
pip install httpx export AI_PROVIDER="zhipu" # 或 openai, minimax
export AI_MODEL="glm-5" # 模型名称
export AI_BASE_URL="https://..." # 可选,自定义 API 地址
``` ```
## 在 kb-workflow 中的使用 ### 重要提示
**必须使用 `-u` 参数运行 Python**,确保输出实时显示在终端:
```bash ```bash
# 步骤 5:深度分析 python3 -u deep_analyzer.py ...
# ⚠️ 必须成功,否则整个流程失败
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 → 整个流程终止,报告错误
``` ```
## ⚠️ 重要提示 如果不使用 `-u` 参数,Python 的 stdout 缓冲会导致输出延迟或看不到进度。
1. **必须使用 `-u` 参数**:确保 Python 输出实时显示 ## 执行方式选择
2. **深度分析不可跳过**:这是必须成功的步骤
3. **失败即终止**:如果返回 `success: false`,整个流程必须停止 ### 方式1: 并发执行(推荐,默认)
4. **禁止降级**:不能使用预设模板或简单摘要"假装成功" - 使用 `batch_size=3`(默认)
5. **并发执行**:默认使用 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"
}
}
}
```
会自动转换为扁平格式进行分析。
+44 -104
View File
@@ -1,41 +1,44 @@
--- ---
name: kb-funasr name: kb-funasr
description: 本地语音识别 - 使用阿里 FunASR 进行中文优化的语音识别 description: 本地语音识别,支持音视频转文字(基于阿里 FunASR)
--- ---
# KB FunASR Skill # 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 ```bash
# 基本用法(使用 Paraformer 中文模型,推荐) # 基本用法(使用 Paraformer 模型)
python3 funasr_tool.py --input video.mp4 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 多语言模型
| `paraformer-zh` | Paraformer 中文模型 | **推荐**,中文优化 | - `sensevoice` - SenseVoice 多语言模型
| `paraformer` | Paraformer 多语言模型 | 多语言场景 |
| `sensevoice` | SenseVoice 模型 | 高精度需求 |
## 输出格式 Schema ## 输出文件
### 必需字段 对于输入 `video.mp4`,将生成:
| 字段 | 类型 | 说明 | - `video.json` - 详细结果(包含时间戳、分段信息)
|------|------|------| - `video.txt` - 纯文本内容
| `success` | boolean | 是否识别成功 |
| `input_file` | string | 输入文件路径 |
| `model` | string | 使用的模型 |
### 可选字段 ## 输出格式示例
| 字段 | 类型 | 说明 | ### JSON 格式
|------|------|------|
| `output_files` | object | 输出文件路径 |
| `duration_seconds` | number | 音频时长 |
| `segments` | array | 识别分段 |
| `error` | string | 错误信息 |
## 成功示例
```json ```json
{ {
"success": true, "success": true,
"input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4", "input_file": "video.mp4",
"model": "paraformer-zh", "model": "paraformer-zh",
"output_files": { "output_files": {
"json": "content/bilibili_BV1xx411c7mD_funasr.json", "json": "video.json",
"txt": "content/bilibili_BV1xx411c7mD_funasr.txt" "txt": "video.txt"
}, },
"duration_seconds": 630.5, "duration_seconds": 120.5,
"segments": [ "segments": [
{ {
"id": 0, "id": 0,
"start": 0.0, "start": 0.0,
"end": 3.2, "end": 3.2,
"text": "这是第一段识别结果" "text": "这是第一段识别结果"
},
{
"id": 1,
"start": 3.2,
"end": 6.5,
"text": "这是第二段识别结果"
} }
] ]
} }
``` ```
## 错误示例 ## Workflow 中的使用
### 模型未下载 ```bash
# 步骤4之后:如果已有音频但无字幕,可以使用 FunASR
```json python funasr.py --input ${video_path} --model paraformer-zh --background
{
"success": false,
"error": "模型未找到",
"model": "paraformer-zh",
"suggestion": "首次运行时会自动下载模型,请确保网络连接正常"
}
```
### 文件不存在
```json
{
"success": false,
"error": "输入文件不存在",
"input_file": "content/downloads/missing.mp4"
}
```
### 内存不足
```json
{
"success": false,
"error": "内存不足",
"suggestion": "尝试使用较小的模型或处理较短的音频片段"
}
``` ```
## 安装 ## 安装
@@ -139,35 +98,16 @@ python3 funasr_tool.py --input video.mp4 --background
# 1. 安装依赖 # 1. 安装依赖
pip install funasr modelscope pip install funasr modelscope
# 2. 首次运行时自动下载模型 # 2. 首次运行时会自动下载模型到缓存目录
python3 funasr_tool.py --input test.mp4 python funasr.py --input test.mp4
# 3. 复制技能 # 3. 复制技能到 skills 目录
cp -r kb-funasr/ ~/.openclaw/skills/ cp -r kb-funasr/ ~/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(深度分析)
``` ```
## 注意事项 ## 注意事项
- **首次运行**:首次运行时会自动下载模型文件(约 1GB),需要稳定网络 - **异步执行**: 使用 `--background` 参数时,命令会在后台运行,不阻塞主代理
- **中文优化**:Paraformer 模型对中文识别效果优于 Whisper - **模型选择**: paraformer-zh 模型适合中文语音识别,速度较快,精度较高
- **耗时操作**:语音识别可能需要几分钟到几十分钟 - **文件格式**: 支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式
- **文件格式**:支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式 - **首次运行**: 首次运行时会自动下载模型文件,需要稳定的网络连接
- **与 Whisper 对比**:
- Whisper:通用性强,支持多语言
- FunASR:中文优化,精度更高
+22 -169
View File
@@ -1,190 +1,43 @@
---
name: kb-link-parser
description: 链接解析器 - 从各平台 URL 提取平台类型、内容类型和 ID
---
# KB Link Parser Skill # 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
## 功能 ## Commands
- 多平台支持:Bilibili、YouTube、知乎、小红书
- 短链接解析:b23.tv、xhslink.com 等
- 多种内容类型:video、article、question、answer 等
- 批量处理支持
- JSON 输出格式
## 命令
```bash ```bash
# 解析单个 URL # Parse single URL
python3 link-parser.py --url "https://www.bilibili.com/video/BV1xx411c7mD" python link-parser.py --url "https://www.bilibili.com/video/BV1xx411c7mD"
# 批量处理 # Batch processing
python3 link-parser.py --batch urls.txt --output results.json python link-parser.py --batch urls.txt --output results.json
# 指定输出格式 # Output format
python3 link-parser.py --url "..." --format json python link-parser.py --url "..." --format json
``` ```
## 输出格式 Schema ## Output
### 必需字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `success` | boolean | 是否解析成功 |
| `platform` | string | 平台名称(成功时必需) |
| `type` | string | 内容类型(成功时必需) |
| `id` | string | 内容 ID(成功时必需) |
| `error` | string | 错误信息(失败时必需) |
### 可选字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `filename` | string | 建议的文件名 |
| `message` | string | 描述信息 |
## 成功示例
### B站视频
```json ```json
{ {
"success": true, "success": true,
"platform": "bilibili", "data": {
"type": "video", "platform": "bilibili",
"id": "BV1xx411c7mD", "type": "video",
"filename": "bilibili_BV1xx411c7mD.link.json", "id": "BV1xx411c7mD"
"message": "URL解析成功" }
} }
``` ```
### B站专栏 ## Installation
```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` |
## 安装
```bash ```bash
cp -r kb-link-parser/ ~/.openclaw/skills/ cp -r kb-link-parser/ ~/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(元数据提取)
``` ```
+28 -108
View File
@@ -1,146 +1,66 @@
---
name: kb-ocr-processor
description: 视频OCR识别 - 从视频帧中提取文字
---
# KB OCR Processor Skill # KB OCR Processor Skill
**kb-ocr-processor** - 从视频帧中提取文字,作为语音识别的补充或替代方案。 **kb-ocr-processor** - Extract text from video frames using OCR.
## 什么时候使用 ## Features
- kb-workflow 步骤 4 的降级方案:当 Whisper 语音识别效果不佳时 - **视频截帧**: 直接从视频文件截取帧图片
- 音频质量差、有背景音乐干扰、多种语言混合等情况 - **批量处理**: 支持处理帧目录
- **双引擎**: EasyOCR / Tesseract
- **置信度评分**: 每帧识别结果带置信度
- **文本合并**: 自动合并所有帧的识别结果
## 功能 ## Commands
- 视频截帧:直接从视频文件截取帧图片
- 批量处理:支持处理帧目录
- 双引擎:EasyOCR / Tesseract
- 置信度评分:每帧识别结果带置信度
- 文本合并:自动合并所有帧的识别结果
## 命令
```bash ```bash
# 方式1: 直接从视频截帧并 OCR(推荐) # 方式1: 直接从视频截帧并OCR(推荐)
python3 ocr_processor.py --video ./video.mp4 --output ocr.json python ocr_processor.py --video ./video.flv --output ocr.json
# 方式2: 处理已截取的帧目录 # 方式2: 处理已截取的帧目录
python3 ocr_processor.py --input ./frames/ --output ocr.json python ocr_processor.py --input ./frames/ --output ocr.json
# 指定截帧帧率(默认1帧/秒) # 指定截帧帧率(默认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 引擎 # 使用 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
```
| 字段 | 类型 | 说明 | ## Output
|------|------|------|
| `success` | boolean | 是否识别成功 |
| `engine` | string | 使用的 OCR 引擎 |
| `total_frames` | number | 处理的总帧数 |
### 可选字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `results` | array | 每帧的识别结果 |
| `merged_text` | string | 合并后的文本 |
| `output_file` | string | 输出文件路径 |
| `error` | string | 错误信息 |
## 成功示例
```json ```json
{ {
"success": true, "success": true,
"engine": "easyocr", "engine": "easyocr",
"total_frames": 619, "total_frames": 619,
"output_file": "content/bilibili_BV1xx411c7mD_ocr.json",
"results": [ "results": [
{ {
"source": "0001.jpg", "source": "0001.jpg",
"text": "字幕文字", "text": "字幕文字",
"confidence": 0.95 "confidence": 0.95
},
{
"source": "0002.jpg",
"text": "更多字幕文字",
"confidence": 0.92
} }
], ]
"merged_text": "字幕文字\n更多字幕文字\n..."
} }
``` ```
## 错误示例 ## Installation
### 视频文件不存在
```json
{
"success": false,
"error": "视频文件不存在",
"video": "./missing.mp4"
}
```
### ffmpeg 未安装
```json
{
"success": false,
"error": "ffmpeg 未安装",
"suggestion": "请运行: sudo apt-get install ffmpeg"
}
```
### 内存不足
```json
{
"success": false,
"error": "内存不足",
"suggestion": "尝试降低帧率或处理较短的片段"
}
```
## 安装
```bash ```bash
cp -r kb-ocr-processor/ ~/.openclaw/skills/ cp -r kb-ocr-processor/ ~/skills/
pip install easyocr pytesseract Pillow 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 速度较快
- **适用场景**:音频质量差、背景音乐干扰、多语言混合时使用
+53 -109
View File
@@ -1,40 +1,44 @@
--- ---
name: kb-whisper name: kb-whisper
description: 本地语音识别 - 使用 Whisper.cpp 将音视频转文字 description: 本地语音识别,支持音视频转文字(基于 Whisper.cpp)
--- ---
# KB Whisper Skill # 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 ```bash
# 基本用法 # 基本用法
python3 whisper.py --input video.mp4 python whisper.py --input video.mp4
# 指定模型(推荐 base) # 指定模型(默认 tiny)
python3 whisper.py --input video.mp4 --model base 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` - 基础模型,平衡速度和精度(推荐)
| `tiny` | 最快 | 较低 | 快速预览 | - `small` - 小型模型,精度更高,速度较慢
| `base` | 快 | 良好 | **推荐** | - `medium` - 中型模型,高精度
| `small` | 中等 | 高 | 精确识别 | - `large` - 大型模型,最高精度,速度慢
| `medium` | 慢 | 很高 | 专业场景 |
| `large` | 最慢 | 最高 | 最高精度 |
## 输出格式 Schema ## 输出文件
### 必需字段 对于输入 `video.mp4`,将生成:
| 字段 | 类型 | 说明 | - `video.json` - 详细结果(包含时间戳、分段信息)
|------|------|------| - `video.srt` - 字幕格式文件
| `success` | boolean | 是否识别成功 | - `video.txt` - 纯文本内容
| `input_file` | string | 输入文件路径 |
| `model` | string | 使用的模型 |
### 可选字段 ## 输出格式示例
| 字段 | 类型 | 说明 | ### JSON 格式
|------|------|------|
| `output_files` | object | 输出文件路径 |
| `duration_seconds` | number | 音频时长 |
| `segments` | array | 识别分段 |
| `error` | string | 错误信息 |
## 成功示例
```json ```json
{ {
"success": true, "success": true,
"input_file": "content/downloads/bilibili_BV1xx411c7mD.mp4", "input_file": "video.mp4",
"model": "base", "model": "tiny",
"output_files": { "output_files": {
"json": "content/bilibili_BV1xx411c7mD.json", "json": "video.json",
"txt": "content/bilibili_BV1xx411c7mD.txt", "srt": "video.srt",
"srt": "content/bilibili_BV1xx411c7mD.srt" "txt": "video.txt"
}, },
"duration_seconds": 630.5, "duration_seconds": 120.5,
"segments": [ "segments": [
{ {
"id": 0, "id": 0,
"start": 0.0, "start": 0.0,
"end": 3.2, "end": 3.2,
"text": "这是第一段字幕" "text": "这是第一段字幕"
},
{
"id": 1,
"start": 3.2,
"end": 6.5,
"text": "这是第二段字幕"
} }
] ]
} }
``` ```
## 错误示例 ## Workflow 中的使用
### 模型未下载 ```bash
# 步骤4之后:如果已有音频但无字幕,可以使用 whisper
```json python whisper.py --input ${video_path} --model base --background
{
"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)"
}
``` ```
## 安装 ## 安装
@@ -142,39 +103,22 @@ python3 whisper.py --input video.mp4 --background
git clone https://github.com/ggerganov/whisper.cpp.git ~/whisper.cpp git clone https://github.com/ggerganov/whisper.cpp.git ~/whisper.cpp
# 2. 编译 # 2. 编译
cd ~/whisper.cpp && make cd ~/whisper.cpp
make
# 3. 下载模型 # 3. 下载模型(tiny)
./models/download-ggml-model.sh base ./models/download-ggml-model.sh tiny
# 4. 设置环境变量 # 4. 下载更多模型(可选)
echo 'export WHISPER_CPP_PATH="$HOME/whisper.cpp"' >> ~/.kb_env # ./models/download-ggml-model.sh base
source ~/.kb_env # ./models/download-ggml-model.sh small
# 5. 复制技能 # 5. 复制技能到 skills 目录
cp -r kb-whisper/ ~/.openclaw/skills/ cp -r kb-whisper/ ~/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(深度分析)
``` ```
## 注意事项 ## 注意事项
- **耗时操作**:语音识别可能需要几分钟到几十分钟,取决于视频长度 - **异步执行**: 使用 `--background` 参数时,命令会在后台运行,不阻塞主代理
- **异步执行**:推荐使用 `--background` 参数 - **模型选择**: tiny 模型适合快速识别,base 模型适合一般用途,large 模型适合高精度需求
- **模型选择**:base 模型平衡速度和精度,适合大多数场景 - **文件格式**: 支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式
- **文件格式**:支持 MP3、MP4、WAV、FLAC、OGG、M4A 等常见格式
+141 -639
View File
@@ -5,698 +5,200 @@ description: 当收到"添加到知识库 + 链接" 或"保存到知识库 + 链
# KB Workflow # KB Workflow
## 触发条件 ## 什么时候使用
当用户发送包含以下模式的消息时,此技能自动触发:
| 触发词 | 行为 | 示例 | | 触发词 | 行为 | 示例 |
|--------|------|------| |--------|------|------|
| `添加到知识库` + 链接 | 添加到知识库并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" | | `添加到知识库` + 链接 | 添加到知识库并处理 | "添加到知识库 https://www.bilibili.com/video/BVxxx" |
| `保存到知识库` + 链接 | 同上 | "保存到知识库 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 ```bash
# 创建专用配置文件
cat > ~/.kb_env << 'EOF'
export AI_API_KEY="your-api-key" export AI_API_KEY="your-api-key"
export AI_PROVIDER="zhipu" export AI_PROVIDER="zhipu"
export AI_MODEL="glm-5" export AI_MODEL="glm-5"
export AI_BASE_URL="https://open.bigmodel.cn/api/coding/paas/v4" 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 ```bash
# 加载环境变量 # 从 ~/.kb_env 加载环境变量
if [ -f ~/.kb_env ]; then source ~/.kb_env; fi 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 "✅ 环境变量检查通过" echo "✅ 环境变量检查通过"
``` ```
**成功标准:** ## Workflow 执行方式
- 所有必需变量已设置
- 输出 "✅ 环境变量检查通过"
**失败处理:** ### 方式一:一键处理(推荐)
- 缺少任何必需变量 → 报错退出,提示用户配置
**输出示例:** 使用管道 CLI 一键完成所有步骤:
```
✅ 环境变量检查通过
AI_PROVIDER: zhipu
AI_MODEL: glm-5
```
**错误示例:**
```
❌ 错误:AI_API_KEY 未设置
请配置以下环境变量:
- AI_API_KEY
- AI_PROVIDER
- AI_MODEL
- AI_BASE_URL
```
---
### Step 1: 链接解析
**前置条件:**
- 环境变量检查通过
- URL 格式有效
**执行命令:**
```bash ```bash
# 获取目录路径 python3 kb-workflow/kb_workflow.py process "https://www.bilibili.com/video/BVxxx"
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --pending
# 解析链接
python3 ~/.openclaw/skills/kb-link-parser/link-parser.py --url "[URL]"
``` ```
**成功标准:** **该命令自动执行:**
- 返回 JSON 包含 `success: true` 1. URL 解析 → 识别平台和内容 ID
- 包含字段:`platform`, `content_type`, `content_id` 2. 元数据提取 → 获取标题、作者等信息
- 生成文件:`pending/{platform}_{id}.link.json` 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 ```bash
# 获取目录路径 # 指定输出目录
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --metadata python3 kb-workflow/kb_workflow.py process "https://..." -o /path/to/output
# 根据平台选择命令 # 强制重新执行(忽略已完成状态)
# B站视频 python3 kb-workflow/kb_workflow.py process "https://..." --no-skip
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"
``` ```
**成功标准:** ### 方式二:手动分步执行(高级)
- 返回 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 ```bash
# 获取目录路径 # 1. 查重
python3 ~/.openclaw/skills/kb-workflow/kb_workflow.py --content_downloads python3 kb-workflow/kb_workflow.py --check --url "https://..."
# B站视频 - 优先尝试字幕 # 2. 一键处理
python3 ~/.openclaw/skills/kb-bilibili-content/bilibili_content.py \ python3 kb-workflow/kb_workflow.py process "https://..."
--id "[BV号]" --type subtitle-download \
--output "content/downloads/"
# 检查是否有官方字幕 # 3. 归档
# 如果 has_subtitle=true → 进入 Step 5 python3 kb-workflow/kb_workflow.py --archive-file "/path/to/report.md"
# 如果 has_subtitle=false → 下载视频,进入 Step 4
``` ```
**成功标准:** ## 支持的平台和内容类型
- 返回 JSON 包含 `success: true`
- `has_subtitle=true`: 有字幕文件
- `has_subtitle=false`: 视频文件下载成功
**失败处理:** | 平台 | 内容类型 | URL 示例 |
- 403 禁止访问 → 检查 BILIBILI_COOKIE 配置 |------|----------|----------|
- 网络超时 → 重试1次 | B站 | 视频 | `bilibili.com/video/BVxxx` |
- 会员视频 → 提示需要配置 Cookie | 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": "官方字幕下载成功"
}
``` ```
┌─────────────────────────────────────────────────────────────┐
**输出示例(无字幕):** │ kb-workflow process │
```json ├─────────────────────────────────────────────────────────────┤
{ │ 1. Parse → LinkParser 解析 URL │
"success": true, │ 2. Download → 平台适配器获取元数据和内容 │
"type": "subtitle", │ 3. ASR → 语音识别(视频无字幕时) │
"has_subtitle": false, │ 4. Analyze → DeepAnalyzer 生成分析报告 │
"message": "无官方字幕,需要下载视频进行语音识别" │ 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/ └── 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. **禁止降级处理**:不能使用预设模板或简单摘要"假装成功" 1. **深度分析不可跳过**:AI 分析是必须成功执行的步骤
4. **每次执行都要使用 AI**:必须有真实的 AI API 调用 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 — 数据模型
```
+128 -354
View File
@@ -5,7 +5,7 @@ KB Workflow - Knowledge Base Workflow Orchestrator
知识库工作流辅助工具函数。 知识库工作流辅助工具函数。
此模块提供查重、文件操作、Git 管理、状态管理等工具函数, 此模块提供查重、文件操作、Git 管理等工具函数,
供主代理在执行 SKILL.md 中定义的 workflow 时调用。 供主代理在执行 SKILL.md 中定义的 workflow 时调用。
""" """
@@ -18,46 +18,7 @@ import shutil
import re import re
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional, Any, Tuple from typing import Dict, List, Optional, Any
# ==================== 状态机定义 ====================
# 工作流步骤顺序
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": "完成"
}
# ==================== 子技能映射 ==================== # ==================== 子技能映射 ====================
@@ -332,249 +293,6 @@ def archive_and_git(
return result 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: 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 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 ==================== # ==================== CLI ====================
def main(): def main():
@@ -618,117 +413,96 @@ def main():
使用示例: 使用示例:
# 查重 # 查重
python kb_workflow.py --check --url "https://www.bilibili.com/video/BVxxx" 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 --archive "/path/to/analyzed.md"
# 状态管理 # 处理URL (通过完整管道)
python kb_workflow.py --init-state --url "https://..." python kb_workflow.py process "https://www.bilibili.com/video/BVxxx"
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://..."
""" """
) )
# 基础参数 # Create subparsers for commands
parser.add_argument('--url', type=str, help='URL 地址') subparsers = parser.add_subparsers(dest='command', help='Available commands')
parser.add_argument('--base-path', type=str, help='知识库根目录')
# 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('--check', action='store_true', help='查重')
parser.add_argument('--url', type=str, help='要检查的URL')
parser.add_argument('--archive-file', type=str, help='归档的文件路径') parser.add_argument('--archive-file', type=str, help='归档的文件路径')
parser.add_argument('--base-path', type=str, help='获取知识库根目录')
# 目录路径查询
parser.add_argument('--pending', action='store_true', help='获取 URL 解析目录') parser.add_argument('--pending', action='store_true', help='获取url解析目录')
parser.add_argument('--metadata', action='store_true', help='获取元数据目录') parser.add_argument('--metadata', action='store_true', help='获取元数据目录')
parser.add_argument('--content', 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('--analyzed', action='store_true', help='获取深度分析目录')
parser.add_argument('--archive_dir', 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('--archive_subscriptions', action='store_true', help='获取订阅信息目录')
parser.add_argument('--extract_platform', type=str, 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='获取恢复执行信息')
args = parser.parse_args() args = parser.parse_args()
base_path = Path(args.base_path) if args.base_path else None base_path = Path(args.base_path) if args.base_path else None
dirs = ensure_directories(base_path) 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: if args.check and args.url:
result = check_duplicate(base_path, args.url) result = check_duplicate(base_path, args.url)
print(json.dumps(result, ensure_ascii=False, indent=2)) print(json.dumps(result, ensure_ascii=False, indent=2))
# 归档
elif args.archive_file: elif args.archive_file:
result = archive_and_git(args.archive_file, base_path) result = archive_and_git(args.archive_file, base_path)
print(json.dumps(result, ensure_ascii=False, indent=2)) print(json.dumps(result, ensure_ascii=False, indent=2))
# 目录路径查询
elif args.pending: elif args.pending:
print(json.dumps({"path": str(dirs["pending"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["pending"])}, ensure_ascii=False, indent=2))
elif args.metadata: elif args.metadata:
print(json.dumps({"path": str(dirs["metadata"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["metadata"])}, ensure_ascii=False, indent=2))
elif args.content: elif args.content:
print(json.dumps({"path": str(dirs["content"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["content"])}, ensure_ascii=False, indent=2))
elif args.content_downloads: elif args.content_downloads:
print(json.dumps({"path": str(dirs["content_downloads"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["content_downloads"])}, ensure_ascii=False, indent=2))
elif args.analyzed: elif args.analyzed:
print(json.dumps({"path": str(dirs["analyzed"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["analyzed"])}, ensure_ascii=False, indent=2))
elif args.archive_dir: elif args.archive_dir:
print(json.dumps({"path": str(get_archive_path())}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(get_archive_path())}, ensure_ascii=False, indent=2))
elif args.archive_subscriptions: elif args.archive_subscriptions:
print(json.dumps({"path": str(dirs["archive_subscriptions"])}, ensure_ascii=False, indent=2)) print(json.dumps({"path": str(dirs["archive_subscriptions"])}, ensure_ascii=False, indent=2))
elif args.extract_platform: elif args.extract_platform:
platform = extract_platform(args.extract_platform) platform = extract_platform(args.extract_platform)
print(json.dumps({"platform": platform}, ensure_ascii=False, indent=2)) print(json.dumps({"platform": platform}, ensure_ascii=False, indent=2))
elif args.base_path: elif args.base_path:
print(json.dumps({"path": str(dirs["base"])}, ensure_ascii=False, indent=2)) 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: else:
parser.print_help() parser.print_help()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
if __name__ == '__main__':
main()
+50 -118
View File
@@ -1,154 +1,86 @@
---
name: kb-zhihu-content
description: 知乎内容下载 - 下载视频、提取文章内容
---
# KB Zhihu Content Skill # KB Zhihu Content Skill
**kb-zhihu-content** - 下载知乎视频、提取文章内容。 **kb-zhihu-content** - Download Zhihu videos and extract content.
## 什么时候使用 ## Features
- kb-workflow 步骤 3a:下载知乎视频 - Video download using **yt-dlp**
- kb-workflow 步骤 3b:提取知乎专栏文章内容 - Subtitle extraction (returns no subtitle, triggers Whisper)
- **Read article content from MediaCrawler data** (NEW!)
- Supports `ZHIHU_COOKIE` environment variable
## 功能 ## Environment Variables
- 视频下载(使用 yt-dlp) | Variable | Required | Description |
- 从 MediaCrawler 数据读取文章内容 |----------|----------|-------------|
- 支持 `ZHIHU_COOKIE` 环境变量 | `ZHIHU_COOKIE` | No | 知乎登录 Cookie (for member-only videos) |
## 环境变量 ## Commands
| 变量名 | 必需 | 说明 |
|--------|------|------|
| `ZHIHU_COOKIE` | 否 | 知乎登录 Cookie |
## 命令
```bash ```bash
# 下载视频 # Download video
python3 zhihu_content.py --id "12345678" --type video --output "/path/to/downloads/" python zhihu_content.py --id "12345678" --type video --output "/path/to/downloads/"
# 从 MediaCrawler 读取文章内容 # Extract subtitle (returns no subtitle, triggers Whisper)
python3 zhihu_content.py --type article-from-media \ 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" \ --input "~/work/MediaCrawler/data/zhihu/json/detail_contents_2026-02-27.json" \
--output "~/work/knowledge-base/data/zhihu/" --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/" --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 ```json
{ {
"success": true, "success": true,
"type": "article", "type": "article",
"filename": "zhihu_article_如何高效的爬取微信公众号.md", "filename": "zhihu_article_如何高效的爬取微信公众号.md",
"filepath": "~/work/knowledge-base/data/zhihu/zhihu_article_如何高效的爬取微信公众号.md", "filepath": "/home/xxx/work/knowledge-base/data/zhihu/zhihu_article_如何高效的爬取微信公众号.md",
"content_length": 4563,
"message": "文章内容已导出" "message": "文章内容已导出"
} }
``` ```
## 错误示例 ## 原有功能
### 视频下载失败 ### Video Download
```json Video download uses **yt-dlp**:
{ 1. Parses `ZHIHU_COOKIE` environment variable (optional)
"success": false, 2. Creates temporary Netscape-format cookie file
"type": "video", 3. Runs `yt-dlp -f best -o <output> <url>`
"error": "视频不存在或无法访问", 4. Cleans up temporary file
"suggestion": "请检查视频 ID 是否正确"
}
```
### MediaCrawler 数据未找到 **Note**: 知乎视频通常没有官方字幕,将自动触发 Whisper 语音识别
```json ## Installation
{
"success": false,
"type": "article-from-media",
"error": "未找到 MediaCrawler 数据文件",
"suggestion": "请先运行 MediaCrawler 爬取文章"
}
```
### 网络错误
```json
{
"success": false,
"error": "网络请求失败: Connection timeout"
}
```
## 安装
```bash ```bash
cp -r kb-zhihu-content/ ~/.openclaw/skills/ # Already included in kb-skills repo
# Ensure yt-dlp is installed
pip install yt-dlp aiohttp 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 需要单独安装和运行
- 部分视频可能需要登录才能下载
+63 -169
View File
@@ -1,207 +1,101 @@
---
name: kb-zhihu-metadata
description: 知乎元数据提取 - 获取问题/回答/专栏/视频的详细信息
---
# KB Zhihu Metadata Skill # KB Zhihu Metadata Skill
**kb-zhihu-metadata** - 提取知乎问题、回答、用户、专栏的元数据。 **kb-zhihu-metadata** - Extract Zhihu question/answer/user metadata and crawl articles.
## 什么时候使用 ## Features
- kb-workflow 步骤 2:获取知乎内容的元数据 - Question metadata extraction
- 需要问题标题、回答者、文章标题等信息 - Answer metadata extraction
- User information extraction
## 功能 - **Article crawling using MediaCrawler** (NEW!)
- JSON output format
- 问题元数据提取 - Markdown conversion support
- 回答元数据提取 - **Cookie 支持**:可配置 ZHIHU_COOKIE 访问需要登录的内容
- 用户信息提取
- 专栏文章爬取(使用 MediaCrawler)
- 支持 `ZHIHU_COOKIE` 环境变量
## 环境变量 ## 环境变量
| 变量名 | 必需 | 说明 | | 变量名 | 用途 | 必需 |
|--------|------|------| |--------|------|------|
| `ZHIHU_COOKIE` | 推荐 | 知乎登录 Cookie(访问专栏等需要) | | `ZHIHU_COOKIE` | 知乎登录 Cookie | 推荐(访问专栏等需要) |
**获取 Cookie:** **获取 ZHIHU_COOKIE**:
1. 登录知乎网页版 1. 登录知乎网页版
2. F12 → Application → Cookies → zhihu.com 2. 打开开发者工具 (F12) → Application → Cookies → zhihu.com
3. 复制 Cookie 字符串 3. 复制 Cookie 字符串
```bash ```bash
export ZHIHU_COOKIE="你的知乎Cookie" # 添加到 ~/.kb_env
echo 'export ZHIHU_COOKIE="你的知乎Cookie"' >> ~/.kb_env
source ~/.kb_env
``` ```
## 命令 ## Commands
```bash ```bash
# 问题元数据 # Question metadata
python3 zhihu_metadata.py --id "266309957" --type question python zhihu_metadata.py --id "266309957" --type question
# 回答元数据 # Answer metadata
python3 zhihu_metadata.py --id "2003427891925509507" --type answer python zhihu_metadata.py --id "2003427891925509507" --type answer
# 知乎视频 # 专栏文章爬取 (使用 MediaCrawler) ⚡ NEW!
python3 zhihu_metadata.py --id "123456789" --type zvideo python zhihu_article_crawler.py --url "https://zhuanlan.zhihu.com/p/1894054073625461813" --output "~/work/knowledge-base/data/zhihu/"
# 专栏文章爬取(使用 MediaCrawler)
python3 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 ```json
{ {
"success": true, "success": true,
"platform": "zhihu", "data": {
"content_type": "question", "platform": "zhihu",
"content_id": "266309957", "type": "question",
"title": "问题标题", "id": "266309957",
"excerpt": "问题描述...", "title": "问题标题",
"stats": { "author": "作者名字",
"answer_count": 50, "answer_count": 50,
"follower_count": 1000, "followers": 1000
"view_count": 50000 }
},
"output_file": "metadata/zhihu_266309957.meta.json"
} }
``` ```
### 回答元数据 ## Installation
```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"
}
```
## 安装
```bash ```bash
cp -r kb-zhihu-metadata/ ~/.openclaw/skills/ cp -r kb-zhihu-metadata/ ~/skills/
pip install httpx
``` ```
## 在 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`
- 部分内容可能有访问限制