foliko 1.0.74 → 1.0.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +29 -0
  39. package/.agent/data/plugins-state.json +255 -0
  40. package/.agent/mcp_config.json +4 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins.json +5 -0
  43. package/.agent/rules/GEMINI.md +273 -0
  44. package/.agent/rules/allow-rule.md +77 -0
  45. package/.agent/rules/log-rule.md +83 -0
  46. package/.agent/rules/security-rule.md +93 -0
  47. package/.agent/scripts/auto_preview.py +148 -0
  48. package/.agent/scripts/checklist.py +217 -0
  49. package/.agent/scripts/session_manager.py +120 -0
  50. package/.agent/scripts/verify_all.py +327 -0
  51. package/.agent/skills/api-patterns/SKILL.md +81 -0
  52. package/.agent/skills/api-patterns/api-style.md +42 -0
  53. package/.agent/skills/api-patterns/auth.md +24 -0
  54. package/.agent/skills/api-patterns/documentation.md +26 -0
  55. package/.agent/skills/api-patterns/graphql.md +41 -0
  56. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  57. package/.agent/skills/api-patterns/response.md +37 -0
  58. package/.agent/skills/api-patterns/rest.md +40 -0
  59. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  60. package/.agent/skills/api-patterns/security-testing.md +122 -0
  61. package/.agent/skills/api-patterns/trpc.md +41 -0
  62. package/.agent/skills/api-patterns/versioning.md +22 -0
  63. package/.agent/skills/app-builder/SKILL.md +75 -0
  64. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  65. package/.agent/skills/app-builder/feature-building.md +53 -0
  66. package/.agent/skills/app-builder/project-detection.md +34 -0
  67. package/.agent/skills/app-builder/scaffolding.md +118 -0
  68. package/.agent/skills/app-builder/tech-stack.md +40 -0
  69. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  70. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  71. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  72. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  73. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  74. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  75. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  76. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  77. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  78. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  79. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  80. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  81. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  82. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  83. package/.agent/skills/architecture/SKILL.md +55 -0
  84. package/.agent/skills/architecture/context-discovery.md +43 -0
  85. package/.agent/skills/architecture/examples.md +94 -0
  86. package/.agent/skills/architecture/pattern-selection.md +68 -0
  87. package/.agent/skills/architecture/patterns-reference.md +50 -0
  88. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  89. package/.agent/skills/clean-code/SKILL.md +201 -0
  90. package/.agent/skills/doc.md +177 -0
  91. package/.agent/skills/frontend-design/SKILL.md +418 -0
  92. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  93. package/.agent/skills/frontend-design/color-system.md +311 -0
  94. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  95. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  96. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  97. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  98. package/.agent/skills/frontend-design/typography-system.md +345 -0
  99. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  100. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  101. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  102. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  103. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  104. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  105. package/.agent/workflows/brainstorm.md +113 -0
  106. package/.agent/workflows/create.md +59 -0
  107. package/.agent/workflows/debug.md +103 -0
  108. package/.agent/workflows/deploy.md +176 -0
  109. package/.agent/workflows/enhance.md +63 -0
  110. package/.agent/workflows/orchestrate.md +237 -0
  111. package/.agent/workflows/plan.md +89 -0
  112. package/.agent/workflows/preview.md +81 -0
  113. package/.agent/workflows/simple-test.md +42 -0
  114. package/.agent/workflows/status.md +86 -0
  115. package/.agent/workflows/structured-orchestrate.md +180 -0
  116. package/.agent/workflows/test.md +144 -0
  117. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  118. package/.claude/settings.local.json +157 -149
  119. package/.editorconfig +56 -0
  120. package/.husky/pre-commit +4 -0
  121. package/.lintstagedrc +7 -0
  122. package/.prettierignore +29 -0
  123. package/.prettierrc +11 -0
  124. package/CLAUDE.md +2 -0
  125. package/README.md +64 -55
  126. package/SPEC.md +102 -61
  127. package/cli/bin/foliko.js +4 -4
  128. package/cli/src/commands/chat.js +53 -51
  129. package/cli/src/commands/list.js +40 -37
  130. package/cli/src/index.js +18 -18
  131. package/cli/src/ui/chat-ui.js +78 -76
  132. package/cli/src/utils/ansi.js +15 -15
  133. package/cli/src/utils/markdown.js +112 -116
  134. package/docker-compose.yml +1 -1
  135. package/docs/ai-sdk-optimization.md +655 -643
  136. package/docs/features.md +80 -80
  137. package/docs/quick-reference.md +49 -46
  138. package/docs/user-manual.md +411 -380
  139. package/examples/ambient-example.js +95 -97
  140. package/examples/basic.js +115 -110
  141. package/examples/bootstrap.js +52 -43
  142. package/examples/mcp-example.js +56 -53
  143. package/examples/skill-example.js +49 -49
  144. package/examples/test-chat.js +60 -58
  145. package/examples/test-mcp.js +49 -43
  146. package/examples/test-reload.js +38 -40
  147. package/examples/test-telegram.js +3 -3
  148. package/examples/test-tg-bot.js +7 -4
  149. package/examples/test-tg-simple.js +4 -3
  150. package/examples/test-tg.js +3 -3
  151. package/examples/test-think.js +13 -7
  152. package/examples/test-web-plugin.js +61 -56
  153. package/examples/test-weixin-feishu.js +40 -37
  154. package/examples/workflow.js +49 -49
  155. package/foliko-1.0.75.tgz +0 -0
  156. package/package.json +37 -3
  157. package/plugins/ai-plugin.js +7 -5
  158. package/plugins/ambient-agent/EventWatcher.js +113 -0
  159. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  160. package/plugins/ambient-agent/GoalManager.js +197 -0
  161. package/plugins/ambient-agent/Reflector.js +95 -0
  162. package/plugins/ambient-agent/StateStore.js +90 -0
  163. package/plugins/ambient-agent/constants.js +101 -0
  164. package/plugins/ambient-agent/index.js +579 -0
  165. package/plugins/default-plugins.js +62 -49
  166. package/plugins/email/constants.js +64 -0
  167. package/plugins/email/handlers.js +461 -0
  168. package/plugins/email/index.js +278 -0
  169. package/plugins/email/monitor.js +269 -0
  170. package/plugins/email/parser.js +138 -0
  171. package/plugins/email/reply.js +151 -0
  172. package/plugins/email/utils.js +124 -0
  173. package/plugins/feishu-plugin.js +23 -19
  174. package/plugins/file-system-plugin.js +456 -106
  175. package/plugins/install-plugin.js +6 -4
  176. package/plugins/python-executor-plugin.js +3 -1
  177. package/plugins/python-plugin-loader.js +10 -8
  178. package/plugins/rules-plugin.js +5 -3
  179. package/plugins/scheduler-plugin.js +18 -16
  180. package/plugins/session-plugin.js +3 -1
  181. package/plugins/storage-plugin.js +5 -3
  182. package/plugins/subagent-plugin.js +152 -92
  183. package/plugins/telegram-plugin.js +26 -19
  184. package/plugins/think-plugin.js +4 -2
  185. package/plugins/tools-plugin.js +3 -1
  186. package/plugins/web-plugin.js +15 -13
  187. package/plugins/weixin-plugin.js +43 -36
  188. package/reports/system-health-report-20260401.md +79 -0
  189. package/skills/ambient-agent/SKILL.md +49 -39
  190. package/skills/foliko-dev/AGENTS.md +64 -61
  191. package/skills/foliko-dev/SKILL.md +125 -119
  192. package/skills/mcp-usage/SKILL.md +19 -17
  193. package/skills/python-plugin-dev/SKILL.md +16 -15
  194. package/skills/skill-guide/SKILL.md +12 -12
  195. package/skills/subagent-guide/SKILL.md +237 -0
  196. package/skills/workflow-guide/SKILL.md +90 -45
  197. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  198. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  199. package/src/capabilities/index.js +4 -4
  200. package/src/capabilities/skill-manager.js +211 -197
  201. package/src/capabilities/workflow-engine.js +461 -547
  202. package/src/core/agent-chat.js +426 -279
  203. package/src/core/agent.js +453 -249
  204. package/src/core/framework.js +183 -149
  205. package/src/core/index.js +8 -8
  206. package/src/core/plugin-base.js +52 -52
  207. package/src/core/plugin-manager.js +377 -281
  208. package/src/core/provider.js +35 -32
  209. package/src/core/sub-agent-config.js +264 -0
  210. package/src/core/system-prompt-builder.js +120 -0
  211. package/src/core/tool-registry.js +416 -33
  212. package/src/core/tool-router.js +149 -68
  213. package/src/executors/executor-base.js +58 -58
  214. package/src/executors/mcp-executor.js +269 -257
  215. package/src/index.js +5 -17
  216. package/src/utils/circuit-breaker.js +301 -0
  217. package/src/utils/error-boundary.js +363 -0
  218. package/src/utils/error.js +374 -0
  219. package/src/utils/event-emitter.js +20 -20
  220. package/src/utils/id.js +133 -0
  221. package/src/utils/index.js +217 -3
  222. package/src/utils/logger.js +181 -0
  223. package/src/utils/plugin-helpers.js +90 -0
  224. package/src/utils/retry.js +122 -0
  225. package/src/utils/sandbox.js +292 -0
  226. package/test/tool-registry-validation.test.js +218 -0
  227. package/test_report.md +70 -0
  228. package/website/docs/api.html +169 -107
  229. package/website/docs/configuration.html +296 -144
  230. package/website/docs/plugin-development.html +154 -85
  231. package/website/docs/project-structure.html +110 -109
  232. package/website/docs/skill-development.html +117 -61
  233. package/website/index.html +209 -205
  234. package/website/script.js +20 -17
  235. package/website/styles.css +1 -1
  236. package/plugins/ambient-agent-plugin.js +0 -1565
  237. package/plugins/email.js +0 -1142
