@bolloon/bolloon-agent 0.5.5 → 0.6.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 (109) hide show
  1. package/dist/agents/parse-tool-call.js +6 -1
  2. package/dist/agents/pi-sdk-session-factory.js +36 -3
  3. package/dist/agents/pi-sdk.js +349 -199
  4. package/dist/agents/run-context.js +20 -0
  5. package/dist/agents/runner-resolver.js +2 -1
  6. package/dist/electron-build/agents/parse-tool-call.js +6 -1
  7. package/dist/electron-build/agents/parse-tool-call.js.map +1 -1
  8. package/dist/electron-build/agents/pi-sdk-session-factory.js +36 -3
  9. package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -1
  10. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
  11. package/dist/electron-build/agents/pi-sdk.js +349 -199
  12. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  13. package/dist/electron-build/agents/run-context.js +24 -0
  14. package/dist/electron-build/agents/run-context.js.map +1 -0
  15. package/dist/electron-build/agents/runner-resolver.js +2 -1
  16. package/dist/electron-build/agents/runner-resolver.js.map +1 -1
  17. package/dist/electron-build/kernel/channel-actor.js +314 -0
  18. package/dist/electron-build/kernel/channel-actor.js.map +1 -0
  19. package/dist/index.js +24 -19
  20. package/dist/kernel/channel-actor.js +297 -0
  21. package/dist/kernel/control.js +95 -0
  22. package/dist/kernel/gate-scan.js +1036 -0
  23. package/dist/kernel/model-runtime.js +472 -0
  24. package/dist/kernel/plan-channel-actor.js +298 -0
  25. package/dist/kernel/plan-constraint.js +165 -0
  26. package/dist/kernel/plan-deletion.js +32 -0
  27. package/dist/kernel/plan-modelruntime.js +60 -0
  28. package/dist/kernel/plan-runcontext.js +163 -0
  29. package/dist/kernel/plan.js +153 -0
  30. package/dist/kernel/roster.js +242 -0
  31. package/dist/web/bolloon-web.json +3 -3
  32. package/dist/web/client.js +3 -2
  33. package/dist/web/routes-tasks.js +5 -1
  34. package/dist/web/server.js +58 -18
  35. package/dist/web/sw.js +1 -1
  36. package/dist/web/ui/message-renderer.js +473 -29
  37. package/dist/web/ui/step-timeline.js +13 -12
  38. package/package.json +1 -1
  39. package/scripts/build-web.ts +74 -1
  40. package/dist/constraint-runtime/_archive_helper.d.ts +0 -1
  41. package/dist/constraint-runtime/_archive_helper.js +0 -9
  42. package/dist/constraint-runtime/assistant/index.d.ts +0 -11
  43. package/dist/constraint-runtime/assistant/index.js +0 -12
  44. package/dist/constraint-runtime/bootstrap/index.d.ts +0 -11
  45. package/dist/constraint-runtime/bootstrap/index.js +0 -12
  46. package/dist/constraint-runtime/bridge/index.d.ts +0 -11
  47. package/dist/constraint-runtime/bridge/index.js +0 -12
  48. package/dist/constraint-runtime/buddy/index.d.ts +0 -11
  49. package/dist/constraint-runtime/buddy/index.js +0 -12
  50. package/dist/constraint-runtime/cli/index.d.ts +0 -11
  51. package/dist/constraint-runtime/cli/index.js +0 -12
  52. package/dist/constraint-runtime/components/index.d.ts +0 -11
  53. package/dist/constraint-runtime/components/index.js +0 -12
  54. package/dist/constraint-runtime/constants/index.d.ts +0 -11
  55. package/dist/constraint-runtime/constants/index.js +0 -12
  56. package/dist/constraint-runtime/coordinator/index.d.ts +0 -11
  57. package/dist/constraint-runtime/coordinator/index.js +0 -12
  58. package/dist/constraint-runtime/cost_hook.d.ts +0 -2
  59. package/dist/constraint-runtime/cost_hook.js +0 -4
  60. package/dist/constraint-runtime/entrypoints/index.d.ts +0 -11
  61. package/dist/constraint-runtime/entrypoints/index.js +0 -12
  62. package/dist/constraint-runtime/execution_registry.d.ts +0 -20
  63. package/dist/constraint-runtime/execution_registry.js +0 -44
  64. package/dist/constraint-runtime/hooks/index.d.ts +0 -11
  65. package/dist/constraint-runtime/hooks/index.js +0 -12
  66. package/dist/constraint-runtime/ink.d.ts +0 -1
  67. package/dist/constraint-runtime/ink.js +0 -4
  68. package/dist/constraint-runtime/keybindings/index.d.ts +0 -11
  69. package/dist/constraint-runtime/keybindings/index.js +0 -12
  70. package/dist/constraint-runtime/memdir/index.d.ts +0 -11
  71. package/dist/constraint-runtime/memdir/index.js +0 -12
  72. package/dist/constraint-runtime/migrations/index.d.ts +0 -11
  73. package/dist/constraint-runtime/migrations/index.js +0 -12
  74. package/dist/constraint-runtime/moreright/index.d.ts +0 -11
  75. package/dist/constraint-runtime/moreright/index.js +0 -12
  76. package/dist/constraint-runtime/native_ts/index.d.ts +0 -11
  77. package/dist/constraint-runtime/native_ts/index.js +0 -12
  78. package/dist/constraint-runtime/output_styles/index.d.ts +0 -11
  79. package/dist/constraint-runtime/output_styles/index.js +0 -12
  80. package/dist/constraint-runtime/plugins/index.d.ts +0 -11
  81. package/dist/constraint-runtime/plugins/index.js +0 -12
  82. package/dist/constraint-runtime/port_manifest.d.ts +0 -7
  83. package/dist/constraint-runtime/port_manifest.js +0 -11
  84. package/dist/constraint-runtime/query.d.ts +0 -6
  85. package/dist/constraint-runtime/query.js +0 -1
  86. package/dist/constraint-runtime/remote/index.d.ts +0 -11
  87. package/dist/constraint-runtime/remote/index.js +0 -12
  88. package/dist/constraint-runtime/schemas/index.d.ts +0 -11
  89. package/dist/constraint-runtime/schemas/index.js +0 -12
  90. package/dist/constraint-runtime/screens/index.d.ts +0 -11
  91. package/dist/constraint-runtime/screens/index.js +0 -12
  92. package/dist/constraint-runtime/server/index.d.ts +0 -11
  93. package/dist/constraint-runtime/server/index.js +0 -12
  94. package/dist/constraint-runtime/services/index.d.ts +0 -11
  95. package/dist/constraint-runtime/services/index.js +0 -12
  96. package/dist/constraint-runtime/state/index.d.ts +0 -11
  97. package/dist/constraint-runtime/state/index.js +0 -12
  98. package/dist/constraint-runtime/system_init.d.ts +0 -1
  99. package/dist/constraint-runtime/system_init.js +0 -20
  100. package/dist/constraint-runtime/types/index.d.ts +0 -11
  101. package/dist/constraint-runtime/types/index.js +0 -12
  102. package/dist/constraint-runtime/upstream_proxy/index.d.ts +0 -11
  103. package/dist/constraint-runtime/upstream_proxy/index.js +0 -12
  104. package/dist/constraint-runtime/utils/index.d.ts +0 -11
  105. package/dist/constraint-runtime/utils/index.js +0 -12
  106. package/dist/constraint-runtime/vim/index.d.ts +0 -11
  107. package/dist/constraint-runtime/vim/index.js +0 -12
  108. package/dist/constraint-runtime/voice/index.d.ts +0 -11
  109. package/dist/constraint-runtime/voice/index.js +0 -12
