foliko 1.1.11 → 1.1.13
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/.agent/data/default.json +4 -0
- package/.agent/memory/feedback/mnvzgvtd-0o2900.md +9 -0
- package/.agent/memory/feedback/mnvzhajn-swbx61.md +15 -0
- package/.agent/memory/feedback/mnvzhgsp-p5vog3.md +9 -0
- package/.agent/memory/feedback/mnvzho0c-fgql7q.md +14 -0
- package/.agent/memory/feedback/mnvzhtzq-ufr5at.md +9 -0
- package/.agent/memory/feedback/mnvzhyb3-9byq2z.md +9 -0
- package/.agent/memory/feedback/mnvzi7hp-hyeafp.md +9 -0
- package/.agent/memory/feedback/mnvzibph-z7rwp5.md +9 -0
- package/.agent/memory/feedback/mnvzilys-7h176w.md +14 -0
- package/.agent/memory/feedback/mnvziuh5-zjshci.md +9 -0
- package/.agent/memory/feedback/mnw07wde-6zqsc8.md +9 -0
- package/.agent/memory/feedback/mnw084bp-j0ba2a.md +9 -0
- package/.agent/sessions/cli_default.json +366 -100
- package/.agent/sessions/test.json +16 -0
- package/.claude/settings.local.json +2 -1
- package/cli/src/ui/chat-ui.js +35 -13
- package/package.json +1 -1
- package/plugins/extension-executor-plugin.js +1 -1
- package/plugins/python-plugin-loader.js +11 -11
- package/plugins/scheduler-plugin.js +1 -6
- package/plugins/subagent-plugin.js +26 -15
- package/plugins/web-plugin.js +1 -1
- package/plugins/weixin-plugin.js +38 -45
- package/src/core/agent-chat.js +352 -218
- package/src/core/agent.js +16 -8
- package/src/core/framework.js +6 -3
- package/src/utils/chat-queue.js +244 -0
- package/system.md +11 -79
- package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +0 -211
|
@@ -179,7 +179,8 @@
|
|
|
179
179
|
"Bash(cd \"D:/Code/foliko\" && node test-python-ext.js 2>&1 | grep -v \"^\\\\[2m\")",
|
|
180
180
|
"Bash(cd \"D:/Code/foliko\" && node -e \"require\\('./plugins/extension-executor-plugin'\\); console.log\\('OK'\\)\")",
|
|
181
181
|
"Bash(cd D:/Code/foliko && timeout 8s node cli/bin/foliko.js chat 2>&1 || true)",
|
|
182
|
-
"Bash(cd /d/Code/foliko-plugins/poster-plugin && node -e \"\nconst LayoutManager = require\\('./src/layout-manager'\\);\nconsole.log\\('LayoutManager loaded successfully'\\);\nconsole.log\\('Methods:', Object.getOwnPropertyNames\\(LayoutManager.prototype\\).join\\(', '\\)\\);\n\")"
|
|
182
|
+
"Bash(cd /d/Code/foliko-plugins/poster-plugin && node -e \"\nconst LayoutManager = require\\('./src/layout-manager'\\);\nconsole.log\\('LayoutManager loaded successfully'\\);\nconsole.log\\('Methods:', Object.getOwnPropertyNames\\(LayoutManager.prototype\\).join\\(', '\\)\\);\n\")",
|
|
183
|
+
"Bash(node test-ctx-push.js 2>&1 | head -50)"
|
|
183
184
|
]
|
|
184
185
|
}
|
|
185
186
|
}
|
package/cli/src/ui/chat-ui.js
CHANGED
|
@@ -140,24 +140,29 @@ class ChatUI {
|
|
|
140
140
|
process.on('SIGINT', interruptHandler);
|
|
141
141
|
|
|
142
142
|
let fullResponse = '';
|
|
143
|
+
let sessionScope = null;
|
|
143
144
|
|
|
144
145
|
try {
|
|
145
146
|
const renderState = { inThink: false, inCodeBlock: false };
|
|
146
147
|
const runWithContext = this.agent.framework?.runWithContext.bind(this.agent.framework);
|
|
147
148
|
const { sessionId } = this;
|
|
148
149
|
|
|
150
|
+
// 创建当前 session 的事件作用域,自动过滤其他 session 的事件
|
|
151
|
+
sessionScope = this.agent.createSessionScope(sessionId);
|
|
152
|
+
|
|
149
153
|
if (this.stream) {
|
|
150
154
|
// 流式模式
|
|
151
155
|
console.log(colored('● ', GREEN));
|
|
152
156
|
|
|
153
157
|
let lineBuffer = '';
|
|
154
158
|
await runWithContext({ sessionId }, async () => {
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
// 使用 sessionScope 监听事件,自动只接收当前 session 的事件
|
|
160
|
+
if (sessionScope) {
|
|
161
|
+
sessionScope.on('stream:chunk', (data) => {
|
|
162
|
+
const { chunk } = data;
|
|
157
163
|
if (interrupted) return;
|
|
158
164
|
|
|
159
165
|
if (chunk.type === 'text') {
|
|
160
|
-
fullResponse += chunk.text;
|
|
161
166
|
lineBuffer += chunk.text;
|
|
162
167
|
|
|
163
168
|
while (lineBuffer.includes('\n')) {
|
|
@@ -173,25 +178,37 @@ class ChatUI {
|
|
|
173
178
|
} else if (chunk.type === 'tool-call') {
|
|
174
179
|
console.log(
|
|
175
180
|
`\n${colored('[工具调用]', YELLOW)} ${chunk.toolName}`,
|
|
181
|
+
`args=`,
|
|
176
182
|
JSON.stringify(chunk.input)
|
|
177
183
|
);
|
|
178
184
|
} else if (chunk.type === 'error') {
|
|
179
185
|
console.error(`\n${colored('[错误]', RED)} ${chunk.error}`);
|
|
180
186
|
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
sessionScope.on('message:complete', ({ sessionId, content }) => {
|
|
190
|
+
const message = '继续下一步';
|
|
191
|
+
if (!content) {
|
|
192
|
+
console.log(colored(`● ${message}...`, DIM));
|
|
193
|
+
this.agent.sendMessage(message, {
|
|
194
|
+
sessionId: sessionId,
|
|
195
|
+
priority: 1,
|
|
196
|
+
});
|
|
187
197
|
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const result = await this.agent.sendMessage(message, {
|
|
202
|
+
sessionId: sessionId,
|
|
203
|
+
priority: 1,
|
|
192
204
|
});
|
|
193
205
|
});
|
|
194
206
|
|
|
207
|
+
// 清除 session scope 的监听器
|
|
208
|
+
if (sessionScope) {
|
|
209
|
+
sessionScope.removeAllListeners();
|
|
210
|
+
}
|
|
211
|
+
|
|
195
212
|
if (lineBuffer.trim() && !interrupted) {
|
|
196
213
|
console.log(renderLine(lineBuffer, renderState));
|
|
197
214
|
}
|
|
@@ -218,10 +235,15 @@ class ChatUI {
|
|
|
218
235
|
}
|
|
219
236
|
}
|
|
220
237
|
} catch (err) {
|
|
238
|
+
console.log(err);
|
|
221
239
|
if (!interrupted) {
|
|
222
240
|
console.error(`\n${colored('[错误]', RED)} ${err.message}\n`);
|
|
223
241
|
}
|
|
224
242
|
} finally {
|
|
243
|
+
// 确保清理 session scope 的监听器
|
|
244
|
+
if (sessionScope) {
|
|
245
|
+
sessionScope.removeAllListeners();
|
|
246
|
+
}
|
|
225
247
|
process.removeListener('SIGINT', interruptHandler);
|
|
226
248
|
}
|
|
227
249
|
}
|
package/package.json
CHANGED
|
@@ -354,7 +354,7 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
354
354
|
existingPrompt = existingPrompt.replace(extRegex, '').trim();
|
|
355
355
|
|
|
356
356
|
// 添加新的 Extensions 部分
|
|
357
|
-
agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
|
|
357
|
+
//agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
_buildExtensionsDescription() {
|
|
@@ -81,18 +81,18 @@ class PythonPluginLoader extends Plugin {
|
|
|
81
81
|
this._loadPythonPlugins()
|
|
82
82
|
|
|
83
83
|
// 监听 agent 创建事件,附加 Python 插件信息到系统提示词
|
|
84
|
-
framework.on('agent:created', (agent) => {
|
|
85
|
-
|
|
86
|
-
})
|
|
84
|
+
// framework.on('agent:created', (agent) => {
|
|
85
|
+
// this._refreshAgentPythonPluginsPrompt(agent)
|
|
86
|
+
// })
|
|
87
87
|
|
|
88
88
|
// 等待框架就绪后,刷新所有已有 agent 的 Python 插件提示词
|
|
89
|
-
if (framework._ready) {
|
|
90
|
-
|
|
91
|
-
} else {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
89
|
+
// if (framework._ready) {
|
|
90
|
+
// this._refreshAllAgentsPythonPluginsPrompt(framework)
|
|
91
|
+
// } else {
|
|
92
|
+
// framework.once('framework:ready', () => {
|
|
93
|
+
// this._refreshAllAgentsPythonPluginsPrompt(framework)
|
|
94
|
+
// })
|
|
95
|
+
// }
|
|
96
96
|
|
|
97
97
|
return this
|
|
98
98
|
}
|
|
@@ -275,7 +275,7 @@ class PythonPluginLoader extends Plugin {
|
|
|
275
275
|
if (!pyDesc) return
|
|
276
276
|
|
|
277
277
|
// 将 Python 插件描述追加到系统提示词
|
|
278
|
-
agent.setSystemPrompt(existingPrompt + '\n\n' + pyDesc)
|
|
278
|
+
//agent.setSystemPrompt(existingPrompt + '\n\n' + pyDesc)
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
/**
|
|
@@ -574,12 +574,7 @@ class SchedulerPlugin extends Plugin {
|
|
|
574
574
|
this._taskStats.completed++
|
|
575
575
|
|
|
576
576
|
// 获取 LLM 返回的消息
|
|
577
|
-
|
|
578
|
-
if (result && result.message) {
|
|
579
|
-
responseText = result.message
|
|
580
|
-
} else if (result && result.text) {
|
|
581
|
-
responseText = result.text
|
|
582
|
-
}
|
|
577
|
+
const responseText = result.message
|
|
583
578
|
|
|
584
579
|
// if (responseText) {
|
|
585
580
|
// console.log(`\n🔔 [定时提醒] ${responseText}\n`)
|
|
@@ -87,13 +87,18 @@ class SubAgentPlugin extends Plugin {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// 获取从父Agent继承的工具
|
|
90
|
-
const parentTools = this._getParentTools(parentAgent)
|
|
90
|
+
// const parentTools = this._getParentTools(parentAgent)
|
|
91
91
|
|
|
92
92
|
// 确定LLM配置
|
|
93
93
|
const aiPlugin = this._framework.pluginManager.get('ai')
|
|
94
94
|
const llmConfig = this.llmConfig || (aiPlugin ? aiPlugin.getConfig() : {})
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
const all_tools=['ext_call']
|
|
96
|
+
if(Array.isArray(this.tools)){
|
|
97
|
+
all_tools.push(...this.tools)
|
|
98
|
+
}else if(typeof this.tools==='string'){
|
|
99
|
+
const list=this.tools.split(',').map(a=>a.trim())
|
|
100
|
+
all_tools.push(...list)
|
|
101
|
+
}
|
|
97
102
|
// 创建子Agent,使用完整的 md 文件内容作为系统提示词
|
|
98
103
|
this._agent = this._framework.createSubAgent({
|
|
99
104
|
name: this.name,
|
|
@@ -102,9 +107,10 @@ class SubAgentPlugin extends Plugin {
|
|
|
102
107
|
provider: llmConfig.provider,
|
|
103
108
|
apiKey: llmConfig.apiKey,
|
|
104
109
|
baseURL: llmConfig.baseURL,
|
|
105
|
-
tools:
|
|
106
|
-
parentTools:
|
|
110
|
+
tools:{}, // 自定义工具
|
|
111
|
+
parentTools: all_tools
|
|
107
112
|
})
|
|
113
|
+
|
|
108
114
|
|
|
109
115
|
// 注册从父Agent继承的工具
|
|
110
116
|
// for (const tool of parentTools) {
|
|
@@ -157,19 +163,20 @@ class SubAgentPlugin extends Plugin {
|
|
|
157
163
|
const toolMap = new Map(allTools.map(t => [t.name, t]))
|
|
158
164
|
|
|
159
165
|
// 如果没有指定 parentTools,返回全部
|
|
160
|
-
if (
|
|
166
|
+
if (this.parentTools === undefined) {
|
|
161
167
|
return allTools
|
|
162
168
|
}
|
|
169
|
+
// 如果是空数组,明确返回空(不要任何工具)
|
|
170
|
+
if (this.parentTools.length === 0) {
|
|
171
|
+
return []
|
|
172
|
+
}
|
|
163
173
|
// 过滤指定工具
|
|
164
174
|
const filtered = []
|
|
165
175
|
for (const toolName of this.parentTools) {
|
|
166
176
|
const tool = toolMap.get(toolName)
|
|
167
177
|
if (tool) {
|
|
168
178
|
filtered.push(tool)
|
|
169
|
-
}
|
|
170
|
-
// else {
|
|
171
|
-
// console.warn(`[SubAgent:${this.config.name}] Parent tool not found: ${toolName}`)
|
|
172
|
-
// }
|
|
179
|
+
}
|
|
173
180
|
}
|
|
174
181
|
|
|
175
182
|
return filtered
|
|
@@ -257,12 +264,12 @@ class SubAgentPlugin extends Plugin {
|
|
|
257
264
|
}
|
|
258
265
|
|
|
259
266
|
// 注册到框架(供后续创建的 Agent 同步)
|
|
260
|
-
|
|
267
|
+
framework.registerTool(toolDef)
|
|
261
268
|
|
|
262
269
|
// // 如果主 Agent 已存在,直接注册到它
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
270
|
+
if (framework._mainAgent) {
|
|
271
|
+
framework._mainAgent.registerTool(toolDef)
|
|
272
|
+
}
|
|
266
273
|
|
|
267
274
|
//console.log(`[SubAgent:${this.config.name}] Delegate tool registered`)
|
|
268
275
|
}
|
|
@@ -458,10 +465,14 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
458
465
|
|
|
459
466
|
try {
|
|
460
467
|
const result = await plugin.chat(args.task)
|
|
468
|
+
if(!result.success){
|
|
469
|
+
throw new Error(result.error||result.message)
|
|
470
|
+
}
|
|
471
|
+
|
|
461
472
|
return {
|
|
462
473
|
success: true,
|
|
463
474
|
agent: args.agentName,
|
|
464
|
-
result: result
|
|
475
|
+
result: result?.message || result?.content||result,
|
|
465
476
|
success: result.success !== false
|
|
466
477
|
}
|
|
467
478
|
} catch (err) {
|
package/plugins/web-plugin.js
CHANGED
|
@@ -521,7 +521,7 @@ class WebPlugin extends Plugin {
|
|
|
521
521
|
if (!webhook.awaitResponse) {
|
|
522
522
|
// 不等待,立即返回
|
|
523
523
|
webhookAgent.chat(`${prompt}\n\n数据:\n${JSON.stringify(webhookData, null, 2)}`).then(result => {
|
|
524
|
-
const responseText = result.message ||
|
|
524
|
+
const responseText = result.message || ''
|
|
525
525
|
log.info(` Webhook processed (${webhook.path}), LLM response (${responseText.length} chars)`)
|
|
526
526
|
|
|
527
527
|
// 添加到 session 历史
|
package/plugins/weixin-plugin.js
CHANGED
|
@@ -365,11 +365,12 @@ class WeixinPlugin extends Plugin {
|
|
|
365
365
|
* 使用 SessionPlugin 统一管理会话历史
|
|
366
366
|
*/
|
|
367
367
|
_getSessionAgent(userId) {
|
|
368
|
+
const sessionId=`weixin_${userId}`
|
|
368
369
|
// 检查缓存
|
|
369
370
|
if (this._sessionAgents.has(userId)) {
|
|
370
371
|
const agent = this._sessionAgents.get(userId)
|
|
371
372
|
// log.info(' Reusing cached session agent for userId:', userId)
|
|
372
|
-
return { agent, sessionId
|
|
373
|
+
return { agent, sessionId }
|
|
373
374
|
}
|
|
374
375
|
|
|
375
376
|
// 创建新 agent - 和 CLI 一样使用 createAgent
|
|
@@ -379,19 +380,24 @@ class WeixinPlugin extends Plugin {
|
|
|
379
380
|
sharedPrompt: `工作目录: {{WORK_DIR}}`,
|
|
380
381
|
metadata: { WORK_DIR: process.cwd() }
|
|
381
382
|
})
|
|
383
|
+
|
|
382
384
|
this._sessionAgents.set(userId, agent)
|
|
383
385
|
// log.info(' Created new session agent for userId:', userId)
|
|
384
386
|
|
|
385
387
|
// 使用 SessionPlugin 管理会话历史
|
|
386
388
|
if (this._sessionPlugin) {
|
|
387
|
-
const sessionId = `weixin_${userId}`
|
|
388
389
|
this._sessionPlugin.getOrCreateSession(sessionId, {
|
|
389
390
|
metadata: { platform: 'weixin', userId }
|
|
390
391
|
})
|
|
391
392
|
}
|
|
392
|
-
|
|
393
|
+
const sessionScope = agent.createSessionScope(sessionId);
|
|
394
|
+
// sessionScope.on('stream:chunk', ({chunk}) => {
|
|
395
|
+
// if (chunk.type === 'text') {
|
|
396
|
+
// process.stdout.write(chunk.text);
|
|
397
|
+
// }
|
|
398
|
+
// });
|
|
393
399
|
// log.info(` Session ready for user: ${userId}`)
|
|
394
|
-
return { agent, sessionId
|
|
400
|
+
return { agent, sessionId }
|
|
395
401
|
}
|
|
396
402
|
|
|
397
403
|
/**
|
|
@@ -468,28 +474,21 @@ class WeixinPlugin extends Plugin {
|
|
|
468
474
|
|
|
469
475
|
try {
|
|
470
476
|
// 使用 continue 获取流式响应
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
onChunk: (text, full) => {
|
|
475
|
-
if (text) fullResponse += text;
|
|
476
|
-
},
|
|
477
|
-
onComplete: async (full, ctx) => {
|
|
478
|
-
const response = cleanResponse(full);
|
|
479
|
-
if (response) {
|
|
480
|
-
await this._sendMessageBatch(originalMsg, userId, response, true)
|
|
481
|
-
} else {
|
|
482
|
-
// 响应为空,压入继续消息
|
|
483
|
-
const msg=`继续进行下一步`
|
|
484
|
-
await this._sendMessageBatch(originalMsg, userId, msg, true)
|
|
485
|
-
ctx.push(msg, { sessionId });
|
|
486
|
-
}
|
|
487
|
-
},
|
|
488
|
-
onError: async (err) => {
|
|
489
|
-
log.error(' Media chat error:', err.message);
|
|
490
|
-
await this._sendMessageBatch(originalMsg, userId, `发生错误:${err.message}`, true)
|
|
491
|
-
}
|
|
477
|
+
const result = await agent.sendMessage(text, {
|
|
478
|
+
sessionId: sessionId,
|
|
479
|
+
priority: 1,
|
|
492
480
|
});
|
|
481
|
+
const errors=result.chunks.filter(a=>a.type==='error').map(a=>a.error)
|
|
482
|
+
if(errors.length){
|
|
483
|
+
throw new Error(errors.join('\n'))
|
|
484
|
+
}
|
|
485
|
+
if(result.content){
|
|
486
|
+
await this._sendMessageBatch(originalMsg, userId, result.content, true)
|
|
487
|
+
}else{
|
|
488
|
+
const msg=`继续进行下一步`
|
|
489
|
+
await this._sendMessageBatch(originalMsg, userId, msg, true)
|
|
490
|
+
agent.sendMessage(msg,{sessionId,priority: 1})
|
|
491
|
+
}
|
|
493
492
|
} catch (err) {
|
|
494
493
|
log.error(' Media chat error:', err)
|
|
495
494
|
await this._sendMessageBatch(originalMsg, userId, `发生错误:${err.message}`, true)
|
|
@@ -516,27 +515,21 @@ class WeixinPlugin extends Plugin {
|
|
|
516
515
|
await new Promise((resolve) => setTimeout(resolve, 1000))
|
|
517
516
|
|
|
518
517
|
try {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
await agent.continue(text, sessionId, {
|
|
523
|
-
onChunk: (text, full) => {
|
|
524
|
-
if (text) fullResponse += text;
|
|
525
|
-
},
|
|
526
|
-
onComplete: async (full, ctx) => {
|
|
527
|
-
const response = cleanResponse(full);
|
|
528
|
-
if (response) {
|
|
529
|
-
await this._sendMessageBatch(originalMsg, userId, response, true)
|
|
530
|
-
} else {
|
|
531
|
-
// 响应为空,压入继续消息
|
|
532
|
-
ctx.push('请继续完成任务', { sessionId });
|
|
533
|
-
}
|
|
534
|
-
},
|
|
535
|
-
onError: async (err) => {
|
|
536
|
-
log.error(' Chat error:', err.message);
|
|
537
|
-
await this._sendMessageBatch(originalMsg, userId, `发生错误:${err.message}`, true)
|
|
538
|
-
}
|
|
518
|
+
const result = await agent.sendMessage(text, {
|
|
519
|
+
sessionId: sessionId,
|
|
520
|
+
priority: 1,
|
|
539
521
|
});
|
|
522
|
+
const errors=result.chunks.filter(a=>a.type==='error').map(a=>a.error)
|
|
523
|
+
if(errors.length){
|
|
524
|
+
throw new Error(errors.join('\n'))
|
|
525
|
+
}
|
|
526
|
+
if(result.content){
|
|
527
|
+
await this._sendMessageBatch(originalMsg, userId, result.content, true)
|
|
528
|
+
}else{
|
|
529
|
+
const msg=`继续进行下一步`
|
|
530
|
+
await this._sendMessageBatch(originalMsg, userId, msg, true)
|
|
531
|
+
agent.sendMessage(msg,{sessionId,priority: 1})
|
|
532
|
+
}
|
|
540
533
|
|
|
541
534
|
} catch (err) {
|
|
542
535
|
log.error(' Chat error:', err.message)
|