chainlesschain 0.162.176 → 0.162.178
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/README.md +10 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BDLu5Elz.js → AIOps-DRftcSue.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DH5us-CK.js → ActionButton-BFvUaMKR.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BZ0u8IFG.js → Analytics-C0-Rru4P.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-bx-BCljj.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-Br2YBbh_.js → Artifacts-DAJ8B3Un.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C3C6a482.js → Audit-hOk4L1lr.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CzHvebcj.js → BackgroundAgents-3pbDpM9z.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DZNHYDFd.js → Backup-BtziGDn9.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-VRiC4fIx.js → BaseInput-kmshphJ3.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-Cm08WWAD.js → Chat-d7tGSosA.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CGHYrugQ.js → ChatBubbleRenderer-p-_PBpX_.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DtByk7d7.js → Checkbox-C4Eh4Tz5.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CphXXOfD.js → Codegen-r7gmhZyA.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Hz86TnLR.js → Col-U7mDaGlL.js} +1 -1
- package/src/assets/web-panel/assets/{Community-HP03ltpD.js → Community-Bpu8aH1T.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-B_N1mqQz.js → Compact-CHb2XBJe.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CVztRpi8.js → Compliance-Cn_r4dey.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-wUVOyZih.js → Cowork-CdMWfDcz.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DW5TLJKw.js → Cron-BtnREHWy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CrAFGhWH.js → Crosschain-BKI9TSzr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-pA-oD8ke.js → DID-pkNubzzJ.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-1rrz1snN.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-EweJcsek.js → Dropdown-DLyFVxDc.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C9xVLPG4.js → EmailListRenderer-CtUWfYVq.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CDcEEqlu.js → FamilyGuardDashboard-B8eX2Qe4.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DtZda9A_.js → Federation-D8lsDGus.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CiYdcVz3.js → FormItemContext-CRYt_aIw.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DA13uwA0.js → GenericCardRenderer-ClKzY8_N.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DzRhZD1O.js → Git-BXj5Dney.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-D5RMgOSb.js → Governance-Cm-I8RMz.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BgrPfSNk.js → Inference-CPvbhvgt.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DzjnD571.js → KnowledgeGraph-sYNDZaoi.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BhWzVDtN.js → Logs-BZY_3CRZ.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BDape9cx.js → MarkdownRenderer-up0BW6pv.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DJtL5GV7.js → Marketplace-C5MEJ2Qe.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CZcQygI7.js → McpTools-ihdrn43I.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-DUWSDUUu.js → Memory-Br8bPMlh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BTwq2WKY.js → MobileBridge-BNntgrYW.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BdV915mw.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-BiGugEQm.js → Mtc-A3wDmlqL.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-DY7a6gUe.js → MtcAudit-CF-mBLWM.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BQbDu_w7.js → Multisig-Iy2k_MSo.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CM2wXTLv.js → NLProgramming-kk0W7HUb.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DI6gGs1v.js → Notes-B5u5t_4S.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BsZOLWAB.js → NotificationSettings-BN0POf6_.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CHkSUrXB.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Cds0_tXr.js → Organization-DwWQESuN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-WunYMD87.js → Overflow-DG6klrcC.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Bo6j4DDv.js → P2P-BwJcKkgZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Bh2XPD5f.js → PdhVaultBrowser-BwOHG0in.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-EMvMMC8N.js → Permissions-CGMXe4TX.js} +4 -4
- package/src/assets/web-panel/assets/PersonalDataHub-ziYqg7-A.js +8 -0
- package/src/assets/web-panel/assets/{Pipeline-BOx8HOgL.js → Pipeline-BzJfeoGt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-tBeTVQVM.js → Privacy-DLh3Bblx.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CVYg1W4M.js → ProjectInit-USVWW36c.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Dvt5I7y1.js → ProjectSettings-CiiOn62h.js} +2 -2
- package/src/assets/web-panel/assets/Projects-6V-PNmcA.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Ct8xqY-E.js → Providers-CBPWWzpu.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Cni8Ooja.js → QrScannerModal-QVwoRUq3.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BJVLKdxr.js → QuickAsk-CXnR-2Vn.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DPG8Rbbm.js → Recommend-ClaNzjmF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DsdR7dCt.js → RemoteSession-C3rGw8vJ.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-Csg1YM-b.js → Reputation-Ci-OWAoP.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D9DoFoEf.js → Row-DRhAwXOS.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BsvKrXMS.js → RssFeed-BQLJQ2_y.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFUStfgQ.js → Search-QQUpkfFd.js} +1 -1
- package/src/assets/web-panel/assets/{Security-ILg1zxdK.js → Security-DdXKzuKT.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Dd41PCaY.js → Services-x2Zh62Qd.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Bzo1cN80.js → Skeleton-GdY4KwRz.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BDHh17P0.js → Skills-Bv4tY1Fd.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jl7UTiRY.js → Sla-C3QnM-11.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BePa-RF6.js → SpeechSettings-Bl3ytvmI.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DiqqDKGZ.js → SyncSettings-Wp9IwTsP.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DYQ_6lxj.js → Tasks-CF3rIrDe.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-JiDeI06L.js → Templates-CGfvVVM9.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-hhgI6zwS.js → Tenant-CVXmwQ3U.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-bvwrt03E.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-B8uB5Llk.js → TimelineRenderer-D0g74KhH.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-C3b_6r2z.js → Tokens-BH4IwzlT.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-tIP7HKVe.js → Trigger-DJOpM533.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-vjoc11vJ.js → Trust-B43EPRLr.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DUPBnGuH.js → UkeySign-BmBFG-em.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CBvhUY5T.js → VideoEditing-n9oJwB8k.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DUaQ0uA5.js → Wallet-D5QeivHp.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DllSivjE.js → WebAuthn-DcNy7igO.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-xc8D3uO6.js → WorkflowEditor-BVjc7-5-.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BVicU7oA.js → chat-Dy5Tfj3m.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DJzLmhLm.js → colors-C4c2CNZU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BvYRfThE.js → compact-item-DPa3O5vN.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DGXxCBKR.js → createContext-TLcfNA6_.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BAwdDA_5.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-SBDJB1y4.js → hasIn-D41LVFkp.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7HimK0M.js → index-0oevYjfT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCdRAgjy.js → index-388pLGJ1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BO1itZaY.js → index-B8nLBZbv.js} +3 -3
- package/src/assets/web-panel/assets/{index-DvUTDYXX.js → index-BPTGAjee.js} +1 -1
- package/src/assets/web-panel/assets/{index-hxTODbM1.js → index-BPtrOBmW.js} +1 -1
- package/src/assets/web-panel/assets/{index-wcCL-miV.js → index-BQiIxHBy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CKyEivf8.js → index-BSM1cHVK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJZf9DhV.js → index-BYPr9fkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHVLJ8q0.js → index-BsQ7Ev6i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs2rmLFt.js → index-Btk9qLL2.js} +1 -1
- package/src/assets/web-panel/assets/{index-z1ZylsLq.js → index-BvmziZSG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf-O_g_8.js → index-BvopLC_T.js} +1 -1
- package/src/assets/web-panel/assets/{index-DMarmfrv.js → index-C7xhTVyP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoJAO1Lm.js → index-CNk_ZooP.js} +1 -1
- package/src/assets/web-panel/assets/{index-9gdI7uUW.js → index-CQrEHoOG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf-ctERC.js → index-CSxex23J.js} +1 -1
- package/src/assets/web-panel/assets/{index-MjC4G09d.js → index-CVjgm992.js} +1 -1
- package/src/assets/web-panel/assets/{index-e4fXH_WO.js → index-CWK4zOPe.js} +1 -1
- package/src/assets/web-panel/assets/{index-xfluRkCT.js → index-CX0VsoP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRfiXB_p.js → index-CXl0YPNG.js} +1 -1
- package/src/assets/web-panel/assets/{index-d5BVd-cL.js → index-Cip7LWml.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dm_77jgR.js → index-Cq_hlWNt.js} +1 -1
- package/src/assets/web-panel/assets/{index-YJkzy8ZF.js → index-CzZ49YZL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtwqO5qo.js → index-D2Nkivlm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYqz4Wrr.js → index-DBUgRs4D.js} +1 -1
- package/src/assets/web-panel/assets/index-DEjVkdzq.js +1 -0
- package/src/assets/web-panel/assets/{index-CdGY9P8a.js → index-DNsBj2Ob.js} +1 -1
- package/src/assets/web-panel/assets/{index-DonCnfMr.js → index-Di4X8cfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-1SdDS6lR.js → index-DljFsVGI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnjPdvR6.js → index-Korc3QIe.js} +1 -1
- package/src/assets/web-panel/assets/index-LMOc5xrS.js +1 -0
- package/src/assets/web-panel/assets/{index-VMfwIH5G.js → index-MKZDje0H.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKrvvWm4.js → index-OHAfRu_3.js} +1 -1
- package/src/assets/web-panel/assets/{index-FxZzRyE1.js → index-WEJr8PL5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Crk5NTb0.js → index-WinCp6du.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCqRS6da.js → index-Yjr6cqSK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTrBGBJs.js → index-iQ6gtFih.js} +1 -1
- package/src/assets/web-panel/assets/{index-lpaGoTH3.js → index-pt3s7yvV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CloCgBUR.js → index-tQ3igERQ.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C1zO1KnY.js → initDefaultProps-BFZu87WZ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CWLtEGmC.js → motion-DJIo7qvt.js} +1 -1
- package/src/assets/web-panel/assets/{move-DzD_C3Vm.js → move-Cfr5qknL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-D880PYJl.js → mtc-parser-Bgc-OadH.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CFR_z2ov.js → omit-X3WI-TNp.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-srIhgrSC.js → pickAttrs-pJhU9IxK.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C1rXpibP.js → placementArrow-BNg_Vj3T.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C30gRcSS.js → responsiveObserve-TeSEGQ5-.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CvtKiMfV.js → slide-D_t_P0bv.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DNHO7ITG.js → statusUtils-DrrIMwAT.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Dt_Sl-g4.js → styleChecker-BjZCuFRm.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Cjev42Gh.js → useFlexGapSupport-rTFdlqdQ.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Baxglj2V.js → useFs-BidCpfLX.js} +1 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-C5mHttA9.js +1 -0
- package/src/assets/web-panel/assets/{vnode-mIRkdT7o.js → vnode-BrbcRiHZ.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-HzI5DlH_.js → zoom-PISX7AkR.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/__tests__/hub-wechat.test.js +45 -0
- package/src/commands/agenda.js +22 -6
- package/src/commands/agent.js +3 -3
- package/src/commands/background-session.js +16 -6
- package/src/commands/batch.js +79 -27
- package/src/commands/changelog.js +15 -4
- package/src/commands/context.js +33 -1
- package/src/commands/eval.js +21 -6
- package/src/commands/hook.js +2 -2
- package/src/commands/hub.js +473 -39
- package/src/commands/init.js +212 -110
- package/src/commands/llm.js +22 -6
- package/src/commands/loop.js +9 -2
- package/src/commands/skill.js +13 -1
- package/src/commands/statusline.js +3 -3
- package/src/data/changelog.json +53 -5
- package/src/gateways/ws/personal-data-hub-protocol.js +22 -2
- package/src/harness/background-task-manager.js +18 -6
- package/src/harness/background-task-worker.js +11 -18
- package/src/harness/golden-transcript.js +3 -0
- package/src/harness/mcp-client.js +9 -15
- package/src/harness/worktree-isolator.js +18 -21
- package/src/index.js +18 -7
- package/src/lib/agent-core.js +5 -0
- package/src/lib/agent-ipc-bus.js +12 -3
- package/src/lib/agent-team/team-worktree.js +28 -6
- package/src/lib/agent-worktree.js +20 -19
- package/src/lib/approval-authority-store.js +891 -0
- package/src/lib/async-hook-supervisor.cjs +134 -24
- package/src/lib/async-hook-supervisor.js +47 -0
- package/src/lib/background-agent-supervisor.js +35 -12
- package/src/lib/background-interaction-resolver.js +399 -54
- package/src/lib/background-session-transport.js +3 -1
- package/src/lib/background-task-manager.js +5 -1
- package/src/lib/changelog.js +57 -0
- package/src/lib/chrome-connector.js +6 -2
- package/src/lib/claude-code-bridge.js +24 -8
- package/src/lib/cli-anything-bridge.js +82 -25
- package/src/lib/context-breakdown.js +82 -3
- package/src/lib/doctor-checkup.js +18 -6
- package/src/lib/eval/tasks.js +25 -31
- package/src/lib/event-runtime-host.js +225 -0
- package/src/lib/event-runtime-store.js +102 -21
- package/src/lib/event-runtime-worker.js +70 -2
- package/src/lib/hook-runner.cjs +71 -36
- package/src/lib/hook-runner.js +55 -0
- package/src/lib/hooks-v2-producers.js +33 -8
- package/src/lib/hooks-v2-runtime.js +360 -40
- package/src/lib/host-adb-bridge.js +18 -3
- package/src/lib/interaction-adapter.js +66 -0
- package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
- package/src/lib/lsp/benchmark.js +20 -4
- package/src/lib/lsp/lsp-client.js +6 -4
- package/src/lib/lsp/lsp-server-registry.js +0 -2
- package/src/lib/operation-fingerprint.js +107 -2
- package/src/lib/orchestrator.js +8 -2
- package/src/lib/packer/pack-update-applier.js +14 -2
- package/src/lib/packer/smoke-runner.js +18 -5
- package/src/lib/paths.js +1 -1
- package/src/lib/pdh-dedicated-batch-collectors.js +124 -0
- package/src/lib/personal-data-hub-wiring.js +327 -52
- package/src/lib/plugin-monitor-supervisor.js +20 -13
- package/src/lib/plugin-runtime/install.js +10 -3
- package/src/lib/process-execution-broker/credential-agent.js +954 -111
- package/src/lib/process-execution-broker/index.js +369 -85
- package/src/lib/process-execution-broker/platform-sandbox.js +320 -140
- package/src/lib/provider-http-error.js +94 -0
- package/src/lib/remote-approval-bridge.js +222 -26
- package/src/lib/repl-bang-memorize.js +10 -2
- package/src/lib/repl-goal.js +19 -2
- package/src/lib/settings-hook-events.cjs +13 -8
- package/src/lib/settings-hook-events.js +20 -0
- package/src/lib/side-effect-ledger-store.js +65 -14
- package/src/lib/skill-loader.js +215 -12
- package/src/lib/skill-packs/generator.js +18 -9
- package/src/lib/skill-process-broker.js +85 -0
- package/src/lib/slash-commands.js +10 -2
- package/src/lib/status-line.cjs +28 -7
- package/src/lib/status-line.js +33 -0
- package/src/lib/sub-agent-context.js +42 -0
- package/src/lib/turn-binding-store.js +64 -15
- package/src/lib/turn-binding.js +85 -16
- package/src/repl/agent-repl.js +88 -49
- package/src/repl/remote-approval.js +13 -13
- package/src/repl/repl-turn-binding.js +46 -16
- package/src/runtime/agent-core.js +419 -84
- package/src/runtime/coding-agent-contract-shared.cjs +16 -0
- package/src/runtime/headless-runner.js +172 -44
- package/src/runtime/headless-stream.js +221 -11
- package/src/runtime/session-slash-commands.js +506 -0
- package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
- package/src/skills/video-editing/extractors/video-extractor.js +13 -3
- package/src/skills/video-editing/media-process.js +20 -0
- package/src/skills/video-editing/render/audio-mix.js +13 -3
- package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
- package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
- package/src/workers/background-agent-worker.js +76 -40
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +0 -9
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-C48mu09U.js +0 -1
- package/src/assets/web-panel/assets/PersonalDataHub-AX3ypUDV.js +0 -9
- package/src/assets/web-panel/assets/Projects-Cc7FC9-e.js +0 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +0 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +0 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +0 -1
- package/src/assets/web-panel/assets/usePersonalDataHub-B4NkcLaP.js +0 -1
package/src/repl/agent-repl.js
CHANGED
|
@@ -183,12 +183,12 @@ function persistRecentDenial(record, options = {}) {
|
|
|
183
183
|
* user's attention (e.g. waiting on a permission/risk confirmation). A hook can
|
|
184
184
|
* ring a bell / send a desktop notification. Best-effort, never blocks.
|
|
185
185
|
*/
|
|
186
|
-
async function _fireNotification(message, type = "info") {
|
|
186
|
+
async function _fireNotification(message, type = "info", session = null) {
|
|
187
187
|
// Fire settings.json observe hooks first (best-effort)
|
|
188
188
|
if (_settingsHooks) {
|
|
189
189
|
try {
|
|
190
190
|
const { runObserveHooks } =
|
|
191
|
-
await import("../lib/settings-hook-events.
|
|
191
|
+
await import("../lib/settings-hook-events.js");
|
|
192
192
|
runObserveHooks(
|
|
193
193
|
_settingsHooks,
|
|
194
194
|
"Notification",
|
|
@@ -196,7 +196,7 @@ async function _fireNotification(message, type = "info") {
|
|
|
196
196
|
message,
|
|
197
197
|
type,
|
|
198
198
|
cwd: process.cwd(),
|
|
199
|
-
session_id:
|
|
199
|
+
session_id: session?.sessionId || null,
|
|
200
200
|
},
|
|
201
201
|
{ cwd: process.cwd() },
|
|
202
202
|
);
|
|
@@ -205,10 +205,10 @@ async function _fireNotification(message, type = "info") {
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
// Fire database-registered Notification hooks (interceptable/suppressible)
|
|
208
|
-
if (
|
|
208
|
+
if (session) {
|
|
209
209
|
try {
|
|
210
210
|
const result = await fireNotification(_hookDb, message, {
|
|
211
|
-
session
|
|
211
|
+
session,
|
|
212
212
|
type,
|
|
213
213
|
});
|
|
214
214
|
if (result?.directive?.suppress) {
|
|
@@ -750,6 +750,8 @@ export async function startAgentRepl(options = {}) {
|
|
|
750
750
|
}
|
|
751
751
|
await _fireNotification(
|
|
752
752
|
`Permission needed: ${riskLevel || "medium"}-risk ${tool || "run_shell"}${args?.command ? " — " + args.command : ""}`,
|
|
753
|
+
"info",
|
|
754
|
+
_sessionHandle,
|
|
753
755
|
);
|
|
754
756
|
const local = askGateApprovalLocally({ tool, args, riskLevel });
|
|
755
757
|
if (!_remoteApproval?.bridge) return local.promise;
|
|
@@ -840,6 +842,8 @@ export async function startAgentRepl(options = {}) {
|
|
|
840
842
|
}
|
|
841
843
|
await _fireNotification(
|
|
842
844
|
`Permission needed: ${tool}${rule ? " (" + rule + ")" : ""}`,
|
|
845
|
+
"info",
|
|
846
|
+
_sessionHandle,
|
|
843
847
|
);
|
|
844
848
|
const local = askPermissionLocally({ tool, args, rule, reason });
|
|
845
849
|
if (!_remoteApproval?.bridge) return local.promise;
|
|
@@ -1119,8 +1123,10 @@ export async function startAgentRepl(options = {}) {
|
|
|
1119
1123
|
// P1 explicit turn→checkpoint binding — the REPL as PRODUCER (mirrors the
|
|
1120
1124
|
// headless runner's feed via the shared feeder core): one record per
|
|
1121
1125
|
// interactive turn, persisted dirty-gated at each settle. Lazily created on
|
|
1122
|
-
// the first prompt turn of a persistable (JSONL) session
|
|
1126
|
+
// the first prompt turn of a persistable (JSONL) session. This is Critical
|
|
1127
|
+
// recovery state: a failure blocks subsequent model/tool turns.
|
|
1123
1128
|
let _turnBindingProducer = null;
|
|
1129
|
+
let _turnBindingCriticalError = null;
|
|
1124
1130
|
// Apply --output-style or the settings.json `outputStyle` default at startup.
|
|
1125
1131
|
try {
|
|
1126
1132
|
const { resolveOutputStyle } = await import("../lib/output-styles.js");
|
|
@@ -1142,7 +1148,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
1142
1148
|
if (_settingsHooks && _loadedReplInstructions) {
|
|
1143
1149
|
try {
|
|
1144
1150
|
const { runInstructionsLoadedHooks } =
|
|
1145
|
-
await import("../lib/settings-hook-events.
|
|
1151
|
+
await import("../lib/settings-hook-events.js");
|
|
1146
1152
|
const ctx = runInstructionsLoadedHooks(_settingsHooks, {
|
|
1147
1153
|
files: _loadedReplInstructions.files,
|
|
1148
1154
|
cwd: process.cwd(),
|
|
@@ -1158,7 +1164,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
1158
1164
|
if (_settingsHooks) {
|
|
1159
1165
|
try {
|
|
1160
1166
|
const { runSessionStartHooks } =
|
|
1161
|
-
await import("../lib/settings-hook-events.
|
|
1167
|
+
await import("../lib/settings-hook-events.js");
|
|
1162
1168
|
const ctx = runSessionStartHooks(_settingsHooks, {
|
|
1163
1169
|
source: "startup",
|
|
1164
1170
|
cwd: process.cwd(),
|
|
@@ -1466,7 +1472,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
1466
1472
|
if (_settingsHooks && messages.some((m) => m.role !== "system")) {
|
|
1467
1473
|
try {
|
|
1468
1474
|
const { runObserveHooks } =
|
|
1469
|
-
await import("../lib/settings-hook-events.
|
|
1475
|
+
await import("../lib/settings-hook-events.js");
|
|
1470
1476
|
runObserveHooks(
|
|
1471
1477
|
_settingsHooks,
|
|
1472
1478
|
"SessionResume",
|
|
@@ -1764,31 +1770,34 @@ export async function startAgentRepl(options = {}) {
|
|
|
1764
1770
|
|
|
1765
1771
|
// MCP elicitation in the interactive REPL uses the same readline surface as
|
|
1766
1772
|
// approvals, while MCPClient retains the protocol-level response shape.
|
|
1767
|
-
const mcpElicitationClients = [
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
].filter((client) => client?.setElicitationHandler);
|
|
1773
|
+
const mcpElicitationClients = [_adhocMcp?.mcpClient, _bundleMcpClient].filter(
|
|
1774
|
+
(client) => client?.setElicitationHandler,
|
|
1775
|
+
);
|
|
1771
1776
|
for (const client of mcpElicitationClients) {
|
|
1772
1777
|
client.setElicitationHandler(
|
|
1773
1778
|
(request) =>
|
|
1774
1779
|
new Promise((resolve) => {
|
|
1775
|
-
const label =
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1780
|
+
const label =
|
|
1781
|
+
request.message || "MCP server requests additional input";
|
|
1782
|
+
rl.question(
|
|
1783
|
+
chalk.yellow(`\n MCP [${request.server}] ${label}\n > `),
|
|
1784
|
+
(answer) => {
|
|
1785
|
+
const trimmed = String(answer || "").trim();
|
|
1786
|
+
if (!trimmed) {
|
|
1787
|
+
resolve({ action: "cancel" });
|
|
1788
|
+
} else {
|
|
1789
|
+
let content = { value: trimmed };
|
|
1790
|
+
try {
|
|
1791
|
+
const parsed = JSON.parse(trimmed);
|
|
1792
|
+
if (parsed && typeof parsed === "object") content = parsed;
|
|
1793
|
+
} catch {
|
|
1794
|
+
// Plain text remains a valid single-field elicitation answer.
|
|
1795
|
+
}
|
|
1796
|
+
resolve({ action: "accept", content });
|
|
1787
1797
|
}
|
|
1788
|
-
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
|
-
});
|
|
1798
|
+
rl.prompt();
|
|
1799
|
+
},
|
|
1800
|
+
);
|
|
1792
1801
|
}),
|
|
1793
1802
|
{ timeoutMs: options.mcpElicitationTimeoutMs },
|
|
1794
1803
|
);
|
|
@@ -1896,7 +1905,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
1896
1905
|
// turn — the session stays open, the current work is suspended. The
|
|
1897
1906
|
// keypress handler can't await, so fire observe-only fire-and-forget.
|
|
1898
1907
|
if (_settingsHooks) {
|
|
1899
|
-
import("../lib/settings-hook-events.
|
|
1908
|
+
import("../lib/settings-hook-events.js")
|
|
1900
1909
|
.then(({ runObserveHooks }) =>
|
|
1901
1910
|
runObserveHooks(
|
|
1902
1911
|
_settingsHooks,
|
|
@@ -2058,7 +2067,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
2058
2067
|
const _costStore = newCostStore(); // running token spend for `/cost`
|
|
2059
2068
|
let _renderStatus = null;
|
|
2060
2069
|
try {
|
|
2061
|
-
const slm = await import("../lib/status-line.
|
|
2070
|
+
const slm = await import("../lib/status-line.js");
|
|
2062
2071
|
const _sl = slm.default || slm;
|
|
2063
2072
|
const _slCfg = _sl.loadStatusLineConfig({ cwd: process.cwd() });
|
|
2064
2073
|
_customStatus = !!_slCfg;
|
|
@@ -3153,12 +3162,12 @@ export async function startAgentRepl(options = {}) {
|
|
|
3153
3162
|
if (_settingsHooks && oldCwd !== newCwd) {
|
|
3154
3163
|
try {
|
|
3155
3164
|
const { runCwdChangedHooks, dispatchAsyncHooks } =
|
|
3156
|
-
await import("../lib/settings-hook-events.
|
|
3165
|
+
await import("../lib/settings-hook-events.js");
|
|
3157
3166
|
const payload = { oldCwd, newCwd, sessionId };
|
|
3158
3167
|
runCwdChangedHooks(_settingsHooks, payload);
|
|
3159
3168
|
if (!_asyncHookSupervisor) {
|
|
3160
3169
|
const { AsyncHookSupervisor } =
|
|
3161
|
-
await import("../lib/async-hook-supervisor.
|
|
3170
|
+
await import("../lib/async-hook-supervisor.js");
|
|
3162
3171
|
_asyncHookSupervisor = new AsyncHookSupervisor({
|
|
3163
3172
|
persistStats: true,
|
|
3164
3173
|
});
|
|
@@ -3643,6 +3652,11 @@ export async function startAgentRepl(options = {}) {
|
|
|
3643
3652
|
_sanitizeRolesNextTurn =
|
|
3644
3653
|
messages[messages.length - 1]?.role === "user";
|
|
3645
3654
|
sessionId = resumeId;
|
|
3655
|
+
// The producer owns one immutable session id. Recreate it lazily
|
|
3656
|
+
// on the next turn so bindings from the resumed conversation can
|
|
3657
|
+
// never be appended to the previously active session.
|
|
3658
|
+
_turnBindingProducer = null;
|
|
3659
|
+
_turnBindingCriticalError = null;
|
|
3646
3660
|
// The prior session's checkpoint marks (turn-index → checkpoint id)
|
|
3647
3661
|
// no longer map to this swapped-in history; keeping them would make
|
|
3648
3662
|
// a later /rewind restore files from the WRONG session's snapshot.
|
|
@@ -3664,6 +3678,8 @@ export async function startAgentRepl(options = {}) {
|
|
|
3664
3678
|
_sanitizeRolesNextTurn =
|
|
3665
3679
|
messages[messages.length - 1]?.role === "user";
|
|
3666
3680
|
sessionId = existing.id;
|
|
3681
|
+
_turnBindingProducer = null;
|
|
3682
|
+
_turnBindingCriticalError = null;
|
|
3667
3683
|
// Drop the prior session's checkpoint marks (see JSONL branch).
|
|
3668
3684
|
_checkpointMarks.length = 0;
|
|
3669
3685
|
_clearedConversation = null; // stash belongs to the swapped-out session
|
|
@@ -3739,7 +3755,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
3739
3755
|
if (_settingsHooks) {
|
|
3740
3756
|
try {
|
|
3741
3757
|
const { runObserveHooks, dispatchAsyncHooks } =
|
|
3742
|
-
await import("../lib/settings-hook-events.
|
|
3758
|
+
await import("../lib/settings-hook-events.js");
|
|
3743
3759
|
const payload = {
|
|
3744
3760
|
session_id: sessionId || null,
|
|
3745
3761
|
source: "reload-plugins",
|
|
@@ -3747,7 +3763,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
3747
3763
|
runObserveHooks(_settingsHooks, "ConfigChange", payload, { cwd });
|
|
3748
3764
|
if (!_asyncHookSupervisor) {
|
|
3749
3765
|
const { AsyncHookSupervisor } =
|
|
3750
|
-
await import("../lib/async-hook-supervisor.
|
|
3766
|
+
await import("../lib/async-hook-supervisor.js");
|
|
3751
3767
|
_asyncHookSupervisor = new AsyncHookSupervisor({
|
|
3752
3768
|
persistStats: true,
|
|
3753
3769
|
});
|
|
@@ -5099,7 +5115,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
5099
5115
|
if (_settingsHooks) {
|
|
5100
5116
|
try {
|
|
5101
5117
|
const { runUserPromptSubmitHooks } =
|
|
5102
|
-
await import("../lib/settings-hook-events.
|
|
5118
|
+
await import("../lib/settings-hook-events.js");
|
|
5103
5119
|
const ups = runUserPromptSubmitHooks(_settingsHooks, {
|
|
5104
5120
|
prompt: userContent,
|
|
5105
5121
|
cwd: process.cwd(),
|
|
@@ -5122,10 +5138,10 @@ export async function startAgentRepl(options = {}) {
|
|
|
5122
5138
|
// turn without blocking it; its result/rewake surfaces on a later turn
|
|
5123
5139
|
// via the async-hook drain below. Lazily create the supervisor.
|
|
5124
5140
|
const { dispatchAsyncHooks } =
|
|
5125
|
-
await import("../lib/settings-hook-events.
|
|
5141
|
+
await import("../lib/settings-hook-events.js");
|
|
5126
5142
|
if (!_asyncHookSupervisor) {
|
|
5127
5143
|
const { AsyncHookSupervisor } =
|
|
5128
|
-
await import("../lib/async-hook-supervisor.
|
|
5144
|
+
await import("../lib/async-hook-supervisor.js");
|
|
5129
5145
|
_asyncHookSupervisor = new AsyncHookSupervisor({
|
|
5130
5146
|
persistStats: true,
|
|
5131
5147
|
});
|
|
@@ -5260,6 +5276,15 @@ export async function startAgentRepl(options = {}) {
|
|
|
5260
5276
|
}
|
|
5261
5277
|
}
|
|
5262
5278
|
|
|
5279
|
+
if (_turnBindingCriticalError) {
|
|
5280
|
+
logger.error(
|
|
5281
|
+
`[recovery] critical turn-binding state is unavailable: ${_turnBindingCriticalError.message}. ` +
|
|
5282
|
+
"Resume or start a healthy session before running another model/tool turn.",
|
|
5283
|
+
);
|
|
5284
|
+
prompt();
|
|
5285
|
+
return;
|
|
5286
|
+
}
|
|
5287
|
+
|
|
5263
5288
|
// Add user message (keep the object ref so a /btw aside can be injected for
|
|
5264
5289
|
// this turn's model call and then stripped before persistence).
|
|
5265
5290
|
const _userMsg = { role: "user", content: _userMessageContent };
|
|
@@ -5276,11 +5301,26 @@ export async function startAgentRepl(options = {}) {
|
|
|
5276
5301
|
if (!_turnBindingProducer) {
|
|
5277
5302
|
const { createReplTurnBindingProducer } =
|
|
5278
5303
|
await import("./repl-turn-binding.js");
|
|
5279
|
-
_turnBindingProducer = createReplTurnBindingProducer({
|
|
5304
|
+
_turnBindingProducer = createReplTurnBindingProducer({
|
|
5305
|
+
sessionId,
|
|
5306
|
+
onError: (error, phase) => {
|
|
5307
|
+
_turnBindingCriticalError = error;
|
|
5308
|
+
logger.warn(
|
|
5309
|
+
`[recovery] turn binding ${phase} failed for ${sessionId}: ${error.message}`,
|
|
5310
|
+
);
|
|
5311
|
+
},
|
|
5312
|
+
});
|
|
5280
5313
|
}
|
|
5281
5314
|
_turnBindingProducer?.beginTurn(messages.length);
|
|
5282
|
-
} catch {
|
|
5283
|
-
|
|
5315
|
+
} catch (error) {
|
|
5316
|
+
_turnBindingCriticalError =
|
|
5317
|
+
error instanceof Error ? error : new Error(String(error));
|
|
5318
|
+
if (messages[messages.length - 1] === _userMsg) messages.pop();
|
|
5319
|
+
logger.error(
|
|
5320
|
+
`[recovery] refusing the turn because binding state is unavailable: ${_turnBindingCriticalError.message}`,
|
|
5321
|
+
);
|
|
5322
|
+
prompt();
|
|
5323
|
+
return;
|
|
5284
5324
|
}
|
|
5285
5325
|
}
|
|
5286
5326
|
|
|
@@ -5433,7 +5473,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
5433
5473
|
// fire-and-forget; their results/rewakes drain into the next turn above.
|
|
5434
5474
|
if (_settingsHooks && !_asyncHookSupervisor) {
|
|
5435
5475
|
const { AsyncHookSupervisor } =
|
|
5436
|
-
await import("../lib/async-hook-supervisor.
|
|
5476
|
+
await import("../lib/async-hook-supervisor.js");
|
|
5437
5477
|
_asyncHookSupervisor = new AsyncHookSupervisor({ persistStats: true });
|
|
5438
5478
|
}
|
|
5439
5479
|
const {
|
|
@@ -5579,7 +5619,6 @@ export async function startAgentRepl(options = {}) {
|
|
|
5579
5619
|
try {
|
|
5580
5620
|
const rg = await import("../lib/repl-goal.js");
|
|
5581
5621
|
const fsMod = await import("node:fs");
|
|
5582
|
-
const cpMod = await import("node:child_process");
|
|
5583
5622
|
const judge = async (cond, { finalText }) => {
|
|
5584
5623
|
const { chatWithTools } = await import("../runtime/agent-core.js");
|
|
5585
5624
|
const { firstBalancedJson } =
|
|
@@ -5621,7 +5660,6 @@ export async function startAgentRepl(options = {}) {
|
|
|
5621
5660
|
response || "",
|
|
5622
5661
|
{
|
|
5623
5662
|
cwd: process.cwd(),
|
|
5624
|
-
spawnSync: cpMod.spawnSync,
|
|
5625
5663
|
existsSync: fsMod.existsSync,
|
|
5626
5664
|
judge,
|
|
5627
5665
|
},
|
|
@@ -5717,8 +5755,9 @@ export async function startAgentRepl(options = {}) {
|
|
|
5717
5755
|
// Non-critical
|
|
5718
5756
|
}
|
|
5719
5757
|
}
|
|
5720
|
-
// Persist the explicit turn-binding table for this settled turn
|
|
5721
|
-
//
|
|
5758
|
+
// Persist the explicit turn-binding table for this settled turn,
|
|
5759
|
+
// including tool-free turns. A failure is Critical: the producer throws,
|
|
5760
|
+
// this turn reports an error, and the guard above blocks later turns.
|
|
5722
5761
|
_turnBindingProducer?.persistIfDirty();
|
|
5723
5762
|
// Auto-compact when context grows too large
|
|
5724
5763
|
if (
|
|
@@ -5772,7 +5811,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
5772
5811
|
if (_settingsHooks) {
|
|
5773
5812
|
try {
|
|
5774
5813
|
const { runObserveHooks, dispatchAsyncHooks } =
|
|
5775
|
-
await import("../lib/settings-hook-events.
|
|
5814
|
+
await import("../lib/settings-hook-events.js");
|
|
5776
5815
|
runObserveHooks(
|
|
5777
5816
|
_settingsHooks,
|
|
5778
5817
|
"Stop",
|
|
@@ -5781,7 +5820,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
5781
5820
|
);
|
|
5782
5821
|
if (!_asyncHookSupervisor) {
|
|
5783
5822
|
const { AsyncHookSupervisor } =
|
|
5784
|
-
await import("../lib/async-hook-supervisor.
|
|
5823
|
+
await import("../lib/async-hook-supervisor.js");
|
|
5785
5824
|
_asyncHookSupervisor = new AsyncHookSupervisor({
|
|
5786
5825
|
persistStats: true,
|
|
5787
5826
|
});
|
|
@@ -5879,7 +5918,7 @@ export async function startAgentRepl(options = {}) {
|
|
|
5879
5918
|
if (_settingsHooks) {
|
|
5880
5919
|
try {
|
|
5881
5920
|
const { runObserveHooks } =
|
|
5882
|
-
await import("../lib/settings-hook-events.
|
|
5921
|
+
await import("../lib/settings-hook-events.js");
|
|
5883
5922
|
runObserveHooks(
|
|
5884
5923
|
_settingsHooks,
|
|
5885
5924
|
"SessionEnd",
|
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* publishes permission.resolved so the phone/web UI clears it)
|
|
9
9
|
* - remote answer first → cancel the local readline prompt and print
|
|
10
10
|
* the outcome
|
|
11
|
-
* - remote leg times out or the bridge closes mid-ask → NOT a
|
|
12
|
-
* keep waiting on the terminal. A
|
|
13
|
-
*
|
|
14
|
-
* semantics only.
|
|
11
|
+
* - remote leg times out or the bridge closes mid-ask → NOT a remote human
|
|
12
|
+
* decision, so keep waiting on the terminal. A later local answer still
|
|
13
|
+
* needs the bridge's durable CAS; an expired/closed card cannot be revived.
|
|
15
14
|
*
|
|
16
15
|
* Pure over an injected bridge + local prompt handle ({promise, cancel}),
|
|
17
16
|
* so the race is unit-testable without a WS server or readline.
|
|
@@ -46,8 +45,9 @@ export function describeAskContext({
|
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
//
|
|
50
|
-
//
|
|
48
|
+
// These outcomes are not a remote human decision. The terminal may still
|
|
49
|
+
// answer, but its result is accepted only if resolveLocally can durably settle
|
|
50
|
+
// the same live card.
|
|
51
51
|
const NON_DECISIVE_REMOTE = new Set(["timeout", "closed"]);
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -90,14 +90,14 @@ export async function raceLocalAndRemote({
|
|
|
90
90
|
winner = await localLeg;
|
|
91
91
|
}
|
|
92
92
|
if (winner.src === "local") {
|
|
93
|
-
if (requestId)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
if (!requestId) return false;
|
|
94
|
+
try {
|
|
95
|
+
const persisted = bridge.resolveLocally(requestId, winner.approved);
|
|
96
|
+
return persisted === true && winner.approved === true;
|
|
97
|
+
} catch {
|
|
98
|
+
// A local "yes" without a durable CAS is not an approval.
|
|
99
|
+
return false;
|
|
99
100
|
}
|
|
100
|
-
return winner.approved;
|
|
101
101
|
}
|
|
102
102
|
try {
|
|
103
103
|
local.cancel?.();
|
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
* anchored at/after its own offset — under `pickPersistedTurn`'s
|
|
15
15
|
* exact-offset matching a stale record from the discarded timeline would
|
|
16
16
|
* otherwise shadow the new turn and could offer the wrong checkpoint.
|
|
17
|
-
* 3. Per-settle persistence:
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* swallows its own failures.
|
|
17
|
+
* 3. Per-settle persistence: `persistTurnBinding` after each turn, including
|
|
18
|
+
* tool-free turns. Failures are reported through `onError` and fail closed
|
|
19
|
+
* by default; tests/diagnostics may explicitly request advisory mode.
|
|
21
20
|
*
|
|
22
21
|
* I/O goes through `_deps` so tests drive the producer hermetically.
|
|
23
22
|
*/
|
|
@@ -37,15 +36,35 @@ export const _deps = {
|
|
|
37
36
|
};
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
|
-
* @param {{sessionId?: string, nonce?: string
|
|
39
|
+
* @param {{sessionId?: string, nonce?: string, failClosed?:boolean,
|
|
40
|
+
* onError?:(error:Error, phase:string)=>void}} [opts]
|
|
41
41
|
* @returns {object|null} null when the session cannot persist (no sessionId)
|
|
42
42
|
*/
|
|
43
|
-
export function createReplTurnBindingProducer({
|
|
43
|
+
export function createReplTurnBindingProducer({
|
|
44
|
+
sessionId,
|
|
45
|
+
nonce,
|
|
46
|
+
onError,
|
|
47
|
+
failClosed = true,
|
|
48
|
+
} = {}) {
|
|
44
49
|
if (!sessionId) return null;
|
|
45
50
|
// Per-process nonce (mirrors the headless runner's per-run nonce): restored
|
|
46
51
|
// turn ids keep their original nonce, new ids can't collide across resumes.
|
|
47
52
|
const runNonce = nonce || String(_deps.now());
|
|
48
53
|
let feed = null;
|
|
54
|
+
let lastError = null;
|
|
55
|
+
const report = (error, phase) => {
|
|
56
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
57
|
+
try {
|
|
58
|
+
onError?.(lastError, phase);
|
|
59
|
+
} catch {
|
|
60
|
+
// Reporting must not replace the underlying recovery warning.
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const rejectOr = (error, phase, fallback) => {
|
|
64
|
+
report(error, phase);
|
|
65
|
+
if (failClosed) throw lastError;
|
|
66
|
+
return fallback;
|
|
67
|
+
};
|
|
49
68
|
return {
|
|
50
69
|
/**
|
|
51
70
|
* Anchor a new interactive turn. Call just AFTER the user message was
|
|
@@ -61,8 +80,8 @@ export function createReplTurnBindingProducer({ sessionId, nonce } = {}) {
|
|
|
61
80
|
});
|
|
62
81
|
}
|
|
63
82
|
return feed.beginTurn(conversationOffset, { supersede: true });
|
|
64
|
-
} catch {
|
|
65
|
-
return null;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
return rejectOr(error, "load", null);
|
|
66
85
|
}
|
|
67
86
|
},
|
|
68
87
|
/** Fold one agent-loop event into the current turn (fed by agentLoop). */
|
|
@@ -70,21 +89,32 @@ export function createReplTurnBindingProducer({ sessionId, nonce } = {}) {
|
|
|
70
89
|
if (!feed) return false;
|
|
71
90
|
try {
|
|
72
91
|
return feed.handleEvent(event);
|
|
73
|
-
} catch {
|
|
74
|
-
return false;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
return rejectOr(error, "event", false);
|
|
75
94
|
}
|
|
76
95
|
},
|
|
77
|
-
/** Persist the table after a settled turn (dirty-gated,
|
|
96
|
+
/** Persist the table after a settled turn (dirty-gated, fail-closed). */
|
|
78
97
|
persistIfDirty() {
|
|
79
98
|
if (!feed || !feed.isDirty()) return false;
|
|
99
|
+
let ok = false;
|
|
80
100
|
try {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
|
|
101
|
+
ok = _deps.persistTurnBinding(sessionId, feed.log);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
return rejectOr(error, "persist", false);
|
|
104
|
+
}
|
|
105
|
+
if (!ok) {
|
|
106
|
+
return rejectOr(
|
|
107
|
+
new Error("turn-binding snapshot was not persisted"),
|
|
108
|
+
"persist",
|
|
109
|
+
false,
|
|
110
|
+
);
|
|
86
111
|
}
|
|
112
|
+
feed.clearDirty();
|
|
113
|
+
lastError = null;
|
|
114
|
+
return true;
|
|
87
115
|
},
|
|
116
|
+
lastError: () => lastError,
|
|
117
|
+
sessionId: () => sessionId,
|
|
88
118
|
/** The live table (for tests / future in-process consumers). */
|
|
89
119
|
log: () => (feed ? feed.log : null),
|
|
90
120
|
};
|