@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
@@ -0,0 +1,278 @@
1
+ /**
2
+ * gateway-network.ts — Agent 网络加入 (2026-08-14 v2)
3
+ *
4
+ * joinNetwork(link): 通过链接自动加入共享 Agent 网络.
5
+ * 链接形式 (三选一):
6
+ * - orbitdb://<storeAddress> 共享 registry store (主链路, OrbitDB 复制)
7
+ * - ipns://<name> IPNS 标识 (registry 静态快照)
8
+ * - https://.../registry HTTP 端点 (远程 registry JSON)
9
+ *
10
+ * v2 新增:
11
+ * - orbitdb:// 真实可开 (CIDDatabase.openStoreByAddress, replica 只读)
12
+ * - 成员身份持久化 ~/.bolloon/gateway-networks.json (重启后仍是家庭成员)
13
+ * - detectGatewayLink / maybeAutoJoinGateway — 消息里收到链接自动加入 (入口要小)
14
+ * - shareNetworkLink — 生成本机可分享的网络链接 (把 registry 发出去)
15
+ */
16
+ import * as os from 'os';
17
+ import * as path from 'path';
18
+ import { getAgentRegistry, warmAgentRegistry } from './agent-registry.js';
19
+ /** 解析链接字符串 → ParsedLink (剥离 ?name= query) */
20
+ export function parseNetworkLink(link) {
21
+ const l = String(link || '').trim();
22
+ if (!l)
23
+ return null;
24
+ const [base, query] = l.split('?');
25
+ let networkName;
26
+ try {
27
+ networkName = query ? (new URLSearchParams(query).get('name') || undefined) : undefined;
28
+ }
29
+ catch { /* 忽略坏 query */ }
30
+ if (base.startsWith('ipns://'))
31
+ return { kind: 'ipns', name: base.slice('ipns://'.length), networkName };
32
+ if (base.startsWith('orbitdb://')) {
33
+ // orbitdb:///orbitdb/<addr> 或 orbitdb://orbitdb/<addr> → /orbitdb/<addr>
34
+ let address = base.slice('orbitdb://'.length);
35
+ if (!address.startsWith('/'))
36
+ address = `/${address}`;
37
+ return { kind: 'orbitdb', address, networkName };
38
+ }
39
+ if (base.startsWith('http://') || base.startsWith('https://'))
40
+ return { kind: 'http', url: base, networkName };
41
+ return null;
42
+ }
43
+ /** 从消息文本里检测 gateway 链接 (自动加入触发器用) */
44
+ export function detectGatewayLink(text) {
45
+ const t = String(text || '');
46
+ // orbitdb:// 地址含 '/' 必须贪婪匹配到空白/引号; https 允许 /registry 后带 ?query
47
+ const re = /(orbitdb:\/\/\/?orbitdb\/[^\s)'"<>,。;]+|ipns:\/\/[^\s)'"<>,。;]+|https?:\/\/[^\s)'"<>,。;]*\/registry(?:\?[^\s)'"<>,。;]*)?)/;
48
+ const m = re.exec(t);
49
+ return m ? m[1].trim() : null;
50
+ }
51
+ // ============ 远端拉取 ============
52
+ /** 从 HTTP 端点拉取远端 registry */
53
+ async function fetchRemoteRegistry(url) {
54
+ try {
55
+ const r = await fetch(url, { signal: AbortSignal.timeout(15000) });
56
+ if (!r.ok)
57
+ return null;
58
+ const data = await r.json();
59
+ // 兼容: {services:[...]} 或 [...]
60
+ const services = Array.isArray(data) ? data : (data.services ?? null);
61
+ return Array.isArray(services) ? services : null;
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ }
67
+ /** 从 IPNS 拉取 registry (需本地 Kubo + 8080 gateway) */
68
+ async function fetchIpnsRegistry(name) {
69
+ try {
70
+ const r = await fetch(`http://127.0.0.1:8080/ipns/${name}/registry.json`, { signal: AbortSignal.timeout(15000) });
71
+ if (!r.ok)
72
+ return null;
73
+ const data = await r.json();
74
+ return Array.isArray(data) ? data : (data.services ?? null);
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ /** 从 OrbitDB 打开共享 registry store (replica 只读) */
81
+ async function fetchOrbitdbRegistry(address) {
82
+ try {
83
+ const { getCIDDatabase } = await import('../orbitdb/cid-database.js');
84
+ const db = getCIDDatabase();
85
+ const store = await db.openStoreByAddress(address, 'keyvalue');
86
+ if (!store)
87
+ return null;
88
+ // 先立即读 (同节点 store 已有数据); 没有再等复制 (owner 在线时 pubsub 复制通常 <1s)
89
+ const first = await store.get('services').catch(() => null);
90
+ if (Array.isArray(first))
91
+ return first;
92
+ await new Promise((resolve) => {
93
+ let done = false;
94
+ const finish = () => { if (!done) {
95
+ done = true;
96
+ try {
97
+ off();
98
+ }
99
+ catch { }
100
+ resolve();
101
+ } };
102
+ const off = store.onChange(finish);
103
+ setTimeout(finish, 4000);
104
+ });
105
+ // 单键 'services' (registry 的 OrbitDB 布局: 整个列表存单键)
106
+ const v = await store.get('services').catch(() => null);
107
+ if (Array.isArray(v))
108
+ return v;
109
+ // 兼容: 遍历 entries 找数组值
110
+ const all = await store.all().catch(() => null);
111
+ if (Array.isArray(all)) {
112
+ for (const entry of all) {
113
+ if (Array.isArray(entry.value))
114
+ return entry.value;
115
+ const val = entry.value;
116
+ if (val?.services && Array.isArray(val.services))
117
+ return val.services;
118
+ }
119
+ }
120
+ return null;
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ }
126
+ const networksFile = () => path.join(os.homedir() || '/tmp', '.bolloon', 'gateway-networks.json');
127
+ async function loadNetworks() {
128
+ try {
129
+ const { readFile } = await import('fs/promises');
130
+ const parsed = JSON.parse(await readFile(networksFile(), 'utf-8'));
131
+ return Array.isArray(parsed) ? parsed : [];
132
+ }
133
+ catch {
134
+ return [];
135
+ }
136
+ }
137
+ async function saveNetworks(list) {
138
+ try {
139
+ const { mkdir, writeFile } = await import('fs/promises');
140
+ await mkdir(path.dirname(networksFile()), { recursive: true });
141
+ await writeFile(networksFile(), JSON.stringify(list, null, 2), 'utf-8');
142
+ }
143
+ catch { /* 持久化失败静默 */ }
144
+ }
145
+ /** 列出已加入的网络 */
146
+ export async function listJoinedNetworks() {
147
+ return loadNetworks();
148
+ }
149
+ /**
150
+ * 通过链接加入共享网络: 拉取远端服务列表 → 合并到本地 registry (按 agentId+service 去重).
151
+ * 幂等: 已加入的网络直接返回 already=true.
152
+ * deps.registry 可注入 (测试用), 默认单例.
153
+ */
154
+ export async function joinNetwork(link, deps) {
155
+ const parsed = parseNetworkLink(link);
156
+ if (!parsed) {
157
+ return { ok: false, joined: 0, total: 0, error: '无法解析链接 (支持 orbitdb:// / ipns:// / https://)' };
158
+ }
159
+ // 幂等: 已加入 (按解析后的网络身份 key 去重, 忽略 ?name 差异)
160
+ const existing = await loadNetworks();
161
+ const norm = String(link).trim();
162
+ const identityKey = parsed.kind === 'orbitdb' ? `orbitdb:${parsed.address}`
163
+ : parsed.kind === 'ipns' ? `ipns:${parsed.name}`
164
+ : `http:${parsed.url}`;
165
+ if (existing.some((n) => n.linkKey === identityKey || n.link === norm)) {
166
+ return { ok: true, joined: 0, total: 0, already: true, linkKind: parsed.kind, networkName: parsed.networkName };
167
+ }
168
+ // 拉取远端服务
169
+ let remote = null;
170
+ if (parsed.kind === 'http') {
171
+ remote = await fetchRemoteRegistry(parsed.url);
172
+ }
173
+ else if (parsed.kind === 'ipns') {
174
+ remote = await fetchIpnsRegistry(parsed.name);
175
+ }
176
+ else if (parsed.kind === 'orbitdb') {
177
+ remote = await fetchOrbitdbRegistry(parsed.address);
178
+ }
179
+ if (!remote || remote.length === 0) {
180
+ return { ok: false, joined: 0, total: 0, error: '远端网络无服务或不可达 (store owner 需在线)', linkKind: parsed.kind };
181
+ }
182
+ // 合并到本地 registry (按 agentId + service.name 去重)
183
+ const registry = deps?.registry ?? getAgentRegistry();
184
+ const local = await registry.list();
185
+ let joined = 0;
186
+ for (const svc of remote) {
187
+ if (!svc?.agentId || !svc?.service?.name)
188
+ continue;
189
+ const exists = local.some((l) => l.agentId === svc.agentId && l.service?.name === svc.service?.name);
190
+ if (!exists) {
191
+ await registry.register(svc).catch(() => { });
192
+ joined++;
193
+ }
194
+ }
195
+ // 记录成员身份 (持久化 → 重启后自动恢复)
196
+ await saveNetworks([
197
+ ...existing,
198
+ {
199
+ link: norm,
200
+ linkKey: identityKey,
201
+ kind: parsed.kind,
202
+ name: parsed.networkName,
203
+ joinedAt: new Date().toISOString(),
204
+ serviceCount: remote.length,
205
+ lastSyncAt: new Date().toISOString(),
206
+ },
207
+ ]);
208
+ return { ok: true, joined, total: remote.length, linkKind: parsed.kind, networkName: parsed.networkName };
209
+ }
210
+ /** 启动恢复: 重拉所有已加入网络 (失败静默, 保留记录). 返回恢复统计. */
211
+ export async function restoreJoinedNetworks() {
212
+ const nets = await loadNetworks();
213
+ if (nets.length === 0)
214
+ return { restored: 0, failed: 0, total: 0 };
215
+ let restored = 0;
216
+ let failed = 0;
217
+ for (const n of nets) {
218
+ const r = await joinNetwork(n.link).catch(() => null);
219
+ if (r?.ok)
220
+ restored++;
221
+ else
222
+ failed++;
223
+ // 更新 lastSyncAt
224
+ if (r?.ok) {
225
+ const updated = (await loadNetworks()).map((m) => m.link === n.link ? { ...m, lastSyncAt: new Date().toISOString(), serviceCount: r.total || m.serviceCount } : m);
226
+ await saveNetworks(updated);
227
+ }
228
+ }
229
+ return { restored, failed, total: nets.length };
230
+ }
231
+ // ============ 分享链接 ============
232
+ /**
233
+ * 生成本机可分享的网络链接: orbitdb://<registry storeAddress>?name=<网络名>.
234
+ * 对方收到链接 → 自动 joinNetwork → 拉取本机注册的服务.
235
+ * opts.registry 可注入 (测试用), 默认单例.
236
+ */
237
+ export async function shareNetworkLink(opts) {
238
+ try {
239
+ let registry = opts?.registry;
240
+ if (!registry) {
241
+ await warmAgentRegistry();
242
+ registry = getAgentRegistry();
243
+ }
244
+ if (!registry.ready || !registry.storeAddress) {
245
+ return { ok: false, error: 'OrbitDB registry 未就绪 (离线模式). 备选: 把 registry 列表发布成 https://.../registry 端点分享' };
246
+ }
247
+ const name = encodeURIComponent(String(opts?.name || registry.storeName || 'bolloon-network'));
248
+ return { ok: true, link: `orbitdb://${registry.storeAddress}?name=${name}` };
249
+ }
250
+ catch (e) {
251
+ return { ok: false, error: `生成分享链接失败: ${String(e?.message || e).slice(0, 160)}` };
252
+ }
253
+ }
254
+ // ============ 自动加入 (消息触发) ============
255
+ /**
256
+ * 自动加入入口: 文本里检测到 gateway 链接 → 幂等 joinNetwork.
257
+ * 返回给 agent 的通知字符串 (无链接 / 已在网络 → null, 静默).
258
+ * 设计: 加入是自由的 (只拉服务列表, 不花钱), 支付仍走 payment-gate 安全链.
259
+ * deps.registry 可注入 (测试用), 默认单例.
260
+ */
261
+ export async function maybeAutoJoinGateway(text, deps) {
262
+ const link = detectGatewayLink(text);
263
+ if (!link)
264
+ return null;
265
+ try {
266
+ const r = await joinNetwork(link, deps);
267
+ if (r.ok && r.already)
268
+ return null; // 已在网络, 静默
269
+ if (r.ok) {
270
+ const netName = r.networkName ? `「${r.networkName}」` : ''; // URLSearchParams 已 decode
271
+ return `🆕 已自动加入 Agent 网络${netName} (${r.linkKind}): 拉取 ${r.total} 个服务, 新增 ${r.joined} 个。用 gateway_status 查看, gateway_call 调用网络里的服务。`;
272
+ }
273
+ return `⚠️ 检测到 Agent 网络链接 (${r.linkKind || 'unknown'}) 但加入失败: ${r.error}`;
274
+ }
275
+ catch (e) {
276
+ return `⚠️ 自动加入 Agent 网络失败: ${String(e?.message || e).slice(0, 160)}`;
277
+ }
278
+ }
@@ -148,20 +148,20 @@ export async function distillDissent(ask) {
148
148
  .slice(-10)
149
149
  .flatMap((j) => j.reasons || [])
150
150
  .slice(0, 20);
151
- const prompt = `你是用户的判断力代理. 用户发起了一个决定: "${ask.decision}"
152
- ${ask.context ? `\n补充: ${ask.context}` : ''}
153
-
154
- [用户价值画像] ${valueHint}
155
- [相关历史判断 (${relevant.length} 条)] ${relevant.slice(0, 3).map((j) => j.decision || '').join(' | ').slice(0, 300)}
156
- [历史理由样本] ${recentReasons.join(' | ').slice(0, 400) || '(无)'}
157
-
158
- 请基于上述判断力, 生成正好 3 个"反方观点" (用户应该考虑但可能忽略的风险/盲点).
159
- 要求:
160
- - 每个反方 1-2 句, 总长 < 80 字
161
- - 必须是这个特定决定的"反对声音", 不是通用建议
162
- - 第 1 个: 历史/经验类风险
163
- - 第 2 个: 关系/信任类风险
164
- - 第 3 个: 隐藏代价/时间类风险
151
+ const prompt = `你是用户的判断力代理. 用户发起了一个决定: "${ask.decision}"
152
+ ${ask.context ? `\n补充: ${ask.context}` : ''}
153
+
154
+ [用户价值画像] ${valueHint}
155
+ [相关历史判断 (${relevant.length} 条)] ${relevant.slice(0, 3).map((j) => j.decision || '').join(' | ').slice(0, 300)}
156
+ [历史理由样本] ${recentReasons.join(' | ').slice(0, 400) || '(无)'}
157
+
158
+ 请基于上述判断力, 生成正好 3 个"反方观点" (用户应该考虑但可能忽略的风险/盲点).
159
+ 要求:
160
+ - 每个反方 1-2 句, 总长 < 80 字
161
+ - 必须是这个特定决定的"反对声音", 不是通用建议
162
+ - 第 1 个: 历史/经验类风险
163
+ - 第 2 个: 关系/信任类风险
164
+ - 第 3 个: 隐藏代价/时间类风险
165
165
  - 用 JSON 数组返回: ["反方1", "反方2", "反方3"]`;
166
166
  // LLM 调用 (OpenAI 兼容, 复用 p2p-chat-tools 的方式)
167
167
  let dissents = [];
@@ -2505,6 +2505,123 @@ export function registerBuiltinTools(ctx) {
2505
2505
  }
2506
2506
  },
2507
2507
  });
2508
+ // 2026-08-14: Agent Gateway — 经济协调层统一入口 (注册/调用/加入网络/状态)
2509
+ ctx.tools.set('gateway_register', {
2510
+ name: 'gateway_register',
2511
+ description: '把本 Agent 注册为服务提供者 (Agent Gateway 入口). capability: 能力名 (research/coding/data...); price: 价格; per: 计价单位; wallet: 收款地址. 注册后其他 Agent 能发现并调用你.',
2512
+ parameters: {
2513
+ capability: '能力名 (必填, research/coding/data/compute...)',
2514
+ price: '价格 (必填, 如 0.05)',
2515
+ currency: '币种 (默认 USDC)',
2516
+ per: '计价单位 (默认 query)',
2517
+ description: '服务描述 (可选)',
2518
+ wallet: '收款钱包地址 (可选)',
2519
+ },
2520
+ execute: async (args) => {
2521
+ const { gatewayRegisterAgent } = await import('./agent-gateway.js');
2522
+ const r = await gatewayRegisterAgent({
2523
+ capability: String(args.capability || '').trim(),
2524
+ price: String(args.price || '').trim(),
2525
+ currency: String(args.currency || 'USDC'),
2526
+ per: String(args.per || 'query'),
2527
+ description: String(args.description || '').trim() || undefined,
2528
+ wallet: String(args.wallet || '').trim() || undefined,
2529
+ }, { did: ctx.identity?.did || '', name: ctx.identity?.name || 'agent', wallet: String(args.wallet || '') });
2530
+ return r.ok
2531
+ ? { success: true, output: `✅ 已加入 Agent 网络: ${args.capability} @ ${args.price} ${args.currency}/${args.per}` }
2532
+ : { success: false, error: r.error };
2533
+ },
2534
+ });
2535
+ ctx.tools.set('gateway_call', {
2536
+ name: 'gateway_call',
2537
+ description: '通过 Agent Gateway 调用服务 (自动闭环: 发现→预算→验证门→执行→信誉). task: 任务描述; budget: 预算 (USDC); capability: 需要的能力. 需人工确认的支付会返回 approval 待审批.',
2538
+ parameters: {
2539
+ task: '任务描述 (必填)',
2540
+ budget: '预算 USDC (必填)',
2541
+ capability: '需要的能力 (可选, 如 research)',
2542
+ url: '服务端点 URL (可选)',
2543
+ },
2544
+ execute: async (args) => {
2545
+ const task = String(args.task || '').trim();
2546
+ const budget = Number(args.budget);
2547
+ if (!task || !budget || budget <= 0)
2548
+ return { success: false, error: 'task 和 budget(>0) 必填' };
2549
+ try {
2550
+ const { gatewayCallAgent } = await import('./agent-gateway.js');
2551
+ const r = await gatewayCallAgent({
2552
+ task,
2553
+ budget,
2554
+ capability: String(args.capability || '').trim() || undefined,
2555
+ url: String(args.url || '').trim() || undefined,
2556
+ });
2557
+ if (r.success)
2558
+ return { success: true, output: `✅ ${r.provider}: ${r.output}` };
2559
+ return { success: false, error: r.error, requiresApproval: r.requiresApproval, approvalId: r.approvalId, provider: r.provider };
2560
+ }
2561
+ catch (e) {
2562
+ return { success: false, error: `gateway_call 失败: ${String(e?.message || e).slice(0, 200)}` };
2563
+ }
2564
+ },
2565
+ });
2566
+ ctx.tools.set('gateway_join', {
2567
+ name: 'gateway_join',
2568
+ description: '通过链接加入共享 Agent 网络 (拉取远端服务合并到本地 registry). link: ipns://<name> 或 orbitdb://<address> 或 https://.../registry. 加入后可用 gateway_call 调用网络里的服务.',
2569
+ parameters: { link: '网络链接 (必填, ipns:// / orbitdb:// / https://)' },
2570
+ execute: async (args) => {
2571
+ const link = String(args.link || '').trim();
2572
+ if (!link)
2573
+ return { success: false, error: 'link 必填 (ipns:// / orbitdb:// / https://)' };
2574
+ try {
2575
+ const { joinNetwork } = await import('./gateway-network.js');
2576
+ const r = await joinNetwork(link);
2577
+ if (!r.ok)
2578
+ return { success: false, error: r.error };
2579
+ return { success: true, output: `✅ 已加入 Agent 网络: 拉取 ${r.total} 个服务, 新增 ${r.joined} 个 (${r.linkKind})` };
2580
+ }
2581
+ catch (e) {
2582
+ return { success: false, error: `gateway_join 失败: ${String(e?.message || e).slice(0, 200)}` };
2583
+ }
2584
+ },
2585
+ });
2586
+ ctx.tools.set('gateway_status', {
2587
+ name: 'gateway_status',
2588
+ description: '查看 Agent 网络状态 (已注册服务 + 信誉 + 已加入的网络).',
2589
+ parameters: {},
2590
+ execute: async () => {
2591
+ try {
2592
+ const { gatewayStatus } = await import('./agent-gateway.js');
2593
+ const { listJoinedNetworks } = await import('./gateway-network.js');
2594
+ const nets = await listJoinedNetworks();
2595
+ const netLine = nets.length
2596
+ ? `\n已加入网络 (${nets.length}):\n` + nets.slice(0, 10).map((n) => ` [${n.kind}] ${n.name || n.link.slice(0, 48)} (${n.serviceCount} 服务, ${n.joinedAt.slice(0, 10)})`).join('\n')
2597
+ : '\n(未加入任何网络, 收到 orbitdb:// 链接会自动加入, 或用 gateway_join)';
2598
+ return { success: true, output: (await gatewayStatus()) + netLine };
2599
+ }
2600
+ catch (e) {
2601
+ return { success: false, error: `gateway_status 失败: ${String(e?.message || e).slice(0, 200)}` };
2602
+ }
2603
+ },
2604
+ });
2605
+ ctx.tools.set('gateway_share', {
2606
+ name: 'gateway_share',
2607
+ description: '生成本 Agent 网络的分享链接 (orbitdb://...). 把链接发给其他 Bolloon/Agent, 对方收到后会自动加入你的网络并发现你注册的服务.',
2608
+ parameters: {
2609
+ name: '网络名 (可选, 默认 registry 名)',
2610
+ },
2611
+ execute: async (args) => {
2612
+ try {
2613
+ const { shareNetworkLink } = await import('./gateway-network.js');
2614
+ const name = String(args.name || '').trim() || undefined;
2615
+ const r = await shareNetworkLink(name ? { name } : undefined);
2616
+ if (!r.ok)
2617
+ return { success: false, error: r.error };
2618
+ return { success: true, output: `🔗 Agent 网络分享链接 (对方收到后自动加入):\n${r.link}` };
2619
+ }
2620
+ catch (e) {
2621
+ return { success: false, error: `gateway_share 失败: ${String(e?.message || e).slice(0, 200)}` };
2622
+ }
2623
+ },
2624
+ });
2508
2625
  // ============================================================
2509
2626
  // publish_did (2026-08-03) — 把当前 agent 的 DID 发布到 IPFS + IPNS
2510
2627
  // 全自动: 自动安装/启动本地 Kubo → 上传 DID 文档 → 发布 IPNS name
@@ -1,13 +1,13 @@
1
- export const TOOL_DEFINITIONS = `
2
- 可用工具:
3
- 1. read_document(path) - 读取文档内容,支持 .txt, .md, .pdf, .docx
4
- 2. summarize_document(path, context?) - 总结文档内容,可选提供上下文
5
- 3. improve_document(path, requirements) - 改进文档,需提供文件路径和改进要求
6
- 4. list_peers() - 列出已连接的对等节点
7
- 5. send_message(peer_id, message) - 向指定对等节点发送消息
8
- 6. broadcast_message(message) - 向所有对等节点广播消息
9
- 7. get_identity() - 获取当前智能体身份信息
10
- 8. set_persona(persona_json) - 更新智能体 persona,包含 name、description、personality、greeting 等
11
- 9. run_workflow(steps) - 执行预定义工作流
12
- 10. get_operation_logs() - 获取操作日志
1
+ export const TOOL_DEFINITIONS = `
2
+ 可用工具:
3
+ 1. read_document(path) - 读取文档内容,支持 .txt, .md, .pdf, .docx
4
+ 2. summarize_document(path, context?) - 总结文档内容,可选提供上下文
5
+ 3. improve_document(path, requirements) - 改进文档,需提供文件路径和改进要求
6
+ 4. list_peers() - 列出已连接的对等节点
7
+ 5. send_message(peer_id, message) - 向指定对等节点发送消息
8
+ 6. broadcast_message(message) - 向所有对等节点广播消息
9
+ 7. get_identity() - 获取当前智能体身份信息
10
+ 8. set_persona(persona_json) - 更新智能体 persona,包含 name、description、personality、greeting 等
11
+ 9. run_workflow(steps) - 执行预定义工作流
12
+ 10. get_operation_logs() - 获取操作日志
13
13
  `;