foliko 1.1.0 → 1.1.1

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 (189) 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 +412 -3
  39. package/.agent/data/plugins-state.json +173 -174
  40. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  43. package/.agent/plugins/poster-plugin/src/elements/polygon.js +37 -6
  44. package/.agent/plugins/poster-plugin/src/elements/text.js +71 -2
  45. package/.agent/plugins/poster-plugin/src/fonts.js +123 -8
  46. package/.agent/plugins/poster-plugin/src/index.js +15 -16
  47. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  48. package/.agent/plugins/puppeteer-plugin/index.js +1418 -0
  49. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  50. package/.agent/plugins.json +5 -11
  51. package/.agent/rules/GEMINI.md +273 -0
  52. package/.agent/rules/allow-rule.md +77 -0
  53. package/.agent/rules/log-rule.md +83 -0
  54. package/.agent/rules/security-rule.md +93 -0
  55. package/.agent/scripts/auto_preview.py +148 -0
  56. package/.agent/scripts/checklist.py +217 -0
  57. package/.agent/scripts/session_manager.py +120 -0
  58. package/.agent/scripts/verify_all.py +327 -0
  59. package/.agent/sessions/cli_default.json +135 -23981
  60. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +2195 -0
  61. package/.agent/skills/api-patterns/SKILL.md +81 -0
  62. package/.agent/skills/api-patterns/api-style.md +42 -0
  63. package/.agent/skills/api-patterns/auth.md +24 -0
  64. package/.agent/skills/api-patterns/documentation.md +26 -0
  65. package/.agent/skills/api-patterns/graphql.md +41 -0
  66. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  67. package/.agent/skills/api-patterns/response.md +37 -0
  68. package/.agent/skills/api-patterns/rest.md +40 -0
  69. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  70. package/.agent/skills/api-patterns/security-testing.md +122 -0
  71. package/.agent/skills/api-patterns/trpc.md +41 -0
  72. package/.agent/skills/api-patterns/versioning.md +22 -0
  73. package/.agent/skills/app-builder/SKILL.md +75 -0
  74. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  75. package/.agent/skills/app-builder/feature-building.md +53 -0
  76. package/.agent/skills/app-builder/project-detection.md +34 -0
  77. package/.agent/skills/app-builder/scaffolding.md +118 -0
  78. package/.agent/skills/app-builder/tech-stack.md +40 -0
  79. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  80. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  81. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  82. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  83. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  84. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  85. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  86. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  87. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  88. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  89. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  90. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  91. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  92. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  93. package/.agent/skills/architecture/SKILL.md +55 -0
  94. package/.agent/skills/architecture/context-discovery.md +43 -0
  95. package/.agent/skills/architecture/examples.md +94 -0
  96. package/.agent/skills/architecture/pattern-selection.md +68 -0
  97. package/.agent/skills/architecture/patterns-reference.md +50 -0
  98. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  99. package/.agent/skills/clean-code/SKILL.md +201 -0
  100. package/.agent/skills/doc.md +177 -0
  101. package/.agent/skills/frontend-design/SKILL.md +418 -0
  102. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  103. package/.agent/skills/frontend-design/color-system.md +311 -0
  104. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  105. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  106. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  107. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  108. package/.agent/skills/frontend-design/typography-system.md +345 -0
  109. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  110. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  111. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  112. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  113. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  114. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  115. package/.agent/workflows/brainstorm.md +113 -0
  116. package/.agent/workflows/create.md +59 -0
  117. package/.agent/workflows/debug.md +103 -0
  118. package/.agent/workflows/deploy.md +176 -0
  119. package/.agent/workflows/enhance.md +63 -0
  120. package/.agent/workflows/orchestrate.md +237 -0
  121. package/.agent/workflows/plan.md +89 -0
  122. package/.agent/workflows/preview.md +81 -0
  123. package/.agent/workflows/simple-test.md +42 -0
  124. package/.agent/workflows/status.md +86 -0
  125. package/.agent/workflows/structured-orchestrate.md +180 -0
  126. package/.agent/workflows/test.md +144 -0
  127. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  128. package/.claude/settings.local.json +16 -1
  129. package/.env.example +56 -56
  130. package/README.md +441 -441
  131. package/calc_tokens_weixin.js +81 -0
  132. package/cli/src/commands/chat.js +2 -1
  133. package/foliko-creative-3.png +0 -0
  134. package/foliko-creative-4.png +0 -0
  135. package/foliko-creative-5.png +0 -0
  136. package/package.json +1 -1
  137. package/plugins/extension-executor-plugin.js +80 -2
  138. package/plugins/file-system-plugin.js +2 -2
  139. package/plugins/weixin-plugin.js +10 -2
  140. package/skills/find-skills/AGENTS.md +162 -162
  141. package/skills/find-skills/SKILL.md +133 -133
  142. package/skills/poster-guide/SKILL.md +948 -632
  143. package/src/core/agent-chat.js +82 -3
  144. package/story-cover-book-v2.png +0 -0
  145. package/story-cover-japanese-1.png +0 -0
  146. package/story-cover-japanese-2.png +0 -0
  147. package/story-cover-japanese-3.png +0 -0
  148. package/story-cover-moran.png +0 -0
  149. package/undefined.png +0 -0
  150. package/.agent/agents/code-assistant.json +0 -14
  151. package/.agent/agents/email-assistant.json +0 -14
  152. package/.agent/agents/file-assistant.json +0 -15
  153. package/.agent/agents/system-assistant.json +0 -15
  154. package/.agent/agents/web-assistant.json +0 -12
  155. package/.agent/data/ambient/goals.json +0 -50
  156. package/.agent/data/ambient/memories.json +0 -7
  157. package/.agent/data/scheduler/tasks.json +0 -1
  158. package/.agent/memory/core.md +0 -1
  159. package/.agent/memory/project/mnn93ogy-ypjn27.md +0 -9
  160. package/.agent/memory/project/mnn98fqy-5nhc1u.md +0 -25
  161. package/.agent/memory/user/mnm67t9m-x8rekk.md +0 -9
  162. package/.agent/memory/user/mnn5mmqh-w6aktx.md +0 -11
  163. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +0 -22
  164. package/.agent/package.json +0 -8
  165. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  166. package/.agent/plugins/daytona/README.md +0 -89
  167. package/.agent/plugins/daytona/index.js +0 -377
  168. package/.agent/plugins/daytona/package.json +0 -12
  169. package/.agent/plugins/marknative/README.md +0 -134
  170. package/.agent/plugins/marknative/index.js +0 -228
  171. package/.agent/plugins/marknative/package.json +0 -12
  172. package/.agent/plugins/marknative/update-readme.js +0 -134
  173. package/.agent/plugins/system-info/index.js +0 -387
  174. package/.agent/plugins/system-info/package.json +0 -4
  175. package/.agent/plugins/system-info/test.js +0 -40
  176. package/.agent/python-scripts/test_sample.py +0 -24
  177. package/.agent/skills/agent-browser/SKILL.md +0 -311
  178. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  179. package/.agent/skills/sysinfo/SKILL.md +0 -38
  180. package/.agent/skills/sysinfo/system-info.sh +0 -130
  181. package/.agent/skills/workflow/SKILL.md +0 -324
  182. package/.agent/weixin.json +0 -6
  183. package/.agent/workflows/email-digest.json +0 -50
  184. package/.agent/workflows/file-backup.json +0 -21
  185. package/.agent/workflows/get-ip-notify.json +0 -32
  186. package/.agent/workflows/news-aggregator.json +0 -93
  187. package/.agent/workflows/news-dashboard-v2.json +0 -94
  188. package/.agent/workflows/notification-batch.json +0 -32
  189. package/output/beef-love-poster.png +0 -0
