@bolloon/bolloon-agent 0.2.12 → 0.2.14

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 +29 -8
  71. package/dist/llm/llm-judgment-client.js +102 -102
  72. package/dist/llm/pi-ai.js +139 -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,28 @@ 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
+ // Pinned to 2.5-pro: the only `-pro` model that is GA per Google docs.
259
+ // The 3.x line ships as `-flash` only — there is no `gemini-3.x-pro`.
260
+ gemini: this.config.model || 'gemini-2.5-pro',
246
261
  minimax: this.config.model || process.env.MINIMAX_MODEL || 'MiniMax-M3',
247
262
  deepseek: this.config.model || process.env.DEEPSEEK_MODEL || 'deepseek-chat',
248
263
  kimi: this.config.model || process.env.KIMI_MODEL || process.env.MOONSHOT_MODEL || 'moonshot-v1-8k',
249
264
  glm: this.config.model || process.env.GLM_MODEL || process.env.ZHIPU_MODEL || 'glm-4-flash',
250
265
  qwen: this.config.model || process.env.QWEN_MODEL || process.env.DASHSCOPE_MODEL || 'qwen-plus',
266
+ // 小米 MiMo (openai 兼容) — env override 优先, 默认 mimo-v2.5-pro
267
+ mimo: this.config.model || process.env.MIMO_MODEL || 'mimo-v2.5-pro',
251
268
  local: this.config.model || 'llama3.2'
252
269
  };
253
270
  return modelMap[this.provider];
@@ -263,24 +280,57 @@ export class PiAIModel {
263
280
  temperature,
264
281
  max_tokens: maxTokens
265
282
  };
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}`);
283
+ // 2026-06-19: 一次命中优化 收到空 content 时重试 2 次, 避免 minimax 上游网络抖动
284
+ // 经验: minimax 偶发返回 200 但 content="" (上游 retry 耗尽), 之前当作 sentinel
285
+ // 现在外层加 2 次重试 + 退避, 让 90%+ 的一次调用不出现错误
286
+ // 2026-06-19: 一次命中优化 — 收到空 content 时重试 2 次, 避免 minimax 上游网络抖动
287
+ // 经验: minimax 偶发返回 200 但 content="" (上游 retry 耗尽), 之前当作 sentinel
288
+ // 现在外层加 2 次重试 + 退避, 让 90%+ 的一次调用不出现错误
289
+ let lastFinishReason = '';
290
+ // 2026-07-06: 加分阶段 instrumentation让"9.8s 大头是哪段"可定位
291
+ const _t0 = Date.now();
292
+ for (let attempt = 0; attempt < 3; attempt++) {
293
+ const _tFetch = Date.now();
294
+ const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
295
+ method: 'POST',
296
+ headers: {
297
+ 'Content-Type': 'application/json',
298
+ 'Authorization': `Bearer ${apiKey}`
299
+ },
300
+ body: JSON.stringify(requestBody),
301
+ signal: this.combinedSignal(signal),
302
+ });
303
+ const _tResp = Date.now();
304
+ if (!response.ok) {
305
+ const errBody = await response.text().catch(() => '(no body)');
306
+ console.log(`[pi-ai DEBUG] OpenAI 错误 ${response.status}: ${errBody.slice(0, 500)}`);
307
+ console.log(`[pi-ai DEBUG] 请求体: model=${requestBody.model}, messages=${requestBody.messages?.length}, max_tokens=${requestBody.max_tokens}, baseUrl=${this.getBaseUrl()}`);
308
+ throw new Error(`OpenAI API error: ${response.status} ${errBody.slice(0, 300)}`);
309
+ }
310
+ const data = await response.json();
311
+ const _tParse = Date.now();
312
+ const choice = data.choices?.[0];
313
+ const content = choice?.message?.content || '';
314
+ const toolCalls = choice?.message?.tool_calls;
315
+ lastFinishReason = choice?.finish_reason || '';
316
+ if (content) {
317
+ if (lastFinishReason === 'length') {
318
+ console.warn(`[pi-ai] hit max_tokens ceiling (model=${this.mapModel()}, max_tokens=${maxTokens}) — caller should trim prompt or raise cap`);
319
+ }
320
+ // 2026-07-06: 日志打 fetch/network/parse 三段 + prompt 体积, 以后 LLM 调用慢直接看这里定位
321
+ const _tAfter = Date.now();
322
+ const promptBytes = JSON.stringify(messages).length;
323
+ 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`);
324
+ return { reply: content, toolCalls: toolCalls && toolCalls.length > 0 ? toolCalls : undefined };
325
+ }
326
+ // 空 content: 200 但 content="" → minimax 上游偶发, 退避后重试
327
+ console.warn(`[pi-ai] attempt ${attempt + 1}/3: 空 content (finish_reason=${lastFinishReason}), 退避 1.5s 重试`);
328
+ const _tSleep = Date.now();
329
+ await new Promise(resolve => setTimeout(resolve, 1500));
330
+ console.log(`[pi-ai timing] attempt=${attempt + 1} empty; backoff=${Date.now() - _tSleep}ms; total=${Date.now() - _t0}ms so far`);
281
331
  }