@@ -3,82 +3,93 @@
3
3
  * 加载和管理 Skill
4
4
  */
5
5
 
6
- const fs = require('fs')
7
- const path = require('path')
8
- const { Plugin } = require('../core/plugin-base')
9
- const { z } = require('zod')
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { Plugin } = require('../core/plugin-base');
9
+ const { logger } = require('../utils/logger');
10
+ const log = logger.child('SkillManager');
11
+ const { z } = require('zod');
10
12
 
11
13
  /**
12
14
  * 验证 skill 名称
13
15
  * 1-64字符,字母数字、下划线和连字符,不能以连字符或下划线开头或结尾
14
16
  */
15
17
  function isValidSkillName(name) {
16
- if (!name || name.length < 1 || name.length > 64) return false
17
- if (!/^[a-zA-Z0-9_-]+$/.test(name)) return false
18
- if (name.startsWith('-') || name.startsWith('_') || name.endsWith('-') || name.endsWith('_')) return false
19
- if (/--/.test(name) || /__/.test(name)) return false
20
- return true
18
+ if (!name || name.length < 1 || name.length > 64) return false;
19
+ if (!/^[a-zA-Z0-9_-]+$/.test(name)) return false;
20
+ if (name.startsWith('-') || name.startsWith('_') || name.endsWith('-') || name.endsWith('_'))
21
+ return false;
22
+ if (/--/.test(name) || /__/.test(name)) return false;
23
+ return true;
21
24
  }
