foliko 1.0.74 → 1.0.76

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 (238) 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 +11 -1
  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 +11 -11
  128. package/cli/src/commands/chat.js +143 -141
  129. package/cli/src/commands/list.js +93 -90
  130. package/cli/src/index.js +75 -75
  131. package/cli/src/ui/chat-ui.js +201 -199
  132. package/cli/src/utils/ansi.js +40 -40
  133. package/cli/src/utils/markdown.js +292 -296
  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 +194 -196
  140. package/examples/basic.js +50 -45
  141. package/examples/bootstrap.js +121 -112
  142. package/examples/mcp-example.js +19 -16
  143. package/examples/skill-example.js +20 -20
  144. package/examples/test-chat.js +137 -135
  145. package/examples/test-mcp.js +85 -79
  146. package/examples/test-reload.js +59 -61
  147. package/examples/test-telegram.js +50 -50
  148. package/examples/test-tg-bot.js +45 -42
  149. package/examples/test-tg-simple.js +47 -46
  150. package/examples/test-tg.js +62 -62
  151. package/examples/test-think.js +43 -37
  152. package/examples/test-web-plugin.js +103 -98
  153. package/examples/test-weixin-feishu.js +103 -100
  154. package/examples/workflow.js +158 -158
  155. package/package.json +37 -3
  156. package/plugins/ai-plugin.js +102 -100
  157. package/plugins/ambient-agent/EventWatcher.js +113 -0
  158. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  159. package/plugins/ambient-agent/GoalManager.js +197 -0
  160. package/plugins/ambient-agent/Reflector.js +95 -0
  161. package/plugins/ambient-agent/StateStore.js +90 -0
  162. package/plugins/ambient-agent/constants.js +101 -0
  163. package/plugins/ambient-agent/index.js +579 -0
  164. package/plugins/audit-plugin.js +187 -187
  165. package/plugins/default-plugins.js +662 -649
  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 +481 -477
  174. package/plugins/file-system-plugin.js +826 -476
  175. package/plugins/install-plugin.js +199 -197
  176. package/plugins/python-executor-plugin.js +367 -365
  177. package/plugins/python-plugin-loader.js +481 -479
  178. package/plugins/rules-plugin.js +294 -292
  179. package/plugins/scheduler-plugin.js +691 -689
  180. package/plugins/session-plugin.js +369 -367
  181. package/plugins/shell-executor-plugin.js +197 -197
  182. package/plugins/storage-plugin.js +240 -238
  183. package/plugins/subagent-plugin.js +845 -785
  184. package/plugins/telegram-plugin.js +482 -475
  185. package/plugins/think-plugin.js +345 -343
  186. package/plugins/tools-plugin.js +196 -194
  187. package/plugins/web-plugin.js +606 -604
  188. package/plugins/weixin-plugin.js +545 -538
  189. package/reports/system-health-report-20260401.md +79 -0
  190. package/skills/ambient-agent/SKILL.md +49 -39
  191. package/skills/foliko-dev/AGENTS.md +64 -61
  192. package/skills/foliko-dev/SKILL.md +125 -119
  193. package/skills/mcp-usage/SKILL.md +19 -17
  194. package/skills/python-plugin-dev/SKILL.md +16 -15
  195. package/skills/skill-guide/SKILL.md +12 -12
  196. package/skills/subagent-guide/SKILL.md +237 -0
  197. package/skills/workflow-guide/SKILL.md +90 -45
  198. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  199. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  200. package/src/capabilities/index.js +11 -11
  201. package/src/capabilities/skill-manager.js +609 -595
  202. package/src/capabilities/workflow-engine.js +1109 -1195
  203. package/src/core/agent-chat.js +882 -735
  204. package/src/core/agent.js +892 -688
  205. package/src/core/framework.js +465 -431
  206. package/src/core/index.js +19 -19
  207. package/src/core/plugin-base.js +219 -219
  208. package/src/core/plugin-manager.js +863 -767
  209. package/src/core/provider.js +114 -111
  210. package/src/core/sub-agent-config.js +264 -0
  211. package/src/core/system-prompt-builder.js +120 -0
  212. package/src/core/tool-registry.js +517 -134
  213. package/src/core/tool-router.js +297 -216
  214. package/src/executors/executor-base.js +12 -12
  215. package/src/executors/mcp-executor.js +741 -729
  216. package/src/index.js +25 -37
  217. package/src/utils/circuit-breaker.js +301 -0
  218. package/src/utils/error-boundary.js +363 -0
  219. package/src/utils/error.js +374 -0
  220. package/src/utils/event-emitter.js +97 -97
  221. package/src/utils/id.js +133 -0
  222. package/src/utils/index.js +217 -3
  223. package/src/utils/logger.js +181 -0
  224. package/src/utils/plugin-helpers.js +90 -0
  225. package/src/utils/retry.js +122 -0
  226. package/src/utils/sandbox.js +292 -0
  227. package/test/tool-registry-validation.test.js +218 -0
  228. package/test_report.md +70 -0
  229. package/website/docs/api.html +169 -107
  230. package/website/docs/configuration.html +296 -144
  231. package/website/docs/plugin-development.html +154 -85
  232. package/website/docs/project-structure.html +110 -109
  233. package/website/docs/skill-development.html +117 -61
  234. package/website/index.html +209 -205
  235. package/website/script.js +136 -133
  236. package/website/styles.css +1 -1
  237. package/plugins/ambient-agent-plugin.js +0 -1565
  238. package/plugins/email.js +0 -1142
