@bolloon/bolloon-agent 0.2.12 → 0.2.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.
Files changed (284) hide show
  1. package/README.md +495 -467
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon-daemon.sh +207 -0
  4. package/bin/bolloon.cjs +0 -0
  5. package/bin/ipfs +0 -0
  6. package/dist/agents/agent-manifest-protocol.js +52 -0
  7. package/dist/agents/chat-segmenter.js +298 -0
  8. package/dist/agents/constraint-layer.js +19 -19
  9. package/dist/agents/judgment-protocol.js +479 -0
  10. package/dist/agents/parse-tool-call.js +304 -0
  11. package/dist/agents/peer-manifest-loader.js +210 -0
  12. package/dist/agents/pi-sdk-session-factory.js +110 -0
  13. package/dist/agents/pi-sdk-session-manager.js +297 -0
  14. package/dist/agents/pi-sdk-tools.js +1288 -0
  15. package/dist/agents/pi-sdk-types.js +13 -0
  16. package/dist/agents/pi-sdk.js +553 -1306
  17. package/dist/agents/react-loop.js +120 -0
  18. package/dist/agents/session-store.js +171 -0
  19. package/dist/agents/shell-guard.js +2 -2
  20. package/dist/agents/tool-registry.js +136 -0
  21. package/dist/agents/workflow-pivot-loop.js +200 -22
  22. package/dist/bollharness/src/scripts/context_router.js +7 -0
  23. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  24. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  25. package/dist/bollharness-integration/context-router.js +292 -292
  26. package/dist/bollharness-integration/gate-state-machine.js +26 -13
  27. package/dist/bollharness-integration/integration.js +71 -0
  28. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  29. package/dist/bollharness-integration/skill-adapter.js +57 -127
  30. package/dist/bootstrap/chat-archiver.js +276 -0
  31. package/dist/bootstrap/context-collector.js +6 -3
  32. package/dist/bootstrap/event-log.js +160 -0
  33. package/dist/bootstrap/lifecycle-hooks.js +15 -1
  34. package/dist/bootstrap/memory-compressor.js +170 -0
  35. package/dist/bootstrap/persona-loader.js +94 -0
  36. package/dist/bootstrap/project-state.js +159 -0
  37. package/dist/bootstrap/remote-mirror.js +97 -0
  38. package/dist/bootstrap/session-window.js +121 -0
  39. package/dist/bootstrap/vector-index.js +248 -0
  40. package/dist/cli/loading-tui.js +40 -0
  41. package/dist/cli-entry.js +41 -37
  42. package/dist/context-compaction/auto-compact.js +7 -7
  43. package/dist/electron/config.js +21 -0
  44. package/dist/electron/config.js.map +1 -0
  45. package/dist/electron/dialogs.js +108 -0
  46. package/dist/electron/dialogs.js.map +1 -0
  47. package/dist/electron/first-run.js +170 -0
  48. package/dist/electron/first-run.js.map +1 -0
  49. package/dist/electron/ipc.js +20 -0
  50. package/dist/electron/ipc.js.map +1 -0
  51. package/dist/electron/logger.js +114 -0
  52. package/dist/electron/logger.js.map +1 -0
  53. package/dist/electron/main.js +63 -0
  54. package/dist/electron/main.js.map +1 -0
  55. package/dist/electron/menu.js +145 -0
  56. package/dist/electron/menu.js.map +1 -0
  57. package/dist/electron/paths.js +75 -0
  58. package/dist/electron/paths.js.map +1 -0
  59. package/dist/electron/server.js +119 -0
  60. package/dist/electron/server.js.map +1 -0
  61. package/dist/electron/tray.js +111 -0
  62. package/dist/electron/tray.js.map +1 -0
  63. package/dist/electron/window.js +111 -0
  64. package/dist/electron/window.js.map +1 -0
  65. package/dist/electron-preload.js +26 -6
  66. package/dist/electron-preload.js.map +1 -1
  67. package/dist/electron.js +6 -168
  68. package/dist/electron.js.map +1 -1
  69. package/dist/index.js +323 -266
  70. package/dist/llm/config-store.js +24 -8
  71. package/dist/llm/llm-judgment-client.js +102 -102
  72. package/dist/llm/pi-ai.js +137 -85
  73. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  74. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  75. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  76. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  77. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  78. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  79. package/dist/llm/system-prompt/layers/core/identity.md +37 -37
  80. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  81. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  82. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  83. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  84. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  85. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  86. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  87. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  88. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  89. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  90. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  91. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  92. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  93. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  94. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  95. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  96. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  97. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  98. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  99. package/dist/llm/tool-manifest/bash.js +3 -3
  100. package/dist/llm/tool-manifest/create_file.js +4 -4
  101. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  102. package/dist/llm/tool-manifest/image_search.js +2 -2
  103. package/dist/llm/tool-manifest/mcp.js +2 -2
  104. package/dist/llm/tool-manifest/message_compose.js +3 -3
  105. package/dist/llm/tool-manifest/places.js +2 -2
  106. package/dist/llm/tool-manifest/present_files.js +1 -1
  107. package/dist/llm/tool-manifest/recipe.js +2 -2
  108. package/dist/llm/tool-manifest/str_replace.js +5 -5
  109. package/dist/llm/tool-manifest/view.js +3 -3
  110. package/dist/llm/tool-manifest/weather.js +4 -4
  111. package/dist/llm/tool-manifest/web.js +4 -4
  112. package/dist/network/local-inbox-bus.js +73 -0
  113. package/dist/network/p2p-outbox.js +161 -0
  114. package/dist/network/peer-fs.js +420 -0
  115. package/dist/network/peer-resource-bridge.js +216 -0
  116. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  117. package/dist/pi-ecosystem-judgment/cleanup.js +126 -0
  118. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  119. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  120. package/dist/pi-ecosystem-judgment/human-value-store.js +45 -11
  121. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  122. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  123. package/dist/security/context-router-tool.js +15 -15
  124. package/dist/security/tool-gate.js +11 -0
  125. package/dist/web/api-config.html +520 -520
  126. package/dist/web/client-loop-status.js +220 -0
  127. package/dist/web/client.js +22 -5
  128. package/dist/web/client.js.map +7 -0
  129. package/dist/web/components/wallet-viem.mjs +118 -118
  130. package/dist/web/index.html +375 -375
  131. package/dist/web/input-validator.js +103 -0
  132. package/dist/web/manifest.json +20 -20
  133. package/dist/web/routes-judgments.js +738 -0
  134. package/dist/web/routes-llm-config.js +279 -0
  135. package/dist/web/routes-tasks.js +222 -0
  136. package/dist/web/server-sse.js +121 -0
  137. package/dist/web/server-storage.js +154 -0
  138. package/dist/web/server-types.js +15 -0
  139. package/dist/web/server-v3-p2p.js +224 -0
  140. package/dist/web/server.js +1070 -1307
  141. package/dist/web/style.css +4742 -4742
  142. package/dist/web/util/safe-name.js +32 -0
  143. package/package.json +162 -160
  144. package/scripts/build-cli.js +215 -215
  145. package/scripts/build-web.ts +130 -130
  146. package/scripts/postinstall.js +152 -152
  147. package/bin/bolloon.js +0 -157
  148. package/dist/constraint-runtime/src/_archive_helper.js +0 -9
  149. package/dist/constraint-runtime/src/agent/coordinator.js +0 -48
  150. package/dist/constraint-runtime/src/agent/index.js +0 -1
  151. package/dist/constraint-runtime/src/assistant/index.js +0 -12
  152. package/dist/constraint-runtime/src/bootstrap/index.js +0 -12
  153. package/dist/constraint-runtime/src/bootstrap_graph.js +0 -13
  154. package/dist/constraint-runtime/src/bridge/index.js +0 -12
  155. package/dist/constraint-runtime/src/buddy/index.js +0 -12
  156. package/dist/constraint-runtime/src/cli/index.js +0 -12
  157. package/dist/constraint-runtime/src/command_graph.js +0 -10
  158. package/dist/constraint-runtime/src/commands.js +0 -60
  159. package/dist/constraint-runtime/src/components/index.js +0 -12
  160. package/dist/constraint-runtime/src/constants/index.js +0 -12
  161. package/dist/constraint-runtime/src/constraint/budget.js +0 -22
  162. package/dist/constraint-runtime/src/constraint/index.js +0 -2
  163. package/dist/constraint-runtime/src/constraint/permission.js +0 -20
  164. package/dist/constraint-runtime/src/context.js +0 -30
  165. package/dist/constraint-runtime/src/coordinator/index.js +0 -12
  166. package/dist/constraint-runtime/src/cost_hook.js +0 -4
  167. package/dist/constraint-runtime/src/cost_tracker.js +0 -8
  168. package/dist/constraint-runtime/src/deferred_init.js +0 -10
  169. package/dist/constraint-runtime/src/direct_modes.js +0 -6
  170. package/dist/constraint-runtime/src/dynamic-tool-loader.js +0 -85
  171. package/dist/constraint-runtime/src/entrypoints/index.js +0 -12
  172. package/dist/constraint-runtime/src/execution_registry.js +0 -44
  173. package/dist/constraint-runtime/src/history.js +0 -9
  174. package/dist/constraint-runtime/src/hooks/index.js +0 -12
  175. package/dist/constraint-runtime/src/index.js +0 -26
  176. package/dist/constraint-runtime/src/ink.js +0 -4
  177. package/dist/constraint-runtime/src/keybindings/index.js +0 -12
  178. package/dist/constraint-runtime/src/memdir/index.js +0 -12
  179. package/dist/constraint-runtime/src/migrations/index.js +0 -12
  180. package/dist/constraint-runtime/src/models.js +0 -1
  181. package/dist/constraint-runtime/src/moreright/index.js +0 -12
  182. package/dist/constraint-runtime/src/native_ts/index.js +0 -12
  183. package/dist/constraint-runtime/src/output_styles/index.js +0 -12
  184. package/dist/constraint-runtime/src/parity_audit.js +0 -12
  185. package/dist/constraint-runtime/src/plugins/index.js +0 -12
  186. package/dist/constraint-runtime/src/port_manifest.js +0 -11
  187. package/dist/constraint-runtime/src/prefetch.js +0 -9
  188. package/dist/constraint-runtime/src/query.js +0 -1
  189. package/dist/constraint-runtime/src/remote/index.js +0 -12
  190. package/dist/constraint-runtime/src/remote_runtime.js +0 -9
  191. package/dist/constraint-runtime/src/runtime/index.js +0 -1
  192. package/dist/constraint-runtime/src/runtime/session.js +0 -35
  193. package/dist/constraint-runtime/src/schemas/index.js +0 -12
  194. package/dist/constraint-runtime/src/screens/index.js +0 -12
  195. package/dist/constraint-runtime/src/server/index.js +0 -12
  196. package/dist/constraint-runtime/src/services/index.js +0 -12
  197. package/dist/constraint-runtime/src/session_store.js +0 -22
  198. package/dist/constraint-runtime/src/setup.js +0 -30
  199. package/dist/constraint-runtime/src/skills/index.js +0 -1
  200. package/dist/constraint-runtime/src/skills/skill-registry.js +0 -28
  201. package/dist/constraint-runtime/src/state/index.js +0 -12
  202. package/dist/constraint-runtime/src/system_init.js +0 -20
  203. package/dist/constraint-runtime/src/thinking/engine.js +0 -42
  204. package/dist/constraint-runtime/src/thinking/index.js +0 -1
  205. package/dist/constraint-runtime/src/tool_pool.js +0 -8
  206. package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +0 -7
  207. package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +0 -7
  208. package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +0 -7
  209. package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +0 -6
  210. package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +0 -8
  211. package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +0 -6
  212. package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +0 -6
  213. package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +0 -6
  214. package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +0 -6
  215. package/dist/constraint-runtime/src/tools.js +0 -80
  216. package/dist/constraint-runtime/src/transcript.js +0 -19
  217. package/dist/constraint-runtime/src/types/index.js +0 -12
  218. package/dist/constraint-runtime/src/upstream_proxy/index.js +0 -12
  219. package/dist/constraint-runtime/src/utils/index.js +0 -12
  220. package/dist/constraint-runtime/src/vim/index.js +0 -12
  221. package/dist/constraint-runtime/src/voice/index.js +0 -12
  222. package/dist/constraint-runtime/tests/agent.test.js +0 -16
  223. package/dist/constraint-runtime/tests/constraint.test.js +0 -41
  224. package/dist/constraint-runtime/tests/skill.test.js +0 -19
  225. package/dist/constraint-runtime/tests/thinking.test.js +0 -22
  226. package/dist/pi-ecosystem-colony/index.js +0 -365
  227. package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
  228. package/dist/social/ant-colony/PheromoneEngine.js +0 -227
  229. package/dist/social/ant-colony/index.js +0 -6
  230. package/dist/social/ant-colony/types.js +0 -24
  231. package/dist/test/ai-judgment-test.js +0 -80
  232. package/dist/test/bollharness-integration.test.js +0 -318
  233. package/dist/test/channel-agent-multi-dialogue.js +0 -205
  234. package/dist/test/channel-heartbeat-agent-test.js +0 -201
  235. package/dist/test/constraint-layer.test.js +0 -164
  236. package/dist/test/diap-identity-test.js +0 -172
  237. package/dist/test/diap-quick-test.js +0 -62
  238. package/dist/test/global-shared-context.test.js +0 -315
  239. package/dist/test/harness-judgment-injection.test.js +0 -246
  240. package/dist/test/harness-workflow-integrator-test.js +0 -228
  241. package/dist/test/human-value-store.test.js +0 -243
  242. package/dist/test/hybrid-integration-test.js +0 -118
  243. package/dist/test/hybrid-messenger-verify.js +0 -55
  244. package/dist/test/iroh-bistream-debug.js +0 -38
  245. package/dist/test/iroh-communication.test.js +0 -66
  246. package/dist/test/iroh-debug-test.js +0 -57
  247. package/dist/test/iroh-diap-test.js +0 -71
  248. package/dist/test/iroh-direct-connect.js +0 -55
  249. package/dist/test/iroh-e2e-fixed.js +0 -89
  250. package/dist/test/iroh-e2e-same-process.js +0 -63
  251. package/dist/test/iroh-e2e.js +0 -66
  252. package/dist/test/iroh-final-e2e.js +0 -72
  253. package/dist/test/iroh-relay-test.js +0 -37
  254. package/dist/test/iroh-simple-test.js +0 -41
  255. package/dist/test/iroh-transport-verify.js +0 -54
  256. package/dist/test/iroh-transport.test.js +0 -37
  257. package/dist/test/iroh-two-nodes.js +0 -70
  258. package/dist/test/iroh-verify.js +0 -44
  259. package/dist/test/judgment-decision.test.js +0 -219
  260. package/dist/test/llm-judgment-integration.test.js +0 -220
  261. package/dist/test/p2p-agent-complex-dialogue.js +0 -385
  262. package/dist/test/p2p-agent-dialogue.js +0 -341
  263. package/dist/test/p2p-agent-full-bidirectional.js +0 -510
  264. package/dist/test/p2p-agent-harness-flow.js +0 -437
  265. package/dist/test/p2p-agent-harness-single.js +0 -143
  266. package/dist/test/p2p-ai-dialogue-test.js +0 -318
  267. package/dist/test/p2p-cid-connect-test.js +0 -195
  268. package/dist/test/p2p-connect-receiver.js +0 -69
  269. package/dist/test/p2p-doc-transfer.js +0 -110
  270. package/dist/test/p2p-identity-page-test.js +0 -77
  271. package/dist/test/p2p-iroh-test.js +0 -171
  272. package/dist/test/p2p-minimal-test.js +0 -241
  273. package/dist/test/p2p-node-1.js +0 -148
  274. package/dist/test/p2p-node-2.js +0 -148
  275. package/dist/test/p2p-server.js +0 -281
  276. package/dist/test/p2p-two-nodes-test.js +0 -438
  277. package/dist/test/pi-sdk.test.js +0 -44
  278. package/dist/test/set-persona.js +0 -40
  279. package/dist/test/simple.test.js +0 -9
  280. package/dist/test/storage-integration.test.js +0 -150
  281. package/dist/test/subagent-manager.test.js +0 -276
  282. package/dist/test/test-gate-flow.test.js +0 -81
  283. package/dist/test/workflow-engine.test.js +0 -87
  284. package/dist/test/workflow-pivot-loop.test.js +0 -246
