foliko 1.1.27 → 1.1.28

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 (44) hide show
  1. package/.agent/data/default.json +1 -25
  2. package/.agent/data/plugins-state.json +1 -1
  3. package/.agent/mcp_config.json +0 -7
  4. package/.agent/sessions/cli_default.json +66 -43
  5. package/.claude/settings.local.json +4 -1
  6. package/examples/test-think-continuous.js +88 -0
  7. package/package.json +1 -1
  8. package/plugins/think-plugin.js +73 -9
  9. package/plugins/web-plugin.js +5 -0
  10. package/src/core/agent-chat.js +46 -13
  11. package/src/core/chat-session.js +13 -0
  12. package/src/core/subagent.js +2 -0
  13. package/test-api.js +34 -0
  14. package/.agent/memory/feedback/mnxe0cxc-14l6q5.md +0 -17
  15. package/.agent/memory/feedback/mnxe11pa-nxf577.md +0 -9
  16. package/.agent/memory/feedback/mnxe1an2-84faff.md +0 -9
  17. package/.agent/memory/feedback/mnxgcfj0-qg3wjc.md +0 -9
  18. package/.agent/memory/feedback/mnxgcn3y-40mqss.md +0 -9
  19. package/.agent/memory/feedback/mnxgcxq9-jm7ydl.md +0 -9
  20. package/.agent/memory/feedback/mnxgdyfj-pzjvkb.md +0 -9
  21. package/.agent/memory/feedback/mnxge3z1-7vyit1.md +0 -9
  22. package/.agent/memory/feedback/mnxhrg28-41hhjr.md +0 -9
  23. package/.agent/memory/feedback/mnxhrx0e-yth94k.md +0 -9
  24. package/.agent/memory/feedback/mnxhs3jd-rvx8aq.md +0 -9
  25. package/.agent/memory/feedback/mnxhs7p7-g5rtn9.md +0 -9
  26. package/.agent/memory/feedback/mnxhslx5-oqwuhr.md +0 -9
  27. package/.agent/memory/feedback/mnxhsvd6-nuyvvc.md +0 -9
  28. package/.agent/memory/project/mnxegq6z-5fc64w.md +0 -22
  29. package/.agent/memory/project/mnxh2w4r-le9hur.md +0 -17
  30. package/.agent/memory/project/mnxhq2yv-9qa8ay.md +0 -31
  31. package/.agent/memory/project/mnxhql11-iaun2o.md +0 -34
  32. package/.agent/memory/project/mnxhr78p-jpg7eq.md +0 -23
  33. package/.agent/memory/reference/mnxe0oa9-p6wzk6.md +0 -27
  34. package/.agent/memory/reference/mnxehcll-kcrmpf.md +0 -29
  35. package/.agent/memory/reference/mnxei0ts-jw091y.md +0 -18
  36. package/.agent/memory/reference/mnxfnrr4-rski36.md +0 -40
  37. package/.agent/memory/reference/mnxfo6n5-af9zls.md +0 -18
  38. package/.agent/memory/reference/mnxh2ady-u6cmvk.md +0 -61
  39. package/.agent/memory/reference/mnxhqdqh-ucsbsk.md +0 -31
  40. package/.agent/memory/reference/mnxiixyp-rz2gvw.md +0 -34
  41. package/.agent/memory/user/mnxhqxk3-vjjhlf.md +0 -23
  42. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +0 -392
  43. package/system1.md +0 -4042
  44. package/test_poster.png +0 -0
@@ -1,25 +1 @@
1
- {
2
- "session:cli_default": {
3
- "messages": [],
4
- "variables": {},
5
- "metadata": {
6
- "platform": "cli"
7
- },
8
- "createdAt": "2026-04-06T11:30:16.479Z",
9
- "lastActive": "2026-04-06T11:30:16.479Z"
10
- },
11
- "session:weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat": {
12
- "messages": [],
13
- "variables": {},
14
- "metadata": {
15
- "platform": "weixin",
16
- "userId": "o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat"
17
- },
18
- "createdAt": "2026-04-11T19:20:50.718Z",
19
- "lastActive": "2026-04-11T19:20:50.718Z"
20
- },
21
- "business_card:business_card_info": {
22
- "value": "{\"name\": \"张明远\", \"title\": \"技术总监\", \"company\": \"星辰科技有限公司\", \"phone\": \"+86 138-0000-1234\", \"email\": \"zhangmingyuan@startech.com\", \"website\": \"www.startech.com\", \"address\": \"北京市朝阳区科技园A座1201\", \"file\": \"business_card.png\", \"size\": \"1050x630\", \"dpi\": 300, \"created\": \"2026-04-13\"}",
23
- "updatedAt": "2026-04-12T16:27:27.826Z"
24
- }
25
- }
1
+ {"session:cli_default":{"messages":[],"variables":{},"metadata":{}},"session:weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat":{"messages":[],"variables":{},"metadata":{"platform":"weixin","userId":"o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat"},"createdAt":"2026-04-11T19:20:50.718Z","lastActive":"2026-04-11T19:20:50.718Z"},"business_card:business_card_info":{"value":"{\"name\": \"张明远\", \"title\": \"技术总监\", \"company\": \"星辰科技有限公司\", \"phone\": \"+86 138-0000-1234\", \"email\": \"zhangmingyuan@startech.com\", \"website\": \"www.startech.com\", \"address\": \"北京市朝阳区科技园A座1201\", \"file\": \"business_card.png\", \"size\": \"1050x630\", \"dpi\": 300, \"created\": \"2026-04-13\"}","updatedAt":"2026-04-12T16:27:27.826Z"}}
@@ -234,7 +234,7 @@
234
234
  "config": {}