@@ -1,111 +1,114 @@
1
- /**
2
- * AI Provider 工厂
3
- * 支持多种 AI 提供商
4
- */
5
-
6
- const { createOpenAICompatible } = require('@ai-sdk/openai-compatible')
7
- const { createOpenAI } = require('@ai-sdk/openai')
8
- const { createAnthropic } = require('@ai-sdk/anthropic')
9
-
10
- /**
11
- * 默认提供商配置
12
- */
13
- const DEFAULT_PROVIDERS = {
14
- openai: {
15
- name: 'OpenAI',
16
- baseURL: 'https://api.openai.com/v1'
17
- },
18
- ollama: {
19
- name: 'Ollama',
20
- baseURL: 'http://localhost:11434/v1'
21
- },
22
- lmstudio: {
23
- name: 'LM Studio',
24
- baseURL: 'http://localhost:1234/v1'
25
- },
26
- deepseek: {
27
- name: 'DeepSeek',
28
- baseURL: 'https://api.deepseek.com/v1'
29
- },
30
- anthropic: {
31
- name: 'Anthropic',
32
- baseURL: 'https://api.anthropic.com/v1'
33
- },
34
- minimax: {
35
- name: 'MiniMax',
36
- baseURL: 'https://api.minimaxi.com/v1'
37
- }
38
- }
39
-
40
- /**
41
- * 创建 AI 客户端
42
- * @param {Object} config - 配置
43
- * @param {string} config.provider - 提供商名称
44
- * @param {string} config.model - 模型名称
45
- * @param {string} config.apiKey - API 密钥
46
- * @param {string} [config.baseURL] - 自定义 API 地址
47
- */
48
- function createAI(config) {
49
- const { provider, model, apiKey, baseURL } = config
50
- const providerName = (provider || 'deepseek').toLowerCase()
51
- // 检查是否是预定义提供商
52
- if (DEFAULT_PROVIDERS[providerName]) {
53
- const providerConfig = DEFAULT_PROVIDERS[providerName]
54
- return createOpenAICompatible({
55
- name: providerConfig.name,
56
- baseURL: baseURL || providerConfig.baseURL,
57
- apiKey: apiKey || 'dummy-key',
58
- headers: provider === 'anthropic' ? {
59
- 'x-api-key': apiKey,
60
- 'anthropic-version': '2023-06-01'
61
- } : undefined,
62
- models: {
63
- default: {
64
- id: model || 'deepseek-chat',
65
- streamOptions: {
66
- includeUsage: true
67
- }
68
- }
69
- }
70
- })
71
- }
72
-
73
- // 自定义提供商
74
- return createOpenAICompatible({
75
- name: providerName || 'Custom',
76
- baseURL: baseURL,
77
- apiKey: apiKey || 'dummy-key',
78
- models: {
79
- default: {
80
- id: model || 'gpt-4'
81
- }
82
- }
83
- })
84
- }
85
-
86
- /**
87
- * 获取可用提供商列表
88
- */
89
- function getAvailableProviders() {
90
- return Object.entries(DEFAULT_PROVIDERS).map(([key, value]) => ({
91
- id: key,
92
- name: value.name,
93
- baseURL: value.baseURL
94
- }))
95
- }
96
-
97
- /**
98
- * 创建模型实例
99
- * @param {string} model - 模型名称
100
- * @param {Object} provider - Provider 实例
101
- */
102
- function createModel(model, provider) {
103
- return provider(model)
104
- }
105
-
106
- module.exports = {
107
- createAI,
108
- createModel,
109
- getAvailableProviders,
110
- DEFAULT_PROVIDERS
111
- }
1
+ /**
2
+ * AI Provider 工厂
3
+ * 支持多种 AI 提供商
4
+ */
5
+
6
+ const { createOpenAICompatible } = require('@ai-sdk/openai-compatible');
7
+ const { createOpenAI } = require('@ai-sdk/openai');
8
+ const { createAnthropic } = require('@ai-sdk/anthropic');
9
+
10
+ /**
11
+ * 默认提供商配置
12
+ */
13
+ const DEFAULT_PROVIDERS = {
14
+ openai: {
15
+ name: 'OpenAI',
16
+ baseURL: 'https://api.openai.com/v1',
17
+ },
18
+ ollama: {
19
+ name: 'Ollama',
20
+ baseURL: 'http://localhost:11434/v1',
21
+ },
22
+ lmstudio: {
23
+ name: 'LM Studio',
24
+ baseURL: 'http://localhost:1234/v1',
25
+ },
26
+ deepseek: {
27
+ name: 'DeepSeek',
28
+ baseURL: 'https://api.deepseek.com/v1',
29
+ },
30
+ anthropic: {
31
+ name: 'Anthropic',
32
+ baseURL: 'https://api.anthropic.com/v1',
33
+ },
34
+ minimax: {
35
+ name: 'MiniMax',
36
+ baseURL: 'https://api.minimaxi.com/v1',
37
+ },
38
+ };
39
+
40
+ /**
41
+ * 创建 AI 客户端
42
+ * @param {Object} config - 配置
43
+ * @param {string} config.provider - 提供商名称
44
+ * @param {string} config.model - 模型名称
45
+ * @param {string} config.apiKey - API 密钥
46
+ * @param {string} [config.baseURL] - 自定义 API 地址
47
+ */
48
+ function createAI(config) {
49
+ const { provider, model, apiKey, baseURL } = config;
50
+ const providerName = (provider || 'deepseek').toLowerCase();
51
+ // 检查是否是预定义提供商
52
+ if (DEFAULT_PROVIDERS[providerName]) {
53
+ const providerConfig = DEFAULT_PROVIDERS[providerName];
54
+ return createOpenAICompatible({
55
+ name: providerConfig.name,
56
+ baseURL: baseURL || providerConfig.baseURL,
57
+ apiKey: apiKey || 'dummy-key',
58
+ headers:
59
+ provider === 'anthropic'
60
+ ? {
61
+ 'x-api-key': apiKey,
62
+ 'anthropic-version': '2023-06-01',
63
+ }
64
+ : undefined,
65
+ models: {
66
+ default: {
67
+ id: model || 'deepseek-chat',
68
+ streamOptions: {
69
+ includeUsage: true,
70
+ },
71
+ },
72
+ },
73
+ });
74
+ }
75
+
76
+ // 自定义提供商
77
+ return createOpenAICompatible({
78
+ name: providerName || 'Custom',
79
+ baseURL: baseURL,
80
+ apiKey: apiKey || 'dummy-key',
81
+ models: {
82
+ default: {
83
+ id: model || 'gpt-4',
84
+ },
85
+ },
86
+ });
87
+ }
88
+
89
+ /**
90
+ * 获取可用提供商列表
91
+ */
92
+ function getAvailableProviders() {
93
+ return Object.entries(DEFAULT_PROVIDERS).map(([key, value]) => ({
94
+ id: key,
95
+ name: value.name,
96
+ baseURL: value.baseURL,
97
+ }));
98
+ }
99
+
100
+ /**
101
+ * 创建模型实例
102
+ * @param {string} model - 模型名称
103
+ * @param {Object} provider - Provider 实例
104
+ */
105
+ function createModel(model, provider) {
106
+ return provider(model);
107
+ }
108
+
109
+ module.exports = {
110
+ createAI,
111
+ createModel,
112
+ getAvailableProviders,
113
+ DEFAULT_PROVIDERS,
114
+ };
@@ -0,0 +1,264 @@
1
+ /**
2
+ * SubAgent 配置管理
3
+ * 负责读取、解析和缓存 .agent/agents/ 目录下的 md 文件
4
+ * 类似 SkillManager 的工作方式
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ /**
11
+ * 解析 YAML frontmatter
12
+ */
13
+ function parseFrontmatter(content) {
14
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
15
+ if (!match) return null;
16
+
17
+ const frontmatter = {};
18
+ const lines = match[1].split('\n');
19
+ let currentKey = null;
20
+
21
+ for (const line of lines) {
22
+ // 处理 metadata 嵌套
23
+ if (currentKey === 'metadata') {
24
+ if (line.match(/^ {2}[a-zA-Z]/)) {
25
+ const colonIndex = line.indexOf(':');
26
+ if (colonIndex > 0) {
27
+ const key = line.substring(2, colonIndex).trim();
28
+ const value = line
29
+ .substring(colonIndex + 1)
30
+ .trim()
31
+ .replace(/^["']|["']$/g, '');
32
+ frontmatter[currentKey][key] = value;
33
+ continue;
34
+ }
35
+ } else if (line.match(/^[a-zA-Z]/)) {
36
+ currentKey = null;
37
+ continue;
38
+ }
39
+ }
40
+
41
+ const colonIndex = line.indexOf(':');
42
+ if (colonIndex === -1) continue;
43
+
44
+ const key = line.substring(0, colonIndex).trim();
45
+ let value = line.substring(colonIndex + 1).trim();
46
+
47
+ // 移除引号
48
+ if (
49
+ (value.startsWith('"') && value.endsWith('"')) ||
50
+ (value.startsWith("'") && value.endsWith("'"))
51
+ ) {
52
+ value = value.slice(1, -1);
53
+ }
54
+
55
+ if (key === 'metadata') {
56
+ currentKey = 'metadata';
57
+ frontmatter.metadata = {};
58
+ } else if (key === 'allowed-tools') {
59
+ frontmatter[key] = value
60
+ .split(',')
61
+ .map((v) => v.trim())
62
+ .filter(Boolean);
63
+ } else if (key === 'skills') {
64
+ frontmatter[key] = value
65
+ .split(',')
66
+ .map((v) => v.trim())
67
+ .filter(Boolean);
68
+ } else if (key === 'tools') {
69
+ frontmatter[key] = value
70
+ .split(',')
71
+ .map((v) => v.trim())
72
+ .filter(Boolean);
73
+ } else {
74
+ frontmatter[key] = value;
75
+ }
76
+ }
77
+
78
+ return frontmatter;
79
+ }
80
+
81
+ /**
82
+ * 移除 frontmatter,只保留正文内容
83
+ */
84
+ function stripFrontmatter(content) {
85
+ return content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n/, '');
86
+ }
87
+
88
+ class SubAgentConfig {
89
+ constructor(name, filePath) {
90
+ this.name = name;
91
+ this.filePath = filePath;
92
+ this._frontmatter = null;
93
+ this._content = null;
94
+ this._loaded = false;
95
+ }
96
+
97
+ /**
98
+ * 加载并解析 md 文件
99
+ */
100
+ load() {
101
+ if (this._loaded) return;
102
+
103
+ try {
104
+ const content = fs.readFileSync(this.filePath, 'utf-8');
105
+ this._frontmatter = parseFrontmatter(content);
106
+ this._content = stripFrontmatter(content);
107
+ this._loaded = true;
108
+ } catch (e) {
109
+ console.warn(`[SubAgentConfig] Failed to load ${this.filePath}:`, e.message);
110
+ this._frontmatter = {};
111
+ this._content = '';
112
+ this._loaded = true;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * 获取 frontmatter 中的值
118
+ */
119
+ get(key, defaultValue = null) {
120
+ this.load();
121
+ return this._frontmatter?.[key] ?? defaultValue;
122
+ }
123
+
124
+ /**
125
+ * 获取名称
126
+ */
127
+ getName() {
128
+ return this.get('name', this.name);
129
+ }
130
+
131
+ /**
132
+ * 获取描述
133
+ */
134
+ getDescription() {
135
+ return this.get('description', '');
136
+ }
137
+
138
+ /**
139
+ * 获取技能列表
140
+ */
141
+ getSkills() {
142
+ return this.get('skills', []);
143
+ }
144
+
145
+ /**
146
+ * 获取工具列表
147
+ */
148
+ getTools() {
149
+ return this.get('tools', []);
150
+ }
151
+
152
+ /**
153
+ * 获取模型配置
154
+ */
155
+ getModel() {
156
+ return this.get('model', 'inherit');
157
+ }
158
+
159
+ /**
160
+ * 获取完整内容(用于构建系统提示词)
161
+ */
162
+ getContent() {
163
+ this.load();
164
+ return this._content || '';
165
+ }
166
+
167
+ /**
168
+ * 获取完整的系统提示词(frontmatter + 内容)
169
+ */
170
+ getSystemPrompt() {
171
+ this.load();
172
+ const desc = this.getDescription();
173
+ const content = this._content || '';
174
+
175
+ // 构建系统提示词
176
+ let prompt = `# ${this.getName()}`;
177
+ if (desc) {
178
+ prompt += `\n\n${desc}`;
179
+ }
180
+ if (content.trim()) {
181
+ prompt += `\n\n${content.trim()}`;
182
+ }
183
+ return prompt;
184
+ }
185
+
186
+ /**
187
+ * 检查是否有效
188
+ */
189
+ isValid() {
190
+ this.load();
191
+ return this._loaded && this._frontmatter !== null;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * SubAgent 配置管理器
197
+ * 管理目录下所有子代理配置的加载和缓存
198
+ */
199
+ class SubAgentConfigManager {
200
+ constructor(agentsDir) {
201
+ this.agentsDir = agentsDir;
202
+ this._configs = new Map(); // name -> SubAgentConfig
203
+ }
204
+
205
+ /**
206
+ * 加载目录下所有子代理配置
207
+ */
208
+ loadAll() {
209
+ if (!fs.existsSync(this.agentsDir)) {
210
+ return;
211
+ }
212
+
213
+ const entries = fs.readdirSync(this.agentsDir, { withFileTypes: true });
214
+ for (const entry of entries) {
215
+ if (entry.isFile() && entry.name.endsWith('.md')) {
216
+ const name = entry.name.replace('.md', '');
217
+ const filePath = path.join(this.agentsDir, entry.name);
218
+
219
+ if (!this._configs.has(name)) {
220
+ this._configs.set(name, new SubAgentConfig(name, filePath));
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ /**
227
+ * 刷新配置(清除后重新加载)
228
+ */
229
+ refresh() {
230
+ this._configs.clear();
231
+ this.loadAll();
232
+ }
233
+
234
+ /**
235
+ * 获取某个子代理配置
236
+ */
237
+ get(name) {
238
+ return this._configs.get(name) || null;
239
+ }
240
+
241
+ /**
242
+ * 获取所有配置
243
+ */
244
+ getAll() {
245
+ return Array.from(this._configs.values());
246
+ }
247
+
248
+ /**
249
+ * 获取所有有效配置
250
+ */
251
+ getValidConfigs() {
252
+ return this.getAll().filter((c) => c.isValid());
253
+ }
254
+
255
+ /**
256
+ * 重新加载
257
+ */
258
+ reload() {
259
+ this._configs.clear();
260
+ this.loadAll();
261
+ }
262
+ }
263
+
264
+ module.exports = { SubAgentConfig, SubAgentConfigManager, parseFrontmatter, stripFrontmatter };
@@ -0,0 +1,120 @@
1
+ /**
2
+ * 系统提示词构建器
3
+ * 负责从多个来源组合系统提示词各部分
4
+ * 支持插件注册自己的提示词部分,支持重载后更新
5
+ */
6
+
7
+ class SystemPromptPart {
8
+ constructor(name, priority, provider) {
9
+ this.name = name;
10
+ this.priority = priority;
11
+ this._provider = provider;
12
+ this._dirty = true;
13
+ this._cached = null;
14
+ }
15
+
16
+ get() {
17
+ if (this._dirty || this._cached === null) {
18
+ try {
19
+ this._cached = this._provider();
20
+ this._dirty = false;
21
+ } catch (e) {
22
+ console.warn(`[SystemPromptPart:${this.name}] Provider failed:`, e.message);
23
+ this._cached = null;
24
+ }
25
+ }
26
+ return this._cached;
27
+ }
28
+
29
+ invalidate() {
30
+ this._dirty = true;
31
+ }
32
+ }
33
+
34
+ class SystemPromptBuilder {
35
+ constructor() {
36
+ this._parts = new Map(); // name -> SystemPromptPart
37
+ this._orderedParts = []; // sorted by priority
38
+ }
39
+
40
+ /**
41
+ * 注册一个提示词部分
42
+ * @param {string} name - 部分名称(唯一标识)
43
+ * @param {number} priority - 优先级(数字越小越靠前)
44
+ * @param {Function} provider - 返回提示词内容的函数
45
+ */
46
+ register(name, priority, provider) {
47
+ const part = new SystemPromptPart(name, priority, provider);
48
+ this._parts.set(name, part);
49
+ this._reorder();
50
+ return this;
51
+ }
52
+
53
+ /**
54
+ * 注销一个提示词部分
55
+ */
56
+ unregister(name) {
57
+ this._parts.delete(name);
58
+ this._reorder();
59
+ return this;
60
+ }
61
+
62
+ /**
63
+ * 使某个部分失效(下次 get 时会重新计算)
64
+ */
65
+ invalidate(name) {
66
+ const part = this._parts.get(name);
67
+ if (part) {
68
+ part.invalidate();
69
+ }
70
+ return this;
71
+ }
72
+
73
+ /**
74
+ * 使所有部分失效
75
+ */
76
+ invalidateAll() {
77
+ for (const part of this._parts.values()) {
78
+ part.invalidate();
79
+ }
80
+ return this;
81
+ }
82
+
83
+ /**
84
+ * 获取某个部分的内容
85
+ */
86
+ getPart(name) {
87
+ const part = this._parts.get(name);
88
+ return part ? part.get() : null;
89
+ }
90
+
91
+ /**
92
+ * 构建完整的系统提示词
93
+ * @returns {string}
94
+ */
95
+ build() {
96
+ const parts = [];
97
+ for (const part of this._orderedParts) {
98
+ const content = part.get();
99
+ if (content && content.trim()) {
100
+ parts.push(content.trim());
101
+ }
102
+ }
103
+ return parts.join('\n\n');
104
+ }
105
+
106
+ /**
107
+ * 获取所有部分名称
108
+ */
109
+ getPartNames() {
110
+ return [...this._parts.keys()];
111
+ }
112
+
113
+ _reorder() {
114
+ this._orderedParts = Array.from(this._parts.values()).sort(
115
+ (a, b) => a.priority - b.priority
116
+ );
117
+ }
118
+ }
119
+
120
+ module.exports = { SystemPromptBuilder, SystemPromptPart };