foliko 2.0.30 → 2.0.32
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/.editorconfig +56 -56
- package/.lintstagedrc +7 -7
- package/.prettierignore +29 -29
- package/.prettierrc +11 -11
- package/Dockerfile +63 -63
- package/docs/plugin-dev-guide.md +850 -0
- package/install.ps1 +129 -129
- package/install.sh +121 -121
- package/package.json +1 -1
- package/plugins/core/workflow/context.js +941 -941
- package/plugins/core/workflow/engine.js +66 -66
- package/plugins/core/workflow/js-runner.js +318 -318
- package/plugins/core/workflow/json-runner.js +323 -323
- package/plugins/core/workflow/stages/choice.js +74 -74
- package/plugins/core/workflow/stages/each.js +123 -123
- package/plugins/core/workflow/stages/parallel.js +69 -69
- package/skills/find-skills/SKILL.md +133 -133
- package/src/agent/chat.js +31 -9
- package/src/agent/sub.js +17 -3
- package/src/agent/tool-loop.js +132 -37
- package/src/common/atomic-write.js +33 -0
- package/src/context/compressor.js +22 -18
- package/src/framework/framework.js +19 -1
- package/src/plugin/manager.js +12 -2
- package/src/session/session.js +9 -4
- package/src/storage/manager.js +3 -1
- package/tests/core/chat-tool.test.js +187 -187
- package/tests/core/latest-message-not-filtered.test.js +143 -0
- package/tests/core/p0-fixes.test.js +129 -0
- package/tests/core/p1-fixes.test.js +76 -0
|
@@ -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
|
+
```
|
package/src/agent/chat.js
CHANGED
|
@@ -116,6 +116,11 @@ class AgentChatHandler extends EventEmitter {
|
|
|
116
116
|
this._messageTokenCache = new Map();
|
|
117
117
|
this._messageTokenCacheMaxSize = 200;
|
|
118
118
|
|
|
119
|
+
// ★ 每 session 串行锁:非流式 chat() 不走 queueManager,
|
|
120
|
+
// 同一 session 并发调用会并发 mutate/save 消息数组 → 交错/丢失。
|
|
121
|
+
// 用 promise 链把同 session 的调用串行化;不同 session 仍并行。
|
|
122
|
+
this._sessionLocks = new Map();
|
|
123
|
+
|
|
119
124
|
// ChatQueueManager: 队列管理
|
|
120
125
|
this.queueManager = new ChatQueueManager({
|
|
121
126
|
maxConcurrent: config.maxConcurrent || DEFAULT_MAX_CONCURRENT,
|
|
@@ -711,10 +716,29 @@ class AgentChatHandler extends EventEmitter {
|
|
|
711
716
|
*/
|
|
712
717
|
async chat(message, options = {}) {
|
|
713
718
|
const sessionId = options.sessionId || this.getDefaultSessionId();
|
|
714
|
-
const result = await this._processMessage(sessionId, message, options);
|
|
719
|
+
const result = await this._withSessionLock(sessionId, () => this._processMessage(sessionId, message, options));
|
|
715
720
|
return { message: result.text, ...result };
|
|
716
721
|
}
|
|
717
722
|
|
|
723
|
+
/**
|
|
724
|
+
* 按 sessionId 串行执行 fn:同一 session 的调用排队,不同 session 并行。
|
|
725
|
+
* 无论前一个成功或失败都继续(不因一次失败卡死队列)。
|
|
726
|
+
* @private
|
|
727
|
+
*/
|
|
728
|
+
_withSessionLock(sessionId, fn) {
|
|
729
|
+
const key = sessionId || '__default__';
|
|
730
|
+
const prev = this._sessionLocks.get(key) || Promise.resolve();
|
|
731
|
+
const run = prev.then(fn, fn); // 前一个 settle(成功/失败)后都执行本次
|
|
732
|
+
// gate 只用于排队,吞掉 run 的结果/异常,避免影响下一个
|
|
733
|
+
const gate = run.then(() => {}, () => {});
|
|
734
|
+
this._sessionLocks.set(key, gate);
|
|
735
|
+
gate.finally(() => {
|
|
736
|
+
// 队尾清理,避免 Map 无限增长
|
|
737
|
+
if (this._sessionLocks.get(key) === gate) this._sessionLocks.delete(key);
|
|
738
|
+
});
|
|
739
|
+
return run;
|
|
740
|
+
}
|
|
741
|
+
|
|
718
742
|
/**
|
|
719
743
|
* 流式聊天
|
|
720
744
|
*/
|
|
@@ -795,8 +819,9 @@ class AgentChatHandler extends EventEmitter {
|
|
|
795
819
|
// yield usage 数据,让 UI 层能直接获取
|
|
796
820
|
// (usage 已在 stream 循环中 yield,无需重复)
|
|
797
821
|
|
|
798
|
-
|
|
799
|
-
|
|
822
|
+
// ★ 用 _prepareSession 返回的 userMessage,而非 messages 末尾——
|
|
823
|
+
// 末尾现在是刚追加的 assistant 最终答复,不再是 user 消息。
|
|
824
|
+
this.emit('message', { content: fullText, sessionId: sessionId, userMessage });
|
|
800
825
|
|
|
801
826
|
// ★ 修复:成功路径才持久化。AI 失败时若 finally 也 save,
|
|
802
827
|
// 会把刚 push 的 userMessage 写盘 → 下次请求 loadHistory 再次
|
|
@@ -939,12 +964,9 @@ class AgentChatHandler extends EventEmitter {
|
|
|
939
964
|
messageStore.usage = { promptTokens: inputTokens, completionTokens: outputTokens };
|
|
940
965
|
}
|
|
941
966
|
|
|
942
|
-
// ToolLoop 已经直接在 messages
|
|
943
|
-
//
|
|
944
|
-
|
|
945
|
-
? messages.slice(-1)[0]
|
|
946
|
-
: messages[messages.length - 1];
|
|
947
|
-
this.emit('message', { content: result.text, sessionId: sessionId, userMessage: userMsg });
|
|
967
|
+
// ToolLoop 已经直接在 messages 末尾添加了新消息(含最终 assistant 答复)
|
|
968
|
+
// ★ userMessage 用 _prepareSession 返回值,不能再取 messages 末尾(已是 assistant)
|
|
969
|
+
this.emit('message', { content: result.text, sessionId: sessionId, userMessage });
|
|
948
970
|
|
|
949
971
|
// ★ 修复:AI 调用成功后才持久化(之前 finally 总是 save,
|
|
950
972
|
// 会把刚 push 的 userMessage 写盘;下次请求 loadHistory 再次 load 到,
|
package/src/agent/sub.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
const { BaseAgent } = require('./base');
|
|
10
10
|
const { cleanResponse } = require('../utils');
|
|
11
11
|
const { ToolLoop } = require('./tool-loop');
|
|
12
|
+
const { isThinkingModel } = require('../llm/provider');
|
|
12
13
|
const { z } = require('zod');
|
|
13
14
|
const { logger } = require('../common/logger');
|
|
14
15
|
const { validateAll } = require('../utils/message-validator');
|
|
@@ -150,13 +151,26 @@ class SubAgent extends BaseAgent {
|
|
|
150
151
|
tools,
|
|
151
152
|
maxSteps,
|
|
152
153
|
prepareStep: this._prepareStep ? this._prepareStep.bind(this) : undefined,
|
|
154
|
+
// ★ 子 Agent 同样要感知 thinking 模式,否则缺 reasoning_content 时会 400。
|
|
155
|
+
// 白名单命中或 providerOptions 显式开启即视为思考模式;
|
|
156
|
+
// 即便都没命中,tool-loop 内部还有 _forceReasoning 自愈兜底。
|
|
157
|
+
thinkingMode: isThinkingModel(this.model) || !!this.providerOptions?.deepseek?.thinking,
|
|
153
158
|
});
|
|
154
159
|
|
|
155
160
|
const result = await loop.generate({ messages, systemPrompt, model: this.model, client, ...this.providerOptions });
|
|
156
|
-
|
|
161
|
+
// ★ 不要再 push:ToolLoop.generate 就地 mutate 并返回同一个 messages 引用,
|
|
162
|
+
// messages.push(...result.response.messages) 等于 push(...messages),会让整段历史翻倍。
|
|
157
163
|
const full_text = cleanResponse(result.text);
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
// ★ maxSteps 耗尽(最后一步仍是工具调用、无最终答复)不能当成功,
|
|
165
|
+
// 否则调用方拿到空/半截结果却以为完成。
|
|
166
|
+
if (result.stopReason === 'max_steps') {
|
|
167
|
+
const msg = `子Agent「${this.name}」达到最大步数(${maxSteps})仍未给出最终答复`;
|
|
168
|
+
logger.warn(`[SubAgent:${this.name}] ${msg}`);
|
|
169
|
+
this.emit('error', { error: msg });
|
|
170
|
+
return { success: false, message: full_text, error: msg, stopReason: 'max_steps', steps: result.steps || 0, messages };
|
|
171
|
+
}
|
|
172
|
+
this.emit('complete', { message: full_text, steps: result.steps || 0 });
|
|
173
|
+
return { success: true, message: full_text, steps: result.steps || 0, messages };
|
|
160
174
|
} catch (err) {
|
|
161
175
|
lastError = err;
|
|
162
176
|
if (isNetworkError(err) && attempt < maxRetries) {
|