@bolloon/bolloon-agent 0.4.32 → 0.5.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 (157) hide show
  1. package/dist/agents/chain/explorer.js +52 -0
  2. package/dist/agents/chain/index.js +2 -0
  3. package/dist/agents/chain/onchain-trade.js +15 -1
  4. package/dist/agents/contacts/chain.js +27 -7
  5. package/dist/agents/execution-supervisor.js +493 -35
  6. package/dist/agents/external-events.js +35 -6
  7. package/dist/agents/gateway-group.js +100 -12
  8. package/dist/agents/goal-criteria.js +10 -3
  9. package/dist/agents/goal-flywheel/block-executor.js +346 -0
  10. package/dist/agents/goal-flywheel/continuation-decision.js +592 -0
  11. package/dist/agents/goal-flywheel/goal-change.js +754 -0
  12. package/dist/agents/goal-flywheel/index.js +26 -0
  13. package/dist/agents/goal-flywheel/memory-layers.js +227 -0
  14. package/dist/agents/goal-flywheel/run-closure.js +809 -0
  15. package/dist/agents/goal-flywheel/skill-candidate.js +628 -0
  16. package/dist/agents/goal-flywheel/types.js +329 -0
  17. package/dist/agents/goal-flywheel/wiring/change.js +288 -0
  18. package/dist/agents/goal-flywheel/wiring/closure.js +697 -0
  19. package/dist/agents/goal-flywheel/wiring/continuation.js +432 -0
  20. package/dist/agents/goal-flywheel/wiring/contract.js +270 -0
  21. package/dist/agents/goal-flywheel/wiring/index.js +26 -0
  22. package/dist/agents/goal-flywheel/wiring/monitor.js +254 -0
  23. package/dist/agents/goal-flywheel/wiring/seams.js +592 -0
  24. package/dist/agents/goal-flywheel/work-contract.js +478 -0
  25. package/dist/agents/goal-flywheel/work-monitor.js +488 -0
  26. package/dist/agents/goal-flywheel-wiring.js +1870 -0
  27. package/dist/agents/goal-state-reducer.js +406 -0
  28. package/dist/agents/goal-store.js +35 -1
  29. package/dist/agents/mobile-flywheel-view.js +144 -0
  30. package/dist/agents/mobile-task-actions-verify.js +74 -0
  31. package/dist/agents/mobile-task-actions.js +178 -0
  32. package/dist/agents/mobile-task-views.js +199 -0
  33. package/dist/agents/network-pulse.js +525 -27
  34. package/dist/agents/pi-sdk.js +75 -20
  35. package/dist/agents/run-store.js +18 -5
  36. package/dist/agents/skill-readiness.js +52 -10
  37. package/dist/agents/subagent-manager.js +209 -3
  38. package/dist/agents/task/task-onchain-runner.js +19 -1
  39. package/dist/agents/task/task-runner.js +36 -6
  40. package/dist/agents/task-board.js +702 -0
  41. package/dist/agents/task-group.js +524 -0
  42. package/dist/agents/task-public-text.js +89 -0
  43. package/dist/cli/commands/index.js +3 -0
  44. package/dist/cli/commands/tasks.js +977 -8
  45. package/dist/cli/identity-command.js +177 -0
  46. package/dist/cli/protocol-envelope.js +4 -0
  47. package/dist/cli/setup-wizard.js +71 -0
  48. package/dist/cli/update-commands.js +150 -24
  49. package/dist/cli-entry.js +12 -2
  50. package/dist/electron-build/agents/chain/explorer.js +59 -0
  51. package/dist/electron-build/agents/chain/explorer.js.map +1 -0
  52. package/dist/electron-build/agents/contacts/chain.js +26 -6
  53. package/dist/electron-build/agents/contacts/chain.js.map +1 -1
  54. package/dist/electron-build/agents/execution-supervisor.js +492 -34
  55. package/dist/electron-build/agents/execution-supervisor.js.map +1 -1
  56. package/dist/electron-build/agents/external-events.js +34 -5
  57. package/dist/electron-build/agents/external-events.js.map +1 -1
  58. package/dist/electron-build/agents/goal-criteria.js +10 -3
  59. package/dist/electron-build/agents/goal-criteria.js.map +1 -1
  60. package/dist/electron-build/agents/goal-flywheel/continuation-decision.js +598 -0
  61. package/dist/electron-build/agents/goal-flywheel/continuation-decision.js.map +1 -0
  62. package/dist/electron-build/agents/goal-flywheel/goal-change.js +773 -0
  63. package/dist/electron-build/agents/goal-flywheel/goal-change.js.map +1 -0
  64. package/dist/electron-build/agents/goal-flywheel/memory-layers.js +269 -0
  65. package/dist/electron-build/agents/goal-flywheel/memory-layers.js.map +1 -0
  66. package/dist/electron-build/agents/goal-flywheel/run-closure.js +818 -0
  67. package/dist/electron-build/agents/goal-flywheel/run-closure.js.map +1 -0
  68. package/dist/electron-build/agents/goal-flywheel/skill-candidate.js +642 -0
  69. package/dist/electron-build/agents/goal-flywheel/skill-candidate.js.map +1 -0
  70. package/dist/electron-build/agents/goal-flywheel/types.js +333 -0
  71. package/dist/electron-build/agents/goal-flywheel/types.js.map +1 -0
  72. package/dist/electron-build/agents/goal-flywheel/wiring/change.js +294 -0
  73. package/dist/electron-build/agents/goal-flywheel/wiring/change.js.map +1 -0
  74. package/dist/electron-build/agents/goal-flywheel/wiring/closure.js +742 -0
  75. package/dist/electron-build/agents/goal-flywheel/wiring/closure.js.map +1 -0
  76. package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js +444 -0
  77. package/dist/electron-build/agents/goal-flywheel/wiring/continuation.js.map +1 -0
  78. package/dist/electron-build/agents/goal-flywheel/wiring/contract.js +279 -0
  79. package/dist/electron-build/agents/goal-flywheel/wiring/contract.js.map +1 -0
  80. package/dist/electron-build/agents/goal-flywheel/wiring/index.js +111 -0
  81. package/dist/electron-build/agents/goal-flywheel/wiring/index.js.map +1 -0
  82. package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js +264 -0
  83. package/dist/electron-build/agents/goal-flywheel/wiring/monitor.js.map +1 -0
  84. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js +612 -0
  85. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js.map +1 -0
  86. package/dist/electron-build/agents/goal-flywheel/work-contract.js +488 -0
  87. package/dist/electron-build/agents/goal-flywheel/work-contract.js.map +1 -0
  88. package/dist/electron-build/agents/goal-flywheel/work-monitor.js +501 -0
  89. package/dist/electron-build/agents/goal-flywheel/work-monitor.js.map +1 -0
  90. package/dist/electron-build/agents/goal-flywheel-wiring.js +1962 -0
  91. package/dist/electron-build/agents/goal-flywheel-wiring.js.map +1 -0
  92. package/dist/electron-build/agents/goal-state-reducer.js +414 -0
  93. package/dist/electron-build/agents/goal-state-reducer.js.map +1 -0
  94. package/dist/electron-build/agents/goal-store.js +35 -1
  95. package/dist/electron-build/agents/goal-store.js.map +1 -1
  96. package/dist/electron-build/agents/local-signer.js +101 -0
  97. package/dist/electron-build/agents/local-signer.js.map +1 -0
  98. package/dist/electron-build/agents/network-pulse.js +531 -28
  99. package/dist/electron-build/agents/network-pulse.js.map +1 -1
  100. package/dist/electron-build/agents/pi-sdk.js +74 -19
  101. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  102. package/dist/electron-build/agents/run-store.js +20 -5
  103. package/dist/electron-build/agents/run-store.js.map +1 -1
  104. package/dist/electron-build/agents/skill-readiness.js +52 -9
  105. package/dist/electron-build/agents/skill-readiness.js.map +1 -1
  106. package/dist/electron-build/agents/task/task-runner.js +35 -5
  107. package/dist/electron-build/agents/task/task-runner.js.map +1 -1
  108. package/dist/electron-build/agents/task-board.js +761 -0
  109. package/dist/electron-build/agents/task-board.js.map +1 -0
  110. package/dist/electron-build/agents/task-contract.js +382 -0
  111. package/dist/electron-build/agents/task-contract.js.map +1 -0
  112. package/dist/electron-build/orbitdb/cid-database.js +83 -17
  113. package/dist/electron-build/orbitdb/cid-database.js.map +1 -1
  114. package/dist/electron-build/orbitdb/ipfs-node.js +31 -2
  115. package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -1
  116. package/dist/electron-build/utils/dual-source.js +471 -0
  117. package/dist/electron-build/utils/dual-source.js.map +1 -0
  118. package/dist/electron-build/utils/update-manager.js +331 -57
  119. package/dist/electron-build/utils/update-manager.js.map +1 -1
  120. package/dist/electron-build/utils/update-state.js +16 -1
  121. package/dist/electron-build/utils/update-state.js.map +1 -1
  122. package/dist/electron-build/utils/version-info.js +82 -2
  123. package/dist/electron-build/utils/version-info.js.map +1 -1
  124. package/dist/index.js +103 -12
  125. package/dist/ios/chain-explorer.js +617 -0
  126. package/dist/ios/explorer.html +163 -0
  127. package/dist/ios/index.html +96 -0
  128. package/dist/ios/mobile-agent.js +2 -2
  129. package/dist/ios/mobile-contacts.js +329 -0
  130. package/dist/ios/mobile-core.js +1379 -226
  131. package/dist/ios/mobile-privacy.js +185 -0
  132. package/dist/ios/mobile.css +19 -0
  133. package/dist/ios/mobile.html +96 -0
  134. package/dist/ios/mobile.js +706 -7
  135. package/dist/ios/routes-chain-index.js +108 -0
  136. package/dist/ios/routes-contacts.js +420 -0
  137. package/dist/ios/routes-onchain-trade.js +99 -0
  138. package/dist/ios/routes-x402-info.js +1 -0
  139. package/dist/ios/server.js +762 -0
  140. package/dist/ios/task-frame-server.js +211 -0
  141. package/dist/orbitdb/cid-database.js +81 -16
  142. package/dist/orbitdb/ipfs-node.js +31 -2
  143. package/dist/utils/dual-source.js +426 -0
  144. package/dist/utils/update-cli.js +16 -21
  145. package/dist/utils/update-health.js +35 -5
  146. package/dist/utils/update-manager.js +329 -57
  147. package/dist/utils/update-state.js +16 -1
  148. package/dist/utils/version-info.js +75 -1
  149. package/dist/web/mobile-contacts.js +44 -11
  150. package/dist/web/mobile-core.js +1197 -513
  151. package/dist/web/mobile-tasks.js +339 -0
  152. package/dist/web/mobile.css +19 -0
  153. package/dist/web/mobile.html +64 -0
  154. package/dist/web/mobile.js +531 -1
  155. package/dist/web/routes-mobile-tasks.js +353 -0
  156. package/dist/web/server.js +163 -4
  157. package/package.json +3 -1
