@bolloon/bolloon-agent 0.5.1 → 0.5.3

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 (77) hide show
  1. package/README.md +39 -0
  2. package/dist/agents/agent-lang.js +101 -0
  3. package/dist/agents/agent-manifest-protocol.js +4 -0
  4. package/dist/agents/chain/transfer-classify.js +99 -0
  5. package/dist/agents/chain/transfer-index.js +354 -0
  6. package/dist/agents/gateway-group.js +44 -3
  7. package/dist/agents/identity/address-binding.js +613 -0
  8. package/dist/agents/network-pulse.js +706 -27
  9. package/dist/agents/pi-sdk.js +101 -8
  10. package/dist/agents/workflow-pivot-loop.js +3 -1
  11. package/dist/agents/x402/direct-payment.js +689 -0
  12. package/dist/agents/x402/order-identity.js +408 -0
  13. package/dist/agents/x402/paid-info-store.js +17 -0
  14. package/dist/agents/x402/seller-signing.js +614 -0
  15. package/dist/agents/x402/seller-summary.js +398 -0
  16. package/dist/cli/identity-command.js +327 -2
  17. package/dist/cli/protocol-envelope.js +4 -0
  18. package/dist/cli/update-commands.js +41 -25
  19. package/dist/cli/x402-buyer-command.js +463 -0
  20. package/dist/cli/x402-seller-command.js +289 -0
  21. package/dist/cli-entry.js +21 -5
  22. package/dist/efficode/compress.js +78 -0
  23. package/dist/efficode/crc32.js +38 -0
  24. package/dist/efficode/did.js +66 -0
  25. package/dist/efficode/index.js +24 -0
  26. package/dist/efficode/lz77.js +170 -0
  27. package/dist/efficode/negotiate.js +187 -0
  28. package/dist/efficode/ops.js +87 -0
  29. package/dist/efficode/packet.js +271 -0
  30. package/dist/efficode/types.js +45 -0
  31. package/dist/electron-build/agents/agent-manifest-protocol.js +4 -0
  32. package/dist/electron-build/agents/agent-manifest-protocol.js.map +1 -1
  33. package/dist/electron-build/agents/chain/transfer-classify.js +106 -0
  34. package/dist/electron-build/agents/chain/transfer-classify.js.map +1 -0
  35. package/dist/electron-build/agents/chain/transfer-index.js +400 -0
  36. package/dist/electron-build/agents/chain/transfer-index.js.map +1 -0
  37. package/dist/electron-build/agents/identity/address-binding.js +672 -0
  38. package/dist/electron-build/agents/identity/address-binding.js.map +1 -0
  39. package/dist/electron-build/agents/network-pulse.js +714 -28
  40. package/dist/electron-build/agents/network-pulse.js.map +1 -1
  41. package/dist/electron-build/agents/pi-sdk.js +102 -8
  42. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  43. package/dist/electron-build/agents/workflow-pivot-loop.js +3 -1
  44. package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
  45. package/dist/electron-build/agents/x402/direct-payment.js +744 -0
  46. package/dist/electron-build/agents/x402/direct-payment.js.map +1 -0
  47. package/dist/electron-build/agents/x402/order-identity.js +458 -0
  48. package/dist/electron-build/agents/x402/order-identity.js.map +1 -0
  49. package/dist/electron-build/agents/x402/paid-info-protocol.js.map +1 -1
  50. package/dist/electron-build/agents/x402/paid-info-store.js +18 -0
  51. package/dist/electron-build/agents/x402/paid-info-store.js.map +1 -1
  52. package/dist/electron-build/agents/x402/seller-signing.js +682 -0
  53. package/dist/electron-build/agents/x402/seller-signing.js.map +1 -0
  54. package/dist/electron-build/llm/pi-ai.js +685 -48
  55. package/dist/electron-build/llm/pi-ai.js.map +1 -1
  56. package/dist/electron-build/utils/auto-update.js +2 -2
  57. package/dist/electron-build/utils/auto-update.js.map +1 -1
  58. package/dist/electron-build/utils/runtime-bootstrap.js +1 -1
  59. package/dist/electron-build/utils/runtime-bootstrap.js.map +1 -1
  60. package/dist/electron-build/utils/update-manager.js +3 -3
  61. package/dist/electron-build/utils/update-manager.js.map +1 -1
  62. package/dist/electron-build/utils/version-identity.js +1 -1
  63. package/dist/electron-build/utils/version-identity.js.map +1 -1
  64. package/dist/electron-build/web/routes-x402-info.js +28 -1
  65. package/dist/electron-build/web/routes-x402-info.js.map +1 -1
  66. package/dist/index.js +3 -3
  67. package/dist/llm/pi-ai.js +666 -47
  68. package/dist/utils/auto-update.js +2 -2
  69. package/dist/utils/runtime-bootstrap.js +1 -1
  70. package/dist/utils/update-health.js +2 -2
  71. package/dist/utils/update-manager.js +3 -3
  72. package/dist/utils/version-identity.js +1 -1
  73. package/dist/web/bolloon-web.json +3 -3
  74. package/dist/web/mobile.js +64 -0
  75. package/dist/web/routes-x402-info.js +28 -1
  76. package/dist/web/sw.js +1 -1
  77. package/package.json +2 -1