235
235
  },
236
236
  "weixin": {
237
- "enabled": true,
237
+ "enabled": false,
238
238
  "config": {
239
239
  "forceLogin": false,
240
240
  "qrcodeTerminal": true,
@@ -1,11 +1,4 @@
1
1
  {
2
2
  "mcpServers": {
3
- "designmd": {
4
- "command": "npx",
5
- "args": ["designmd-mcp"],
6
- "env": {
7
- "DESIGNMD_API_KEY": "dk_a8df8439b0b7de2b55a059814bc1e085b66fc0ee"
8
- }
9
- }
10
3
  }
11
4
  }
@@ -1,36 +1,37 @@
1
1
  {
2
2
  "sessionId": "cli_default",
3
3
  "messages": [
4
- {
5
- "role": "user",
6
- "content": "你好"
7
- },
8
4
  {
9
5
  "role": "assistant",
10
- "content": [
11
- {
12
- "type": "text",
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请告诉我你的需求!"
14
- }
15
- ]
6
+ "content": "【数字9的意义 总结】\n**数字9的意义总结**\n\n数字9在多个维度呈现独特的象征意义。\n\n**数学层面**,9作为最大个位数,具有“数字根”特性——任何9的倍数其各位数字之和仍为9的倍数,隐喻“回归本源”。\n\n**文化层面**,中国视9为阳数之极,谐音“久”,象征永恒与尊贵,如“九五之尊”“九重天”;西方毕达哥拉斯学派则认为9代表完结与开始。\n\n**艺术领域**,第9部作品常被视为艺术家的“遗言”——贝多芬第九交响曲、马勒第九交响曲均成绝响。\n\n**哲学层面**,9处于从“统一”(1)到“完满”(9)的终点,此后回归虚无(0),开启新的循环,体现周期更替的宇宙观。",
7
+ "metadata": {
8
+ "isThinkingSummary": true,
9
+ "topic": "数字9的意义",
10
+ "rounds": 2
11
+ }
16
12
  },
17
13
  {
18
14
  "role": "user",
19
- "content": "关闭微信插件"
15
+ "content": "开启持续思考模式,思考人生的意义"
20
16
  },
21
17
  {
22
18
  "role": "assistant",
23
19
  "content": [
24
20
  {
25
21
  "type": "text",
26
- "text": "<think>\n用户想要关闭微信插件。我需要使用 disable_plugin 工具来禁用 weixin 插件。\n</think>\n\n\n"
22
+ "text": "<think>\n用户要求开启持续思考模式来思考人生的意义。这是一个关于哲学和人生观的深度思考问题。根据系统能力,我应该使用 think 插件来实现持续思考。\n\n根据工具描述:\n- think_continue: 让 LLM 持续思考模式(后台自动思考,定期输出结果)\n - interval: 思考间隔毫秒,默认 30000 (30秒)\n - topic: 思考主题\n\n用户要求思考\"人生的意义\",这是一个深刻的主题,我应该设置较长的思考间隔(如60000毫秒=1分钟),这样可以给出有深度的思考结果。\n</think>\n\n我将为你开启持续思考模式,深入思考人生的意义这个永恒命题。\n"
27
23
  },
28
24
  {
29
25
  "type": "tool-call",
30
- "toolCallId": "call_function_fq6znurz0zqk_1",
31
- "toolName": "disable_plugin",
26
+ "toolCallId": "call_function_4vwshtp6fwf2_1",
27
+ "toolName": "ext_call",
32
28
  "input": {
33
- "name": "weixin"
29
+ "plugin": "think",
30
+ "tool": "think_continue",
31
+ "args": {
32
+ "interval": 60000,
33
+ "topic": "人生的意义"
34
+ }
34
35
  }
35
36
  }
36
37
  ]
@@ -40,11 +41,11 @@
40
41
  "content": [
41
42
  {
42
43
  "type": "tool-result",
43
- "toolCallId": "call_function_fq6znurz0zqk_1",
44
- "toolName": "disable_plugin",
44
+ "toolCallId": "call_function_4vwshtp6fwf2_1",
45
+ "toolName": "ext_call",
45
46
  "output": {
46
47
  "type": "text",
47
- "value": "{\"success\":true,\"message\":\"插件 'weixin' 已禁用\"}"
48
+ "value": "{\"success\":true,\"result\":{\"success\":true,\"message\":\"【持续思考已启动】\\n间隔: 60000ms\\n主题: 人生的意义\\n\\nLLM 将定期自动思考并在有新想法时通知你。\"}}"
48
49
  }
49
50
  }
50
51
  ]
@@ -54,52 +55,74 @@
54
55
  "content": [
55
56
  {
56
57
  "type": "text",
57
- "text": "<think>\n成功禁用了微信插件。\n</think>\n\n微信插件已成功禁用。"
58
+ "text": "<think>\n持续思考模式已成功启动。我应该向用户说明当前状态,并给出一些初步的思考框架,让用户知道系统正在运作。\n</think>\n\n✅ **持续思考模式已启动**\n\n- 思考主题:人生的意义\n- 思考间隔:每 60 秒进行一次深度思考\n- 每次有新的想法时会通知你\n\n---\n\n**初始思考方向**\n\n关于\"人生的意义\",以下几个维度值得深入探索:\n\n1. **存在主义视角** — 人生本无预设意义,意义由我们主动创造\n2. **关系视角** — 意义在于与他人的连接、爱与被爱\n3. **成长视角** — 意义在于自我实现、超越自我\n4. **体验视角** — 意义在于感受生命本身的丰富性\n5. **传承视角** — 意义在于留下些什么、影响后人\n\n持续思考正在进行中,稍后将为你呈现更深入的洞见……\n\n是否想调整思考方向,或者有特定角度希望我重点探讨?"
58
59
  }
59
60
  ]
60
61
  },
62
+ {
63
+ "role": "assistant",
64
+ "content": "【人生的意义 总结】\n**人生意义的多维思考总结**\n\n人生意义是一个多维度的哲学命题。存在主义视角认为,意义并非预设存在,而是通过个体主动的选择、责任承担和实际行动来创造。关系性视角则强调,爱、与他人的深层连接及对他人生命的积极影响,是意义感的核心来源。超越性维度指出,使命感、精神成长和超越个人利益的奉献追求,能够带来更深层的意义体验。此外,过程性理解揭示了意义不在于抵达某个终点,而在于持续成长、体验与自我超越的动态过程。综合来看,意义既是主动建构的,也是关系中生成的;既存在于超越性追求中,也蕴含于持续的成长体验里。",
65
+ "metadata": {
66
+ "isThinkingSummary": true,
67
+ "topic": "人生的意义",
68
+ "rounds": 2
69
+ }
70
+ },
61
71
  {
62
72
  "role": "user",
63
- "content": "你好啊"
73
+ "content": "得出的结论是什么"
64
74
  },
65
75
  {
66
76
  "role": "assistant",
67
77
  "content": [
68
78
  {
69
79
  "type": "text",
70
- "text": "<think>\n用户只是打了个招呼,没有具体需求。我简单友好地回复即可。\n</think>\n\n你好!有什么需要帮忙的吗?"
80
+ "text": "<think>\n用户想了解持续思考得出的结论。我需要获取思考历史记录来查看LLM持续思考的结果。\n</think>\n\n\n"
81
+ },
82
+ {
83
+ "type": "tool-call",
84
+ "toolCallId": "call_function_w3neynu9ooyc_1",
85
+ "toolName": "ext_call",
86
+ "input": {
87
+ "plugin": "think",
88
+ "tool": "think_get_thoughts",
89
+ "args": {
90
+ "limit": 20
91
+ }
92
+ }
71
93
  }
72
94
  ]
73
95
  },
74
96
  {
75
- "role": "user",
76
- "content": "今"
77
- },
78
- {
79
- "role": "assistant",
97
+ "role": "tool",
80
98
  "content": [
81
99
  {
82
- "type": "text",
83
- "text": "<think>\n用户只发了一个字\"今\",这可能是个不完整的输入,可能是想说\"今天\"或其他什么。我应该友好地询问用户想要表达什么。\n</think>\n\n你好!你的消息好像发送不完整,请问你想要说什么或需要什么帮助呢?😊"
100
+ "type": "tool-result",
101
+ "toolCallId": "call_function_w3neynu9ooyc_1",
102
+ "toolName": "ext_call",
103
+ "output": {
104
+ "type": "text",
105
+ "value": "{\"success\":true,\"result\":{\"success\":true,\"thoughts\":[{\"id\":1776446598300,\"mode\":\"reflect\",\"depth\":2,\"topic\":\"人生的意义\",\"prompt\":\"请简单反思:\\n\\n1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充\\n2. 如果发现遗漏或更好的思路,请输出\\n3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束\\n\\n额外关注: 人生的意义\\n\\n请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。\",\"result\":\"【无新增论点,思考已充分】\\n\\n当前对话中无前序思考内容可供检视。\",\"timestamp\":\"2026-04-17T17:23:18.300Z\",\"messages\":[{\"role\":\"user\",\"content\":\"请简单反思:\\n\\n1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充\\n2. 如果发现遗漏或更好的思路,请输出\\n3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束\\n\\n额外关注: 人生的意义\\n\\n请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。\"},{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"<think>用户要求我进行反思,检查之前是否有遗漏的分析角度或补充,特别是关于\\\"人生的意义\\\"这个主题。\\n\\n但我需要回顾一下:之前的对话内容中并没有关于\\\"人生意义\\\"的深入讨论。用户之前只是让我进行简单的反思,但没有给出具体要反思的主题。\\n\\n现在用户明确说要关注\\\"人生的意义\\\",这是一个哲学性的深度话题。让我思考一下:\\n\\n1. 我之前是否有关于\\\"人生意义\\\"的思考?从对话历史看,似乎没有深入讨论过这个话题\\n2. \\\"人生的意义\\\"本身就是一个深刻且多维的哲学问题,我可以提供一些补充性的思考\\n\\n但问题是,用户要求我反思\\\"基于之前的思考\\\",而之前的思考内容在当前对话中并没有提供给我。我只能看到用户现在的问题。\\n\\n让我分析一下关于\\\"人生的意义\\\"这个话题可能的思考角度:\\n\\n**传统观点:**\\n- 宗教/灵性视角:人生意义来自上帝/超越性存在\\n- 存在主义:人生本无固定意义,需要自己创造\\n- 功利主义:追求最大幸福\\n- 成就导向:事业成功、财富积累\\n\\n\\n- 关系导向:爱与被爱、家庭\\n- 体验导向:丰富的人生体验\\n\\n**现代/新兴视角:**\\n- 心理学视角:心流、峰值体验、自我实现(马斯洛)\\n- 意义疗法(维克多·弗兰克尔):找到\\\"活着的理由\\\"\\n- 积极心理学:幸福感、感恩、心灵花园\\n- 集体主义视角:个人意义与社会贡献的结合\\n- 生态整体观:人生意义与生态系统的联系\\n\\n思考这个话题时,我意识到用户的请求似乎基于之前的对话内容,但当前对话中并没有显示。用户的指令要求我\\\"基于之前的思考\\\"进行反思,这意味着我应该依赖之前的思考成果。然而,由于之前的思考内容在当前对话中不可见,我无法直接进行对比和补充。\\n\\n用户明确要求关注\\\"人生的意义\\\"这个主题,并强调如果没有新论点就要明确输出【无新增论点,思考已充分】。这表明之前的对话中确实讨论过这个话题,但我现在看不到具体内容。\\n\\n鉴于这是一个哲学深度话题,我应该从多个角度提供补充性思考:超越性意义(宗教、使命、精神成长)、存在主义视角(创造意义的过程、选择与承担责任)、关系与连接(人际纽带对他人的影响)、成长与贡献(自我实现与他人的利益)以及超越二元对立(意义的多元性与流动性)。但我需要谨慎,因为用户的核心要求是基于之前的思考进行反思,如果之前已经充分讨论过这个主题,我的补充可能不必要。\\n\\n我需要重新审视用户的实际需求。他们要求我反思之前的思考内容,检查是否有新的论点或分析角度,并明确指出遗漏或更好的思路。如果没有新内容,就输出【无新增论点,思考已充分】并结束。这个请求暗示之前的对话中确实讨论过\\\"人生的意义\\\"这个主题。我应该思考关于人生意义这个话题可能的思考维度。\\n\\n但我面临一个关键问题:我没有看到之前的思考内容,无法直接评估是否有遗漏。用户明确要求\\\"直接输出反思结果,不重复之前的对话内容\\\",这意味着用户可能认为之前的思考已经包含了相关信息,或者用户自己在之前的讨论中已经提到了这个主题。由于用户现在明确指出要额外关注人生的意义,这表明之前的对话中讨论过这个话题,我的反思应该基于这个假设进行。\\n\\n关于人生意义的思考需要考虑几个核心维度。存在主义强调人需要主动创造自己的意义,而非被动接受既定的答案。心理学研究表明,拥有清晰的人生意义感对心理健康和幸福感至关重要。弗兰克尔的意义疗法指出,人能够通过发现意义、创造意义和面对苦难时找到意义来克服困境。\\n\\n这些观点并非全新的论点。我需要重新理解用户的实际需求——他们要求的是基于之前对话内容的反思,而不是对这个主题的初次分析。由于我看不到之前的思考记录,我的反思应该是谨慎的。用户明确指出要\\\"额外关注:人生的意义\\\",这可能意味着之前讨论过这个话题但没有深入,或者用户想要引导我朝这个方向思考。\\n\\n作为AI,我的反思能力有限,但关于人生意义这个问题,我可以提供一个可能的思考框架。这个框架包括多个维度:超越性追求(宗教、精神、使命导向)、自我实现与成长、内在幸福感以及人生意义的流动性——它可能随时间变化,而非固定不变。这个框架本身提供了一些新的视角。\\n\\n如果之前的思考已经涵盖了这些方面,或者这只是一个补充性的关注点而非核心主题,那么这些观点可能不算全新。但用户的表述暗示人生意义可能是一个相对未被充分探讨的维度,因此我应该指出这些思考方向作为补充。这样做既能响应用户对反思的要求,又能诚实地说明我的分析基于对人生意义维度的假设。\\n</think>\\n\\n【无新增论点,思考已充分】\\n\\n基于当前对话上下文,关于“人生的意义”这一主题,此前对话中并未涉及深度讨论。若需展开这一议题的思考,可从以下维度进行:\\n\\n1. **存在主义路径**:意义并非既定存在,而是由个体主动创造——选择、责任与行动赋予人生价值\\n2. **关系性视角**:爱、连接、对他人生命的积极影响,构成意义感的核心来源\\n3. **超越性维度**:使命感、精神成长、奉献超越个体利益的意义追求\\n4. **过程性理解**:意义不在于抵达某个终点,而在于持续成长、体验与自我超越的动态过程\\n\\n如需基于具体思考内容进行反思,请提供前序思考记录,我可进行针对性补充分析。\"}]},{\"role\":\"user\",\"content\":\"请简单反思:\\n\\n1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充\\n2. 如果发现遗漏或更好的思路,请输出\\n3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束\\n\\n额外关注: 人生的意义\\n\\n请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。\"},{\"role\":\"assistant\",\"content\":\"【无新增论点,思考已充分】\\n\\n当前对话中无前序思考内容可供检视。\"}]},{\"id\":1776446531818,\"mode\":\"reflect\",\"depth\":2,\"topic\":\"人生的意义\",\"prompt\":\"请简单反思:\\n\\n1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充\\n2. 如果发现遗漏或更好的思路,请输出\\n3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束\\n\\n额外关注: 人生的意义\\n\\n请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。\",\"result\":\"【无新增论点,思考已充分】\\n\\n基于当前对话上下文,关于“人生的意义”这一主题,此前对话中并未涉及深度讨论。若需展开这一议题的思考,可从以下维度进行:\\n\\n1. **存在主义路径**:意义并非既定存在,而是由个体主动创造——选择、责任与行动赋予人生价值\\n2. **关系性视角**:爱、连接、对他人生命的积极影响,构成意义感的核心来源\\n3. **超越性维度**:使命感、精神成长、奉献超越个体利益的意义追求\\n4. **过程性理解**:意义不在于抵达某个终点,而在于持续成长、体验与自我超越的动态过程\\n\\n如需基于具体思考内容进行反思,请提供前序思考记录,我可进行针对性补充分析。\",\"timestamp\":\"2026-04-17T17:22:11.818Z\",\"messages\":[{\"role\":\"user\",\"content\":\"请简单反思:\\n\\n1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充\\n2. 如果发现遗漏或更好的思路,请输出\\n3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束\\n\\n额外关注: 人生的意义\\n\\n请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。\"},{\"role\":\"assistant\",\"content\":\"【无新增论点,思考已充分】\\n\\n基于当前对话上下文,关于“人生的意义”这一主题,此前对话中并未涉及深度讨论。若需展开这一议题的思考,可从以下维度进行:\\n\\n1. **存在主义路径**:意义并非既定存在,而是由个体主动创造——选择、责任与行动赋予人生价值\\n2. **关系性视角**:爱、连接、对他人生命的积极影响,构成意义感的核心来源\\n3. **超越性维度**:使命感、精神成长、奉献超越个体利益的意义追求\\n4. **过程性理解**:意义不在于抵达某个终点,而在于持续成长、体验与自我超越的动态过程\\n\\n如需基于具体思考内容进行反思,请提供前序思考记录,我可进行针对性补充分析。\"}]}],\"total\":2}}"
106
+ }
84
107
  }
85
108
  ]
86
109
  },
87
- {
88
- "role": "user",
89
- "content": "今天星期几?"
90
- },
91
110
  {
92
111
  "role": "assistant",
93
112
  "content": [
94
113
  {
95
114
  "type": "text",
96
- "text": "<think>\n用户问今天星期几,我需要获取当前时间信息。\n</think>\n\n\n"
115
+ "text": "<think>\n从思考历史来看,持续思考模式进行了多次反思,但每次都因为\"无前序思考内容\"而标记为\"无新增论点\"。这说明持续思考在当前对话中并没有实际产生新的思考内容。\n\n让我总结一下给用户:\n1. 持续思考已运行,但因缺少前序内容参考,每次反思都标记无新论点\n2. 提供了一些关于\"人生意义\"的思考维度供参考\n\n但这个问题我也需要诚实回答 - 持续思考模式启动了,但因为是全新的对话会话,没有之前的思考内容可供检视,所以每次反思都返回\"无新增论点\"。\n\n我应该停止这个思考模式,然后给用户一个清晰的总结。\n</think>\n\n让我先停止这个没有实际产出的持续思考模式:\n"
97
116
  },
98
117
  {
99
118
  "type": "tool-call",
100
- "toolCallId": "call_function_xxe5r4wlfi0c_1",
101
- "toolName": "get_time",
102
- "input": {}
119
+ "toolCallId": "call_function_icijebz5vam6_1",
120
+ "toolName": "ext_call",
121
+ "input": {
122
+ "plugin": "think",
123
+ "tool": "think_stop",
124
+ "args": {}
125
+ }
103
126
  }
104
127
  ]
105
128
  },
@@ -108,11 +131,11 @@
108
131
  "content": [
109
132
  {
110
133
  "type": "tool-result",
111
- "toolCallId": "call_function_xxe5r4wlfi0c_1",
112
- "toolName": "get_time",
134
+ "toolCallId": "call_function_icijebz5vam6_1",
135
+ "toolName": "ext_call",
113
136
  "output": {
114
137
  "type": "text",
115
- "value": "{\"success\":true,\"beijingTime\":\"2026-04-17 22:00:30\",\"timestamp\":1776434430624,\"timezone\":\"Asia/Shanghai (UTC+8)\",\"formatted\":{\"year\":2026,\"month\":\"04\",\"day\":\"17\",\"hour\":\"22\",\"minute\":\"00\",\"second\":\"00\"}}"
138
+ "value": "{\"success\":true,\"result\":{\"success\":true,\"message\":\"持续思考已停止\"}}"
116
139
  }
117
140
  }
118
141
  ]
@@ -122,16 +145,16 @@
122
145
  "content": [
123
146
  {
124
147
  "type": "text",
125
- "text": "<think>\n根据当前时间 2026-04-17,用户问今天星期几。我可以计算一下:2026年4月17日是星期五。不过我看到系统提示中已经明确说了是\"星期五\",所以我可以直接回答。\n</think>\n\n今天是 **2026年4月17日,星期五**。"
148
+ "text": "<think>\n用户问我持续思考得出的结论是什么。我需要诚实说明情况:\n\n1. 持续思考启动了,但因为是全新的对话会话,没有之前的内容可供检视\n2. 所以每次\"反思\"都返回\"无新增论点\"\n3. 实际上持续思考没有产生实质性的思考结果\n\n我应该:\n1. 承认持续思考没有产生实质结论(因为缺少前序内容)\n2. 直接给用户一个关于\"人生意义\"的思考总结,而不是依赖自动思考\n\n让我直接回答用户的问题,给出一个有价值的总结。\n</think>\n\n**坦诚说明:**\n\n持续思考模式实际上没有产生实质结论。原因:这是全新的对话会话,持续思考的\"反思\"机制需要参考前序思考内容,但会话中没有——每次反思都因\"无前序内容\"而标记\"无新增论点\"。\n\n---\n\n**直接回答你的问题:人生的意义是什么**\n\n这个问题没有标准答案,但以下是几种被广泛认同的思考路径:\n\n| 视角 | 核心观点 |\n|------|----------|\n| **存在主义** | 意义不是被发现的,而是被创造的——你选择成为谁,你就是谁 |\n| **关系主义** | 意义根植于爱、连接、对他人生命的积极影响 |\n| **超越主义** | 意义来自使命感、精神成长、奉献比自己更大的事业 |\n| **过程主义** | 意义不在终点,而在\"成为\"的过程——成长、体验、创造 |\n\n**一个反直觉的洞见:** 过度追问\"人生有什么意义\"反而可能让人陷入虚无。有时候,意义不需要被追问——它在你专注做事、深度连接、认真生活的过程中自然浮现。\n\n你更倾向于哪种视角?或者有具体的困惑想探讨?"
126
149
  }
127
150
  ]
128
151
  }
129
152
  ],
130
153
  "variables": {},
131
154
  "metadata": {
132
- "createdAt": 1776096714159,
133
- "lastActive": 1776096714159,
134
- "messageCount": 0,
155
+ "createdAt": 1776446323386,
156
+ "lastActive": 1776446604296,
157
+ "messageCount": 2,
135
158
  "compressionCount": 0
136
159
  }
137
160
  }
@@ -202,7 +202,10 @@
202
202
  "Bash(node -e \"\nconst { createTools } = require\\('ai'\\);\nconsole.log\\('createTools exists:', typeof createTools\\);\n\" 2>&1)",
203
203
  "Bash(node -e \"\nconst poster = require\\('/d/code/foliko-plugins/poster-plugin'\\);\nconsole.log\\('poster.tools:', typeof poster.tools\\);\nconsole.log\\('poster.tools keys:', Object.keys\\(poster.tools || {}\\).slice\\(0, 5\\)\\);\n\" 2>&1)",
204
204
  "Bash(node -e \"require\\('./src/core/agent-chat.js'\\); console.log\\('OK'\\)\" 2>&1)",
205
- "Bash(node -e \"const ai = require\\('ai'\\); console.log\\('tool type:', typeof ai.tool\\)\")"
205
+ "Bash(node -e \"const ai = require\\('ai'\\); console.log\\('tool type:', typeof ai.tool\\)\")",
206
+ "Bash(cd D:/Code/foliko && node examples/test-think-continuous.js 2>&1)",
207
+ "Bash(cd D:/Code/foliko && node -e \"\nrequire\\('dotenv'\\).config\\(\\);\nconst { createAI } = require\\('./src/core/provider'\\);\nconst { generateText } = require\\('ai'\\);\nconst { createModel } = require\\('./src/core/provider'\\);\nconst ai = createAI\\({\n provider: 'minimax',\n model: 'MiniMax-M2.7',\n apiKey: process.env.FOLIKO_API_KEY,\n baseURL: 'https://api.minimaxi.com/v1',\n}\\);\nconst model = createModel\\('MiniMax-M2.7', ai\\);\ngenerateText\\({ model, prompt: 'Hello' }\\).then\\(r => console.log\\('OK:', r.text.substring\\(0, 50\\)\\)\\).catch\\(e => console.error\\('ERROR:', e.message\\)\\);\n\" 2>&1)",
208
+ "Bash(node examples/test-think-continuous.js 2>&1)"
206
209
  ]