22
25
 
23
26
  /**
24
27
  * 解析 YAML frontmatter
25
28
  */
26
29
  function parseFrontmatter(content) {
27
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)
28
- if (!match) return null
30
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
31
+ if (!match) return null;
29
32
 
30
- const frontmatter = {}
31
- const lines = match[1].split('\n')
32
- let currentKey = null
33
+ const frontmatter = {};
34
+ const lines = match[1].split('\n');
35
+ let currentKey = null;
33
36
 
34
37
  for (const line of lines) {
35
38
  // 处理 metadata 嵌套
36
39
  if (currentKey === 'metadata') {
37
40
  if (line.match(/^ {2}[a-zA-Z]/)) {
38
- const colonIndex = line.indexOf(':')
41
+ const colonIndex = line.indexOf(':');
39
42
  if (colonIndex > 0) {
40
- const key = line.substring(2, colonIndex).trim()
41
- const value = line.substring(colonIndex + 1).trim().replace(/^["']|["']$/g, '')
42
- frontmatter[currentKey][key] = value
43
- continue
43
+ const key = line.substring(2, colonIndex).trim();
44
+ const value = line
45
+ .substring(colonIndex + 1)
46
+ .trim()
47
+ .replace(/^["']|["']$/g, '');
48
+ frontmatter[currentKey][key] = value;
49
+ continue;
44
50
  }
45
51
  } else if (line.match(/^[a-zA-Z]/)) {
46
- currentKey = null
47
- continue
52
+ currentKey = null;
53
+ continue;
48
54
  }
49
55
  }
50
56
 
51
- const colonIndex = line.indexOf(':')
52
- if (colonIndex === -1) continue
57
+ const colonIndex = line.indexOf(':');
58
+ if (colonIndex === -1) continue;
53
59
 
54
- const key = line.substring(0, colonIndex).trim()
55
- let value = line.substring(colonIndex + 1).trim()
60
+ const key = line.substring(0, colonIndex).trim();
61
+ let value = line.substring(colonIndex + 1).trim();
56
62
 
57
63
  // 移除引号
58
- if ((value.startsWith('"') && value.endsWith('"')) ||
59
- (value.startsWith("'") && value.endsWith("'"))) {
60
- value = value.slice(1, -1)
64
+ if (
65
+ (value.startsWith('"') && value.endsWith('"')) ||
66
+ (value.startsWith("'") && value.endsWith("'"))
67
+ ) {
68
+ value = value.slice(1, -1);
61
69
  }
62
70
 
63
71
  if (key === 'metadata') {
64
- currentKey = 'metadata'
65
- frontmatter.metadata = {}
72
+ currentKey = 'metadata';
73
+ frontmatter.metadata = {};
66
74
  } else if (key === 'allowed-tools') {
67
- frontmatter[key] = value.split(',').map(t => t.trim().replace(/^["']|["']$/g, '')).filter(t => t)
68
- } else {
69
75
  frontmatter[key] = value
76
+ .split(',')
77
+ .map((t) => t.trim().replace(/^["']|["']$/g, ''))
78
+ .filter((t) => t);
79
+ } else {
80
+ frontmatter[key] = value;
70
81
  }
71
82
  }
72
83
 
73
- return frontmatter
84
+ return frontmatter;
74
85
  }
75
86
 
76
87
  /**
77
88
  * 移除 frontmatter,获取正文
78
89
  */
79
90
  function stripFrontmatter(content) {
80
- const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/)
81
- return match ? content.slice(match[0].length).trim() : content.trim()
91
+ const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);
92
+ return match ? content.slice(match[0].length).trim() : content.trim();
82
93
  }
83
94
 
84
95
  /**
@@ -86,12 +97,12 @@ function stripFrontmatter(content) {
86
97
  */
87
98
  class SkillMetadata {
88
99
  constructor(data) {
89
- this.name = data.name || ''
90
- this.description = data.description || ''
91
- this.license = data.license || null
92
- this.compatibility = data.compatibility || null
93
- this.metadata = data.metadata || {}
94
- this.allowedTools = data.allowedTools || []
100
+ this.name = data.name || '';
101
+ this.description = data.description || '';
102
+ this.license = data.license || null;
103
+ this.compatibility = data.compatibility || null;
104
+ this.metadata = data.metadata || {};
105
+ this.allowedTools = data.allowedTools || [];
95
106
  }
96
107
  }
97
108
 
@@ -100,24 +111,24 @@ class SkillMetadata {
100
111
  */
101
112
  class Skill {
102
113
  constructor(metadata, content) {
103
- this.metadata = metadata
104
- this.content = content
105
- this._framework = null
114
+ this.metadata = metadata;
115
+ this.content = content;
116
+ this._framework = null;
106
117
  }
107
118
 
108
119
  /**
109
120
  * 安装 skill
110
121
  */
111
122
  install(framework) {
112
- this._framework = framework
113
- return this
123
+ this._framework = framework;
124
+ return this;
114
125
  }
115
126
 
116
127
  /**
117
128
  * 获取工具定义
118
129
  */
119
130
  getTools() {
120
- return []
131
+ return [];
121
132
  }
122
133
  }
123
134
 
@@ -126,48 +137,50 @@ class Skill {
126
137
  */
127
138
  class SkillManagerPlugin extends Plugin {
128
139
  constructor(config = {}) {
129
- super()
130
- this.name = 'skill-manager'
131
- this.version = '1.0.0'
132
- this.description = '技能管理器,加载和管理 Skill'
133
- this.priority = 5
134
- this.system = true
135
-
136
- this._framework = null
137
- this._skillsDirs = Array.isArray(config.skillsDirs) ? config.skillsDirs : [config.skillsDir || '.agent/skills', 'skills']
138
- this._skills = new Map()
139
- this._loaded = false
140
+ super();
141
+ this.name = 'skill-manager';
142
+ this.version = '1.0.0';
143
+ this.description = '技能管理器,加载和管理 Skill';
144
+ this.priority = 5;
145
+ this.system = true;
146
+
147
+ this._framework = null;
148
+ this._skillsDirs = Array.isArray(config.skillsDirs)
149
+ ? config.skillsDirs
150
+ : [config.skillsDir || '.agent/skills', 'skills'];
151
+ this._skills = new Map();
152
+ this._loaded = false;
140
153
  }
141
154
 
142
155
  install(framework) {
143
- this._framework = framework
144
- return this
156
+ this._framework = framework;
157
+ return this;
145
158
  }
146
159
 
147
160
  start(framework) {
148
- this._loadAllSkills()
161
+ this._loadAllSkills();
149
162
 
150
163
  // 注册 loadSkill 工具
151
164
  framework.registerTool({
152
165
  name: 'loadSkill',
153
166
  description: '加载指定技能,获取技能的使用指南和内容',
154
167
  inputSchema: z.object({
155
- skill: z.string().describe('技能名称')
168
+ skill: z.string().describe('技能名称'),
156
169
  }),
157
170
  execute: async (args) => {
158
- const skillName = args.skill
159
- const skill = this.getSkill(skillName)
171
+ const skillName = args.skill;
172
+ const skill = this.getSkill(skillName);
160
173
  if (!skill) {
161
- return { success: false, error: `Skill '${skillName}' not found` }
174
+ return { success: false, error: `Skill '${skillName}' not found` };
162
175
  }
163
176
  return {
164
177
  success: true,
165
178
  name: skill.name,
166
179
  description: skill.metadata?.description || '',
167
- content: skill.content
168
- }
169
- }
170
- })
180
+ content: skill.content,
181
+ };
182
+ },
183
+ });
171
184
 
172
185
  // 注册 reloadSkills 工具
173
186
  framework.registerTool({
@@ -175,14 +188,14 @@ class SkillManagerPlugin extends Plugin {
175
188
  description: '重载所有技能,当用户添加新技能或修改技能后调用此工具',
176
189
  inputSchema: z.object({}),
177
190
  execute: async () => {
178
- this.reload(this._framework)
191
+ this.reload(this._framework);
179
192
  return {
180
193
  success: true,
181
194
  message: `Skills reloaded. Total: ${this._skills.size}`,
182
- skills: Array.from(this._skills.keys())
183
- }
184
- }
185
- })
195
+ skills: Array.from(this._skills.keys()),
196
+ };
197
+ },
198
+ });
186
199
 
187
200
  // 注册 loadReference 工具(按需加载 skill 的附加文档)
188
201
  framework.registerTool({
@@ -191,51 +204,51 @@ class SkillManagerPlugin extends Plugin {
191
204
  inputSchema: z.object({
192
205
  skill: z.string().describe('技能名称'),
193
206
  reference: z.string().describe('参考文档名称(不含 .md 后缀)'),
194
- list: z.boolean().optional().describe('如果为 true,列出该技能的所有可用的 reference 文件')
207
+ list: z.boolean().optional().describe('如果为 true,列出该技能的所有可用的 reference 文件'),
195
208
  }),
196
209
  execute: async (args) => {
197
210
  if (args.list) {
198
211
  // 列出该技能的所有 reference
199
- const refs = this.listReferences(args.skill)
212
+ const refs = this.listReferences(args.skill);
200
213
  return {
201
214
  success: true,
202
215
  skill: args.skill,
203
- references: refs
204
- }
216
+ references: refs,
217
+ };
205
218
  }
206
219
 
207
- const content = this.loadReference(args.skill, args.reference)
220
+ const content = this.loadReference(args.skill, args.reference);
208
221
  if (content === null) {
209
222
  return {
210
223
  success: false,
211
- error: `Reference '${args.reference}' not found in skill '${args.skill}'`
212
- }
224
+ error: `Reference '${args.reference}' not found in skill '${args.skill}'`,
225
+ };
213
226
  }
214
227
  return {
215
228
  success: true,
216
229
  skill: args.skill,
217
230
  reference: args.reference,
218
- content
219
- }
220
- }
221
- })
231
+ content,
232
+ };
233
+ },
234
+ });
222
235
 