282
- const data = await response.json();
283
- return data.choices?.[0]?.message?.content || '';
332
+ console.warn(`[pi-ai] 3 次重试都返回空 content (finish_reason=${lastFinishReason})`);
333
+ return { reply: '' }; // 返回空让上层看到 [AI 服务调用失败]
284
334
  }
285
335
  async callAnthropic(messages, temperature, maxTokens, signal) {
286
336
  const apiKey = this.getApiKey();
@@ -310,7 +360,7 @@ export class PiAIModel {
310
360
  throw new Error(`Anthropic API error: ${response.status}`);
311
361
  }
312
362
  const data = await response.json();
313
- return data.content?.[0]?.text || '';
363
+ return { reply: data.content?.[0]?.text || '' };
314
364
  }
315
365
  async callOllama(messages, temperature, signal) {
316
366
  const response = await fetch(`${this.getBaseUrl()}/api/chat`, {
@@ -330,7 +380,7 @@ export class PiAIModel {
330
380
  throw new Error(`Ollama API error: ${response.status}`);
331
381
  }
332
382
  const data = await response.json();
333
- return data.message?.content || '';
383
+ return { reply: data.message?.content || '' };
334
384
  }
335
385
  async callOpenRouter(messages, temperature, maxTokens, signal) {
336
386
  const apiKey = this.getApiKey();
@@ -357,7 +407,7 @@ export class PiAIModel {
357
407
  throw new Error(`OpenRouter API error: ${response.status}`);
358
408
  }
359
409
  const data = await response.json();
360
- return data.choices?.[0]?.message?.content || '';
410
+ return { reply: data.choices?.[0]?.message?.content || '' };
361
411
  }
362
412
  async callGemini(messages, temperature, maxTokens, signal) {
363
413
  const apiKey = this.getApiKey();
@@ -390,7 +440,7 @@ export class PiAIModel {
390
440
  throw new Error(`Gemini API error: ${response.status}`);
391
441
  }
392
442
  const data = await response.json();
393
- return data.candidates?.[0]?.content?.parts?.[0]?.text || '';
443
+ return { reply: data.candidates?.[0]?.content?.parts?.[0]?.text || '' };
394
444
  }
395
445
  async callLocal(messages, temperature, signal) {
396
446
  return this.callOllama(messages, temperature, signal);
@@ -410,12 +460,12 @@ export class PiAIModel {
410
460
  // 降级: 旧硬编码 (layer registry 不可用时不挂)
411
461
  console.warn('[pi-ai] layer registry 不可用, 降级:', err.message?.slice(0, 100));
412
462
  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
463
+ return `You are a friendly AI assistant in a P2P document collaboration network.
464
+
465
+ ## User Working Directory
466
+ ${context || process.cwd()}
467
+
468
+ ## Environment
419
469
  ${envDetails}`;
420
470
  }
421
471
  }
@@ -423,49 +473,49 @@ ${envDetails}`;
423
473
  // 保留但内部用 sync fallback; 后续可改成 async
424
474
  buildSystemPrompt(context) {
425
475
  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
476
+ return `You are a friendly AI assistant in a P2P document collaboration network.
477
+
478
+ ## User Working Directory
479
+ ${context || process.cwd()}
480
+
481
+ ## Environment
432
482
  ${envDetails}`;
433
483
  }
434
484
  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
485
+ return `
486
+ ## Available Workflows
487
+ - read - Read documents
488
+ - summarize - Summarize documents
489
+ - improve - Improve documents
490
+ - collaborate - Multi-agent collaboration
491
+ - query - Query status
492
+ - report - Generate reports
493
+
494
+ ## System Capabilities
495
+ - Document processing (Markdown, Text, PDF, DOCX)
496
+ - Multi-agent collaboration (P2P network)
497
+ - Workflow engine (constraint layer)
498
+ - Quality assessment and auto-send
499
+
500
+ ## Current Time
451
501
  ${new Date().toISOString()}`;
452
502
  }
453
503
  buildSummarizePrompt(text, context) {
454
504
  const maxLength = 8000;
455
505
  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
506
+ let prompt = `Please generate a concise and accurate summary for the following document:
507
+
508
+ ${truncatedText}
509
+
510
+ Please output in the following format:
511
+ ## Summary
512
+ [Write summary here]
513
+
514
+ ## Quality Self-Assessment
465
515
  [Score 1-10, with reasoning]`;
466
516
  if (context) {
467
- prompt = `Context: ${context}
468
-
517
+ prompt = `Context: ${context}
518
+
469
519
  ${prompt}`;
470
520
  }
471
521
  return prompt;
@@ -473,17 +523,17 @@ ${prompt}`;
473
523
  buildImprovePrompt(content, requirements, context) {
474
524
  const maxLength = 8000;
475
525
  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
-
526
+ let prompt = `Please improve the document according to the following requirements:
527
+
528
+ Requirements: ${requirements}
529
+
530
+ Original Document:
531
+ ${truncatedContent}
532
+
483
533
  Please output only the improved document without additional explanation.`;
484
534
  if (context) {
485
- prompt = `Context: ${context}
486
-
535
+ prompt = `Context: ${context}
536
+
487
537
  ${prompt}`;
488
538
  }
