@bolloon/bolloon-agent 0.6.5 → 0.6.6
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.
- package/dist/agents/chain/chain-settlement.js +0 -1
- package/dist/agents/chat-segmenter.js +4 -16
- package/dist/agents/contacts/human-directory.js +155 -0
- package/dist/agents/contacts/tools.js +79 -0
- package/dist/agents/experience-review.js +0 -3
- package/dist/agents/goal-flywheel/goal-change.js +3 -4
- package/dist/agents/goal-resume.js +0 -4
- package/dist/agents/intent-classifier.js +1 -1
- package/dist/agents/iteration-budget.js +12 -0
- package/dist/agents/knowledge-organizer.js +0 -2
- package/dist/agents/lesson-to-skill.js +0 -1
- package/dist/agents/loop-review.js +2 -2
- package/dist/agents/memory-store.js +359 -0
- package/dist/agents/opportunity-web-search.js +39 -0
- package/dist/agents/p2p-chat-tools.js +1 -2
- package/dist/agents/parse-tool-call.js +9 -22
- package/dist/agents/pi-harness.js +1 -2
- package/dist/agents/pi-sdk-tools.js +180 -5
- package/dist/agents/pi-sdk.js +143 -9
- package/dist/agents/process-runner.js +28 -9
- package/dist/agents/react-loop.js +9 -17
- package/dist/agents/runner-resolver.js +4 -3
- package/dist/agents/skill-loader.js +22 -15
- package/dist/agents/skills-manager.js +1 -25
- package/dist/agents/workflow-pivot-loop.js +152 -61
- package/dist/bootstrap/context-collector.js +2 -4
- package/dist/bootstrap/context-hierarchy.js +13 -1
- package/dist/cli/ink-app.js +44 -17
- package/dist/cli/intent-command.js +22 -12
- package/dist/cli/loading-tui.js +8 -2
- package/dist/cli/log-gate.js +40 -8
- package/dist/cli/mention-data.js +1 -0
- package/dist/cli/reply-hygiene.js +22 -0
- package/dist/cli/trace-line.js +61 -2
- package/dist/electron-build/agents/agent-gateway.js.map +1 -1
- package/dist/electron-build/agents/chain/chain-indexer.js.map +1 -1
- package/dist/electron-build/agents/chain/chain-settlement.js +0 -1
- package/dist/electron-build/agents/chain/chain-settlement.js.map +1 -1
- package/dist/electron-build/agents/contacts/chain.js.map +1 -1
- package/dist/electron-build/agents/contacts/human-directory.js +204 -0
- package/dist/electron-build/agents/contacts/human-directory.js.map +1 -0
- package/dist/electron-build/agents/contacts/policy.js.map +1 -1
- package/dist/electron-build/agents/contacts/tools.js +112 -0
- package/dist/electron-build/agents/contacts/tools.js.map +1 -1
- package/dist/electron-build/agents/experience-review.js +0 -3
- package/dist/electron-build/agents/experience-review.js.map +1 -1
- package/dist/electron-build/agents/external-events.js.map +1 -1
- package/dist/electron-build/agents/goal-flywheel/goal-change.js +3 -4
- package/dist/electron-build/agents/goal-flywheel/goal-change.js.map +1 -1
- package/dist/electron-build/agents/goal-flywheel-wiring.js.map +1 -1
- package/dist/electron-build/agents/goal-resume.js +0 -4
- package/dist/electron-build/agents/goal-resume.js.map +1 -1
- package/dist/electron-build/agents/intent-classifier.js +1 -1
- package/dist/electron-build/agents/lesson-to-skill.js +0 -1
- package/dist/electron-build/agents/lesson-to-skill.js.map +1 -1
- package/dist/electron-build/agents/loop-review.js +2 -2
- package/dist/electron-build/agents/loop-review.js.map +1 -1
- package/dist/electron-build/agents/memory-recall.js.map +1 -1
- package/dist/electron-build/agents/memory-store.js +404 -0
- package/dist/electron-build/agents/memory-store.js.map +1 -0
- package/dist/electron-build/agents/parse-tool-call.js +9 -22
- package/dist/electron-build/agents/parse-tool-call.js.map +1 -1
- package/dist/electron-build/agents/pi-harness.js +1 -2
- package/dist/electron-build/agents/pi-harness.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk-tools.js +180 -5
- package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
- package/dist/electron-build/agents/pi-sdk.js +143 -9
- package/dist/electron-build/agents/pi-sdk.js.map +1 -1
- package/dist/electron-build/agents/pre-tool-validator.js.map +1 -1
- package/dist/electron-build/agents/process-runner.js +28 -9
- package/dist/electron-build/agents/process-runner.js.map +1 -1
- package/dist/electron-build/agents/runner-resolver.js +4 -3
- package/dist/electron-build/agents/runner-resolver.js.map +1 -1
- package/dist/electron-build/agents/skill-loader.js +22 -16
- package/dist/electron-build/agents/skill-loader.js.map +1 -1
- package/dist/electron-build/agents/skill-supervisor-link.js.map +1 -1
- package/dist/electron-build/agents/skills-manager.js +0 -24
- package/dist/electron-build/agents/skills-manager.js.map +1 -1
- package/dist/electron-build/agents/task/task-runner.js.map +1 -1
- package/dist/electron-build/agents/workflow-engine.js.map +1 -1
- package/dist/electron-build/agents/workflow-pivot-loop.js +155 -62
- package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
- package/dist/electron-build/agents/x402/goal-run-bridge.js.map +1 -1
- package/dist/electron-build/bollharness-integration/gate-state-machine.js.map +1 -1
- package/dist/electron-build/bootstrap/context-collector.js +2 -4
- package/dist/electron-build/bootstrap/context-collector.js.map +1 -1
- package/dist/electron-build/bootstrap/context-hierarchy.js +13 -1
- package/dist/electron-build/bootstrap/context-hierarchy.js.map +1 -1
- package/dist/electron-build/electron-preload.js.map +1 -1
- package/dist/electron-build/external-engines/delegate.js.map +1 -1
- package/dist/electron-build/kernel/channel-actor.js +31 -2
- package/dist/electron-build/kernel/channel-actor.js.map +1 -1
- package/dist/electron-build/kernel/model-runtime.js +8 -1
- package/dist/electron-build/kernel/model-runtime.js.map +1 -1
- package/dist/electron-build/llm/config-store.js +20 -0
- package/dist/electron-build/llm/config-store.js.map +1 -1
- package/dist/electron-build/llm/embedding-adapter.js +75 -0
- package/dist/electron-build/llm/embedding-adapter.js.map +1 -0
- package/dist/electron-build/llm/pi-ai.js +96 -35
- package/dist/electron-build/llm/pi-ai.js.map +1 -1
- package/dist/electron-build/network/agent-network.js.map +1 -1
- package/dist/electron-build/orbitdb/memory-sync.js +76 -0
- package/dist/electron-build/orbitdb/memory-sync.js.map +1 -0
- package/dist/electron-build/pi-ecosystem-judgment/adaptive-scan.js.map +1 -1
- package/dist/electron-build/security/tool-gate.js +2 -0
- package/dist/electron-build/security/tool-gate.js.map +1 -1
- package/dist/electron-build/setup/setup-store.js +34 -6
- package/dist/electron-build/setup/setup-store.js.map +1 -1
- package/dist/electron-build/social/heartbeat.js +18 -5
- package/dist/electron-build/social/heartbeat.js.map +1 -1
- package/dist/electron-build/utils/update-manager.js.map +1 -1
- package/dist/index.js +250 -12
- package/dist/ios/bolloon-web.json +2 -2
- package/dist/ios/client.js +74 -35
- package/dist/ios/icons/icon-1400x1400.png +0 -0
- package/dist/ios/icons/icon-1400x1400.webp +0 -0
- package/dist/ios/index.html +106 -107
- package/dist/ios/mobile-agent.js +346 -45
- package/dist/ios/mobile-core.js +7303 -4590
- package/dist/ios/mobile-harness.js +1004 -0
- package/dist/ios/mobile-orbitdb.js +194 -0
- package/dist/ios/mobile-persona.js +80 -0
- package/dist/ios/mobile-privacy.js +2 -3
- package/dist/ios/mobile.css +286 -21
- package/dist/ios/mobile.html +106 -107
- package/dist/ios/mobile.js +300 -132
- package/dist/ios/routes-world.js +4 -1
- package/dist/ios/server.js +3 -1
- package/dist/ios/style.css +13 -5
- package/dist/ios/ui/message-renderer.js +4 -18
- package/dist/ios/ui/step-timeline.js +14 -1
- package/dist/kernel/channel-actor.js +30 -2
- package/dist/kernel/gate-scan.js +1 -1
- package/dist/kernel/index.js +33 -0
- package/dist/kernel/model-runtime.js +8 -1
- package/dist/kernel/plan.js +3 -3
- package/dist/kernel/roster.js +3 -3
- package/dist/llm/config-store.js +20 -0
- package/dist/llm/embedding-adapter.js +69 -0
- package/dist/llm/pi-ai.js +94 -34
- package/dist/orbitdb/memory-sync.js +70 -0
- package/dist/pi-ecosystem-judgment/adaptive-scan.js +1 -1
- package/dist/security/tool-gate.js +2 -0
- package/dist/setup/setup-store.js +34 -6
- package/dist/social/heartbeat.js +18 -5
- package/dist/web/bolloon-web.json +3 -3
- package/dist/web/client.js +74 -35
- package/dist/web/icons/icon-1400x1400.png +0 -0
- package/dist/web/icons/icon-1400x1400.webp +0 -0
- package/dist/web/index.html +37 -25
- package/dist/web/mobile-agent.js +351 -45
- package/dist/web/mobile-contacts.js +0 -4
- package/dist/web/mobile-core.js +7430 -4590
- package/dist/web/mobile-harness.js +1004 -0
- package/dist/web/mobile-orbitdb.js +194 -0
- package/dist/web/mobile-persona.js +80 -0
- package/dist/web/mobile-privacy.js +2 -3
- package/dist/web/mobile.css +286 -21
- package/dist/web/mobile.html +121 -107
- package/dist/web/mobile.js +409 -136
- package/dist/web/routes-contacts.js +94 -1
- package/dist/web/routes-world.js +4 -1
- package/dist/web/server.js +4 -2
- package/dist/web/style.css +13 -5
- package/dist/web/sw.js +1 -1
- package/dist/web/ui/message-renderer.js +4 -18
- package/dist/web/ui/step-timeline.js +14 -1
- package/package.json +3 -2
- package/scripts/build-web.ts +16 -1
|
@@ -413,8 +413,101 @@ export function registerContactRoutes(app, opts = {}) {
|
|
|
413
413
|
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
414
414
|
}
|
|
415
415
|
});
|
|
416
|
+
// ── 手机号目录 (2026-10-11, phone-account-lookup-design 落点 A) ────────────
|
|
417
|
+
// 隐私: 请求/响应全程只过「盲化哈希」, 明文手机号只在请求体出现一次 (发布/查询),
|
|
418
|
+
// 永不出现在响应里 (与 contacts 既有红线一致)。
|
|
419
|
+
const dirHome = () => opts.home || undefined;
|
|
420
|
+
/** 发布手机号 → DID 指针 (opt-in; 用户显式调用) */
|
|
421
|
+
app.post('/api/contacts/directory/publish', async (req, res) => {
|
|
422
|
+
try {
|
|
423
|
+
const { publishEntry, isPlausiblePhone } = await import('../agents/contacts/human-directory.js');
|
|
424
|
+
const phone = String(req.body?.phone || '');
|
|
425
|
+
const did = String(req.body?.did || ownerDidFromDisk());
|
|
426
|
+
if (!isPlausiblePhone(phone))
|
|
427
|
+
return res.status(400).json({ ok: false, error: '手机号格式不正确' });
|
|
428
|
+
const e = await publishEntry(phone, did, {
|
|
429
|
+
displayName: req.body?.displayName ? String(req.body.displayName) : undefined,
|
|
430
|
+
publicKeyHex: req.body?.publicKeyHex ? String(req.body.publicKeyHex) : undefined,
|
|
431
|
+
homeDir: dirHome(),
|
|
432
|
+
});
|
|
433
|
+
res.json({ ok: true, phoneHash: e.phoneHash.slice(0, 8) + '…', did: e.did, publicKeyHex: e.publicKeyHex || null, publishedAt: e.publishedAt });
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
/** 撤销目录条目 (软删) */
|
|
440
|
+
app.post('/api/contacts/directory/retract', async (req, res) => {
|
|
441
|
+
try {
|
|
442
|
+
const { retractEntry } = await import('../agents/contacts/human-directory.js');
|
|
443
|
+
const did = String(req.body?.did || ownerDidFromDisk());
|
|
444
|
+
const ok = await retractEntry(did, dirHome());
|
|
445
|
+
res.json({ ok, revoked: ok });
|
|
446
|
+
}
|
|
447
|
+
catch (err) {
|
|
448
|
+
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
/** 按手机号查账号 (在本机目录内找; 响应只回 DID/昵称, 绝不回手机号) */
|
|
452
|
+
app.post('/api/contacts/directory/lookup', async (req, res) => {
|
|
453
|
+
try {
|
|
454
|
+
const { lookupPhone, isPlausiblePhone } = await import('../agents/contacts/human-directory.js');
|
|
455
|
+
const phone = String(req.body?.phone || '');
|
|
456
|
+
if (!isPlausiblePhone(phone))
|
|
457
|
+
return res.status(400).json({ ok: false, error: '手机号格式不正确' });
|
|
458
|
+
const r = await lookupPhone(phone, dirHome());
|
|
459
|
+
if (!r.found)
|
|
460
|
+
return res.json({ ok: true, found: false, note: '未找到 (未注册或未公开)' });
|
|
461
|
+
res.json({ ok: true, found: true, did: r.did, publicKeyHex: r.publicKeyHex || null, displayName: r.displayName || null });
|
|
462
|
+
}
|
|
463
|
+
catch (err) {
|
|
464
|
+
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
/** 按手机号直接发好友请求 (P1, 2026-10-15): directory lookup → publicKeyHex → 既有 /api/friend-request */
|
|
468
|
+
app.post('/api/contacts/directory/add-friend', async (req, res) => {
|
|
469
|
+
try {
|
|
470
|
+
const { lookupPhone, isPlausiblePhone } = await import('../agents/contacts/human-directory.js');
|
|
471
|
+
const phone = String(req.body?.phone || '');
|
|
472
|
+
if (!isPlausiblePhone(phone))
|
|
473
|
+
return res.status(400).json({ ok: false, error: '手机号格式不正确' });
|
|
474
|
+
const r = await lookupPhone(phone, dirHome());
|
|
475
|
+
if (!r.found)
|
|
476
|
+
return res.json({ ok: true, found: false, note: '未找到 (未注册或未公开)' });
|
|
477
|
+
if (!r.publicKeyHex)
|
|
478
|
+
return res.status(422).json({ ok: false, found: true, error: `对方已注册目录但未公开 P2P 公钥 (${r.did?.slice(0, 20)}…), 无法直接加好友` });
|
|
479
|
+
// 委托给既有好友请求链路 (本机端口; 与 pi-sdk accept 工具同口径)
|
|
480
|
+
const port = process.env.PORT || '54188';
|
|
481
|
+
const fr = await fetch(`http://127.0.0.1:${port}/api/friend-request`, {
|
|
482
|
+
method: 'POST',
|
|
483
|
+
headers: { 'Content-Type': 'application/json' },
|
|
484
|
+
body: JSON.stringify({
|
|
485
|
+
targetPublicKey: r.publicKeyHex,
|
|
486
|
+
name: req.body?.name ? String(req.body.name) : r.displayName || undefined,
|
|
487
|
+
message: req.body?.message ? String(req.body.message) : `来自手机号目录: 想加你为好友`,
|
|
488
|
+
note: `via-phone-directory`,
|
|
489
|
+
}),
|
|
490
|
+
});
|
|
491
|
+
const data = await fr.json();
|
|
492
|
+
res.status(fr.status).json({ ok: data.ok !== false, found: true, did: r.did, friend: data });
|
|
493
|
+
}
|
|
494
|
+
catch (err) {
|
|
495
|
+
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
/** 列出已发布条目 (本机审计; 只回脱敏哈希) */
|
|
499
|
+
app.get('/api/contacts/directory/list', async (_req, res) => {
|
|
500
|
+
try {
|
|
501
|
+
const { readDirectory, summarizeEntries } = await import('../agents/contacts/human-directory.js');
|
|
502
|
+
const entries = await readDirectory(dirHome());
|
|
503
|
+
res.json({ ok: true, entries: summarizeEntries(entries) });
|
|
504
|
+
}
|
|
505
|
+
catch (err) {
|
|
506
|
+
res.status(500).json({ ok: false, error: String(err?.message || err) });
|
|
507
|
+
}
|
|
508
|
+
});
|
|
416
509
|
// ── 隐藏守卫自检 (验收/测试直接用) ──────────────────────────────────────────
|
|
417
510
|
app.get('/api/contacts/_selfcheck', (_req, res) => {
|
|
418
|
-
res.json({ ok: true, plaintextGuard: looksLikePlaintextSecret({ contacts: [{ value: '+
|
|
511
|
+
res.json({ ok: true, plaintextGuard: looksLikePlaintextSecret({ contacts: [{ value: '+861****5678' }] }) });
|
|
419
512
|
});
|
|
420
513
|
}
|
package/dist/web/routes-world.js
CHANGED
|
@@ -12,7 +12,10 @@ function bodyOf(req) {
|
|
|
12
12
|
}
|
|
13
13
|
/** 限制输入形状: 只收明确字段, 不整个吞前端对象 */
|
|
14
14
|
function intentInputFromBody(body) {
|
|
15
|
-
|
|
15
|
+
// 2026-10-06 修 bug: 之前调 bodyOf(body) —— bodyOf 期望 Request 访问 .body,
|
|
16
|
+
// 传 body 对象本身时 req.body = body.body = undefined ⇒ 永远返回 {} ⇒ 所有字段都丢。
|
|
17
|
+
// body 此刻已是 express.json 解析后的对象, 直接校验即可。
|
|
18
|
+
const b = body && typeof body === 'object' ? body : {};
|
|
16
19
|
const out = {};
|
|
17
20
|
if (typeof b.text === 'string' && b.text.trim())
|
|
18
21
|
out.text = b.text.trim();
|
package/dist/web/server.js
CHANGED
|
@@ -920,6 +920,7 @@ async function handleV3P2PMessage(parsed, conn, comm) {
|
|
|
920
920
|
output: event.output,
|
|
921
921
|
error: event.error,
|
|
922
922
|
args: event.args,
|
|
923
|
+
durationMs: event.durationMs, // 2026-10-12: 命令执行时间读秒
|
|
923
924
|
fromPublicKey: v3P2PRef?.getPublicKey() || ''
|
|
924
925
|
}
|
|
925
926
|
});
|
|
@@ -4941,7 +4942,7 @@ fetchState();
|
|
|
4941
4942
|
// (与邮箱串行一致), web 不再自己持 abortController。取到 agent 后立刻开户 (见下面 getAgentForChannel 之后)。
|
|
4942
4943
|
let abortSignal;
|
|
4943
4944
|
// 2026-07-04: pivot loop safety net — 防止 LLM hang (minimax M3
|
|
4944
|
-
// 偶尔反复 think
|
|
4945
|
+
// 偶尔反复 think 不输出结果, pivot 连 5 次无进展时会 hang 在
|
|
4945
4946
|
// quality 评估). setTimeout 让 LLM 客户端收 signal 主动 break.
|
|
4946
4947
|
// 2026-07-06: 30s 太短 — minimax M3 单次 LLM 约 10s, pivot 默认 moderate profile 30 iter
|
|
4947
4948
|
// 留 ~300s. 之前 30s 自动 abort 时, 一次"你好"调用就被截断, 用户看到 ❌ 循环异常 + 空内容.
|
|
@@ -5169,7 +5170,7 @@ fetchState();
|
|
|
5169
5170
|
// 2026-06-10: 注入 skills 列表 (本机 ~/.bolloon/skills/ 下所有 skills)
|
|
5170
5171
|
// 让 LLM 知道有哪些 skill 可用, 在回复中提示用户
|
|
5171
5172
|
try {
|
|
5172
|
-
const { loadSkillsFromPaths, defaultSkillPaths
|
|
5173
|
+
const { loadSkillsFromPaths, defaultSkillPaths } = await import('../agents/skill-loader.js');
|
|
5173
5174
|
const paths = defaultSkillPaths();
|
|
5174
5175
|
const skills = await loadSkillsFromPaths(paths);
|
|
5175
5176
|
if (skills.length > 0) {
|
|
@@ -6901,6 +6902,7 @@ fetchState();
|
|
|
6901
6902
|
output: event.output,
|
|
6902
6903
|
error: event.error,
|
|
6903
6904
|
args: event.args,
|
|
6905
|
+
durationMs: event.durationMs, // 2026-10-12: 命令执行时间读秒
|
|
6904
6906
|
}, channelId);
|
|
6905
6907
|
}
|
|
6906
6908
|
else if (event.type === 'error') {
|
package/dist/web/style.css
CHANGED
|
@@ -126,13 +126,20 @@ body {
|
|
|
126
126
|
flex-shrink: 0;
|
|
127
127
|
transition: var(--transition);
|
|
128
128
|
transform: translateX(0);
|
|
129
|
-
|
|
129
|
+
/* 2026-10-06: 改为 fixed 覆盖 — sidebar 收起时绝对定位脱离流, relative 会被挤成 0 宽,
|
|
130
|
+
恢复条必须固定在屏幕左侧才能被看到/点到 */
|
|
131
|
+
position: fixed;
|
|
132
|
+
left: 0;
|
|
133
|
+
top: 0;
|
|
134
|
+
height: 100%;
|
|
130
135
|
z-index: 99;
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
.sidebar-collapsed.hidden {
|
|
134
139
|
transform: translateX(calc(-1 * var(--sidebar-collapsed)));
|
|
135
|
-
position:
|
|
140
|
+
position: fixed;
|
|
141
|
+
left: 0;
|
|
142
|
+
top: 0;
|
|
136
143
|
height: 100%;
|
|
137
144
|
}
|
|
138
145
|
|
|
@@ -1876,18 +1883,19 @@ body {
|
|
|
1876
1883
|
flex-shrink: 0;
|
|
1877
1884
|
}
|
|
1878
1885
|
.header-tab {
|
|
1879
|
-
padding:
|
|
1886
|
+
padding: 7px 22px;
|
|
1880
1887
|
background: transparent;
|
|
1881
1888
|
border: none;
|
|
1882
1889
|
border-radius: 6px;
|
|
1883
1890
|
color: var(--text-secondary);
|
|
1884
|
-
font-size:
|
|
1891
|
+
font-size: 13px;
|
|
1885
1892
|
font-weight: 600;
|
|
1886
1893
|
cursor: pointer;
|
|
1887
1894
|
transition: var(--transition);
|
|
1888
1895
|
display: flex;
|
|
1889
1896
|
align-items: center;
|
|
1890
|
-
gap:
|
|
1897
|
+
gap: 5px;
|
|
1898
|
+
white-space: nowrap;
|
|
1891
1899
|
}
|
|
1892
1900
|
.header-tab:hover {
|
|
1893
1901
|
color: var(--text-primary);
|
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.6.
|
|
9
|
+
const CACHE = 'bolloon-mobile-v0.6.6';
|
|
10
10
|
const SHELL = [
|
|
11
11
|
'./mobile.html',
|
|
12
12
|
'./mobile.css',
|
|
@@ -261,21 +261,10 @@ function segmentChatReply(reply, ctx) {
|
|
|
261
261
|
if (remaining.trim()) {
|
|
262
262
|
remaining = filterFillerText(remaining);
|
|
263
263
|
}
|
|
264
|
-
const
|
|
265
|
-
let beforeFinalText = remaining;
|
|
266
|
-
if (finalIdx >= 0) {
|
|
267
|
-
beforeFinalText = remaining.substring(0, finalIdx);
|
|
268
|
-
}
|
|
269
|
-
const textContent = beforeFinalText.trim();
|
|
264
|
+
const textContent = remaining.trim();
|
|
270
265
|
if (textContent) {
|
|
271
266
|
segments.push({ type: "text", content: textContent });
|
|
272
267
|
}
|
|
273
|
-
if (finalIdx >= 0) {
|
|
274
|
-
const afterFinal = remaining.substring(finalIdx + "<final gen>".length).trim();
|
|
275
|
-
if (afterFinal) {
|
|
276
|
-
segments.push({ type: "final", content: afterFinal });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
268
|
return segments;
|
|
280
269
|
}
|
|
281
270
|
function extractAndPush(type, text, out, re) {
|
|
@@ -530,11 +519,7 @@ function addMessage(content, type, save = true, container, usedJudgmentIds = [],
|
|
|
530
519
|
div.className = `message message-${type}`;
|
|
531
520
|
let cleanContent = content;
|
|
532
521
|
if (type === "ai") {
|
|
533
|
-
cleanContent = cleanContent.replace(
|
|
534
|
-
const finalGenIdx = cleanContent.indexOf("<final gen>");
|
|
535
|
-
if (finalGenIdx >= 0) {
|
|
536
|
-
cleanContent = cleanContent.substring(0, finalGenIdx).trim();
|
|
537
|
-
}
|
|
522
|
+
cleanContent = cleanContent.replace(/ thinking[\s\S]*?<\/think>/g, "");
|
|
538
523
|
}
|
|
539
524
|
const knownToolNames = ctx && ctx.knownToolNames || /* @__PURE__ */ new Set();
|
|
540
525
|
const segments = segmentChatReply(cleanContent, { knownToolNames });
|
|
@@ -858,7 +843,8 @@ function handleStepEvent(data, ctx = { messagesEl: null, messagesContainers: /*
|
|
|
858
843
|
args: data.args,
|
|
859
844
|
success: data.success,
|
|
860
845
|
output: data.output,
|
|
861
|
-
error: data.error
|
|
846
|
+
error: data.error,
|
|
847
|
+
durationMs: data.durationMs
|
|
862
848
|
});
|
|
863
849
|
}
|
|
864
850
|
function flushStepEventBuffer(channelId, ctx) {
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
// src/web/ui/step-timeline.ts
|
|
2
2
|
var MAX_VISIBLE_NODES = 20;
|
|
3
3
|
var STORAGE_PREFIX = "bolloon.stepTimeline.expanded.";
|
|
4
|
+
function formatDuration(ms) {
|
|
5
|
+
if (!Number.isFinite(ms) || ms < 0) return "(耗时未知)";
|
|
6
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
7
|
+
const s = ms / 1e3;
|
|
8
|
+
if (s < 60) return `${s.toFixed(1)}s`;
|
|
9
|
+
const m = Math.floor(s / 60);
|
|
10
|
+
const rem = Math.round(s % 60);
|
|
11
|
+
return `${m}m${rem}s`;
|
|
12
|
+
}
|
|
4
13
|
var stateMap = /* @__PURE__ */ new WeakMap();
|
|
5
14
|
function readExpanded(channelId) {
|
|
6
15
|
if (!channelId) return false;
|
|
@@ -121,7 +130,10 @@ function render(timelineEl) {
|
|
|
121
130
|
}
|
|
122
131
|
node.setAttribute("data-status", step.status);
|
|
123
132
|
const label = node.querySelector(".step-timeline-label");
|
|
124
|
-
if (label)
|
|
133
|
+
if (label) {
|
|
134
|
+
const dur = step.durationMs !== void 0 && step.status !== "active" ? ` · ${formatDuration(step.durationMs)}` : "";
|
|
135
|
+
label.textContent = step.name + dur;
|
|
136
|
+
}
|
|
125
137
|
const argsEl = node.querySelector(".step-timeline-args");
|
|
126
138
|
if (argsEl) {
|
|
127
139
|
const argStr = step.args && Object.keys(step.args).length > 0 ? JSON.stringify(step.args).slice(0, 60) : "";
|
|
@@ -265,6 +277,7 @@ function pushStepToTimeline(timelineEl, eventType, data) {
|
|
|
265
277
|
steps[targetIdx].status = data.success === false ? "error" : "done";
|
|
266
278
|
if (data.output) steps[targetIdx].output = data.output;
|
|
267
279
|
if (data.error) steps[targetIdx].error = data.error;
|
|
280
|
+
if (data.durationMs !== void 0) steps[targetIdx].durationMs = data.durationMs;
|
|
268
281
|
} else {
|
|
269
282
|
steps[targetIdx].status = "error";
|
|
270
283
|
if (data.error) steps[targetIdx].error = data.error;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bolloon/bolloon-agent",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "P2P AI Document Agent - 全局安装后执行 `bolloon` 启动产品",
|
|
6
6
|
"main": "dist/cli-entry.js",
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
"ios:release": "bash scripts/ios-release.sh"
|
|
60
60
|
},
|
|
61
61
|
"workspaces": [
|
|
62
|
-
"src/constraint-runtime"
|
|
62
|
+
"src/constraint-runtime",
|
|
63
|
+
"src/kernel"
|
|
63
64
|
],
|
|
64
65
|
"dependencies": {
|
|
65
66
|
"@a2ui/react": "^0.11.0",
|
package/scripts/build-web.ts
CHANGED
|
@@ -14,7 +14,7 @@ async function main() {
|
|
|
14
14
|
|
|
15
15
|
// 重要: 不能 rm -rf 整个 dist/web/, 否则会删掉 build:main 编译出来的
|
|
16
16
|
// dist/web/server.js. 只清理 web 静态资源, 保留 server.js.
|
|
17
|
-
for (const f of ['index.html', 'api-config.html', 'explorer.html', 'style.css', 'client.js', 'chain-explorer.js', 'mobile.html', 'mobile.css', 'mobile.js', 'mobile-core.js', 'components']) {
|
|
17
|
+
for (const f of ['index.html', 'api-config.html', 'explorer.html', 'style.css', 'client.js', 'chain-explorer.js', 'mobile.html', 'mobile.css', 'mobile.js', 'mobile-core.js', 'mobile-persona.js', 'components']) {
|
|
18
18
|
await fs.rm(path.join(DIST_WEB, f), { recursive: true, force: true });
|
|
19
19
|
}
|
|
20
20
|
await fs.mkdir(DIST_WEB, { recursive: true });
|
|
@@ -115,6 +115,21 @@ async function main() {
|
|
|
115
115
|
bundle: true,
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
+
// 2026-10-09: mobile.js 动态 import('./mobile-persona.js')。
|
|
119
|
+
// 这是手机端可直接运行 Agent 的配置依赖,必须随 dist/web 一起生成,
|
|
120
|
+
// 否则 WebView 会静默 404,性格页和 Web Agent 都会失效。
|
|
121
|
+
console.log('[build-web] 编译 mobile-persona.ts...');
|
|
122
|
+
await esbuild.build({
|
|
123
|
+
entryPoints: [path.join(ROOT, 'src/web/mobile-persona.ts')],
|
|
124
|
+
outfile: path.join(DIST_WEB, 'mobile-persona.js'),
|
|
125
|
+
format: 'esm',
|
|
126
|
+
target: 'es2022',
|
|
127
|
+
platform: 'browser',
|
|
128
|
+
minify: false,
|
|
129
|
+
bundle: true,
|
|
130
|
+
charset: 'utf8',
|
|
131
|
+
});
|
|
132
|
+
|
|
118
133
|
// 2026-08-12: 编译 A2UI 前端渲染器 (a2ui-client.tsx → a2ui-client.js)
|
|
119
134
|
// react + @a2ui/react + @a2ui/web_core 全部打包进 bundle (手机端 webview 无 CDN)
|
|
120
135
|
console.log('[build-web] 编译 a2ui-client.tsx...');
|