foliko 1.1.86 → 1.1.88

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.
package/.env.example CHANGED
@@ -1,56 +1,56 @@
1
- # ========== AI Configuration ==========
2
- # 最大输出 tokens(影响 AI 回复长度)
3
- MAX_OUTPUT_TOKENS=8192
4
- # AI Provider: minimax, deepseek, openai, anthropic 等
5
- FOLIKO_PROVIDER=minimax
6
-
7
- # AI Model(如果未设置,使用 provider 默认值)
8
- # MiniMax: MiniMax-M2.7
9
- # DeepSeek: deepseek-chat, deepseek-coder 等
10
- FOLIKO_MODEL=MiniMax-M2.7
11
-
12
- # API Base URL(如果未设置,使用 provider 默认值)
13
- # MiniMax: https://api.minimaxi.com/v1
14
- # DeepSeek: https://api.deepseek.com/v1
15
- FOLIKO_BASE_URL=https://api.minimaxi.com/v1
16
-
17
- # API Key(通用,如果未设置则尝试 provider 专用 key)
18
- FOLIKO_API_KEY=sk-your-api-key
19
-
20
- # Provider 专用 API Key(可选,如果 FOLIKO_API_KEY 未设置则使用这些)
21
- DEEPSEEK_API_KEY=sk-your-deepseek-api-key
22
- MINIMAX_API_KEY=sk-your-minimax-api-key
23
-
24
- # ========== Email Configuration ==========
25
- # SMTP Settings (for sending emails)
26
- SMTP_HOST=smtp.gmail.com
27
- SMTP_PORT=587
28
- SMTP_SECURE=false
29
- SMTP_USER=your-email@gmail.com
30
- SMTP_PASS=your-app-password
31
-
32
- # IMAP Settings (for reading emails)
33
- IMAP_HOST=imap.gmail.com
34
- IMAP_PORT=993
35
- IMAP_USER=your-email@gmail.com
36
- IMAP_PASS=your-app-password
37
-
38
- # Default sender email address
39
- FROM_EMAIL=your-email@gmail.com
40
-
41
- # ========== Telegram Bot (optional) ==========
42
- TELEGRAM_BOT_TOKEN=your-telegram-bot-token
43
-
44
- # ========== Feishu Bot (optional) ==========
45
- FEISHU_APP_ID=cli_xxxxxxxxxxx
46
- FEISHU_APP_SECRET=app_secret
47
-
48
- # ========== Web Server (optional) ==========
49
- # Web 服务端口,默认 8088
50
- WEB_PORT=3000
51
-
52
- # Web 服务主机,默认 127.0.0.1
53
- WEB_HOST=127.0.0.1
54
-
55
- # 公网访问的 base URL(用于生成 webhook URL 等),不设置则使用 host:port,最好部署在docker中可以暴露自定义域名
56
- WEB_BASE_URL=https://your-domain.com
1
+ # ========== AI Configuration ==========
2
+ # 最大输出 tokens(影响 AI 回复长度)
3
+ MAX_OUTPUT_TOKENS=8192
4
+ # AI Provider: minimax, deepseek, openai, anthropic 等
5
+ FOLIKO_PROVIDER=minimax
6
+
7
+ # AI Model(如果未设置,使用 provider 默认值)
8
+ # MiniMax: MiniMax-M2.7
9
+ # DeepSeek: deepseek-chat, deepseek-coder 等
10
+ FOLIKO_MODEL=MiniMax-M2.7
11
+
12
+ # API Base URL(如果未设置,使用 provider 默认值)
13
+ # MiniMax: https://api.minimaxi.com/v1
14
+ # DeepSeek: https://api.deepseek.com/v1
15
+ FOLIKO_BASE_URL=https://api.minimaxi.com/v1
16
+
17
+ # API Key(通用,如果未设置则尝试 provider 专用 key)
18
+ FOLIKO_API_KEY=sk-your-api-key
19
+
20
+ # Provider 专用 API Key(可选,如果 FOLIKO_API_KEY 未设置则使用这些)
21
+ DEEPSEEK_API_KEY=sk-your-deepseek-api-key
22
+ MINIMAX_API_KEY=sk-your-minimax-api-key
23
+
24
+ # ========== Email Configuration ==========
25
+ # SMTP Settings (for sending emails)
26
+ SMTP_HOST=smtp.gmail.com
27
+ SMTP_PORT=587
28
+ SMTP_SECURE=false
29
+ SMTP_USER=your-email@gmail.com
30
+ SMTP_PASS=your-app-password
31
+
32
+ # IMAP Settings (for reading emails)
33
+ IMAP_HOST=imap.gmail.com
34
+ IMAP_PORT=993
35
+ IMAP_USER=your-email@gmail.com
36
+ IMAP_PASS=your-app-password
37
+
38
+ # Default sender email address
39
+ FROM_EMAIL=your-email@gmail.com
40
+
41
+ # ========== Telegram Bot (optional) ==========
42
+ TELEGRAM_BOT_TOKEN=your-telegram-bot-token
43
+
44
+ # ========== Feishu Bot (optional) ==========
45
+ FEISHU_APP_ID=cli_xxxxxxxxxxx
46
+ FEISHU_APP_SECRET=app_secret
47
+
48
+ # ========== Web Server (optional) ==========
49
+ # Web 服务端口,默认 8088
50
+ WEB_PORT=3000
51
+
52
+ # Web 服务主机,默认 127.0.0.1
53
+ WEB_HOST=127.0.0.1
54
+
55
+ # 公网访问的 base URL(用于生成 webhook URL 等),不设置则使用 host:port,最好部署在docker中可以暴露自定义域名
56
+ WEB_BASE_URL=https://your-domain.com
@@ -175,7 +175,7 @@ class ChatUI {
175
175
  const result = await this.agent.framework.executeTool('ext_call', {
176
176
  plugin: 'skill',
177
177
  tool: cmdName,
178
- args: { args: cmdArgs }
178
+ args: { command: cmdArgs }
179
179
  });
180
180
  if (result.success !== false) {
181
181
  console.log(colored(`[指令] ${cmdName}`, GREEN));
@@ -376,7 +376,7 @@ class ChatUI {
376
376
  const result = await this.agent.framework.executeTool('ext_call', {
377
377
  plugin: 'skill',
378
378
  tool: cmdName,
379
- args: { args: cmdArgs }
379
+ args: { command: cmdArgs }
380
380
  });
381
381
  if (result.success !== false) {
382
382
  this.create_message(`${colored('[指令] '+cmdName, CYAN)}\n\n ${result.data || result}\n`, chalk.green('● '));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.86",
3
+ "version": "1.1.88",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -607,7 +607,7 @@ class ExtensionExecutorPlugin extends Plugin {
607
607
  const result = await this._framework.executeTool('ext_call', {
608
608
  plugin: 'skill',
609
609
  tool: command,
610
- args: { args }
610
+ args: { command: args }
611
611
  });
612
612
  return result.success !== false ? result : null;
613
613
  } catch (err) {
@@ -239,7 +239,7 @@ class FeishuPlugin extends Plugin {
239
239
  const result = await this._framework.executeTool('ext_call', {
240
240
  plugin: 'skill',
241
241
  tool: skillCmd,
242
- args: { args }
242
+ args: { command: args }
243
243
  })
244
244
  if (result.success !== false) {
245
245
  await this._sendMessage(openId, `✅ ${result.data || result}`, originalMsg)
@@ -729,7 +729,7 @@ class QQPlugin extends Plugin {
729
729
  const result = await this._framework.executeTool('ext_call', {
730
730
  plugin: 'skill',
731
731
  tool: skillCmd,
732
- args: { args }
732
+ args: { command: args }
733
733
  })
734
734
  if (result.success !== false) {
735
735
  await this._sendMessage(openid, `✅ ${result.data || result}`)
@@ -353,7 +353,7 @@ class TelegramPlugin extends Plugin {
353
353
  const result = await this._framework.executeTool('ext_call', {
354
354
  plugin: 'skill',
355
355
  tool: skillCmd,
356
- args: { args }
356
+ args: { command: args }
357
357
  })
358
358
  if (result.success !== false) {
359
359
  await this._sendMessage(chatId, `✅ ${result.data || result}`, msg.message_id)
@@ -1,133 +1,133 @@
1
- ---
2
- name: find-skills
3
- description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
4
- ---
5
-
6
- # Find Skills
7
-
8
- This skill helps you discover and install skills from the open agent skills ecosystem.
9
-
10
- ## When to Use This Skill
11
-
12
- Use this skill when the user:
13
-
14
- - Asks "how do I do X" where X might be a common task with an existing skill
15
- - Says "find a skill for X" or "is there a skill for X"
16
- - Asks "can you do X" where X is a specialized capability
17
- - Expresses interest in extending agent capabilities
18
- - Wants to search for tools, templates, or workflows
19
- - Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
20
-
21
- ## What is the Skills CLI?
22
-
23
- The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
24
-
25
- **Key commands:**
26
-
27
- - `npx skills find [query]` - Search for skills interactively or by keyword
28
- - `npx skills add <package>` - Install a skill from GitHub or other sources
29
- - `npx skills check` - Check for skill updates
30
- - `npx skills update` - Update all installed skills
31
-
32
- **Browse skills at:** https://skills.sh/
33
-
34
- ## How to Help Users Find Skills
35
-
36
- ### Step 1: Understand What They Need
37
-
38
- When a user asks for help with something, identify:
39
-
40
- 1. The domain (e.g., React, testing, design, deployment)
41
- 2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
42
- 3. Whether this is a common enough task that a skill likely exists
43
-
44
- ### Step 2: Search for Skills
45
-
46
- Run the find command with a relevant query:
47
-
48
- ```bash
49
- npx skills find [query]
50
- ```
51
-
52
- For example:
53
-
54
- - User asks "how do I make my React app faster?" → `npx skills find react performance`
55
- - User asks "can you help me with PR reviews?" → `npx skills find pr review`
56
- - User asks "I need to create a changelog" → `npx skills find changelog`
57
-
58
- The command will return results like:
59
-
60
- ```
61
- Install with npx skills add <owner/repo@skill>
62
-
63
- vercel-labs/agent-skills@vercel-react-best-practices
64
- └ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
65
- ```
66
-
67
- ### Step 3: Present Options to the User
68
-
69
- When you find relevant skills, present them to the user with:
70
-
71
- 1. The skill name and what it does
72
- 2. The install command they can run
73
- 3. A link to learn more at skills.sh
74
-
75
- Example response:
76
-
77
- ```
78
- I found a skill that might help! The "vercel-react-best-practices" skill provides
79
- React and Next.js performance optimization guidelines from Vercel Engineering.
80
-
81
- To install it:
82
- npx skills add vercel-labs/agent-skills@vercel-react-best-practices
83
-
84
- Learn more: https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
85
- ```
86
-
87
- ### Step 4: Offer to Install
88
-
89
- If the user wants to proceed, you can install the skill for them:
90
-
91
- ```bash
92
- npx skills add <owner/repo@skill> -g -y
93
- ```
94
-
95
- The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
96
-
97
- ## Common Skill Categories
98
-
99
- When searching, consider these common categories:
100
-
101
- | Category | Example Queries |
102
- | --------------- | ---------------------------------------- |
103
- | Web Development | react, nextjs, typescript, css, tailwind |
104
- | Testing | testing, jest, playwright, e2e |
105
- | DevOps | deploy, docker, kubernetes, ci-cd |
106
- | Documentation | docs, readme, changelog, api-docs |
107
- | Code Quality | review, lint, refactor, best-practices |
108
- | Design | ui, ux, design-system, accessibility |
109
- | Productivity | workflow, automation, git |
110
-
111
- ## Tips for Effective Searches
112
-
113
- 1. **Use specific keywords**: "react testing" is better than just "testing"
114
- 2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
115
- 3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
116
-
117
- ## When No Skills Are Found
118
-
119
- If no relevant skills exist:
120
-
121
- 1. Acknowledge that no existing skill was found
122
- 2. Offer to help with the task directly using your general capabilities
123
- 3. Suggest the user could create their own skill with `npx skills init`
124
-
125
- Example:
126
-
127
- ```
128
- I searched for skills related to "xyz" but didn't find any matches.
129
- I can still help you with this task directly! Would you like me to proceed?
130
-
131
- If this is something you do often, you could create your own skill:
132
- npx skills init my-xyz-skill
133
- ```
1
+ ---
2
+ name: find-skills
3
+ description: Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
4
+ ---
5
+
6
+ # Find Skills
7
+
8
+ This skill helps you discover and install skills from the open agent skills ecosystem.
9
+
10
+ ## When to Use This Skill
11
+
12
+ Use this skill when the user:
13
+
14
+ - Asks "how do I do X" where X might be a common task with an existing skill
15
+ - Says "find a skill for X" or "is there a skill for X"
16
+ - Asks "can you do X" where X is a specialized capability
17
+ - Expresses interest in extending agent capabilities
18
+ - Wants to search for tools, templates, or workflows
19
+ - Mentions they wish they had help with a specific domain (design, testing, deployment, etc.)
20
+
21
+ ## What is the Skills CLI?
22
+
23
+ The Skills CLI (`npx skills`) is the package manager for the open agent skills ecosystem. Skills are modular packages that extend agent capabilities with specialized knowledge, workflows, and tools.
24
+
25
+ **Key commands:**
26
+
27
+ - `npx skills find [query]` - Search for skills interactively or by keyword
28
+ - `npx skills add <package>` - Install a skill from GitHub or other sources
29
+ - `npx skills check` - Check for skill updates
30
+ - `npx skills update` - Update all installed skills
31
+
32
+ **Browse skills at:** https://skills.sh/
33
+
34
+ ## How to Help Users Find Skills
35
+
36
+ ### Step 1: Understand What They Need
37
+
38
+ When a user asks for help with something, identify:
39
+
40
+ 1. The domain (e.g., React, testing, design, deployment)
41
+ 2. The specific task (e.g., writing tests, creating animations, reviewing PRs)
42
+ 3. Whether this is a common enough task that a skill likely exists
43
+
44
+ ### Step 2: Search for Skills
45
+
46
+ Run the find command with a relevant query:
47
+
48
+ ```bash
49
+ npx skills find [query]
50
+ ```
51
+
52
+ For example:
53
+
54
+ - User asks "how do I make my React app faster?" → `npx skills find react performance`
55
+ - User asks "can you help me with PR reviews?" → `npx skills find pr review`
56
+ - User asks "I need to create a changelog" → `npx skills find changelog`
57
+
58
+ The command will return results like:
59
+
60
+ ```
61
+ Install with npx skills add <owner/repo@skill>
62
+
63
+ vercel-labs/agent-skills@vercel-react-best-practices
64
+ └ https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
65
+ ```
66
+
67
+ ### Step 3: Present Options to the User
68
+
69
+ When you find relevant skills, present them to the user with:
70
+
71
+ 1. The skill name and what it does
72
+ 2. The install command they can run
73
+ 3. A link to learn more at skills.sh
74
+
75
+ Example response:
76
+
77
+ ```
78
+ I found a skill that might help! The "vercel-react-best-practices" skill provides
79
+ React and Next.js performance optimization guidelines from Vercel Engineering.
80
+
81
+ To install it:
82
+ npx skills add vercel-labs/agent-skills@vercel-react-best-practices
83
+
84
+ Learn more: https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices
85
+ ```
86
+
87
+ ### Step 4: Offer to Install
88
+
89
+ If the user wants to proceed, you can install the skill for them:
90
+
91
+ ```bash
92
+ npx skills add <owner/repo@skill> -g -y
93
+ ```
94
+
95
+ The `-g` flag installs globally (user-level) and `-y` skips confirmation prompts.
96
+
97
+ ## Common Skill Categories
98
+
99
+ When searching, consider these common categories:
100
+
101
+ | Category | Example Queries |
102
+ | --------------- | ---------------------------------------- |
103
+ | Web Development | react, nextjs, typescript, css, tailwind |
104
+ | Testing | testing, jest, playwright, e2e |
105
+ | DevOps | deploy, docker, kubernetes, ci-cd |
106
+ | Documentation | docs, readme, changelog, api-docs |
107
+ | Code Quality | review, lint, refactor, best-practices |
108
+ | Design | ui, ux, design-system, accessibility |
109
+ | Productivity | workflow, automation, git |
110
+
111
+ ## Tips for Effective Searches
112
+
113
+ 1. **Use specific keywords**: "react testing" is better than just "testing"
114
+ 2. **Try alternative terms**: If "deploy" doesn't work, try "deployment" or "ci-cd"
115
+ 3. **Check popular sources**: Many skills come from `vercel-labs/agent-skills` or `ComposioHQ/awesome-claude-skills`
116
+
117
+ ## When No Skills Are Found
118
+
119
+ If no relevant skills exist:
120
+
121
+ 1. Acknowledge that no existing skill was found
122
+ 2. Offer to help with the task directly using your general capabilities
123
+ 3. Suggest the user could create their own skill with `npx skills init`
124
+
125
+ Example:
126
+
127
+ ```
128
+ I searched for skills related to "xyz" but didn't find any matches.
129
+ I can still help you with this task directly! Would you like me to proceed?
130
+
131
+ If this is something you do often, you could create your own skill:
132
+ npx skills init my-xyz-skill
133
+ ```
@@ -174,6 +174,51 @@ module.exports = [
174
174
  | Telegram | 发送 `/skillname:cmdname` |
175
175
  | QQ | 发送 `/skillname:cmdname` |
176
176
 
177
+ ### ext_call 调用格式
178
+
179
+ 当需要通过 AI 调用 skill 命令时,使用 `ext_call` 工具:
180
+
181
+ ```javascript
182
+ ext_call({
183
+ plugin: "skill",
184
+ tool: "<skillname>:<commandname>",
185
+ args: { command: "<命令行>" }
186
+ });
187
+ ```
188
+
189
+ **参数说明:**
190
+
191
+ | 参数 | 类型 | 说明 |
192
+ |------|------|------|
193
+ | `plugin` | string | 固定为 `"skill"` |
194
+ | `tool` | string | 格式为 `<技能名>:<命令名>`,如 `test-skill:greet` |
195
+ | `args.command` | string | 命令行参数字符串 |
196
+
197
+ **示例:**
198
+
199
+ ```javascript
200
+ // 调用 test-skill 的 greet 命令,无参数
201
+ ext_call({
202
+ plugin: "skill",
203
+ tool: "test-skill:greet",
204
+ args: { command: "" }
205
+ });
206
+
207
+ // 调用 test-skill 的 greet 命令,带参数
208
+ ext_call({
209
+ plugin: "skill",
210
+ tool: "test-skill:greet",
211
+ args: { command: "Alice" }
212
+ });
213
+
214
+ // 调用 test-skill 的 echo 命令
215
+ ext_call({
216
+ plugin: "skill",
217
+ tool: "test-skill:echo",
218
+ args: { command: "Hello World" }
219
+ });
220
+ ```
221
+
177
222
  ### 使用流程
178
223
 
179
224
  1. **查看可用命令**:发送 `/help` 或 `/start` 查看帮助,其中列出所有技能命令
@@ -336,6 +381,51 @@ module.exports = [
336
381
  | Telegram | 发送 `/skillname:cmdname` |
337
382
  | QQ | 发送 `/skillname:cmdname` |
338
383
 
384
+ ### ext_call 调用格式
385
+
386
+ 当需要通过 AI 调用 skill 命令时,使用 `ext_call` 工具:
387
+
388
+ ```javascript
389
+ ext_call({
390
+ plugin: "skill",
391
+ tool: "<skillname>:<commandname>",
392
+ args: { command: "<命令行>" }
393
+ });
394
+ ```
395
+
396
+ **参数说明:**
397
+
398
+ | 参数 | 类型 | 说明 |
399
+ |------|------|------|
400
+ | `plugin` | string | 固定为 `"skill"` |
401
+ | `tool` | string | 格式为 `<技能名>:<命令名>`,如 `test-skill:greet` |
402
+ | `args.command` | string | 命令行参数字符串 |
403
+
404
+ **示例:**
405
+
406
+ ```javascript
407
+ // 调用 test-skill 的 greet 命令,无参数
408
+ ext_call({
409
+ plugin: "skill",
410
+ tool: "test-skill:greet",
411
+ args: { command: "" }
412
+ });
413
+
414
+ // 调用 test-skill 的 greet 命令,带参数
415
+ ext_call({
416
+ plugin: "skill",
417
+ tool: "test-skill:greet",
418
+ args: { command: "Alice" }
419
+ });
420
+
421
+ // 调用 test-skill 的 echo 命令
422
+ ext_call({
423
+ plugin: "skill",
424
+ tool: "test-skill:echo",
425
+ args: { command: "Hello World" }
426
+ });
427
+ ```
428
+
339
429
  ### 使用流程
340
430
 
341
431
  1. **查看可用命令**:发送 `/help` 或 `/start` 查看帮助,其中列出所有技能命令
@@ -239,7 +239,7 @@ class Skill {
239
239
  name: fullName,
240
240
  description: cmd.description || `Skill command: ${fullName}`,
241
241
  inputSchema: z.object({
242
- args: z.string().optional().describe('命令参数'),
242
+ command: z.string().optional().describe('命令行'),
243
243
  }),
244
244
  _options: cmd.options || null, // 保存 options 信息用于提示词生成
245
245
  execute: async (toolArgs, framework) => {
@@ -250,9 +250,9 @@ class Skill {
250
250
  cwd: process.cwd(), // 工作目录,用于路径解析
251
251
  };
252
252
  // 支持 argumentParser 先解析参数
253
- let parsedArgs = toolArgs.args || '';
253
+ let parsedArgs = toolArgs.command || '';
254
254
  if (typeof argumentParser === 'function') {
255
- parsedArgs = argumentParser(toolArgs.args || '');
255
+ parsedArgs = argumentParser(toolArgs.command || '');
256
256
  }
257
257
  return await handler(parsedArgs, ctx);
258
258
  },
@@ -478,7 +478,7 @@ class SkillManagerPlugin extends Plugin {
478
478
  lines.push(`ext_call({`);
479
479
  lines.push(` plugin: "skill",`);
480
480
  lines.push(` tool: "${name}:<命令名>",`);
481
- lines.push(` args: { args: "参数" } // 注意:args 必须是对象,不能是字符串`);
481
+ lines.push(` args: { command: "<命令行>" }`);
482
482
  lines.push(`})`);
483
483
  lines.push('```');
484
484
  lines.push('');
@@ -498,7 +498,7 @@ class SkillManagerPlugin extends Plugin {
498
498
  lines.push('');
499
499
  lines.push('**示例:**');
500
500
  for (const c of toolsBySkill[name]) {
501
- lines.push(`- 调用 \`ext_call({ plugin: "skill", tool: "${name}:${c.name}", args: { args: "参数" } })\``);
501
+ lines.push(`- 调用 \`ext_call({ plugin: "skill", tool: "${name}:${c.name}", args: { command: "<命令行>" } })\``);
502
502
  }
503
503
  }
504
504
  lines.push('');
@@ -475,7 +475,7 @@ class AgentChatHandler extends EventEmitter {
475
475
  if (!this._aiClient) {
476
476
  throw new Error('AI client not configured.');
477
477
  }
478
-
478
+ this._validateToolCalls(messages);
479
479
  const systemPrompt = framework.getSystemPrompt();
480
480
  //await fs.promises.writeFile(`.${sessionId}_systemPrompt.md`, systemPrompt); // 调试用:保存系统提示词
481
481
  const tools = this._getAITools(aiTool);
@@ -580,7 +580,7 @@ class AgentChatHandler extends EventEmitter {
580
580
  usage: usageData,
581
581
  });
582
582
  }
583
-
583
+ this._validateToolCalls(messages);
584
584
  // yield usage 数据,让 UI 层能直接获取
585
585
  yield {
586
586
  type: 'usage',
@@ -658,7 +658,7 @@ class AgentChatHandler extends EventEmitter {
658
658
  if (this._thinkingMode) {
659
659
  delete apiOptions.temperature;
660
660
  }
661
-
661
+ this._validateToolCalls(messages);
662
662
  const agent = new ToolLoopAgent({
663
663
  model: this._aiClient,
664
664
  instructions: systemPrompt,
@@ -699,7 +699,7 @@ class AgentChatHandler extends EventEmitter {
699
699
  messages.push(...result.response.messages);
700
700
  const userMsg = messages[messages.length - result.response.messages.length - 1];
701
701
  this.emit('message', { content: result.text, sessionId: sessionId, userMessage: userMsg });
702
-
702
+ this._validateToolCalls(messages);
703
703
  return {
704
704
  success: true,
705
705
  message: cleanResponse(result.text || ''),
@@ -1,8 +1,8 @@
1
- /* Foliko v2 - Animations */
2
- @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }
3
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
4
- @keyframes glow { 0%, 100% { opacity: 0.4; transform: translateX(-50%) scale(1); } 50% { opacity: 0.7; transform: translateX(-50%) scale(1.1); } }
5
- @keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.2); } }
6
- .reveal { opacity: 0; transform: translateY(30px); transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); }
7
- .reveal.visible { opacity: 1; transform: translateY(0); }
1
+ /* Foliko v2 - Animations */
2
+ @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }
3
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
4
+ @keyframes glow { 0%, 100% { opacity: 0.4; transform: translateX(-50%) scale(1); } 50% { opacity: 0.7; transform: translateX(-50%) scale(1.1); } }
5
+ @keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.2); } }
6
+ .reveal { opacity: 0; transform: translateY(30px); transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); }
7
+ .reveal.visible { opacity: 1; transform: translateY(0); }
8
8