@@ -0,0 +1,81 @@
1
+ const fs = require('fs');
2
+
3
+ function encode(text) {
4
+ if (!text || typeof text !== 'string') return 0;
5
+ const cleanText = text.replace(/\0+/g, '').replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '').slice(0, 100000);
6
+ if (!cleanText) return 0;
7
+ const chineseChars = (cleanText.match(/[\u4e00-\u9fff\u3400-\u4dbf]/g) || []).length;
8
+ const englishChars = cleanText.length - chineseChars;
9
+ const chineseTokens = chineseChars / 2;
10
+ const englishTokens = englishChars / 4;
11
+ return Math.ceil(chineseTokens + englishTokens);
12
+ }
13
+
14
+ const filePath = 'D:/code/vb-agent/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json';
15
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
16
+
17
+ let totalTokens = 0;
18
+ let totalChars = 0;
19
+ let largeMessages = [];
20
+ const messages = data.messages || [];
21
+
22
+ for (let i = 0; i < messages.length; i++) {
23
+ const msg = messages[i];
24
+ let msgTokens = 4;
25
+ let msgChars = 0;
26
+
27
+ if (typeof msg.content === 'string') {
28
+ msgTokens += encode(msg.content);
29
+ msgChars += msg.content.length;
30
+ } else if (Array.isArray(msg.content)) {
31
+ for (const part of msg.content) {
32
+ if (!part || typeof part !== 'object') continue;
33
+ if (part.text) {
34
+ const text = String(part.text);
35
+ msgTokens += encode(text);
36
+ msgChars += text.length;
37
+ }
38
+ if (part.type === 'tool-result' && part.output) {
39
+ let outputText = '';
40
+ if (typeof part.output === 'string') {
41
+ outputText = part.output;
42
+ } else if (part.output && part.output.value) {
43
+ outputText = String(part.output.value);
44
+ } else if (part.output && part.output.html) {
45
+ outputText = part.output.html;
46
+ } else if (part.output) {
47
+ outputText = JSON.stringify(part.output);
48
+ }
49
+ msgTokens += encode(outputText);
50
+ msgChars += outputText.length;
51
+ }
52
+ if (part.type === 'tool_use' && part.input) {
53
+ const inputStr = JSON.stringify(part.input);
54
+ msgTokens += encode(inputStr);
55
+ msgChars += inputStr.length;
56
+ }
57
+ }
58
+ } else if (msg.content && typeof msg.content === 'object') {
59
+ try {
60
+ const str = JSON.stringify(msg.content);
61
+ msgTokens += encode(str);
62
+ msgChars += str.length;
63
+ } catch (e) {}
64
+ }
65
+
66
+ totalTokens += msgTokens;
67
+ totalChars += msgChars;
68
+
69
+ if (msgTokens > 3000) {
70
+ largeMessages.push({ index: i, role: msg.role, tokens: msgTokens, chars: msgChars });
71
+ }
72
+ }
73
+
74
+ console.log('Messages:', messages.length);
75
+ console.log('Total chars:', totalChars);
76
+ console.log('Total tokens (approx):', totalTokens);
77
+ console.log('File size:', fs.statSync(filePath).size, 'bytes');
78
+ console.log('\nLarge messages (>3000 tokens):');
79
+ largeMessages.forEach(m => {
80
+ console.log(` [${m.index}] ${m.role}: ${m.tokens} tokens, ${m.chars} chars`);
81
+ });
@@ -94,7 +94,8 @@ async function chatCommand(args) {
94
94
  baseURL: options.baseURL,
95
95
  apiKey: options.apiKey,
96
96
  providerOptions: {
97
- maxOutputTokens: 8192,
97
+ maxOutputTokens: 16384,
98
+ reasoning_split: true,
98
99
  },
99
100
  },