223
236
  // 注册 listScripts 工具(列出 skill 的脚本)
224
237
  framework.registerTool({
225
238
  name: 'listScripts',
226
239
  description: '列出指定技能下的所有可执行脚本',
227
240
  inputSchema: z.object({
228
- skill: z.string().describe('技能名称')
241
+ skill: z.string().describe('技能名称'),
229
242
  }),
230
243
  execute: async (args) => {
231
- const scripts = this.listScripts(args.skill)
244
+ const scripts = this.listScripts(args.skill);
232
245
  return {
233
246
  success: true,
234
247
  skill: args.skill,
235
- scripts
236
- }
237
- }
238
- })
248
+ scripts,
249
+ };
250
+ },
251
+ });
239
252
 
240
253
  // 注册 loadScript 工具(读取脚本内容)
241
254
  framework.registerTool({
@@ -243,74 +256,74 @@ class SkillManagerPlugin extends Plugin {
243
256
  description: '读取指定技能下脚本文件的内容',
244
257
  inputSchema: z.object({
245
258
  skill: z.string().describe('技能名称'),
246
- script: z.string().describe('脚本名称(包含扩展名)')
259
+ script: z.string().describe('脚本名称(包含扩展名)'),
247
260
  }),
248
261
  execute: async (args) => {
249
- const content = this.loadScript(args.skill, args.script)
262
+ const content = this.loadScript(args.skill, args.script);
250
263
  if (content === null) {
251
264
  return {
252
265
  success: false,
253
- error: `Script '${args.script}' not found in skill '${args.skill}'`
254
- }
266
+ error: `Script '${args.script}' not found in skill '${args.skill}'`,
267
+ };
255
268
  }
256
269
  return {
257
270
  success: true,
258
271
  skill: args.skill,
259
272
  script: args.script,
260
- content
261
- }
262
- }
263
- })
273
+ content,
274
+ };
275
+ },
276
+ });
264
277
 