@@ -94,10 +94,10 @@ export async function checkAndUpdate(opts = {}) {
94
94
  case 'update_available': {
95
95
  notify(`⚠ 发现新版本: ${r.currentVersion} → ${r.latestVersion}`, YELLOW);
96
96
  if (!prefs.autoInstall) {
97
- notify(' 当前设置为**只通知不自动安装** (autoInstall=false)。更新: bolloon update plan → bolloon update now', CYAN);
97
+ notify(' 当前设置为**只通知不自动安装** (autoInstall=false)。更新: bolloon update (直接执行; 只看计划用 --dry-run)', CYAN);
98
98
  return {
99
99
  hasUpdate: true, info, updated: false,
100
- message: `发现新版 ${r.latestVersion}(未自动安装;运行 bolloon update now 更新)`,
100
+ message: `发现新版 ${r.latestVersion}(未自动安装;运行 bolloon update 更新)`,
101
101
  };
102
102
  }
103
103
  notify(' 自动安装已开启 (autoInstall=true),执行更新...', CYAN);
@@ -25,7 +25,7 @@ import { execFileSync, spawnSync } from 'child_process';
25
25
  import { resolveBolloonHome, CANONICAL_CONFIG_FILE } from '../setup/setup-store.js';
26
26
  export const RUNTIME_MIN = {
27
27
  node: { min: '18.0.0', why: 'Bolloon CLI 与依赖 (ESM / 全局 fetch / node: 前缀) 的运行时' },
28
- npm: { min: '9.0.0', why: '随 Node 18+ 发布; 全局安装与 `update now` 的安装通道' },
28
+ npm: { min: '9.0.0', why: '随 Node 18+ 发布; 全局安装与 `bolloon update` 的安装通道' },
29
29
  git: { min: '2.20.0', why: '`git -C` / `--porcelain` / worktree —— 源码更新与协作通道' },
30
30
  python: { min: '3.8.0', why: 'scripts/** (wiki 门禁/消融夹具) 与 Python Skill 执行' },
31
31
  };
@@ -345,13 +345,13 @@ export async function runDoctor(opts) {
345
345
  detail: `dev 快照: GitHub master ${st.devRef || 'refs/heads/master'} @ commit ${devSha} (比较语义 ${channelKindOf('dev')}, 非 semver)`
346
346
  + `${st.switchableTo ? ` · 可切回 stable (${st.switchableTo.source}${st.switchableTo.target ? ` @ ${st.switchableTo.target}` : ''})` : ''}`
347
347
  + ` · ${DEV_CHANNEL_WARNING}`,
348
- action: 'bolloon update now --channel stable',
348
+ action: 'bolloon update --channel stable',
349
349
  }
350
350
  : {
351
351
  id: 'update_source', label: '安装来源 (双源)', grade: 'ok',
352
352
  detail: `stable: npm registry 权威 (比较语义 ${channelKindOf('stable')})`
353
353
  + `${st.devSha ? ` · 上次用过 dev 快照 commit ${st.devSha}${st.devCheckedAt ? ` (${st.devCheckedAt})` : ''}, 已切回` : ''}`
354
- + ` · 默认通道 ${prefsChannel} · 切 dev 用: bolloon update now --channel dev`,
354
+ + ` · 默认通道 ${prefsChannel} · 切 dev 用: bolloon update --channel dev`,
355
355
  });
356
356
  }
357
357
  const inFlight = st.lastUpdate && IN_FLIGHT_RUN_STATUSES.includes(st.lastUpdate.status);