@@ -87,6 +87,8 @@ console.log = (...args) => {
87
87
  import { createHyperswarmCommunicator, createTopic, KeyManager, AgentAuthManager, } from '@diap/sdk';
88
88
  import { initMinimax } from '../constraints/index.js';
89
89
  import { createAgentSession } from '../agents/pi-sdk.js';
90
+ // **K5 步骤④ (入口投递)**: 把一次入口执行投进会话 Actor 的 mailbox ⇒ 同一会话身份的输入排队执行
91
+ import { deliverThroughActor } from '../kernel/channel-actor.js';
90
92
  import { irohTransport } from '../network/iroh-transport.js';
91
93
  import { createAgentDelegateApp } from './agent-delegate-server.js';
92
94
  import { createIrohDelegateTransport } from './iroh-delegate-transport.js';
@@ -585,7 +587,7 @@ async function triggerRemoteFollowup(channelId, remoteReply, fromPublicKey, roun
585
587
  broadcast({ type: 'followup-step', ...event, channelId }, channelId);
586
588
  }
587
589
  };
588
- const fullResponse = await agent.promptStream(markedPrompt, streamCallback, undefined, channelId);
590
+ const fullResponse = await deliverThroughActor(agent, () => agent.promptStream(markedPrompt, streamCallback, undefined, channelId));
589
591
  if (!fullResponse.trim())