265
- return this
278
+ return this;
266
279
  }
267
280
 
268
281
  /**
269
282
  * 加载所有 skills
270
283
  */
271
284
  _loadAllSkills() {
272
- if (this._loaded) return
285
+ if (this._loaded) return;
273
286
 
274
- let totalLoaded = 0
287
+ let totalLoaded = 0;
275
288
 
276
289
  for (const skillsDir of this._skillsDirs) {
277
- const resolvedDir = path.resolve(process.cwd(), skillsDir)
290
+ const resolvedDir = path.resolve(process.cwd(), skillsDir);
278
291
 
279
292
  if (!fs.existsSync(resolvedDir)) {
280
- continue
293
+ continue;
281
294
  }
282
295
 
283
296
  try {
284
- const entries = fs.readdirSync(resolvedDir, { withFileTypes: true })
297
+ const entries = fs.readdirSync(resolvedDir, { withFileTypes: true });
285
298
 
286
299
  for (const entry of entries) {
287
- if (!entry.isDirectory()) continue
300
+ if (!entry.isDirectory()) continue;
288
301
 
289
- const skillPath = path.join(resolvedDir, entry.name)
302
+ const skillPath = path.join(resolvedDir, entry.name);
290
303
 
291
304
  if (!isValidSkillName(entry.name)) {
292
- continue
305
+ continue;
293
306
  }
294
307
 
295
308
  // 跳过已加载的 skill
296
309
  if (this._skills.has(entry.name)) {
297
- continue
310
+ continue;
298
311
  }
299
312
 
300
313
  try {
301
- this._loadSkill(entry.name, skillPath)
302
- totalLoaded++
314
+ this._loadSkill(entry.name, skillPath);
315
+ totalLoaded++;
303
316
  } catch (err) {
304
- console.error(`[SkillManager] Failed to load skill '${entry.name}':`, err.message)
317
+ log.error(` Failed to load skill '${entry.name}':`, err.message);
305
318
  }
306
319
  }
307
320
  } catch (err) {
308
- console.error('[SkillManager] Failed to load skills from:', skillsDir, err.message)
321
+ log.error('Failed to load skills from:', skillsDir, err.message);
309
322
  }
310
323
  }
311
324
 
312
- console.log(`[SkillManager] Loaded ${this._skills.size} skills`)
313
- this._loaded = true
325
+ log.info(` Loaded ${this._skills.size} skills`);
326
+ this._loaded = true;
314
327
  }
