@bolloon/bolloon-agent 0.1.0

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 (808) hide show
  1. package/README.md +462 -0
  2. package/dist/agents/constraint-layer.js +211 -0
  3. package/dist/agents/constraint-layer.js.map +1 -0
  4. package/dist/agents/pi-sdk.js +1199 -0
  5. package/dist/agents/pi-sdk.js.map +1 -0
  6. package/dist/agents/protocol.js +229 -0
  7. package/dist/agents/subagent-manager.js +361 -0
  8. package/dist/agents/workflow-engine.js +222 -0
  9. package/dist/agents/workflow-engine.js.map +1 -0
  10. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.d.ts +48 -0
  11. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.js +261 -0
  12. package/dist/bollharness-integration/bollharness-integration/context-router.d.ts +110 -0
  13. package/dist/bollharness-integration/bollharness-integration/context-router.js +542 -0
  14. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.d.ts +87 -0
  15. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.js +231 -0
  16. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.d.ts +30 -0
  17. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.js +91 -0
  18. package/dist/bollharness-integration/bollharness-integration/guard-checker.d.ts +105 -0
  19. package/dist/bollharness-integration/bollharness-integration/guard-checker.js +353 -0
  20. package/dist/bollharness-integration/bollharness-integration/index.d.ts +66 -0
  21. package/dist/bollharness-integration/bollharness-integration/index.js +32 -0
  22. package/dist/bollharness-integration/bollharness-integration/integration.d.ts +219 -0
  23. package/dist/bollharness-integration/bollharness-integration/integration.js +420 -0
  24. package/dist/bollharness-integration/bollharness-integration/skill-adapter.d.ts +151 -0
  25. package/dist/bollharness-integration/bollharness-integration/skill-adapter.js +518 -0
  26. package/dist/bollharness-integration/context-router-judgment.js +269 -0
  27. package/dist/bollharness-integration/context-router-judgment.js.map +1 -0
  28. package/dist/bollharness-integration/context-router.js +584 -0
  29. package/dist/bollharness-integration/context-router.js.map +1 -0
  30. package/dist/bollharness-integration/gate-state-machine.js +349 -0
  31. package/dist/bollharness-integration/gate-state-machine.js.map +1 -0
  32. package/dist/bollharness-integration/gate-transition-hooks.js +136 -0
  33. package/dist/bollharness-integration/gate-transition-hooks.js.map +1 -0
  34. package/dist/bollharness-integration/guard-checker.js +400 -0
  35. package/dist/bollharness-integration/guard-checker.js.map +1 -0
  36. package/dist/bollharness-integration/index.js +142 -0
  37. package/dist/bollharness-integration/index.js.map +1 -0
  38. package/dist/bollharness-integration/integration.js +427 -0
  39. package/dist/bollharness-integration/integration.js.map +1 -0
  40. package/dist/bollharness-integration/llm/pi-ai.d.ts +60 -0
  41. package/dist/bollharness-integration/llm/pi-ai.js +397 -0
  42. package/dist/bollharness-integration/pi-ecosystem-colony/index.d.ts +153 -0
  43. package/dist/bollharness-integration/pi-ecosystem-colony/index.js +365 -0
  44. package/dist/bollharness-integration/pi-ecosystem-goals/index.d.ts +136 -0
  45. package/dist/bollharness-integration/pi-ecosystem-goals/index.js +458 -0
  46. package/dist/bollharness-integration/pi-ecosystem-judgment/decision.d.ts +117 -0
  47. package/dist/bollharness-integration/pi-ecosystem-judgment/decision.js +300 -0
  48. package/dist/bollharness-integration/pi-ecosystem-judgment/distillation.d.ts +78 -0
  49. package/dist/bollharness-integration/pi-ecosystem-judgment/distillation.js +291 -0
  50. package/dist/bollharness-integration/pi-ecosystem-judgment/index.d.ts +139 -0
  51. package/dist/bollharness-integration/pi-ecosystem-judgment/index.js +445 -0
  52. package/dist/bollharness-integration/pi-ecosystem-mcp/index.d.ts +127 -0
  53. package/dist/bollharness-integration/pi-ecosystem-mcp/index.js +331 -0
  54. package/dist/bollharness-integration/pi-ecosystem-subagents/index.d.ts +95 -0
  55. package/dist/bollharness-integration/pi-ecosystem-subagents/index.js +303 -0
  56. package/dist/bollharness-integration/skill-adapter.js +564 -0
  57. package/dist/bollharness-integration/skill-adapter.js.map +1 -0
  58. package/dist/cli/interface.js +181 -0
  59. package/dist/constraint-runtime/src/_archive_helper.js +9 -0
  60. package/dist/constraint-runtime/src/agent/coordinator.js +48 -0
  61. package/dist/constraint-runtime/src/agent/index.js +1 -0
  62. package/dist/constraint-runtime/src/assistant/index.js +12 -0
  63. package/dist/constraint-runtime/src/bootstrap/index.js +12 -0
  64. package/dist/constraint-runtime/src/bootstrap_graph.js +13 -0
  65. package/dist/constraint-runtime/src/bridge/index.js +12 -0
  66. package/dist/constraint-runtime/src/buddy/index.js +12 -0
  67. package/dist/constraint-runtime/src/cli/index.js +12 -0
  68. package/dist/constraint-runtime/src/command_graph.js +10 -0
  69. package/dist/constraint-runtime/src/commands.js +50 -0
  70. package/dist/constraint-runtime/src/components/index.js +12 -0
  71. package/dist/constraint-runtime/src/constants/index.js +12 -0
  72. package/dist/constraint-runtime/src/constraint/budget.js +27 -0
  73. package/dist/constraint-runtime/src/constraint/budget.js.map +1 -0
  74. package/dist/constraint-runtime/src/constraint/index.js +2 -0
  75. package/dist/constraint-runtime/src/constraint/permission.js +25 -0
  76. package/dist/constraint-runtime/src/constraint/permission.js.map +1 -0
  77. package/dist/constraint-runtime/src/context.js +30 -0
  78. package/dist/constraint-runtime/src/coordinator/index.js +12 -0
  79. package/dist/constraint-runtime/src/cost_hook.js +4 -0
  80. package/dist/constraint-runtime/src/cost_tracker.js +8 -0
  81. package/dist/constraint-runtime/src/deferred_init.js +10 -0
  82. package/dist/constraint-runtime/src/direct_modes.js +6 -0
  83. package/dist/constraint-runtime/src/dynamic-tool-loader.js +85 -0
  84. package/dist/constraint-runtime/src/entrypoints/index.js +12 -0
  85. package/dist/constraint-runtime/src/execution_registry.js +44 -0
  86. package/dist/constraint-runtime/src/history.js +9 -0
  87. package/dist/constraint-runtime/src/hooks/index.js +12 -0
  88. package/dist/constraint-runtime/src/index.js +26 -0
  89. package/dist/constraint-runtime/src/ink.js +4 -0
  90. package/dist/constraint-runtime/src/keybindings/index.js +12 -0
  91. package/dist/constraint-runtime/src/memdir/index.js +12 -0
  92. package/dist/constraint-runtime/src/migrations/index.js +12 -0
  93. package/dist/constraint-runtime/src/models.js +3 -0
  94. package/dist/constraint-runtime/src/models.js.map +1 -0
  95. package/dist/constraint-runtime/src/moreright/index.js +12 -0
  96. package/dist/constraint-runtime/src/native_ts/index.js +12 -0
  97. package/dist/constraint-runtime/src/output_styles/index.js +12 -0
  98. package/dist/constraint-runtime/src/parity_audit.js +12 -0
  99. package/dist/constraint-runtime/src/plugins/index.js +12 -0
  100. package/dist/constraint-runtime/src/port_manifest.js +11 -0
  101. package/dist/constraint-runtime/src/prefetch.js +9 -0
  102. package/dist/constraint-runtime/src/query.js +1 -0
  103. package/dist/constraint-runtime/src/remote/index.js +12 -0
  104. package/dist/constraint-runtime/src/remote_runtime.js +9 -0
  105. package/dist/constraint-runtime/src/runtime/index.js +1 -0
  106. package/dist/constraint-runtime/src/runtime/session.js +35 -0
  107. package/dist/constraint-runtime/src/schemas/index.js +12 -0
  108. package/dist/constraint-runtime/src/screens/index.js +12 -0
  109. package/dist/constraint-runtime/src/server/index.js +12 -0
  110. package/dist/constraint-runtime/src/services/index.js +12 -0
  111. package/dist/constraint-runtime/src/session_store.js +22 -0
  112. package/dist/constraint-runtime/src/setup.js +30 -0
  113. package/dist/constraint-runtime/src/skills/index.js +1 -0
  114. package/dist/constraint-runtime/src/skills/skill-registry.js +28 -0
  115. package/dist/constraint-runtime/src/state/index.js +12 -0
  116. package/dist/constraint-runtime/src/system_init.js +20 -0
  117. package/dist/constraint-runtime/src/thinking/engine.js +42 -0
  118. package/dist/constraint-runtime/src/thinking/index.js +1 -0
  119. package/dist/constraint-runtime/src/tool_pool.js +8 -0
  120. package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +7 -0
  121. package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +7 -0
  122. package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +7 -0
  123. package/dist/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.js +6 -0
  124. package/dist/constraint-runtime/src/tools/PolymarketSDK/createOrder.js +6 -0
  125. package/dist/constraint-runtime/src/tools/PolymarketSDK/getMarket.js +5 -0
  126. package/dist/constraint-runtime/src/tools/PolymarketSDK/getOrders.js +6 -0
  127. package/dist/constraint-runtime/src/tools/PolymarketSDK/listMarkets.js +4 -0
  128. package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +6 -0
  129. package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +8 -0
  130. package/dist/constraint-runtime/src/tools/SafeSDK/deploySafe.js +6 -0
  131. package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +6 -0
  132. package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +6 -0
  133. package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +6 -0
  134. package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +6 -0
  135. package/dist/constraint-runtime/src/tools/WalletTools/autoPay.js +29 -0
  136. package/dist/constraint-runtime/src/tools/WalletTools/createWallet.js +10 -0
  137. package/dist/constraint-runtime/src/tools/WalletTools/getBalance.js +13 -0
  138. package/dist/constraint-runtime/src/tools/WalletTools/importWallet.js +22 -0
  139. package/dist/constraint-runtime/src/tools/WalletTools/sendTransaction.js +25 -0
  140. package/dist/constraint-runtime/src/tools/WalletTools/signMessage.js +10 -0
  141. package/dist/constraint-runtime/src/tools/WalletTools/transferToken.js +25 -0
  142. package/dist/constraint-runtime/src/tools.js +70 -0
  143. package/dist/constraint-runtime/src/transcript.js +19 -0
  144. package/dist/constraint-runtime/src/types/index.js +12 -0
  145. package/dist/constraint-runtime/src/upstream_proxy/index.js +12 -0
  146. package/dist/constraint-runtime/src/utils/index.js +12 -0
  147. package/dist/constraint-runtime/src/vim/index.js +12 -0
  148. package/dist/constraint-runtime/src/voice/index.js +12 -0
  149. package/dist/constraint-runtime/tests/agent.test.js +16 -0
  150. package/dist/constraint-runtime/tests/constraint.test.js +41 -0
  151. package/dist/constraint-runtime/tests/skill.test.js +19 -0
  152. package/dist/constraint-runtime/tests/thinking.test.js +22 -0
  153. package/dist/constraints/commands.js +100 -0
  154. package/dist/constraints/index.js +11 -0
  155. package/dist/constraints/index.js.map +1 -0
  156. package/dist/constraints/permissions.js +37 -0
  157. package/dist/constraints/runtime.js +135 -0
  158. package/dist/constraints/session.js +48 -0
  159. package/dist/constraints/system-init.js +51 -0
  160. package/dist/constraints/tools.js +104 -0
  161. package/dist/documents/reader.js +104 -0
  162. package/dist/documents/reader.js.map +1 -0
  163. package/dist/electron-preload.js +15 -0
  164. package/dist/electron-preload.js.map +1 -0
  165. package/dist/electron.js +206 -0
  166. package/dist/electron.js.map +1 -0
  167. package/dist/index.js +1053 -0
  168. package/dist/llm/config-store.js +301 -0
  169. package/dist/llm/config-store.js.map +1 -0
  170. package/dist/llm/minimax-provider.js +46 -0
  171. package/dist/llm/minimax.js +45 -0
  172. package/dist/llm/pi-ai.js +471 -0
  173. package/dist/llm/pi-ai.js.map +1 -0
  174. package/dist/network/agent-network.js +692 -0
  175. package/dist/network/agent-network.js.map +1 -0
  176. package/dist/network/iroh-integration.js +117 -0
  177. package/dist/network/iroh-integration.js.map +1 -0
  178. package/dist/network/iroh-transport.js +506 -0
  179. package/dist/network/iroh-transport.js.map +1 -0
  180. package/dist/network/p2p.js +864 -0
  181. package/dist/network/p2p.js.map +1 -0
  182. package/dist/network/storage/adapters/json-adapter.js +401 -0
  183. package/dist/network/storage/adapters/json-adapter.js.map +1 -0
  184. package/dist/pi-ecosystem-colony/index.js +426 -0
  185. package/dist/pi-ecosystem-colony/index.js.map +1 -0
  186. package/dist/pi-ecosystem-goals/index.js +512 -0
  187. package/dist/pi-ecosystem-goals/index.js.map +1 -0
  188. package/dist/pi-ecosystem-judgment/decision.js +318 -0
  189. package/dist/pi-ecosystem-judgment/decision.js.map +1 -0
  190. package/dist/pi-ecosystem-judgment/distillation.js +304 -0
  191. package/dist/pi-ecosystem-judgment/distillation.js.map +1 -0
  192. package/dist/pi-ecosystem-judgment/human-value-store.js +463 -0
  193. package/dist/pi-ecosystem-judgment/human-value-store.js.map +1 -0
  194. package/dist/pi-ecosystem-judgment/index.js +581 -0
  195. package/dist/pi-ecosystem-judgment/index.js.map +1 -0
  196. package/dist/pi-ecosystem-judgment/value-injection.js +592 -0
  197. package/dist/pi-ecosystem-judgment/value-injection.js.map +1 -0
  198. package/dist/pi-ecosystem-mcp/index.js +385 -0
  199. package/dist/pi-ecosystem-mcp/index.js.map +1 -0
  200. package/dist/pi-ecosystem-subagents/index.js +352 -0
  201. package/dist/pi-ecosystem-subagents/index.js.map +1 -0
  202. package/dist/runtime/context/minimax-prompt.js +178 -0
  203. package/dist/runtime/context/sys-prompt.js +1 -0
  204. package/dist/social/ant-colony/AdaptiveHeartbeat.js +106 -0
  205. package/dist/social/ant-colony/AdaptiveHeartbeat.js.map +1 -0
  206. package/dist/social/ant-colony/PheromoneEngine.js +265 -0
  207. package/dist/social/ant-colony/PheromoneEngine.js.map +1 -0
  208. package/dist/social/ant-colony/types.js +28 -0
  209. package/dist/social/ant-colony/types.js.map +1 -0
  210. package/dist/social/channels/ChannelManager.js +444 -0
  211. package/dist/social/channels/ChannelManager.js.map +1 -0
  212. package/dist/social/channels/DiapChannelBridge.js +451 -0
  213. package/dist/social/channels/DiapChannelBridge.js.map +1 -0
  214. package/dist/social/channels/InterestMatcher.js +135 -0
  215. package/dist/social/channels/InterestMatcher.js.map +1 -0
  216. package/dist/social/channels/types.js +21 -0
  217. package/dist/social/channels/types.js.map +1 -0
  218. package/dist/social/global-shared-context.js +368 -0
  219. package/dist/social/global-shared-context.js.map +1 -0
  220. package/dist/social/heartbeat.js +865 -0
  221. package/dist/social/heartbeat.js.map +1 -0
  222. package/dist/test/constraint-layer.test.js +164 -0
  223. package/dist/test/global-shared-context.test.js +315 -0
  224. package/dist/test/pi-sdk.test.js +47 -0
  225. package/dist/test/set-persona.test.js +38 -0
  226. package/dist/test/subagent-manager.test.js +276 -0
  227. package/dist/test/workflow-engine.test.js +87 -0
  228. package/dist/web/api-config.html +265 -0
  229. package/dist/web/client.js +1401 -0
  230. package/dist/web/components/p2p/index.js +357 -0
  231. package/dist/web/components/p2p/p2p-connection.js +161 -0
  232. package/dist/web/components/p2p/p2p-identity.js +78 -0
  233. package/dist/web/components/p2p/p2p-manager.js +82 -0
  234. package/dist/web/components/p2p/p2p-messages.js +186 -0
  235. package/dist/web/components/p2p/p2p-store-memory.js +129 -0
  236. package/dist/web/components/p2p/types.js +23 -0
  237. package/dist/web/index.html +192 -0
  238. package/dist/web/server.js +1647 -0
  239. package/dist/web/server.js.map +1 -0
  240. package/dist/web/style.css +3260 -0
  241. package/dist/workflows/collaboration.js +374 -0
  242. package/dist/workflows/index.js +54 -0
  243. package/docs/agent-communication.md +333 -0
  244. package/docs/plans/2026-05-15-document-agent-design.md +479 -0
  245. package/docs/plans/2026-05-15-document-agent-implementation-plan.md +792 -0
  246. package/docs/plans/2026-05-16-chat-ui-design.md +86 -0
  247. package/docs/plans/2026-05-16-constraint-runtime-design.md +106 -0
  248. package/docs/plans/2026-05-16-constraint-runtime-implementation.md +441 -0
  249. package/docs//346/225/260/345/255/246/350/276/205/345/212/251/346/231/272/350/203/275/344/275/223-/346/240/270/345/277/203/346/225/210/346/236/234/345/256/232/344/271/211.md +287 -0
  250. package/package.json +121 -0
  251. package/scripts/build-web.ts +61 -0
  252. package/src/agents/constraint-layer.ts +309 -0
  253. package/src/agents/pi-sdk.ts +1591 -0
  254. package/src/agents/protocol.ts +304 -0
  255. package/src/agents/subagent-manager.ts +553 -0
  256. package/src/agents/workflow-engine.ts +332 -0
  257. package/src/bollharness/.boll/CLAUDE.md.template +34 -0
  258. package/src/bollharness/.boll/MANIFEST.yaml +213 -0
  259. package/src/bollharness/.boll/active-review-agents/.gitkeep +0 -0
  260. package/src/bollharness/.boll/agents/review-base.yaml +108 -0
  261. package/src/bollharness/.boll/deploy-allowlist.yaml +38 -0
  262. package/src/bollharness/.boll/inbox/schema/message-v1.json +99 -0
  263. package/src/bollharness/.boll/install-staging/.gitkeep +0 -0
  264. package/src/bollharness/.boll/issue-adapter.yaml +31 -0
  265. package/src/bollharness/.boll/plugins/boll-mode-toolkit/contracts/mode-contract.md +85 -0
  266. package/src/bollharness/.boll/plugins/boll-review-toolkit/contracts/evidence-packet-schema.json +102 -0
  267. package/src/bollharness/.boll/plugins/boll-review-toolkit/contracts/review-contract.yaml +247 -0
  268. package/src/bollharness/.boll/rules/backend-routes.md +31 -0
  269. package/src/bollharness/.boll/rules/closure-semantics.md +30 -0
  270. package/src/bollharness/.boll/rules/env-vars.md +32 -0
  271. package/src/bollharness/.boll/rules/hanis-protocol.md +145 -0
  272. package/src/bollharness/.boll/rules/repo-structure.md +42 -0
  273. package/src/bollharness/.boll/rules/review-agent-isolation.md +73 -0
  274. package/src/bollharness/.boll/rules/source-of-truth.md +33 -0
  275. package/src/bollharness/.boll/settings.json +180 -0
  276. package/src/bollharness/.boll/settings.json.template +31 -0
  277. package/src/bollharness/.boll/skills/arch/SKILL.md +372 -0
  278. package/src/bollharness/.boll/skills/bug-pipeline/SKILL.md +168 -0
  279. package/src/bollharness/.boll/skills/bug-triage/SKILL.md +161 -0
  280. package/src/bollharness/.boll/skills/context-chains/SKILL.md +250 -0
  281. package/src/bollharness/.boll/skills/context-chains/context-chain-index.md +48 -0
  282. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/code_change_extractor.ts +142 -0
  283. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/debugging_extractor.ts +126 -0
  284. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/design_extractor.ts +148 -0
  285. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/planning_extractor.ts +162 -0
  286. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/question_extractor.ts +116 -0
  287. package/src/bollharness/.boll/skills/context-chains/work-type-extractors/review_extractor.ts +136 -0
  288. package/src/bollharness/.boll/skills/crystal-learn/SKILL.md +93 -0
  289. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-0.md +34 -0
  290. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-1.md +34 -0
  291. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-2.md +35 -0
  292. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-3.md +34 -0
  293. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-4.md +43 -0
  294. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-5.md +34 -0
  295. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-6.md +37 -0
  296. package/src/bollharness/.boll/skills/crystal-learn/invariants/INV-7.md +46 -0
  297. package/src/bollharness/.boll/skills/guardian-fixer/PROMPT.md +415 -0
  298. package/src/bollharness/.boll/skills/guardian-fixer/SKILL.md +320 -0
  299. package/src/bollharness/.boll/skills/harness-dev/SKILL.md +93 -0
  300. package/src/bollharness/.boll/skills/harness-dev/examples/README.md +227 -0
  301. package/src/bollharness/.boll/skills/harness-dev-handoff/SKILL.md +165 -0
  302. package/src/bollharness/.boll/skills/harness-eng/SKILL.md +110 -0
  303. package/src/bollharness/.boll/skills/harness-eng-test/SKILL.md +79 -0
  304. package/src/bollharness/.boll/skills/harness-lab/SKILL.md +170 -0
  305. package/src/bollharness/.boll/skills/harness-ops/SKILL.md +57 -0
  306. package/src/bollharness/.boll/skills/harness-voice/SKILL.md +183 -0
  307. package/src/bollharness/.boll/skills/judgment/SKILL.md +115 -0
  308. package/src/bollharness/.boll/skills/lead/SKILL.md +245 -0
  309. package/src/bollharness/.boll/skills/lead/install-wow-harness.md +77 -0
  310. package/src/bollharness/.boll/skills/lead/ref-review-sop.md +91 -0
  311. package/src/bollharness/.boll/skills/lead/ref-stages.md +129 -0
  312. package/src/bollharness/.boll/skills/skill-discovery/SKILL.md +169 -0
  313. package/src/bollharness/.boll/skills/task-arch/SKILL.md +106 -0
  314. package/src/bollharness/.boll/skills/toolkit/SKILL.md +57 -0
  315. package/src/bollharness/.boll/tasks/.gitkeep +0 -0
  316. package/src/bollharness/.boll/toolkit-index.yaml +112 -0
  317. package/src/bollharness/.claude/agents/review-base.yaml +108 -0
  318. package/src/bollharness/.claude/plugins/boll-mode-toolkit/.claude-plugin/plugin.json +44 -0
  319. package/src/bollharness/.claude/plugins/boll-review-toolkit/.claude-plugin/plugin.json +24 -0
  320. package/src/bollharness/.claude/plugins/boll-review-toolkit/contracts/evidence-packet-schema.json +102 -0
  321. package/src/bollharness/.claude/plugins/boll-review-toolkit/contracts/review-contract.yaml +247 -0
  322. package/src/bollharness/.claude/settings.json +157 -0
  323. package/src/bollharness/.claude/skills/arch/SKILL.md +64 -0
  324. package/src/bollharness/.claude/skills/crystal-learn/SKILL.md +93 -0
  325. package/src/bollharness/.claude/skills/guardian-fixer/PROMPT.md +44 -0
  326. package/src/bollharness/.claude/skills/guardian-fixer/SKILL.md +324 -0
  327. package/src/bollharness/.claude/skills/harness-dev/SKILL.md +93 -0
  328. package/src/bollharness/.claude/skills/harness-dev/examples/README.md +17 -0
  329. package/src/bollharness/.claude/skills/harness-dev-handoff/SKILL.md +165 -0
  330. package/src/bollharness/.claude/skills/harness-eng/SKILL.md +183 -0
  331. package/src/bollharness/.claude/skills/harness-eng-test/SKILL.md +57 -0
  332. package/src/bollharness/.claude/skills/harness-ops/SKILL.md +57 -0
  333. package/src/bollharness/.claude/skills/harness-voice/SKILL.md +84 -0
  334. package/src/bollharness/.claude/skills/lead/INDEX.md +28 -0
  335. package/src/bollharness/.claude/skills/lead/SKILL.md +24 -0
  336. package/src/bollharness/.claude/skills/lead/install-wow-harness.md +77 -0
  337. package/src/bollharness/.claude/skills/lead/ref-review-sop.md +48 -0
  338. package/src/bollharness/.claude/skills/lead/ref-stages.md +58 -0
  339. package/src/bollharness/.claude/skills/plan-lock/SKILL.md +74 -0
  340. package/src/bollharness/.claude/skills/skill-discovery/SKILL.md +120 -0
  341. package/src/bollharness/.claude/skills/task-arch/SKILL.md +106 -0
  342. package/src/bollharness/.claude/skills/toolkit/SKILL.md +57 -0
  343. package/src/bollharness/.claude/skills/toolkit/list.sh +92 -0
  344. package/src/bollharness/.githooks/pre-commit +21 -0
  345. package/src/bollharness/.github/workflows/ci.yml +88 -0
  346. package/src/bollharness/.sanitize-report.json +13 -0
  347. package/src/bollharness/CLAUDE.md +73 -0
  348. package/src/bollharness/LICENSE +21 -0
  349. package/src/bollharness/README.md +143 -0
  350. package/src/bollharness/README.zh-CN.md +131 -0
  351. package/src/bollharness/docs/decisions/ADR-030-guard-signal-protocol-and-governance-reload.md +1076 -0
  352. package/src/bollharness/docs/decisions/ADR-038-harness-optimization-strategy.md +2039 -0
  353. package/src/bollharness/docs/decisions/ADR-041-codex-claude-code-division-of-labor.md +128 -0
  354. package/src/bollharness/docs/decisions/ADR-H1-crystal-learn-revival.md +188 -0
  355. package/src/bollharness/docs/decisions/ADR-H2-identity-isolation.md +183 -0
  356. package/src/bollharness/docs/decisions/ADR-H3-memory-scope.md +133 -0
  357. package/src/bollharness/docs/decisions/ADR-H4-prompt-governance.md +146 -0
  358. package/src/bollharness/docs/decisions/ADR-H5-gate-quantization.md +212 -0
  359. package/src/bollharness/docs/decisions/ADR-H6-state-file-health.md +211 -0
  360. package/src/bollharness/docs/decisions/ADR-H8-issue-and-doc-compliance.md +202 -0
  361. package/src/bollharness/docs/decisions/ADR-H9-mailbox.md +231 -0
  362. package/src/bollharness/docs/decisions/PLAN-H1-crystal-learn-revival.md +270 -0
  363. package/src/bollharness/docs/decisions/PLAN-H2-identity-isolation.md +291 -0
  364. package/src/bollharness/docs/decisions/PLAN-H3-memory-scope.md +228 -0
  365. package/src/bollharness/docs/decisions/PLAN-H4-prompt-governance.md +227 -0
  366. package/src/bollharness/docs/decisions/PLAN-H5-gate-quantization.md +239 -0
  367. package/src/bollharness/docs/decisions/PLAN-H6-state-file-health.md +325 -0
  368. package/src/bollharness/docs/decisions/PLAN-H8-issue-and-doc-compliance.md +242 -0
  369. package/src/bollharness/docs/decisions/PLAN-H9-mailbox.md +378 -0
  370. package/src/bollharness/docs/launch-article-en.md +276 -0
  371. package/src/bollharness/docs/launch-article-zh.md +305 -0
  372. package/src/bollharness/docs/practice.html +356 -0
  373. package/src/bollharness/docs/practice.md +82 -0
  374. package/src/bollharness/docs/research/round-1/README.md +11 -0
  375. package/src/bollharness/docs/research/round-2/README.md +11 -0
  376. package/src/bollharness/docs/research/round-3/README.md +11 -0
  377. package/src/bollharness/docs/research/round-4/README.md +11 -0
  378. package/src/bollharness/docs/research/round-5/README.md +11 -0
  379. package/src/bollharness/docs/research/round-6/README.md +11 -0
  380. package/src/bollharness/package-lock.json +48 -0
  381. package/src/bollharness/package.json +20 -0
  382. package/src/bollharness/reference/SOURCE-COMMIT.txt +3 -0
  383. package/src/bollharness/reference/boll-reference/.claude/rules/backend-routes.md +268 -0
  384. package/src/bollharness/reference/boll-reference/.claude/rules/bridge.md +20 -0
  385. package/src/bollharness/reference/boll-reference/.claude/rules/closure-semantics.md +30 -0
  386. package/src/bollharness/reference/boll-reference/.claude/rules/coaching.md +13 -0
  387. package/src/bollharness/reference/boll-reference/.claude/rules/env-vars.md +50 -0
  388. package/src/bollharness/reference/boll-reference/.claude/rules/hackathon.md +12 -0
  389. package/src/bollharness/reference/boll-reference/.claude/rules/repo-structure.md +184 -0
  390. package/src/bollharness/reference/boll-reference/.claude/rules/review-agent-isolation.md +112 -0
  391. package/src/bollharness/reference/boll-reference/.claude/rules/scenes.md +12 -0
  392. package/src/bollharness/reference/boll-reference/.claude/skills/arch/SKILL.md +551 -0
  393. package/src/bollharness/reference/boll-reference/.claude/skills/boll-animation/SKILL.md +26 -0
  394. package/src/bollharness/reference/boll-reference/.claude/skills/boll-bridge/SKILL.md +227 -0
  395. package/src/bollharness/reference/boll-reference/.claude/skills/boll-bridge/agents/openai.yaml +4 -0
  396. package/src/bollharness/reference/boll-reference/.claude/skills/boll-bridge/references/bridge-failure-taxonomy.md +142 -0
  397. package/src/bollharness/reference/boll-reference/.claude/skills/boll-bridge/references/bridge-validation-ladder.md +107 -0
  398. package/src/bollharness/reference/boll-reference/.claude/skills/boll-crystal/SKILL.md +893 -0
  399. package/src/bollharness/reference/boll-reference/.claude/skills/boll-crystal-learn/SKILL.md +89 -0
  400. package/src/bollharness/reference/boll-reference/.claude/skills/boll-dev/SKILL.md +93 -0
  401. package/src/bollharness/reference/boll-reference/.claude/skills/boll-dev/examples/README.md +209 -0
  402. package/src/bollharness/reference/boll-reference/.claude/skills/boll-dev-handoff/SKILL.md +165 -0
  403. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng/SKILL.md +110 -0
  404. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng-frontend/SKILL.md +203 -0
  405. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng-hdc/SKILL.md +27 -0
  406. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng-orchestrator/SKILL.md +28 -0
  407. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng-prompt/SKILL.md +27 -0
  408. package/src/bollharness/reference/boll-reference/.claude/skills/boll-eng-test/SKILL.md +79 -0
  409. package/src/bollharness/reference/boll-reference/.claude/skills/boll-lab/SKILL.md +372 -0
  410. package/src/bollharness/reference/boll-reference/.claude/skills/boll-run/SKILL.md +437 -0
  411. package/src/bollharness/reference/boll-reference/.claude/skills/boll-ux-appstore/SKILL.md +27 -0
  412. package/src/bollharness/reference/boll-reference/.claude/skills/boll-voice/SKILL.md +442 -0
  413. package/src/bollharness/reference/boll-reference/.claude/skills/guardian-fixer/PROMPT.md +421 -0
  414. package/src/bollharness/reference/boll-reference/.claude/skills/guardian-fixer/SKILL.md +326 -0
  415. package/src/bollharness/reference/boll-reference/.claude/skills/lead/SKILL.md +155 -0
  416. package/src/bollharness/reference/boll-reference/.claude/skills/lead/ref-review-sop.md +91 -0
  417. package/src/bollharness/reference/boll-reference/.claude/skills/lead/ref-stages.md +129 -0
  418. package/src/bollharness/reference/boll-reference/.claude/skills/nature-designer/output/skill-map-preview.png +0 -0
  419. package/src/bollharness/reference/boll-reference/.claude/skills/nature-designer/output/skill-map-v2.png +0 -0
  420. package/src/bollharness/reference/boll-reference/.claude/skills/nature-designer/output/skill-map-v3.png +0 -0
  421. package/src/bollharness/reference/boll-reference/.claude/skills/nature-designer/output/skill-map-v4.png +0 -0
  422. package/src/bollharness/reference/boll-reference/.claude/skills/plan-lock/SKILL.md +425 -0
  423. package/src/bollharness/reference/boll-reference/.claude/skills/plan-lock/ref-three-checks.md +62 -0
  424. package/src/bollharness/reference/boll-reference/.claude/skills/plan-lock/ref-wp-templates.md +78 -0
  425. package/src/bollharness/reference/boll-reference/.claude/skills/task-arch/SKILL.md +76 -0
  426. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-graph/SKILL.md +57 -0
  427. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-graph/beads-graph.sh +153 -0
  428. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-init/SKILL.md +52 -0
  429. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-init/beads-auto-link.sh +76 -0
  430. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-sync/SKILL.md +50 -0
  431. package/src/bollharness/reference/boll-reference/.claude/skills/vibedevteam-sync/beads-sync-proj.sh +108 -0
  432. package/src/bollharness/reference/boll-reference/docs/architecture/AGENT-PROFILE.md +151 -0
  433. package/src/bollharness/reference/boll-reference/docs/architecture/COST-STRUCTURE.md +56 -0
  434. package/src/bollharness/reference/boll-reference/docs/architecture/INDEX.md +76 -0
  435. package/src/bollharness/reference/boll-reference/docs/architecture/MODULE1-INTENT-FIELD.md +116 -0
  436. package/src/bollharness/reference/boll-reference/docs/architecture/MODULE2-CRYSTALLIZATION.md +200 -0
  437. package/src/bollharness/reference/boll-reference/docs/architecture/PRINCIPLES.md +84 -0
  438. package/src/bollharness/reference/boll-reference/docs/architecture/PROTOCOL-CORE.md +209 -0
  439. package/src/bollharness/reference/boll-reference/docs/architecture/VISION.md +181 -0
  440. package/src/bollharness/reference/boll-reference/docs/architecture/discussions/D-01-MARKET-SCENE-PROTOCOL.md +754 -0
  441. package/src/bollharness/reference/boll-reference/scripts/hooks/.sanitize-report.json +12 -0
  442. package/src/bollharness/reference/boll-reference/scripts/hooks/find-boll-root.sh +27 -0
  443. package/src/bollharness/reference/boll-reference/scripts/hooks/precompact.sh +57 -0
  444. package/src/bollharness/reference/boll-reference/scripts/hooks/stop-evaluator.md +57 -0
  445. package/src/bollharness/schemas/metrics-jsonl-allowlist.json +67 -0
  446. package/src/bollharness/scripts/checks/next_decision_number.sh +48 -0
  447. package/src/bollharness/scripts/ci/count-components.sh +65 -0
  448. package/src/bollharness/scripts/context-fragments/artifact-linkage.md +14 -0
  449. package/src/bollharness/scripts/context-fragments/auth-consumers.md +17 -0
  450. package/src/bollharness/scripts/context-fragments/bridge-constitution.md +13 -0
  451. package/src/bollharness/scripts/context-fragments/catalyst-distributed.md +18 -0
  452. package/src/bollharness/scripts/context-fragments/closure-checklist.md +13 -0
  453. package/src/bollharness/scripts/context-fragments/contract-consumers.md +15 -0
  454. package/src/bollharness/scripts/context-fragments/db-shared-structures.md +15 -0
  455. package/src/bollharness/scripts/context-fragments/fixed-three-layers.md +19 -0
  456. package/src/bollharness/scripts/context-fragments/general-dev-principles.md +11 -0
  457. package/src/bollharness/scripts/context-fragments/issue-first.md +8 -0
  458. package/src/bollharness/scripts/context-fragments/mcp-parity.md +16 -0
  459. package/src/bollharness/scripts/context-fragments/pi-agent-operations.md +74 -0
  460. package/src/bollharness/scripts/context-fragments/protocol-consumers.md +15 -0
  461. package/src/bollharness/scripts/context-fragments/run-events-consumers.md +15 -0
  462. package/src/bollharness/scripts/context-fragments/scene-fidelity.md +13 -0
  463. package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +15 -0
  464. package/src/bollharness/scripts/context-fragments/two-language.md +15 -0
  465. package/src/bollharness/scripts/context-fragments/version-sources.md +14 -0
  466. package/src/bollharness/scripts/hooks/find-project-root.sh +47 -0
  467. package/src/bollharness/scripts/hooks/inbox-poll.sh +78 -0
  468. package/src/bollharness/scripts/hooks/precompact.sh +56 -0
  469. package/src/bollharness/scripts/hooks/stop-evaluator.md +83 -0
  470. package/src/bollharness/scripts/sync-from-upstream.sh +281 -0
  471. package/src/bollharness/src/index.ts +5 -0
  472. package/src/bollharness/src/scripts/checks/check_adr_plan_numbering.ts +11 -0
  473. package/src/bollharness/src/scripts/checks/check_api_types.ts +52 -0
  474. package/src/bollharness/src/scripts/checks/check_artifact_link.ts +156 -0
  475. package/src/bollharness/src/scripts/checks/check_bridge_deps.ts +11 -0
  476. package/src/bollharness/src/scripts/checks/check_bugfix_binding.ts +11 -0
  477. package/src/bollharness/src/scripts/checks/check_bugfix_binding_ci.ts +11 -0
  478. package/src/bollharness/src/scripts/checks/check_doc_file_references.ts +11 -0
  479. package/src/bollharness/src/scripts/checks/check_doc_freshness.ts +141 -0
  480. package/src/bollharness/src/scripts/checks/check_doc_links.ts +36 -0
  481. package/src/bollharness/src/scripts/checks/check_file_existence_claims.ts +11 -0
  482. package/src/bollharness/src/scripts/checks/check_fragment_integrity.ts +40 -0
  483. package/src/bollharness/src/scripts/checks/check_hook_installed.ts +70 -0
  484. package/src/bollharness/src/scripts/checks/check_issue_closure.ts +51 -0
  485. package/src/bollharness/src/scripts/checks/check_mcp_parity.ts +11 -0
  486. package/src/bollharness/src/scripts/checks/check_security.ts +54 -0
  487. package/src/bollharness/src/scripts/checks/check_skill_parity.ts +11 -0
  488. package/src/bollharness/src/scripts/checks/check_versions.ts +11 -0
  489. package/src/bollharness/src/scripts/checks/finding.ts +35 -0
  490. package/src/bollharness/src/scripts/checks/next_decision_number.ts +24 -0
  491. package/src/bollharness/src/scripts/checks/regenerate_magic_docs.ts +11 -0
  492. package/src/bollharness/src/scripts/ci/detect_rebaseline_triggers.ts +14 -0
  493. package/src/bollharness/src/scripts/ci/scan_subprocess_cfg.ts +14 -0
  494. package/src/bollharness/src/scripts/ci/scan_verify_artifacts.ts +14 -0
  495. package/src/bollharness/src/scripts/ci/scan_yaml_schema.ts +14 -0
  496. package/src/bollharness/src/scripts/context_router.ts +76 -0
  497. package/src/bollharness/src/scripts/deploy-guard.ts +182 -0
  498. package/src/bollharness/src/scripts/guard-feedback.ts +215 -0
  499. package/src/bollharness/src/scripts/guard_router.ts +194 -0
  500. package/src/bollharness/src/scripts/hooks/_hook_output.js +3 -0
  501. package/src/bollharness/src/scripts/hooks/_hook_output.ts +11 -0
  502. package/src/bollharness/src/scripts/hooks/auto-python3.ts +10 -0
  503. package/src/bollharness/src/scripts/hooks/deploy-progress-on-session-end.ts +10 -0
  504. package/src/bollharness/src/scripts/hooks/failure-analyzer.ts +10 -0
  505. package/src/bollharness/src/scripts/hooks/gate-judgment-inject.ts +111 -0
  506. package/src/bollharness/src/scripts/hooks/gate-transition-judgment.ts +74 -0
  507. package/src/bollharness/src/scripts/hooks/inbox-ack.ts +10 -0
  508. package/src/bollharness/src/scripts/hooks/inbox-inject-on-start.ts +10 -0
  509. package/src/bollharness/src/scripts/hooks/inbox-validate.ts +10 -0
  510. package/src/bollharness/src/scripts/hooks/inbox-write-ledger.ts +10 -0
  511. package/src/bollharness/src/scripts/hooks/initializer-agent.ts +10 -0
  512. package/src/bollharness/src/scripts/hooks/loop-detection.ts +83 -0
  513. package/src/bollharness/src/scripts/hooks/owner-guard.ts +10 -0
  514. package/src/bollharness/src/scripts/hooks/precompact.ts +10 -0
  515. package/src/bollharness/src/scripts/hooks/review-agent-gatekeeper.ts +10 -0
  516. package/src/bollharness/src/scripts/hooks/risk-tracker.ts +121 -0
  517. package/src/bollharness/src/scripts/hooks/sanitize-on-read.ts +10 -0
  518. package/src/bollharness/src/scripts/hooks/session-reflection.ts +12 -0
  519. package/src/bollharness/src/scripts/hooks/session-start-magic-docs.ts +12 -0
  520. package/src/bollharness/src/scripts/hooks/session-start-reset-risk.ts +12 -0
  521. package/src/bollharness/src/scripts/hooks/session-start-toolkit-reminder.ts +12 -0
  522. package/src/bollharness/src/scripts/hooks/stop-evaluator.ts +164 -0
  523. package/src/bollharness/src/scripts/hooks/tool-call-counter.ts +10 -0
  524. package/src/bollharness/src/scripts/hooks/trace-analyzer.ts +14 -0
  525. package/src/bollharness/src/scripts/install/install-trust-token.ts +13 -0
  526. package/src/bollharness/src/scripts/install/multi_project_registry.ts +13 -0
  527. package/src/bollharness/src/scripts/install/phase2_auto.ts +28 -0
  528. package/src/bollharness/src/scripts/install/pre_commit_installer.ts +10 -0
  529. package/src/bollharness/src/scripts/install/tier_selector.ts +10 -0
  530. package/src/bollharness/src/scripts/install/transcript_miner.ts +13 -0
  531. package/src/bollharness/src/scripts/lib/claim_patterns.ts +11 -0
  532. package/src/bollharness/src/scripts/lib/sanitize_patterns.ts +13 -0
  533. package/src/bollharness/src/scripts/sanitize.ts +9 -0
  534. package/src/bollharness/templates/persona/default.json +19 -0
  535. package/src/bollharness/templates/scaffold/.boll/guard/.gitkeep +0 -0
  536. package/src/bollharness/templates/scaffold/.boll/metrics/.gitkeep +0 -0
  537. package/src/bollharness/templates/scaffold/.boll/state/.gitkeep +0 -0
  538. package/src/bollharness/templates/scaffold/.gitignore.append +16 -0
  539. package/src/bollharness/templates/scaffold/CLAUDE.md +89 -0
  540. package/src/bollharness/templates/scaffold/docs/INDEX.md +3 -0
  541. package/src/bollharness/templates/scaffold/docs/decisions/ADR_TEMPLATE.md +38 -0
  542. package/src/bollharness/templates/scaffold/docs/decisions/PLAN_TEMPLATE.md +45 -0
  543. package/src/bollharness/templates/scaffold/docs/decisions/tasks/.gitkeep +2 -0
  544. package/src/bollharness/templates/scaffold/docs/issues/.gitkeep +0 -0
  545. package/src/bollharness/templates/scaffold/docs/issues/GUARD_ISSUE_TEMPLATE.md +35 -0
  546. package/src/bollharness/templates/scaffold/docs/issues/ISSUE_TEMPLATE.md +51 -0
  547. package/src/bollharness/tsconfig.json +26 -0
  548. package/src/bollharness-integration/channel-judgment-engine.ts +634 -0
  549. package/src/bollharness-integration/context-chain-router.ts +474 -0
  550. package/src/bollharness-integration/context-router-judgment.ts +339 -0
  551. package/src/bollharness-integration/context-router.ts +583 -0
  552. package/src/bollharness-integration/gate-state-machine.ts +444 -0
  553. package/src/bollharness-integration/gate-transition-hooks.ts +137 -0
  554. package/src/bollharness-integration/guard-checker.ts +451 -0
  555. package/src/bollharness-integration/index.ts +219 -0
  556. package/src/bollharness-integration/integration.ts +538 -0
  557. package/src/bollharness-integration/judgment-prompts.yaml +535 -0
  558. package/src/bollharness-integration/llm-judgment-engine.ts +712 -0
  559. package/src/bollharness-integration/skill-adapter.ts +646 -0
  560. package/src/cli/interface.ts +211 -0
  561. package/src/constraint-runtime/package-lock.json +48 -0
  562. package/src/constraint-runtime/package.json +34 -0
  563. package/src/constraint-runtime/src/_archive_helper.ts +16 -0
  564. package/src/constraint-runtime/src/agent/coordinator.ts +71 -0
  565. package/src/constraint-runtime/src/agent/index.ts +1 -0
  566. package/src/constraint-runtime/src/assistant/index.ts +15 -0
  567. package/src/constraint-runtime/src/bootstrap/index.ts +15 -0
  568. package/src/constraint-runtime/src/bootstrap_graph.ts +17 -0
  569. package/src/constraint-runtime/src/bridge/index.ts +15 -0
  570. package/src/constraint-runtime/src/buddy/index.ts +15 -0
  571. package/src/constraint-runtime/src/cli/index.ts +15 -0
  572. package/src/constraint-runtime/src/command_graph.ts +20 -0
  573. package/src/constraint-runtime/src/commands.ts +83 -0
  574. package/src/constraint-runtime/src/components/index.ts +15 -0
  575. package/src/constraint-runtime/src/constants/index.ts +15 -0
  576. package/src/constraint-runtime/src/constraint/budget.ts +25 -0
  577. package/src/constraint-runtime/src/constraint/index.ts +3 -0
  578. package/src/constraint-runtime/src/constraint/permission.ts +28 -0
  579. package/src/constraint-runtime/src/context.ts +45 -0
  580. package/src/constraint-runtime/src/coordinator/index.ts +15 -0
  581. package/src/constraint-runtime/src/cost_hook.ts +6 -0
  582. package/src/constraint-runtime/src/cost_tracker.ts +9 -0
  583. package/src/constraint-runtime/src/deferred_init.ts +18 -0
  584. package/src/constraint-runtime/src/direct_modes.ts +13 -0
  585. package/src/constraint-runtime/src/dynamic-tool-loader.ts +115 -0
  586. package/src/constraint-runtime/src/entrypoints/index.ts +15 -0
  587. package/src/constraint-runtime/src/execution_registry.ts +41 -0
  588. package/src/constraint-runtime/src/history.ts +16 -0
  589. package/src/constraint-runtime/src/hooks/index.ts +15 -0
  590. package/src/constraint-runtime/src/index.ts +28 -0
  591. package/src/constraint-runtime/src/ink.ts +4 -0
  592. package/src/constraint-runtime/src/keybindings/index.ts +15 -0
  593. package/src/constraint-runtime/src/memdir/index.ts +15 -0
  594. package/src/constraint-runtime/src/migrations/index.ts +15 -0
  595. package/src/constraint-runtime/src/models.ts +49 -0
  596. package/src/constraint-runtime/src/moreright/index.ts +15 -0
  597. package/src/constraint-runtime/src/native_ts/index.ts +15 -0
  598. package/src/constraint-runtime/src/output_styles/index.ts +15 -0
  599. package/src/constraint-runtime/src/parity_audit.ts +23 -0
  600. package/src/constraint-runtime/src/plugins/index.ts +15 -0
  601. package/src/constraint-runtime/src/port_manifest.ts +20 -0
  602. package/src/constraint-runtime/src/prefetch.ts +17 -0
  603. package/src/constraint-runtime/src/query.ts +7 -0
  604. package/src/constraint-runtime/src/reference_data/archive_surface_snapshot.json +63 -0
  605. package/src/constraint-runtime/src/reference_data/commands_snapshot.json +1037 -0
  606. package/src/constraint-runtime/src/reference_data/subsystems/OpenCLI.json +10 -0
  607. package/src/constraint-runtime/src/reference_data/subsystems/PolymarketSDK.json +12 -0
  608. package/src/constraint-runtime/src/reference_data/subsystems/SafeSDK.json +14 -0
  609. package/src/constraint-runtime/src/reference_data/subsystems/assistant.json +8 -0
  610. package/src/constraint-runtime/src/reference_data/subsystems/bootstrap.json +8 -0
  611. package/src/constraint-runtime/src/reference_data/subsystems/bridge.json +32 -0
  612. package/src/constraint-runtime/src/reference_data/subsystems/buddy.json +13 -0
  613. package/src/constraint-runtime/src/reference_data/subsystems/cli.json +26 -0
  614. package/src/constraint-runtime/src/reference_data/subsystems/components.json +32 -0
  615. package/src/constraint-runtime/src/reference_data/subsystems/constants.json +28 -0
  616. package/src/constraint-runtime/src/reference_data/subsystems/coordinator.json +8 -0
  617. package/src/constraint-runtime/src/reference_data/subsystems/entrypoints.json +15 -0
  618. package/src/constraint-runtime/src/reference_data/subsystems/hooks.json +32 -0
  619. package/src/constraint-runtime/src/reference_data/subsystems/keybindings.json +21 -0
  620. package/src/constraint-runtime/src/reference_data/subsystems/memdir.json +15 -0
  621. package/src/constraint-runtime/src/reference_data/subsystems/migrations.json +18 -0
  622. package/src/constraint-runtime/src/reference_data/subsystems/moreright.json +8 -0
  623. package/src/constraint-runtime/src/reference_data/subsystems/native_ts.json +11 -0
  624. package/src/constraint-runtime/src/reference_data/subsystems/outputStyles.json +8 -0
  625. package/src/constraint-runtime/src/reference_data/subsystems/plugins.json +9 -0
  626. package/src/constraint-runtime/src/reference_data/subsystems/remote.json +11 -0
  627. package/src/constraint-runtime/src/reference_data/subsystems/schemas.json +8 -0
  628. package/src/constraint-runtime/src/reference_data/subsystems/screens.json +10 -0
  629. package/src/constraint-runtime/src/reference_data/subsystems/server.json +10 -0
  630. package/src/constraint-runtime/src/reference_data/subsystems/services.json +32 -0
  631. package/src/constraint-runtime/src/reference_data/subsystems/skills.json +27 -0
  632. package/src/constraint-runtime/src/reference_data/subsystems/state.json +13 -0
  633. package/src/constraint-runtime/src/reference_data/subsystems/types.json +18 -0
  634. package/src/constraint-runtime/src/reference_data/subsystems/upstreamproxy.json +9 -0
  635. package/src/constraint-runtime/src/reference_data/subsystems/utils.json +32 -0
  636. package/src/constraint-runtime/src/reference_data/subsystems/vim.json +12 -0
  637. package/src/constraint-runtime/src/reference_data/subsystems/voice.json +8 -0
  638. package/src/constraint-runtime/src/reference_data/tools_snapshot.json +1042 -0
  639. package/src/constraint-runtime/src/remote/index.ts +15 -0
  640. package/src/constraint-runtime/src/remote_runtime.ts +17 -0
  641. package/src/constraint-runtime/src/runtime/index.ts +1 -0
  642. package/src/constraint-runtime/src/runtime/session.ts +42 -0
  643. package/src/constraint-runtime/src/schemas/index.ts +15 -0
  644. package/src/constraint-runtime/src/screens/index.ts +15 -0
  645. package/src/constraint-runtime/src/server/index.ts +15 -0
  646. package/src/constraint-runtime/src/services/index.ts +15 -0
  647. package/src/constraint-runtime/src/session_store.ts +32 -0
  648. package/src/constraint-runtime/src/setup.ts +50 -0
  649. package/src/constraint-runtime/src/skills/index.ts +1 -0
  650. package/src/constraint-runtime/src/skills/skill-registry.ts +40 -0
  651. package/src/constraint-runtime/src/state/index.ts +15 -0
  652. package/src/constraint-runtime/src/system_init.ts +21 -0
  653. package/src/constraint-runtime/src/thinking/engine.ts +61 -0
  654. package/src/constraint-runtime/src/thinking/index.ts +1 -0
  655. package/src/constraint-runtime/src/tool_pool.ts +20 -0
  656. package/src/constraint-runtime/src/tools/OpenCLI/execAdapter.ts +12 -0
  657. package/src/constraint-runtime/src/tools/OpenCLI/listAdapters.ts +12 -0
  658. package/src/constraint-runtime/src/tools/OpenCLI/runCommand.ts +13 -0
  659. package/src/constraint-runtime/src/tools/PolymarketSDK/cancelOrder.ts +10 -0
  660. package/src/constraint-runtime/src/tools/PolymarketSDK/createOrder.ts +13 -0
  661. package/src/constraint-runtime/src/tools/PolymarketSDK/getMarket.ts +14 -0
  662. package/src/constraint-runtime/src/tools/PolymarketSDK/getOrders.ts +10 -0
  663. package/src/constraint-runtime/src/tools/PolymarketSDK/listMarkets.ts +24 -0
  664. package/src/constraint-runtime/src/tools/SafeSDK/confirmTransaction.ts +13 -0
  665. package/src/constraint-runtime/src/tools/SafeSDK/createTransaction.ts +23 -0
  666. package/src/constraint-runtime/src/tools/SafeSDK/deploySafe.ts +12 -0
  667. package/src/constraint-runtime/src/tools/SafeSDK/executeTransaction.ts +12 -0
  668. package/src/constraint-runtime/src/tools/SafeSDK/getBalance.ts +10 -0
  669. package/src/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.ts +10 -0
  670. package/src/constraint-runtime/src/tools/SafeSDK/proposeTransaction.ts +14 -0
  671. package/src/constraint-runtime/src/tools/WalletTools/autoPay.ts +58 -0
  672. package/src/constraint-runtime/src/tools/WalletTools/createWallet.ts +19 -0
  673. package/src/constraint-runtime/src/tools/WalletTools/getBalance.ts +28 -0
  674. package/src/constraint-runtime/src/tools/WalletTools/importWallet.ts +34 -0
  675. package/src/constraint-runtime/src/tools/WalletTools/sendTransaction.ts +50 -0
  676. package/src/constraint-runtime/src/tools/WalletTools/signMessage.ts +23 -0
  677. package/src/constraint-runtime/src/tools/WalletTools/transferToken.ts +49 -0
  678. package/src/constraint-runtime/src/tools.ts +100 -0
  679. package/src/constraint-runtime/src/transcript.ts +23 -0
  680. package/src/constraint-runtime/src/types/index.ts +15 -0
  681. package/src/constraint-runtime/src/upstream_proxy/index.ts +15 -0
  682. package/src/constraint-runtime/src/utils/index.ts +15 -0
  683. package/src/constraint-runtime/src/vim/index.ts +15 -0
  684. package/src/constraint-runtime/src/voice/index.ts +15 -0
  685. package/src/constraint-runtime/tests/agent.test.ts +20 -0
  686. package/src/constraint-runtime/tests/constraint.test.ts +47 -0
  687. package/src/constraint-runtime/tests/skill.test.ts +23 -0
  688. package/src/constraint-runtime/tests/thinking.test.ts +28 -0
  689. package/src/constraint-runtime/tsconfig.json +13 -0
  690. package/src/constraints/index.ts +6 -0
  691. package/src/documents/reader.ts +80 -0
  692. package/src/electron-preload.ts +25 -0
  693. package/src/electron.ts +200 -0
  694. package/src/index.ts +1606 -0
  695. package/src/llm/config-store.ts +312 -0
  696. package/src/llm/llm-judgment-client.ts +470 -0
  697. package/src/llm/pi-ai.ts +522 -0
  698. package/src/network/agent-network.ts +800 -0
  699. package/src/network/hybrid-messenger.ts +199 -0
  700. package/src/network/iroh-bootstrap.ts +57 -0
  701. package/src/network/iroh-discovery.ts +207 -0
  702. package/src/network/iroh-integration.ts +158 -0
  703. package/src/network/iroh-transport.ts +594 -0
  704. package/src/network/p2p.ts +963 -0
  705. package/src/network/storage/adapters/json-adapter.ts +439 -0
  706. package/src/network/storage/index.ts +187 -0
  707. package/src/network/storage/types.ts +166 -0
  708. package/src/pi-ecosystem/index.ts +453 -0
  709. package/src/pi-ecosystem-colony/index.ts +482 -0
  710. package/src/pi-ecosystem-goals/index.ts +585 -0
  711. package/src/pi-ecosystem-judgment/decision.ts +431 -0
  712. package/src/pi-ecosystem-judgment/distillation.ts +398 -0
  713. package/src/pi-ecosystem-judgment/human-value-store.ts +580 -0
  714. package/src/pi-ecosystem-judgment/index.ts +678 -0
  715. package/src/pi-ecosystem-judgment/value-injection.ts +744 -0
  716. package/src/pi-ecosystem-mcp/index.ts +427 -0
  717. package/src/pi-ecosystem-subagents/index.ts +408 -0
  718. package/src/social/ant-colony/AdaptiveHeartbeat.ts +131 -0
  719. package/src/social/ant-colony/PheromoneEngine.ts +302 -0
  720. package/src/social/ant-colony/index.ts +18 -0
  721. package/src/social/ant-colony/types.ts +94 -0
  722. package/src/social/channels/ChannelManager.ts +485 -0
  723. package/src/social/channels/DiapChannelBridge.ts +501 -0
  724. package/src/social/channels/InterestMatcher.ts +189 -0
  725. package/src/social/channels/agent-workflow-config.json +214 -0
  726. package/src/social/channels/agent-workflow-config.yaml +334 -0
  727. package/src/social/channels/channel-agent-session.ts +407 -0
  728. package/src/social/channels/channel-heartbeat-agent.ts +622 -0
  729. package/src/social/channels/diap-doc-parser.ts +282 -0
  730. package/src/social/channels/harness-workflow-integrator.ts +594 -0
  731. package/src/social/channels/index.ts +22 -0
  732. package/src/social/channels/types.ts +115 -0
  733. package/src/social/global-shared-context.ts +506 -0
  734. package/src/social/heartbeat.ts +1041 -0
  735. package/src/social/persona/enhanced-persona.ts +359 -0
  736. package/src/test/ai-judgment-test.ts +92 -0
  737. package/src/test/bollharness-integration.test.ts +398 -0
  738. package/src/test/channel-agent-multi-dialogue.ts +265 -0
  739. package/src/test/channel-heartbeat-agent-test.ts +244 -0
  740. package/src/test/constraint-layer.test.ts +191 -0
  741. package/src/test/diap-identity-test.ts +222 -0
  742. package/src/test/diap-quick-test.ts +73 -0
  743. package/src/test/global-shared-context.test.ts +393 -0
  744. package/src/test/harness-judgment-injection.test.ts +353 -0
  745. package/src/test/harness-workflow-integrator-test.ts +285 -0
  746. package/src/test/human-value-store.test.ts +316 -0
  747. package/src/test/hybrid-integration-test.ts +126 -0
  748. package/src/test/hybrid-messenger-verify.ts +68 -0
  749. package/src/test/iroh-bistream-debug.ts +50 -0
  750. package/src/test/iroh-communication.test.ts +81 -0
  751. package/src/test/iroh-debug-test.ts +69 -0
  752. package/src/test/iroh-diap-test.ts +90 -0
  753. package/src/test/iroh-direct-connect.ts +65 -0
  754. package/src/test/iroh-e2e-fixed.ts +106 -0
  755. package/src/test/iroh-e2e-same-process.ts +83 -0
  756. package/src/test/iroh-e2e.ts +83 -0
  757. package/src/test/iroh-final-e2e.ts +84 -0
  758. package/src/test/iroh-relay-test.ts +46 -0
  759. package/src/test/iroh-simple-test.ts +49 -0
  760. package/src/test/iroh-transport-verify.ts +60 -0
  761. package/src/test/iroh-transport.test.ts +47 -0
  762. package/src/test/iroh-two-nodes.ts +87 -0
  763. package/src/test/iroh-verify.ts +55 -0
  764. package/src/test/judgment-decision.test.ts +373 -0
  765. package/src/test/llm-judgment-integration.test.ts +257 -0
  766. package/src/test/p2p-agent-complex-dialogue.ts +490 -0
  767. package/src/test/p2p-agent-dialogue.ts +423 -0
  768. package/src/test/p2p-agent-full-bidirectional.ts +686 -0
  769. package/src/test/p2p-agent-harness-flow.ts +562 -0
  770. package/src/test/p2p-agent-harness-single.ts +175 -0
  771. package/src/test/p2p-ai-dialogue-test.ts +374 -0
  772. package/src/test/p2p-cid-connect-test.ts +245 -0
  773. package/src/test/p2p-connect-receiver.ts +85 -0
  774. package/src/test/p2p-iroh-test.ts +214 -0
  775. package/src/test/p2p-minimal-test.ts +264 -0
  776. package/src/test/p2p-node-1.ts +172 -0
  777. package/src/test/p2p-node-2.ts +172 -0
  778. package/src/test/p2p-server.ts +335 -0
  779. package/src/test/p2p-two-nodes-test.ts +542 -0
  780. package/src/test/pi-sdk.test.ts +47 -0
  781. package/src/test/set-persona.ts +56 -0
  782. package/src/test/simple.test.ts +11 -0
  783. package/src/test/storage-integration.test.ts +191 -0
  784. package/src/test/subagent-manager.test.ts +392 -0
  785. package/src/test/test-gate-flow.test.ts +92 -0
  786. package/src/test/workflow-engine.test.ts +101 -0
  787. package/src/web/api-config.html +265 -0
  788. package/src/web/client.js +1401 -0
  789. package/src/web/components/p2p/P2PModal.tsx +328 -0
  790. package/src/web/components/p2p/index.ts +404 -0
  791. package/src/web/components/p2p/index.tsx +297 -0
  792. package/src/web/components/p2p/p2p-connection.ts +186 -0
  793. package/src/web/components/p2p/p2p-identity.ts +92 -0
  794. package/src/web/components/p2p/p2p-manager.ts +109 -0
  795. package/src/web/components/p2p/p2p-messages.ts +219 -0
  796. package/src/web/components/p2p/p2p-modal.ts +685 -0
  797. package/src/web/components/p2p/p2p-store-memory.ts +162 -0
  798. package/src/web/components/p2p/types.ts +112 -0
  799. package/src/web/design.md +99 -0
  800. package/src/web/index.html +192 -0
  801. package/src/web/server.ts +1878 -0
  802. package/src/web/style.css +3260 -0
  803. package/src/workflows/collaboration.ts +455 -0
  804. package/src/workflows/index.ts +64 -0
  805. package/tsconfig.electron.json +20 -0
  806. package/tsconfig.json +19 -0
  807. package/vitest.config.ts +12 -0
  808. package//346/203/263/346/263/225.md +79 -0