package/dist/llm/pi-ai.js CHANGED
@@ -55,23 +55,32 @@ export class PiAIModel {
55
55
  /**
56
56
  * 与 LLM 对话.
57
57
  *
58
- * 支持两种调用形式:
58
+ * 支持三种调用形式:
59
59
  * - 旧: chat(message: string, context?: string, signal?)
60
60
  * 单一 user message + 附加 system context. 简单场景用.
61
61
  * - 新: chat(messages: ChatMessage[], context?: string, signal?)
62
62
  * 完整 messages 数组, 含 user/assistant/tool/system role.
63
63
  * 工具调用场景必用 — 否则 LLM 看不到工具结果.
64
+ * - pivot loop 兼容: chat(context: string, systemPrompt: string, signal?)
65
+ * 第二参超过 2K 时视为 system prompt 覆盖, 避免把 46K context 当 user message 发送.
64
66
  *
65
67
  * 2026-06-17 (M3.5 调试): buildContext() 之前把所有 history 序列化成单字符串,
66
68
  * LLM 看不到 tool 调用的真实结果,导致 CLI loop 卡死.
67
69
  * 现在 messages 数组版本保留 role 语义, LLM 能正确看到工具返回.
68
70
  */
69
- async chat(messageOrMessages, context, signal) {
70
- const systemPrompt = await this.buildSystemPromptAsync(context);
71
+ async chat(messageOrMessages, contextOrSystemPrompt, signal) {
72
+ const systemPrompt = await this.buildSystemPromptAsync(contextOrSystemPrompt);
71
73
  let messages;
72
74
  if (Array.isArray(messageOrMessages)) {
73
75
  messages = [{ role: 'system', content: systemPrompt }, ...messageOrMessages];
74
76
  }
77
+ else if (contextOrSystemPrompt && contextOrSystemPrompt.length > 2000) {
78
+ const baseSystem = await this.buildSystemPromptAsync(undefined);
79
+ messages = [
80
+ { role: 'system', content: baseSystem + '\n\n' + contextOrSystemPrompt },
81
+ { role: 'user', content: messageOrMessages }
82
+ ];
83
+ }
75
84
  else {
76
85
  messages = [
77
86
  { role: 'system', content: systemPrompt },
@@ -82,10 +91,10 @@ export class PiAIModel {
82
91
  const response = await this.generateText({
83
92
  messages,
84
93
  temperature: 0.8,
85
- maxTokens: 8192, // 2026-06-15: 提到 8192, 避免长回答 (含表格/代码块) 被截断
94
+ maxTokens: 16384, // 2026-06-17: 提到 16384 agent 注入 16K+ system prompt + 8K tool defs 时, 8K 撞上限返回空 content (见 memory: bolloon-llm-empty-large-prompt)
86
95
  signal,
87
96
  });
88
- return { reply: response };
97
+ return { reply: response.reply, toolCalls: response.toolCalls };
89
98
  }
90
99
  catch (error) {
91
100
  // abort 不当作错误, 透传一个 sentinel 让上层能识别
@@ -113,8 +122,8 @@ export class PiAIModel {
113
122
  ],
114
123
  temperature: 0.7
115
124
  });
116
- const qualityScore = this.estimateQuality(text, response);
117
- return { summary: response, qualityScore };
125
+ const qualityScore = this.estimateQuality(text, response.reply);
126
+ return { summary: response.reply, qualityScore };
118
127
  }
119
128
  catch (error) {
120
129
  console.error('PiAI summarize error:', error);
@@ -134,7 +143,7 @@ export class PiAIModel {
134
143
  ],
135
144
  temperature: 0.8
136
145
  });
137
- return response;
146
+ return response.reply;
138
147
  }
139
148
  catch (error) {
140
149
  console.error('PiAI improve error:', error);
@@ -182,6 +191,7 @@ export class PiAIModel {
182
191
  case 'kimi':
183
192
  case 'glm':
184
193
  case 'qwen':
194
+ case 'mimo':
185
195
  return this.callOpenAI(finalMessages, temperature, maxTokens, signal);
186
196
  case 'anthropic':
187
197
  return this.callAnthropic(finalMessages, temperature, maxTokens, signal);
@@ -212,6 +222,7 @@ export class PiAIModel {
212
222
  kimi: process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY || '',
213
223
  glm: process.env.GLM_API_KEY || process.env.ZHIPU_API_KEY || '',
214
224
  qwen: process.env.QWEN_API_KEY || process.env.DASHSCOPE_API_KEY || '',
225
+ mimo: process.env.MIMO_API_KEY || '',
215
226
  local: ''
216
227
  };
217
228
  return envVars[this.provider] || '';
@@ -232,22 +243,26 @@ export class PiAIModel {
232
243
  kimi: process.env.KIMI_BASE_URL || process.env.MOONSHOT_BASE_URL || 'https://api.moonshot.cn/v1',
233
244
  glm: process.env.GLM_BASE_URL || process.env.ZHIPU_BASE_URL || 'https://open.bigmodel.cn/api/paas/v4',
234
245
  qwen: process.env.QWEN_BASE_URL || process.env.DASHSCOPE_BASE_URL || 'https://dashscope.aliyuncs.com/compatible-mode/v1',
246
+ // 小米 MiMo: 走 OpenAI 兼容 API, 官方 endpoint
247
+ mimo: process.env.MIMO_BASE_URL || 'https://api.xiaomi.com/v1',
235
248
  local: 'http://localhost:11434'
236
249
  };
237
250
  return baseUrls[this.provider];
238
251
  }
239
252
  mapModel() {
240
253
  const modelMap = {
241
- openai: this.config.model || process.env.OPENAI_MODEL || 'gpt-4',
242
- anthropic: this.config.model || 'claude-3-5-sonnet-20241022',
254
+ openai: this.config.model || process.env.OPENAI_MODEL || 'gpt-4.1',
255
+ anthropic: this.config.model || 'claude-sonnet-4-5-20250929',
243
256
  ollama: this.config.model || 'llama3.2',
244
- openrouter: this.config.model || 'anthropic/claude-3.5-sonnet',
245
- gemini: this.config.model || 'gemini-2.0-flash',
257
+ openrouter: this.config.model || 'anthropic/claude-sonnet-4.5',
258
+ gemini: this.config.model || 'gemini-2.5-pro',
246
259
  minimax: this.config.model || process.env.MINIMAX_MODEL || 'MiniMax-M3',
247
260
  deepseek: this.config.model || process.env.DEEPSEEK_MODEL || 'deepseek-chat',
248
261
  kimi: this.config.model || process.env.KIMI_MODEL || process.env.MOONSHOT_MODEL || 'moonshot-v1-8k',
249
262
  glm: this.config.model || process.env.GLM_MODEL || process.env.ZHIPU_MODEL || 'glm-4-flash',
250
263
  qwen: this.config.model || process.env.QWEN_MODEL || process.env.DASHSCOPE_MODEL || 'qwen-plus',
264
+ // 小米 MiMo (openai 兼容) — env override 优先, 默认 mimo-v2.5-pro
265
+ mimo: this.config.model || process.env.MIMO_MODEL || 'mimo-v2.5-pro',
251
266
  local: this.config.model || 'llama3.2'
252
267
  };
253
268
  return modelMap[this.provider];
@@ -263,24 +278,57 @@ export class PiAIModel {
263
278
  temperature,
264
279
  max_tokens: maxTokens
265
280
  };
266
- const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
267
- method: 'POST',
268
- headers: {
269
- 'Content-Type': 'application/json',
270
- 'Authorization': `Bearer ${apiKey}`
271
- },
272
- body: JSON.stringify(requestBody),
273
- // 2026-06-15: signal 字段防御Node 22+ undici 强类型 AbortSignal, 非 AbortSignal 实例
274
- // (e.g. 误传的 { maxTokens: 1 } 对象) 会 throw "Expected signal to be AbortSignal".
275
- // 若不是 AbortSignal, 退到无 signal 调用, fetch 自然支持 timeout 由外层控制.
276
- // 2026-06-17: combinedSignal 把外部 signal 和 120s timeout 合并, 防止上游卡死
277
- signal: this.combinedSignal(signal),
278
- });
279
- if (!response.ok) {
280
- throw new Error(`OpenAI API error: ${response.status}`);
281
+ // 2026-06-19: 一次命中优化 收到空 content 时重试 2 次, 避免 minimax 上游网络抖动
282
+ // 经验: minimax 偶发返回 200 但 content="" (上游 retry 耗尽), 之前当作 sentinel
283
+ // 现在外层加 2 次重试 + 退避, 让 90%+ 的一次调用不出现错误
284
+ // 2026-06-19: 一次命中优化 — 收到空 content 时重试 2 次, 避免 minimax 上游网络抖动
285
+ // 经验: minimax 偶发返回 200 但 content="" (上游 retry 耗尽), 之前当作 sentinel
286
+ // 现在外层加 2 次重试 + 退避, 让 90%+ 的一次调用不出现错误
287
+ let lastFinishReason = '';
288
+ // 2026-07-06: 加分阶段 instrumentation让"9.8s 大头是哪段"可定位
289
+ const _t0 = Date.now();
290
+ for (let attempt = 0; attempt < 3; attempt++) {
291
+ const _tFetch = Date.now();
292
+ const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
293
+ method: 'POST',
294
+ headers: {
295
+ 'Content-Type': 'application/json',
296
+ 'Authorization': `Bearer ${apiKey}`
297
+ },
298
+ body: JSON.stringify(requestBody),
299
+ signal: this.combinedSignal(signal),
300
+ });
301
+ const _tResp = Date.now();
302
+ if (!response.ok) {
303
+ const errBody = await response.text().catch(() => '(no body)');
304
+ console.log(`[pi-ai DEBUG] OpenAI 错误 ${response.status}: ${errBody.slice(0, 500)}`);
305
+ console.log(`[pi-ai DEBUG] 请求体: model=${requestBody.model}, messages=${requestBody.messages?.length}, max_tokens=${requestBody.max_tokens}, baseUrl=${this.getBaseUrl()}`);
306
+ throw new Error(`OpenAI API error: ${response.status} ${errBody.slice(0, 300)}`);
307
+ }
308
+ const data = await response.json();
309
+ const _tParse = Date.now();
310
+ const choice = data.choices?.[0];
311
+ const content = choice?.message?.content || '';
312
+ const toolCalls = choice?.message?.tool_calls;
313
+ lastFinishReason = choice?.finish_reason || '';
314
+ if (content) {
315
+ if (lastFinishReason === 'length') {
316
+ console.warn(`[pi-ai] hit max_tokens ceiling (model=${this.mapModel()}, max_tokens=${maxTokens}) — caller should trim prompt or raise cap`);
317
+ }
318
+ // 2026-07-06: 日志打 fetch/network/parse 三段 + prompt 体积, 以后 LLM 调用慢直接看这里定位
319
+ const _tAfter = Date.now();
320
+ const promptBytes = JSON.stringify(messages).length;
321
+ console.log(`[pi-ai timing] total=${_tAfter - _t0}ms attempt=${attempt + 1} fetch=${_tResp - _tFetch}ms parse=${_tParse - _tResp}ms reply=${content.length}B model=${this.mapModel()} prompt=${promptBytes}B`);
322
+ return { reply: content, toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined };
323
+ }
324
+ // 空 content: 200 但 content="" → minimax 上游偶发, 退避后重试
325
+ console.warn(`[pi-ai] attempt ${attempt + 1}/3: 空 content (finish_reason=${lastFinishReason}), 退避 1.5s 重试`);
326
+ const _tSleep = Date.now();
327
+ await new Promise(resolve => setTimeout(resolve, 1500));
328
+ console.log(`[pi-ai timing] attempt=${attempt + 1} empty; backoff=${Date.now() - _tSleep}ms; total=${Date.now() - _t0}ms so far`);
281
329
  }
