@bolloon/bolloon-agent 0.3.52 → 0.4.2

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 (225) hide show
  1. package/README.md +135 -135
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon.cjs +0 -0
  4. package/bin/bolloon.js +157 -0
  5. package/dist/agents/constraint-layer.js +19 -19
  6. package/dist/agents/judgment-protocol.js +14 -14
  7. package/dist/agents/loop-review.js +21 -0
  8. package/dist/agents/pi-sdk-tools.js +86 -2
  9. package/dist/agents/pi-sdk-types.js +12 -12
  10. package/dist/agents/pi-sdk.js +90 -90
  11. package/dist/agents/shell-guard.js +22 -1
  12. package/dist/agents/skill-organizer.js +19 -19
  13. package/dist/agents/verify-recipe.js +84 -0
  14. package/dist/agents/workflow-pivot-loop.js +101 -13
  15. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  16. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  17. package/dist/bollharness-integration/context-router.js +292 -292
  18. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  19. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  20. package/dist/bollharness-integration/skill-adapter.js +21 -21
  21. package/dist/bootstrap/chat-archiver.js +14 -14
  22. package/dist/bootstrap/context-os.js +50 -40
  23. package/dist/bootstrap/memory-compressor.js +13 -13
  24. package/dist/cli-entry.js +36 -36
  25. package/dist/context-compaction/auto-compact.js +7 -7
  26. package/dist/cron/cron-parser.js +142 -0
  27. package/dist/cron/jobs-store.js +96 -0
  28. package/dist/cron/scheduler.js +72 -0
  29. package/dist/cron/suggestion-catalog.js +41 -0
  30. package/dist/cron/suggestions-command.js +96 -0
  31. package/dist/cron/suggestions.js +110 -0
  32. package/dist/electron/first-run.js +54 -54
  33. package/dist/electron-build/electron/first-run.js +54 -54
  34. package/dist/electron-preload.js.map +1 -1
  35. package/dist/electron.js.map +1 -1
  36. package/dist/external-engines/delegate-handle.js +70 -0
  37. package/dist/external-engines/delegate.js +24 -3
  38. package/dist/index.js +219 -112
  39. package/dist/llm/error-lessons.js +69 -0
  40. package/dist/llm/llm-judgment-client.js +102 -102
  41. package/dist/llm/pi-ai.js +86 -48
  42. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  43. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  44. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  45. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  46. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  47. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  48. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  49. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  50. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  51. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  52. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  53. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  54. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  55. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  56. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  57. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  58. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  59. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  60. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  61. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  62. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  63. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  64. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  65. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  66. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  67. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  68. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  69. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  70. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  71. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  72. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  73. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  74. package/dist/llm/system-prompt/registry.js +9 -1
  75. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  76. package/dist/llm/tool-manifest/bash.js +3 -3
  77. package/dist/llm/tool-manifest/create_file.js +4 -4
  78. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  79. package/dist/llm/tool-manifest/image_search.js +2 -2
  80. package/dist/llm/tool-manifest/index.js +0 -59
  81. package/dist/llm/tool-manifest/mcp.js +2 -2
  82. package/dist/llm/tool-manifest/message_compose.js +3 -3
  83. package/dist/llm/tool-manifest/places.js +2 -2
  84. package/dist/llm/tool-manifest/present_files.js +1 -1
  85. package/dist/llm/tool-manifest/recipe.js +2 -2
  86. package/dist/llm/tool-manifest/str_replace.js +5 -5
  87. package/dist/llm/tool-manifest/view.js +3 -3
  88. package/dist/llm/tool-manifest/weather.js +4 -4
  89. package/dist/llm/tool-manifest/web.js +4 -4
  90. package/dist/locales/en.js +28 -0
  91. package/dist/locales/zh.js +26 -0
  92. package/dist/pi-ecosystem-colony/index.js +365 -0
  93. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  94. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  95. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  96. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  97. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  98. package/dist/security/context-router-tool.js +15 -15
  99. package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
  100. package/dist/social/ant-colony/PheromoneEngine.js +227 -0
  101. package/dist/social/ant-colony/index.js +6 -0
  102. package/dist/social/ant-colony/types.js +24 -0
  103. package/dist/storage/trajectory.js +101 -0
  104. package/dist/test/ai-judgment-test.js +80 -0
  105. package/dist/test/bollharness-integration.test.js +318 -0
  106. package/dist/test/channel-agent-multi-dialogue.js +205 -0
  107. package/dist/test/channel-heartbeat-agent-test.js +201 -0
  108. package/dist/test/constraint-layer.test.js +164 -0
  109. package/dist/test/diap-identity-test.js +172 -0
  110. package/dist/test/diap-quick-test.js +62 -0
  111. package/dist/test/global-shared-context.test.js +315 -0
  112. package/dist/test/harness-judgment-injection.test.js +246 -0
  113. package/dist/test/harness-workflow-integrator-test.js +228 -0
  114. package/dist/test/human-value-store.test.js +243 -0
  115. package/dist/test/hybrid-integration-test.js +118 -0
  116. package/dist/test/hybrid-messenger-verify.js +55 -0
  117. package/dist/test/iroh-bistream-debug.js +38 -0
  118. package/dist/test/iroh-communication.test.js +66 -0
  119. package/dist/test/iroh-debug-test.js +57 -0
  120. package/dist/test/iroh-diap-test.js +71 -0
  121. package/dist/test/iroh-direct-connect.js +55 -0
  122. package/dist/test/iroh-e2e-fixed.js +89 -0
  123. package/dist/test/iroh-e2e-same-process.js +63 -0
  124. package/dist/test/iroh-e2e.js +66 -0
  125. package/dist/test/iroh-final-e2e.js +72 -0
  126. package/dist/test/iroh-relay-test.js +37 -0
  127. package/dist/test/iroh-simple-test.js +41 -0
  128. package/dist/test/iroh-transport-verify.js +54 -0
  129. package/dist/test/iroh-transport.test.js +37 -0
  130. package/dist/test/iroh-two-nodes.js +70 -0
  131. package/dist/test/iroh-verify.js +44 -0
  132. package/dist/test/judgment-decision.test.js +219 -0
  133. package/dist/test/llm-judgment-integration.test.js +220 -0
  134. package/dist/test/p2p-agent-complex-dialogue.js +385 -0
  135. package/dist/test/p2p-agent-dialogue.js +341 -0
  136. package/dist/test/p2p-agent-full-bidirectional.js +510 -0
  137. package/dist/test/p2p-agent-harness-flow.js +437 -0
  138. package/dist/test/p2p-agent-harness-single.js +143 -0
  139. package/dist/test/p2p-ai-dialogue-test.js +318 -0
  140. package/dist/test/p2p-cid-connect-test.js +195 -0
  141. package/dist/test/p2p-connect-receiver.js +69 -0
  142. package/dist/test/p2p-doc-transfer.js +110 -0
  143. package/dist/test/p2p-identity-page-test.js +77 -0
  144. package/dist/test/p2p-iroh-test.js +171 -0
  145. package/dist/test/p2p-minimal-test.js +241 -0
  146. package/dist/test/p2p-node-1.js +148 -0
  147. package/dist/test/p2p-node-2.js +148 -0
  148. package/dist/test/p2p-server.js +281 -0
  149. package/dist/test/p2p-two-nodes-test.js +438 -0
  150. package/dist/test/pi-sdk.test.js +44 -0
  151. package/dist/test/set-persona.js +40 -0
  152. package/dist/test/simple.test.js +9 -0
  153. package/dist/test/storage-integration.test.js +150 -0
  154. package/dist/test/subagent-manager.test.js +276 -0
  155. package/dist/test/test-gate-flow.test.js +81 -0
  156. package/dist/test/workflow-engine.test.js +87 -0
  157. package/dist/test/workflow-pivot-loop.test.js +246 -0
  158. package/dist/web/api-config.html +779 -779
  159. package/dist/web/client-hearth.js +10 -10
  160. package/dist/web/components/wallet-viem.mjs +118 -118
  161. package/dist/web/delivery-ledger.js +103 -0
  162. package/dist/web/i18n.js +104 -0
  163. package/dist/web/index.html +472 -472
  164. package/dist/web/loop-noise.js +86 -0
  165. package/dist/web/manifest.json +20 -20
  166. package/dist/web/routes-tasks.js +242 -24
  167. package/dist/web/server-sse.js +10 -5
  168. package/dist/web/server-storage.js +111 -0
  169. package/dist/web/server.js +55 -26
  170. package/dist/web/style.css +4946 -4946
  171. package/dist/web/task-breaker.js +18 -0
  172. package/dist/web/task-cancel.js +35 -0
  173. package/dist/web/task-deps.js +36 -0
  174. package/dist/web/task-review.js +27 -0
  175. package/dist/web/task-verify.js +60 -0
  176. package/package.json +196 -196
  177. package/scripts/build-cli.js +215 -215
  178. package/scripts/build-web.ts +130 -130
  179. package/scripts/postinstall.js +152 -152
  180. package/bin/bolloon-daemon.sh +0 -207
  181. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +0 -63
  182. package/dist/constraint-runtime/reference_data/commands_snapshot.json +0 -1037
  183. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +0 -8
  184. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +0 -8
  185. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +0 -32
  186. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +0 -13
  187. package/dist/constraint-runtime/reference_data/subsystems/cli.json +0 -26
  188. package/dist/constraint-runtime/reference_data/subsystems/components.json +0 -32
  189. package/dist/constraint-runtime/reference_data/subsystems/constants.json +0 -28
  190. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +0 -8
  191. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +0 -15
  192. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +0 -32
  193. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +0 -21
  194. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +0 -15
  195. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +0 -18
  196. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +0 -8
  197. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +0 -11
  198. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +0 -8
  199. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +0 -9
  200. package/dist/constraint-runtime/reference_data/subsystems/remote.json +0 -11
  201. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +0 -8
  202. package/dist/constraint-runtime/reference_data/subsystems/screens.json +0 -10
  203. package/dist/constraint-runtime/reference_data/subsystems/server.json +0 -10
  204. package/dist/constraint-runtime/reference_data/subsystems/services.json +0 -32
  205. package/dist/constraint-runtime/reference_data/subsystems/skills.json +0 -27
  206. package/dist/constraint-runtime/reference_data/subsystems/state.json +0 -13
  207. package/dist/constraint-runtime/reference_data/subsystems/types.json +0 -18
  208. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +0 -9
  209. package/dist/constraint-runtime/reference_data/subsystems/utils.json +0 -32
  210. package/dist/constraint-runtime/reference_data/subsystems/vim.json +0 -12
  211. package/dist/constraint-runtime/reference_data/subsystems/voice.json +0 -8
  212. package/dist/constraint-runtime/reference_data/tools_snapshot.json +0 -922
  213. package/dist/electron/config.js.map +0 -1
  214. package/dist/electron/dialogs.js.map +0 -1
  215. package/dist/electron/first-run.js.map +0 -1
  216. package/dist/electron/ipc.js.map +0 -1
  217. package/dist/electron/logger.js.map +0 -1
  218. package/dist/electron/main.js.map +0 -1
  219. package/dist/electron/menu.js.map +0 -1
  220. package/dist/electron/paths.js.map +0 -1
  221. package/dist/electron/server.js.map +0 -1
  222. package/dist/electron/tray.js.map +0 -1
  223. package/dist/electron/window.js.map +0 -1
  224. package/dist/utils/auto-update.js.map +0 -1
  225. package/dist/web/client.js.map +0 -7