590
592
  return;
591
593
  // 广播续看结果给 UI
@@ -913,7 +915,7 @@ async function handleV3P2PMessage(parsed, conn, comm) {
913
915
  }
914
916
  };
915
917
  const agent = await getAgentForChannel(channelId, ch.did || '', ch.name, ch.didDocRef);
916
- fullResponse = await agent.promptStream(fullPrompt, streamCallback, undefined, channelId);
918
+ fullResponse = await deliverThroughActor(agent, () => agent.promptStream(fullPrompt, streamCallback, undefined, channelId));
917
919
  // 2026-07-06: 防御性兜底
918
920
  if (!fullResponse.trim()) {
919
921
  fullResponse = '⚠️ AI 未返回内容, 请重试';
@@ -1065,7 +1067,7 @@ async function handleV3P2PMessage(parsed, conn, comm) {
1065
1067
  // 临时用 channelId = "__collab__" 拿个一次性 agent
1066
1068
  const collabChannelId = `__collab_${senderKey.substring(0, 8)}__`;
1067
1069
  const agent = await getAgentForChannel(collabChannelId, '', `collab-${senderKey.substring(0, 8)}`, undefined);
1068
- const resultText = await agent.prompt(fullPrompt);
1070
+ const resultText = await deliverThroughActor(agent, () => agent.prompt(fullPrompt));
1069
1071
  const reply = JSON.stringify({
1070
1072
  v: 3,
1071
1073
  op: 'agent.collab.reply',
@@ -1679,7 +1681,7 @@ export async function createWebServer(port = 3000, options = {}) {
1679
1681
  // 跨预算继续: 新 Run 必须挂在同一个 Goal 下 (setGoalId), 并带上上一个 Run 的非幂等守卫
1680
1682
  agent.setGoalId?.(goal.goalId);
1681
1683
  agent.setContinuationGuards?.(r.guards || []);
1682
- const reply = await agent.prompt(r.instruction);
1684
+ const reply = await deliverThroughActor(agent, () => agent.prompt(r.instruction));
1683
1685
  // 注意: prompt 收尾会清空 currentRunId → 必须读 lastRunId (否则会拿上一条 run 做决策)
1684
1686
  const runId = agent.getLastRunId?.() || agent.getRunId?.();
1685
1687
  return { runId, status: 'done', reply: typeof reply === 'string' ? reply.slice(0, 500) : undefined };
@@ -2489,7 +2491,7 @@ export async function createWebServer(port = 3000, options = {}) {
2489
2491
  new Promise((res) => setTimeout(() => res(null), 8000)),
2490
2492
  ]);
2491
2493
  if (agent && typeof agent.promptStream === 'function') {
2492
- llm = (p) => agent.promptStream(p, () => { }, undefined, local.id);
2494
+ llm = (p) => deliverThroughActor(agent, () => agent.promptStream(p, () => { }, undefined, local.id));
2493
2495
  }
2494
2496
  }
2495
2497
  }
@@ -2541,7 +2543,7 @@ export async function createWebServer(port = 3000, options = {}) {
2541
2543
  throw new Error('无可用 agent, 跳过定时任务');
2542
2544
  }
2543
2545
  // 前缀 [cron] 标记后台执行来源 (供审计/日志区分人类消息与定时任务)
2544
- await agent.promptStream(`[cron] ${job.name}: ${job.prompt}`, () => { }, undefined, target.id);
2546
+ await deliverThroughActor(agent, () => agent.promptStream(`[cron] ${job.name}: ${job.prompt}`, () => { }, undefined, target.id));
2545
2547
  },
2546
2548
  });
2547
2549
  global.cronScheduler = cronHandle;
@@ -2593,7 +2595,7 @@ ${goalDesc}
2593
2595
  现在是否要主动联系其中某个智能体? 只输出一个 JSON 对象, 不要任何其他文字:
2594
2596
  {"initiate": true 或 false, "goalAchieved": true 或 false, "targetPeerPublicKey": "对方 pk", "targetChannelId": "对方渠道 id", "message": "你要说的话"}
