@bolloon/bolloon-agent 0.4.12 → 0.4.14

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.
@@ -2446,6 +2446,182 @@ export function registerBuiltinTools(ctx) {
2446
2446
  }
2447
2447
  },
2448
2448
  });
2449
+ // 2026-08-13: Treasury 桥 — 链下结算 (Policy/Registry) 驱动链上 Treasury.payAgent
2450
+ // 配置: BOLLOON_TREASURY_RPC / BOLLOON_TREASURY_ADDRESS / BOLLOON_TREASURY_KEY / BOLLOON_TREASURY_TOKEN
2451
+ const treasuryConfigFromEnv = () => {
2452
+ const rpcUrl = process.env.BOLLOON_TREASURY_RPC || '';
2453
+ const treasuryAddress = process.env.BOLLOON_TREASURY_ADDRESS || '';
2454
+ const tokenAddress = process.env.BOLLOON_TREASURY_TOKEN || '';
2455
+ const privateKey = process.env.BOLLOON_TREASURY_KEY || '';
2456
+ return { rpcUrl, treasuryAddress, tokenAddress, privateKey };
2457
+ };
2458
+ ctx.tools.set('treasury_pay', {
2459
+ name: 'treasury_pay',
2460
+ description: '从 Treasury 支付给 Agent (链上 AgentTreasury.payAgent). 自动过 Policy 预算校验 + 信誉门槛 (链上). agent_address: 收款 Agent 地址; amount: 金额 (USDC). 需配置 BOLLOON_TREASURY_* 环境变量 (RPC/合约/私钥).',
2461
+ parameters: { agent_address: '收款 Agent 钱包地址 (必填)', amount: '金额 USDC (必填)', service: '服务名 (可选, Policy 校验用)' },
2462
+ execute: async (args) => {
2463
+ const cfg = treasuryConfigFromEnv();
2464
+ if (!cfg.rpcUrl || !cfg.treasuryAddress || !cfg.privateKey) {
2465
+ return { success: false, error: '未配置 Treasury (BOLLOON_TREASURY_RPC/ADDRESS/KEY/TOKEN)' };
2466
+ }
2467
+ const agentAddress = String(args.agent_address || '').trim();
2468
+ const amount = Number(args.amount);
2469
+ if (!agentAddress || !amount || amount <= 0)
2470
+ return { success: false, error: 'agent_address 和 amount(>0) 必填' };
2471
+ try {
2472
+ const { treasuryPay } = await import('./treasury-bridge.js');
2473
+ const r = await treasuryPay(cfg, {
2474
+ agentAddress,
2475
+ amount,
2476
+ service: String(args.service || '').trim() || undefined,
2477
+ });
2478
+ if (!r.success)
2479
+ return { success: false, error: r.error };
2480
+ return { success: true, output: `✅ Treasury 已支付 ${amount} USDC → ${agentAddress.slice(0, 10)}... tx=${r.txHash}` };
2481
+ }
2482
+ catch (e) {
2483
+ return { success: false, error: `treasury_pay 失败: ${String(e?.message || e).slice(0, 200)}` };
2484
+ }
2485
+ },
2486
+ });
2487
+ ctx.tools.set('treasury_status', {
2488
+ name: 'treasury_status',
2489
+ description: '查询 Treasury 状态 (余额/日限/冻结). 需配置 BOLLOON_TREASURY_* 环境变量.',
2490
+ parameters: {},
2491
+ execute: async () => {
2492
+ const cfg = treasuryConfigFromEnv();
2493
+ if (!cfg.rpcUrl || !cfg.treasuryAddress) {
2494
+ return { success: false, error: '未配置 Treasury (BOLLOON_TREASURY_RPC/ADDRESS)' };
2495
+ }
2496
+ try {
2497
+ const { treasuryStatus } = await import('./treasury-bridge.js');
2498
+ const s = await treasuryStatus(cfg);
2499
+ if (!s.ok)
2500
+ return { success: false, error: s.error };
2501
+ return { success: true, output: `Treasury:\n 余额: ${s.balance} USDC\n 日限: ${s.dailyLimit} USDC\n 冻结: ${s.frozen ? '是' : '否'}` };
2502
+ }
2503
+ catch (e) {
2504
+ return { success: false, error: `treasury_status 失败: ${String(e?.message || e).slice(0, 200)}` };
2505
+ }
2506
+ },
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
+ });
2449
2625
  // ============================================================