315
328
 
316
329
  /**
@@ -320,35 +333,35 @@ class SkillManagerPlugin extends Plugin {
320
333
  */
321
334
  _findSkillMarkdown(dir) {
322
335
  if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
323
- return null
336
+ return null;
324
337
  }
325
338
 
326
- const entries = fs.readdirSync(dir, { withFileTypes: true })
339
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
327
340
 
328
341
  // 第一遍:优先查找 SKILL.MD
329
342
  for (const entry of entries) {
330
343
  if (entry.isFile() && entry.name.toUpperCase() === 'SKILL.MD') {
331
- return path.join(dir, entry.name)
344
+ return path.join(dir, entry.name);
332
345
  }
333
346
  }
334
347
 
335
348
  // 第二遍:查找 AGENTS.MD
336
349
  for (const entry of entries) {
337
350
  if (entry.isFile() && entry.name.toUpperCase() === 'AGENTS.MD') {
338
- return path.join(dir, entry.name)
351
+ return path.join(dir, entry.name);
339
352
  }
340
353
  }
341
354
 
342
355
  // 如果没找到,递归搜索子目录(排除 node_modules)
343
356
  for (const entry of entries) {
344
357
  if (entry.isDirectory() && entry.name !== 'node_modules') {
345
- const subPath = path.join(dir, entry.name)
346
- const found = this._findSkillMarkdown(subPath)
347
- if (found) return found
358
+ const subPath = path.join(dir, entry.name);
359
+ const found = this._findSkillMarkdown(subPath);
360
+ if (found) return found;
348
361
  }
349
362
  }
350
363
 
351
- return null
364
+ return null;
352
365
  }
353
366
 
354
367
  /**
@@ -356,17 +369,17 @@ class SkillManagerPlugin extends Plugin {
356
369
  */
357
370
  _loadSkill(name, skillPath) {
358
371
  // 查找 markdown 文件,优先加载 SKILL.md 或 AGENTS.md(支持多层嵌套)
359
- const skillMdPath = this._findSkillMarkdown(skillPath)
372
+ const skillMdPath = this._findSkillMarkdown(skillPath);
360
373
  if (!skillMdPath) {
361
- throw new Error('No markdown file found')
374
+ throw new Error('No markdown file found');
362
375
  }
363
376
 
364
- const mainFile = skillMdPath
365
- const content = fs.readFileSync(mainFile, 'utf-8')
366
- const frontmatter = parseFrontmatter(content)
377
+ const mainFile = skillMdPath;
378
+ const content = fs.readFileSync(mainFile, 'utf-8');
379
+ const frontmatter = parseFrontmatter(content);
367
380
 
368
381
  if (!frontmatter) {
369
- throw new Error('No valid frontmatter found')
382
+ throw new Error('No valid frontmatter found');
370
383
  }
371
384
 
372
385
  const metadata = new SkillMetadata({
@@ -375,17 +388,17 @@ class SkillManagerPlugin extends Plugin {
375
388
  license: frontmatter.license,
376
389
  compatibility: frontmatter.compatibility,
377
390
  metadata: frontmatter.metadata || {},
378
- allowedTools: frontmatter['allowed-tools'] || []
379
- })
391
+ allowedTools: frontmatter['allowed-tools'] || [],
392
+ });
380
393
 
381
- const skill = new Skill(metadata, stripFrontmatter(content))
382
- skill.install(this._framework)
394
+ const skill = new Skill(metadata, stripFrontmatter(content));
395
+ skill.install(this._framework);
383
396
 
384
397
  // 扫描 references 子目录(按需加载的附加文档)
385
- const references = this._scanReferences(skillPath)
398
+ const references = this._scanReferences(skillPath);
386
399
 
387
400
  // 扫描 scripts 子目录(可执行脚本)
388
- const scripts = this._scanScripts(skillPath)
401
+ const scripts = this._scanScripts(skillPath);
389
402
 