2595
2597
  若不想发起, 输出 {"initiate": false}。`;
2596
- const raw = await agent.promptStream(prompt, () => { }, undefined, local.id);
2598
+ const raw = await deliverThroughActor(agent, () => agent.promptStream(prompt, () => { }, undefined, local.id));
2597
2599
  const m = raw.match(/\{[\s\S]*\}/);
2598
2600
  if (!m)
2599
2601
  return { initiate: false };
@@ -3406,7 +3408,16 @@ fetchState();
3406
3408
  if (!woke) {
3407
3409
  // 没在等外部事件也要如实回答 (可能它其实在等人/在跑), 但允许显式加急
3408
3410
  if (req.body?.force) {
3409
- await setContinuation(goalId, { wakeReason: 'active', autoContinue: true, wakeAt: undefined, needsExternal: undefined });
3411
+ // **K4**: channel 不直接写 Goal —— 提交控制请求, 由内核控制面执行
3412
+ const { submitRunControl } = await import('../kernel/control.js');
3413
+ const outcome = await submitRunControl({
3414
+ kind: 'wake-goal', origin: 'web', goalId, reason: 'force 加急唤醒',
3415
+ payload: { wakeReason: 'active', autoContinue: true, wakeAt: undefined, needsExternal: undefined },
3416
+ }, { setContinuation });
3417
+ if (!outcome.ok) {
3418
+ res.status(500).json({ error: `控制面拒绝: ${outcome.detail}` });
3419
+ return;
3420
+ }
3410
3421
  res.json({ ok: true, goalId, woke: false, forced: true, note: `原状态 ${g.status} (不在等外部事件), 已按 force 加急` });
3411
3422
  return;
3412
3423
  }
@@ -3467,12 +3478,17 @@ fetchState();
3467
3478
  let boundary = view.runBoundary;
3468
3479
  if (boundary.action === 'stop_running_run' && !boundary.stopped) {
3469
3480
  const { setRunStatus } = await import('../agents/run-store.js');
3481
+ const { submitRunControl } = await import('../kernel/control.js');
3470
3482
  boundary = await seam.applyRunBoundary({
3471
3483
  plan: view.plan,
3472
3484
  now,
3473
3485
  stop: async (i) => {
3474
- const r = await setRunStatus(i.runId, i.runStatus, { error: `变更注入 (${i.goalId}): ${String(i.reason).slice(0, 120)}` });
3475
- return { ok: !!r.ok, reason: r.reason || '' };
3486
+ // **K4**: 提交控制请求 (端口返回值里的"拒绝"会被控制面归一化成 ok=false + detail)
3487
+ const outcome = await submitRunControl({
3488
+ kind: 'set-run-status', origin: 'web', runId: i.runId, reason: `变更注入 (${i.goalId})`,
3489
+ payload: { status: i.runStatus, error: `变更注入 (${i.goalId}): ${String(i.reason).slice(0, 120)}` },
3490
+ }, { setRunStatus });
3491
+ return { ok: outcome.ok, reason: outcome.ok ? '' : String(outcome.detail ?? '') };
3476
3492
  },
3477
3493
  });
3478
3494
  }
@@ -3606,7 +3622,19 @@ fetchState();
3606
3622
  res.status(409).json({ error: `只有 needs_human 的运行需要批准 (当前 ${run.status})` });
3607
3623
  return;
3608
3624
  }
3609
- await recordRecovery(runId, { errorClass: run.errorClass || 'unknown', message: '人工批准后继续', action: 'resume' });
3625
+ // **K4**: channel 不直接写 Run —— 提交控制请求, 由内核控制面执行 (这里只做 ports wiring)
3626
+ const { submitRunControl } = await import('../kernel/control.js');
3627
+ const outcome = await submitRunControl({
3628
+ kind: 'record-recovery',
3629
+ origin: 'web',
3630
+ runId,
3631
+ reason: '人工批准后继续',
3632
+ payload: { errorClass: run.errorClass || 'unknown', message: '人工批准后继续', action: 'resume' },
3633
+ }, { recordRecovery });
3634
+ if (!outcome.ok) {
3635
+ res.status(500).json({ error: `控制面拒绝: ${outcome.detail}` });
3636
+ return;
3637
+ }
3610
3638
  if (!run.channelId) {
3611
3639
  res.status(400).json({ error: '该 run 没有 channelId, 请在 CLI 用 /approve' });
3612
3640
  return;
@@ -3630,9 +3658,11 @@ fetchState();
3630
3658
  const runId = String(req.params.runId);
3631
3659
  try {
3632
3660
  const { setRunStatus } = await import('../agents/run-store.js');
3633
- const r = await setRunStatus(runId, to, { error: `外部请求 (${suffix})` });
3634
- if (!r.ok) {
3635
- res.status(409).json({ error: r.reason || '状态迁移被拒绝' });
3661
+ const { submitRunControl } = await import('../kernel/control.js');
3662
+ const outcome = await submitRunControl({ kind: 'set-run-status', origin: 'web', runId, reason: `外部请求 (${suffix})`, payload: { status: to, error: `外部请求 (${suffix})` } }, { setRunStatus });
3663
+ // 语义不变: 端口/store 拒绝 ⇒ 409 (原因由控制面归一化进 detail)
3664
+ if (!outcome.ok) {
3665
+ res.status(409).json({ error: String(outcome.detail ?? '状态迁移被拒绝').replace(/^端口拒绝: /, '') });
3636
3666
  return;
3637
3667
  }
3638
3668
  res.json({ ok: true, runId, status: to, note: '运行中的 agent 会在下一轮循环检查时停下 (轮内不打断)' });
@@ -3911,7 +3941,7 @@ fetchState();
3911
3941
  req.docContent ? `\n资料内容:\n${req.docContent}` : '',
3912
3942
  `\n(来自 agent ${req.fromAgentId || 'unknown'}),请直接给出可交付结果。`,
3913
3943
  ].join('');
3914
- const out = await agent.prompt(task);
3944
+ const out = await deliverThroughActor(agent, () => agent.prompt(task));
3915
3945
  const text = String(out || '').trim();
3916
3946
  if (!text || text.startsWith('❌') || text.startsWith('[AI 服务调用失败]')) {
3917
3947
  return { ok: false, summary: text.slice(0, 800) || '(空结果)', error: 'execution-failed' };
@@ -5361,7 +5391,16 @@ fetchState();
5361
5391
  }
5362
5392
  // 2026-07-15 修 Bug 3: 拖拽附件 — attachmentContext 提到 contextHint 最前, LLM 第一眼看到文件清单
5363
5393
  const markedPrompt = `${extraHint}【本轮用户请求】\n${text}\n【请求结束】\n\n${attachmentContext}${contextHint}`;
5364
- fullResponse = await agent.promptStream(markedPrompt, streamCallback, runState.abortController?.signal, channelId);
5394
+ // 闭包里 TS 不再保留 null 收窄 ⇒ 先收成局部 const
5395
+ const agentForRun = agent;
5396
+ // **K5 步骤⑦**: 入口只交一个一次性 `ExecutionRequest` (绑定/流/取消都在请求里), Pi 侧 runExecution 统一派发
5397
+ const request = {
5398
+ input: markedPrompt,
5399
+ channelId,
5400
+ signal: runState.abortController?.signal,
5401
+ onStream: streamCallback,
5402
+ };
5403
+ fullResponse = await deliverThroughActor(agentForRun, () => agentForRun.runExecution(request));
5365
5404
  }
5366
5405
  catch (err) {
5367
5406
  // abort 抛错: 保留已输出的部分 (fullResponse 可能是空字符串)
@@ -5732,7 +5771,8 @@ fetchState();
5732
5771
  const contextHint = attachmentContext + `[系统上下文] 队列消息 (auto-drain)\n`;
5733
5772
  // 4) promptStream
5734
5773
  const markedPrompt = `【本轮用户请求】\n${text}\n【请求结束】\n\n${contextHint}`;
5735
- const fullResponse = await agent.promptStream(markedPrompt, () => { }, runState.abortController?.signal, channelId);
5774
+ const agentForRun = agent;
5775
+ const fullResponse = await deliverThroughActor(agentForRun, () => agentForRun.promptStream(markedPrompt, () => { }, runState.abortController?.signal, channelId));
5736
5776
  if (!fullResponse.trim()) {
5737
5777
  broadcast({ type: 'error', content: '⚠️ AI 未返回内容' }, channelId);
5738
5778
  }
@@ -6934,7 +6974,7 @@ fetchState();
6934
6974
  // 2026-06-15: 同 /message 路径, 用显式 marker 包裹 userMessage, 避免 LLM 把它当背景信息
6935
6975
  const regenHint = await buildJudgmentHint(channel, channelId);
6936
6976
  const markedRegen = `${regenHint}\n\n【本轮用户请求】\n${userMessage}\n【请求结束】\n`;
6937
- fullResponse = await agent.promptStream(markedRegen, streamCallback, undefined, channelId);
6977
+ fullResponse = await deliverThroughActor(agent, () => agent.promptStream(markedRegen, streamCallback, undefined, channelId));
6938
6978
  // 2026-07-06: 防御性兜底 — 同 /message 路径
6939
6979
  if (!fullResponse.trim()) {
6940
6980
  fullResponse = '⚠️ AI 未返回内容, 请重试';
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.5';
9
+ const CACHE = 'bolloon-mobile-v0.6.0';
10
10
  const SHELL = [
11
11
  './mobile.html',
12
12
  './mobile.css',