@@ -589,12 +589,12 @@ export function renderUpdatePlan(plan) {
589
589
  L.push('提醒 (不阻塞, 但建议先处理):');
590
590
  for (const a of plan.advisories)
591
591
  L.push(` - ${a}`);
592
- L.push(` 建议策略: 等当前 Run 结束后更新 (bolloon update --now --wait)`);
592
+ L.push(` 建议策略: 等当前 Run 结束后更新 (bolloon update wait)`);
593
593
  }
594
594
  L.push('');
595
- L.push(`可选: 立即更新 (bolloon update --now --channel ${plan.channel}) / 等当前 Run 结束 (bolloon update --now --wait --channel ${plan.channel}) / 取消`);
595
+ L.push(`可选: 立即更新 (bolloon update --channel ${plan.channel}) / 等当前 Run 结束 (bolloon update wait --channel ${plan.channel}) / 取消`);
596
596
  if (plan.channelKind === 'git-ref')
597
- L.push(`一键回稳定版: bolloon update now --channel stable`);
597
+ L.push(`一键回稳定版: bolloon update --channel stable`);
598
598
  L.push(`默认: ${plan.defaultStrategy === 'wait' ? '等待当前 Run 结束后更新' : '立即更新'}`);
599
599
  return L.join('\n');
600
600
  }
@@ -101,7 +101,7 @@ export function devShaFromIdentity(v) {
101
101
  */
102
102
  export const DEV_CHANNEL_WARNING = '⚠️ dev 通道 = GitHub master HEAD 的即时快照 (未走发布门): 可能中断正在跑的 Goal/Run, 且不保证可回滚到上一个 dev 版。';
103
103
  /** 一键回 stable 的提示语 (同一份措辞)。 */
104
- export const DEV_BACK_TO_STABLE_HINT = '一键回稳定版: bolloon update now --channel stable';
104
+ export const DEV_BACK_TO_STABLE_HINT = '一键回稳定版: bolloon update --channel stable';
105
105
  /** 手机端同一件事的说法 (原生层规则不同: 手机走 web 层 OTA, 不是 npm 全局安装)。 */
106
106
  export const DEV_BACK_TO_STABLE_HINT_MOBILE = '一键回稳定版: 手机端「更新」页 → 切回 stable';
107
107
  // ── 版本比较 (唯一一份) ─────────────────────────────────────────────────────
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schema": "bolloon-mobile-web/1",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "channel": "stable",
5
5
  "build": "stable",
6
- "commit": "8efb696025ea635cc4f0c907c275ea41c1ecf7a1",
7
- "builtAt": "2026-09-27T15:24:38.506Z",
6
+ "commit": "5d4b12a9059a6fa1679b349f9577e827a21fc427",
7
+ "builtAt": "2026-09-30T02:06:24.229Z",
8
8
  "layer": "web",
9
9
  "note": "web 资源层构建戳 (手机端 OTA 的身份第 ③ 级回退; 装机后以 OTA state.json 为准)"
10
10
  }
@@ -225,6 +225,68 @@
225
225
  }
226
226
  }
227
227
 