100
101
  });
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -23,6 +23,52 @@ class ExtensionExecutorPlugin extends Plugin {
23
23
  this._extensions = new Map();
24
24
  }
25
25
 
26
+ /**
27
+ * 从 JSON Schema 构建 Zod Schema
28
+ * @param {Object} jsonSchema - JSON Schema 对象
29
+ * @returns {z.ZodObject}
30
+ */
31
+ _buildZodSchema(jsonSchema) {
32
+ const properties = jsonSchema.properties || {};
33
+ const required = jsonSchema.required || [];
34
+ const shape = {};
35
+
36
+ for (const [name, prop] of Object.entries(properties)) {
37
+ let field;
38
+ const isRequired = required.includes(name);
39
+
40
+ switch (prop.type) {
41
+ case 'string':
42
+ field = z.string();
43
+ break;
44
+ case 'number':
45
+ field = z.number();
46
+ break;
47
+ case 'boolean':
48
+ field = z.boolean();
49
+ break;
50
+ case 'array':
51
+ field = z.array(z.any());
52
+ break;
53
+ case 'object':
54
+ field = z.object({});
55
+ break;
56
+ default:
57
+ field = z.any();
58
+ }
59
+
60
+ if (prop.description) {
61
+ field = field.describe(prop.description);
62
+ }
63
+ if (!isRequired) {
64
+ field = field.optional();
65
+ }
66
+ shape[name] = field;
67
+ }
68
+
69
+ return z.object(shape);
70
+ }
71
+
26
72
  install(framework) {
27
73
  this._framework = framework;
28
74
 
@@ -142,7 +188,35 @@ class ExtensionExecutorPlugin extends Plugin {
142
188
 
143
189
  const toolDef = ext.tools.find((t) => t.name === tool);
144
190
  if (!toolDef) {
145
- return { success: false, error: `扩展工具 '${tool}' 不存在` };
191
+ const availableTools = ext.tools.map((t) => t.name).join(', ');
192
+ return {
193
+ success: false,
194
+ error: `扩展工具 '${tool}' 不存在。可用工具: ${availableTools || '无'}`
195
+ };
196
+ }
197
+
198
+ // 验证参数
199
+ if (toolDef.inputSchema) {
200
+ try {
201
+ const schema = toolDef.inputSchema instanceof z.ZodType
202
+ ? toolDef.inputSchema
203
+ : this._buildZodSchema(toolDef.inputSchema);
204
+ schema.parse(toolArgs);
205
+ } catch (err) {
206
+ if (err instanceof z.ZodError) {
207
+ const fieldErrors = err.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join('; ');
208
+ return {
209
+ success: false,
210
+ error: `参数错误: ${fieldErrors}`,
211
+ inputSchema: toolDef.inputSchema,
212
+ };
213
+ }
214
+ return {
215
+ success: false,
216
+ error: `参数验证失败: ${err.message}`,
217
+ inputSchema: toolDef.inputSchema,
218
+ };
219
+ }
146
220
  }
147
221
 
148
222
  try {
@@ -220,7 +294,11 @@ class ExtensionExecutorPlugin extends Plugin {
220
294
 
221
295
  const toolDef = ext.tools.find((t) => t.name === tool);
222
296
  if (!toolDef) {
223
- return { success: false, error: `扩展工具 '${tool}' 不存在` };
297
+ const availableTools = ext.tools.map((t) => t.name).join(', ');
298
+ return {
299
+ success: false,
300
+ error: `扩展工具 '${tool}' 不存在。可用工具: ${availableTools || '无'}`
301
+ };
224
302
  }
225
303
 
226
304
  return {
@@ -827,10 +827,10 @@ class FileSystemPlugin extends Plugin {
827
827
  timeout: z.number().optional().describe('超时时间(ms),默认 30000'),
828
828
  proxy: z.boolean().optional().describe('是否使用代理,默认 false。访问失败时可自动设为 true 重试'),
829
829
  toMarkdown: z.boolean().default(true).describe('是否将 HTML 响应转换为 Markdown 格式,默认 true'),
830
- maxLength: z.number().optional().describe('最大返回长度(字符数),超过则截断')
830
+ maxLength: z.number().default(50000).describe('最大返回长度(字符数),超过则截断,默认 50000')
831
831
  }),
832
832
  execute: async (args, framework) => {
833
- const { url, method = 'GET', headers = {}, body, timeout = 30000, proxy = false, toMarkdown = true, maxLength } = args
833
+ const { url, method = 'GET', headers = {}, body, timeout = 30000, proxy = false, toMarkdown = true, maxLength = 50000 } = args
834
834
  try {
835
835
  const controller = new AbortController()
836
836
  const timeoutId = setTimeout(() => controller.abort(), timeout)
@@ -6,7 +6,7 @@
6
6
  * - forceLogin: 是否强制重新扫码登录
7
7
  * - qrcodeTerminal: 是否在终端渲染二维码 (默认 true)
8
8
  */
9
-
9
+ const { CLEAR_LINE, CYAN, DIM, GREEN, RED, YELLOW, colored } = require('../cli/src/utils/ansi');
10
10
  const { Plugin } = require('../src/core/plugin-base')
11
11
  const { logger } = require('../src/utils/logger')
12
12
  const log = logger.child('WeChat')
@@ -468,11 +468,14 @@ class WeixinPlugin extends Plugin {
468
468
 
469
469
  try {
470
470
  // 使用 chatStream 保持和 CLI 一致的行为
471
-
472
471
  let fullResponse = '';
473
472
  for await (const chunk of agent.chatStream(text, { sessionId })) {
474
473
  if (chunk.type === 'text') {
475
474
  fullResponse += chunk.text;
475
+ } else if (chunk.type === 'tool-call') {
476
+ log.info(`[工具调用] ${chunk.toolName}`);
477
+ } else if (chunk.type === 'error') {
478
+ log.warn(' Chat stream error:', chunk.error);
476
479
  }
477
480
  }
478
481
  const response = cleanResponse(fullResponse);
@@ -516,6 +519,11 @@ class WeixinPlugin extends Plugin {
516
519
  for await (const chunk of agent.chatStream(text, { sessionId })) {
517
520
  if (chunk.type === 'text') {
518
521
  fullResponse += chunk.text;
522
+ } else if (chunk.type === 'tool-call') {
523
+ // 发送工具调用提示
524
+ log.info(`[工具调用] ${chunk.toolName}`);
525
+ } else if (chunk.type === 'error') {
526
+ log.warn(' Chat stream error:', chunk.error);
519
527
  }
520
528
  }
521
529
  const response = cleanResponse(fullResponse);
@@ -1,162 +1,162 @@
1
- # AGENTS.md
2
-
3
- This file provides guidance to AI coding agents working on the `skills` CLI codebase.
4
-
5
- ## Project Overview
6
-
7
- `skills` is the CLI for the open agent skills ecosystem.
8
-
9
- ## Commands
10
-
11
- | Command | Description |
12
- | ----------------------------- | --------------------------------------------------- |
13
- | `skills` | Show banner with available commands |
14
- | `skills add <pkg>` | Install skills from git repos, URLs, or local paths |
15
- | `skills experimental_install` | Restore skills from skills-lock.json |
16
- | `skills experimental_sync` | Sync skills from node_modules into agent dirs |
17
- | `skills list` | List installed skills (alias: `ls`) |
18
- | `skills check` | Check for available skill updates |
19
- | `skills update` | Update all skills to latest versions |
20
- | `skills init [name]` | Create a new SKILL.md template |
21
-
22
- Aliases: `skills a` works for `add`. `skills i`, `skills install` (no args) restore from `skills-lock.json`. `skills ls` works for `list`. `skills experimental_install` restores from `skills-lock.json`. `skills experimental_sync` crawls `node_modules` for skills.
23
-
24
- ## Architecture
25
-
26
- ```
27
- src/
28
- ├── cli.ts # Main entry point, command routing, init/check/update
29
- ├── cli.test.ts # CLI tests
30
- ├── add.ts # Core add command logic
31
- ├── add.test.ts # Add command tests
32
- ├── list.ts # List installed skills command
33
- ├── list.test.ts # List command tests
34
- ├── agents.ts # Agent definitions and detection
35
- ├── installer.ts # Skill installation logic (symlink/copy) + listInstalledSkills
36
- ├── skills.ts # Skill discovery and parsing
37
- ├── skill-lock.ts # Global lock file management (~/.agents/.skill-lock.json)
38
- ├── local-lock.ts # Local lock file management (skills-lock.json, checked in)
39
- ├── sync.ts # Sync command - crawl node_modules for skills
40
- ├── source-parser.ts # Parse git URLs, GitHub shorthand, local paths
41
- ├── git.ts # Git clone operations
42
- ├── telemetry.ts # Anonymous usage tracking
43
- ├── types.ts # TypeScript types
44
- ├── mintlify.ts # Mintlify skill fetching (legacy)
45
- ├── providers/ # Remote skill providers (GitHub, HuggingFace, Mintlify)
46
- │ ├── index.ts
47
- │ ├── registry.ts
48
- │ ├── types.ts
49
- │ ├── huggingface.ts
50
- │ └── mintlify.ts
51
- ├── init.test.ts # Init command tests
52
- └── test-utils.ts # Test utilities
53
-
54
- tests/
55
- ├── sanitize-name.test.ts # Tests for sanitizeName (path traversal prevention)
56
- ├── skill-matching.test.ts # Tests for filterSkills (multi-word skill name matching)
57
- ├── source-parser.test.ts # Tests for URL/path parsing
58
- ├── installer-symlink.test.ts # Tests for symlink installation
59
- ├── list-installed.test.ts # Tests for listing installed skills
60
- ├── skill-path.test.ts # Tests for skill path handling
61
- ├── wellknown-provider.test.ts # Tests for well-known provider
62
- └── dist.test.ts # Tests for built distribution
63
- ```
64
-
65
- ## Update Checking System
66
-
67
- ### How `skills check` and `skills update` Work
68
-
69
- 1. Read `~/.agents/.skill-lock.json` for installed skills
70
- 2. For each skill, get `skillFolderHash` from lock file
71
- 3. POST to `https://add-skill.vercel.sh/check-updates` with:
72
- ```json
73
- {
74
- "skills": [{ "name": "...", "source": "...", "skillFolderHash": "..." }],
75
- "forceRefresh": true
76
- }
77
- ```
78
- 4. API fetches fresh content from GitHub, computes hash, compares
79
- 5. Returns list of skills with different hashes (updates available)
80
-
81
- ### Why `forceRefresh: true`?
82
-
83
- Both `check` and `update` always send `forceRefresh: true`. This ensures the API fetches fresh content from GitHub rather than using its Redis cache.
84
-
85
- **Without forceRefresh:** Users saw phantom "updates available" due to stale cached hashes. The fix was to always fetch fresh.
86
-
87
- **Tradeoff:** Slightly slower (GitHub API call per skill), but always accurate.
88
-
89
- ### Lock File Compatibility
90
-
91
- The lock file format is v3. Key field: `skillFolderHash` (GitHub tree SHA for the skill folder).
92
-
93
- If reading an older lock file version, it's wiped. Users must reinstall skills to populate the new format.
94
-
95
- ## Key Integration Points
96
-
97
- | Feature | Implementation |
98
- | -------------------------- | ------------------------------------------- |
99
- | `skills add` | `src/add.ts` - full implementation |
100
- | `skills experimental_sync` | `src/sync.ts` - crawl node_modules |
101
- | `skills check` | `POST /check-updates` API |
102
- | `skills update` | `POST /check-updates` + reinstall per skill |
103
-
104
- ## Development
105
-
106
- ```bash
107
- # Install dependencies
108
- pnpm install
109
-
110
- # Build
111
- pnpm build
112
-
113
- # Test locally
114
- pnpm dev add vercel-labs/agent-skills --list
115
- pnpm dev experimental_sync
116
- pnpm dev check
117
- pnpm dev update
118
- pnpm dev init my-skill
119
-
120
- # Run all tests
121
- pnpm test
122
-
123
- # Run specific test file(s)
124
- pnpm test tests/sanitize-name.test.ts
125
- pnpm test tests/skill-matching.test.ts tests/source-parser.test.ts
126
-
127
- # Type check
128
- pnpm type-check
129
-
130
- # Format code
131
- pnpm format
132
- ```
133
-
134
- ## Code Style
135
-
136
- This project uses Prettier for code formatting. **Always run `pnpm format` before committing changes** to ensure consistent formatting.
137
-
138
- ```bash
139
- # Format all files
140
- pnpm format
141
-
142
- # Check formatting without fixing
143
- pnpm prettier --check .
144
- ```
145
-
146
- CI will fail if code is not properly formatted.
147
-
148
- ## Publishing
149
-
150
- ```bash
151
- # 1. Bump version in package.json
152
- # 2. Build
153
- pnpm build
154
- # 3. Publish
155
- npm publish
156
- ```
157
-
158
- ## Adding a New Agent
159
-
160
- 1. Add the agent definition to `src/agents.ts`
161
- 2. Run `pnpm run -C scripts validate-agents.ts` to validate
162
- 3. Run `pnpm run -C scripts sync-agents.ts` to update README.md
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to AI coding agents working on the `skills` CLI codebase.
4
+
5
+ ## Project Overview
6
+
7
+ `skills` is the CLI for the open agent skills ecosystem.
8
+
9
+ ## Commands
10
+
11
+ | Command | Description |
12
+ | ----------------------------- | --------------------------------------------------- |
13
+ | `skills` | Show banner with available commands |
14
+ | `skills add <pkg>` | Install skills from git repos, URLs, or local paths |
15
+ | `skills experimental_install` | Restore skills from skills-lock.json |
16
+ | `skills experimental_sync` | Sync skills from node_modules into agent dirs |
17
+ | `skills list` | List installed skills (alias: `ls`) |
18
+ | `skills check` | Check for available skill updates |
19
+ | `skills update` | Update all skills to latest versions |
20
+ | `skills init [name]` | Create a new SKILL.md template |
21
+
22
+ Aliases: `skills a` works for `add`. `skills i`, `skills install` (no args) restore from `skills-lock.json`. `skills ls` works for `list`. `skills experimental_install` restores from `skills-lock.json`. `skills experimental_sync` crawls `node_modules` for skills.
23
+
24
+ ## Architecture
25
+
26
+ ```
27
+ src/
28
+ ├── cli.ts # Main entry point, command routing, init/check/update
29
+ ├── cli.test.ts # CLI tests
30
+ ├── add.ts # Core add command logic
31
+ ├── add.test.ts # Add command tests
32
+ ├── list.ts # List installed skills command
33
+ ├── list.test.ts # List command tests
34
+ ├── agents.ts # Agent definitions and detection
35
+ ├── installer.ts # Skill installation logic (symlink/copy) + listInstalledSkills
36
+ ├── skills.ts # Skill discovery and parsing
37
+ ├── skill-lock.ts # Global lock file management (~/.agents/.skill-lock.json)
38
+ ├── local-lock.ts # Local lock file management (skills-lock.json, checked in)
39
+ ├── sync.ts # Sync command - crawl node_modules for skills
40
+ ├── source-parser.ts # Parse git URLs, GitHub shorthand, local paths
41
+ ├── git.ts # Git clone operations
42
+ ├── telemetry.ts # Anonymous usage tracking
43
+ ├── types.ts # TypeScript types
44
+ ├── mintlify.ts # Mintlify skill fetching (legacy)
45
+ ├── providers/ # Remote skill providers (GitHub, HuggingFace, Mintlify)
46
+ │ ├── index.ts
47
+ │ ├── registry.ts
48
+ │ ├── types.ts
49
+ │ ├── huggingface.ts
50
+ │ └── mintlify.ts
51
+ ├── init.test.ts # Init command tests
52
+ └── test-utils.ts # Test utilities
53
+
54
+ tests/
55
+ ├── sanitize-name.test.ts # Tests for sanitizeName (path traversal prevention)
56
+ ├── skill-matching.test.ts # Tests for filterSkills (multi-word skill name matching)
57
+ ├── source-parser.test.ts # Tests for URL/path parsing
58
+ ├── installer-symlink.test.ts # Tests for symlink installation
59
+ ├── list-installed.test.ts # Tests for listing installed skills
60
+ ├── skill-path.test.ts # Tests for skill path handling
61
+ ├── wellknown-provider.test.ts # Tests for well-known provider
62
+ └── dist.test.ts # Tests for built distribution
63
+ ```
64
+
65
+ ## Update Checking System
66
+
67
+ ### How `skills check` and `skills update` Work
68
+
69
+ 1. Read `~/.agents/.skill-lock.json` for installed skills
70
+ 2. For each skill, get `skillFolderHash` from lock file
71
+ 3. POST to `https://add-skill.vercel.sh/check-updates` with:
72
+ ```json
73
+ {
74
+ "skills": [{ "name": "...", "source": "...", "skillFolderHash": "..." }],
75
+ "forceRefresh": true
76
+ }
77
+ ```
78
+ 4. API fetches fresh content from GitHub, computes hash, compares
79
+ 5. Returns list of skills with different hashes (updates available)
80
+
81
+ ### Why `forceRefresh: true`?
82
+
83
+ Both `check` and `update` always send `forceRefresh: true`. This ensures the API fetches fresh content from GitHub rather than using its Redis cache.
84
+
85
+ **Without forceRefresh:** Users saw phantom "updates available" due to stale cached hashes. The fix was to always fetch fresh.
86
+
87
+ **Tradeoff:** Slightly slower (GitHub API call per skill), but always accurate.
88
+
89
+ ### Lock File Compatibility
90
+
91
+ The lock file format is v3. Key field: `skillFolderHash` (GitHub tree SHA for the skill folder).
92
+
93
+ If reading an older lock file version, it's wiped. Users must reinstall skills to populate the new format.
94
+
95
+ ## Key Integration Points
96
+
97
+ | Feature | Implementation |
98
+ | -------------------------- | ------------------------------------------- |
99
+ | `skills add` | `src/add.ts` - full implementation |
100
+ | `skills experimental_sync` | `src/sync.ts` - crawl node_modules |
101
+ | `skills check` | `POST /check-updates` API |
102
+ | `skills update` | `POST /check-updates` + reinstall per skill |
103
+
104
+ ## Development
105
+
106
+ ```bash
107
+ # Install dependencies
108
+ pnpm install
109
+
110
+ # Build
111
+ pnpm build
112
+
113
+ # Test locally
114
+ pnpm dev add vercel-labs/agent-skills --list
115
+ pnpm dev experimental_sync
116
+ pnpm dev check
117
+ pnpm dev update
118
+ pnpm dev init my-skill
119
+
120
+ # Run all tests
121
+ pnpm test
122
+
123
+ # Run specific test file(s)
124
+ pnpm test tests/sanitize-name.test.ts
125
+ pnpm test tests/skill-matching.test.ts tests/source-parser.test.ts
126
+
127
+ # Type check
128
+ pnpm type-check
129
+
130
+ # Format code
131
+ pnpm format
132
+ ```
133
+
134
+ ## Code Style
135
+
136
+ This project uses Prettier for code formatting. **Always run `pnpm format` before committing changes** to ensure consistent formatting.
137
+
138
+ ```bash
139
+ # Format all files
140
+ pnpm format
141
+
142
+ # Check formatting without fixing
143
+ pnpm prettier --check .
144
+ ```
145
+
146
+ CI will fail if code is not properly formatted.
147
+
148
+ ## Publishing
149
+
150
+ ```bash
151
+ # 1. Bump version in package.json
152
+ # 2. Build
153
+ pnpm build
154
+ # 3. Publish
155
+ npm publish
156
+ ```
157
+
158
+ ## Adding a New Agent
159
+
160
+ 1. Add the agent definition to `src/agents.ts`
161
+ 2. Run `pnpm run -C scripts validate-agents.ts` to validate
162
+ 3. Run `pnpm run -C scripts sync-agents.ts` to update README.md