207
210
  }
208
211
  }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * 测试 think-plugin 持续思考的上下文感知
3
+ * 验证每轮思考是否正确传递上下文
4
+ */
5
+
6
+ require('dotenv').config();
7
+ const { Framework } = require('../src');
8
+
9
+ async function main() {
10
+ const framework = new Framework({ debug: false });
11
+
12
+ await framework.bootstrap({
13
+ agentDir: process.cwd() + '/.agent',
14
+ aiConfig: {
15
+ provider: process.env.FOLIKO_PROVIDER || 'minimax',
16
+ model: process.env.FOLIKO_MODEL || 'MiniMax-M2.7',
17
+ baseURL: process.env.FOLIKO_BASE_URL || 'https://api.minimaxi.com/v1',
18
+ apiKey: process.env.FOLIKO_API_KEY,
19
+ },
20
+ });
21
+
22
+ const agent = framework.createAgent({
23
+ name: 'TestAgent',
24
+ systemPrompt: '你是一个有帮助的助手。',
25
+ });
26
+
27
+ // 找到 think 插件
28
+ const thinkPlugin = framework.pluginManager.get('think');
29
+ if (!thinkPlugin) {
30
+ console.error('think plugin not found');
31
+ await framework.destroy();
32
+ return;
33
+ }
34
+
35
+ console.log('=== 测试 1: 持续思考上下文感知 ===\n');
36
+
37
+ // 启动持续思考(3轮,每轮2秒)
38
+ console.log('启动持续思考 maxRounds=3 interval=2000ms...');
39
+ const result = await thinkPlugin.tools.think_continue.execute({
40
+ interval: 2000,
41
+ topic: '分析数字 42 的数学意义',
42
+ maxRounds: 5,
43
+ });
44
+
45
+ console.log('启动结果:', JSON.stringify(result, null, 2));
46
+
47
+ // 等待思考完成(3轮 + 总结时间)
48
+ console.log('\n等待思考完成...');
49
+ await new Promise((r) => setTimeout(r, 20000));
50
+
51
+ // 检查插件内部状态
52
+ console.log('\n=== 插件内部状态 ===');
53
+ console.log('_continuousMode:', thinkPlugin._continuousMode);
54
+ console.log('_continuousRounds:', thinkPlugin._continuousRounds);
55
+ console.log('_continuousMessages length:', thinkPlugin._continuousMessages.length);
56
+ console.log('_continuousTopic:', thinkPlugin._continuousTopic);
57
+
58
+ // 检查会话历史
59
+ const sessionPlugin = framework.pluginManager.get('session');
60
+ if (sessionPlugin) {
61
+ const defaultSession = sessionPlugin.getSession('default');
62
+ if (defaultSession) {
63
+ console.log('\n=== 主会话历史 ===');
64
+ console.log('消息数量:', defaultSession.messages.length);
65
+ defaultSession.messages.forEach((msg, i) => {
66
+ const preview = typeof msg.content === 'string'
67
+ ? msg.content.substring(0, 100) + (msg.content.length > 100 ? '...' : '')
68
+ : JSON.stringify(msg.content).substring(0, 100);
69
+ console.log(`[${i}] ${msg.role}: ${preview}`);
70
+ });
71
+ }
72
+ }
73
+
74
+ // 检查思考记录
75
+ console.log('\n=== 思考记录 ===');
76
+ console.log('总思考次数:', thinkPlugin._thoughts.length);
77
+ thinkPlugin._thoughts.slice(-3).forEach((t, i) => {
78
+ const resultPreview = t.result ? t.result.substring(0, 100) : '(empty)';
79
+ console.log(`思考 ${i + 1}: [${t.mode}] ${t.topic}`);
80
+ console.log(` 结果: ${resultPreview}...`);
81
+ console.log(` messages字段: ${t.messages ? t.messages.length + '条' : '无'}`);
82
+ });
83
+
84
+ console.log('\n=== 测试完成 ===');
85
+ await framework.destroy();
86
+ }
87
+
88
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "1.1.27",
3
+ "version": "1.1.28",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -31,6 +31,10 @@ class ThinkPlugin extends Plugin {
31
31
  this._continuousTimer = null
32
32
  this._continuousTopic = null
33
33
  this._continuousMessages = [] // 持续思考的上下文消息
34
+ this._continuousRounds = 0 // 持续思考轮次计数
35
+ this._lastThinkResultHash = null // 上次思考结果 hash(用于检测重复)
36
+ this._consecutiveSimilarRounds = 0 // 连续相似轮次计数
37
+ this._maxContinuousRounds = 10 // 默认最大轮次
34
38
  this._pendingReflection = null
35
39
  }
