@bolloon/bolloon-agent 0.4.31 → 0.4.33

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 (55) hide show
  1. package/dist/agents/chain/chain-config.js +504 -0
  2. package/dist/agents/chain/chain-index-query.js +135 -0
  3. package/dist/agents/chain/chain-indexer.js +1045 -0
  4. package/dist/agents/chain/chain-settlement.js +284 -0
  5. package/dist/agents/chain/chain-state-store.js +245 -0
  6. package/dist/agents/chain/chain-wallet.js +198 -0
  7. package/dist/agents/chain/escrow-client.js +433 -0
  8. package/dist/agents/chain/explorer.js +52 -0
  9. package/dist/agents/chain/index.js +22 -0
  10. package/dist/agents/chain/onchain-trade.js +705 -0
  11. package/dist/agents/network-pulse.js +676 -2
  12. package/dist/agents/task/task-onchain-runner.js +302 -0
  13. package/dist/agents/task/task-runner.js +27 -3
  14. package/dist/agents/task-board.js +702 -0
  15. package/dist/agents/task-group.js +567 -0
  16. package/dist/agents/x402/paid-info-store.js +75 -6
  17. package/dist/cli/commands/chain.js +926 -0
  18. package/dist/cli/commands/index.js +12 -2
  19. package/dist/cli/commands/tasks.js +627 -6
  20. package/dist/cli/mcp/server.js +4 -1
  21. package/dist/cli/mcp/tools.js +348 -5
  22. package/dist/cli/protocol-envelope.js +16 -0
  23. package/dist/cli-entry.js +6 -1
  24. package/dist/electron-build/agents/chain/chain-config.js +556 -0
  25. package/dist/electron-build/agents/chain/chain-config.js.map +1 -0
  26. package/dist/electron-build/agents/chain/chain-index-query.js +145 -0
  27. package/dist/electron-build/agents/chain/chain-index-query.js.map +1 -0
  28. package/dist/electron-build/agents/chain/chain-indexer.js +1095 -0
  29. package/dist/electron-build/agents/chain/chain-indexer.js.map +1 -0
  30. package/dist/electron-build/agents/chain/chain-settlement.js +291 -0
  31. package/dist/electron-build/agents/chain/chain-settlement.js.map +1 -0
  32. package/dist/electron-build/agents/chain/escrow-client.js +443 -0
  33. package/dist/electron-build/agents/chain/escrow-client.js.map +1 -0
  34. package/dist/electron-build/agents/chain/explorer.js +59 -0
  35. package/dist/electron-build/agents/chain/explorer.js.map +1 -0
  36. package/dist/electron-build/agents/local-signer.js +101 -0
  37. package/dist/electron-build/agents/local-signer.js.map +1 -0
  38. package/dist/electron-build/agents/network-pulse.js +693 -3
  39. package/dist/electron-build/agents/network-pulse.js.map +1 -1
  40. package/dist/electron-build/agents/task/task-runner.js +27 -3
  41. package/dist/electron-build/agents/task/task-runner.js.map +1 -1
  42. package/dist/electron-build/agents/task-board.js +761 -0
  43. package/dist/electron-build/agents/task-board.js.map +1 -0
  44. package/dist/electron-build/agents/task-contract.js +382 -0
  45. package/dist/electron-build/agents/task-contract.js.map +1 -0
  46. package/dist/electron-build/agents/x402/paid-info-store.js +76 -6
  47. package/dist/electron-build/agents/x402/paid-info-store.js.map +1 -1
  48. package/dist/web/chain-explorer.js +617 -0
  49. package/dist/web/explorer.html +163 -0
  50. package/dist/web/index.html +5 -0
  51. package/dist/web/routes-chain-index.js +108 -0
  52. package/dist/web/routes-onchain-trade.js +99 -0
  53. package/dist/web/server.js +13 -0
  54. package/package.json +2 -1
  55. package/scripts/build-web.ts +20 -1
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ /**
3
+ * chain-index-query.ts — 链上索引的**只读查询接口** (P5, ③)
4
+ * =========================================================================
5
+ * 只做四件事, 全部是**读已落盘索引**, 不发任何 RPC、不写盘、不签名:
6
+ * ① 按 taskKey 查 escrow 时间线 → getEscrowTimeline(taskKey)
7
+ * ② 按 cursor(区块号+logIndex) 增量拉取 → fetchIndexSince(cursor, {limit})
8
+ * ③ 全量统计 (tasks/released/refunded/disputed/expired) → getIndexStats()
9
+ * ④ 当前索引高度 + 最后同步时间 → getIndexStatus()
10
+ *
11
+ * 为什么单独一个文件: 网页/工具/别的进程都可能要读, 而**读不该需要 RPC**。
12
+ * 这里构造的 ChainIndexer 一律是只读模式 (deploymentBlock 显式给 0, 不查 manifest),
13
+ * 真去读链会明确报 'chain_index_readonly' —— 不静默返回空。
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.setChainIndexPathForTesting = setChainIndexPathForTesting;
17
+ exports.currentIndexPath = currentIndexPath;
18
+ exports.readIndexFile = readIndexFile;
19
+ exports.getIndexStatus = getIndexStatus;
20
+ exports.getIndexStats = getIndexStats;
21
+ exports.getEscrowTimeline = getEscrowTimeline;
22
+ exports.fetchIndexSince = fetchIndexSince;
23
+ const chain_indexer_js_1 = require("./chain-indexer.js");
24
+ const chain_config_js_1 = require("./chain-config.js");
25
+ let overridePath = null;
26
+ /** 测试/嵌入用: 把索引文件路径钉死 (null = 恢复默认 ~/.bolloon/chain/index.json) */
27
+ function setChainIndexPathForTesting(p) {
28
+ overridePath = p;
29
+ }
30
+ function currentIndexPath(home) {
31
+ return overridePath || (0, chain_indexer_js_1.chainIndexPath)(home);
32
+ }
33
+ /** 只读模式的 indexer (故意不查 manifest: 查索引不需要知道部署块) */
34
+ function readonlyIndexer(opts = {}) {
35
+ const p = currentIndexPath(opts.home);
36
+ return new chain_indexer_js_1.ChainIndexer({
37
+ // 只读: 给个占位 provider, 真调链会抛 chain_index_readonly
38
+ provider: {
39
+ async getBlockNumber() { throw new Error('chain_index_readonly: 只读查询不发 RPC'); },
40
+ async getBlock() { throw new Error('chain_index_readonly: 只读查询不发 RPC'); },
41
+ async getLogs() { throw new Error('chain_index_readonly: 只读查询不发 RPC'); },
42
+ },
43
+ escrowAddress: '0x' + '00'.repeat(20),
44
+ deploymentBlock: 0,
45
+ deploymentSource: 'readonly-query (不需要起点)',
46
+ home: opts.home,
47
+ indexPath: p,
48
+ confirmations: chain_config_js_1.DEFAULT_CONFIRMATIONS,
49
+ });
50
+ }
51
+ /** 读索引文件 (没有 → 空索引, 不假装有) */
52
+ function readIndexFile(opts = {}) {
53
+ return readonlyIndexer(opts).load();
54
+ }
55
+ /** ④ 当前索引高度 + 最后同步时间 */
56
+ function getIndexStatus(opts = {}) {
57
+ const s = readIndexFile(opts);
58
+ return {
59
+ indexPath: currentIndexPath(opts.home),
60
+ chainId: s.chainId, networkName: s.networkName,
61
+ escrowAddress: s.escrowAddress, deploymentBlock: s.deploymentBlock, deploymentSource: s.deploymentSource,
62
+ identity: s.identity ?? { chainId: s.chainId, escrowAddress: s.escrowAddress.toLowerCase(), deploymentBlock: s.deploymentBlock },
63
+ lastSyncedBlock: s.lastSyncedBlock, lastSyncedAt: s.lastSyncedAt,
64
+ lastSyncedAgoMs: s.lastSyncedAt == null ? null : Date.now() - s.lastSyncedAt,
65
+ headBlock: s.headBlock, headBlockHash: s.headBlockHash,
66
+ entries: s.entries.length, suspects: s.entries.filter((e) => e.suspect).length,
67
+ confirmations: s.confirmations, pageSize: s.pageSize, reorgDepth: s.reorgDepth,
68
+ rebuiltAt: s.rebuiltAt ?? null, updatedAt: s.updatedAt,
69
+ lagFromSnapshot: s.headBlock == null ? null : Math.max(0, s.headBlock - (s.lastSyncedBlock + 1)),
70
+ };
71
+ }
72
+ /** ③ 全量统计。suspect (被回退) 的记录**不计入**业务计数, 但单独报出来。 */
73
+ function getIndexStats(opts = {}) {
74
+ const s = readIndexFile(opts);
75
+ const live = s.entries.filter((e) => !e.suspect);
76
+ const byEvent = {};
77
+ for (const e of live)
78
+ byEvent[e.eventName] = (byEvent[e.eventName] || 0) + 1;
79
+ const byFinality = { observed: 0, confirmed: 0, finalized: 0 };
80
+ for (const e of s.entries)
81
+ byFinality[e.finality]++;
82
+ const n = (name) => live.filter((e) => e.eventName === name).length;
83
+ return {
84
+ entries: s.entries.length,
85
+ suspects: s.entries.filter((e) => e.suspect).length,
86
+ tasks: new Set(live.filter((e) => e.eventName === 'EscrowCreatedV2').map((e) => e.taskKey.toLowerCase())).size,
87
+ created: n('EscrowCreatedV2'),
88
+ proofSubmitted: n('ProofSubmittedV2'),
89
+ released: n('ReleasedV2'),
90
+ refunded: n('RefundedV2'),
91
+ disputed: n('DisputedV2'),
92
+ expired: n('ExpiredV2'),
93
+ byFinality, byEvent,
94
+ lastSyncedBlock: s.lastSyncedBlock, lastSyncedAt: s.lastSyncedAt, headBlock: s.headBlock,
95
+ deploymentBlock: s.deploymentBlock, chainId: s.chainId, escrowAddress: s.escrowAddress,
96
+ };
97
+ }
98
+ const slim = (e) => ({
99
+ blockNumber: e.blockNumber, blockHash: e.blockHash, txHash: e.txHash, logIndex: e.logIndex,
100
+ eventName: e.eventName, args: e.args, confirmations: e.confirmations, finality: e.finality,
101
+ suspect: e.suspect, suspectReason: e.suspectReason,
102
+ });
103
+ /** ① 按 taskKey 查 escrow 时间线 (块号 + logIndex 升序) */
104
+ function getEscrowTimeline(taskKey, opts = {}) {
105
+ const key = String(taskKey || '').toLowerCase();
106
+ if (!/^0x[0-9a-f]{64}$/.test(key)) {
107
+ // 非法 taskKey 不硬搜: 直接空时间线 + 明确说明 (路由层会回 400)
108
+ return { taskKey: key, state: null, events: [], count: 0, hasSuspect: false };
109
+ }
110
+ const events = readIndexFile(opts).entries
111
+ .filter((e) => e.taskKey.toLowerCase() === key)
112
+ .sort(chain_indexer_js_1.byBlockLogIndex);
113
+ return {
114
+ taskKey: key,
115
+ state: (0, chain_indexer_js_1.deriveEscrowState)(events),
116
+ events: events.map(slim),
117
+ count: events.length,
118
+ hasSuspect: events.some((e) => e.suspect),
119
+ };
120
+ }
121
+ /** ② 按 cursor 增量拉取 (严格大于 cursor 的 (blockNumber, logIndex)) */
122
+ function fetchIndexSince(cursor, opts = {}) {
123
+ const limit = Math.max(1, Math.min(1000, Math.floor(opts.limit ?? 200)));
124
+ const all = readIndexFile(opts).entries
125
+ .filter((e) => {
126
+ if (!cursor)
127
+ return true;
128
+ const cb = Number(cursor.blockNumber), cl = Number(cursor.logIndex);
129
+ return e.blockNumber > cb || (e.blockNumber === cb && e.logIndex > cl);
130
+ })
131
+ .sort(chain_indexer_js_1.byBlockLogIndex);
132
+ const page = all.slice(0, limit);
133
+ const last = page[page.length - 1];
134
+ return {
135
+ events: page.map(slim),
136
+ nextCursor: last ? { blockNumber: last.blockNumber, logIndex: last.logIndex } : (cursor ?? null),
137
+ hasMore: all.length > page.length,
138
+ remaining: all.length,
139
+ cursor: cursor ?? null,
140
+ limit,
141
+ };
142
+ }
143
+ // 索引目录/路径的唯一出口在 chain-indexer.ts (chainIndexDir / chainIndexPath) —— 这里不重复导出,
144
+ // 否则 index.ts 的 `export *` 会出现同名歧义 (ESM 下歧义名会被静默丢掉)。
145
+ //# sourceMappingURL=chain-index-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-index-query.js","sourceRoot":"","sources":["../../../../src/agents/chain/chain-index-query.ts"],"names":[],"mappings":"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"}