@@ -49,60 +49,60 @@ const fs = __importStar(require("fs"));
49
49
  const path = __importStar(require("path"));
50
50
  const paths_1 = require("./paths");
51
51
  const logger_1 = require("./logger");
52
- const OVERLAY_HTML = `
53
- <!DOCTYPE html>
54
- <html>
55
- <head>
56
- <meta charset="utf-8" />
57
- <style>
58
- :root { color-scheme: light dark; }
59
- body {
60
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
61
- margin: 0; padding: 32px 28px;
62
- background: rgba(245,245,247,0.97);
63
- color: #1d1d1f;
64
- height: 100vh; box-sizing: border-box;
65
- }
66
- @media (prefers-color-scheme: dark) {
67
- body { background: rgba(28,28,30,0.97); color: #f5f5f7; }
68
- }
69
- h1 { font-size: 18px; margin: 0 0 14px; font-weight: 600; }
70
- p { font-size: 13px; line-height: 1.55; margin: 8px 0; }
71
- code {
72
- font-family: ui-monospace, "SF Mono", Menlo, monospace;
73
- font-size: 12px; padding: 1px 5px;
74
- background: rgba(0,0,0,0.06); border-radius: 3px;
75
- }
76
- @media (prefers-color-scheme: dark) {
77
- code { background: rgba(255,255,255,0.08); }
78
- }
79
- .btn {
80
- display: inline-block; margin-top: 18px; padding: 8px 18px;
81
- background: #007aff; color: #fff; border: none; border-radius: 6px;
82
- font-size: 13px; font-weight: 500; cursor: pointer;
83
- }
84
- .btn:hover { background: #0066d6; }
85
- ul { padding-left: 20px; }
86
- li { font-size: 13px; line-height: 1.7; }
87
- </style>
88
- </head>
89
- <body>
90
- <h1>欢迎使用 Bolloon Agent</h1>
91
- <p>你的数据存放在本地, 不上传:</p>
92
- <ul>
93
- <li>配置 / 频道 / P2P 密钥: <code id="data"></code></li>
94
- <li>运行日志: <code id="logs"></code></li>
95
- </ul>
96
- <p>所有数据在卸载后仍保留 — 想清理就手动删除 ~/.bolloon/。</p>
97
- <button class="btn" id="ok">知道了</button>
98
- <script>
99
- const ok = document.getElementById('ok');
100
- ok.addEventListener('click', () => window.electronAPI.markFirstRunSeen());
101
- document.getElementById('data').textContent = window.electronAPI.getDataPathSync?.() || '';
102
- document.getElementById('logs').textContent = window.electronAPI.getLogsPathSync?.() || '';
103
- </script>
104
- </body>
105
- </html>
52
+ const OVERLAY_HTML = `
53
+ <!DOCTYPE html>
54
+ <html>
55
+ <head>
56
+ <meta charset="utf-8" />
57
+ <style>
58
+ :root { color-scheme: light dark; }
59
+ body {
60
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
61
+ margin: 0; padding: 32px 28px;
62
+ background: rgba(245,245,247,0.97);
63
+ color: #1d1d1f;
64
+ height: 100vh; box-sizing: border-box;
65
+ }
66
+ @media (prefers-color-scheme: dark) {
67
+ body { background: rgba(28,28,30,0.97); color: #f5f5f7; }
68
+ }
69
+ h1 { font-size: 18px; margin: 0 0 14px; font-weight: 600; }
70
+ p { font-size: 13px; line-height: 1.55; margin: 8px 0; }
71
+ code {
72
+ font-family: ui-monospace, "SF Mono", Menlo, monospace;
73
+ font-size: 12px; padding: 1px 5px;
74
+ background: rgba(0,0,0,0.06); border-radius: 3px;
75
+ }
76
+ @media (prefers-color-scheme: dark) {
77
+ code { background: rgba(255,255,255,0.08); }
78
+ }
79
+ .btn {
80
+ display: inline-block; margin-top: 18px; padding: 8px 18px;
81
+ background: #007aff; color: #fff; border: none; border-radius: 6px;
82
+ font-size: 13px; font-weight: 500; cursor: pointer;
83
+ }
84
+ .btn:hover { background: #0066d6; }
85
+ ul { padding-left: 20px; }
86
+ li { font-size: 13px; line-height: 1.7; }
87
+ </style>
88
+ </head>
89
+ <body>
90
+ <h1>欢迎使用 Bolloon Agent</h1>
91
+ <p>你的数据存放在本地, 不上传:</p>
92
+ <ul>
93
+ <li>配置 / 频道 / P2P 密钥: <code id="data"></code></li>
94
+ <li>运行日志: <code id="logs"></code></li>
95
+ </ul>
96
+ <p>所有数据在卸载后仍保留 — 想清理就手动删除 ~/.bolloon/。</p>
97
+ <button class="btn" id="ok">知道了</button>
98
+ <script>
99
+ const ok = document.getElementById('ok');
100
+ ok.addEventListener('click', () => window.electronAPI.markFirstRunSeen());
101
+ document.getElementById('data').textContent = window.electronAPI.getDataPathSync?.() || '';
102
+ document.getElementById('logs').textContent = window.electronAPI.getLogsPathSync?.() || '';
103
+ </script>
104
+ </body>
105
+ </html>
106
106
  `;
107
107
  function hasSeenFirstRun() {
108
108
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"electron-preload.js","sourceRoot":"","sources":["../src/electron-preload.ts"],"names":[],"mappings":";;AAAA;;;;GAIG;AACH,uCAAwE;AAIxE,wBAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE;IAC7C,kBAAkB;IAClB,UAAU,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,aAAa,CAAC;IACnD,eAAe,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC;IAC/D,YAAY,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC;IAEvE,mBAAmB;IACnB,WAAW,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,eAAe,CAAC;IAEtD,wBAAwB;IACxB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,kBAAkB,EAAE,IAAI,CAAC;IACtE,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,kBAAkB,EAAE,IAAI,CAAC;IACtE,aAAa,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,uBAAuB,EAAE,IAAI,CAAC;IAEhF,gCAAgC;IAChC,YAAY,EAAE,CAAC,IAAyC,EAAE,EAAE,CAC1D,sBAAW,CAAC,MAAM,CAAC,mBAAmB,EAAE,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,IAA0D,EAAE,EAAE,CAC5E,sBAAW,CAAC,MAAM,CAAC,oBAAoB,EAAE,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,IAAsB,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC;IAElF,mBAAmB;IACnB,eAAe,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC;IAC3D,gBAAgB,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,qBAAqB,CAAC;IACjE,eAAe,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC;IAC/D,eAAe,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC;IAE/D,cAAc;IACd,QAAQ,EAAE,OAAO,CAAC,QAAQ;CAC3B,CAAC,CAAC"}
1
+ {"version":3,"file":"electron-preload.js","sourceRoot":"","sources":["../src/electron-preload.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,uCAAsD;AAEtD,eAAe;AACf,wBAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE;IAC7C,UAAU,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,aAAa,CAAC;IACnD,eAAe,EAAE,GAAG,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,oBAAoB,CAAC;IAC/D,YAAY,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,sBAAW,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC;IACvE,QAAQ,EAAE,OAAO,CAAC,QAAQ;CAC3B,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"electron.js","sourceRoot":"","sources":["../src/electron.ts"],"names":[],"mappings":";;AAAA;;;GAGG;AACH,2BAAyB"}
1
+ {"version":3,"file":"electron.js","sourceRoot":"","sources":["../src/electron.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * delegate-handle.ts — 委派句柄 (借鉴 Hermes Agent `agent/subagent_lifecycle.py` 的 handle 设计)
3
+ *
4
+ * Hermes 模式: 子任务 handle 是不可变契约 + HMAC 签名 capability,
5
+ * `capability = HMAC(secret, subagent_id|parent_session_id|created_at)`,
6
+ * 校验时 strict 类型检查 + `hmac.compare_digest` 定时安全比对 + 父 session 必须匹配。
7
+ * 子 agent 拿到 handle 也伪造不了、跨 session 用不了 — 防提权。
8
+ *
9
+ * Bolloon 对应物: delegate_to_engine 的委派记录。
10
+ * - 父身份用 `ownerDid` (agent 的 DID, 稳定跨重启; 比 sessionId 更适合防跨 channel)
11
+ * - handle 写入 sidechain JSONL 落盘, 可事后验证记录真实性 (防伪造委派记录)
12
+ * - correlationId 支持幂等去重 (同一 parent+correlation 只允许一次)
13
+ */
14
+ import { createHmac, randomBytes, randomUUID, timingSafeEqual } from 'crypto';
15
+ /** 契约版本: 结构不兼容时递增, 旧 handle 直接拒绝而不是猜字段 */
16
+ export const DELEGATE_CONTRACT_VERSION = 1;
17
+ /**
18
+ * 进程级随机密钥 (与 Hermes `_SECRET = secrets.token_bytes(32)` 同思路):
19
+ * 每次启动重新生成 → 重启后的旧 handle 全部失效, 序列化 handle 不可重放。
20
+ */
21
+ const _SECRET = randomBytes(32);
22
+ function _capability(delegateId, ownerDid, createdAt) {
23
+ return createHmac('sha256', _SECRET)
24
+ .update(`${delegateId}|${ownerDid}|${createdAt}`)
25
+ .digest('hex');
26
+ }
27
+ /** 创建委派句柄 (与 Hermes launch() 返回 SubagentHandle 对应) */
28
+ export function createDelegateHandle(opts) {
29
+ const delegateId = randomUUID();
30
+ const createdAt = Date.now();
31
+ return {
32
+ contractVersion: DELEGATE_CONTRACT_VERSION,
33
+ delegateId,
34
+ ownerDid: opts.ownerDid,
35
+ correlationId: opts.correlationId,
36
+ createdAt,
37
+ engineId: opts.engineId,
38
+ model: opts.model,
39
+ capability: _capability(delegateId, opts.ownerDid, createdAt),
40
+ };
41
+ }
42
+ /**
43
+ * 校验句柄真实性。
44
+ * @param ownerDid 传当前活跃父 DID → 额外强制匹配 (防跨 channel/跨 agent 使用)
45
+ */
46
+ export function verifyDelegateHandle(handle, ownerDid) {
47
+ if (!handle || typeof handle !== 'object')
48
+ return false;
49
+ const h = handle;
50
+ // strict 类型检查 (Hermes `_record` 同款): 类型不对直接拒, 不猜
51
+ if (h.contractVersion !== DELEGATE_CONTRACT_VERSION)
52
+ return false;
53
+ if (typeof h.delegateId !== 'string' || h.delegateId === '')
54
+ return false;
55
+ if (typeof h.ownerDid !== 'string' || h.ownerDid === '')
56
+ return false;
57
+ if (typeof h.createdAt !== 'number' || !Number.isFinite(h.createdAt))
58
+ return false;
59
+ if (typeof h.engineId !== 'string' || h.engineId === '')
60
+ return false;
61
+ if (typeof h.capability !== 'string' || h.capability === '')
62
+ return false;
63
+ if (ownerDid !== undefined && h.ownerDid !== ownerDid)
64
+ return false;
65
+ // 定时安全比对 (与 hmac.compare_digest 等价)
66
+ const expected = _capability(h.delegateId, h.ownerDid, h.createdAt);
67
+ const a = Buffer.from(h.capability, 'hex');
68
+ const b = Buffer.from(expected, 'hex');
69
+ return a.length === b.length && timingSafeEqual(a, b);
70
+ }
@@ -14,6 +14,7 @@ import * as fs from 'fs/promises';
14
14
  import * as path from 'path';
15
15
  import * as os from 'os';
16
16
  import { discoverEngines, buildDelegateArgs } from './discovery.js';
17
+ import { createDelegateHandle } from './delegate-handle.js';
17
18
  function delegateTimeoutMs() {
18
19
  const env = Number(process.env.BOLLOON_ENGINE_DELEGATE_TIMEOUT_MS);
19
20
  return Number.isFinite(env) && env > 0 ? env : 120_000;
@@ -57,6 +58,15 @@ export async function delegateToEngine(id, prompt, opts = {}) {
57
58
  }
58
59
  const cwd = opts.cwd || process.cwd();
59
60
  const timeoutMs = opts.timeoutMs || delegateTimeoutMs();
61
+ // Hermes 模式: 委派句柄 — HMAC 签名, 随 sidechain 落盘, 返回给调用方供事后验证
62
+ const handle = opts.ownerDid
63
+ ? createDelegateHandle({
64
+ ownerDid: opts.ownerDid,
65
+ engineId: trimmedId,
66
+ correlationId: opts.correlationId,
67
+ model: opts.model,
68
+ })
69
+ : undefined;
60
70
  return new Promise((resolve) => {
61
71
  let stdout = '';
62
72
  let stderr = '';
@@ -137,6 +147,7 @@ export async function delegateToEngine(id, prompt, opts = {}) {
137
147
  killTree();
138
148
  const combined = (stdout + (stderr ? `\n[stderr]\n${stderr}` : '')).trim();
139
149
  // 2026-07-29: Sidechain transcript — 保存委派完整记录
150
+ // 2026-08-11: 记录带 HMAC 签名 handle (contract_version + capability), 可事后验真
140
151
  try {
141
152
  const sidechainDir = path.join(os.homedir(), '.bolloon', 'sidechains');
142
153
  fs.mkdir(sidechainDir, { recursive: true });
@@ -147,19 +158,29 @@ export async function delegateToEngine(id, prompt, opts = {}) {
147
158
  stdout: stdout.slice(0, 100_000),
148
159
  stderr: stderr.slice(0, 10_000),
149
160
  exitCode: code, duration: Date.now() - ts, model: opts.model || null,
161
+ handle: handle ? {
162
+ contractVersion: handle.contractVersion,
163
+ delegateId: handle.delegateId,
164
+ ownerDid: handle.ownerDid,
165
+ correlationId: handle.correlationId ?? null,
166
+ createdAt: handle.createdAt,
167
+ engineId: handle.engineId,
168
+ model: handle.model ?? null,
169
+ capability: handle.capability,
170
+ } : null,
150
171
  }) + '\n';
151
172
  // fire-and-forget, 不阻塞主流程
152
173
  fs.appendFile(filePath, entry, 'utf-8').catch(() => { });
153
174
  }
154
175
  catch { /* sidechain 写入失败静默 */ }
155
176
  if (code === 0) {
156
- resolve({ success: true, output: combined || '(无输出)', exitCode: code });
177
+ resolve({ success: true, output: combined || '(无输出)', exitCode: code, handle });
157
178
  }
158
179
  else if (signal) {
159
- resolve({ success: false, output: combined || '(无输出)', error: `${trimmedId} 被信号 ${signal} 终止`, exitCode: null });
180
+ resolve({ success: false, output: combined || '(无输出)', error: `${trimmedId} 被信号 ${signal} 终止`, exitCode: null, handle });
160
181
  }
161
182
  else {
162
- resolve({ success: false, output: combined || '(无输出)', error: `${trimmedId} 退出码 ${code}`, exitCode: code });
183
+ resolve({ success: false, output: combined || '(无输出)', error: `${trimmedId} 退出码 ${code}`, exitCode: code, handle });
163
184
  }
164
185
  });
165
186
  });
package/dist/index.js CHANGED
@@ -635,6 +635,36 @@ async function startCLI(comm) {
635
635
  setTimeout(() => { cliOrganizeHeartbeat?.runOnce().catch(() => { }); }, 3000);
636
636
  }
637
637
  catch { /* 自动整理启动失败不阻塞 CLI */ }
638
+ // ==================== 2026-08-11: cron 调度心跳 (借鉴 Hermes cron/scheduler.py) ====================
639
+ // 轻量定时任务: 每隔一段时间扫一次 due 的 job, 把 job.prompt 投给 agent 执行.
640
+ // 不阻塞启动, 失败不崩溃 (各自 try/catch), 继承 organize heartbeat 的"静默降级"心智.
641
+ let cliCronTimer = null;
642
+ try {
643
+ const { Scheduler } = await import('./cron/scheduler.js');
644
+ const cronScheduler = new Scheduler({
645
+ now: () => new Date(),
646
+ exec: async (job) => {
647
+ // 借 agent 执行任务 prompt (脱壳为 text 提示). 无 agent / 超时 / 失败 → 抛出交给 scheduler 记录失败
648
+ const a = await Promise.race([
649
+ await getAgent().catch(() => null),
650
+ new Promise((res) => setTimeout(() => res(null), 8000)),
651
+ ]).catch(() => null);
652
+ if (!a || typeof a.promptStream !== 'function') {
653
+ throw new Error('无可用 agent, 跳过调度任务');
654
+ }
655
+ await a.promptStream?.(`[cron] ${job.name}: ${job.prompt}`, () => { }, undefined, cliActiveChannelId || undefined);
656
+ },
657
+ });
658
+ const cronIntervalMs = Number(process.env.BOLLOON_CRON_HEARTBEAT_MS) || 60_000;
659
+ cliCronTimer = setInterval(() => {
660
+ cronScheduler.tick().catch((e) => {
661
+ console.error('[cron] 调度心跳失败 (不影响主流程):', e?.message ?? e);
662
+ });
663
+ }, cronIntervalMs);
664
+ // 启动延迟一轮, 避开启动峰值
665
+ setTimeout(() => { cronScheduler.tick().catch(() => { }); }, 15_000);
666
+ }
667
+ catch { /* cron 调度启动失败不阻塞 CLI */ }
638
668
  // Wait on a promise that resolves on Ctrl+C / 双击 Esc
639
669
  // (ink-app 的 requestExit 调 __inkRequestExit → resolve, 清理后 process.exit)
640
670
  let cliExitResolve = () => { };
@@ -648,6 +678,8 @@ async function startCLI(comm) {
648
678
  cliOrganizeHeartbeat?.stop();
649
679
  }
650
680
  catch { /* 非致命 */ }
681
+ if (cliCronTimer)
682
+ clearInterval(cliCronTimer);
651
683
  comm.stop();
652
684
  process.exit(0);
653
685
  }
@@ -983,6 +1015,79 @@ async function processInput(input, comm) {
983
1015
  catch { /* 静默 */ }
984
1016
  return;
985
1017
  }
1018
+ // /suggestions — 建议队列 (/suggestions [list|accept <n>|dismiss <n>|clear|catalog|install <key>])
1019
+ // 借鉴 Hermes cron/suggestions.py: 有界待办建议, dedup + 用户消费
1020
+ if (cmd === '/suggestions' || cmd.startsWith('/suggestions ')) {
1021
+ try {
1022
+ const { handleSuggestionsCommand } = await import('./cron/suggestions-command.js');
1023
+ const res = await handleSuggestionsCommand(trimmed.slice('/suggestions'.length));
1024
+ appendLine(`${C_ACCENT}◎ 建议${RESET}`);
1025
+ appendLine(res.text);
1026
+ }
1027
+ catch (e) {
1028
+ appendLine(`${C_ERROR}✗ /suggestions 失败: ${String(e.message || e).slice(0, 200)}${RESET}`);
1029
+ }
1030
+ return;
1031
+ }
1032
+ // /cron — 定时任务 (/cron list | add <name> <schedule> <prompt> | rm <id> | on/off <id>)
1033
+ // 借鉴 Hermes cron/scheduler.py: 轻量单文件定时任务 + 调度 tick
1034
+ if (cmd === '/cron' || cmd.startsWith('/cron ')) {
1035
+ const { listJobs, addJob, removeJob, setEnabled } = await import('./cron/jobs-store.js');
1036
+ const { parseSchedule } = await import('./cron/cron-parser.js');
1037
+ const parts = trimmed.slice('/cron'.length).trim().split(/\s+/).filter(Boolean);
1038
+ const action = parts[0]?.toLowerCase() ?? 'list';
1039
+ try {
1040
+ if (action === 'list') {
1041
+ const jobs = await listJobs();
1042
+ if (jobs.length === 0) {
1043
+ appendLine(`${C_ACCENT}⏱ 定时任务${RESET}${C_DIM} 空 — 用 /cron add <名称> '<schedule>' <prompt> 添加${RESET}`);
1044
+ appendLine(`${C_DIM} 示例: /cron add 每日复盘 '0 18 * * *' 总结今天工作并写进 wiki${RESET}`);
1045
+ }
1046
+ else {
1047
+ appendLine(`${C_ACCENT}⏱ 定时任务 (${jobs.length}):${RESET}`);
1048
+ for (const j of jobs) {
1049
+ const next = (() => { try {
1050
+ return parseSchedule(j.schedule)?.next.toISOString();
1051
+ }
1052
+ catch {
1053
+ return null;
1054
+ } })();
1055
+ appendLine(` ${j.enabled ? C_ACCENT + '●' + RESET : C_DIM + '○' + RESET} [${C_DIM}${j.id.slice(0, 8)}${RESET}] ${j.name} ${C_DIM}· ${j.schedule}${RESET}`);
1056
+ appendLine(` ${C_DIM}prompt: ${j.prompt.slice(0, 60)}${RESET}`);
1057
+ if (next)
1058
+ appendLine(` ${C_DIM}下次: ${next} · 已跑 ${j.runCount} 次${RESET}`);
1059
+ }
1060
+ }
1061
+ }
1062
+ else if (action === 'add') {
1063
+ // 参数: <name> <schedule> <prompt...> — name 可能带空格, 用引号/斜杠分隔
1064
+ const m = trimmed.slice('/cron'.length).trim().match(/^add\s+(.*?)\s+'([^']+)'?\s+(.*)$/);
1065
+ if (!m || !parseSchedule(m[2])) {
1066
+ appendLine(`${C_WARN}用法: /cron add <名称> '<schedule>' <prompt>${RESET}`);
1067
+ }
1068
+ else {
1069
+ const job = await addJob({ name: m[1], schedule: m[2], prompt: m[3] }, os.homedir());
1070
+ appendLine(`${C_OK}✓ 已创建任务 ${job.name} (${job.schedule})${RESET}`);
1071
+ }
1072
+ }
1073
+ else if (action === 'rm') {
1074
+ const ok = await removeJob(parts[1], os.homedir());
1075
+ appendLine(`${ok ? C_OK + '✓' + RESET + ' 已删除' : C_ERROR + '✗ 未找到' + RESET} 任务 ${parts[1] ?? ''}`);
1076
+ }
1077
+ else if (action === 'on' || action === 'off') {
1078
+ const en = action === 'on';
1079
+ const j = await setEnabled(parts[1], en, os.homedir());
1080
+ appendLine(j ? `${C_OK}✓ ${en ? '启用' : '停用'} ${j.name}${RESET}` : `${C_ERROR}✗ 未找到 ${parts[1]}${RESET}`);
1081
+ }
1082
+ else {
1083
+ appendLine(`${C_DIM}用法: /cron list | add | rm <id> | on/off <id>${RESET}`);
1084
+ }
1085
+ }
1086
+ catch (e) {
1087
+ appendLine(`${C_ERROR}✗ /cron 失败: ${String(e.message || e).slice(0, 200)}${RESET}`);
1088
+ }
1089
+ return;
1090
+ }
986
1091
  // /session — 当前会话信息
987
1092
  if (cmd === '/session') {
988
1093
  try {
@@ -1554,6 +1659,8 @@ async function processInput(input, comm) {
1554
1659
  appendLine(` ${C_ACCENT}/judgement${RESET} 判断力列表`);
1555
1660
  appendLine(` ${C_ACCENT}/insight${RESET} Context OS 洞察 (08-Insights)`);
1556
1661
  appendLine(` ${C_ACCENT}/wiki${RESET} wiki 状态`);
1662
+ appendLine(` ${C_ACCENT}/suggestions${RESET} 建议队列 ${C_DIM}list · accept <n> · dismiss <n> · clear · catalog · install${RESET}`);
1663
+ appendLine(` ${C_ACCENT}/cron${RESET} 定时任务 ${C_DIM}list · add <名> '<schedule>' <prompt> · rm/on/off <id>${RESET}`);
1557
1664
  appendLine(` ${C_ACCENT}/dream${RESET} 随机灵感 ${C_DIM}/dream <主题> 写入梦想文档并触发循环${RESET}`);
1558
1665
  appendLine(` ${C_ACCENT}@名字${RESET} @ 命中智能体 ${C_DIM}弹出窗选择后发送给智能体${RESET}`);
1559
1666
  appendLine(` ${C_ACCENT}/名字${RESET} / 命中命令/技能/插件 ${C_DIM}输入 / 自动弹出${RESET}`);
@@ -1874,10 +1981,10 @@ async function runToolCommand(tool, args, outputJson, comm, model, prompt) {
1874
1981
  const running = irohTransport.isRunning();
1875
1982
  const irohPeers = irohTransport.getPeers();
1876
1983
  const messenger = hybridMessenger ? 'HybridMessenger 就绪' : 'HybridMessenger 未初始化';
1877
- response = `iroh P2P 状态:
1878
- 运行中: ${running ? '是' : '否'}
1879
- Node ID: ${nodeId ? nodeId.substring(0, 32) + '...' : 'N/A'}
1880
- 已知节点: ${irohPeers.length}
1984
+ response = `iroh P2P 状态:
1985
+ 运行中: ${running ? '是' : '否'}
1986
+ Node ID: ${nodeId ? nodeId.substring(0, 32) + '...' : 'N/A'}
1987
+ 已知节点: ${irohPeers.length}
1881
1988
  ${messenger}`;
1882
1989
  break;
1883
1990
  }
@@ -3011,114 +3118,114 @@ function parseArgs() {
3011
3118
  return result;
3012
3119
  }
3013
3120
  function printHelp() {
3014
- console.log(`
3015
- 🤖 Bolloon Agent - AI 可调用文档处理智能体
3016
-
3017
- 用法:
3018
- npx tsx src/index.ts [选项] [参数]
3019
-
3020
- 选项:
3021
- # 文档处理
3022
- --read <file> 读取文档 (txt, md, pdf, docx)
3023
- --summarize <file> [ctx] 总结文档,可选上下文
3024
- --improve <file> <req> 改进文档,req 为改进要求
3025
-
3026
- # P2P 网络
3027
- --peers 列出已连接的对等节点
3028
- --broadcast <msg> 广播消息到所有节点
3029
- --send <peerId> <msg> 向指定节点发送消息
3030
-
3031
- # 智能体
3032
- --identity 显示当前智能体身份
3033
- --logs 显示操作日志
3034
- --search <keyword> 搜索文件
3035
- --tools 显示所有可用工具
3036
-
3037
- # SubAgent 管理
3038
- --agents 列出所有 SubAgent
3039
- --register-agent <name> [cap1] [cap2]... 注册新 SubAgent
3040
- --delegate <任务描述> [能力要求...] 委派任务给最佳 Agent
3041
-
3042
- # 全局共享上下文
3043
- --context 显示全局共享上下文摘要
3044
- --global-agents 显示全局 Agent 注册表
3045
- --add-action <内容> [重要性] 添加用户行动到共享上下文
3046
-
3047
- # Bollharness 治理框架
3048
- --harness-init 初始化 Bollharness 治理框架
3049
- --harness-gate 显示当前 Gate 状态
3050
- --harness-transition [PASS|BLOCK] 执行 Gate 转移
3051
- --harness-skill <name> [action] 执行 Harness Skill
3052
- --harness-classify <描述> 分类变更类型
3053
- --harness-context <file> 获取文件上下文
3054
- --harness-check <file> 执行 Guard 检查
3055
- --harness-archive 归档当前 Session 到 Harness
3056
- --harness-sessions 列出 Session 归档记录
3057
- --harness-session-context [id] 获取 Session 上下文
3058
-
3059
- # 自动更新
3060
- --update-check 检查 npm 包更新
3061
- --update-now [pkg] 更新到最新版本
3062
-
3063
- # 跨机聊天 (commits-as-messages, 共享 GitHub 仓库)
3064
- --chat-init 初始化 .comm/ 目录 (一次性)
3065
- --chat-send "消息正文" 把消息写到 .comm/<role>/, commit + push
3066
- --chat-pull 拉取远端 .comm/ 的新消息并显示
3067
- --chat-list 列出本地所有已同步消息
3068
- --chat-watch [--interval 15s] 后台定时拉取, 有新消息时输出
3069
- --chat-status 一屏查看: role / publicKey / remote / ahead-behind
3070
-
3071
- # 纯 P2P 私聊 (不走 GitHub, 不写 git, 不持久化)
3072
- --chat-p2p-send <peer|publicKey> "消息正文" 通过 P2P 直接发一条
3073
- --chat-p2p-listen 后台监听对方 P2P 私聊消息 (Ctrl-C 退出)
3074
-
3075
- # 跨机 agent 协作 (对方 bolloon --web 起着才能处理, 走 P2P 不经 GitHub)
3076
- --collab <peer|publicKey> "<任务描述>" 派任务给对端 LLM 干活, 等回结果 (90s 超时)
3077
-
3078
- # 外部编码智能体委派
3079
- --engine, -e <id> [--model <m>] <prompt> 委派任务给外部引擎,如 opencode/codex
3080
- --model <name> 指定委派时使用的模型
3081
-
3082
- # 输出控制
3083
- --json, -j 输出 JSON 格式
3084
- --output, -o <file> 结果保存到文件
3085
- --web 启动 Web UI 模式
3086
- --help, -h 显示帮助信息
3087
-
3088
- 示例:
3089
- # 文档处理
3090
- npx tsx src/index.ts --read 想法.md
3091
- npx tsx src/index.ts --summarize docs/想法.md
3092
- npx tsx src/index.ts --improve docs/README.md "让内容更简洁"
3093
- npx tsx src/index.ts --read 想法.md -o summary.txt
3094
-
3095
- # P2P 网络
3096
- npx tsx src/index.ts --peers
3097
- npx tsx src/index.ts --broadcast "Hello everyone"
3098
- npx tsx src/index.ts --send QmABC... "私信内容"
3099
-
3100
- # AI 对话
3101
- npx tsx src/index.ts --prompt "总结 README.md"
3102
- npx tsx src/index.ts -p "分析这个项目" -j
3103
-
3104
- # 交互模式
3105
- npx tsx src/index.ts
3106
-
3107
- # 外部引擎委派
3108
- npx tsx src/index.ts --engine opencode --model opencode/deepseek-v4-flash-free "说你好"
3109
-
3110
- # Web 模式
3111
- npx tsx src/index.ts --web
3112
-
3113
- 环境变量:
3114
- MINIMAX_API_KEY MiniMax API 密钥
3115
- DEEPSEEK_API_KEY DeepSeek API 密钥
3116
- KIMI_API_KEY / MOONSHOT_API_KEY Kimi/Moonshot API 密钥
3117
- GLM_API_KEY / ZHIPU_API_KEY 智谱 GLM API 密钥
3118
- QWEN_API_KEY / DASHSCOPE_API_KEY 通义千问 API 密钥
3119
- OPENAI_API_KEY OpenAI API 密钥(Pi SDK)
3120
- ANTHROPIC_API_KEY Anthropic API 密钥(Pi SDK)
3121
- PORT Web 服务端口(默认 54188)
3121
+ console.log(`
3122
+ 🤖 Bolloon Agent - AI 可调用文档处理智能体
3123
+
3124
+ 用法:
3125
+ npx tsx src/index.ts [选项] [参数]
3126
+
3127
+ 选项:
3128
+ # 文档处理
3129
+ --read <file> 读取文档 (txt, md, pdf, docx)
3130
+ --summarize <file> [ctx] 总结文档,可选上下文
3131
+ --improve <file> <req> 改进文档,req 为改进要求
3132
+
3133
+ # P2P 网络
3134
+ --peers 列出已连接的对等节点
3135
+ --broadcast <msg> 广播消息到所有节点
3136
+ --send <peerId> <msg> 向指定节点发送消息
3137
+
3138
+ # 智能体
3139
+ --identity 显示当前智能体身份
3140
+ --logs 显示操作日志
3141
+ --search <keyword> 搜索文件
3142
+ --tools 显示所有可用工具
3143
+
3144
+ # SubAgent 管理
3145
+ --agents 列出所有 SubAgent
3146
+ --register-agent <name> [cap1] [cap2]... 注册新 SubAgent
3147
+ --delegate <任务描述> [能力要求...] 委派任务给最佳 Agent
3148
+
3149
+ # 全局共享上下文
3150
+ --context 显示全局共享上下文摘要
3151
+ --global-agents 显示全局 Agent 注册表
3152
+ --add-action <内容> [重要性] 添加用户行动到共享上下文
3153
+
3154
+ # Bollharness 治理框架
3155
+ --harness-init 初始化 Bollharness 治理框架
3156
+ --harness-gate 显示当前 Gate 状态
3157
+ --harness-transition [PASS|BLOCK] 执行 Gate 转移
3158
+ --harness-skill <name> [action] 执行 Harness Skill
3159
+ --harness-classify <描述> 分类变更类型
3160
+ --harness-context <file> 获取文件上下文
3161
+ --harness-check <file> 执行 Guard 检查
3162
+ --harness-archive 归档当前 Session 到 Harness
3163
+ --harness-sessions 列出 Session 归档记录
3164
+ --harness-session-context [id] 获取 Session 上下文
3165
+
3166
+ # 自动更新
3167
+ --update-check 检查 npm 包更新
3168
+ --update-now [pkg] 更新到最新版本
3169
+
3170
+ # 跨机聊天 (commits-as-messages, 共享 GitHub 仓库)
3171
+ --chat-init 初始化 .comm/ 目录 (一次性)
3172
+ --chat-send "消息正文" 把消息写到 .comm/<role>/, commit + push
3173
+ --chat-pull 拉取远端 .comm/ 的新消息并显示
3174
+ --chat-list 列出本地所有已同步消息
3175
+ --chat-watch [--interval 15s] 后台定时拉取, 有新消息时输出
3176
+ --chat-status 一屏查看: role / publicKey / remote / ahead-behind
3177
+
3178
+ # 纯 P2P 私聊 (不走 GitHub, 不写 git, 不持久化)
3179
+ --chat-p2p-send <peer|publicKey> "消息正文" 通过 P2P 直接发一条
3180
+ --chat-p2p-listen 后台监听对方 P2P 私聊消息 (Ctrl-C 退出)
3181
+
3182
+ # 跨机 agent 协作 (对方 bolloon --web 起着才能处理, 走 P2P 不经 GitHub)
3183
+ --collab <peer|publicKey> "<任务描述>" 派任务给对端 LLM 干活, 等回结果 (90s 超时)
3184
+
3185
+ # 外部编码智能体委派
3186
+ --engine, -e <id> [--model <m>] <prompt> 委派任务给外部引擎,如 opencode/codex
3187
+ --model <name> 指定委派时使用的模型
3188
+
3189
+ # 输出控制
3190
+ --json, -j 输出 JSON 格式
3191
+ --output, -o <file> 结果保存到文件
3192
+ --web 启动 Web UI 模式
3193
+ --help, -h 显示帮助信息
3194
+
3195
+ 示例:
3196
+ # 文档处理
3197
+ npx tsx src/index.ts --read 想法.md
3198
+ npx tsx src/index.ts --summarize docs/想法.md
3199
+ npx tsx src/index.ts --improve docs/README.md "让内容更简洁"
3200
+ npx tsx src/index.ts --read 想法.md -o summary.txt
3201
+
3202
+ # P2P 网络
3203
+ npx tsx src/index.ts --peers
3204
+ npx tsx src/index.ts --broadcast "Hello everyone"
3205
+ npx tsx src/index.ts --send QmABC... "私信内容"
3206
+
3207
+ # AI 对话
3208
+ npx tsx src/index.ts --prompt "总结 README.md"
3209
+ npx tsx src/index.ts -p "分析这个项目" -j
3210
+
3211
+ # 交互模式
3212
+ npx tsx src/index.ts
3213
+
3214
+ # 外部引擎委派
3215
+ npx tsx src/index.ts --engine opencode --model opencode/deepseek-v4-flash-free "说你好"
3216
+
3217
+ # Web 模式
3218
+ npx tsx src/index.ts --web
3219
+
3220
+ 环境变量:
3221
+ MINIMAX_API_KEY MiniMax API 密钥
3222
+ DEEPSEEK_API_KEY DeepSeek API 密钥
3223
+ KIMI_API_KEY / MOONSHOT_API_KEY Kimi/Moonshot API 密钥
3224
+ GLM_API_KEY / ZHIPU_API_KEY 智谱 GLM API 密钥
3225
+ QWEN_API_KEY / DASHSCOPE_API_KEY 通义千问 API 密钥
3226
+ OPENAI_API_KEY OpenAI API 密钥(Pi SDK)
3227
+ ANTHROPIC_API_KEY Anthropic API 密钥(Pi SDK)
3228
+ PORT Web 服务端口(默认 54188)
3122
3229
  `);
3123
3230
  }
3124
3231
  // ---------------------------------------------------------------------------