489
539
  return prompt;
@@ -538,20 +588,24 @@ function detectProvider() {
538
588
  return 'glm';
539
589
  if (process.env.QWEN_API_KEY || process.env.DASHSCOPE_API_KEY)
540
590
  return 'qwen';
591
+ if (process.env.MIMO_API_KEY)
592
+ return 'mimo';
541
593
  return 'openai';
542
594
  }
543
595
  function detectModel(provider) {
544
596
  const defaults = {
545
- openai: 'gpt-4',
546
- anthropic: 'claude-3-5-sonnet-20241022',
597
+ openai: 'gpt-4.1',
598
+ anthropic: 'claude-sonnet-4-5-20250929',
547
599
  ollama: 'llama3.2',
548
- openrouter: 'anthropic/claude-3.5-sonnet',
549
- gemini: 'gemini-2.0-flash',
600
+ openrouter: 'anthropic/claude-sonnet-4.5',
601
+ gemini: 'gemini-2.5-pro',
550
602
  minimax: 'MiniMax-M3',
551
603
  deepseek: 'deepseek-chat',
552
604
  kimi: 'moonshot-v1-8k',
553
605
  glm: 'glm-4-flash',
554
606
  qwen: 'qwen-plus',
607
+ // 小米 MiMo 默认走最新旗舰版 (v2.5-Pro); 2026-06 当前公开版
608
+ mimo: 'mimo-v2.5-pro',
555
609
  local: 'llama3.2'
556
610
  };
557
611
  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
+ - 未经身份验证前, 不接收访客上传的"判决"作为高权重 (避免污染)