390
403
  this._skills.set(name, {
391
404
  name,
@@ -394,12 +407,12 @@ class SkillManagerPlugin extends Plugin {
394
407
  instance: skill,
395
408
  path: skillPath,
396
409
  references,
397
- scripts
398
- })
410
+ scripts,
411
+ });
399
412
 
400
- const refsInfo = references.size > 0 ? `, ${references.size} refs` : ''
401
- const scriptsInfo = scripts.size > 0 ? `, ${scripts.size} scripts` : ''
402
- //console.log(`[SkillManager] Loaded skill: ${name}${refsInfo}${scriptsInfo}`)
413
+ const refsInfo = references.size > 0 ? `, ${references.size} refs` : '';
414
+ const scriptsInfo = scripts.size > 0 ? `, ${scripts.size} scripts` : '';
415
+ //log.info(` Loaded skill: ${name}${refsInfo}${scriptsInfo}`)
403
416
  }
404
417
 
405
418
  /**
@@ -408,30 +421,30 @@ class SkillManagerPlugin extends Plugin {
408
421
  * @returns {Map} references 文件映射 { filename: { path, content } }
409
422
  */
410
423
  _scanReferences(skillPath) {
411
- const references = new Map()
412
- const refsDir = path.join(skillPath, 'references')
424
+ const references = new Map();
425
+ const refsDir = path.join(skillPath, 'references');
413
426
 
414
427
  if (!fs.existsSync(refsDir) || !fs.statSync(refsDir).isDirectory()) {
415
- return references
428
+ return references;
416
429
  }
417
430
 
418
431
  try {
419
- const entries = fs.readdirSync(refsDir, { withFileTypes: true })
432
+ const entries = fs.readdirSync(refsDir, { withFileTypes: true });
420
433
  for (const entry of entries) {
421
434
  if (entry.isFile() && entry.name.endsWith('.md')) {
422
- const refPath = path.join(refsDir, entry.name)
423
- const refName = entry.name.replace('.md', '')
435
+ const refPath = path.join(refsDir, entry.name);
436
+ const refName = entry.name.replace('.md', '');
424
437
  references.set(refName, {
425
438
  path: refPath,
426
- content: null // 延迟加载
427
- })
439
+ content: null, // 延迟加载
440
+ });
428
441
  }
429
442
  }
430
443
  } catch (err) {
431
- console.warn(`[SkillManager] Failed to scan references for ${skillPath}:`, err.message)
444
+ log.warn(` Failed to scan references for ${skillPath}:`, err.message);
432
445
  }
433
446
 
434
- return references
447
+ return references;
435
448
  }
436
449
 
437
450
  /**
@@ -440,34 +453,35 @@ class SkillManagerPlugin extends Plugin {
440
453
  * @returns {Map} scripts 映射 { filename: { path, isExecutable } }
441
454
  */
442
455
  _scanScripts(skillPath) {
443
- const scripts = new Map()
444
- const scriptsDir = path.join(skillPath, 'scripts')
456
+ const scripts = new Map();
457
+ const scriptsDir = path.join(skillPath, 'scripts');
445
458
 
446
459
  if (!fs.existsSync(scriptsDir) || !fs.statSync(scriptsDir).isDirectory()) {
447
- return scripts
460
+ return scripts;
448
461
  }
449
462
 
450
463
  try {
451
- const entries = fs.readdirSync(scriptsDir, { withFileTypes: true })
464
+ const entries = fs.readdirSync(scriptsDir, { withFileTypes: true });
452
465
  for (const entry of entries) {
453
466
  if (entry.isFile()) {
454
- const scriptPath = path.join(scriptsDir, entry.name)
467
+ const scriptPath = path.join(scriptsDir, entry.name);
455
468
  // 检查文件是否有执行权限(或检查扩展名)
456
- const isExecutable = entry.name.endsWith('.sh') ||
457
- entry.name.endsWith('.js') ||
458
- entry.name.endsWith('.py') ||
459
- entry.name.endsWith('.ts')
469
+ const isExecutable =
470
+ entry.name.endsWith('.sh') ||
471
+ entry.name.endsWith('.js') ||
472
+ entry.name.endsWith('.py') ||
473
+ entry.name.endsWith('.ts');
460
474
  scripts.set(entry.name, {
461
475
  path: scriptPath,
462
- isExecutable
463
- })
476
+ isExecutable,
477
+ });
464
478
  }
465
479
  }
466
480
  } catch (err) {
467
- console.warn(`[SkillManager] Failed to scan scripts for ${skillPath}:`, err.message)
481
+ log.warn(` Failed to scan scripts for ${skillPath}:`, err.message);
468
482
  }
469
483
 
470
- return scripts
484
+ return scripts;
471
485
  }
472
486
 
473
487
  /**
@@ -477,22 +491,22 @@ class SkillManagerPlugin extends Plugin {
477
491
  * @returns {string|null} 文件内容
478
492
  */
