foliko 1.1.15 → 1.1.16

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.
@@ -3,45 +3,14 @@
3
3
  "messages": [
4
4
  {
5
5
  "role": "user",
6
- "content": "开启微信插件"
6
+ "content": "你好"
7
7
  },
8
8
  {
9
9
  "role": "assistant",
10
10
  "content": [
11
11
  {
12
12
  "type": "text",
13
- "text": "<think>\n用户想要开启微信插件。我需要使用 enable_plugin 工具来启用微信插件。\n</think>\n\n\n"
14
- },
15
- {
16
- "type": "tool-call",
17
- "toolCallId": "call_function_3pauayvivqe2_1",
18
- "toolName": "enable_plugin",
19
- "input": {
20
- "name": "weixin"
21
- }
22
- }
23
- ]
24
- },
25
- {
26
- "role": "tool",
27
- "content": [
28
- {
29
- "type": "tool-result",
30
- "toolCallId": "call_function_3pauayvivqe2_1",
31
- "toolName": "enable_plugin",
32
- "output": {
33
- "type": "text",
34
- "value": "{\"success\":true,\"message\":\"插件 'weixin' 已启用\"}"
35
- }
36
- }
37
- ]
38
- },
39
- {
40
- "role": "assistant",
41
- "content": [
42
- {
43
- "type": "text",
44
- "text": "<think>\n微信插件已成功启用。让我告诉用户结果。\n</think>\n\n✅ **微信插件已成功开启!**\n\n你现在可以使用以下微信功能:\n\n| 功能 | 说明 |\n|------|------|\n| 📱 发送文本消息 | `weixin_send_message` |\n| 🖼️ 发送图片 | `weixin_send_image` |\n| 📄 发送文件 | `weixin_send_file` |\n| 🎬 发送视频 | `weixin_send_video` |\n| 🎤 发送语音 | `weixin_send_voice` |\n\n> **注意**:微信功能需要你已登录微信网页版才能使用。"
13
+ "text": "<think>\n用户只是打了个招呼\"你好\"。这是一个简单的问候,我应该友好地回应并询问有什么可以帮助的。\n\n根据系统提示,我不需要调用任何工具就可以回复这个简单的问候。\n</think>\n\n你好!有什么我可以帮助你的吗?\n\n我可以帮你完成很多事情,比如:\n\n- 📊 **海报设计** - 使用 poster 插件制作精美海报\n- 📝 **文档转换** - 将 Markdown 渲染成图片\n- 💻 **代码执行** - 运行 Python、Shell 命令\n- 🌐 **网页抓取** - 获取网页内容\n- 📧 **邮件管理** - 发送和读取邮件\n- 💰 **加密货币交易** - Gate.io 交易操作\n- 🔧 **插件开发** - 开发 Foliko 插件\n- ⏰ **定时任务** - 设置提醒和定时任务\n- 💭 **记忆系统** - 存储和检索信息\n\n请告诉我你的需求!"
45
14
  }
46
15
  ]
47
16
  }
@@ -3,14 +3,14 @@
3
3
  "messages": [
4
4
  {
5
5
  "role": "user",
6
- "content": "\n [用户发送了图片消息]\n\n 文件列表:\n\n [\n \"D:\\\\Code\\\\foliko\\\\.agent\\\\data\\\\weixin\\\\images\\\\file_1776189097450.jpg\"\n] \n\n \n *重要:* 不要试图读取文件内容!\n "
6
+ "content": "你好"
7
7
  },
8
8
  {
9
9
  "role": "assistant",
10
10
  "content": [
11
11
  {
12
12
  "type": "text",
13
- "text": "<think>\n用户发送了一张图片,路径是 \"D:\\\\Code\\\\foliko\\\\.agent\\\\data\\\\weixin\\\\images\\\\file_1776189097450.jpg\"。我需要帮助用户查看这张图片的内容。\n\n我可以直接使用 read_file 工具来读取图片文件,但用户说不要试图读取文件内容。不过,用户可能是想让我帮忙识别图片内容或进行其他处理。\n\n让我先看看这张图片是什么类型的文件,然后尝试理解用户的需求。由于这是一个图片文件,我可以考虑使用 Python 来处理它,或者直接向用户询问他们想对这张图片做什么。\n\n实际上,从工具列表来看,我没有专门处理图片的工具。我应该告诉用户我收到了图片,并询问他们想对这张图片做什么。\n\n等等,用户说的是\"不要试图读取文件内容\",这可能是因为:\n1. 图片是私密内容,不想让我知道\n2. 只是想让我识别图片内容\n3. 担心读取大文件会有问题\n\n无论如何,我应该询问用户他们希望我对这张图片做什么操作。\n</think>\n\n我收到了你发送的图片文件。请问你想对这张图片做什么处理?比如:\n\n- **识别图片内容**(描述图片中的内容)\n- **提取图片文字**(OCR)\n- **查看图片信息**(尺寸、格式、大小等)\n- **其他处理**\n\n请告诉我你的需求,我会帮你处理。"
13
+ "text": "<think>\n用户只是打了个招呼\"你好\",这是一个简单的问候,我应该直接回复。\n</think>\n\n你好!有什么我可以帮助你的吗?"
14
14
  }
15
15
  ]
16
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.15",
3
+ "version": "1.1.16",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -390,13 +390,19 @@ class WeixinPlugin extends Plugin {
390
390
  }
391
391
 
392
392
  // 创建新 agent - 和 CLI 一样使用 createAgent
393
+ const aiPlugin = this._framework.pluginManager.get('ai')
394
+ const aiConfig = aiPlugin?.config || {}
393
395
  const agent = this._framework.createAgent({
394
396
  name: `weixin_${userId}`,
395
397
  systemPrompt: this.systemPrompt,
396
398
  sharedPrompt: `工作目录: {{WORK_DIR}}`,
397
- metadata: { WORK_DIR: process.cwd() }
399
+ metadata: { WORK_DIR: process.cwd() },
400
+ model: aiConfig.model,
401
+ provider: aiConfig.provider,
402
+ apiKey: aiConfig.apiKey,
403
+ baseURL: aiConfig.baseURL
398
404
  })
399
-
405
+
400
406
  this._sessionAgents.set(userId, agent)
401
407
  // log.info(' Created new session agent for userId:', userId)
402
408
 
@@ -425,11 +425,11 @@ class AgentChatHandler extends EventEmitter {
425
425
  if (!this._aiClient) {
426
426
  throw new Error('AI client not configured.');
427
427
  }
428
-
428
+ const systemPrompt=framework._mainAgent._buildSystemPrompt()
429
429
  const tools = this._getAITools(aiTool);
430
430
  const agent = new ToolLoopAgent({
431
431
  model: this._aiClient,
432
- instructions: this._systemPrompt,
432
+ instructions: systemPrompt,
433
433
  tools,
434
434
  stopWhen: isLoopFinished(),
435
435
  prepareStep: this._createPrepareStep(),
@@ -441,9 +441,8 @@ class AgentChatHandler extends EventEmitter {
441
441
 
442
442
  const stream = result.fullStream;
443
443
  let fullText = '';
444
- const iterator = stream[Symbol.asyncIterator] ? stream : stream.fullStream;
445
444
 
446
- for await (const part of iterator || stream) {
445
+ for await (const part of stream) {
447
446
  if (part.type === 'text-delta') {
448
447
  const text = part.text || part.textDelta || '';
449
448
  fullText += text;
@@ -490,7 +489,7 @@ class AgentChatHandler extends EventEmitter {
490
489
  if (isTransientError) {
491
490
  yield { type: 'error', error: 'AI 服务暂时不可用,请稍后重试。' };
492
491
  } else {
493
- logger.error(`[AgentChat] Stream error: ${err.message}`);
492
+ logger.error(`[AgentChat] Stream error: ${err.message}`, err.stack);
494
493
  this.emit('error', { error: err.message });
495
494
  yield { type: 'error', error: err.message };
496
495
  }
@@ -732,27 +731,33 @@ class AgentChatHandler extends EventEmitter {
732
731
  _createPrepareStep() {
733
732
  return async ({ stepNumber, messages: inputMessages }) => {
734
733
  try {
734
+ // 检查 inputMessages 是否是有效数组
735
+ if (!Array.isArray(inputMessages)) {
736
+ logger.error('prepareStep: inputMessages is not an array', typeof inputMessages);
737
+ return { messages: [] };
738
+ }
739
+
735
740
  const tokenCount = this._countMessagesTokens(inputMessages);
736
741
  const tokenLimit = this._maxContextTokens * 0.75;
737
742
 
738
743
  if (inputMessages.length > 50 || tokenCount > tokenLimit) {
739
744
  const pairedMessages = this._compressContextForPrepare(inputMessages);
740
- if (pairedMessages.length !== inputMessages.length) {
745
+ if (Array.isArray(pairedMessages) && pairedMessages.length !== inputMessages.length) {
741
746
  inputMessages.length = 0;
742
747
  inputMessages.push(...pairedMessages);
743
748
  }
744
749
  }
745
750
 
746
751
  const validated = this._validateMessagesPairing(inputMessages);
747
- if (validated.length !== inputMessages.length) {
752
+ if (Array.isArray(validated) && validated.length !== inputMessages.length) {
748
753
  inputMessages.length = 0;
749
754
  inputMessages.push(...validated);
750
755
  }
751
756
  this._validateToolCalls(inputMessages);
752
757
  return { messages: inputMessages };
753
758
  } catch (err) {
754
- logger.error('prepareStep error:', err.message);
755
- return { messages: inputMessages };
759
+ logger.error('prepareStep error:', err.message, err.stack);
760
+ return { messages: inputMessages || [] };
756
761
  }
757
762
  };
758
763
  }