282
- const data = await response.json();
283
- return data.choices?.[0]?.message?.content || '';
330
+ console.warn(`[pi-ai] 3 次重试都返回空 content (finish_reason=${lastFinishReason})`);
331
+ return { reply: '' }; // 返回空让上层看到 [AI 服务调用失败]
284
332
  }
285
333
  async callAnthropic(messages, temperature, maxTokens, signal) {
286
334
  const apiKey = this.getApiKey();
@@ -310,7 +358,7 @@ export class PiAIModel {
310
358
  throw new Error(`Anthropic API error: ${response.status}`);
311
359
  }
312
360
  const data = await response.json();
313
- return data.content?.[0]?.text || '';
361
+ return { reply: data.content?.[0]?.text || '' };
314
362
  }
315
363
  async callOllama(messages, temperature, signal) {
316
364
  const response = await fetch(`${this.getBaseUrl()}/api/chat`, {
@@ -330,7 +378,7 @@ export class PiAIModel {
330
378
  throw new Error(`Ollama API error: ${response.status}`);
331
379
  }
332
380
  const data = await response.json();
333
- return data.message?.content || '';
381
+ return { reply: data.message?.content || '' };
334
382
  }
335
383
  async callOpenRouter(messages, temperature, maxTokens, signal) {
336
384
  const apiKey = this.getApiKey();
@@ -357,7 +405,7 @@ export class PiAIModel {
357
405
  throw new Error(`OpenRouter API error: ${response.status}`);
358
406
  }
359
407
  const data = await response.json();
360
- return data.choices?.[0]?.message?.content || '';
408
+ return { reply: data.choices?.[0]?.message?.content || '' };
361
409
  }
362
410
  async callGemini(messages, temperature, maxTokens, signal) {
363
411
  const apiKey = this.getApiKey();
@@ -390,7 +438,7 @@ export class PiAIModel {
390
438
  throw new Error(`Gemini API error: ${response.status}`);
391
439
  }
392
440
  const data = await response.json();
393
- return data.candidates?.[0]?.content?.parts?.[0]?.text || '';
441
+ return { reply: data.candidates?.[0]?.content?.parts?.[0]?.text || '' };
394
442
  }
395
443
  async callLocal(messages, temperature, signal) {
396
444
  return this.callOllama(messages, temperature, signal);
@@ -410,12 +458,12 @@ export class PiAIModel {
410
458
  // 降级: 旧硬编码 (layer registry 不可用时不挂)
411
459
  console.warn('[pi-ai] layer registry 不可用, 降级:', err.message?.slice(0, 100));
412
460
  const envDetails = this.getEnvironmentDetails();
413
- return `You are a friendly AI assistant in a P2P document collaboration network.
414
-
415
- ## User Working Directory
416
- ${context || process.cwd()}
417
-
418
- ## Environment
461
+ return `You are a friendly AI assistant in a P2P document collaboration network.
462
+
463
+ ## User Working Directory
464
+ ${context || process.cwd()}
465
+
466
+ ## Environment
419
467
  ${envDetails}`;
420
468
  }
421
469
  }
@@ -423,49 +471,49 @@ ${envDetails}`;
423
471
  // 保留但内部用 sync fallback; 后续可改成 async
424
472
  buildSystemPrompt(context) {
425
473
  const envDetails = this.getEnvironmentDetails();
426
- return `You are a friendly AI assistant in a P2P document collaboration network.
427
-
428
- ## User Working Directory
429
- ${context || process.cwd()}
430
-
431
- ## Environment
474
+ return `You are a friendly AI assistant in a P2P document collaboration network.
475
+
476
+ ## User Working Directory
477
+ ${context || process.cwd()}
478
+
479
+ ## Environment
432
480
  ${envDetails}`;
433
481
  }
434
482
  getEnvironmentDetails() {
435
- return `
436
- ## Available Workflows
437
- - read - Read documents
438
- - summarize - Summarize documents
439
- - improve - Improve documents
440
- - collaborate - Multi-agent collaboration
441
- - query - Query status
442
- - report - Generate reports
443
-
444
- ## System Capabilities
445
- - Document processing (Markdown, Text, PDF, DOCX)
446
- - Multi-agent collaboration (P2P network)
447
- - Workflow engine (constraint layer)
448
- - Quality assessment and auto-send
449
-
450
- ## Current Time
483
+ return `
484
+ ## Available Workflows
485
+ - read - Read documents
486
+ - summarize - Summarize documents
487
+ - improve - Improve documents
488
+ - collaborate - Multi-agent collaboration
489
+ - query - Query status
490
+ - report - Generate reports
491
+
492
+ ## System Capabilities
493
+ - Document processing (Markdown, Text, PDF, DOCX)
494
+ - Multi-agent collaboration (P2P network)
495
+ - Workflow engine (constraint layer)
496
+ - Quality assessment and auto-send
497
+
498
+ ## Current Time
451
499
  ${new Date().toISOString()}`;
452
500
  }
453
501
  buildSummarizePrompt(text, context) {
454
502
  const maxLength = 8000;
455
503
  const truncatedText = text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
456
- let prompt = `Please generate a concise and accurate summary for the following document:
457
-
458
- ${truncatedText}
459
-
460
- Please output in the following format:
461
- ## Summary
462
- [Write summary here]
463
-
464
- ## Quality Self-Assessment
504
+ let prompt = `Please generate a concise and accurate summary for the following document:
505
+
506
+ ${truncatedText}
507
+
508
+ Please output in the following format:
509
+ ## Summary
510
+ [Write summary here]
511
+
512
+ ## Quality Self-Assessment
465
513
  [Score 1-10, with reasoning]`;
466
514
  if (context) {
467
- prompt = `Context: ${context}
468
-
515
+ prompt = `Context: ${context}
516
+
469
517
  ${prompt}`;
470
518
  }
471
519
  return prompt;
@@ -473,17 +521,17 @@ ${prompt}`;
473
521
  buildImprovePrompt(content, requirements, context) {
474
522
  const maxLength = 8000;
475
523
  const truncatedContent = content.length > maxLength ? content.substring(0, maxLength) + '...' : content;
476
- let prompt = `Please improve the document according to the following requirements:
477
-
478
- Requirements: ${requirements}
479
-
480
- Original Document:
481
- ${truncatedContent}
482
-
524
+ let prompt = `Please improve the document according to the following requirements:
525
+
526
+ Requirements: ${requirements}
527
+
528
+ Original Document:
529
+ ${truncatedContent}
530
+
483
531
  Please output only the improved document without additional explanation.`;
484
532
  if (context) {
485
- prompt = `Context: ${context}
486
-
533
+ prompt = `Context: ${context}
534
+
487
535
  ${prompt}`;
488
536
  }
489
537
  return prompt;
@@ -538,20 +586,24 @@ function detectProvider() {
538
586
  return 'glm';
539
587
  if (process.env.QWEN_API_KEY || process.env.DASHSCOPE_API_KEY)
540
588
  return 'qwen';
589
+ if (process.env.MIMO_API_KEY)
590
+ return 'mimo';
541
591
  return 'openai';
542
592
  }
543
593
  function detectModel(provider) {
544
594
  const defaults = {
545
- openai: 'gpt-4',
546
- anthropic: 'claude-3-5-sonnet-20241022',
595
+ openai: 'gpt-4.1',
596
+ anthropic: 'claude-sonnet-4-5-20250929',
547
597
  ollama: 'llama3.2',
548
- openrouter: 'anthropic/claude-3.5-sonnet',
549
- gemini: 'gemini-2.0-flash',
598
+ openrouter: 'anthropic/claude-sonnet-4.5',
599
+ gemini: 'gemini-2.5-pro',
550
600
  minimax: 'MiniMax-M3',
551
601
  deepseek: 'deepseek-chat',
552
602
  kimi: 'moonshot-v1-8k',
553
603
  glm: 'glm-4-flash',
554
604
  qwen: 'qwen-plus',
605
+ // 小米 MiMo 默认走最新旗舰版 (v2.5-Pro); 2026-06 当前公开版
606
+ mimo: 'mimo-v2.5-pro',
555
607
  local: 'llama3.2'
556
608
  };
557
609
  return defaults[provider];
@@ -1,14 +1,14 @@
1
- ---
2
- added_at: 2026-06-15
3
- last_reviewed_at: 2026-06-15
4
- ttl_days: 180
5
- author: yuanjie
6
- ---
7
-
8
- <!-- channel.local@1.0.0 -->
9
- # 本地渠道 (默认, bolloon 跑在用户本机)
10
-
11
- 你跑在用户的本地设备上, 可直接读写用户文件系统. 信任度高.
12
-
13
- 允许: 读写文件、执行命令、调用所有工具.
14
- 边界: 仍遵守 core.refusal / core.wellbeing / 拒绝处理.
1
+ ---
2
+ added_at: 2026-06-15
3
+ last_reviewed_at: 2026-06-15
4
+ ttl_days: 180
5
+ author: yuanjie
6
+ ---
7
+
8
+ <!-- channel.local@1.0.0 -->
9
+ # 本地渠道 (默认, bolloon 跑在用户本机)
10
+
11
+ 你跑在用户的本地设备上, 可直接读写用户文件系统. 信任度高.
12
+
13
+ 允许: 读写文件、执行命令、调用所有工具.
14
+ 边界: 仍遵守 core.refusal / core.wellbeing / 拒绝处理.
@@ -1,18 +1,18 @@
1
- ---
2
- added_at: 2026-06-15
3
- last_reviewed_at: 2026-06-15
4
- ttl_days: 180
5
- author: yuanjie
6
- ---
7
-
8
- <!-- channel.p2p-agent@1.0.0 -->
9
- # P2P 远程智能体 (另一个 bolloon 经 P2P 路由)
10
-
11
- 你是远端 bolloon, 收到的是**另一个 bolloon 实例**的协作请求. 信任度高 (基于 P2P 节点身份验证, 不是基于人类).
12
-
13
- 允许: 读 / 写, 协作推理, 共享上下文.
14
-
15
- 边界:
16
- - 身份验证优先: 先确认对方节点 ID + 公钥签名
17
- - 共享上下文时避免把人类隐私数据 (judgment / persona) 外泄给未知节点
18
- - 协作冲突时回退到 snapshot 重新协商, 不强推修改
1
+ ---
2
+ added_at: 2026-06-15
3
+ last_reviewed_at: 2026-06-15
4
+ ttl_days: 180
5
+ author: yuanjie
6
+ ---
7
+
8
+ <!-- channel.p2p-agent@1.0.0 -->
9
+ # P2P 远程智能体 (另一个 bolloon 经 P2P 路由)
10
+
11
+ 你是远端 bolloon, 收到的是**另一个 bolloon 实例**的协作请求. 信任度高 (基于 P2P 节点身份验证, 不是基于人类).
12
+
13
+ 允许: 读 / 写, 协作推理, 共享上下文.
14
+
15
+ 边界:
16
+ - 身份验证优先: 先确认对方节点 ID + 公钥签名
17
+ - 共享上下文时避免把人类隐私数据 (judgment / persona) 外泄给未知节点
18
+ - 协作冲突时回退到 snapshot 重新协商, 不强推修改
@@ -1,19 +1,19 @@
1
- ---
2
- added_at: 2026-06-15
3
- last_reviewed_at: 2026-06-15
4
- ttl_days: 180
5
- author: yuanjie
6
- ---
7
-
8
- <!-- channel.p2p-visitor@1.0.0 -->
9
- # P2P 远程访客 (人类用户经 P2P 路由)
10
-
11
- 你是远端 bolloon, 通过 P2P 应答**远端人类用户**的请求. 信任度中.
12
-
13
- 允许: 读 / 写, 但**不能直接改远端用户的文件** — 只能回传建议/代码/回复.
14
-
15
- 边界:
16
- - 拒绝执行任何会修改访客文件系统的命令
17
- - 输出可被远端 P2P 节点审计/转发
18
- - 不假定访客身份已知, 拒绝协助身份冒用
19
- - 未经身份验证前, 不接收访客上传的"判决"作为高权重 (避免污染)
1
+ ---
2
+ added_at: 2026-06-15
3
+ last_reviewed_at: 2026-06-15
4
+ ttl_days: 180
5
+ author: yuanjie
6
+ ---
7
+
8
+ <!-- channel.p2p-visitor@1.0.0 -->
9
+ # P2P 远程访客 (人类用户经 P2P 路由)
10
+
11
+ 你是远端 bolloon, 通过 P2P 应答**远端人类用户**的请求. 信任度中.
12
+
13
+ 允许: 读 / 写, 但**不能直接改远端用户的文件** — 只能回传建议/代码/回复.
14
+
15
+ 边界:
16
+ - 拒绝执行任何会修改访客文件系统的命令
17
+ - 输出可被远端 P2P 节点审计/转发
18
+ - 不假定访客身份已知, 拒绝协助身份冒用
19
+ - 未经身份验证前, 不接收访客上传的"判决"作为高权重 (避免污染)