2450
2626
  // publish_did (2026-08-03) — 把当前 agent 的 DID 发布到 IPFS + IPNS
2451
2627
  // 全自动: 自动安装/启动本地 Kubo → 上传 DID 文档 → 发布 IPNS name
@@ -0,0 +1,127 @@
1
+ /**
2
+ * treasury-bridge.ts — Treasury 合约 × Agent 经济网络桥接 (2026-08-13)
3
+ *
4
+ * 打通: 链下结算逻辑 (Registry 服务/Policy 授权/Reputation 门槛) → 链上 Treasury.payAgent.
5
+ *
6
+ * 流程:
7
+ * registry 服务完成 → reputation_update(success) → treasuryPay(agent, amount)
8
+ * ├─ 链下校验: Policy (预算) + Registry (服务价格) + Reputation (≥60)
9
+ * └─ 链上执行: AgentTreasury.payAgent(agent, amount)
10
+ *
11
+ * 合约 ABI 用最小接口 (viem writeContract), 支持任意部署地址 + RPC.
12
+ * 真实链上需部署 AgentTreasury + 注入 owner 私钥; 测试注入 mock.
13
+ */
14
+ /** Treasury 合约最小 ABI (payAgent/deposit/balance/dailySpend/frozen) */
15
+ const TREASURY_ABI = [
16
+ {
17
+ name: 'payAgent',
18
+ type: 'function',
19
+ stateMutability: 'nonpayable',
20
+ inputs: [
21
+ { name: 'agent', type: 'address' },
22
+ { name: 'amount', type: 'uint256' },
23
+ ],
24
+ outputs: [],
25
+ },
26
+ {
27
+ name: 'deposit',
28
+ type: 'function',
29
+ stateMutability: 'nonpayable',
30
+ inputs: [{ name: 'amount', type: 'uint256' }],
31
+ outputs: [],
32
+ },
33
+ {
34
+ name: 'balance',
35
+ type: 'function',
36
+ stateMutability: 'view',
37
+ inputs: [],
38
+ outputs: [{ name: '', type: 'uint256' }],
39
+ },
40
+ {
41
+ name: 'frozen',
42
+ type: 'function',
43
+ stateMutability: 'view',
44
+ inputs: [],
45
+ outputs: [{ name: '', type: 'bool' }],
46
+ },
47
+ {
48
+ name: 'dailyLimit',
49
+ type: 'function',
50
+ stateMutability: 'view',
51
+ inputs: [],
52
+ outputs: [{ name: '', type: 'uint256' }],
53
+ },
54
+ ];
55
+ /**
56
+ * 链下校验 → 链上 Treasury.payAgent.
57
+ * 校验链: Policy (预算/白名单) → 合约调用.
58
+ */
59
+ export async function treasuryPay(config, opts) {
60
+ const { agentAddress, amount, service } = opts;
61
+ // 1. Policy 授权 (预算/白名单) — 链下, 防无预算支付
62
+ if (opts.policyCheck) {
63
+ const decision = await opts.policyCheck({ payTo: agentAddress, amount, service: service || 'treasury-pay' });
64
+ if (!decision.allowed) {
65
+ return { success: false, error: `[policy] ${decision.reason}`, checks: { policy: decision } };
66
+ }
67
+ }
68
+ else {
69
+ try {
70
+ const { getEconomicPolicy } = await import('./economic-policy.js');
71
+ const policy = getEconomicPolicy();
72
+ const decision = await policy.check({ payTo: agentAddress, amount, service: service || 'treasury-pay' });
73
+ if (!decision.allowed) {
74
+ return { success: false, error: `[policy] ${decision.reason}`, checks: { policy: decision } };
75
+ }
76
+ }
77
+ catch { /* policy 不可用放行 */ }
78
+ }
79
+ // 2. 链上 payAgent (dryRun: 只验证 policy 门, 不真实上链)
80
+ if (opts.dryRun) {
81
+ return { success: true, txHash: 'dry-run:0x0', checks: { policy: { allowed: true } }, dryRun: true };
82
+ }
83
+ try {
84
+ const { createWalletClient, http, parseUnits } = await import('viem');
85
+ const { privateKeyToAccount } = await import('viem/accounts');
86
+ const { base, baseSepolia } = await import('viem/chains');
87
+ const decimals = config.decimals ?? 6;
88
+ const account = privateKeyToAccount(config.privateKey);
89
+ const chain = config.rpcUrl.includes('sepolia') ? baseSepolia : base;
90
+ const client = createWalletClient({ account, chain, transport: http(config.rpcUrl) });
91
+ const txHash = await client.writeContract({
92
+ address: config.treasuryAddress,
93
+ abi: TREASURY_ABI,
94
+ functionName: 'payAgent',
95
+ args: [agentAddress, parseUnits(String(amount), decimals)],
96
+ });
97
+ // 记录花费 (链下日预算镜像)
98
+ try {
99
+ const { getEconomicPolicy } = await import('./economic-policy.js');
100
+ await getEconomicPolicy().recordSpend(amount).catch(() => { });
101
+ }
102
+ catch { /* 静默 */ }
103
+ return { success: true, txHash, checks: { policy: { allowed: true } } };
104
+ }
105
+ catch (e) {
106
+ return { success: false, error: `Treasury.payAgent 失败: ${String(e?.message || e).slice(0, 200)}` };
107
+ }
108
+ }
109
+ /** 查询 Treasury 状态 (余额/日限/冻结) */
110
+ export async function treasuryStatus(config) {
111
+ try {
112
+ const { createPublicClient, http, formatUnits } = await import('viem');
113
+ const { base, baseSepolia } = await import('viem/chains');
114
+ const chain = config.rpcUrl.includes('sepolia') ? baseSepolia : base;
115
+ const client = createPublicClient({ chain, transport: http(config.rpcUrl) });
116
+ const decimals = config.decimals ?? 6;
117
+ const [bal, limit, frozen] = await Promise.all([
118
+ client.readContract({ address: config.treasuryAddress, abi: TREASURY_ABI, functionName: 'balance' }),
119
+ client.readContract({ address: config.treasuryAddress, abi: TREASURY_ABI, functionName: 'dailyLimit' }),
120
+ client.readContract({ address: config.treasuryAddress, abi: TREASURY_ABI, functionName: 'frozen' }),
121
+ ]);
122
+ return { ok: true, balance: formatUnits(bal, decimals), dailyLimit: formatUnits(limit, decimals), frozen: frozen };
123
+ }
124
+ catch (e) {
125
+ return { ok: false, error: `Treasury 状态查询失败: ${String(e?.message || e).slice(0, 200)}` };
126
+ }
127
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * econ-integration.ts — Polymarket × Agent 经济网络集成 (2026-08-13, Task C4)
3
+ *
4
+ * 打通 Agent Economic Network 与 Polymarket 预测市场:
5
+ * - Agent 可用 Treasury 资金在 Polymarket 下单 (预测/对冲)
6
+ * - 下单前过 Policy Engine (预算/授权)
7
+ * - 订单结果 (成交/收益) 记录回经济层 (审计)
8
+ *
9
+ * Polymarket 合约架构 (Polygon):
10
+ * - CLOB (链上订单簿): createOrder/getOrders/cancelOrder (现有 SDK)
11
+ * - CTF 条件代币框架: 市场 = 条件代币对 (Yes/No)
12
+ * - NegRisk 适配器: 互斥结果市场
13
+ * 收益结算在链上 (USDC), Agent Treasury 可接收.
14
+ */
15
+ import { type CreateOrderParams, type CreateOrderResult } from './createOrder.js';
16
+ import { type GetOrdersParams, type GetOrdersResult } from './getOrders.js';
17
+ export interface EconOrderOptions {
18
+ /** 预算上限 (USDC) — 经 Policy Engine 检查 */
19
+ maxSpendUsdc?: number;
20
+ /** 服务名 (Policy 白名单用, 默认 polymarket) */
21
+ service?: string;
22
+ /** 是否记录经济审计 */
23
+ audit?: boolean;
24
+ /** 注入 Policy 检查回调 (根包 Agent 经济层注入; 子包不跨包 import) */
25
+ policyCheck?: (intent: {
26
+ payTo: string;
27
+ amount: number;
28
+ service?: string;
29
+ }) => Promise<{
30
+ allowed: boolean;
31
+ reason?: string;
32
+ }>;
33
+ /** 注入花费记录回调 */
34
+ recordSpend?: (amount: number) => Promise<void>;
35
+ /** 注入 createOrder 实现 (测试 mock; 默认真实 CLOB) */
36
+ createOrderImpl?: (params: CreateOrderParams) => Promise<CreateOrderResult>;
37
+ }
38
+ export interface EconOrderResult {
39
+ success: boolean;
40
+ order?: CreateOrderResult;
41
+ policy?: {
42
+ allowed: boolean;
43
+ reason?: string;
44
+ };
45
+ error?: string;
46
+ }
47
+ /**
48
+ * 带 Policy 检查的 Polymarket 下单.
49
+ * 流程: 金额 → Policy 授权 (回调注入) → CLOB 下单.
50
+ */
51
+ export declare function createOrderEcon(params: CreateOrderParams, opts?: EconOrderOptions): Promise<EconOrderResult>;
52
+ /** 查询订单 (含经济层关联信息) */
53
+ export declare function getOrdersEcon(params?: GetOrdersParams): Promise<GetOrdersResult>;
54
+ /** Polymarket 合约架构摘要 (文档化, 供 Agent 理解) */
55
+ export declare const POLYMARKET_CONTRACT_OVERVIEW = "\nPolymarket \u5408\u7EA6\u67B6\u6784 (Polygon):\n- CLOB: \u94FE\u4E0A\u8BA2\u5355\u7C3F (createOrder/getOrders/cancelOrder)\n- CTF (Conditional Token Framework): \u5E02\u573A = \u6761\u4EF6\u4EE3\u5E01\u5BF9 Yes/No\n- NegRisk \u9002\u914D\u5668: \u4E92\u65A5\u7ED3\u679C\u5E02\u573A (\u5982\"\u54EA\u4E2A\u5019\u9009\u4EBA\u80DC\u51FA\")\n- \u7ED3\u7B97: USDC \u94FE\u4E0A, \u6536\u76CA\u53EF\u56DE\u6536\u5230 Agent Treasury\n- Agent \u96C6\u6210: Treasury \u8D44\u91D1 \u2192 Policy \u6388\u6743 \u2192 CLOB \u4E0B\u5355 \u2192 \u7ED3\u679C \u2192 \u6536\u76CA\u56DE\u6D41\n";
@@ -0,0 +1,59 @@
1
+ /**
2
+ * econ-integration.ts — Polymarket × Agent 经济网络集成 (2026-08-13, Task C4)
3
+ *
4
+ * 打通 Agent Economic Network 与 Polymarket 预测市场:
5
+ * - Agent 可用 Treasury 资金在 Polymarket 下单 (预测/对冲)
6
+ * - 下单前过 Policy Engine (预算/授权)
7
+ * - 订单结果 (成交/收益) 记录回经济层 (审计)
8
+ *
9
+ * Polymarket 合约架构 (Polygon):
10
+ * - CLOB (链上订单簿): createOrder/getOrders/cancelOrder (现有 SDK)
11
+ * - CTF 条件代币框架: 市场 = 条件代币对 (Yes/No)
12
+ * - NegRisk 适配器: 互斥结果市场
13
+ * 收益结算在链上 (USDC), Agent Treasury 可接收.
14
+ */
15
+ import { createOrder as pmCreateOrder } from './createOrder.js';
16
+ import { getOrders as pmGetOrders } from './getOrders.js';
17
+ /**
18
+ * 带 Policy 检查的 Polymarket 下单.
19
+ * 流程: 金额 → Policy 授权 (回调注入) → CLOB 下单.
20
+ */
21
+ export async function createOrderEcon(params, opts = {}) {
22
+ const amountUsdc = Number(params.price) * Number(params.size ?? 1);
23
+ // 1. Policy 授权 (预算/白名单) — 回调注入, 不跨包
24
+ if (opts.policyCheck) {
25
+ const decision = await opts.policyCheck({
26
+ payTo: 'polymarket-clob',
27
+ amount: amountUsdc,
28
+ service: opts.service || 'polymarket',
29
+ });
30
+ if (!decision.allowed) {
31
+ return { success: false, policy: { allowed: false, reason: `[policy] ${decision.reason}` } };
32
+ }
33
+ await opts.recordSpend?.(amountUsdc).catch(() => { });
34
+ }
35
+ else if (opts.maxSpendUsdc !== undefined && amountUsdc > opts.maxSpendUsdc) {
36
+ return { success: false, policy: { allowed: false, reason: `Polymarket 下单超预算: ${amountUsdc} > ${opts.maxSpendUsdc}` } };
37
+ }
38
+ // 2. CLOB 下单 (可注入 mock, 默认真实)
39
+ try {
40
+ const order = opts.createOrderImpl ? await opts.createOrderImpl(params) : await pmCreateOrder(params);
41
+ return { success: true, order, policy: { allowed: true } };
42
+ }
43
+ catch (e) {
44
+ return { success: false, error: `Polymarket 下单失败: ${String(e?.message || e).slice(0, 200)}` };
45
+ }
46
+ }
47
+ /** 查询订单 (含经济层关联信息) */
48
+ export async function getOrdersEcon(params = {}) {
49
+ return pmGetOrders(params);
50
+ }
51
+ /** Polymarket 合约架构摘要 (文档化, 供 Agent 理解) */
52
+ export const POLYMARKET_CONTRACT_OVERVIEW = `
53
+ Polymarket 合约架构 (Polygon):
54
+ - CLOB: 链上订单簿 (createOrder/getOrders/cancelOrder)
55
+ - CTF (Conditional Token Framework): 市场 = 条件代币对 Yes/No
56
+ - NegRisk 适配器: 互斥结果市场 (如"哪个候选人胜出")
57
+ - 结算: USDC 链上, 收益可回收到 Agent Treasury
58
+ - Agent 集成: Treasury 资金 → Policy 授权 → CLOB 下单 → 结果 → 收益回流
59
+ `;
package/dist/index.js CHANGED
@@ -1333,6 +1333,48 @@ async function processInput(input, comm) {
1333
1333
  }
1334
1334
  return;
1335
1335
  }