@@ -0,0 +1,52 @@
1
+ /**
2
+ * explorer.ts — 区块浏览器映射 (chainId → 公网浏览器) + **交易**链接构造
3
+ *
4
+ * 只回答一件事: **这条链有没有已知的公网浏览器**。
5
+ * · 有 → `https://<explorer>/tx/0x…` (公开可核验的链上事实)
6
+ * · 认不出 / 本机隔离开发链 (31337) → **null** —— 没有公网浏览器就**不给链接**,
7
+ * 绝不编造 `href="#"`、死链或猜一个域名 (宁缺勿错)。
8
+ *
9
+ * 隐私红线 (2026-09-23 leo 拍板; 同日收窄):
10
+ * · 允许出现在公开快照里的 0x 字符串**只有两种**: 交易哈希 (0x+64 hex) 与 escrow **合约**地址
11
+ * (0x+40 hex) —— 它们本来就是公开链上事实。
12
+ * · 但**页面只可点交易**: escrow 合约地址保留在行数据里供索引/诊断, **不渲染、不生成合约链接**
13
+ * (所以本文件**没有** address 链接构造器 —— 少一个能凭空造出合约链接的入口)。
14
+ * · EOA / 钱包地址 (买方·卖方·payTo 之类)、taskKey 原文、taskId、args 里的地址、DID、
15
+ * peer IP / multiaddr、私钥 —— **一个都不许**经这里或别处进快照。
16
+ * · 本文件只构造 URL, 不读盘不发 RPC, 也从不接受「调用方说它是合约地址」的自我声明。
17
+ */
18
+ /** chainId → 公网浏览器 base URL (白名单; 认不出的一律没有) */
19
+ export const EXPLORER_BY_CHAIN = Object.freeze({
20
+ 8453: 'https://basescan.org', // Base 主网
21
+ 84532: 'https://sepolia.basescan.org', // Base Sepolia 测试网
22
+ 1: 'https://etherscan.io', // Ethereum 主网
23
+ 11155111: 'https://sepolia.etherscan.io', // Sepolia 测试网
24
+ });
25
+ /** 交易哈希: 小写 0x + 64 位十六进制 (词法唯一形状) */
26
+ export const TX_HASH_RE = /^0x[0-9a-f]{64}$/;
27
+ /** 地址: 小写 0x + 40 位十六进制 (合约地址同样长这样 —— 是**谁**由调用方的白名单决定) */
28
+ export const ADDRESS_RE = /^0x[0-9a-f]{40}$/;
29
+ /**
30
+ * 浏览器**交易**链接形状 (反向校验用): https + 已知浏览器域名 + `/tx/0x64hex`。
31
+ * 给守卫 / 单测一把「这不是我们造的链接」的尺子 —— 端口 / 凭据 / 别的路径 (含 `/address/`) 一律不认。
32
+ */
33
+ export const EXPLORER_URL_RE = /^https:\/\/(?:[a-z0-9-]+\.)*(?:basescan\.org|etherscan\.io)\/tx\/0x[0-9a-f]{64}$/;
34
+ /** chainId 有没有已知公网浏览器 → base URL; 认不出 (含本机 31337) → null */
35
+ export function explorerBaseUrl(chainId) {
36
+ const id = Number(chainId);
37
+ if (!Number.isInteger(id) || id < 0)
38
+ return null;
39
+ return EXPLORER_BY_CHAIN[id] ?? null;
40
+ }
41
+ /** 交易链接; 链没浏览器 / 哈希非法 → null (调用方**不要**填 null 之外的占位) */
42
+ export function explorerTxUrl(chainId, txHash) {
43
+ const base = explorerBaseUrl(chainId);
44
+ const h = String(txHash ?? '').toLowerCase();
45
+ if (!base || !TX_HASH_RE.test(h))
46
+ return null;
47
+ return `${base}/tx/${h}`;
48
+ }
49
+ /** 这个字符串是不是我们亲手造的那种**交易**浏览器链接 (守卫 / 单测用) */
50
+ export function isExplorerUrl(url) {
51
+ return typeof url === 'string' && EXPLORER_URL_RE.test(url);
52
+ }
@@ -9,6 +9,7 @@
9
9
  * · chain-state-store — 落盘 / 重启恢复 / 重组对账
