@bolloon/bolloon-agent 0.4.13 → 0.4.15

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 (221) hide show
  1. package/README.md +127 -127
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon-daemon.sh +207 -0
  4. package/bin/bolloon.cjs +0 -0
  5. package/dist/agents/agent-gateway.js +130 -0
  6. package/dist/agents/constraint-layer.js +19 -19
  7. package/dist/agents/gateway-group.js +261 -0
  8. package/dist/agents/gateway-network.js +278 -0
  9. package/dist/agents/judgment-protocol.js +14 -14
  10. package/dist/agents/pi-sdk-tools.js +117 -0
  11. package/dist/agents/pi-sdk-types.js +12 -12
  12. package/dist/agents/pi-sdk.js +101 -101
  13. package/dist/agents/skill-organizer.js +19 -19
  14. package/dist/agents/workflow-pivot-loop.js +2 -2
  15. package/dist/agents/x402/x402Pay.js +4 -0
  16. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  17. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  18. package/dist/bollharness-integration/context-router.js +292 -292
  19. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  20. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  21. package/dist/bollharness-integration/skill-adapter.js +21 -21
  22. package/dist/bootstrap/chat-archiver.js +14 -14
  23. package/dist/bootstrap/context-os.js +24 -24
  24. package/dist/bootstrap/memory-compressor.js +13 -13
  25. package/dist/cli-entry.js +36 -36
  26. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +63 -0
  27. package/dist/constraint-runtime/reference_data/commands_snapshot.json +1037 -0
  28. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +8 -0
  29. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +8 -0
  30. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +32 -0
  31. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +13 -0
  32. package/dist/constraint-runtime/reference_data/subsystems/cli.json +26 -0
  33. package/dist/constraint-runtime/reference_data/subsystems/components.json +32 -0
  34. package/dist/constraint-runtime/reference_data/subsystems/constants.json +28 -0
  35. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +8 -0
  36. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +15 -0
  37. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +32 -0
  38. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +21 -0
  39. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +15 -0
  40. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +18 -0
  41. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +8 -0
  42. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +11 -0
  43. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +8 -0
  44. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +9 -0
  45. package/dist/constraint-runtime/reference_data/subsystems/remote.json +11 -0
  46. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +8 -0
  47. package/dist/constraint-runtime/reference_data/subsystems/screens.json +10 -0
  48. package/dist/constraint-runtime/reference_data/subsystems/server.json +10 -0
  49. package/dist/constraint-runtime/reference_data/subsystems/services.json +32 -0
  50. package/dist/constraint-runtime/reference_data/subsystems/skills.json +27 -0
  51. package/dist/constraint-runtime/reference_data/subsystems/state.json +13 -0
  52. package/dist/constraint-runtime/reference_data/subsystems/types.json +18 -0
  53. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +9 -0
  54. package/dist/constraint-runtime/reference_data/subsystems/utils.json +32 -0
  55. package/dist/constraint-runtime/reference_data/subsystems/vim.json +12 -0
  56. package/dist/constraint-runtime/reference_data/subsystems/voice.json +8 -0
  57. package/dist/constraint-runtime/reference_data/tools_snapshot.json +922 -0
  58. package/dist/constraint-runtime/tools/PolymarketSDK/econ-integration.d.ts +55 -0
  59. package/dist/constraint-runtime/tools/PolymarketSDK/econ-integration.js +59 -0
  60. package/dist/context-compaction/auto-compact.js +7 -7
  61. package/dist/electron/config.js.map +1 -0
  62. package/dist/electron/dialogs.js.map +1 -0
  63. package/dist/electron/first-run.js +54 -54
  64. package/dist/electron/first-run.js.map +1 -0
  65. package/dist/electron/ipc.js.map +1 -0
  66. package/dist/electron/logger.js.map +1 -0
  67. package/dist/electron/main.js.map +1 -0
  68. package/dist/electron/menu.js.map +1 -0
  69. package/dist/electron/paths.js.map +1 -0
  70. package/dist/electron/server.js.map +1 -0
  71. package/dist/electron/tray.js.map +1 -0
  72. package/dist/electron/window.js.map +1 -0
  73. package/dist/electron-build/electron/first-run.js +54 -54
  74. package/dist/electron-preload.js.map +1 -1
  75. package/dist/electron.js.map +1 -1
  76. package/dist/index.js +112 -112
  77. package/dist/llm/llm-judgment-client.js +102 -102
  78. package/dist/llm/pi-ai.js +48 -48
  79. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  80. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  81. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  82. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  83. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  84. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  85. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  86. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  87. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  88. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  89. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  90. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  91. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  92. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  93. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  94. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  95. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  96. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  97. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  98. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  99. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  100. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  101. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  102. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  103. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  104. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  105. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  106. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  107. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  108. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  109. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  110. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  111. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  112. package/dist/llm/tool-manifest/bash.js +3 -3
  113. package/dist/llm/tool-manifest/create_file.js +4 -4
  114. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  115. package/dist/llm/tool-manifest/image_search.js +2 -2
  116. package/dist/llm/tool-manifest/index.js +59 -0
  117. package/dist/llm/tool-manifest/mcp.js +2 -2
  118. package/dist/llm/tool-manifest/message_compose.js +3 -3
  119. package/dist/llm/tool-manifest/places.js +2 -2
  120. package/dist/llm/tool-manifest/present_files.js +1 -1
  121. package/dist/llm/tool-manifest/recipe.js +2 -2
  122. package/dist/llm/tool-manifest/str_replace.js +5 -5
  123. package/dist/llm/tool-manifest/view.js +3 -3
  124. package/dist/llm/tool-manifest/weather.js +4 -4
  125. package/dist/llm/tool-manifest/web.js +4 -4
  126. package/dist/network/p2p.js +78 -4
  127. package/dist/orbitdb/cid-database.js +39 -10
  128. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  129. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  130. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  131. package/dist/pi-ecosystem-judgment/index.js +1 -1
  132. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  133. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  134. package/dist/security/context-router-tool.js +15 -15
  135. package/dist/utils/auto-update.js.map +1 -0
  136. package/dist/web/a2ui-client.js +1594 -223
  137. package/dist/web/api-config.html +779 -779
  138. package/dist/web/client-hearth.js +10 -10
  139. package/dist/web/client.js +273 -0
  140. package/dist/web/client.js.map +7 -0
  141. package/dist/web/components/wallet-viem.mjs +118 -118
  142. package/dist/web/index.html +502 -485
  143. package/dist/web/manifest.json +20 -20
  144. package/dist/web/mobile-agent.js +397 -0
  145. package/dist/web/mobile-core.js +86235 -0
  146. package/dist/web/mobile-data.js +346 -0
  147. package/dist/web/mobile-http-api.js +71 -0
  148. package/dist/web/mobile-p2p.js +250 -0
  149. package/dist/web/mobile-payments.js +80 -0
  150. package/dist/web/mobile-wallet.js +226 -0
  151. package/dist/web/mobile.css +483 -6
  152. package/dist/web/mobile.html +99 -50
  153. package/dist/web/mobile.js +1040 -187
  154. package/dist/web/server.js +196 -13
  155. package/dist/web/style.css +5062 -4946
  156. package/package.json +201 -198
  157. package/scripts/build-cli.js +215 -215
  158. package/scripts/build-web.ts +162 -149
  159. package/scripts/postinstall.js +152 -152
  160. package/bin/bolloon.js +0 -157
  161. package/dist/agents/python-exec.js +0 -115
  162. package/dist/pi-ecosystem-colony/index.js +0 -365
  163. package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
  164. package/dist/social/ant-colony/PheromoneEngine.js +0 -227
  165. package/dist/social/ant-colony/index.js +0 -6
  166. package/dist/social/ant-colony/types.js +0 -24
  167. package/dist/storage/trajectory.js +0 -101
  168. package/dist/test/ai-judgment-test.js +0 -80
  169. package/dist/test/bollharness-integration.test.js +0 -318
  170. package/dist/test/channel-agent-multi-dialogue.js +0 -205
  171. package/dist/test/channel-heartbeat-agent-test.js +0 -201
  172. package/dist/test/constraint-layer.test.js +0 -164
  173. package/dist/test/diap-identity-test.js +0 -172
  174. package/dist/test/diap-quick-test.js +0 -62
  175. package/dist/test/global-shared-context.test.js +0 -315
  176. package/dist/test/harness-judgment-injection.test.js +0 -246
  177. package/dist/test/harness-workflow-integrator-test.js +0 -228
  178. package/dist/test/human-value-store.test.js +0 -243
  179. package/dist/test/hybrid-integration-test.js +0 -118
  180. package/dist/test/hybrid-messenger-verify.js +0 -55
  181. package/dist/test/iroh-bistream-debug.js +0 -38
  182. package/dist/test/iroh-communication.test.js +0 -66
  183. package/dist/test/iroh-debug-test.js +0 -57
  184. package/dist/test/iroh-diap-test.js +0 -71
  185. package/dist/test/iroh-direct-connect.js +0 -55
  186. package/dist/test/iroh-e2e-fixed.js +0 -89
  187. package/dist/test/iroh-e2e-same-process.js +0 -63
  188. package/dist/test/iroh-e2e.js +0 -66
  189. package/dist/test/iroh-final-e2e.js +0 -72
  190. package/dist/test/iroh-relay-test.js +0 -37
  191. package/dist/test/iroh-simple-test.js +0 -41
  192. package/dist/test/iroh-transport-verify.js +0 -54
  193. package/dist/test/iroh-transport.test.js +0 -37
  194. package/dist/test/iroh-two-nodes.js +0 -70
  195. package/dist/test/iroh-verify.js +0 -44
  196. package/dist/test/judgment-decision.test.js +0 -219
  197. package/dist/test/llm-judgment-integration.test.js +0 -220
  198. package/dist/test/p2p-agent-complex-dialogue.js +0 -385
  199. package/dist/test/p2p-agent-dialogue.js +0 -341
  200. package/dist/test/p2p-agent-full-bidirectional.js +0 -510
  201. package/dist/test/p2p-agent-harness-flow.js +0 -437
  202. package/dist/test/p2p-agent-harness-single.js +0 -143
  203. package/dist/test/p2p-ai-dialogue-test.js +0 -318
  204. package/dist/test/p2p-cid-connect-test.js +0 -195
  205. package/dist/test/p2p-connect-receiver.js +0 -69
  206. package/dist/test/p2p-doc-transfer.js +0 -110
  207. package/dist/test/p2p-identity-page-test.js +0 -77
  208. package/dist/test/p2p-iroh-test.js +0 -171
  209. package/dist/test/p2p-minimal-test.js +0 -241
  210. package/dist/test/p2p-node-1.js +0 -148
  211. package/dist/test/p2p-node-2.js +0 -148
  212. package/dist/test/p2p-server.js +0 -281
  213. package/dist/test/p2p-two-nodes-test.js +0 -438
  214. package/dist/test/pi-sdk.test.js +0 -44
  215. package/dist/test/set-persona.js +0 -40
  216. package/dist/test/simple.test.js +0 -9
  217. package/dist/test/storage-integration.test.js +0 -150
  218. package/dist/test/subagent-manager.test.js +0 -276
  219. package/dist/test/test-gate-flow.test.js +0 -81
  220. package/dist/test/workflow-engine.test.js +0 -87
  221. package/dist/test/workflow-pivot-loop.test.js +0 -246