228
+ // ── Efficode 条目 (内置参考实现: 仓内 src/efficode/**, 不靠"从电脑端同步") ──────
229
+ // 纪律: 这段**不用 innerHTML 拼任何数据** (纯 createElement + textContent) ·
230
+ // 双语走 data-zh/data-en (切语言时外面那段 applyLang 会一起改文字节点) ·
231
+ // role=button + tabindex + aria-label + Enter/Space 可达 · 无外部依赖。
232
+ const EFFICODE_SPEC_PATH = 'docs/wiki/efficode.md';
233
+ const EFFICODE_IMPL_PATH = 'src/efficode/** · src/agents/agent-lang.ts';
234
+ const EFFICODE_GATE = 'scripts/verify-efficode.ts (55/0)';
235
+ function effiLangNow() {
236
+ try { return localStorage.getItem('bolloon_lang') === 'en' ? 'en' : 'zh'; } catch (e) { return 'zh'; }
237
+ }
238
+ function buildEfficodeEntry() {
239
+ const el = document.createElement('div');
240
+ el.className = 'conv-item';
241
+ el.id = 'item-efficode';
242
+ el.setAttribute('role', 'button');
243
+ el.setAttribute('tabindex', '0');
244
+ el.setAttribute('aria-label', 'Efficode 规范页 (中文): ' + EFFICODE_SPEC_PATH);
245
+ const avatar = document.createElement('div');
246
+ avatar.className = 'conv-avatar';
247
+ avatar.textContent = 'E';
248
+ const body = document.createElement('div');
249
+ body.className = 'conv-body';
250
+ const name = document.createElement('div');
251
+ name.className = 'conv-name';
252
+ name.textContent = '/efficode';
253
+ const desc = document.createElement('div');
254
+ desc.className = 'conv-preview';
255
+ desc.setAttribute('data-zh', '智能体间的符号化交流语言 · 参考实现 (签名/声波未实现) — 点开看规范页 docs/wiki/efficode.md');
256
+ desc.setAttribute('data-en', 'Symbolic agent-to-agent language · reference impl (signing/audio not implemented) — tap for docs/wiki/efficode.md');
257
+ desc.textContent = effiLangNow() === 'en' ? desc.getAttribute('data-en') : desc.getAttribute('data-zh');
258
+ body.appendChild(name);
259
+ body.appendChild(desc);
260
+ el.appendChild(avatar);
261
+ el.appendChild(body);
262
+ const open = () => alert(
263
+ '/efficode\n\n' +
264
+ (effiLangNow() === 'en'
265
+ ? 'Symbolic binary language between agents (Efficient + Code). Reference implementation in this repo; negotiation falls back to natural language unless both sides declare efficode. Signing / ECC session keys / sound-wave mode are NOT implemented.\n\n'
266
+ : '智能体之间的符号化二进制交流语言 (Efficient + Code)。本仓有参考实现; 只有双方都声明 efficode 才用, 否则明确回落自然语言。签名验证 / ECC 临时会话密钥 / 声波模式尚未实现。\n\n') +
267
+ '规范页: ' + EFFICODE_SPEC_PATH + '\n' +
268
+ '实现: ' + EFFICODE_IMPL_PATH + '\n' +
269
+ '验收门: ' + EFFICODE_GATE
270
+ );
271
+ el.addEventListener('click', open);
272
+ el.addEventListener('keydown', (ev) => {
273
+ if (ev.key === 'Enter' || ev.key === ' ' || ev.key === 'Spacebar') { ev.preventDefault(); open(); }
274
+ });
275
+ return el;
276
+ }
277
+
278
+ /** 把内置 Efficode 条目追加到 Skills 页 (空态 / 有列表都显示 —— 它是仓内参考实现) */
279
+ function appendEfficodeBlock(body) {
280
+ if (!body || body.querySelector('#item-efficode')) return;
281
+ const cap = document.createElement('div');
282
+ cap.style.cssText = 'font-size:11px;color:var(--text-muted);margin:14px 0 6px';
283
+ cap.setAttribute('data-zh', '内置 (随客户端发布, 不来自电脑端同步)');
284
+ cap.setAttribute('data-en', 'Built in (ships with the client, not synced from desktop)');
285
+ cap.textContent = effiLangNow() === 'en' ? cap.getAttribute('data-en') : cap.getAttribute('data-zh');
286
+ body.appendChild(cap);
287
+ body.appendChild(buildEfficodeEntry());
288
+ }
289
+
228
290
  async function openSkillsPage() {
229
291
  if ($('#skills-page')) return;
230
292
  const page = mkOverlayPage('skills-page', 'Skills', '<div style="font-size:12px;color:var(--text-muted)">读取中…</div>');
@@ -241,6 +303,7 @@
241
303
  body.innerHTML = `<div style="padding:18px 8px;text-align:center;color:var(--text-muted);line-height:1.8">
242
304
  还没有技能列表<br><span style="font-size:12px">电脑端 ~/.bolloon/skills/ 下的 skills,会在「从电脑端同步」后出现在这里</span>
243
305
  ${err ? `<div style="font-size:11px;margin-top:8px">(读取失败:${escapeHtml(err)})</div>` : ''}</div>`;
306
+ appendEfficodeBlock(body);
244
307
  return;
245
308
  }