36
40
 
@@ -98,6 +102,9 @@ class ThinkPlugin extends Plugin {
98
102
  * 创建思考用的 Subagent
99
103
  */
100
104
  _createThinkSubagent() {
105
+ const aiPlugin = this._framework.pluginManager?.get('ai');
106
+ const aiConfig = aiPlugin ? aiPlugin.getConfig() : {};
107
+ log.info(`[Think] createSubAgent AI config: provider=${aiConfig.provider}, model=${aiConfig.model}, hasKey=${!!aiConfig.apiKey}`);
101
108
  return this._framework.createSubAgent({
102
109
  name: 'think',
103
110
  role: '思考助手',
@@ -149,12 +156,14 @@ class ThinkPlugin extends Plugin {
149
156
 
150
157
  // 优先使用外部传入的 agent,否则使用缓存的 think agent
151
158
  const thinkAgent = externalAgent || this._thinkAgent || (this._thinkAgent = this._createThinkSubagent())
159
+ log.info(`[Think] thinkAgent apiKey: ${thinkAgent.apiKey ? thinkAgent.apiKey.substring(0,8) + '...' : 'null'}, provider: ${thinkAgent.provider}, model: ${thinkAgent.model}`)
152
160
 
153
161
  let result
154
162
  if (contextMessages && contextMessages.length > 0) {
155
163
  // 持续对话模式:传入上下文消息
156
164
  const messages = [...contextMessages, { role: 'user', content: reflectPrompt }]
157
- result = await thinkAgent.chatWithMessages(messages)
165
+ log.info(`[Think] round with context: contextLen=${contextMessages.length}, totalMsgs=${messages.length}`);
166
+ result = await thinkAgent.chat(messages)
158
167
  } else {
159
168
  // 普通模式:新对话
160
169
  result = await thinkAgent.chat(reflectPrompt)
@@ -170,6 +179,7 @@ class ThinkPlugin extends Plugin {
170
179
  timestamp: new Date()
171
180
  }
172
181
 
182
+ log.info(`[Think] result.messages length: ${result.messages ? result.messages.length : 'undefined/null'}, success: ${result.success}, msgLen: ${(result.message || '').length}`);
173
183
  this._thoughts.push(thought)
174
184
  if (this._thoughts.length > 100) {
175
185
  this._thoughts = this._thoughts.slice(-100)
@@ -196,7 +206,8 @@ class ThinkPlugin extends Plugin {
196
206
  return {
197
207
  success: true,
198
208
  thought,
199
- message: `【主动思考完成】\n模式: ${mode}\n主题: ${topic}\n\n${result.message || result.error || ''}`
209
+ message: `【主动思考完成】\n模式: ${mode}\n主题: ${topic}\n\n${result.message || result.error || ''}`,
210
+ messages: result.messages // 累积的消息历史,用于持续对话上下文
200
211
  }
201
212
  } catch (err) {
202
213
  this._emitNotification('error', '🧠 思考失败', err.message.slice(0, 100))
@@ -231,16 +242,15 @@ class ThinkPlugin extends Plugin {
231
242
  }
232
243
 
233
244
  const modePrompts = {
234
- reflect: `你刚刚完成了一次对话。请${depthDesc[depth]}:
245
+ reflect: `请${depthDesc[depth]}:
235
246
 
236
- 1. 检查回答是否完整、准确
237
- 2. 是否有遗漏的重要信息
238
- 3. 是否有更好的表达方式
239
- 4. 是否需要补充示例或细节
247
+ 1. 基于之前的思考,检查是否有真正新的论点、分析角度或补充
248
+ 2. 如果发现遗漏或更好的思路,请输出
249
+ 3. 如果认为之前的思考已经完整、没有新内容可补充,请输出【无新增论点,思考已充分】并结束
240
250
 
241
251
  ${topic ? `额外关注: ${topic}` : ''}
242
252
 
243
- 请直接输出你的反思结果,不需要重复之前的对话内容。`,
253
+ 请直接输出你的反思结果,不需要重复之前的对话内容。如果确认没有新论点,必须明确输出【无新增论点,思考已充分】。`,
244
254
 
245
255
  brainstorm: `请进行头脑风暴,针对以下主题产生更多想法:
246
256
 
@@ -326,10 +336,16 @@ ${topic || '接下来的行动'}
326
336
 
327
337
  const interval = args.interval || 30000
328
338
  const topic = args.topic || '基于最近的对话,还有什么值得深入思考的方向?'
339
+ const maxRounds = args.maxRounds || 10 // 默认最多10轮
329
340
 
330
341
  this._continuousMode = true
331
342
  this._continuousTopic = topic
332
343
  this._continuousMessages = [] // 初始化上下文消息
344
+ this._continuousRounds = 0 // 当前轮次计数
345
+ this._lastThinkResultHash = null // 上次思考结果的 hash,用于检测重复
346
+ this._consecutiveSimilarRounds = 0 // 连续相似轮次计数
347
+ this._maxContinuousRounds = maxRounds
348
+ // 注意:不再需要捕获 sessionId,因为总结不加到会话
333
349
 
334
350
  const runThink = async () => {
335
351
  if (!this._continuousMode) return
@@ -342,6 +358,8 @@ ${topic || '接下来的行动'}
342
358
  messages: this._continuousMessages
343
359
  })
344
360
 
361
+ this._continuousRounds++
362
+
345
363
  // 更新上下文消息(用于下次思考)
346
364
  if (result.messages) {
347
365
  this._continuousMessages = result.messages
@@ -351,6 +369,31 @@ ${topic || '接下来的行动'}
351
369
  }
352
370
  }
353
371
 
372
+ // 自然停止检测:结果相似度判断 + LLM 主动确认无新论点(第一轮不触发判断)
373
+ const currentResult = (result.thought?.result || '').trim()
374
+ // 第一轮不判断无新论点(还没有内容可供对比),后续轮次才判断
375
+ const noNewPoints = this._continuousRounds > 1 && currentResult.includes('【无新增论点,思考已充分】')
376
+ const currentHash = this._hashString(currentResult)
377
+ if (this._lastThinkResultHash !== null && currentHash === this._lastThinkResultHash) {
378
+ this._consecutiveSimilarRounds++
379
+ } else {
380
+ this._consecutiveSimilarRounds = 0
381
+ }
382
+ this._lastThinkResultHash = currentHash
383
+
384
+ // 满足自然停止条件:LLM 主动确认无新论点 或 连续3轮相似 或 达到最大轮次
385
+ const shouldStopNaturally =
386
+ noNewPoints ||
387
+ this._consecutiveSimilarRounds >= 3 ||
388
+ this._continuousRounds >= this._maxContinuousRounds
389
+
390
+ if (shouldStopNaturally) {
391
+ this._continuousMode = false
392
+ this._continuousMessages = []
393
+ this._emitNotification('info', '🧠 持续思考自然停止', `共思考 ${this._continuousRounds} 轮`)
394
+ return
395
+ }
396
+
354
397
  // 触发下一轮
355
398
  if (this._continuousMode) {
356
399
  this._continuousTimer = setTimeout(runThink, interval)
@@ -376,13 +419,18 @@ ${topic || '接下来的行动'}
376
419
  * 停止持续思考模式
377
420
  */
378
421
  _stopContinuousThinking() {
422
+ const rounds = this._continuousRounds
379
423
  this._continuousMode = false
380
424
  if (this._continuousTimer) {
381
425
  clearTimeout(this._continuousTimer)
382
426
  this._continuousTimer = null
383
427
  }
384
428
  this._continuousMessages = [] // 清空上下文
385
- this._emitNotification('info', 'ℹ️ 持续思考已停止', '')
429
+ this._continuousTopic = null
430
+ this._continuousRounds = 0
431
+ this._lastThinkResultHash = null
432
+ this._consecutiveSimilarRounds = 0
433
+ this._emitNotification('info', 'ℹ️ 持续思考已停止', `共思考 ${rounds} 轮`)
386
434
  return {
387
435
  success: true,
388
436
  message: '持续思考已停止'
@@ -417,6 +465,22 @@ ${topic || '接下来的行动'}
417
465
  return this._thoughts.slice(-10).reverse()
418
466
  }
419
467
 
468
+ /**
469
+ * 字符串 hash(用于判断思考结果是否重复)
470
+ */
471
+ _hashString(str) {
472
+ if (!str || str.length === 0) return ''
473
+ // 简化为取前64字符的 hashcode
474
+ let hash = 0
475
+ const s = str.substring(0, 64)
476
+ for (let i = 0; i < s.length; i++) {
477
+ const ch = s.charCodeAt(i)
478
+ hash = ((hash << 5) - hash) + ch
479
+ hash = hash & hash
480
+ }
481
+ return hash.toString(36)
482
+ }
483
+
420
484
  reload(framework) {
421
485
  this._framework = framework
422
486
  }
@@ -133,6 +133,11 @@ class WebPlugin extends Plugin {
133
133
 
134
134
  log.info(` 加载 Web 配置...`)
135
135
 
136
+ // 恢复前先清空,避免 install -> reload 重复加载导致数据翻倍
137
+ this._routes = []
138
+ this._webhooks = new Map()
139
+ this._statics = []
140
+
136
141
  let hasRoutes = false
137
142
  let hasWebhooks = false
138
143
  let hasStatics = false