10
10
  * · chain-indexer — P5: v2 事件索引器 (分页扫 / 增量 / 去重 / 重组回退 / 全量重建)
11
11
  * · chain-index-query — P5: 只读查询 (时间线 / cursor 增量 / 统计 / 索引高度)
12
+ * · explorer — chainId → 公网区块浏览器 (**只造交易链接**: 合约地址不页面化; 认不出的链不给链接)
12
13
  */
13
14
  export * from './chain-config.js';
14
15
  export * from './escrow-client.js';
@@ -18,3 +19,4 @@ export * from './chain-state-store.js';
18
19
  export * from './onchain-trade.js';
19
20
  export * from './chain-indexer.js';
20
21
  export * from './chain-index-query.js';
22
+ export * from './explorer.js';
@@ -116,7 +116,7 @@ function emptyStep(stage, partial) {
116
116
  async function judge(req, taskKey, txHash, expect, recorded) {
117
117
  const gate = req.gate || 'confirmed';
118
118
  const verify = req.verifyOnChain || (await defaultVerifyPaymentOnChain());
119
- return verify({
119
+ const run = () => verify({
120
120
  txHash,
121
121
  chainSettlement: {
122
122
  verifier: createChainSettlementVerifier(req.client, { gate }),
@@ -125,6 +125,20 @@ async function judge(req, taskKey, txHash, expect, recorded) {
125
125
  recorded,
126
126
  },
127
127
  });
128
+ let v = await run();
129
+ // ★ 未定/读偏的有界重读: 交易已经发出去了 (钱/证明在链上), 一次读偏不该定案 —— 只重读, 不重发。
130
+ // 两种读偏形态都要覆盖:
131
+ // · 'pending' —— eth_blockNumber 还停在前一个块 → 确认数数成 0
132
+ // · 'event_mismatch' —— 事件读到了 (receipt 按 txHash 取, 一定新), 但合约状态 eth_call 读回旧值
133
+ // 真 mismatch (event/taskKey 真对不上) 重读 3 次后结论不变 → 不会把错的判成对的。
134
+ const attempts = req.settleRetryAttempts ?? 3;
135
+ const delayMs = req.settleRetryDelayMs ?? 1500;
136
+ for (let i = 1; i <= attempts && !v.chainSettled && v.rpcAvailable !== false
137
+ && (v.status === 'pending' || v.status === 'event_mismatch'); i++) {
138
+ await new Promise((r) => setTimeout(r, delayMs));
139
+ v = await run();
140
+ }
141
+ return v;
128
142
  }
129
143
  /** 判定落盘 (P3 chain-state-store) */
130
144
  async function persist(req, method, taskKey, txHash, amountAtomic, verdict) {
@@ -18,7 +18,9 @@
18
18
  * - 联系人撤销后不允许重试 (revoke 时清等待 + 记 unresolved)
19
19
  * - 同一 requestId 不重复发送 (policy 的 duplicate_request + sent.json)
20
20
  */
21
- import { addEvidence, readGoal, setContinuation, setUnresolved, updateGoal } from '../goal-store.js';
21
+ import { addEvidence, readGoal, setUnresolved } from '../goal-store.js';
22
+ // 2026-09-25 (M0 接线冻结, 规则 ②): Goal 状态变更只有一个漏斗
23
+ import { reduceGoalState } from '../goal-state-reducer.js';
22
24
  import { addRunEvidence } from '../run-store.js';
23
25
  import { bindExternalWait, clearExternalWait, deliverExternalEvent, expireExternalWaits, newContinuationId } from '../external-events.js';
24
26
  import { ContactsStore } from './store.js';
@@ -321,7 +323,14 @@ export class ContactChain {
321
323
  note: `等 ${contact.displayValue} 回复 (通道 ${contact.provider})`,
322
324
  };
323
325
  await bindExternalWait(opts.goalId, wait);
324
- await updateGoal(opts.goalId, { status: 'awaiting_external' });
326
+ // 规则 ②: 进入"等外部"也是一种 Goal 状态变更 → 走 Goal reducer
327
+ await reduceGoalState({
328
+ goalId: opts.goalId,
329
+ intent: 'external_wait_enter',
330
+ now: new Date(this.now()).toISOString(),
331
+ by: 'contacts',
332
+ externalWait: `等 ${contact.displayValue} 回复 (通道 ${contact.provider})`,
333
+ });
325
334
  const g = await readGoal(opts.goalId);
326
335
  await this.ledger({
327
336
  activity: 'contact.authorization_requested', contactId: contact.contactId, goalId: opts.goalId, runId: opts.runId,
@@ -453,9 +462,14 @@ export class ContactChain {
453
462
  await clearExternalWait(s.goalId);
454
463
  const g = await readGoal(s.goalId);
455
464
  await setUnresolved(s.goalId, Array.from(new Set([...(g?.unresolvedItems || []), `联系方式授权 ${grantId} 已撤销, 该联系不可自动重试 (转人工)`])));
456
- // 撤等待 + 转人工: 不再自动唤醒, 由人接手 (Supervisor 下一轮看到 needs_human)
457
- await setContinuation(s.goalId, { wakeReason: 'needs_human', needsExternal: undefined, autoContinue: false }).catch(() => null);
458
- await updateGoal(s.goalId, { status: 'needs_human' }).catch(() => null);
465
+ // 撤等待 + 转人工: 不再自动唤醒, 由人接手 (规则 ②: 状态经 Goal reducer 写, 单一漏斗)
466
+ await reduceGoalState({
467
+ goalId: s.goalId,
468
+ intent: 'contact_revoked_human',
469
+ now: new Date().toISOString(),
470
+ by: 'contacts',
471
+ revokeNote: `联系方式授权 ${grantId} 已撤销, 该联系不可自动重试`,
472
+ }).catch(() => null);
459
473
  affected.push(s.goalId);
460
474
  }
461
475
  return { ok: true, affectedGoals: affected };
@@ -555,8 +569,14 @@ export class ContactChain {
555
569
  await clearExternalWait(s.goalId);
556
570
  const g = await readGoal(s.goalId);
557
571
  await setUnresolved(s.goalId, Array.from(new Set([...(g?.unresolvedItems || []), `联系人 ${c.displayValue} 已撤销授权, 该联系不可重试`])));
558
- await setContinuation(s.goalId, { wakeReason: 'needs_human', needsExternal: undefined, autoContinue: false }).catch(() => null);
559
- await updateGoal(s.goalId, { status: 'needs_human' }).catch(() => null);
572
+ // 规则 ②: 经 Goal reducer 写 (单一漏斗)
573
+ await reduceGoalState({
574
+ goalId: s.goalId,
575
+ intent: 'contact_revoked_human',
576
+ now: new Date().toISOString(),
577
+ by: 'contacts',
578
+ revokeNote: `联系人 ${c.displayValue} 已撤销授权, 该联系不可重试`,
579
+ }).catch(() => null);
560
580
  affected.push(s.goalId);
561
581
  }
562
582
  return { ok: true, evidenceRef: ev.evidenceRef, affectedGoals: affected };