479
493
  loadReference(skillName, refName) {
480
- const skill = this._skills.get(skillName)
494
+ const skill = this._skills.get(skillName);
481
495
  if (!skill || !skill.references.has(refName)) {
482
- return null
496
+ return null;
483
497
  }
484
498
 
485
- const ref = skill.references.get(refName)
499
+ const ref = skill.references.get(refName);
486
500
  if (!ref.content) {
487
501
  try {
488
- ref.content = fs.readFileSync(ref.path, 'utf-8')
502
+ ref.content = fs.readFileSync(ref.path, 'utf-8');
489
503
  } catch (err) {
490
- console.error(`[SkillManager] Failed to load reference ${skillName}/${refName}:`, err.message)
491
- return null
504
+ log.error(` Failed to load reference ${skillName}/${refName}:`, err.message);
505
+ return null;
492
506
  }
493
507
  }
494
508
 
495
- return ref.content
509
+ return ref.content;
496
510
  }
497
511
 
498
512
  /**
@@ -501,9 +515,9 @@ class SkillManagerPlugin extends Plugin {
501
515
  * @returns {string[]} reference 文件名列表
502
516
  */
503
517
  listReferences(skillName) {
504
- const skill = this._skills.get(skillName)
505
- if (!skill) return []
506
- return Array.from(skill.references.keys())
518
+ const skill = this._skills.get(skillName);
519
+ if (!skill) return [];
520
+ return Array.from(skill.references.keys());
507
521
  }
508
522
 
509
523
  /**
@@ -512,13 +526,13 @@ class SkillManagerPlugin extends Plugin {
512
526
  * @returns {Object[]} script 信息列表 [{ name, path, isExecutable }]
513
527
  */
514
528
  listScripts(skillName) {
515
- const skill = this._skills.get(skillName)
516
- if (!skill) return []
529
+ const skill = this._skills.get(skillName);
530
+ if (!skill) return [];
517
531
  return Array.from(skill.scripts.entries()).map(([name, info]) => ({
518
532
  name,
519
533
  path: info.path,
520
- isExecutable: info.isExecutable
521
- }))
534
+ isExecutable: info.isExecutable,
535
+ }));
522
536
  }
523
537
 
524
538
  /**
@@ -528,17 +542,17 @@ class SkillManagerPlugin extends Plugin {
528
542
  * @returns {string|null}
529
543
  */
530
544
  loadScript(skillName, scriptName) {
531
- const skill = this._skills.get(skillName)
545
+ const skill = this._skills.get(skillName);
532
546
  if (!skill || !skill.scripts.has(scriptName)) {
533
- return null
547
+ return null;
534
548
  }
535
549
 
536
- const script = skill.scripts.get(scriptName)
550
+ const script = skill.scripts.get(scriptName);
537
551
  try {
538
- return fs.readFileSync(script.path, 'utf-8')
552
+ return fs.readFileSync(script.path, 'utf-8');
539
553
  } catch (err) {
540
- console.error(`[SkillManager] Failed to load script ${skillName}/${scriptName}:`, err.message)
541
- return null
554
+ log.error(` Failed to load script ${skillName}/${scriptName}:`, err.message);
555
+ return null;
542
556
  }
543
557
  }
544
558
 
@@ -546,42 +560,42 @@ class SkillManagerPlugin extends Plugin {
546
560
  * 获取所有 skills
547
561
  */
548
562
  getAllSkills() {
549
- return Array.from(this._skills.values())
563
+ return Array.from(this._skills.values());
550
564
  }
551
565
 
552
566
  /**
553
567
  * 获取 skill
554
568
  */
555
569
  getSkill(name) {
556
- return this._skills.get(name)
570
+ return this._skills.get(name);
557
571
  }
558
572
 
559
573
  /**
560
574
  * 检查 skill 是否存在
561
575
  */
562
576
  hasSkill(name) {
563
- return this._skills.has(name)
577
+ return this._skills.has(name);
564
578
  }
565
579
 
566
580
  /**
567
581
  * 获取 skill 数量
568
582
  */
569
583
  size() {
570
- return this._skills.size
584
+ return this._skills.size;
571
585
  }
572
586
 
573
587
  reload(framework) {
574
- console.log('[SkillManager] Reloading...')
575
- this._skills.clear()
576
- this._loaded = false
577
- this._framework = framework
578
- this._loadAllSkills()
588
+ log.info(' Reloading...');
589
+ this._skills.clear();
590
+ this._loaded = false;
591
+ this._framework = framework;
592
+ this._loadAllSkills();
579
593
  }
580
594
 
581
595
  uninstall(framework) {
582
- this._skills.clear()
583
- this._framework = null
584
- this._loaded = false
596
+ this._skills.clear();
597
+ this._framework = null;
598
+ this._loaded = false;
585
599
  }
586
600
  }
587
601
 
@@ -591,5 +605,5 @@ module.exports = {
591
605
  SkillMetadata,
592
606
  isValidSkillName,
593
607
  parseFrontmatter,
594
- stripFrontmatter
595
- }
608
+ stripFrontmatter,
609
+ };