246
309
  body.innerHTML = skills.map((s, i) => `<div class="conv-item" data-sk="${i}">
@@ -252,6 +315,7 @@
252
315
  const s = skills[Number(el.dataset.sk)] || {};
253
316
  alert(`/${s.name || ''}\n\n${s.description || '(无说明)'}`);
254
317
  }));
318
+ appendEfficodeBlock(body);
255
319
  };
256
320
  await render();
257
321
  const btn = page.querySelector('#skills-sync');
@@ -20,6 +20,7 @@ import * as os from 'os';
20
20
  import { listInfo, getStoredInfo, publishInfo, removeInfo, buildPaymentRequired, checkAndSettlePayment, buyInfo, } from '../agents/x402/paid-info-store.js';
21
21
  import { buildSignedEnvelope, verifyEnvelope, summarizeVerify } from '../agents/x402/paid-info-protocol.js';
22
22
  import { makeDidResolver } from '../agents/x402/paid-info-tools.js';
23
+ import { handleDirectPayment, directHealth, directPaymentPath, directPaymentEnabled } from '../agents/x402/direct-payment.js';
23
24
  /** 本机 DIAP 身份 (签发信封用) — 缺失时明确报错, 不静默造一个 */
24
25
  async function loadProviderKeypair() {
25
26
  try {
@@ -122,7 +123,7 @@ export function registerX402InfoRoutes(app) {
122
123
  content: stored.content,
123
124
  keypair: kp,
124
125
  payment: {
125
- mode: pay.mode === 'facilitator' ? 'facilitator' : 'local-dev',
126
+ mode: pay.mode === 'facilitator' ? 'facilitator' : pay.mode === 'direct' ? 'direct' : 'local-dev',
126
127
  receipt: String(pay.receipt || ''),
127
128
  txHash: pay.txHash,
128
129
  network: pay.network || stored.item.price.network,
@@ -139,6 +140,32 @@ export function registerX402InfoRoutes(app) {
139
140
  res.status(500).json({ error: e?.message });
140
141
  }
141
142
  });
143
+ // ---- 去中心化直付 (mode = 'direct'): 买方自己发 USDC, 把 txHash 交回来 ----
144
+ // POST /api/x402/info/:id/payment body: { "txHash": "0x…" }
145
+ // 服务器**只读链**: receipt.status=1 + USDC Transfer → payTo + value >= accepts.amount
146
+ // + 两条不同 RPC 交叉一致 + 确认数够 → 落待办 + 给取件 token (202); 未过 → 402 (accepts 逐字)
147
+ app.post('/api/x402/info/:id/payment', async (req, res) => {
148
+ try {
149
+ const id = String(req.params.id);
150
+ const stored = await getStoredInfo(id);
151
+ if (!stored)
152
+ return res.status(404).json({ error: '信息不存在' });
153
+ const baseUrl = `${req.protocol || 'http'}://${req.headers?.host || `127.0.0.1:${process.env.PORT || 54188}`}`;
154
+ const out = await handleDirectPayment({
155
+ item: stored.item,
156
+ bodyText: typeof req.body === 'string' ? req.body : JSON.stringify(req.body ?? {}),
157
+ resourceUrl: `${baseUrl}${directPaymentPath(stored.item.id)}`,
158
+ });
159
+ return res.status(out.status).set(out.headers).send(out.body);
160
+ }
161
+ catch (e) {
162
+ res.status(500).json({ error: e?.message });
163
+ }
164
+ });
165
+ // ---- 直付模式自述 (health 用: 开关与口径必须能从机器读到) ----
166
+ app.get('/api/x402/direct', async (_req, res) => {
167
+ res.json({ enabled: directPaymentEnabled(), paymentPath: directPaymentPath(':id'), ...directHealth() });
168
+ });
142
169
  // ---- 买方辅助: 代付 + 验真 ----
143
170
  app.post('/api/x402/info/buy', async (req, res) => {
144
171
  try {
package/dist/web/sw.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * 现在: 代码类资源 (html/js/css/json) 一律 **network-first** (拿不到网才回退缓存),
7
7
  * 缓存名带版本号, activate 时清掉所有旧缓存; 图标等静态资源仍 cache-first。
8
8
  */
9
- const CACHE = 'bolloon-mobile-v0.5.1';
9
+ const CACHE = 'bolloon-mobile-v0.5.3';
10
10
  const SHELL = [
11
11
  './mobile.html',
12
12
  './mobile.css',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolloon/bolloon-agent",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
6
6
  "main": "dist/cli-entry.js",
@@ -108,6 +108,7 @@
108
108
  "qrcode": "^1.5.4",
109
109
  "react": "^19.2.8",
110
110
  "react-dom": "^19.2.8",
111
+ "undici": "^7.30.0",
111
112
  "viem": "^2.56.3"
112
113
  },
113
114
  "devDependencies": {