chainlesschain 0.163.6 → 0.163.8
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/package.json +2 -1
- package/src/assets/web-panel/assets/{AIOps-DDIUofA8.js → AIOps-CavM7W3k.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Bm-5xYRn.js → ActionButton-CUvZGabQ.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D5UH4ljI.js → Analytics-DeBnWnbe.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-D_ifjOOP.js → AppLayout-DbI5kxvd.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-BY1mXdC7.js → Artifacts-D93bigKm.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Bujr4Ml3.js → Audit-CBNvfUZa.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-sioKSTcC.js → BackgroundAgents-CJLyh_YU.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DDOAK8RK.js → Backup-D_0yoehD.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CtCsVVke.js → BaseInput-TJxmbObW.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DpNj0vnd.js → Chat-CE0dto1q.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZta3Ftr.js → ChatBubbleRenderer-CZ5-yYiD.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DoHVNSXq.js → Checkbox-Ck1RVIVo.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DlVl7Qmv.js → Codegen-qpoyf6DK.js} +1 -1
- package/src/assets/web-panel/assets/{Col-GIqoPYty.js → Col-DUyPWjIE.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CIAPEVji.js → Community-D_S1BemS.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BN7JiI_h.js → Compact-BjxeK-Gc.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CqUWCM9B.js → Compliance-Dd3CEJsu.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-A4iPp7A4.js → Cowork-B4QG7-ad.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-B2zeXXWb.js → Cron-BtZnids5.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BR2xmWr8.js → Crosschain-CHPfCBFD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BzFDjrIv.js → DID-DT8DCEOK.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DKtDo3yA.js → Dashboard-COQab5_U.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-RNx43_YG.js → Dropdown-BY1PsQuU.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-SwMt4Rcy.js → EmailListRenderer-CsuAuaq3.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CsYebZ4X.js → FamilyGuardDashboard-BqpinD-j.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BmRKvBTy.js → Federation-D0gkfQFv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CVxGTA-0.js → FormItemContext-BqgE-axK.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-x2iXpyB7.js → GenericCardRenderer-D0hJ2KvC.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DfqbkiOP.js → Git-CmMB0uPY.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-RuHyyj5O.js → Governance-BnVEI0Dk.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Bn7uZ7rI.js → Inference-YTAMihRP.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DlP7XefZ.js → KnowledgeGraph-0ax7VHop.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BYNdOiCd.js → Logs-B9TRcokL.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-JQYmDqM8.js → Marketplace-B6CSuD_H.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Cyx4yZ-9.js → McpTools-CjMXvOVU.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-VDuGZTN2.js → Memory-CXRF71U3.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-_yKo97gi.js → MobileBridge-DQgNp_oS.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CXRXW3q7.js → MobileProjects-DlPwcCbq.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-acTGtfLH.js → Mtc-6hDTRPe1.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-ClpjXfkY.js → MtcAudit-BlVHU1DS.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-_6Tn3o96.js → Multisig-DP9pzEbV.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CK7pbZzP.js → NLProgramming-Djorh8EV.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Czy6V_P8.js → Notes-oLZ-JkUg.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Cqx-UVv3.js → NotificationSettings-Cg288VH3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C69WDxGy.js → OrderTableRenderer-Bb1O3Ofr.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DFnA9vLQ.js → Organization-CBdo-bHs.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-ReZkk2yT.js → Overflow-qZdnVumx.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DzjSI0aI.js → P2P-D4kNfGNQ.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-DnlMemM7.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-DhQ5klhR.js → Permissions-DHucHFBJ.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CUL1iHrW.js → PersonalDataHub-BovlOIPR.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-DU88iu4N.js → Pipeline-Deru3CQY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Bw-sYfyK.js → Privacy-Bq5oTTbU.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bq3Q5y0z.js → ProjectInit-BfzxVWAz.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C8spzpho.js → ProjectSettings-CKC6XBtH.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CMolGhae.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Bf4eTP9W.js → Providers-C_jx4TWX.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Dme9BDU1.js → QrScannerModal-BdIHeVGC.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CIXfv1rE.js → QuickAsk-BwZwAcPD.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CIxvdeZ-.js → Recommend-BNTt0L-m.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C6k7MExI.js → RemoteSession-Biyn2-Ro.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CISDz2bl.js → Reputation-D6VpG32B.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CdnDxXyf.js → Row-D_74OvQQ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C-QpRHsl.js → RssFeed-BTr0a-BQ.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DBjaGzSn.js → Search-C3MCFoNU.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CQKukOeE.js → Security-CqW9aJ6s.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DZz86jWb.js → Services-Cw5GNaHF.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-jb8RMK0d.js → Skeleton-DZps5qeY.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CdY76fZG.js → Skills-C6NQ1znT.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-C_CSiZX9.js → Sla-DFP8G2Sh.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-ESt6MB6v.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-qvimGO0O.js → SyncSettings-BHnN98aM.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Dng5LPJC.js → Tasks-NiSCaOf-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Bwqq5Wll.js → Templates-DsKFhW2C.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DNWuwP7Z.js → Tenant-CQ0E0ze5.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B-6Othpp.js → Terminal-D_rBu_by.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DKpKZfzx.js → TimelineRenderer-D3Vm4Po4.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DzfGMd2J.js → Tokens-DNTxRH6q.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BXwUi74J.js → Trigger-Dgprz1ms.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BNzUq4ui.js → Trust-B2rUnVBD.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BYugxww4.js → UkeySign-DEGQNc6_.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DdauhtSJ.js → VideoEditing-jlsAx3Eh.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CSC9bCe_.js → Wallet-8jQih1ij.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Q8AN3bTO.js → WebAuthn-XLeO6xIB.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-d-LBGCuA.js → WorkflowEditor-De_dgDAG.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BLVDCgsZ.js → chat-CI19R_Sk.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BZlPSEHl.js → colors-DsYTOYN3.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-IWseP6R6.js → compact-item-CM3-t_Qr.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DnVRV3Ao.js → createContext-BjxlBRZv.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DLQZA_Wn.js → hasIn-RDaWX_4i.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSjilZ9L.js → index-9R6BxAr0.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_N4-Gq9.js → index-B-Z8eFUJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dy0R5ZED.js → index-B0PMlbMs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1ifZtXo.js → index-B5REnKt8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CINJQEj6.js → index-B7WBt_4T.js} +1 -1
- package/src/assets/web-panel/assets/{index-DocEhinm.js → index-B9O9YyWE.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjWnONdy.js → index-BCnZyIMA.js} +1 -1
- package/src/assets/web-panel/assets/{index-hwVDeoC0.js → index-BGqqJfL0.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bbj2NS_I.js → index-BHNYPO0b.js} +3 -3
- package/src/assets/web-panel/assets/{index-C5dgnilC.js → index-BKJr-TZp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CT9vVN-X.js → index-BN6UPD2E.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpVrK6fr.js → index-Bi46Xu4u.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpBaJ3TD.js → index-BlT2VAEK.js} +1 -1
- package/src/assets/web-panel/assets/{index-1jeAudHd.js → index-C0yx-jtQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOoQpuQY.js → index-C4gkzxkw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZpYeqrh.js → index-CVQMeiwH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhA3QEni.js → index-Cd3euP_4.js} +1 -1
- package/src/assets/web-panel/assets/{index-N_GoWZX4.js → index-Cd9OJhHG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOZJBTWZ.js → index-CiECJi-Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-CarMTIyQ.js → index-CjTrRt13.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZDekj7T.js → index-CnHH7bnD.js} +1 -1
- package/src/assets/web-panel/assets/{index-M7wxfAbm.js → index-Cpqm1qfU.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bxp7uDD8.js → index-CyOGN6a5.js} +1 -1
- package/src/assets/web-panel/assets/{index-DalA0TKC.js → index-D0zcy54x.js} +1 -1
- package/src/assets/web-panel/assets/{index-COev0W2g.js → index-D6sm5-Xq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUq0c7gq.js → index-DIUnNOjG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZs5bBnk.js → index-DX7tuWVJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbQNL0ue.js → index-DXXtGMUJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTbxp4UH.js → index-DcPFB8qJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-YSw_gxlZ.js → index-DoQA0-52.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_LQodeJ.js → index-Drlnwr8F.js} +1 -1
- package/src/assets/web-panel/assets/index-Drz6yq0m.js +1 -0
- package/src/assets/web-panel/assets/{index-jWb70ZgZ.js → index-Dsij_KsN.js} +1 -1
- package/src/assets/web-panel/assets/{index-DB0MJgF_.js → index-Dxge-xWl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEu2lMBy.js → index-DyIWssPC.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2FqfMvU.js → index-IeiL9RKc.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dkwsi1Kn.js → index-nAH87mQP.js} +1 -1
- package/src/assets/web-panel/assets/{index-gt8bNefW.js → index-pPL66J85.js} +1 -1
- package/src/assets/web-panel/assets/index-uWiUs7S_.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-Co67Kqmb.js → initDefaultProps-BTL88of4.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BMOxQSF_.js → motion-BUB2pXwB.js} +1 -1
- package/src/assets/web-panel/assets/{move-C5fWDw-N.js → move-egCkkOMm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BJevpL0e.js → mtc-parser-DAWhZC8c.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCzNU8s6.js → omit-CvOxe_6d.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CybWvDPk.js → pickAttrs-DZUSLZ5Z.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BMWS9HnW.js → placementArrow-BERxGNMY.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BoL2UnGY.js → responsiveObserve-DZuDfZ9n.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DWNfXraU.js → slide-DO756sgI.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BquTM3tX.js → statusUtils-BRQlIz28.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BEkCleim.js → styleChecker-DCSfdybl.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Oecnq7EA.js → useFlexGapSupport-LD8dWVve.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CkDffJ4F.js → useFs-BX9uW2LK.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-qbvKXesB.js → usePersonalDataHub-BPSlPuHU.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-C6v8n6mA.js → vnode-BmOILC9V.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-4CTeFILV.js → zoom-1iKowKGg.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +5 -5
- package/src/commands/agent.js +90 -1
- package/src/commands/automation.js +103 -1
- package/src/commands/chat.js +11 -2
- package/src/commands/compact.js +106 -23
- package/src/commands/loop.js +28 -10
- package/src/commands/routine.js +1 -1
- package/src/commands/scheduler-daemon.js +359 -2
- package/src/commands/session-observability.js +305 -0
- package/src/commands/session.js +38 -0
- package/src/commands/team-merge-review.js +937 -0
- package/src/commands/team.js +2 -0
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/ws-agent-handler.js +439 -5
- package/src/harness/jsonl-session-store.js +463 -125
- package/src/harness/prompt-compressor.js +86 -13
- package/src/harness/provider-backed-compaction.js +100 -27
- package/src/lib/advisor-runtime.js +3 -1
- package/src/lib/agent-schedule-store.js +549 -28
- package/src/lib/agent-team/team-adjudication.js +40 -1
- package/src/lib/agent-team/team-merge-review-store.js +765 -0
- package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
- package/src/lib/agent-team/team-merge-review.js +1847 -0
- package/src/lib/automation-center-incidents.js +314 -0
- package/src/lib/automation-center-runtime.js +448 -0
- package/src/lib/automation-center.js +182 -38
- package/src/lib/automation-engine.js +535 -0
- package/src/lib/automation-execution-authority.js +241 -12
- package/src/lib/automation-execution-incident.js +737 -0
- package/src/lib/background-agent-supervisor.js +793 -215
- package/src/lib/background-command-argv.js +24 -0
- package/src/lib/background-interaction-journal.js +361 -52
- package/src/lib/background-interaction-resolver.js +32 -0
- package/src/lib/background-launch-profile.js +2 -0
- package/src/lib/causal-observability.js +2661 -0
- package/src/lib/chat-session-admission.js +76 -0
- package/src/lib/cost-budget.js +5 -7
- package/src/lib/cowork/ab-comparator-cli.js +11 -0
- package/src/lib/cowork/debate-review-cli.js +12 -0
- package/src/lib/cowork-adapter.js +159 -38
- package/src/lib/cowork-cron.js +442 -15
- package/src/lib/cowork-task-runner.js +112 -17
- package/src/lib/delivery-coordinator.js +142 -0
- package/src/lib/direct-model-usage.js +121 -0
- package/src/lib/file-lines.js +183 -47
- package/src/lib/llm-pricing.js +12 -17
- package/src/lib/loop.js +26 -2
- package/src/lib/routine-store.js +380 -21
- package/src/lib/runtime-usage-ledger.js +182 -0
- package/src/lib/scheduler-kernel/agenda-adapter.js +325 -10
- package/src/lib/scheduler-kernel/automation-adapter.js +514 -18
- package/src/lib/scheduler-kernel/automation-event-adapter.js +123 -11
- package/src/lib/scheduler-kernel/contract.js +91 -0
- package/src/lib/scheduler-kernel/cowork-cron-adapter.js +297 -4
- package/src/lib/scheduler-kernel/loop-adapter.js +547 -6
- package/src/lib/scheduler-kernel/migration-admin.js +346 -0
- package/src/lib/scheduler-kernel/migration-rollback-admin.js +932 -0
- package/src/lib/scheduler-kernel/routine-adapter.js +400 -20
- package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
- package/src/lib/scheduler-kernel/runtime.js +237 -2
- package/src/lib/scheduler-kernel/source-locator-path.js +142 -0
- package/src/lib/scheduler-kernel/store.js +3957 -248
- package/src/lib/session-host-lease.js +171 -2
- package/src/lib/session-host-snapshot.js +14 -3
- package/src/lib/session-persistence-failure.js +1 -0
- package/src/lib/session-tail.js +179 -34
- package/src/lib/session-transcript-structure.js +96 -0
- package/src/lib/sub-agent-context.js +328 -22
- package/src/lib/ws-agent-handler.js +4 -1
- package/src/repl/agent-repl.js +732 -91
- package/src/repl/chat-repl.js +5 -1
- package/src/runtime/agent-core.js +1282 -207
- package/src/runtime/fallback-model.js +5 -0
- package/src/runtime/headless-runner.js +324 -82
- package/src/runtime/headless-stream.js +232 -26
- package/src/runtime/mcp-config.js +81 -10
- package/src/runtime/policies/agent-policy.js +4 -0
- package/src/workers/background-agent-worker.js +403 -96
- package/src/assets/web-panel/assets/MarkdownRenderer-aMtgN-R6.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-DKTf5xIP.js +0 -7
- package/src/assets/web-panel/assets/Projects-Dd-xuPIc.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-C7tT9iad.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Jzu62CLC.js +0 -1
- package/src/assets/web-panel/assets/index-Zb2MeDSy.js +0 -1
- package/src/assets/web-panel/assets/index-fikqml4k.js +0 -1
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
import { readFileSync, writeSync } from "node:fs";
|
|
16
16
|
import { randomBytes } from "node:crypto";
|
|
17
|
+
import { resolve } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
17
19
|
import {
|
|
18
20
|
DEFAULT_HEARTBEAT_INTERVAL_MS,
|
|
19
21
|
DEFAULT_HEARTBEAT_STALE_MS,
|
|
@@ -31,6 +33,7 @@ import { startBackgroundSessionServer } from "../lib/background-session-transpor
|
|
|
31
33
|
import { idlePhaseFor } from "../lib/background-agent-phase.js";
|
|
32
34
|
import { attachInteractionRequestHandler } from "../lib/background-interaction-resolver.js";
|
|
33
35
|
import {
|
|
36
|
+
classifyLateBackgroundInteractionSettlement,
|
|
34
37
|
loadBackgroundInteractionJournal,
|
|
35
38
|
rejectPendingBackgroundInteractions,
|
|
36
39
|
updateBackgroundInteractionJournal,
|
|
@@ -45,6 +48,10 @@ import {
|
|
|
45
48
|
closeNeedsInputIncident,
|
|
46
49
|
createNeedsInputIncident,
|
|
47
50
|
} from "../lib/background-needs-input-incident.js";
|
|
51
|
+
import {
|
|
52
|
+
withSessionHostDelegatedWriteAuthority,
|
|
53
|
+
withSessionHostRecoveryLease,
|
|
54
|
+
} from "../lib/session-host-lease.js";
|
|
48
55
|
|
|
49
56
|
const jobFile = process.argv[2];
|
|
50
57
|
let job;
|
|
@@ -59,6 +66,7 @@ let lastExit = { code: 0, signal: null };
|
|
|
59
66
|
let transportState = null;
|
|
60
67
|
let detachInteractionHandler = null;
|
|
61
68
|
let interactionJournal = null;
|
|
69
|
+
let interactionFinalSweep = null;
|
|
62
70
|
let turnLaunchUncertainty = null;
|
|
63
71
|
let turnLaunchSettlement = null;
|
|
64
72
|
const promptQueue = [];
|
|
@@ -71,24 +79,210 @@ const pendingInteractions = new Map();
|
|
|
71
79
|
// relays the throw as {type:"error", message}) instead of silently queued.
|
|
72
80
|
const MAX_PROMPT_QUEUE = 100;
|
|
73
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Bind one idempotent termination settlement to a turn child.
|
|
84
|
+
*
|
|
85
|
+
* Node normally emits `exit` before `close`, but a spawn/runtime error can
|
|
86
|
+
* produce `error` followed only by `close`. Treat `error` as diagnostic (it
|
|
87
|
+
* does not prove process death) and settle when either terminal event arrives.
|
|
88
|
+
* The first terminal event wins, so the ordinary exit->close sequence cannot
|
|
89
|
+
* run journal recovery or finalization twice.
|
|
90
|
+
*
|
|
91
|
+
* Exported only so the event-order contract can be exercised without booting
|
|
92
|
+
* the detached worker process.
|
|
93
|
+
*/
|
|
94
|
+
export function attachTurnChildTerminationSettlement(
|
|
95
|
+
childProcess,
|
|
96
|
+
settleTermination,
|
|
97
|
+
) {
|
|
98
|
+
if (!childProcess || typeof childProcess.once !== "function") {
|
|
99
|
+
throw new TypeError("turn child must be an EventEmitter-like process");
|
|
100
|
+
}
|
|
101
|
+
if (typeof settleTermination !== "function") {
|
|
102
|
+
throw new TypeError("turn child termination callback is required");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let settled = false;
|
|
106
|
+
let observedError = null;
|
|
107
|
+
const settleOnce = (source, code, signal) => {
|
|
108
|
+
if (settled) return false;
|
|
109
|
+
settled = true;
|
|
110
|
+
settleTermination(
|
|
111
|
+
Object.freeze({
|
|
112
|
+
source,
|
|
113
|
+
code: observedError ? 1 : (code ?? null),
|
|
114
|
+
signal: signal || null,
|
|
115
|
+
error: observedError,
|
|
116
|
+
errorMessage: observedError?.message || null,
|
|
117
|
+
}),
|
|
118
|
+
);
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
121
|
+
const onError = (error) => {
|
|
122
|
+
observedError ||= error instanceof Error ? error : new Error(String(error));
|
|
123
|
+
};
|
|
124
|
+
const onExit = (code, signal) => settleOnce("exit", code, signal);
|
|
125
|
+
const onClose = (code, signal) => settleOnce("close", code, signal);
|
|
126
|
+
|
|
127
|
+
childProcess.once("error", onError);
|
|
128
|
+
childProcess.once("exit", onExit);
|
|
129
|
+
childProcess.once("close", onClose);
|
|
130
|
+
|
|
131
|
+
return () => {
|
|
132
|
+
childProcess.off?.("error", onError);
|
|
133
|
+
childProcess.off?.("exit", onExit);
|
|
134
|
+
childProcess.off?.("close", onClose);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Deliver an already-durable interaction outcome after best-effort cleanup of
|
|
140
|
+
* the worker-state projection.
|
|
141
|
+
*
|
|
142
|
+
* The transcript journal is the settlement authority. Once it contains the
|
|
143
|
+
* terminal answer, failure to clear the rebuildable state projection (or to
|
|
144
|
+
* persist its diagnostic marker) must not strand the child that is waiting
|
|
145
|
+
* for that answer.
|
|
146
|
+
*/
|
|
147
|
+
export function deliverAfterDurableInteractionCleanup({
|
|
148
|
+
cleanupProjection,
|
|
149
|
+
recordCleanupFailure,
|
|
150
|
+
detachAbort,
|
|
151
|
+
deliver,
|
|
152
|
+
}) {
|
|
153
|
+
if (typeof deliver !== "function") {
|
|
154
|
+
throw new TypeError("durable interaction delivery callback is required");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let cleanupError = null;
|
|
158
|
+
try {
|
|
159
|
+
cleanupProjection?.();
|
|
160
|
+
} catch (error) {
|
|
161
|
+
cleanupError = error;
|
|
162
|
+
try {
|
|
163
|
+
recordCleanupFailure?.(error);
|
|
164
|
+
} catch {
|
|
165
|
+
// The canonical terminal journal remains the answer authority even when
|
|
166
|
+
// both the state cleanup and its rebuildable diagnostic marker fail.
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
detachAbort?.();
|
|
172
|
+
} catch {
|
|
173
|
+
// Listener cleanup is also subordinate to delivering the durable answer.
|
|
174
|
+
}
|
|
175
|
+
deliver();
|
|
176
|
+
return { cleanupError };
|
|
177
|
+
}
|
|
178
|
+
|
|
74
179
|
function updateInteractionJournal(mutate, options = {}) {
|
|
75
|
-
const
|
|
180
|
+
const {
|
|
181
|
+
sessionHostWriteDelegation = null,
|
|
182
|
+
expectedOwnerPid,
|
|
183
|
+
...journalOptions
|
|
184
|
+
} = options;
|
|
185
|
+
const update = () =>
|
|
186
|
+
updateBackgroundInteractionJournal(
|
|
187
|
+
job.sessionId,
|
|
188
|
+
interactionJournal,
|
|
189
|
+
mutate,
|
|
190
|
+
journalOptions,
|
|
191
|
+
);
|
|
192
|
+
// Live child interaction writes always require the exact lease delegated by
|
|
193
|
+
// that child. Recovery is the only exception and uses its own acquired lease
|
|
194
|
+
// outside this helper; never fall back to legacy no-lease write authority.
|
|
195
|
+
const mutation = withSessionHostDelegatedWriteAuthority(
|
|
76
196
|
job.sessionId,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
197
|
+
sessionHostWriteDelegation,
|
|
198
|
+
update,
|
|
199
|
+
{ expectedOwnerPid },
|
|
80
200
|
);
|
|
81
201
|
interactionJournal = mutation.journal;
|
|
82
202
|
return mutation.result;
|
|
83
203
|
}
|
|
84
204
|
|
|
85
|
-
function persistInteractionSettlement(
|
|
205
|
+
function persistInteractionSettlement(
|
|
206
|
+
requestId,
|
|
207
|
+
binding,
|
|
208
|
+
outcome,
|
|
209
|
+
authority = {},
|
|
210
|
+
) {
|
|
86
211
|
return updateInteractionJournal(
|
|
87
212
|
(draft) => draft.settle(requestId, binding, outcome),
|
|
88
|
-
{ persistIf: (result) => result.applied },
|
|
213
|
+
{ ...authority, persistIf: (result) => result.applied },
|
|
89
214
|
);
|
|
90
215
|
}
|
|
91
216
|
|
|
217
|
+
function beginFinalInteractionSweep(continuation) {
|
|
218
|
+
if (interactionFinalSweep) return;
|
|
219
|
+
if (!job?.sessionId || !interactionJournal) {
|
|
220
|
+
continuation();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const context = {
|
|
224
|
+
attempts: 0,
|
|
225
|
+
timer: null,
|
|
226
|
+
continuation,
|
|
227
|
+
};
|
|
228
|
+
interactionFinalSweep = context;
|
|
229
|
+
|
|
230
|
+
const attempt = () => {
|
|
231
|
+
if (interactionFinalSweep !== context) return;
|
|
232
|
+
context.attempts += 1;
|
|
233
|
+
try {
|
|
234
|
+
// Reload from the canonical transcript under a fresh lease after the
|
|
235
|
+
// child is proven dead. This deliberately ignores the worker's cached
|
|
236
|
+
// journal: an earlier append may have reported commitState=unknown even
|
|
237
|
+
// though its pending snapshot reached disk.
|
|
238
|
+
const recovery = withSessionHostRecoveryLease(job.sessionId, () =>
|
|
239
|
+
rejectPendingBackgroundInteractions(job.sessionId, job.id, {
|
|
240
|
+
code: "INTERACTION_CHILD_EXITED",
|
|
241
|
+
message: "The agent child exited before the interaction settled",
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
interactionJournal = recovery.journal;
|
|
245
|
+
phase = "turn";
|
|
246
|
+
mergeState({
|
|
247
|
+
phase,
|
|
248
|
+
pendingQuestion: null,
|
|
249
|
+
interactionRecovery: {
|
|
250
|
+
status: recovery.changed ? "rejected" : "clean",
|
|
251
|
+
requestIds: recovery.rejected.map((record) => record.requestId),
|
|
252
|
+
recoveredAt: Date.now(),
|
|
253
|
+
attempts: context.attempts,
|
|
254
|
+
turn: turnCount,
|
|
255
|
+
workerGeneration: job.workerGeneration,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
interactionFinalSweep = null;
|
|
259
|
+
context.continuation();
|
|
260
|
+
} catch (error) {
|
|
261
|
+
phase = "interaction_recovery";
|
|
262
|
+
const retryMs = Math.min(
|
|
263
|
+
5_000,
|
|
264
|
+
250 * 2 ** Math.min(context.attempts - 1, 4),
|
|
265
|
+
);
|
|
266
|
+
mergeState({
|
|
267
|
+
phase,
|
|
268
|
+
pendingQuestion: null,
|
|
269
|
+
interactionRecovery: {
|
|
270
|
+
status: "failed",
|
|
271
|
+
code: error?.code || "INTERACTION_RECOVERY_FAILED",
|
|
272
|
+
message: error?.message || String(error),
|
|
273
|
+
failedAt: Date.now(),
|
|
274
|
+
attempts: context.attempts,
|
|
275
|
+
retryAfterMs: retryMs,
|
|
276
|
+
turn: turnCount,
|
|
277
|
+
workerGeneration: job.workerGeneration,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
context.timer = setTimeout(attempt, retryMs);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
attempt();
|
|
284
|
+
}
|
|
285
|
+
|
|
92
286
|
function mutateWorkerState(updater) {
|
|
93
287
|
return mutateBackgroundAgentState(job.id, (current) => {
|
|
94
288
|
if (!current || current.status !== "running" || current.stopRequestedAt) {
|
|
@@ -158,6 +352,10 @@ function finalize(code, signal, errorMessage) {
|
|
|
158
352
|
// result is durably recorded. Transport detach, a queued prompt, or a fatal
|
|
159
353
|
// callback must not exit through finalize and strand that retry protocol.
|
|
160
354
|
if (turnLaunchSettlement) return;
|
|
355
|
+
// A child-death journal sweep is part of terminal durability. Keep the
|
|
356
|
+
// worker and heartbeat alive until its fresh-lease reload either settles
|
|
357
|
+
// every disk-visible pending request or persists retry evidence.
|
|
358
|
+
if (interactionFinalSweep) return;
|
|
161
359
|
if (finalized) return;
|
|
162
360
|
finalized = true;
|
|
163
361
|
clearInterval(heartbeat);
|
|
@@ -286,6 +484,17 @@ function persistConfirmedTurnLaunchSettlement(context) {
|
|
|
286
484
|
turnLaunchFinalizationUncertain: false,
|
|
287
485
|
turnLaunchToken: null,
|
|
288
486
|
turnLaunchError: null,
|
|
487
|
+
interactionRecovery: job.sessionId
|
|
488
|
+
? {
|
|
489
|
+
status: "failed",
|
|
490
|
+
code: "INTERACTION_TURN_LAUNCH_SETTLEMENT",
|
|
491
|
+
message:
|
|
492
|
+
"Turn launch settlement completed before interaction recovery",
|
|
493
|
+
turn: Math.max(turnCount, context.turnLaunchAttempt),
|
|
494
|
+
workerGeneration: job.workerGeneration,
|
|
495
|
+
failedAt: Date.now(),
|
|
496
|
+
}
|
|
497
|
+
: current.interactionRecovery,
|
|
289
498
|
turnLaunchTermination: {
|
|
290
499
|
confirmed: true,
|
|
291
500
|
treeMode: context.termination.treeMode || null,
|
|
@@ -302,11 +511,18 @@ function persistConfirmedTurnLaunchSettlement(context) {
|
|
|
302
511
|
turnLaunchUncertainty = null;
|
|
303
512
|
turnLaunchSettlement = null;
|
|
304
513
|
child = null;
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
514
|
+
const finishLaunchFailure = () =>
|
|
515
|
+
finalize(
|
|
516
|
+
1,
|
|
517
|
+
null,
|
|
518
|
+
context.error?.message || "background turn launch failed",
|
|
519
|
+
);
|
|
520
|
+
if (context.owned && job.sessionId && interactionJournal) {
|
|
521
|
+
turnCount = Math.max(turnCount, context.turnLaunchAttempt);
|
|
522
|
+
beginFinalInteractionSweep(finishLaunchFailure);
|
|
523
|
+
} else {
|
|
524
|
+
finishLaunchFailure();
|
|
525
|
+
}
|
|
310
526
|
} catch {
|
|
311
527
|
scheduleTurnLaunchSettlementPersistence();
|
|
312
528
|
}
|
|
@@ -431,6 +647,9 @@ function startTurn(argv, promptText) {
|
|
|
431
647
|
if (!writeHeartbeat()) return false;
|
|
432
648
|
const nextTurn = turnCount + 1;
|
|
433
649
|
const turnLaunchToken = randomBytes(16).toString("hex");
|
|
650
|
+
// Private spawn-generation binding for the dedicated child IPC channel.
|
|
651
|
+
// It is never persisted in state or exposed through attach transports.
|
|
652
|
+
const turnIpcToken = randomBytes(32).toString("hex");
|
|
434
653
|
let turnLaunchAttempt = 0;
|
|
435
654
|
let prepared;
|
|
436
655
|
try {
|
|
@@ -507,7 +726,11 @@ function startTurn(argv, promptText) {
|
|
|
507
726
|
[job.cliEntry, ...argv],
|
|
508
727
|
{
|
|
509
728
|
cwd: job.cwd,
|
|
510
|
-
env: {
|
|
729
|
+
env: {
|
|
730
|
+
...process.env,
|
|
731
|
+
CC_BACKGROUND_AGENT_ID: job.id,
|
|
732
|
+
CC_BACKGROUND_TURN_IPC_NONCE: turnIpcToken,
|
|
733
|
+
},
|
|
511
734
|
stdio: ["ignore", log.fd, log.fd, "ipc"],
|
|
512
735
|
windowsHide: true,
|
|
513
736
|
origin: "background-agent:turn",
|
|
@@ -525,6 +748,12 @@ function startTurn(argv, promptText) {
|
|
|
525
748
|
pendingApprovals: 0,
|
|
526
749
|
pendingQuestion: null,
|
|
527
750
|
uncertainSideEffects: 0,
|
|
751
|
+
interactionRecovery: {
|
|
752
|
+
status: "pending",
|
|
753
|
+
turn: nextTurn,
|
|
754
|
+
workerGeneration: job.workerGeneration,
|
|
755
|
+
startedAt: agentStartedAt,
|
|
756
|
+
},
|
|
528
757
|
agentPid: spawned.pid,
|
|
529
758
|
agentStartedAt,
|
|
530
759
|
turnLaunchIntent: null,
|
|
@@ -573,13 +802,22 @@ function startTurn(argv, promptText) {
|
|
|
573
802
|
child,
|
|
574
803
|
async (payload, msg, { signal }) => {
|
|
575
804
|
const requestId = msg.requestId;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
805
|
+
const journalAuthority = {
|
|
806
|
+
sessionHostWriteDelegation: msg.sessionHostWriteDelegation || null,
|
|
807
|
+
// On Windows the broker ChildProcess PID can be the restricted-token
|
|
808
|
+
// sandbox helper. The dedicated IPC target reports its actual Node PID;
|
|
809
|
+
// require that PID to be the owner embedded in the exact active lease.
|
|
810
|
+
expectedOwnerPid: msg.senderPid,
|
|
811
|
+
};
|
|
812
|
+
updateInteractionJournal(
|
|
813
|
+
(draft) =>
|
|
814
|
+
draft.recordPending({
|
|
815
|
+
requestId,
|
|
816
|
+
binding: msg.binding,
|
|
817
|
+
payload,
|
|
818
|
+
createdAt: Date.now(),
|
|
819
|
+
}),
|
|
820
|
+
journalAuthority,
|
|
583
821
|
);
|
|
584
822
|
phase = "needs_input";
|
|
585
823
|
const pendingQuestion = {
|
|
@@ -633,67 +871,97 @@ function startTurn(argv, promptText) {
|
|
|
633
871
|
|
|
634
872
|
return new Promise((resolve, reject) => {
|
|
635
873
|
let settled = false;
|
|
636
|
-
const
|
|
874
|
+
const deliverTerminalOutcome = (
|
|
875
|
+
incidentStatus = "resolved",
|
|
876
|
+
deliver,
|
|
877
|
+
) => {
|
|
637
878
|
if (settled) return false;
|
|
638
879
|
settled = true;
|
|
639
880
|
pendingInteractions.delete(requestId);
|
|
640
881
|
let releasedQuestion = false;
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
current
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
882
|
+
deliverAfterDurableInteractionCleanup({
|
|
883
|
+
cleanupProjection() {
|
|
884
|
+
const cleanupMutation = mutateWorkerState((current) => {
|
|
885
|
+
const ownsQuestion =
|
|
886
|
+
current.pendingQuestion?.requestId === requestId ||
|
|
887
|
+
current.pendingQuestion?.intId === requestId;
|
|
888
|
+
const ownsIncident =
|
|
889
|
+
current.needsInputIncident?.requestId === requestId;
|
|
890
|
+
if (!ownsQuestion && !ownsIncident) return null;
|
|
891
|
+
releasedQuestion = ownsQuestion;
|
|
892
|
+
return {
|
|
893
|
+
...current,
|
|
894
|
+
id: job.id,
|
|
895
|
+
...(ownsQuestion
|
|
896
|
+
? { phase: "turn", pendingQuestion: null }
|
|
897
|
+
: {}),
|
|
898
|
+
...(ownsIncident
|
|
899
|
+
? {
|
|
900
|
+
needsInputIncident: closeNeedsInputIncident(
|
|
901
|
+
current.needsInputIncident,
|
|
902
|
+
{ status: incidentStatus, now: Date.now() },
|
|
903
|
+
),
|
|
904
|
+
}
|
|
905
|
+
: {}),
|
|
906
|
+
};
|
|
907
|
+
});
|
|
908
|
+
if (cleanupMutation.applied && releasedQuestion) phase = "turn";
|
|
909
|
+
},
|
|
910
|
+
recordCleanupFailure(error) {
|
|
911
|
+
// The terminal journal snapshot is already durable and therefore
|
|
912
|
+
// remains answer authority. Retain an explicit failed marker for
|
|
913
|
+
// the next heartbeat/recovery pass when possible.
|
|
914
|
+
mergeState({
|
|
915
|
+
interactionRecovery: {
|
|
916
|
+
status: "failed",
|
|
917
|
+
code: "INTERACTION_STATE_CLEANUP_FAILED",
|
|
918
|
+
message: error?.message || String(error),
|
|
919
|
+
failedAt: Date.now(),
|
|
920
|
+
turn: turnCount,
|
|
921
|
+
workerGeneration: job.workerGeneration,
|
|
922
|
+
},
|
|
923
|
+
});
|
|
924
|
+
},
|
|
925
|
+
detachAbort() {
|
|
926
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
927
|
+
},
|
|
928
|
+
deliver,
|
|
662
929
|
});
|
|
663
|
-
if (cleanupMutation.applied && releasedQuestion) phase = "turn";
|
|
664
|
-
signal?.removeEventListener?.("abort", onAbort);
|
|
665
930
|
return true;
|
|
666
931
|
};
|
|
667
932
|
const onAbort = () => {
|
|
668
933
|
let rejection;
|
|
669
934
|
try {
|
|
670
|
-
persistInteractionSettlement(
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
935
|
+
persistInteractionSettlement(
|
|
936
|
+
requestId,
|
|
937
|
+
msg.binding,
|
|
938
|
+
{
|
|
939
|
+
status: "cancelled",
|
|
940
|
+
error: {
|
|
941
|
+
code: "INTERACTION_CANCELLED",
|
|
942
|
+
message: "Background interaction was cancelled",
|
|
943
|
+
},
|
|
675
944
|
},
|
|
676
|
-
|
|
945
|
+
journalAuthority,
|
|
946
|
+
);
|
|
677
947
|
} catch (error) {
|
|
678
948
|
rejection = error;
|
|
679
949
|
}
|
|
680
|
-
if (!cleanup("cancelled")) return;
|
|
681
950
|
if (!rejection) {
|
|
682
951
|
rejection = new Error("Background interaction was cancelled");
|
|
683
952
|
rejection.code = "INTERACTION_CANCELLED";
|
|
684
953
|
}
|
|
685
|
-
reject(rejection);
|
|
954
|
+
deliverTerminalOutcome("cancelled", () => reject(rejection));
|
|
686
955
|
};
|
|
687
956
|
const entry = {
|
|
688
957
|
payload,
|
|
689
958
|
binding: msg.binding,
|
|
959
|
+
journalAuthority,
|
|
690
960
|
deliverResolved(answer) {
|
|
691
|
-
|
|
692
|
-
resolve(answer);
|
|
961
|
+
deliverTerminalOutcome("resolved", () => resolve(answer));
|
|
693
962
|
},
|
|
694
963
|
deliverRejected(error) {
|
|
695
|
-
|
|
696
|
-
reject(error);
|
|
964
|
+
deliverTerminalOutcome("cancelled", () => reject(error));
|
|
697
965
|
},
|
|
698
966
|
};
|
|
699
967
|
pendingInteractions.set(requestId, entry);
|
|
@@ -708,39 +976,46 @@ function startTurn(argv, promptText) {
|
|
|
708
976
|
{
|
|
709
977
|
backgroundAgentId: job.id,
|
|
710
978
|
sessionId: job.sessionId || null,
|
|
979
|
+
turnIpcToken,
|
|
980
|
+
requireSenderPid: true,
|
|
981
|
+
requireDelegationOwnerPid: true,
|
|
711
982
|
},
|
|
712
983
|
);
|
|
713
984
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
// so the supervisor recovery path can reject it deterministically.
|
|
985
|
+
attachTurnChildTerminationSettlement(
|
|
986
|
+
child,
|
|
987
|
+
({ code, signal, errorMessage }) => {
|
|
988
|
+
lastExit = {
|
|
989
|
+
code,
|
|
990
|
+
signal,
|
|
991
|
+
...(errorMessage ? { errorMessage } : {}),
|
|
992
|
+
};
|
|
993
|
+
child = null;
|
|
994
|
+
// 清理交互处理器
|
|
995
|
+
detachInteractionHandler?.();
|
|
996
|
+
detachInteractionHandler = null;
|
|
997
|
+
// Reject any request that survived an abnormal child exit. Normal
|
|
998
|
+
// responses remove themselves from this map before the turn continues.
|
|
999
|
+
for (const [requestId, pending] of pendingInteractions) {
|
|
1000
|
+
const error = new Error("Agent exited");
|
|
1001
|
+
error.code = "INTERACTION_CHILD_EXITED";
|
|
1002
|
+
pending.deliverRejected?.(error);
|
|
733
1003
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1004
|
+
pendingInteractions.clear();
|
|
1005
|
+
beginFinalInteractionSweep(() => {
|
|
1006
|
+
server?.broadcast({
|
|
1007
|
+
type: "turn-ended",
|
|
1008
|
+
turn: turnCount,
|
|
1009
|
+
exitCode: code,
|
|
1010
|
+
});
|
|
1011
|
+
if (lastExit.errorMessage) {
|
|
1012
|
+
finalize(1, signal, lastExit.errorMessage);
|
|
1013
|
+
} else {
|
|
1014
|
+
maybeContinue();
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
},
|
|
1018
|
+
);
|
|
744
1019
|
return true;
|
|
745
1020
|
}
|
|
746
1021
|
|
|
@@ -814,24 +1089,38 @@ async function main() {
|
|
|
814
1089
|
}
|
|
815
1090
|
removeJobFile(jobFile);
|
|
816
1091
|
log = openBackgroundLogFile(job.id);
|
|
817
|
-
|
|
1092
|
+
const bootstrapState = readBackgroundAgentState(job.id);
|
|
1093
|
+
const allowAbsentBootstrap =
|
|
1094
|
+
job.sessionBootstrapExpected === true &&
|
|
1095
|
+
bootstrapState?.sessionBootstrapExpected === true &&
|
|
1096
|
+
bootstrapState?.workerGeneration === job.workerGeneration &&
|
|
1097
|
+
Number(bootstrapState?.turnCount || 0) === 0 &&
|
|
1098
|
+
!bootstrapState?.pendingQuestion;
|
|
1099
|
+
interactionJournal = loadBackgroundInteractionJournal(job.sessionId, job.id, {
|
|
1100
|
+
// A fresh background session is created by the first headless turn child.
|
|
1101
|
+
// Bootstrap may inspect an actually absent transcript before that child
|
|
1102
|
+
// writes session_start; it must remain an empty in-memory journal and may
|
|
1103
|
+
// never create transcript genesis itself.
|
|
1104
|
+
allowAbsent: allowAbsentBootstrap,
|
|
1105
|
+
});
|
|
818
1106
|
if (interactionJournal.pending().length > 0) {
|
|
819
|
-
const recovery =
|
|
820
|
-
job.sessionId,
|
|
821
|
-
job.id,
|
|
822
|
-
{
|
|
1107
|
+
const recovery = withSessionHostRecoveryLease(job.sessionId, () =>
|
|
1108
|
+
rejectPendingBackgroundInteractions(job.sessionId, job.id, {
|
|
823
1109
|
code: "INTERACTION_WORKER_RESTARTED",
|
|
824
1110
|
message:
|
|
825
1111
|
"The background worker restarted before the interaction settled",
|
|
826
|
-
},
|
|
1112
|
+
}),
|
|
827
1113
|
);
|
|
828
1114
|
interactionJournal = recovery.journal;
|
|
829
1115
|
mergeState({
|
|
830
1116
|
phase: "turn",
|
|
831
1117
|
pendingQuestion: null,
|
|
832
1118
|
interactionRecovery: {
|
|
833
|
-
|
|
1119
|
+
status: recovery.changed ? "rejected" : "clean",
|
|
1120
|
+
requestIds: recovery.rejected.map((record) => record.requestId),
|
|
834
1121
|
recoveredAt: Date.now(),
|
|
1122
|
+
turn: turnCount,
|
|
1123
|
+
workerGeneration: job.workerGeneration,
|
|
835
1124
|
},
|
|
836
1125
|
});
|
|
837
1126
|
}
|
|
@@ -900,17 +1189,23 @@ async function main() {
|
|
|
900
1189
|
: { code: "INTERACTION_REJECTED", message: String(error) },
|
|
901
1190
|
}
|
|
902
1191
|
: { status: "resolved", answer };
|
|
1192
|
+
if (!entry) {
|
|
1193
|
+
return classifyLateBackgroundInteractionSettlement(
|
|
1194
|
+
interactionJournal,
|
|
1195
|
+
resolvedId,
|
|
1196
|
+
binding,
|
|
1197
|
+
outcome,
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
903
1200
|
const settlement = persistInteractionSettlement(
|
|
904
1201
|
resolvedId,
|
|
905
1202
|
binding,
|
|
906
1203
|
outcome,
|
|
1204
|
+
entry.journalAuthority,
|
|
907
1205
|
);
|
|
908
1206
|
if (!settlement.applied) {
|
|
909
1207
|
return { accepted: true, duplicate: true };
|
|
910
1208
|
}
|
|
911
|
-
if (!entry) {
|
|
912
|
-
return { accepted: true, duplicate: false, delivered: false };
|
|
913
|
-
}
|
|
914
1209
|
if (error) {
|
|
915
1210
|
const rejection = new Error(
|
|
916
1211
|
typeof error === "object" ? error.message : error,
|
|
@@ -979,7 +1274,7 @@ async function main() {
|
|
|
979
1274
|
if (!startTurn(job.argv, null)) finalize(0, null);
|
|
980
1275
|
}
|
|
981
1276
|
|
|
982
|
-
|
|
1277
|
+
function handleWorkerFatal(error) {
|
|
983
1278
|
// The earliest bootstrap failures happen before `job` and `log` exist.
|
|
984
1279
|
// Write synchronously to the launcher-provided stderr handle so detached
|
|
985
1280
|
// Windows workers retain the loader/job/state error that caused the exit.
|
|
@@ -1002,4 +1297,16 @@ main().catch((error) => {
|
|
|
1002
1297
|
}
|
|
1003
1298
|
}
|
|
1004
1299
|
process.exit(1);
|
|
1005
|
-
}
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
const invokedWorkerPath = process.argv[1] ? resolve(process.argv[1]) : null;
|
|
1303
|
+
const moduleWorkerPath = resolve(fileURLToPath(import.meta.url));
|
|
1304
|
+
const directWorkerEntrypoint =
|
|
1305
|
+
invokedWorkerPath !== null &&
|
|
1306
|
+
(process.platform === "win32"
|
|
1307
|
+
? invokedWorkerPath.toLowerCase() === moduleWorkerPath.toLowerCase()
|
|
1308
|
+
: invokedWorkerPath === moduleWorkerPath);
|
|
1309
|
+
|
|
1310
|
+
if (directWorkerEntrypoint) {
|
|
1311
|
+
main().catch(handleWorkerFatal);
|
|
1312
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{P as c,J as p,b as s}from"./vendor-Bn1JzzAn.js";import{r as a}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-Bbj2NS_I.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=s(()=>a(e.content||"")),n={props:e,rendered:r,computed:s,get renderMarkdown(){return a}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function m(t,o,e,r,n,u){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=d(_,[["render",m],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-dUjpNL/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
|