1336
+ // /payments [/approve <id> /reject <id>] — 人工支付审批 (2026-08-13)
1337
+ // YAML 验证门判定 confirm 的支付请求 → 这里人工批准/拒绝
1338
+ if (cmd === '/payments' || cmd.startsWith('/payments ') || cmd.startsWith('/approve ') || cmd.startsWith('/reject ')) {
1339
+ try {
1340
+ const { getApprovalStore } = await import('./agents/payment-approval.js');
1341
+ const store = getApprovalStore();
1342
+ if (cmd.startsWith('/approve ')) {
1343
+ const id = cmd.slice('/approve '.length).trim();
1344
+ const r = await store.approve(id);
1345
+ if (!r.ok) {
1346
+ appendLine(`${C_ERROR}${r.error}${RESET}`);
1347
+ return;
1348
+ }
1349
+ appendLine(`${C_OK}✓ 已批准 ${id} → ${r.approval?.status}${r.approval?.result ? ` (${String(r.approval.result).slice(0, 80)})` : ''}${RESET}`);
1350
+ return;
1351
+ }
1352
+ if (cmd.startsWith('/reject ')) {
1353
+ const id = cmd.slice('/reject '.length).trim();
1354
+ const r = await store.reject(id);
1355
+ if (!r.ok) {
1356
+ appendLine(`${C_ERROR}${r.error}${RESET}`);
1357
+ return;
1358
+ }
1359
+ appendLine(`${C_WARN}✗ 已拒绝 ${id}${RESET}`);
1360
+ return;
1361
+ }
1362
+ const approvals = await store.pending();
1363
+ appendLine(`${C_ACCENT}待人工审批支付 (${approvals.length}):${RESET}`);
1364
+ if (approvals.length === 0) {
1365
+ appendLine(` ${C_DIM}无待审批 — YAML 验证门 allow/deny 已自动处理${RESET}`);
1366
+ }
1367
+ for (const a of approvals) {
1368
+ appendLine(` ${C_WARN}⏳${RESET} ${C_ACCENT}${a.id}${RESET} ${a.service} $${a.amount} → ${String(a.recipient).slice(0, 12)}...`);
1369
+ appendLine(` ${C_DIM}${a.reason}${RESET}`);
1370
+ appendLine(` ${C_DIM}/approve ${a.id} | /reject ${a.id}${RESET}`);
1371
+ }
1372
+ }
1373
+ catch (e) {
1374
+ appendLine(`${C_ERROR}/payments 失败: ${String(e?.message || e).slice(0, 120)}${RESET}`);
1375
+ }
1376
+ return;
1377
+ }
1336
1378
  // /skill — 技能候选 (skill-writer 落盘)