@@ -0,0 +1,1647 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createWebServer = createWebServer;
40
+ exports.bootstrapIdentity = bootstrapIdentity;
41
+ exports.publishDIDBackground = publishDIDBackground;
42
+ exports.bootstrapP2P = bootstrapP2P;
43
+ exports.openBrowser = openBrowser;
44
+ const express_1 = __importDefault(require("express"));
45
+ const http_1 = require("http");
46
+ const path_1 = require("path");
47
+ const fs = __importStar(require("fs/promises"));
48
+ const path = __importStar(require("path"));
49
+ const sdk_1 = require("@diap/sdk");
50
+ const reader_js_1 = require("../documents/reader.js");
51
+ const index_js_1 = require("../constraints/index.js");
52
+ const pi_sdk_js_1 = require("../agents/pi-sdk.js");
53
+ const config_store_js_1 = require("../llm/config-store.js");
54
+ const iroh_transport_js_1 = require("../network/iroh-transport.js");
55
+ // 前端资源路径:在打包后会通过 CommonJS require 加载,使用全局 __dirname
56
+ // @ts-ignore - __dirname is available in CommonJS
57
+ const webRoot = path.join(__dirname, '..', '..', 'dist', 'web');
58
+ const SHARED_SESSION_PATH = path.join(process.env.HOME || '/tmp', '.bolloon', 'sessions');
59
+ const SESSION_CACHE_PATH = path.join(SHARED_SESSION_PATH, 'cache');
60
+ const CHANNELS_PATH = path.join(SHARED_SESSION_PATH, 'channels.json');
61
+ const THEME_PATH = path.join(SHARED_SESSION_PATH, 'theme.json');
62
+ const IPFS_ENDPOINT = 'http://127.0.0.1:5001';
63
+ let irohNodeInfo = null;
64
+ let irohInitialized = false;
65
+ async function ensureSessionDirs() {
66
+ await fs.mkdir(SESSION_CACHE_PATH, { recursive: true });
67
+ }
68
+ async function loadChannels() {
69
+ try {
70
+ const data = await fs.readFile(CHANNELS_PATH, 'utf-8');
71
+ return JSON.parse(data);
72
+ }
73
+ catch {
74
+ return [];
75
+ }
76
+ }
77
+ async function saveChannels(channels) {
78
+ const jsonStr = JSON.stringify(channels, null, 2);
79
+ console.log('[saveChannels] 保存频道数据, 数量:', channels.length);
80
+ console.log('[saveChannels] JSON 长度:', jsonStr.length);
81
+ await fs.writeFile(CHANNELS_PATH, jsonStr);
82
+ // 验证保存的内容
83
+ const verifyData = await fs.readFile(CHANNELS_PATH, 'utf-8');
84
+ const verifyChannels = JSON.parse(verifyData);
85
+ console.log('[saveChannels] 验证 - 保存了', verifyChannels.length, '个频道');
86
+ verifyChannels.forEach((ch, i) => {
87
+ console.log(` [${i}] ${ch.name}: did=${ch.did || '无'}`);
88
+ });
89
+ }
90
+ async function loadSession(channelId) {
91
+ const sessionPath = path.join(SESSION_CACHE_PATH, `${channelId}.json`);
92
+ try {
93
+ const data = await fs.readFile(sessionPath, 'utf-8');
94
+ return JSON.parse(data);
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ async function saveSession(session) {
101
+ const sessionPath = path.join(SESSION_CACHE_PATH, `${session.channelId}.json`);
102
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
103
+ }
104
+ async function loadTheme() {
105
+ try {
106
+ const data = await fs.readFile(THEME_PATH, 'utf-8');
107
+ return JSON.parse(data);
108
+ }
109
+ catch {
110
+ return { theme: 'light', agentId: '' };
111
+ }
112
+ }
113
+ async function saveTheme(theme, agentId) {
114
+ await fs.writeFile(THEME_PATH, JSON.stringify({ theme, agentId }, null, 2));
115
+ }
116
+ // ==================== Task Queue & Workflow System ====================
117
+ const TASK_QUEUE_PATH = path.join(SHARED_SESSION_PATH, 'task-queue.json');
118
+ const WORKFLOW_STATE_PATH = path.join(SHARED_SESSION_PATH, 'workflow-state.json');
119
+ async function loadTaskQueue() {
120
+ try {
121
+ const data = await fs.readFile(TASK_QUEUE_PATH, 'utf-8');
122
+ return JSON.parse(data);
123
+ }
124
+ catch {
125
+ return [];
126
+ }
127
+ }
128
+ async function saveTaskQueue(tasks) {
129
+ await fs.writeFile(TASK_QUEUE_PATH, JSON.stringify(tasks, null, 2));
130
+ }
131
+ async function loadWorkflowState(channelId) {
132
+ try {
133
+ const data = await fs.readFile(WORKFLOW_STATE_PATH, 'utf-8');
134
+ const states = JSON.parse(data);
135
+ return states.find(s => s.channelId === channelId) || null;
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ }
141
+ async function saveWorkflowState(state) {
142
+ try {
143
+ const data = await fs.readFile(WORKFLOW_STATE_PATH, 'utf-8');
144
+ const states = JSON.parse(data);
145
+ const index = states.findIndex(s => s.channelId === state.channelId);
146
+ if (index >= 0) {
147
+ states[index] = state;
148
+ }
149
+ else {
150
+ states.push(state);
151
+ }
152
+ await fs.writeFile(WORKFLOW_STATE_PATH, JSON.stringify(states, null, 2));
153
+ }
154
+ catch {
155
+ await fs.writeFile(WORKFLOW_STATE_PATH, JSON.stringify([state], null, 2));
156
+ }
157
+ }
158
+ let isExecutingTask = false;
159
+ let executionTaskId = null;
160
+ async function executeTask(task, channelId) {
161
+ if (isExecutingTask)
162
+ return;
163
+ isExecutingTask = true;
164
+ executionTaskId = task.id;
165
+ const agent = await getAgentForChannel(channelId);
166
+ const tasks = await loadTaskQueue();
167
+ const taskIndex = tasks.findIndex(t => t.id === task.id);
168
+ if (taskIndex >= 0) {
169
+ tasks[taskIndex].status = 'running';
170
+ tasks[taskIndex].updatedAt = new Date().toISOString();
171
+ await saveTaskQueue(tasks);
172
+ }
173
+ broadcast({ type: 'task_status', taskId: task.id, status: 'running', progress: 0 }, channelId);
174
+ try {
175
+ let result = '';
176
+ switch (task.type) {
177
+ case 'chat':
178
+ if (task.description) {
179
+ broadcast({ type: 'status', content: `执行任务: ${task.title}` }, channelId);
180
+ result = await agent.prompt(task.description);
181
+ }
182
+ break;
183
+ case 'read':
184
+ if (task.description) {
185
+ broadcast({ type: 'status', content: `读取文档: ${task.description}` }, channelId);
186
+ const content = await reader_js_1.documentReader.read(task.description);
187
+ result = `📄 文档读取完成\n\n${content.text.substring(0, 500)}${content.text.length > 500 ? '...' : ''}`;
188
+ }
189
+ break;
190
+ case 'summarize':
191
+ if (task.description) {
192
+ broadcast({ type: 'status', content: `总结文档: ${task.description}` }, channelId);
193
+ const content = await reader_js_1.documentReader.read(task.description);
194
+ const llm = (0, index_js_1.getMinimax)();
195
+ const summary = await llm.summarize(content.text);
196
+ result = `📝 文档总结:\n\n${summary.summary}`;
197
+ }
198
+ break;
199
+ case 'workflow':
200
+ // 执行多步骤工作流
201
+ if (task.steps && task.steps.length > 0) {
202
+ let loopCount = 0;
203
+ for (let i = 0; i < task.steps.length; i++) {
204
+ // 广播循环开始
205
+ loopCount++;
206
+ broadcast({ type: 'workflow_loop', loopCount, content: `开始步骤 ${i + 1}/${task.steps.length}: ${task.steps[i].name}` }, channelId);
207
+ task.steps[i].status = 'running';
208
+ broadcast({ type: 'task_status', taskId: task.id, status: 'running', currentStep: i, totalSteps: task.steps.length }, channelId);
209
+ broadcast({ type: 'workflow_step', step: `步骤 ${i + 1}`, content: `执行中: ${task.steps[i].name}` }, channelId);
210
+ // 执行步骤 - 模拟流式输出
211
+ for (let j = 0; j < 3; j++) {
212
+ await new Promise(resolve => setTimeout(resolve, 300));
213
+ broadcast({ type: 'workflow_step', step: `步骤 ${i + 1}`, content: `执行中... (${(j + 1) * 33}%)` }, channelId);
214
+ }
215
+ task.steps[i].status = 'completed';
216
+ task.progress = Math.round(((i + 1) / task.steps.length) * 100);
217
+ broadcast({ type: 'workflow_step', step: `步骤 ${i + 1}`, content: `✅ 完成: ${task.steps[i].name}` }, channelId);
218
+ broadcast({ type: 'workflow_loop', loopCount, status: 'completed', content: `步骤 ${i + 1} 完成` }, channelId);
219
+ broadcast({ type: 'task_status', taskId: task.id, progress: task.progress }, channelId);
220
+ }
221
+ result = '✅ 工作流执行完成';
222
+ broadcast({ type: 'workflow_loop', loopCount, status: 'finished', content: result }, channelId);
223
+ }
224
+ break;
225
+ default:
226
+ result = '未知任务类型';
227
+ }
228
+ // 更新任务状态
229
+ const tasks = await loadTaskQueue();
230
+ const idx = tasks.findIndex(t => t.id === task.id);
231
+ if (idx >= 0) {
232
+ tasks[idx].status = 'completed';
233
+ tasks[idx].progress = 100;
234
+ tasks[idx].result = result;
235
+ tasks[idx].updatedAt = new Date().toISOString();
236
+ await saveTaskQueue(tasks);
237
+ }
238
+ broadcast({ type: 'task_status', taskId: task.id, status: 'completed', progress: 100, result }, channelId);
239
+ broadcast({ type: 'ai', content: result }, channelId);
240
+ }
241
+ catch (error) {
242
+ const tasks = await loadTaskQueue();
243
+ const idx = tasks.findIndex(t => t.id === task.id);
244
+ if (idx >= 0) {
245
+ tasks[idx].status = 'failed';
246
+ tasks[idx].error = error.message;
247
+ tasks[idx].updatedAt = new Date().toISOString();
248
+ await saveTaskQueue(tasks);
249
+ }
250
+ broadcast({ type: 'task_status', taskId: task.id, status: 'failed', error: error.message }, channelId);
251
+ broadcast({ type: 'error', content: `任务执行失败: ${error.message}` }, channelId);
252
+ }
253
+ isExecutingTask = false;
254
+ executionTaskId = null;
255
+ }
256
+ let sseClients = new Set();
257
+ let channelSessions = new Map();
258
+ async function getAgentForChannel(channelId, channelDid, channelName, channelDidDoc) {
259
+ const existingSession = channelSessions.get(channelId);
260
+ // 如果已有 session,检查是否需要更新 identity
261
+ if (existingSession) {
262
+ const currentIdentity = existingSession.getIdentity();
263
+ // 如果当前 identity 没有真实 DID,或者 DID 与频道的 DID 不匹配,需要重建
264
+ let needsUpdate = !currentIdentity.did.startsWith('did:pi:') ||
265
+ (channelDid && !currentIdentity.did.includes(channelId));
266
+ if (!needsUpdate && channelDid && currentIdentity.did !== channelDid) {
267
+ needsUpdate = true;
268
+ }
269
+ if (needsUpdate && channelDid) {
270
+ // 更新现有 session 的 identity
271
+ existingSession.updateIdentity({
272
+ did: channelDid,
273
+ name: channelName || `Channel-${channelId.slice(-6)}`,
274
+ publicKey: '',
275
+ createdAt: Date.now(),
276
+ cid: channelDidDoc?.cid,
277
+ ipnsName: channelDidDoc?.ipnsName
278
+ });
279
+ console.log(`[Agent] 频道 ${channelId} 身份更新: DID = ${channelDid}`);
280
+ }
281
+ return existingSession;
282
+ }
283
+ // 构建频道的身份文档
284
+ const identityDoc = channelDid ? {
285
+ did: channelDid,
286
+ name: channelName || `Channel-${channelId.slice(-6)}`,
287
+ publicKey: '',
288
+ createdAt: Date.now(),
289
+ cid: channelDidDoc?.cid,
290
+ ipnsName: channelDidDoc?.ipnsName
291
+ } : undefined;
292
+ const session = await (0, pi_sdk_js_1.createAgentSession)({
293
+ cwd: process.cwd(),
294
+ peerId: `channel-${channelId}`,
295
+ identityDoc
296
+ });
297
+ channelSessions.set(channelId, session);
298
+ if (channelDid) {
299
+ console.log(`[Agent] 新建频道 ${channelId} session, DID = ${channelDid}, CID = ${channelDidDoc?.cid || '无'}`);
300
+ }
301
+ else {
302
+ console.log(`[Agent] 新建频道 ${channelId} session, 使用默认身份`);
303
+ }
304
+ return session;
305
+ }
306
+ async function createWebServer(port = 3000) {
307
+ // 防止 P2P DHT 超时等错误导致进程崩溃
308
+ process.on('unhandledRejection', (reason, promise) => {
309
+ console.error('[警告] 未处理的 Promise 拒绝:', reason);
310
+ });
311
+ // 重置旧的 agent session,确保使用新的 LLM 配置
312
+ const { resetAgentSession } = await Promise.resolve().then(() => __importStar(require('../agents/pi-sdk.js')));
313
+ resetAgentSession();
314
+ // 初始化 LLM(从配置文件读取 MiniMax 配置)
315
+ (0, index_js_1.initMinimax)();
316
+ // ==================== P2P DIAP 身份初始化 ====================
317
+ let p2pIdentity = {
318
+ did: '',
319
+ name: '',
320
+ publicKey: '',
321
+ keypair: null
322
+ };
323
+ let p2pCommunicator = null;
324
+ try {
325
+ console.log('开始生成 P2P 身份...');
326
+ // 生成 DIAP 身份
327
+ const kp = sdk_1.KeyManager.generate();
328
+ console.log('KeyManager.generate() 完成, kp:', !!kp, 'kp.did:', kp?.did);
329
+ console.log('kp.publicKey:', kp?.publicKey);
330
+ const did = kp.did || 'did:unknown:123456';
331
+ console.log(`DID: ${did}`);
332
+ const username = 'web-user';
333
+ const suffix = did?.split(':').pop()?.substring(0, 4) || 'xxxx';
334
+ const name = `blln-${username}-${suffix}`;
335
+ p2pIdentity = {
336
+ did: did || '',
337
+ name,
338
+ publicKey: Buffer.from(kp.publicKey).toString('hex'),
339
+ keypair: kp
340
+ };
341
+ console.log(`P2P 身份已生成: ${p2pIdentity.did}`);
342
+ // 尝试发布 DID 到 IPFS
343
+ try {
344
+ const auth = await sdk_1.AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
345
+ await auth.registerAgent({ name, services: [] }, kp, '');
346
+ console.log('P2P DID 已发布到 IPFS');
347
+ }
348
+ catch (e) {
349
+ console.log('P2P DID 本地模式运行');
350
+ }
351
+ // 初始化 P2P 通信器
352
+ try {
353
+ const rawSeed = crypto.getRandomValues(new Uint8Array(32));
354
+ p2pCommunicator = (0, sdk_1.createHyperswarmCommunicator)({
355
+ server: true,
356
+ client: true,
357
+ autoConnect: true,
358
+ maxConnections: 50,
359
+ seed: rawSeed
360
+ });
361
+ p2pCommunicator.on('connection', (conn) => {
362
+ console.log(`P2P 连接: ${conn.publicKey.substring(0, 8)}...`);
363
+ });
364
+ p2pCommunicator.on('message', async (msg, conn) => {
365
+ const content = new TextDecoder().decode(msg.content);
366
+ console.log(`P2P 收到消息: ${content.substring(0, 50)}...`);
367
+ // 可以在这里处理接收到的消息
368
+ broadcast({ type: 'p2p_message', from: conn.publicKey.substring(0, 8), content }, undefined);
369
+ });
370
+ await p2pCommunicator.start();
371
+ const topic = (0, sdk_1.createTopic)('bolloon-agent-harness');
372
+ await p2pCommunicator.joinTopic(topic);
373
+ console.log(`P2P 网络已就绪`);
374
+ }
375
+ catch (e) {
376
+ console.log(`P2P 网络初始化失败: ${e.message}`);
377
+ }
378
+ }
379
+ catch (e) {
380
+ console.log(`P2P 身份初始化失败: ${e.message}`);
381
+ }
382
+ const app = (0, express_1.default)();
383
+ const server = (0, http_1.createServer)(app);
384
+ await ensureSessionDirs();
385
+ app.use(express_1.default.json());
386
+ app.use((req, res, next) => {
387
+ res.setHeader('Access-Control-Allow-Origin', '*');
388
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
389
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
390
+ if (req.method === 'OPTIONS') {
391
+ return res.status(200).end();
392
+ }
393
+ next();
394
+ });
395
+ app.use(express_1.default.static(webRoot));
396
+ app.get('/', (req, res) => {
397
+ res.sendFile((0, path_1.join)(webRoot, 'index.html'));
398
+ });
399
+ app.get('/api-config', (req, res) => {
400
+ res.sendFile((0, path_1.join)(webRoot, 'api-config.html'));
401
+ });
402
+ app.get('/events', (req, res) => {
403
+ const channelId = req.query.channelId;
404
+ res.setHeader('Content-Type', 'text/event-stream');
405
+ res.setHeader('Cache-Control', 'no-cache');
406
+ res.setHeader('Connection', 'keep-alive');
407
+ res.flushHeaders();
408
+ const clientInfo = { res, channelId };
409
+ sseClients.add(clientInfo);
410
+ req.on('close', () => {
411
+ sseClients.delete(clientInfo);
412
+ });
413
+ });
414
+ app.post('/message', async (req, res) => {
415
+ const { text, channelId, channelDid } = req.body;
416
+ if (!text) {
417
+ return res.status(400).json({ error: 'No text provided' });
418
+ }
419
+ if (!channelId) {
420
+ return res.status(400).json({ error: 'No channelId provided' });
421
+ }
422
+ // 获取频道信息,包括真实 DID 和完整 DID 文档
423
+ const channels = await loadChannels();
424
+ const channel = channels.find(c => c.id === channelId);
425
+ const realChannelDid = channelDid || channel?.did || '';
426
+ const realChannelName = channel?.name || '';
427
+ const realChannelDidDoc = channel?.didDocument;
428
+ broadcast({ type: 'user', content: text }, channelId);
429
+ try {
430
+ const agent = await getAgentForChannel(channelId, realChannelDid, realChannelName, realChannelDidDoc);
431
+ let fullResponse = '';
432
+ const streamCallback = (event) => {
433
+ // 同时发送给流式显示和工作流显示
434
+ if (event.type === 'token' || event.type === 'thinking') {
435
+ broadcast({ type: 'stream', streamType: event.type, content: event.content }, channelId);
436
+ // 同时作为 workflow_step 显示(用于动态 loop 循环)
437
+ if (event.content) {
438
+ broadcast({ type: 'workflow_step', step: 'AI 思考', content: event.content.substring(0, 100) }, channelId);
439
+ }
440
+ }
441
+ else if (event.type === 'status' || event.type === 'tool') {
442
+ broadcast({ type: 'status', tool: event.tool, content: event.content }, channelId);
443
+ broadcast({ type: 'workflow_step', step: event.tool || '状态', content: event.content }, channelId);
444
+ }
445
+ else if (event.type === 'error') {
446
+ broadcast({ type: 'error', content: event.content }, channelId);
447
+ }
448
+ };
449
+ // 将真实 DID 作为上下文前缀,让 AI 使用真实的 DID 而不是自己编造的
450
+ const contextHint = realChannelDid ? `[系统上下文] 当前频道名称: ${realChannelName}, 你的真实 DID: ${realChannelDid}\n\n` : '';
451
+ fullResponse = await agent.promptStream(contextHint + text, streamCallback);
452
+ broadcast({ type: 'ai', content: fullResponse }, channelId);
453
+ const existingSession = await loadSession(channelId);
454
+ const session = existingSession || { channelId, messages: [], lastUpdated: new Date().toISOString() };
455
+ session.messages.push({ id: crypto.randomUUID(), type: 'user', content: text, timestamp: new Date().toISOString() });
456
+ session.messages.push({ id: crypto.randomUUID(), type: 'ai', content: fullResponse, timestamp: new Date().toISOString() });
457
+ session.lastUpdated = new Date().toISOString();
458
+ await saveSession(session);
459
+ const channels = await loadChannels();
460
+ const channel = channels.find(c => c.id === channelId);
461
+ if (channel && channel.name === '智能体') {
462
+ const renameSuggestion = await agent.suggestRename(session.messages);
463
+ if (renameSuggestion) {
464
+ channel.name = renameSuggestion;
465
+ await saveChannels(channels);
466
+ broadcast({ type: 'renamed', channelId, newName: renameSuggestion }, channelId);
467
+ }
468
+ }
469
+ if (channel) {
470
+ channel.updatedAt = new Date().toISOString();
471
+ await saveChannels(channels);
472
+ }
473
+ broadcast({ type: 'done' }, channelId);
474
+ res.json({ ok: true });
475
+ }
476
+ catch (err) {
477
+ broadcast({ type: 'error', content: err.message }, channelId);
478
+ broadcast({ type: 'done' }, channelId);
479
+ res.status(500).json({ error: err.message });
480
+ }
481
+ });
482
+ // 获取频道并确保每个频道都有 DID
483
+ async function getChannelsWithDID() {
484
+ const channels = await loadChannels();
485
+ console.log(`[getChannelsWithDID] 加载了 ${channels.length} 个频道`);
486
+ let changed = false;
487
+ for (const channel of channels) {
488
+ // 检查 DID 是否有效
489
+ const didMissing = channel.did === undefined || channel.did === null || channel.did === 'undefined' || channel.did === 'null' || channel.did === '';
490
+ console.log(`[getChannelsWithDID] 频道 ${channel.name}: did=${JSON.stringify(channel.did)}, 缺失=${didMissing}`);
491
+ if (didMissing) {
492
+ console.log(`[修复频道] ${channel.name} (${channel.id}) 缺少 DID,正在生成...`);
493
+ try {
494
+ const kp = sdk_1.KeyManager.generate();
495
+ const generatedDid = kp.did;
496
+ console.log(`[修复频道] KeyManager.generate() 结果: kp=${!!kp}, did=${generatedDid}`);
497
+ if (generatedDid && typeof generatedDid === 'string' && generatedDid.length > 0) {
498
+ channel.did = generatedDid;
499
+ channel.publicKey = Buffer.from(kp.publicKey).toString('hex');
500
+ console.log(`[修复频道] ${channel.name} 生成了 DID: ${channel.did}`);
501
+ // 发布到 IPFS 并保存完整 DID 文档
502
+ try {
503
+ const auth = await sdk_1.AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
504
+ const result = await auth.registerAgent({ name: channel.name, services: [] }, kp, '');
505
+ channel.cid = result.cid || '';
506
+ // 保存完整 DID 文档(用于传递给 session)
507
+ if (result.didDocument) {
508
+ channel.didDocument = result.didDocument;
509
+ }
510
+ console.log(`[修复频道] ${channel.name} CID: ${channel.cid}`);
511
+ }
512
+ catch (ipfsErr) {
513
+ console.log(`[修复频道] ${channel.name} IPFS 失败`);
514
+ }
515
+ }
516
+ else {
517
+ console.log(`[修复频道] ${channel.name} KeyManager 返回无效 DID`);
518
+ channel.did = `did:web:${channel.id}`;
519
+ channel.publicKey = `pk_${channel.id}`;
520
+ }
521
+ changed = true;
522
+ }
523
+ catch (e) {
524
+ console.log(`[修复频道] ${channel.name} 失败: ${e}`);
525
+ }
526
+ }
527
+ }
528
+ if (changed) {
529
+ console.log('[getChannelsWithDID] 保存修改后的频道');
530
+ await saveChannels(channels);
531
+ }
532
+ return channels;
533
+ }
534
+ app.get('/channels', async (_req, res) => {
535
+ try {
536
+ console.log('[API] /channels 被调用');
537
+ const channels = await getChannelsWithDID();
538
+ console.log('[获取频道] 返回', channels.length, '个');
539
+ channels.forEach((ch, i) => {
540
+ console.log(` [${i}] ${ch.name} - did: ${ch.did || '无'} - cid: ${ch.cid || '无'}`);
541
+ });
542
+ res.json(channels);
543
+ }
544
+ catch (err) {
545
+ console.error('[API] /channels 错误:', err);
546
+ res.status(500).json({ error: err.message });
547
+ }
548
+ });
549
+ app.post('/channels', async (req, res) => {
550
+ try {
551
+ const { name, agentId } = req.body;
552
+ console.log(`[创建频道] 收到请求: name=${name}, agentId=${agentId}`);
553
+ if (!name || !agentId) {
554
+ return res.status(400).json({ error: 'name and agentId required' });
555
+ }
556
+ const channels = await loadChannels();
557
+ const id = `ch_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
558
+ // 先创建频道(不阻塞等待 DID 生成)
559
+ const channel = {
560
+ id,
561
+ name,
562
+ agentId,
563
+ createdAt: new Date().toISOString(),
564
+ updatedAt: new Date().toISOString(),
565
+ };
566
+ console.log(`[创建频道] 先保存频道 ID: ${id}`);
567
+ channels.push(channel);
568
+ await saveChannels(channels);
569
+ await saveSession({ channelId: id, messages: [], lastUpdated: new Date().toISOString() });
570
+ res.json(channel);
571
+ // 后台生成 DID
572
+ console.log(`[创建频道] 后台生成 DID...`);
573
+ setTimeout(async () => {
574
+ try {
575
+ const kp = sdk_1.KeyManager.generate();
576
+ if (kp.did) {
577
+ const allChannels = await loadChannels();
578
+ const ch = allChannels.find(c => c.id === id);
579
+ if (ch) {
580
+ ch.did = kp.did;
581
+ ch.publicKey = Buffer.from(kp.publicKey).toString('hex');
582
+ console.log(`[创建频道] DID 生成完成: ${ch.did}`);
583
+ // 发布到 IPFS
584
+ try {
585
+ const auth = await sdk_1.AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
586
+ const result = await auth.registerAgent({ name, services: [] }, kp, '');
587
+ ch.cid = result.cid || '';
588
+ console.log(`[创建频道] CID: ${ch.cid}`);
589
+ }
590
+ catch { }
591
+ await saveChannels(allChannels);
592
+ }
593
+ }
594
+ }
595
+ catch (e) {
596
+ console.log(`[创建频道] ${name} 后台生成 DID 失败`);
597
+ }
598
+ }, 100);
599
+ }
600
+ catch (err) {
601
+ console.error('[创建频道] 错误:', err);
602
+ res.status(500).json({ error: err.message });
603
+ }
604
+ });
605
+ app.delete('/channels/:channelId', async (req, res) => {
606
+ try {
607
+ const { channelId } = req.params;
608
+ const channels = await loadChannels();
609
+ const index = channels.findIndex(c => c.id === channelId);
610
+ if (index === -1) {
611
+ return res.status(404).json({ error: 'Channel not found' });
612
+ }
613
+ channels.splice(index, 1);
614
+ await saveChannels(channels);
615
+ try {
616
+ await fs.unlink(path.join(SESSION_CACHE_PATH, `${channelId}.json`));
617
+ }
618
+ catch { }
619
+ res.json({ ok: true });
620
+ }
621
+ catch (err) {
622
+ res.status(500).json({ error: err.message });
623
+ }
624
+ });
625
+ app.patch('/channels/:channelId', async (req, res) => {
626
+ try {
627
+ const { channelId } = req.params;
628
+ const { name } = req.body;
629
+ if (!name) {
630
+ return res.status(400).json({ error: 'Name required' });
631
+ }
632
+ const channels = await loadChannels();
633
+ const channel = channels.find(c => c.id === channelId);
634
+ if (!channel) {
635
+ return res.status(404).json({ error: 'Channel not found' });
636
+ }
637
+ channel.name = name;
638
+ channel.updatedAt = new Date().toISOString();
639
+ await saveChannels(channels);
640
+ res.json(channel);
641
+ }
642
+ catch (err) {
643
+ res.status(500).json({ error: err.message });
644
+ }
645
+ });
646
+ app.get('/sessions/:channelId', async (req, res) => {
647
+ try {
648
+ const session = await loadSession(req.params.channelId);
649
+ res.json(session || { channelId: req.params.channelId, messages: [], lastUpdated: null });
650
+ }
651
+ catch (err) {
652
+ res.status(500).json({ error: err.message });
653
+ }
654
+ });
655
+ app.get('/theme', async (req, res) => {
656
+ try {
657
+ const themeData = await loadTheme();
658
+ res.json(themeData);
659
+ }
660
+ catch (err) {
661
+ res.json({ theme: 'light', agentId: '' });
662
+ }
663
+ });
664
+ app.post('/theme', async (req, res) => {
665
+ try {
666
+ const { theme, agentId } = req.body;
667
+ if (theme !== 'light' && theme !== 'dark') {
668
+ return res.status(400).json({ error: 'Invalid theme' });
669
+ }
670
+ await saveTheme(theme, agentId || '');
671
+ res.json({ ok: true });
672
+ }
673
+ catch (err) {
674
+ res.status(500).json({ error: err.message });
675
+ }
676
+ });
677
+ // 重新生成回复
678
+ app.post('/regenerate', async (req, res) => {
679
+ const { channelId, userMessage } = req.body;
680
+ if (!channelId) {
681
+ return res.status(400).json({ error: 'No channelId provided' });
682
+ }
683
+ if (!userMessage) {
684
+ return res.status(400).json({ error: 'No userMessage provided' });
685
+ }
686
+ try {
687
+ const channels = await loadChannels();
688
+ const channel = channels.find(c => c.id === channelId);
689
+ const realChannelDid = channel?.did || '';
690
+ const realChannelName = channel?.name || '';
691
+ const realChannelDidDoc = channel?.didDocument;
692
+ // 通知前端开始重新生成
693
+ broadcast({ type: 'regenerating', channelId }, channelId);
694
+ const agent = await getAgentForChannel(channelId, realChannelDid, realChannelName, realChannelDidDoc);
695
+ let fullResponse = '';
696
+ const streamCallback = (event) => {
697
+ if (event.type === 'token' || event.type === 'thinking') {
698
+ broadcast({ type: 'stream', streamType: event.type, content: event.content }, channelId);
699
+ }
700
+ else if (event.type === 'status' || event.type === 'tool') {
701
+ broadcast({ type: 'status', tool: event.tool, content: event.content }, channelId);
702
+ }
703
+ else if (event.type === 'error') {
704
+ broadcast({ type: 'error', content: event.content }, channelId);
705
+ }
706
+ };
707
+ // 重新生成时只发送用户消息
708
+ fullResponse = await agent.promptStream(userMessage, streamCallback);
709
+ broadcast({ type: 'ai', content: fullResponse }, channelId);
710
+ // 更新 session
711
+ const existingSession = await loadSession(channelId);
712
+ if (existingSession && existingSession.messages.length > 0) {
713
+ // 移除最后一个 AI 消息,替换为新的
714
+ const lastAiIndex = existingSession.messages.map((m) => m.type).lastIndexOf('ai');
715
+ if (lastAiIndex !== -1) {
716
+ existingSession.messages = existingSession.messages.slice(0, lastAiIndex);
717
+ }
718
+ existingSession.messages.push({
719
+ id: crypto.randomUUID(),
720
+ type: 'ai',
721
+ content: fullResponse,
722
+ timestamp: new Date().toISOString()
723
+ });
724
+ existingSession.lastUpdated = new Date().toISOString();
725
+ await saveSession(existingSession);
726
+ }
727
+ broadcast({ type: 'done' }, channelId);
728
+ res.json({ ok: true });
729
+ }
730
+ catch (err) {
731
+ broadcast({ type: 'error', content: err.message }, channelId);
732
+ broadcast({ type: 'done' }, channelId);
733
+ res.status(500).json({ error: err.message });
734
+ }
735
+ });
736
+ // ==================== Task Queue API ====================
737
+ // 获取所有任务
738
+ app.get('/api/tasks', async (req, res) => {
739
+ try {
740
+ const tasks = await loadTaskQueue();
741
+ res.json(tasks);
742
+ }
743
+ catch (err) {
744
+ res.status(500).json({ error: err.message });
745
+ }
746
+ });
747
+ // 创建新任务
748
+ app.post('/api/tasks', async (req, res) => {
749
+ try {
750
+ const { type, title, description, steps } = req.body;
751
+ if (!type || !title) {
752
+ return res.status(400).json({ error: 'type and title required' });
753
+ }
754
+ const tasks = await loadTaskQueue();
755
+ const task = {
756
+ id: `task_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`,
757
+ type,
758
+ title,
759
+ description,
760
+ status: 'pending',
761
+ progress: 0,
762
+ createdAt: new Date().toISOString(),
763
+ updatedAt: new Date().toISOString(),
764
+ steps: steps?.map((s, i) => ({
765
+ id: `step_${i}`,
766
+ name: s,
767
+ status: 'pending'
768
+ }))
769
+ };
770
+ tasks.push(task);
771
+ await saveTaskQueue(tasks);
772
+ res.json(task);
773
+ }
774
+ catch (err) {
775
+ res.status(500).json({ error: err.message });
776
+ }
777
+ });
778
+ // 获取单个任务
779
+ app.get('/api/tasks/:taskId', async (req, res) => {
780
+ try {
781
+ const { taskId } = req.params;
782
+ const tasks = await loadTaskQueue();
783
+ const task = tasks.find(t => t.id === taskId);
784
+ if (!task) {
785
+ return res.status(404).json({ error: 'Task not found' });
786
+ }
787
+ res.json(task);
788
+ }
789
+ catch (err) {
790
+ res.status(500).json({ error: err.message });
791
+ }
792
+ });
793
+ // 更新任务
794
+ app.patch('/api/tasks/:taskId', async (req, res) => {
795
+ try {
796
+ const { taskId } = req.params;
797
+ const { status, currentStep } = req.body;
798
+ const tasks = await loadTaskQueue();
799
+ const taskIndex = tasks.findIndex(t => t.id === taskId);
800
+ if (taskIndex === -1) {
801
+ return res.status(404).json({ error: 'Task not found' });
802
+ }
803
+ if (status) {
804
+ tasks[taskIndex].status = status;
805
+ }
806
+ if (currentStep !== undefined) {
807
+ tasks[taskIndex].currentStep = currentStep;
808
+ }
809
+ tasks[taskIndex].updatedAt = new Date().toISOString();
810
+ await saveTaskQueue(tasks);
811
+ res.json(tasks[taskIndex]);
812
+ }
813
+ catch (err) {
814
+ res.status(500).json({ error: err.message });
815
+ }
816
+ });
817
+ // 删除任务
818
+ app.delete('/api/tasks/:taskId', async (req, res) => {
819
+ try {
820
+ const { taskId } = req.params;
821
+ const tasks = await loadTaskQueue();
822
+ const filtered = tasks.filter(t => t.id !== taskId);
823
+ await saveTaskQueue(filtered);
824
+ res.json({ ok: true });
825
+ }
826
+ catch (err) {
827
+ res.status(500).json({ error: err.message });
828
+ }
829
+ });
830
+ // 执行任务(自动执行下一步)
831
+ app.post('/api/tasks/:taskId/execute', async (req, res) => {
832
+ try {
833
+ const { taskId } = req.params;
834
+ const { channelId } = req.body;
835
+ if (!channelId) {
836
+ return res.status(400).json({ error: 'channelId required' });
837
+ }
838
+ const tasks = await loadTaskQueue();
839
+ const task = tasks.find(t => t.id === taskId);
840
+ if (!task) {
841
+ return res.status(404).json({ error: 'Task not found' });
842
+ }
843
+ if (isExecutingTask) {
844
+ return res.status(409).json({ error: 'Another task is currently executing' });
845
+ }
846
+ // 异步执行任务
847
+ executeTask(task, channelId);
848
+ res.json({ ok: true, taskId: task.id });
849
+ }
850
+ catch (err) {
851
+ res.status(500).json({ error: err.message });
852
+ }
853
+ });
854
+ // 执行下一个待处理任务
855
+ app.post('/api/tasks/execute-next', async (req, res) => {
856
+ try {
857
+ const { channelId } = req.body;
858
+ if (!channelId) {
859
+ return res.status(400).json({ error: 'channelId required' });
860
+ }
861
+ const tasks = await loadTaskQueue();
862
+ const nextTask = tasks.find(t => t.status === 'pending');
863
+ if (!nextTask) {
864
+ return res.json({ ok: false, message: 'No pending tasks' });
865
+ }
866
+ if (isExecutingTask) {
867
+ return res.status(409).json({ error: 'Another task is currently executing' });
868
+ }
869
+ // 异步执行任务
870
+ executeTask(nextTask, channelId);
871
+ res.json({ ok: true, taskId: nextTask.id });
872
+ }
873
+ catch (err) {
874
+ res.status(500).json({ error: err.message });
875
+ }
876
+ });
877
+ // 创建并执行工作流
878
+ app.post('/api/workflow', async (req, res) => {
879
+ try {
880
+ const { channelId, title, steps } = req.body;
881
+ if (!channelId || !steps || !Array.isArray(steps)) {
882
+ return res.status(400).json({ error: 'channelId and steps required' });
883
+ }
884
+ const tasks = await loadTaskQueue();
885
+ const task = {
886
+ id: `wf_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`,
887
+ type: 'workflow',
888
+ title: title || '工作流',
889
+ description: `包含 ${steps.length} 个步骤的工作流`,
890
+ status: 'pending',
891
+ progress: 0,
892
+ createdAt: new Date().toISOString(),
893
+ updatedAt: new Date().toISOString(),
894
+ steps: steps.map((s, i) => ({
895
+ id: `step_${i}`,
896
+ name: s,
897
+ status: 'pending'
898
+ })),
899
+ currentStep: 0
900
+ };
901
+ tasks.push(task);
902
+ await saveTaskQueue(tasks);
903
+ // 自动开始执行
904
+ if (!isExecutingTask) {
905
+ executeTask(task, channelId);
906
+ }
907
+ res.json({ ok: true, task });
908
+ }
909
+ catch (err) {
910
+ res.status(500).json({ error: err.message });
911
+ }
912
+ });
913
+ // ==================== LLM 配置 API ====================
914
+ // 获取所有 LLM 配置
915
+ app.get('/api/llm-config', async (req, res) => {
916
+ try {
917
+ const config = await config_store_js_1.llmConfigStore.getConfig();
918
+ const providerInfo = config_store_js_1.llmConfigStore.getAllProviderInfo();
919
+ // 隐藏 API Key
920
+ const safeConfig = {
921
+ ...config,
922
+ providers: Object.fromEntries(Object.entries(config.providers).map(([key, val]) => [
923
+ key,
924
+ { ...val, apiKey: val.apiKey ? '***' + val.apiKey.slice(-4) : '' }
925
+ ])),
926
+ providerInfo
927
+ };
928
+ res.json(safeConfig);
929
+ }
930
+ catch (err) {
931
+ res.status(500).json({ error: err.message });
932
+ }
933
+ });
934
+ // 更新 LLM 配置
935
+ app.post('/api/llm-config', async (req, res) => {
936
+ try {
937
+ const { provider, config } = req.body;
938
+ if (!provider || !config) {
939
+ return res.status(400).json({ error: 'provider and config required' });
940
+ }
941
+ await config_store_js_1.llmConfigStore.updateProvider(provider, config);
942
+ // 如果是活跃供应商,重新初始化 Pi SDK
943
+ const currentActive = await config_store_js_1.llmConfigStore.getActiveProvider();
944
+ if (provider === currentActive) {
945
+ const newConfig = await config_store_js_1.llmConfigStore.getActiveProviderConfig();
946
+ if (newConfig) {
947
+ (0, index_js_1.initMinimax)({
948
+ provider,
949
+ apiKey: newConfig.apiKey || undefined,
950
+ baseUrl: newConfig.baseUrl || undefined,
951
+ model: newConfig.model || undefined
952
+ });
953
+ }
954
+ }
955
+ res.json({ ok: true });
956
+ }
957
+ catch (err) {
958
+ res.status(500).json({ error: err.message });
959
+ }
960
+ });
961
+ // 设置活跃供应商
962
+ app.post('/api/llm-provider', async (req, res) => {
963
+ try {
964
+ const { provider } = req.body;
965
+ if (!provider) {
966
+ return res.status(400).json({ error: 'provider required' });
967
+ }
968
+ await config_store_js_1.llmConfigStore.setActiveProvider(provider);
969
+ // 重新初始化 Pi SDK
970
+ const config = await config_store_js_1.llmConfigStore.getActiveProviderConfig();
971
+ if (config) {
972
+ (0, index_js_1.initMinimax)({
973
+ provider: provider,
974
+ apiKey: config.apiKey || undefined,
975
+ baseUrl: config.baseUrl || undefined,
976
+ model: config.model || undefined
977
+ });
978
+ }
979
+ res.json({ ok: true, provider });
980
+ }
981
+ catch (err) {
982
+ res.status(500).json({ error: err.message });
983
+ }
984
+ });
985
+ // 测试供应商连接
986
+ app.post('/api/llm-test', async (req, res) => {
987
+ try {
988
+ const { provider } = req.body;
989
+ if (!provider) {
990
+ return res.status(400).json({ error: 'provider required' });
991
+ }
992
+ const result = await config_store_js_1.llmConfigStore.testProvider(provider);
993
+ res.json(result);
994
+ }
995
+ catch (err) {
996
+ res.status(500).json({ error: err.message });
997
+ }
998
+ });
999
+ // ==================== P2P Network API ====================
1000
+ // 获取当前身份
1001
+ app.get('/api/identity', async (_req, res) => {
1002
+ console.log('收到 /api/identity 请求');
1003
+ console.log('p2pIdentity.did:', p2pIdentity.did);
1004
+ try {
1005
+ res.json({
1006
+ did: p2pIdentity.did,
1007
+ name: p2pIdentity.name,
1008
+ publicKey: p2pIdentity.publicKey
1009
+ });
1010
+ }
1011
+ catch (err) {
1012
+ console.error('API identity 错误:', err);
1013
+ res.status(500).json({ error: err.message });
1014
+ }
1015
+ });
1016
+ // 获取已连接的节点
1017
+ app.get('/api/peers', async (_req, res) => {
1018
+ try {
1019
+ if (!p2pCommunicator) {
1020
+ res.json([]);
1021
+ return;
1022
+ }
1023
+ const connections = p2pCommunicator.getConnections();
1024
+ const peers = connections.map((conn) => ({
1025
+ id: conn.publicKey.substring(0, 16),
1026
+ publicKey: conn.publicKey,
1027
+ peerId: conn.publicKey
1028
+ }));
1029
+ res.json(peers);
1030
+ }
1031
+ catch (err) {
1032
+ res.status(500).json({ error: err.message });
1033
+ }
1034
+ });
1035
+ // 获取已发现的所有节点(包括通过 CID 解析的)
1036
+ app.get('/api/discovered-peers', async (_req, res) => {
1037
+ try {
1038
+ // 从全局状态获取已发现的节点
1039
+ const discovered = global.discoveredAgents || [];
1040
+ res.json(discovered);
1041
+ }
1042
+ catch (err) {
1043
+ res.status(500).json({ error: err.message });
1044
+ }
1045
+ });
1046
+ // ==================== iroh P2P API ====================
1047
+ // 初始化 iroh P2P(带持久化)
1048
+ app.post('/api/iroh/init', async (_req, res) => {
1049
+ try {
1050
+ if (irohInitialized && irohNodeInfo) {
1051
+ res.json({ ok: true, ...irohNodeInfo });
1052
+ return;
1053
+ }
1054
+ console.log('[iroh API] 初始化 iroh...');
1055
+ // 启动 iroh(启用持久化)
1056
+ await iroh_transport_js_1.irohTransport.start(undefined, true);
1057
+ const nodeId = iroh_transport_js_1.irohTransport.getNodeId() || '';
1058
+ console.log(`[iroh API] iroh 节点 ID: ${nodeId.substring(0, 20)}...`);
1059
+ // 生成 DID
1060
+ const keyPair = sdk_1.KeyManager.generate();
1061
+ const did = keyPair.did;
1062
+ // 构建节点信息文档
1063
+ const nodeDoc = {
1064
+ id: did,
1065
+ name: `bolloon-web-${Date.now()}`,
1066
+ version: '1.0',
1067
+ capabilities: ['chat', 'ai', 'judgment-injection', 'web-interface'],
1068
+ interests: ['ai', 'p2p', 'judgment-system'],
1069
+ irohNodeId: nodeId,
1070
+ channels: [{ id: 'main', name: '主对话' }],
1071
+ createdAt: new Date().toISOString()
1072
+ };
1073
+ // 发布到 IPFS
1074
+ const formData = new FormData();
1075
+ const blob = new Blob([JSON.stringify(nodeDoc)], { type: 'application/json' });
1076
+ formData.append('file', blob, 'node-info.json');
1077
+ const ipfsRes = await fetch(`${IPFS_ENDPOINT}/api/v0/add`, {
1078
+ method: 'POST',
1079
+ body: formData
1080
+ });
1081
+ const ipfsResult = await ipfsRes.text();
1082
+ const cidMatch = ipfsResult.match(/"Hash":"([^"]+)"/);
1083
+ const cid = cidMatch ? cidMatch[1] : '';
1084
+ irohNodeInfo = {
1085
+ did,
1086
+ cid,
1087
+ irohNodeId: nodeId,
1088
+ name: nodeDoc.name,
1089
+ initialized: true
1090
+ };
1091
+ irohInitialized = true;
1092
+ // 设置消息处理
1093
+ iroh_transport_js_1.irohTransport.onMessage('chat', (msg) => {
1094
+ const content = new TextDecoder().decode(msg.payload);
1095
+ console.log(`[iroh] 收到消息 from ${msg.from.substring(0, 12)}...`);
1096
+ // 通过 SSE 广播给所有客户端
1097
+ broadcast({
1098
+ type: 'p2p_message',
1099
+ from: msg.from,
1100
+ content,
1101
+ timestamp: Date.now()
1102
+ }, 'p2p-global');
1103
+ });
1104
+ iroh_transport_js_1.irohTransport.onMessage('ai-dialogue', (msg) => {
1105
+ const content = new TextDecoder().decode(msg.payload);
1106
+ console.log(`[iroh] 收到 AI 对话 from ${msg.from.substring(0, 12)}...`);
1107
+ broadcast({
1108
+ type: 'p2p_message',
1109
+ content,
1110
+ timestamp: Date.now()
1111
+ }, 'p2p-global');
1112
+ });
1113
+ console.log(`[iroh API] 初始化完成: DID=${did}, CID=${cid}`);
1114
+ res.json({ ok: true, ...irohNodeInfo });
1115
+ }
1116
+ catch (err) {
1117
+ console.error('[iroh API] 初始化失败:', err);
1118
+ res.status(500).json({ error: err.message });
1119
+ }
1120
+ });
1121
+ // 获取 iroh 节点信息
1122
+ app.get('/api/iroh/info', async (_req, res) => {
1123
+ if (!irohInitialized || !irohNodeInfo) {
1124
+ res.json({ initialized: false });
1125
+ return;
1126
+ }
1127
+ res.json({
1128
+ initialized: true,
1129
+ did: irohNodeInfo.did,
1130
+ cid: irohNodeInfo.cid,
1131
+ irohNodeId: irohNodeInfo.irohNodeId,
1132
+ name: irohNodeInfo.name
1133
+ });
1134
+ });
1135
+ // 通过 CID 连接到其他节点
1136
+ app.post('/api/iroh/connect', async (req, res) => {
1137
+ try {
1138
+ const { cid } = req.body;
1139
+ if (!cid) {
1140
+ return res.status(400).json({ error: 'CID required' });
1141
+ }
1142
+ if (!irohInitialized) {
1143
+ return res.status(500).json({ error: 'iroh not initialized' });
1144
+ }
1145
+ console.log(`[iroh API] 连接到 CID: ${cid}`);
1146
+ // 从 IPFS 获取节点信息
1147
+ const ipfsRes = await fetch(`${IPFS_ENDPOINT}/api/v0/cat?arg=${cid}`, {
1148
+ method: 'POST'
1149
+ });
1150
+ const content = await ipfsRes.text();
1151
+ const doc = JSON.parse(content);
1152
+ if (!doc.irohNodeId) {
1153
+ return res.status(400).json({ error: '节点信息中不包含 irohNodeId' });
1154
+ }
1155
+ const targetNodeId = doc.irohNodeId;
1156
+ console.log(`[iroh API] 目标节点: ${targetNodeId.substring(0, 20)}...`);
1157
+ // 发送连接消息
1158
+ const message = JSON.stringify({
1159
+ type: 'hello',
1160
+ from: irohNodeInfo?.irohNodeId,
1161
+ name: irohNodeInfo?.name,
1162
+ timestamp: Date.now()
1163
+ });
1164
+ const success = await iroh_transport_js_1.irohTransport.sendMessage(targetNodeId, 'chat', new TextEncoder().encode(message));
1165
+ if (success) {
1166
+ console.log(`[iroh API] 连接成功!`);
1167
+ res.json({
1168
+ ok: true,
1169
+ targetNodeId,
1170
+ nodeName: doc.name || 'Unknown'
1171
+ });
1172
+ }
1173
+ else {
1174
+ console.log(`[iroh API] 连接失败(对方可能离线)`);
1175
+ res.json({
1176
+ ok: false,
1177
+ error: '连接失败,对方可能离线',
1178
+ targetNodeId
1179
+ });
1180
+ }
1181
+ }
1182
+ catch (err) {
1183
+ console.error('[iroh API] 连接错误:', err);
1184
+ res.status(500).json({ error: err.message });
1185
+ }
1186
+ });
1187
+ // 发送消息给指定节点
1188
+ app.post('/api/iroh/send', async (req, res) => {
1189
+ try {
1190
+ const { targetNodeId, type, content } = req.body;
1191
+ if (!targetNodeId || !content) {
1192
+ return res.status(400).json({ error: 'targetNodeId and content required' });
1193
+ }
1194
+ if (!irohInitialized) {
1195
+ return res.status(500).json({ error: 'iroh not initialized' });
1196
+ }
1197
+ const messageType = type || 'chat';
1198
+ const success = await iroh_transport_js_1.irohTransport.sendMessage(targetNodeId, messageType, new TextEncoder().encode(content));
1199
+ res.json({ ok: success });
1200
+ }
1201
+ catch (err) {
1202
+ console.error('[iroh API] 发送消息错误:', err);
1203
+ res.status(500).json({ error: err.message });
1204
+ }
1205
+ });
1206
+ // 获取已连接的 iroh 节点列表
1207
+ app.get('/api/iroh/peers', async (_req, res) => {
1208
+ try {
1209
+ if (!irohInitialized) {
1210
+ res.json([]);
1211
+ return;
1212
+ }
1213
+ const peers = iroh_transport_js_1.irohTransport.getConnectedPeers();
1214
+ res.json(peers.map((nodeId) => ({
1215
+ nodeId,
1216
+ shortId: nodeId.substring(0, 16)
1217
+ })));
1218
+ }
1219
+ catch (err) {
1220
+ res.status(500).json({ error: err.message });
1221
+ }
1222
+ });
1223
+ // 获取离线消息数量
1224
+ app.get('/api/iroh/offline-count', async (_req, res) => {
1225
+ try {
1226
+ if (!irohInitialized) {
1227
+ res.json({ count: 0 });
1228
+ return;
1229
+ }
1230
+ const count = iroh_transport_js_1.irohTransport.getPendingOfflineCount();
1231
+ res.json({ count });
1232
+ }
1233
+ catch (err) {
1234
+ res.json({ count: 0 });
1235
+ }
1236
+ });
1237
+ // 获取当前频道的身份信息
1238
+ app.get('/api/channel-identity/:channelId', async (req, res) => {
1239
+ try {
1240
+ const { channelId } = req.params;
1241
+ const channels = await loadChannels();
1242
+ const channel = channels.find(c => c.id === channelId);
1243
+ if (!channel) {
1244
+ return res.status(404).json({ error: 'Channel not found' });
1245
+ }
1246
+ res.json({
1247
+ did: channel.did || '',
1248
+ cid: channel.cid || '',
1249
+ publicKey: channel.publicKey || '',
1250
+ name: channel.name
1251
+ });
1252
+ }
1253
+ catch (err) {
1254
+ res.status(500).json({ error: err.message });
1255
+ }
1256
+ });
1257
+ // 通过 DID/CID 连接远程智能体
1258
+ app.post('/api/connect', async (req, res) => {
1259
+ try {
1260
+ const { did, cid, ipnsName } = req.body;
1261
+ if (!did && !cid && !ipnsName) {
1262
+ return res.status(400).json({ error: 'DID, CID or IPNS name required' });
1263
+ }
1264
+ console.log(`[连接] 尝试连接 DID: ${did}, CID: ${cid}, IPNS: ${ipnsName}`);
1265
+ let doc = null;
1266
+ // 1. 通过 CID 或 IPNS 解析 DiapDoc
1267
+ if (cid || ipnsName) {
1268
+ try {
1269
+ const { IpfsClient } = await Promise.resolve().then(() => __importStar(require('@diap/sdk')));
1270
+ const ipfs = new IpfsClient('http://127.0.0.1:5001', null);
1271
+ let resolvedCid = cid;
1272
+ if (ipnsName) {
1273
+ resolvedCid = await ipfs.resolveIpns(ipnsName);
1274
+ }
1275
+ if (resolvedCid) {
1276
+ const content = await ipfs.get(resolvedCid);
1277
+ doc = JSON.parse(content);
1278
+ console.log(`[连接] 解析 DiapDoc 成功: ${doc.name}`);
1279
+ }
1280
+ }
1281
+ catch (e) {
1282
+ console.warn(`[连接] 解析 IPFS 内容失败:`, e);
1283
+ }
1284
+ }
1285
+ // 2. 如果有 DID,检查是否已连接
1286
+ if (did) {
1287
+ // 广播连接请求
1288
+ if (p2pCommunicator) {
1289
+ const payload = JSON.stringify({
1290
+ type: 'connect_request',
1291
+ requesterDid: did,
1292
+ targetDid: did,
1293
+ timestamp: Date.now()
1294
+ });
1295
+ // 广播到网络
1296
+ console.log(`[连接] 广播连接请求: ${did}`);
1297
+ }
1298
+ }
1299
+ // 3. 将解析的文档添加到已发现列表
1300
+ if (doc) {
1301
+ const discovered = global.discoveredAgents || [];
1302
+ const existing = discovered.findIndex((a) => a.did === doc.id);
1303
+ if (existing >= 0) {
1304
+ discovered[existing] = { ...discovered[existing], ...doc, lastSeen: Date.now() };
1305
+ }
1306
+ else {
1307
+ discovered.push({
1308
+ did: doc.id || doc.did,
1309
+ name: doc.name,
1310
+ capabilities: doc.capabilities || [],
1311
+ interests: doc.interests || [],
1312
+ channels: doc.channels || [],
1313
+ cid: cid,
1314
+ ipnsName: ipnsName,
1315
+ lastSeen: Date.now()
1316
+ });
1317
+ }
1318
+ global.discoveredAgents = discovered;
1319
+ // 广播发现事件到前端
1320
+ broadcast({ type: 'peer_discovered', peer: doc });
1321
+ }
1322
+ res.json({
1323
+ ok: true,
1324
+ did: doc?.id || did,
1325
+ name: doc?.name,
1326
+ capabilities: doc?.capabilities || [],
1327
+ channels: doc?.channels || [],
1328
+ message: doc ? 'DiapDoc 解析成功' : '连接请求已发送'
1329
+ });
1330
+ }
1331
+ catch (err) {
1332
+ res.status(500).json({ error: err.message });
1333
+ }
1334
+ });
1335
+ // 发送 P2P 消息
1336
+ app.post('/api/message-p2p', async (req, res) => {
1337
+ try {
1338
+ const { peerId, did, message } = req.body;
1339
+ if (!message) {
1340
+ return res.status(400).json({ error: 'message required' });
1341
+ }
1342
+ let targetPeerId = peerId;
1343
+ // 如果没有 peerId,通过 DID 查找
1344
+ if (!targetPeerId && did) {
1345
+ const discovered = global.discoveredAgents || [];
1346
+ const peer = discovered.find((a) => a.did === did);
1347
+ if (peer) {
1348
+ targetPeerId = peer.peerId;
1349
+ }
1350
+ }
1351
+ if (!targetPeerId) {
1352
+ // 如果没有 P2P 连接,将消息存储到本地队列
1353
+ const messageQueue = global.messageQueue || [];
1354
+ messageQueue.push({
1355
+ did,
1356
+ message,
1357
+ timestamp: Date.now(),
1358
+ status: 'pending'
1359
+ });
1360
+ global.messageQueue = messageQueue;
1361
+ res.json({ ok: true, queued: true, message: '消息已加入队列,等待对方上线' });
1362
+ return;
1363
+ }
1364
+ // 通过 P2P 发送消息
1365
+ if (p2pCommunicator) {
1366
+ const payload = JSON.stringify({
1367
+ from: 'bolloon-web',
1368
+ content: message,
1369
+ timestamp: Date.now()
1370
+ });
1371
+ // 找到连接并发送
1372
+ const connections = p2pCommunicator.getConnections();
1373
+ for (const conn of connections) {
1374
+ if (conn.publicKey.includes(targetPeerId) || targetPeerId.includes(conn.publicKey.substring(0, 16))) {
1375
+ conn.send(payload);
1376
+ res.json({ ok: true, sent: true });
1377
+ return;
1378
+ }
1379
+ }
1380
+ }
1381
+ res.json({ ok: true, sent: false, message: '对方不在线,消息已加入队列' });
1382
+ }
1383
+ catch (err) {
1384
+ res.status(500).json({ error: err.message });
1385
+ }
1386
+ });
1387
+ // 获取待接收的消息队列
1388
+ app.get('/api/peer-messages', async (_req, res) => {
1389
+ try {
1390
+ const messageQueue = global.messageQueue || [];
1391
+ const pendingMessages = messageQueue.filter((m) => m.status === 'pending');
1392
+ res.json(pendingMessages);
1393
+ }
1394
+ catch (err) {
1395
+ res.status(500).json({ error: err.message });
1396
+ }
1397
+ });
1398
+ // 标记消息已读
1399
+ app.post('/api/peer-messages/:messageId/read', async (req, res) => {
1400
+ try {
1401
+ const { messageId } = req.params;
1402
+ const messageQueue = global.messageQueue || [];
1403
+ const msg = messageQueue.find((m) => m.id === messageId);
1404
+ if (msg) {
1405
+ msg.status = 'read';
1406
+ }
1407
+ res.json({ ok: true });
1408
+ }
1409
+ catch (err) {
1410
+ res.status(500).json({ error: err.message });
1411
+ }
1412
+ });
1413
+ // ==================== P2P 连接进度 SSE ====================
1414
+ // 连接进度流(用于实时显示解析进度)
1415
+ const connectProgressClients = new Map();
1416
+ app.get('/api/p2p/connect/progress', async (req, res) => {
1417
+ const sessionId = crypto.randomUUID();
1418
+ res.setHeader('Content-Type', 'text/event-stream');
1419
+ res.setHeader('Cache-Control', 'no-cache');
1420
+ res.setHeader('Connection', 'keep-alive');
1421
+ res.write(`data: ${JSON.stringify({ type: 'start', sessionId })}\n\n`);
1422
+ connectProgressClients.set(sessionId, res);
1423
+ req.on('close', () => {
1424
+ connectProgressClients.delete(sessionId);
1425
+ });
1426
+ });
1427
+ function emitConnectProgress(sessionId, data) {
1428
+ const client = connectProgressClients.get(sessionId);
1429
+ if (client) {
1430
+ client.write(`data: ${JSON.stringify(data)}\n\n`);
1431
+ }
1432
+ }
1433
+ // 取消连接
1434
+ app.post('/api/p2p/connect/cancel', async (req, res) => {
1435
+ const { sessionId } = req.body;
1436
+ if (sessionId && connectProgressClients.has(sessionId)) {
1437
+ connectProgressClients.get(sessionId).end();
1438
+ connectProgressClients.delete(sessionId);
1439
+ }
1440
+ res.json({ ok: true });
1441
+ });
1442
+ // ==================== P2P 连接历史 API ====================
1443
+ const P2P_HISTORY_PATH = path.join(SHARED_SESSION_PATH, 'p2p-history.json');
1444
+ async function loadP2PHistory() {
1445
+ try {
1446
+ const data = await fs.readFile(P2P_HISTORY_PATH, 'utf-8');
1447
+ return JSON.parse(data);
1448
+ }
1449
+ catch {
1450
+ return [];
1451
+ }
1452
+ }
1453
+ async function saveP2PHistory(history) {
1454
+ await fs.writeFile(P2P_HISTORY_PATH, JSON.stringify(history, null, 2));
1455
+ }
1456
+ // 获取连接历史
1457
+ app.get('/api/p2p/history', async (_req, res) => {
1458
+ try {
1459
+ const history = await loadP2PHistory();
1460
+ res.json(history);
1461
+ }
1462
+ catch (err) {
1463
+ res.status(500).json({ error: err.message });
1464
+ }
1465
+ });
1466
+ // 添加到连接历史
1467
+ app.post('/api/p2p/history', async (req, res) => {
1468
+ try {
1469
+ const history = await loadP2PHistory();
1470
+ const entry = req.body;
1471
+ // 检查是否已存在
1472
+ const existingIndex = history.findIndex((h) => h.did === entry.did);
1473
+ if (existingIndex >= 0) {
1474
+ history[existingIndex] = { ...history[existingIndex], ...entry, lastConnectedAt: Date.now() };
1475
+ }
1476
+ else {
1477
+ history.unshift({ ...entry, id: crypto.randomUUID(), lastConnectedAt: Date.now(), lastMessageAt: 0, totalMessages: 0 });
1478
+ }
1479
+ await saveP2PHistory(history);
1480
+ res.json({ ok: true });
1481
+ }
1482
+ catch (err) {
1483
+ res.status(500).json({ error: err.message });
1484
+ }
1485
+ });
1486
+ // 更新连接历史
1487
+ app.patch('/api/p2p/history/:id', async (req, res) => {
1488
+ try {
1489
+ const history = await loadP2PHistory();
1490
+ const { id } = req.params;
1491
+ const updates = req.body;
1492
+ const index = history.findIndex((h) => h.id === id);
1493
+ if (index >= 0) {
1494
+ history[index] = { ...history[index], ...updates };
1495
+ await saveP2PHistory(history);
1496
+ }
1497
+ res.json({ ok: true });
1498
+ }
1499
+ catch (err) {
1500
+ res.status(500).json({ error: err.message });
1501
+ }
1502
+ });
1503
+ // 删除连接历史
1504
+ app.delete('/api/p2p/history/:id', async (req, res) => {
1505
+ try {
1506
+ const history = await loadP2PHistory();
1507
+ const { id } = req.params;
1508
+ const filtered = history.filter((h) => h.id !== id);
1509
+ await saveP2PHistory(filtered);
1510
+ res.json({ ok: true });
1511
+ }
1512
+ catch (err) {
1513
+ res.status(500).json({ error: err.message });
1514
+ }
1515
+ });
1516
+ // ==================== P2P 偏好设置 API ====================
1517
+ const P2P_PREFS_PATH = path.join(SHARED_SESSION_PATH, 'p2p-preferences.json');
1518
+ async function loadP2PPreferences() {
1519
+ try {
1520
+ const data = await fs.readFile(P2P_PREFS_PATH, 'utf-8');
1521
+ return JSON.parse(data);
1522
+ }
1523
+ catch {
1524
+ return {
1525
+ autoReconnect: true,
1526
+ autoConnectOnStartup: true,
1527
+ preferredNodes: [],
1528
+ maxOfflineQueue: 100,
1529
+ notifications: {
1530
+ newMessage: true,
1531
+ connectionEstablished: true,
1532
+ peerWentOnline: true,
1533
+ peerWentOffline: true
1534
+ }
1535
+ };
1536
+ }
1537
+ }
1538
+ async function saveP2PPreferences(prefs) {
1539
+ await fs.writeFile(P2P_PREFS_PATH, JSON.stringify(prefs, null, 2));
1540
+ }
1541
+ app.get('/api/p2p/preferences', async (_req, res) => {
1542
+ try {
1543
+ const prefs = await loadP2PPreferences();
1544
+ res.json(prefs);
1545
+ }
1546
+ catch (err) {
1547
+ res.status(500).json({ error: err.message });
1548
+ }
1549
+ });
1550
+ app.patch('/api/p2p/preferences', async (req, res) => {
1551
+ try {
1552
+ const current = await loadP2PPreferences();
1553
+ const updates = req.body;
1554
+ await saveP2PPreferences({ ...current, ...updates });
1555
+ res.json({ ok: true });
1556
+ }
1557
+ catch (err) {
1558
+ res.status(500).json({ error: err.message });
1559
+ }
1560
+ });
1561
+ return new Promise((resolve) => {
1562
+ server.listen(port, () => {
1563
+ setInterval(() => {
1564
+ for (const client of sseClients) {
1565
+ client.res.write(': ping\n\n');
1566
+ }
1567
+ }, 30000);
1568
+ resolve({ app, server });
1569
+ });
1570
+ });
1571
+ }
1572
+ function broadcast(data, channelId) {
1573
+ const envelope = { ...data, channelId };
1574
+ const message = `data: ${JSON.stringify(envelope)}\n\n`;
1575
+ for (const client of sseClients) {
1576
+ if (!channelId || client.channelId === channelId) {
1577
+ client.res.write(message);
1578
+ }
1579
+ }
1580
+ }
1581
+ function getUserName() {
1582
+ const home = process.env.HOME || process.env.USERPROFILE || '';
1583
+ const match = home.match(/\/Users\/(\w+)/);
1584
+ if (match)
1585
+ return match[1];
1586
+ const user = process.env.USERNAME || process.env.USER || 'user';
1587
+ return user.toLowerCase().replace(/[^a-z0-9]/g, '');
1588
+ }
1589
+ async function bootstrapIdentity() {
1590
+ console.log('🔐 身份生成...');
1591
+ const kp = sdk_1.KeyManager.generate();
1592
+ const did = kp.did;
1593
+ const username = getUserName();
1594
+ const suffix = did.split(':').pop()?.substring(0, 4);
1595
+ const name = `blln-${username}-${suffix}`;
1596
+ console.log(` DID: ${did.substring(0, 30)}...`);
1597
+ return { keypair: kp, did, name };
1598
+ }
1599
+ function publishDIDBackground(name, kp) {
1600
+ console.log('📝 IPNS注册(后台)...');
1601
+ let retries = 0;
1602
+ const attempt = async () => {
1603
+ try {
1604
+ const auth = await sdk_1.AgentAuthManager.newWithRemoteIpfs('http://127.0.0.1:5001', 'http://127.0.0.1:8080');
1605
+ await auth.registerAgent({ name, services: [] }, kp, '');
1606
+ console.log('✅ IPNS注册成功');
1607
+ }
1608
+ catch (e) {
1609
+ retries++;
1610
+ if (retries < 10) {
1611
+ setTimeout(attempt, 60000);
1612
+ }
1613
+ }
1614
+ };
1615
+ setTimeout(attempt, 100);
1616
+ }
1617
+ async function bootstrapP2P(verifier) {
1618
+ console.log('🌐 P2P连接...');
1619
+ const rawSeed = crypto.getRandomValues(new Uint8Array(32));
1620
+ const comm = (0, sdk_1.createHyperswarmCommunicator)({ server: true, client: true, autoConnect: true, maxConnections: 50, seed: rawSeed });
1621
+ await comm.start();
1622
+ const topic = (0, sdk_1.createTopic)('bolloon-agent-harness');
1623
+ await comm.joinTopic(topic);
1624
+ console.log(' P2P已就绪');
1625
+ return comm;
1626
+ }
1627
+ async function openBrowser(url) {
1628
+ const { exec } = await Promise.resolve().then(() => __importStar(require('child_process')));
1629
+ const { platform } = await Promise.resolve().then(() => __importStar(require('os')));
1630
+ const p = platform();
1631
+ let cmd;
1632
+ if (p === 'darwin') {
1633
+ cmd = `open ${url}`;
1634
+ }
1635
+ else if (p === 'win32') {
1636
+ cmd = `start ${url}`;
1637
+ }
1638
+ else {
1639
+ cmd = `xdg-open ${url}`;
1640
+ }
1641
+ exec(cmd, (err) => {
1642
+ if (err) {
1643
+ console.error('打开浏览器失败:', err.message);
1644
+ }
1645
+ });
1646
+ }
1647
+ //# sourceMappingURL=server.js.map