@@ -20,16 +20,16 @@ export async function renderMyHearth(root) {
20
20
  root.innerHTML = '<h1>My Hearth</h1><p>Loading…</p>';
21
21
  try {
22
22
  const data = await fetchHearth('/api/hearth');
23
- root.innerHTML = `
24
- <h1>My Hearth</h1>
25
- <dl>
26
- <dt>Service</dt><dd>${data.service} v${data.version}</dd>
27
- <dt>Root</dt><dd><code>${data.rootPath}</code></dd>
28
- <dt>Description count</dt><dd>${data.descriptionCount}</dd>
29
- <dt>Visibility channels</dt><dd>${data.visibilityChannels}</dd>
30
- <dt>Allowlist count</dt><dd>${data.allowlistCount}</dd>
31
- <dt>Defense mode</dt><dd>${data.defenseMode ? 'ON (write APIs disabled)' : 'OFF (反攻期)'}</dd>
32
- </dl>
23
+ root.innerHTML = `
24
+ <h1>My Hearth</h1>
25
+ <dl>
26
+ <dt>Service</dt><dd>${data.service} v${data.version}</dd>
27
+ <dt>Root</dt><dd><code>${data.rootPath}</code></dd>
28
+ <dt>Description count</dt><dd>${data.descriptionCount}</dd>
29
+ <dt>Visibility channels</dt><dd>${data.visibilityChannels}</dd>
30
+ <dt>Allowlist count</dt><dd>${data.allowlistCount}</dd>
31
+ <dt>Defense mode</dt><dd>${data.defenseMode ? 'ON (write APIs disabled)' : 'OFF (反攻期)'}</dd>
32
+ </dl>
33
33
  <p>视图: <a href="#/hearth/discover">Discover</a> · <a href="#/hearth/visit/__self__">Visit self</a></p>`;
34
34
  }
35
35
  catch (e) {
@@ -1771,6 +1771,275 @@
1771
1771
  notice.remove();
1772
1772
  }, 15e3);
1773
1773
  }
1774
+ var gwGroups = [];
1775
+ var gwNetworks = [];
1776
+ var gwActiveChat = null;
1777
+ var gwMsgCache = /* @__PURE__ */ new Map();
1778
+ function gwToast(text) {
1779
+ try {
1780
+ window.showToast?.(text);
1781
+ } catch {
1782
+ }
1783
+ console.log("[gateway]", text);
1784
+ }
1785
+ function gwEsc(s) {
1786
+ try {
1787
+ return escapeHtml2(String(s ?? ""));
1788
+ } catch {
1789
+ return String(s ?? "");
1790
+ }
1791
+ }
1792
+ function gwModal(html) {
1793
+ const overlay = document.createElement("div");
1794
+ overlay.className = "gw-modal-overlay";
1795
+ overlay.innerHTML = `<div class="gw-modal">${html}<div class="gw-modal-close" title="\u5173\u95ED">\u2715</div></div>`;
1796
+ document.body.appendChild(overlay);
1797
+ const close = () => overlay.remove();
1798
+ overlay.querySelector(".gw-modal-close")?.addEventListener("click", close);
1799
+ overlay.addEventListener("click", (e) => {
1800
+ if (e.target === overlay) close();
1801
+ });
1802
+ return { root: overlay, close };
1803
+ }
1804
+ async function loadGatewaySidebar() {
1805
+ try {
1806
+ const [g, n] = await Promise.all([
1807
+ fetch("/api/gateway/groups").then((r) => r.json()).catch(() => ({ groups: [] })),
1808
+ fetch("/api/gateway/status").then((r) => r.json()).catch(() => ({ networks: [] }))
1809
+ ]);
1810
+ gwGroups = Array.isArray(g.groups) ? g.groups : [];
1811
+ gwNetworks = Array.isArray(n.networks) ? n.networks : [];
1812
+ renderGatewaySidebar();
1813
+ } catch {
1814
+ }
1815
+ }
1816
+ function renderGatewaySidebar() {
1817
+ const list = document.getElementById("gateway-list");
1818
+ if (!list) return;
1819
+ list.innerHTML = "";
1820
+ for (const grp of gwGroups) {
1821
+ const li = document.createElement("li");
1822
+ li.className = "gateway-item";
1823
+ li.innerHTML = `<span class="gateway-item-icon">\u{1F465}</span>
1824
+ <span class="gateway-item-main">
1825
+ <span class="gateway-item-name">${gwEsc(grp.name || "\u7FA4\u7EC4")}</span>
1826
+ <span class="gateway-item-sub">${grp.memberCount ?? 0} \u6210\u5458 \xB7 ${grp.messageCount ?? 0} \u6761\u6D88\u606F</span>
1827
+ </span>`;
1828
+ li.title = "\u6253\u5F00\u7FA4\u804A";
1829
+ li.onclick = () => openGroupChat(grp.id, grp.name || grp.id);
1830
+ list.appendChild(li);
1831
+ }
1832
+ for (const net of gwNetworks) {
1833
+ const li = document.createElement("li");
1834
+ li.className = "gateway-item gateway-item-net";
1835
+ li.innerHTML = `<span class="gateway-item-icon">\u{1F310}</span>
1836
+ <span class="gateway-item-main">
1837
+ <span class="gateway-item-name">${gwEsc(net.name || String(net.link || "").slice(0, 24) || "\u7F51\u7EDC")}</span>
1838
+ <span class="gateway-item-sub">${net.serviceCount ?? 0} \u4E2A\u670D\u52A1</span>
1839
+ </span>`;
1840
+ li.title = `\u670D\u52A1\u7F51\u7EDC: ${net.link || ""}`;
1841
+ list.appendChild(li);
1842
+ }
1843
+ if (!gwGroups.length && !gwNetworks.length) {
1844
+ list.innerHTML = '<li class="sidebar-empty-hint">(\u6682\u65E0\u7F51\u7EDC, \u70B9 + \u52A0\u5165)</li>';
1845
+ }
1846
+ }
1847
+ function openGatewayJoinModal() {
1848
+ const { root, close } = gwModal(`
1849
+ <div class="gw-join">
1850
+ <h3>\u52A0\u5165 Agent \u7F51\u7EDC / \u7FA4\u7EC4</h3>
1851
+ <p class="gw-hint">\u7C98\u8D34\u9080\u8BF7\u94FE\u63A5 (orbitdb://...), \u81EA\u52A8\u8BC6\u522B\u670D\u52A1\u7F51\u7EDC\u6216\u7FA4\u7EC4.</p>
1852
+ <input class="gw-join-input" placeholder="orbitdb:///orbitdb/...?type=group&name=..." />
1853
+ <div class="gw-join-actions">
1854
+ <button class="gw-join-go">\u52A0\u5165</button>
1855
+ <button class="gw-join-my">\u{1F517} \u6211\u7684\u7F51\u7EDC\u94FE\u63A5</button>
1856
+ </div>
1857
+ <div class="gw-join-result"></div>
1858
+ </div>`);
1859
+ const input2 = root.querySelector(".gw-join-input");
1860
+ const go = root.querySelector(".gw-join-go");
1861
+ const my = root.querySelector(".gw-join-my");
1862
+ const result = root.querySelector(".gw-join-result");
1863
+ go.onclick = async () => {
1864
+ const link = String(input2.value || "").trim();
1865
+ if (!link) {
1866
+ result.textContent = "\u8BF7\u8F93\u5165\u94FE\u63A5";
1867
+ return;
1868
+ }
1869
+ if (link.includes("type=group")) {
1870
+ const r = await fetch("/api/gateway/groups/join", {
1871
+ method: "POST",
1872
+ headers: { "Content-Type": "application/json" },
1873
+ body: JSON.stringify({ link })
1874
+ }).then((x) => x.json()).catch(() => ({ ok: false, error: "\u8BF7\u6C42\u5931\u8D25" }));
1875
+ if (r.ok) {
1876
+ result.textContent = r.already ? "\u5DF2\u5728\u8BE5\u7FA4\u7EC4\u4E2D \u2713" : `\u2705 \u5DF2\u52A0\u5165\u7FA4\u7EC4\u300C${r.group?.name || ""}\u300D`;
1877
+ close();
1878
+ loadGatewaySidebar();
1879
+ } else result.textContent = `\u274C ${r.error || "\u52A0\u5165\u5931\u8D25"}`;
1880
+ } else {
1881
+ const r = await fetch("/api/gateway/join", {
1882
+ method: "POST",
1883
+ headers: { "Content-Type": "application/json" },
1884
+ body: JSON.stringify({ link })
1885
+ }).then((x) => x.json()).catch(() => ({ ok: false, error: "\u8BF7\u6C42\u5931\u8D25" }));
1886
+ if (r.ok) {
1887
+ result.textContent = r.already ? "\u5DF2\u5728\u8BE5\u7F51\u7EDC\u4E2D \u2713" : `\u2705 \u5DF2\u52A0\u5165\u7F51\u7EDC (${r.total} \u670D\u52A1, \u65B0\u589E ${r.joined})`;
1888
+ close();
1889
+ loadGatewaySidebar();
1890
+ } else result.textContent = `\u274C ${r.error || "\u52A0\u5165\u5931\u8D25"}`;
1891
+ }
1892
+ };
1893
+ my.onclick = async () => {
1894
+ const r = await fetch("/api/gateway/link").then((x) => x.json()).catch(() => null);
1895
+ if (r?.link) {
1896
+ try {
1897
+ await navigator.clipboard.writeText(r.link);
1898
+ } catch {
1899
+ }
1900
+ result.innerHTML = `\u6211\u7684\u7F51\u7EDC\u9080\u8BF7\u94FE\u63A5\u5DF2\u590D\u5236:<br><code>${gwEsc(r.link)}</code>`;
1901
+ } else result.textContent = "\u274C \u751F\u6210\u94FE\u63A5\u5931\u8D25 (OrbitDB \u672A\u5C31\u7EEA)";
1902
+ };
1903
+ }
1904
+ function openGatewayNewGroupModal() {
1905
+ const { root, close } = gwModal(`
1906
+ <div class="gw-join">
1907
+ <h3>\u521B\u5EFA\u7FA4\u7EC4</h3>
1908
+ <p class="gw-hint">\u7FA4\u7EC4 = \u5FAE\u4FE1\u5F0F\u7FA4\u804A, \u5206\u4EAB\u94FE\u63A5\u9080\u8BF7\u5176\u4ED6 Agent / Bolloon \u52A0\u5165.</p>
1909
+ <input class="gw-join-input" placeholder="\u7FA4\u7EC4\u540D (\u5982: \u7814\u7A76\u534F\u4F5C\u7EC4)" />
1910
+ <div class="gw-join-actions"><button class="gw-join-go">\u521B\u5EFA</button></div>
1911
+ <div class="gw-join-result"></div>
1912
+ </div>`);
1913
+ const input2 = root.querySelector(".gw-join-input");
1914
+ const go = root.querySelector(".gw-join-go");
1915
+ const result = root.querySelector(".gw-join-result");
1916
+ go.onclick = async () => {
1917
+ const name = String(input2.value || "").trim();
1918
+ if (!name) {
1919
+ result.textContent = "\u8BF7\u8F93\u5165\u7FA4\u7EC4\u540D";
1920
+ return;
1921
+ }
1922
+ const r = await fetch("/api/gateway/groups", {
1923
+ method: "POST",
1924
+ headers: { "Content-Type": "application/json" },
1925
+ body: JSON.stringify({ name, from: "web-user" })
1926
+ }).then((x) => x.json()).catch(() => ({ ok: false, error: "\u8BF7\u6C42\u5931\u8D25" }));
1927
+ if (r.ok) {
1928
+ result.innerHTML = `\u2705 \u7FA4\u7EC4\u5DF2\u521B\u5EFA.<br><b>\u9080\u8BF7\u94FE\u63A5:</b><br><code>${gwEsc(r.group?.link)}</code><br>\u590D\u5236\u5206\u4EAB\u7ED9\u5176\u4ED6 Bolloon/Agent.`;
1929
+ loadGatewaySidebar();
1930
+ } else result.textContent = `\u274C ${r.error || "\u521B\u5EFA\u5931\u8D25"}`;
1931
+ };
1932
+ }
1933
+ function openGroupChat(id, name) {
1934
+ gwActiveChat = { id, name };
1935
+ const { root, close } = gwModal(`
1936
+ <div class="gw-chat">
1937
+ <div class="gw-chat-header">
1938
+ <b>\u{1F465} ${gwEsc(name)}</b>
1939
+ <span class="gw-chat-actions">
1940
+ <button class="gw-chat-invite" title="\u590D\u5236\u7FA4\u9080\u8BF7\u94FE\u63A5">\u{1F517} \u9080\u8BF7</button>
1941
+ </span>
1942
+ </div>
1943
+ <div class="gw-chat-msgs" id="gw-msgs-${id}"><div class="gw-msg-empty">\u52A0\u8F7D\u4E2D...</div></div>
1944
+ <div class="gw-chat-input-row">
1945
+ <input class="gw-chat-input" id="gw-input-${id}" placeholder="\u53D1\u6D88\u606F\u7ED9\u7FA4\u6210\u5458... (Enter \u53D1\u9001)" />
1946
+ <button class="gw-chat-send">\u53D1\u9001</button>
1947
+ </div>
1948
+ </div>`);
1949
+ root.querySelector(".gw-chat-invite")?.addEventListener("click", async () => {
1950
+ const r = await fetch(`/api/gateway/groups/${id}/link`).then((x) => x.json()).catch(() => null);
1951
+ if (r?.link) {
1952
+ try {
1953
+ await navigator.clipboard.writeText(r.link);
1954
+ } catch {
1955
+ }
1956
+ gwToast("\u7FA4\u9080\u8BF7\u94FE\u63A5\u5DF2\u590D\u5236, \u5206\u4EAB\u7ED9\u5176\u4ED6 Agent");
1957
+ } else gwToast("\u83B7\u53D6\u94FE\u63A5\u5931\u8D25");
1958
+ });
1959
+ const sendBtn2 = root.querySelector(".gw-chat-send");
1960
+ const input2 = root.querySelector(".gw-chat-input");
1961
+ sendBtn2.onclick = () => {
1962
+ void sendGroupMessage(id);
1963
+ };
1964
+ input2.onkeydown = (e) => {
1965
+ if (e.key === "Enter") {
1966
+ e.preventDefault();
1967
+ void sendGroupMessage(id);
1968
+ }
1969
+ };
1970
+ void loadGroupMessages(id);
1971
+ }
1972
+ async function loadGroupMessages(id) {
1973
+ const box = document.getElementById(`gw-msgs-${id}`);
1974
+ if (!box) return;
1975
+ const r = await fetch(`/api/gateway/groups/${id}/messages?limit=50`).then((x) => x.json()).catch(() => ({ messages: [] }));
1976
+ gwMsgCache.set(id, Array.isArray(r.messages) ? r.messages : []);
1977
+ renderGroupMessages(id);
1978
+ }
1979
+ function renderGroupMessages(id) {
1980
+ const box = document.getElementById(`gw-msgs-${id}`);
1981
+ if (!box) return;
1982
+ const msgs = gwMsgCache.get(id) || [];
1983
+ const myName = (document.getElementById("user-name")?.textContent || "web-user").trim();
1984
+ box.innerHTML = msgs.map((m) => {
1985
+ const mine = m.from === myName || m.from === "web-user" || m.from === "me";
1986
+ const t = new Date(m.ts).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1987
+ return `<div class="gw-msg ${mine ? "gw-msg-mine" : ""}">
1988
+ <div class="gw-msg-meta"><b>${gwEsc(String(m.from).slice(0, 24))}</b> \xB7 ${t}</div>
1989
+ <div class="gw-msg-text">${gwEsc(String(m.text))}</div>
1990
+ </div>`;
1991
+ }).join("") || '<div class="gw-msg-empty">\u7FA4\u8FD8\u6CA1\u6709\u6D88\u606F, \u8BF4\u70B9\u4EC0\u4E48\u5427 \u{1F44B}</div>';
1992
+ box.scrollTop = box.scrollHeight;
1993
+ }
1994
+ async function sendGroupMessage(id) {
1995
+ const input2 = document.getElementById(`gw-input-${id}`);
1996
+ const text = input2?.value?.trim();
1997
+ if (!text) return;
1998
+ const myName = (document.getElementById("user-name")?.textContent || "web-user").trim();
1999
+ const r = await fetch(`/api/gateway/groups/${id}/message`, {
2000
+ method: "POST",
2001
+ headers: { "Content-Type": "application/json" },
2002
+ body: JSON.stringify({ text, from: myName })
2003
+ }).then((x) => x.json()).catch(() => ({ ok: false, error: "\u8BF7\u6C42\u5931\u8D25" }));
2004
+ if (r.ok) {
2005
+ if (input2) input2.value = "";
2006
+ void loadGroupMessages(id);
2007
+ } else gwToast(r.error || "\u53D1\u9001\u5931\u8D25");
2008
+ }
2009
+ function handleGroupMessage(msg) {
2010
+ const { groupId, message, groupName } = msg || {};
2011
+ if (!groupId || !message) return;
2012
+ const cur = gwActiveChat;
2013
+ if (cur && cur.id === groupId) {
2014
+ const cache = gwMsgCache.get(groupId) || [];
2015
+ cache.push(message);
2016
+ gwMsgCache.set(groupId, cache.slice(-100));
2017
+ renderGroupMessages(groupId);
2018
+ } else {
2019
+ gwToast(`\u{1F4E2} ${groupName || "\u7FA4\u7EC4"} \u65B0\u6D88\u606F: ${String(message.text || "").slice(0, 40)}`);
2020
+ }
2021
+ void loadGatewaySidebar();
2022
+ }
2023
+ document.addEventListener("DOMContentLoaded", () => {
2024
+ const addBtn = document.getElementById("gateway-add-btn");
2025
+ if (addBtn) addBtn.onclick = openGatewayJoinModal;
2026
+ const ngBtn = document.getElementById("gateway-new-group-btn");
2027
+ if (ngBtn) ngBtn.onclick = openGatewayNewGroupModal;
2028
+ const gHeader = document.getElementById("gateway-header");
2029
+ if (gHeader) gHeader.onclick = () => {
2030
+ const t = document.getElementById("gateway-toggle");
2031
+ const list = document.getElementById("gateway-list");
2032
+ if (t && list) {
2033
+ const open = t.textContent === "\u25BC";
2034
+ t.textContent = open ? "\u25B6" : "\u25BC";
2035
+ list.style.display = open ? "none" : "";
2036
+ }
2037
+ };
2038
+ void loadGatewaySidebar();
2039
+ setInterval(() => {
2040
+ void loadGatewaySidebar();
2041
+ }, 3e4);
2042
+ });
1774
2043
  var v3GlobalEventSource = null;
1775
2044
  function startV3GlobalSSE() {
1776
2045
  if (v3GlobalEventSource) return;
@@ -1779,6 +2048,10 @@
1779
2048
  v3GlobalEventSource.onmessage = (e) => {
1780
2049
  try {
1781
2050
  const msg = JSON.parse(e.data);
2051
+ if (msg.type === "group-message") {
2052
+ handleGroupMessage(msg);
2053
+ return;
2054
+ }
1782
2055
  if (msg.type === "remote-chat-sent") {
1783
2056
  console.log("[v3] \u6536\u5230 remote-chat-sent:", msg.channelId, "|", String(msg.text || "").slice(0, 30));
1784
2057
  try {