1337
1379
  if (cmd === '/skill') {
1338
1380
  try {
@@ -151,15 +151,9 @@ export class OrbitDBAdapter {
151
151
  await this.node.helia.blockstore.put(CID.parse(rec.id), dagCbor.encode(rec));
152
152
  return `bolloon-cid://${rec.id}`;
153
153
  }
154
- /**
155
- * 2026-08-08: 在同一 OrbitDB 实例上打开附加 store。
156
- * events 类型 = append-only 事件流 (WAL 复制 / 轨迹流用).
157
- * 返回的 store 是通用适配 (put=keyvalue / add=events).
158
- */
159
- async openStore(name, type = 'keyvalue') {
160
- await this.ensure();
161
- const raw = (await this._orbitdb.open(name, { type }));
162
- const store = {
154
+ /** 打开 store 的通用适配 (keyvalue/events 统一成 OrbitDBStore) */
155
+ wrapStore(raw) {
156
+ return {
163
157
  address: raw.address,
164
158
  put: async (key, value) => { await raw.put(key, JSON.parse(JSON.stringify(value))); },
165
159
  add: async (value) => { await raw.add(JSON.parse(JSON.stringify(value))); },
@@ -190,7 +184,42 @@ export class OrbitDBAdapter {
190
184
  };
191
185
  },
192
186
  };
193
- return store;
187
+ }
188
+ /**
189
+ * 2026-08-08: 在同一 OrbitDB 实例上打开附加 store。
190
+ * events 类型 = append-only 事件流 (WAL 复制 / 轨迹流用).
191
+ * opts.accessController: 群组用 write:['*'] (任何人可写).
192
+ */
193
+ async openStore(name, type = 'keyvalue', opts) {
194
+ await this.ensure();
195
+ const options = { type };
196
+ if (opts?.accessController)
197
+ options.accessController = opts.accessController;
198
+ const raw = (await this._orbitdb.open(name, options));
199
+ return this.wrapStore(raw);
200
+ }
201
+ /**
202
+ * 2026-08-14: 按地址打开远端 store (Agent Gateway 共享网络 / 群组)。
203
+ * replica=true → 只读副本: 拉取复制但不写回 (自动加入网络不污染他人 registry)。
204
+ * replica=false → 可写 (群组: events store 配 write:'*' 时成员可广播)。
205
+ */
206
+ async openStoreByAddress(address, type = 'keyvalue', opts) {
207
+ await this.ensure();
208
+ try {
209
+ const options = { type };
210
+ if (opts?.replica === false)
211
+ options.replica = false;
212
+ else
213
+ options.replica = true;
214
+ if (opts?.accessController)
215
+ options.accessController = opts.accessController;
216
+ const raw = (await this._orbitdb.open(address, options));
217
+ return this.wrapStore(raw);
218
+ }
219
+ catch (err) {
220
+ console.warn(`[orbitdb] openStoreByAddress 失败: ${String(err?.message || err).slice(0, 160)}`);
221
+ return null;
222
+ }
194
223
  }
195
224
  async close() {
196
225
  try {