chainlesschain 0.162.197 → 0.162.198
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 +1 -1
- package/src/assets/web-panel/assets/{AIOps-D3Gu1a5d.js → AIOps-CSN-D2xb.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DrwAoKaz.js → ActionButton-CBSMlGzv.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C7Q-gd_3.js → Analytics-3yr3Nt2t.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DgBtae-n.js → AppLayout-1b-o3lMH.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-pQ6LcA-W.js → Artifacts-Dr8rJi17.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DK61tocB.js → Audit-2V689HC2.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BOKgDFRh.js → BackgroundAgents-DIxkNrD_.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Bo9G4vTP.js → Backup-Pg6BcwrE.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Do_dE9_v.js → BaseInput-CLUpqyfH.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-COVvZzOL.js → Chat-qVS8rD4G.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-ti49X12Q.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Z9MJMolt.js → Checkbox-Bs9AaEay.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BVzWKVbf.js → Codegen-Dvc1mq8q.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C8MnYcbT.js → Col-C4_biO7A.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DQxqw15l.js → Community-al25XQUV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BAUmrh3y.js → Compact-D-ZDB8M1.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-jPAkQ3zK.js → Compliance-6lIfDz1W.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BBQyxbh8.js → Cowork-DdI48XMJ.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-W5koq8Z5.js → Cron-DF5HZd2g.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BQhnu5hS.js → Crosschain-DuxeSvt3.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DD7PlI18.js → DID-B9yHkUTd.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-w_ILuwKI.js → Dashboard-Z5EuI3IM.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-qiDUAyAo.js → Dropdown-vuRfO3dY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-PDeBcI5H.js → EmailListRenderer-QFLCc1uL.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-SuArscRM.js → FamilyGuardDashboard-BZ7EXkFJ.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BCovZaUn.js → Federation-DycIEg2s.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DjlFdVFk.js → FormItemContext-Ba0H_7yG.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DoEZ7fcS.js → GenericCardRenderer--JgSTK-C.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CV0-6GPI.js → Git-DEvTbldE.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B_SFN50w.js → Governance-BJIljy18.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-heI0Eo6k.js → Inference-CVyW3G3q.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cz5INS5p.js → KnowledgeGraph-v8-borge.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BSFxiHkg.js → Logs-BCdS7gGo.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-CU-JB2Ns.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-0TWTpE7k.js → Marketplace-AN6tGA2B.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CV4-wBLm.js → McpTools-DGViXASN.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-x5bH5rw5.js → Memory-Bpvmx9X4.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DaBmUu9G.js → MobileBridge-CTP-DOTC.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-C8qfktxn.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B_zKEBif.js → Mtc-ndYr0M1s.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BCfKD2yg.js → MtcAudit-Ci0-YK7W.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DgYfj6c_.js → Multisig-BehSTFW7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dz09lFUm.js → NLProgramming-B91_YBLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cuj6ugBE.js → Notes-BQlJ0-gq.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DK2WXjhg.js → NotificationSettings-CDgYMjYK.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-D1IAOQoo.js → OrderTableRenderer-BJkSlKeH.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-9fqnPvTw.js → Organization-B-b3cWCp.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-n5xHkhow.js → Overflow-CILUL4nL.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B5AUWwH-.js → P2P-BTCFBkF0.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CoUDV6dy.js → PdhVaultBrowser-BAR6AUx5.js} +4 -4
- package/src/assets/web-panel/assets/{Permissions-DPRmQf_H.js → Permissions-RRf6HbWJ.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B37bsbEN.js → PersonalDataHub-BGTMiICa.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-CCAuPqu9.js → Pipeline-945qY9YF.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B81msZdv.js → Privacy-DPZwI6lJ.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B-Py2NbF.js → ProjectInit-BPH2NRKc.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CYsneiRB.js → ProjectSettings-BZCRNCvb.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Y975Mh6R.js → Projects-BTI__tBt.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-uO-10aP1.js → Providers-DDCf_nIw.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-Bj_6gJ0l.js → QrScannerModal-N6rbqt1r.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BgpBCMPE.js → QuickAsk-DrwjPS7M.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DhUW3YUA.js → Recommend-Cog9Wd99.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DdeyfbkA.js → RemoteSession-DC9pynjM.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-fxW421xd.js → Reputation-D4th4gKS.js} +1 -1
- package/src/assets/web-panel/assets/{Row-De73w1og.js → Row-ogiWR6v9.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-3US_Q_lj.js → RssFeed-uYlk-2Oj.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DbZ_DU74.js → Search-DYzzwvtM.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DoIU1vMF.js → Security-Da7YOyX6.js} +4 -4
- package/src/assets/web-panel/assets/{Services-DB_RGqpc.js → Services-CLI1VM1X.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DnzLaayC.js → Skeleton-DK77dzDC.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-VzVXHENF.js → Skills-C_z7Lmhl.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DMfvjCAI.js → Sla-D6413Q8L.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DQQOYWbF.js → SpeechSettings-C07ydbj2.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Bmx3FG1P.js → SyncSettings-DGOm2W22.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DOQyfb-2.js → Tasks-Cr_PVyLM.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D6hTRT7c.js → Templates-BhL2mZ0t.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CTPQZAzs.js → Tenant-CPk5oyUr.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B7vII3oH.js → Terminal-ClhqUsqV.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BkiFJeXV.js → TimelineRenderer-BCC7MV5a.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BPPdQMNo.js → Tokens-DD1Jt4oO.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BxG8JAEI.js → Trigger-BCydFvN2.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DHD7nMpM.js → Trust-DDHT1noa.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B4BJpU47.js → UkeySign-CWPZC7oI.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CRiGpFx2.js → VideoEditing-9Ea0nJR0.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BSDSNiem.js → Wallet-BjxhLxTf.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DLTUh5Zv.js → WebAuthn-C6uCye67.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-tW2MwjhD.js → WorkflowEditor-d2g4reYo.js} +1 -1
- package/src/assets/web-panel/assets/{chat-SgsLQ3FC.js → chat-frTc6ScX.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BHjjLIKO.js → colors-B5K6lG3v.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-VceErdKq.js → compact-item-Cdn46r8D.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BZ332MYl.js → createContext-DU1jqVQi.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CP-jEUyw.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CBTjJOjn.js → hasIn-DdNH-aW_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CawpdGTW.js → index-32ajXmTb.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOtvPdHt.js → index-7ehytj1K.js} +1 -1
- package/src/assets/web-panel/assets/{index-vIXOpcjD.js → index-BC4eGkar.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr4rjlW5.js → index-BVLL-mq_.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_SePDWj.js → index-BXKhhx9V.js} +1 -1
- package/src/assets/web-panel/assets/{index-BETEjuNr.js → index-BcGwGIaR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BY1wexYG.js → index-Be4OtL-N.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRWhLbWF.js → index-BoFak7le.js} +1 -1
- package/src/assets/web-panel/assets/{index-29wVzi-k.js → index-BwlIxAmX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BeiqkxJG.js → index-CGiwfwB9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQSmZGgs.js → index-CHmkkdfT.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhXZEUAc.js → index-CQorP1Ng.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_B9rFQE.js → index-CUoNAmE8.js} +1 -1
- package/src/assets/web-panel/assets/{index-iYQNU9za.js → index-Cj6P9Nst.js} +1 -1
- package/src/assets/web-panel/assets/{index-DePOeMDM.js → index-CtRPi4YC.js} +1 -1
- package/src/assets/web-panel/assets/index-CzrCHrFy.js +1 -0
- package/src/assets/web-panel/assets/{index-DdefYBSw.js → index-D1qIC4GR.js} +1 -1
- package/src/assets/web-panel/assets/{index-By5jBtkV.js → index-D23xGYjM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMVvxIS8.js → index-D4l82Me1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLc19alH.js → index-D4miNkWv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2u26AS3.js → index-DIVyTmZ3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaCCy6lq.js → index-DM5FmPZU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUkVN794.js → index-DRzBBdQ0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPXFLYdW.js → index-Dca_i7H8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpumS98o.js → index-DftZuyA7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrUgDQkf.js → index-DtBCCkC4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtjLcCNU.js → index-HjCvXHf5.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaIS_TNX.js → index-LaivuXyF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC1xuQgX.js → index-MM4Zz2OE.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcUenmCX.js → index-NmEXVjzt.js} +1 -1
- package/src/assets/web-panel/assets/index-OJsGskZw.js +1 -0
- package/src/assets/web-panel/assets/{index-_PHrIO4O.js → index-PjAS0sIZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgPvuIn2.js → index-VDM2KKo9.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5KAGxNo.js → index-cYaWV4Mq.js} +1 -1
- package/src/assets/web-panel/assets/{index-B40dQn0G.js → index-gg3QPC3i.js} +3 -3
- package/src/assets/web-panel/assets/{index-BTlc-Bve.js → index-kVO_MDm-.js} +1 -1
- package/src/assets/web-panel/assets/{index-FJ3zC9LK.js → index-mgU3Q-lN.js} +1 -1
- package/src/assets/web-panel/assets/{index-1n7xjKDU.js → index-t_OBzIP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-fU7wNHDB.js → index-yZRuZpwK.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D1oZNz0D.js → initDefaultProps-DwLTRNdo.js} +1 -1
- package/src/assets/web-panel/assets/{motion-C8k6doMO.js → motion-BchZDXnh.js} +1 -1
- package/src/assets/web-panel/assets/{move-DJ4qSbYt.js → move-e8M-zZFl.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CdpJD85j.js → mtc-parser-Ci40fQb3.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B0V4slKA.js → omit-C7110_f2.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Di5NiW1F.js → pickAttrs-skteMgnM.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B5OMHgEM.js → placementArrow-MGZ-lh2B.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C6U9IWql.js → responsiveObserve-N4Sd7uy-.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BMyTH3rN.js → slide-C7HDGRaa.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C7d6BG7Z.js → statusUtils-BhRexlgy.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CR50QnQy.js → styleChecker-ChEoQkN2.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DBEeoMb8.js → useFlexGapSupport-CDbG1s2Y.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-3r099cjv.js → useFs-CUIx0tcJ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-C5IYNdTK.js → usePersonalDataHub-bkO7L7ec.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DmEOLRHf.js → vnode-B_ZvABIG.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DnpUiVCB.js → zoom-D5shjpS8.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +4 -4
- package/src/commands/agent.js +3 -3
- package/src/commands/background-session.js +145 -0
- package/src/commands/mcp.js +125 -7
- package/src/commands/serve.js +1 -1
- package/src/commands/session-show.js +131 -0
- package/src/commands/session.js +50 -106
- package/src/commands/skill.js +87 -50
- package/src/data/changelog.json +14 -1
- package/src/gateways/ws/ws-agent-handler.js +8 -1
- package/src/harness/jsonl-session-store.js +428 -25
- package/src/harness/mcp-client.js +2652 -404
- package/src/harness/session-list-index.js +65 -7
- package/src/lazy-dispatch.js +76 -8
- package/src/lib/abort-utils.js +68 -0
- package/src/lib/agent-core.js +1 -59
- package/src/lib/chat-core.js +24 -6
- package/src/lib/cowork-mcp-tools.js +47 -2
- package/src/lib/cowork-task-runner.js +11 -3
- package/src/lib/doctor-checkup.js +9 -7
- package/src/lib/learning/skill-improver.js +21 -2
- package/src/lib/mcp-call-ledger-store.js +116 -3
- package/src/lib/mcp-call-ledger.js +59 -14
- package/src/lib/mcp-client.js +1 -0
- package/src/lib/mcp-stdio-executable-identity.js +598 -0
- package/src/lib/mcp-stdio-execution-authority.js +363 -0
- package/src/lib/mcp-tool-metadata.js +436 -0
- package/src/lib/mcp-tool-result.js +367 -0
- package/src/lib/observability/index.js +71 -0
- package/src/lib/pr-link-ledger.js +8 -27
- package/src/lib/pr-link-store.js +26 -0
- package/src/lib/process-execution-broker/index.js +14 -0
- package/src/lib/process-tree-termination.js +253 -0
- package/src/lib/session-host-snapshot.js +9 -5
- package/src/lib/session-projection.js +5 -1
- package/src/lib/session-tail.js +31 -1
- package/src/lib/skill-budget.js +222 -0
- package/src/lib/skill-execution-authority.js +381 -0
- package/src/lib/skill-execution-identity.js +39 -2
- package/src/lib/skill-loader.js +322 -86
- package/src/lib/skill-mcp.js +43 -1
- package/src/repl/agent-repl.js +174 -38
- package/src/repl/bg-dashboard.js +81 -28
- package/src/repl/chat-repl.js +77 -12
- package/src/runtime/agent-core.js +340 -108
- package/src/runtime/agent-runtime.js +26 -3
- package/src/runtime/headless-runner.js +150 -23
- package/src/runtime/headless-stream.js +309 -59
- package/src/runtime/mcp-config.js +157 -10
- package/src/runtime/mcp-tool-search.js +0 -0
- package/src/runtime/output-backpressure.js +366 -0
- package/src/runtime/pipe-safety.js +56 -21
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BUUyJ5QO.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-1mNozZ8v.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DqnoFPgR.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DosMaL-k.js +0 -1
- package/src/assets/web-panel/assets/index-0O5ePnUq.js +0 -1
- package/src/assets/web-panel/assets/index-ChAzPigF.js +0 -1
- package/src/lib/skill-process-broker.js +0 -85
|
@@ -92,6 +92,7 @@ import {
|
|
|
92
92
|
readVerifiedProjection as jsonlReadVerifiedProjection,
|
|
93
93
|
findLatestEvent as jsonlFindLatestEvent,
|
|
94
94
|
sessionExists as jsonlSessionExists,
|
|
95
|
+
sessionHasPersistedEvidence as jsonlSessionHasPersistedEvidence,
|
|
95
96
|
} from "../harness/jsonl-session-store.js";
|
|
96
97
|
import {
|
|
97
98
|
isVerifiedSessionHostSnapshot,
|
|
@@ -123,6 +124,7 @@ import {
|
|
|
123
124
|
parseSessionSlashCommandEvent,
|
|
124
125
|
} from "./session-slash-commands.js";
|
|
125
126
|
import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
|
|
127
|
+
import { createHeadlessOutputBackpressure } from "./output-backpressure.js";
|
|
126
128
|
|
|
127
129
|
function invalidMcpRecoveryTransaction(capability, expected) {
|
|
128
130
|
const error = new TypeError(
|
|
@@ -778,6 +780,7 @@ async function runTurn(
|
|
|
778
780
|
sideEffects,
|
|
779
781
|
turnNumber,
|
|
780
782
|
turnBindingFeed,
|
|
783
|
+
waitForOutput,
|
|
781
784
|
now = Date.now,
|
|
782
785
|
},
|
|
783
786
|
) {
|
|
@@ -1017,6 +1020,7 @@ async function runTurn(
|
|
|
1017
1020
|
if (event.type) emit(event);
|
|
1018
1021
|
break;
|
|
1019
1022
|
}
|
|
1023
|
+
await waitForOutput?.();
|
|
1020
1024
|
// Hard cost cap reached — stop consuming the loop (break the for-await, not
|
|
1021
1025
|
// just the switch) so no further paid LLM call is made.
|
|
1022
1026
|
if (stopForCost) break;
|
|
@@ -1044,21 +1048,216 @@ async function runTurn(
|
|
|
1044
1048
|
* writeOut, writeErr, expandFileRefs }
|
|
1045
1049
|
* @returns {Promise<{exitCode:number, turns:number}>}
|
|
1046
1050
|
*/
|
|
1051
|
+
function createHeadlessStreamCleanupScope({ input }) {
|
|
1052
|
+
let mcpClient = null;
|
|
1053
|
+
let remoteApproval = null;
|
|
1054
|
+
let inputCancel = null;
|
|
1055
|
+
let interactionCleanup = null;
|
|
1056
|
+
let outputCleanup = null;
|
|
1057
|
+
let sessionEnd = null;
|
|
1058
|
+
let reason = "error";
|
|
1059
|
+
let stopRequested = false;
|
|
1060
|
+
let interactionCleanupPromise = Promise.resolve();
|
|
1061
|
+
let cleanupPromise = null;
|
|
1062
|
+
|
|
1063
|
+
const runBestEffort = async (operation) => {
|
|
1064
|
+
if (typeof operation !== "function") return;
|
|
1065
|
+
try {
|
|
1066
|
+
await operation();
|
|
1067
|
+
} catch {
|
|
1068
|
+
// Cleanup is exhaustive: one failing disposer must not prevent the
|
|
1069
|
+
// remaining resources from being retired.
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
const stopInputOwner = () => {
|
|
1074
|
+
try {
|
|
1075
|
+
if (input && input.readableEnded !== true && input.destroyed !== true) {
|
|
1076
|
+
if (typeof input.destroy === "function") input.destroy();
|
|
1077
|
+
else input.pause?.();
|
|
1078
|
+
}
|
|
1079
|
+
} catch {
|
|
1080
|
+
// Best-effort for non-Node custom input objects.
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
const cancelInputIterator = () => {
|
|
1084
|
+
try {
|
|
1085
|
+
Promise.resolve(inputCancel?.()).catch(() => {});
|
|
1086
|
+
} catch {
|
|
1087
|
+
// A custom async iterator may reject cancellation synchronously.
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
const settleInteractions = () => {
|
|
1091
|
+
interactionCleanupPromise = runBestEffort(() =>
|
|
1092
|
+
interactionCleanup?.(reason),
|
|
1093
|
+
);
|
|
1094
|
+
};
|
|
1095
|
+
const requestStop = () => {
|
|
1096
|
+
if (stopRequested) return;
|
|
1097
|
+
stopRequested = true;
|
|
1098
|
+
stopInputOwner();
|
|
1099
|
+
cancelInputIterator();
|
|
1100
|
+
settleInteractions();
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
return {
|
|
1104
|
+
setReason(nextReason) {
|
|
1105
|
+
if (!stopRequested && !cleanupPromise && nextReason) {
|
|
1106
|
+
reason = String(nextReason);
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
setMcpClient(client) {
|
|
1110
|
+
mcpClient = client || null;
|
|
1111
|
+
},
|
|
1112
|
+
setRemoteApproval(approval) {
|
|
1113
|
+
remoteApproval = approval || null;
|
|
1114
|
+
},
|
|
1115
|
+
setInputCancel(cancel) {
|
|
1116
|
+
inputCancel = typeof cancel === "function" ? cancel : null;
|
|
1117
|
+
if (stopRequested) cancelInputIterator();
|
|
1118
|
+
},
|
|
1119
|
+
setInteractionCleanup(cleanup) {
|
|
1120
|
+
interactionCleanup = typeof cleanup === "function" ? cleanup : null;
|
|
1121
|
+
if (stopRequested) settleInteractions();
|
|
1122
|
+
},
|
|
1123
|
+
setOutputCleanup(cleanup) {
|
|
1124
|
+
outputCleanup = typeof cleanup === "function" ? cleanup : null;
|
|
1125
|
+
},
|
|
1126
|
+
setSessionEnd(cleanup) {
|
|
1127
|
+
sessionEnd = typeof cleanup === "function" ? cleanup : null;
|
|
1128
|
+
},
|
|
1129
|
+
requestStop,
|
|
1130
|
+
cleanup() {
|
|
1131
|
+
if (!cleanupPromise) {
|
|
1132
|
+
cleanupPromise = (async () => {
|
|
1133
|
+
// Stop the live stdin owner before network/process resources. A
|
|
1134
|
+
// flowing stdin iterator can otherwise keep the process alive after
|
|
1135
|
+
// an early return or exception.
|
|
1136
|
+
requestStop();
|
|
1137
|
+
await interactionCleanupPromise;
|
|
1138
|
+
await runBestEffort(() => outputCleanup?.(reason));
|
|
1139
|
+
await runBestEffort(() => mcpClient?.disconnectAll?.());
|
|
1140
|
+
await runBestEffort(() => remoteApproval?.close?.());
|
|
1141
|
+
await runBestEffort(() => sessionEnd?.(reason));
|
|
1142
|
+
})();
|
|
1143
|
+
}
|
|
1144
|
+
return cleanupPromise;
|
|
1145
|
+
},
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1047
1149
|
export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
1048
1150
|
const trustedWorkspaceRoot = options.cwd || process.cwd();
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
);
|
|
1151
|
+
const input = deps.input || process.stdin;
|
|
1152
|
+
const pipeState = { closed: false };
|
|
1153
|
+
const streamCleanup = createHeadlessStreamCleanupScope({ input });
|
|
1154
|
+
const stdout = deps.stdout || process.stdout;
|
|
1155
|
+
const stderr = deps.stderr || process.stderr;
|
|
1156
|
+
const shouldInstallPipeSafety =
|
|
1157
|
+
typeof deps.installPipeSafety === "function" ||
|
|
1158
|
+
(!deps.writeOut && !deps.writeErr);
|
|
1159
|
+
const pipeAbort = shouldInstallPipeSafety ? new AbortController() : null;
|
|
1160
|
+
const managesNativeOutput = !deps.writeOut || !deps.writeErr;
|
|
1161
|
+
const outputAbort = managesNativeOutput ? new AbortController() : null;
|
|
1162
|
+
const handlePipeClosed = () => {
|
|
1163
|
+
if (pipeState.closed) return;
|
|
1164
|
+
pipeState.closed = true;
|
|
1165
|
+
streamCleanup.setReason("pipe_closed");
|
|
1166
|
+
process.exitCode = 0;
|
|
1167
|
+
pipeAbort?.abort();
|
|
1168
|
+
streamCleanup.requestStop();
|
|
1169
|
+
};
|
|
1170
|
+
const outputFlow =
|
|
1171
|
+
deps.outputFlow ||
|
|
1172
|
+
createHeadlessOutputBackpressure({
|
|
1173
|
+
stdout,
|
|
1174
|
+
stderr,
|
|
1175
|
+
writeOut: deps.writeOut,
|
|
1176
|
+
writeErr: deps.writeErr,
|
|
1177
|
+
maxQueuedBytes: deps.outputBackpressureMaxBytes,
|
|
1178
|
+
onFailure: (error) => {
|
|
1179
|
+
outputAbort?.abort(error);
|
|
1180
|
+
if (error?.code === "EPIPE") handlePipeClosed();
|
|
1181
|
+
},
|
|
1182
|
+
});
|
|
1183
|
+
const abortSignals = [
|
|
1184
|
+
options.signal,
|
|
1185
|
+
pipeAbort?.signal,
|
|
1186
|
+
outputAbort?.signal,
|
|
1187
|
+
].filter(Boolean);
|
|
1188
|
+
const runtimeOptions =
|
|
1189
|
+
abortSignals.length === 0
|
|
1190
|
+
? options
|
|
1191
|
+
: {
|
|
1192
|
+
...options,
|
|
1193
|
+
signal:
|
|
1194
|
+
abortSignals.length === 1
|
|
1195
|
+
? abortSignals[0]
|
|
1196
|
+
: AbortSignal.any(abortSignals),
|
|
1197
|
+
};
|
|
1198
|
+
const runtimeDeps = {
|
|
1199
|
+
...deps,
|
|
1200
|
+
writeOut: outputFlow.writeOut,
|
|
1201
|
+
writeErr: outputFlow.writeErr,
|
|
1202
|
+
outputFlow,
|
|
1203
|
+
};
|
|
1204
|
+
const onCallerAbort = () => {
|
|
1205
|
+
streamCleanup.setReason("aborted");
|
|
1206
|
+
streamCleanup.requestStop();
|
|
1207
|
+
};
|
|
1208
|
+
options.signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
1209
|
+
if (options.signal?.aborted) onCallerAbort();
|
|
1210
|
+
const installSafety = deps.installPipeSafety || installPipeSafety;
|
|
1211
|
+
let disposePipeSafety = null;
|
|
1212
|
+
|
|
1213
|
+
let outcome;
|
|
1214
|
+
let failure = null;
|
|
1215
|
+
try {
|
|
1216
|
+
disposePipeSafety = shouldInstallPipeSafety
|
|
1217
|
+
? installSafety([stdout, stderr], handlePipeClosed)
|
|
1218
|
+
: null;
|
|
1219
|
+
|
|
1220
|
+
outcome = await runWithHostHooksV2Workspace(trustedWorkspaceRoot, () =>
|
|
1221
|
+
runAgentHeadlessStreamInWorkspace(
|
|
1222
|
+
runtimeOptions,
|
|
1223
|
+
runtimeDeps,
|
|
1224
|
+
pipeState,
|
|
1225
|
+
streamCleanup,
|
|
1226
|
+
),
|
|
1227
|
+
);
|
|
1228
|
+
} catch (error) {
|
|
1229
|
+
failure = error;
|
|
1230
|
+
} finally {
|
|
1231
|
+
await streamCleanup.cleanup();
|
|
1232
|
+
try {
|
|
1233
|
+
await outputFlow.wait();
|
|
1234
|
+
} catch (error) {
|
|
1235
|
+
failure ||= error;
|
|
1236
|
+
}
|
|
1237
|
+
outputFlow.dispose();
|
|
1238
|
+
options.signal?.removeEventListener("abort", onCallerAbort);
|
|
1239
|
+
disposePipeSafety?.();
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
if (pipeState.closed) {
|
|
1243
|
+
return { ...(outcome || { turns: 0 }), exitCode: 0 };
|
|
1244
|
+
}
|
|
1245
|
+
if (failure) throw failure;
|
|
1246
|
+
return outcome;
|
|
1052
1247
|
}
|
|
1053
1248
|
|
|
1054
|
-
async function runAgentHeadlessStreamInWorkspace(
|
|
1249
|
+
async function runAgentHeadlessStreamInWorkspace(
|
|
1250
|
+
options = {},
|
|
1251
|
+
deps = {},
|
|
1252
|
+
pipeState = { closed: false },
|
|
1253
|
+
streamCleanup,
|
|
1254
|
+
) {
|
|
1055
1255
|
const model = options.model || "qwen2.5:7b";
|
|
1056
1256
|
const provider = options.provider || "ollama";
|
|
1057
1257
|
const baseUrl = options.baseUrl || "http://localhost:11434";
|
|
1058
1258
|
const apiKey = options.apiKey || null;
|
|
1059
|
-
const writeOut = deps.writeOut
|
|
1060
|
-
const writeErr = deps.writeErr
|
|
1061
|
-
if (!deps.writeOut && !deps.writeErr) installPipeSafety();
|
|
1259
|
+
const writeOut = deps.writeOut;
|
|
1260
|
+
const writeErr = deps.writeErr;
|
|
1062
1261
|
|
|
1063
1262
|
const sessionId =
|
|
1064
1263
|
options.sessionId || `headless-stream-${Date.now()}-${process.pid}`;
|
|
@@ -1079,8 +1278,10 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1079
1278
|
fieldGate,
|
|
1080
1279
|
});
|
|
1081
1280
|
const emit = streamCoalescer.emit;
|
|
1281
|
+
streamCleanup.setOutputCleanup(() => streamCoalescer.flush?.());
|
|
1082
1282
|
|
|
1083
1283
|
const hasInjectedSessionStore =
|
|
1284
|
+
typeof deps.sessionHasPersistedEvidence === "function" ||
|
|
1084
1285
|
typeof deps.sessionExists === "function" ||
|
|
1085
1286
|
typeof deps.rebuildMessages === "function" ||
|
|
1086
1287
|
typeof deps.appendEvent === "function" ||
|
|
@@ -1118,7 +1319,10 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1118
1319
|
? jsonlReadVerifiedProjection
|
|
1119
1320
|
: null;
|
|
1120
1321
|
const resumeDependencies = {
|
|
1121
|
-
sessionExists:
|
|
1322
|
+
sessionExists:
|
|
1323
|
+
deps.sessionHasPersistedEvidence ||
|
|
1324
|
+
deps.sessionExists ||
|
|
1325
|
+
jsonlSessionHasPersistedEvidence,
|
|
1122
1326
|
readVerifiedEvents: (...args) =>
|
|
1123
1327
|
requireSynchronousRecoveryResult(
|
|
1124
1328
|
readVerifiedEvents(...args),
|
|
@@ -1293,7 +1497,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1293
1497
|
cwd,
|
|
1294
1498
|
settingsFile: options.settingsFile,
|
|
1295
1499
|
});
|
|
1296
|
-
if (notice)
|
|
1500
|
+
if (notice) writeErr(notice + "\n");
|
|
1297
1501
|
} catch {
|
|
1298
1502
|
/* trust notice is best-effort */
|
|
1299
1503
|
}
|
|
@@ -1334,6 +1538,20 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1334
1538
|
const doExpand = deps.expandFileRefs || expandFileRefsAsync;
|
|
1335
1539
|
const runSessionSlashCommand =
|
|
1336
1540
|
deps.executeSessionSlashCommand || executeSessionSlashCommand;
|
|
1541
|
+
let turns = 0;
|
|
1542
|
+
|
|
1543
|
+
streamCleanup.setSessionEnd(async (reason) => {
|
|
1544
|
+
if (!settingsHooks) return;
|
|
1545
|
+
const runObserveHooks =
|
|
1546
|
+
deps.runObserveHooks ||
|
|
1547
|
+
(await import("../lib/settings-hook-events.js")).runObserveHooks;
|
|
1548
|
+
runObserveHooks(
|
|
1549
|
+
settingsHooks,
|
|
1550
|
+
"SessionEnd",
|
|
1551
|
+
{ reason, cwd, session_id: sessionId },
|
|
1552
|
+
{ cwd },
|
|
1553
|
+
);
|
|
1554
|
+
});
|
|
1337
1555
|
|
|
1338
1556
|
const getApprovalGate =
|
|
1339
1557
|
deps.getApprovalGate ||
|
|
@@ -1388,6 +1606,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1388
1606
|
result: reason,
|
|
1389
1607
|
session_id: sessionId,
|
|
1390
1608
|
});
|
|
1609
|
+
streamCleanup.setReason("blocked");
|
|
1391
1610
|
return { exitCode: 2, turns: 0 };
|
|
1392
1611
|
}
|
|
1393
1612
|
|
|
@@ -1444,11 +1663,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1444
1663
|
(hasInjectedSessionStore ? null : jsonlReadVerifiedProjection),
|
|
1445
1664
|
findLatestEvent: storeFindLatestEvent,
|
|
1446
1665
|
};
|
|
1447
|
-
|
|
1448
|
-
? createSessionMcpLedgerSink(sessionId, {
|
|
1449
|
-
appendEvent: store.appendAuthorityEvent,
|
|
1450
|
-
})
|
|
1451
|
-
: null;
|
|
1666
|
+
let mcpLedgerSink = null;
|
|
1452
1667
|
|
|
1453
1668
|
// ── P0-2: crash-safe side-effect ledger — the stream twin of the
|
|
1454
1669
|
// single-prompt runner (headless-runner.js) and the WS bridge
|
|
@@ -1740,6 +1955,37 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
1740
1955
|
e.code = "USER_TIMEOUT"; // handler → user_timeout (model proceeds, not a failure)
|
|
1741
1956
|
p.reject(e);
|
|
1742
1957
|
};
|
|
1958
|
+
streamCleanup.setInteractionCleanup((reason) => {
|
|
1959
|
+
const via = reason === "pipe_closed" ? "pipe-closed" : "session-closed";
|
|
1960
|
+
for (const [id, pending] of [...pendingApprovals.entries()]) {
|
|
1961
|
+
pendingApprovals.delete(id);
|
|
1962
|
+
clearTimeout(pending.timer);
|
|
1963
|
+
try {
|
|
1964
|
+
emit({
|
|
1965
|
+
type: "approval_resolved",
|
|
1966
|
+
id,
|
|
1967
|
+
approved: false,
|
|
1968
|
+
via,
|
|
1969
|
+
session_id: sessionId,
|
|
1970
|
+
});
|
|
1971
|
+
} catch {
|
|
1972
|
+
// The output pipe may itself be the reason cleanup is running.
|
|
1973
|
+
}
|
|
1974
|
+
pending.resolve(false);
|
|
1975
|
+
}
|
|
1976
|
+
for (const [id, pending] of [...pendingQuestions.entries()]) {
|
|
1977
|
+
pendingQuestions.delete(id);
|
|
1978
|
+
clearTimeout(pending.timer);
|
|
1979
|
+
try {
|
|
1980
|
+
emit({ type: "question_resolved", id, via, session_id: sessionId });
|
|
1981
|
+
} catch {
|
|
1982
|
+
// Best-effort cleanup notification.
|
|
1983
|
+
}
|
|
1984
|
+
const error = new Error(`ask_user_question ${via}`);
|
|
1985
|
+
error.code = "USER_TIMEOUT";
|
|
1986
|
+
pending.reject(error);
|
|
1987
|
+
}
|
|
1988
|
+
});
|
|
1743
1989
|
const interactionAskUser = ({
|
|
1744
1990
|
question,
|
|
1745
1991
|
options: qOptions,
|
|
@@ -2089,6 +2335,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2089
2335
|
loadJetbrainsMcp: deps.loadJetbrainsMcp,
|
|
2090
2336
|
},
|
|
2091
2337
|
);
|
|
2338
|
+
streamCleanup.setMcpClient(mcp?.mcpClient);
|
|
2092
2339
|
// MCP tool search (context scaling): defer big tool schemas behind the
|
|
2093
2340
|
// internal tool_search tool. Below-threshold / disabled → no-op.
|
|
2094
2341
|
if (mcp) {
|
|
@@ -2114,6 +2361,14 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2114
2361
|
}
|
|
2115
2362
|
}
|
|
2116
2363
|
|
|
2364
|
+
mcpLedgerSink = persist
|
|
2365
|
+
? createSessionMcpLedgerSink(
|
|
2366
|
+
sessionId,
|
|
2367
|
+
hasInjectedSessionStore
|
|
2368
|
+
? { appendEvent: store.appendAuthorityEvent }
|
|
2369
|
+
: { recovery: mcpLedgerRecovery },
|
|
2370
|
+
)
|
|
2371
|
+
: null;
|
|
2117
2372
|
const mcpRecoveryRuntime = createMcpHostRecoveryRuntime({
|
|
2118
2373
|
bundle: mcp,
|
|
2119
2374
|
sessionId,
|
|
@@ -2156,7 +2411,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2156
2411
|
});
|
|
2157
2412
|
}
|
|
2158
2413
|
if (mcp?.mcpClient?.setElicitationHandler && interactiveQuestions) {
|
|
2159
|
-
|
|
2414
|
+
const elicitationHandler = async (request) => {
|
|
2160
2415
|
const hookContext = {
|
|
2161
2416
|
schema_version: 1,
|
|
2162
2417
|
server: request.server || null,
|
|
@@ -2214,6 +2469,9 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2214
2469
|
});
|
|
2215
2470
|
throw error;
|
|
2216
2471
|
}
|
|
2472
|
+
};
|
|
2473
|
+
mcp.mcpClient.setElicitationHandler(elicitationHandler, {
|
|
2474
|
+
signal: options.signal || null,
|
|
2217
2475
|
});
|
|
2218
2476
|
}
|
|
2219
2477
|
|
|
@@ -2247,7 +2505,6 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2247
2505
|
is_error: true,
|
|
2248
2506
|
error: err.message,
|
|
2249
2507
|
});
|
|
2250
|
-
if (mcp?.mcpClient) await mcp.mcpClient.disconnectAll().catch(() => {});
|
|
2251
2508
|
return { exitCode: 1, turns: 0 };
|
|
2252
2509
|
}
|
|
2253
2510
|
if (approvalGate && typeof approvalGate.setConfirmer === "function") {
|
|
@@ -2273,11 +2530,14 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2273
2530
|
options.interactiveApprovals !== true
|
|
2274
2531
|
) {
|
|
2275
2532
|
try {
|
|
2276
|
-
const
|
|
2277
|
-
|
|
2278
|
-
|
|
2533
|
+
const startRemoteApproval =
|
|
2534
|
+
deps.startHeadlessRemoteApproval ||
|
|
2535
|
+
(await import("../lib/remote-approval-bridge.js"))
|
|
2536
|
+
.startHeadlessRemoteApproval;
|
|
2537
|
+
_remoteApproval = await startRemoteApproval({
|
|
2279
2538
|
agentSessionId: sessionId,
|
|
2280
2539
|
});
|
|
2540
|
+
streamCleanup.setRemoteApproval(_remoteApproval);
|
|
2281
2541
|
emit({
|
|
2282
2542
|
type: "remote_control",
|
|
2283
2543
|
subtype: "pairing",
|
|
@@ -2414,7 +2674,6 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2414
2674
|
})
|
|
2415
2675
|
: null;
|
|
2416
2676
|
|
|
2417
|
-
let turns = 0;
|
|
2418
2677
|
let sawError = false;
|
|
2419
2678
|
// Session-scoped tool-call correlation ids ("tu-<n>", additive protocol-v1
|
|
2420
2679
|
// field): one counter across ALL turns so ids never repeat within a session.
|
|
@@ -2447,9 +2706,11 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2447
2706
|
let inputDone = false;
|
|
2448
2707
|
let currentAbort = null;
|
|
2449
2708
|
let slashRequestSeq = 0;
|
|
2709
|
+
const inputLines = readJsonLines(input);
|
|
2710
|
+
streamCleanup.setInputCancel(() => inputLines.return?.());
|
|
2450
2711
|
(async () => {
|
|
2451
2712
|
try {
|
|
2452
|
-
for await (const line of
|
|
2713
|
+
for await (const line of inputLines) {
|
|
2453
2714
|
const parsed = parseInputEvent(line);
|
|
2454
2715
|
if (parsed == null) continue;
|
|
2455
2716
|
if (parsed.hello) {
|
|
@@ -2537,15 +2798,25 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
2537
2798
|
const nextEvent = async () => {
|
|
2538
2799
|
for (;;) {
|
|
2539
2800
|
if (queue.length > 0) return queue.shift();
|
|
2540
|
-
if (inputDone) return null;
|
|
2801
|
+
if (inputDone || options.signal?.aborted) return null;
|
|
2541
2802
|
await new Promise((r) => {
|
|
2542
|
-
|
|
2803
|
+
let settled = false;
|
|
2804
|
+
const wake = () => {
|
|
2805
|
+
if (settled) return;
|
|
2806
|
+
settled = true;
|
|
2807
|
+
options.signal?.removeEventListener("abort", wake);
|
|
2808
|
+
if (wakeQueue === wake) wakeQueue = null;
|
|
2809
|
+
r();
|
|
2810
|
+
};
|
|
2811
|
+
wakeQueue = wake;
|
|
2812
|
+
options.signal?.addEventListener("abort", wake, { once: true });
|
|
2813
|
+
if (options.signal?.aborted) wake();
|
|
2543
2814
|
});
|
|
2544
|
-
wakeQueue = null;
|
|
2545
2815
|
}
|
|
2546
2816
|
};
|
|
2547
2817
|
|
|
2548
2818
|
for (;;) {
|
|
2819
|
+
await deps.outputFlow?.wait?.();
|
|
2549
2820
|
const parsed = await nextEvent();
|
|
2550
2821
|
if (parsed == null) break; // stdin closed
|
|
2551
2822
|
if (turnBindingPersistenceError) {
|
|
@@ -3118,6 +3389,7 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
3118
3389
|
sideEffects,
|
|
3119
3390
|
turnNumber: turns,
|
|
3120
3391
|
turnBindingFeed,
|
|
3392
|
+
waitForOutput: deps.outputFlow?.wait,
|
|
3121
3393
|
now: deps.now || Date.now,
|
|
3122
3394
|
},
|
|
3123
3395
|
);
|
|
@@ -3294,41 +3566,19 @@ async function runAgentHeadlessStreamInWorkspace(options = {}, deps = {}) {
|
|
|
3294
3566
|
}
|
|
3295
3567
|
}
|
|
3296
3568
|
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
// server so the stream session's port never outlives the invocation.
|
|
3308
|
-
if (_remoteApproval) {
|
|
3309
|
-
try {
|
|
3310
|
-
await _remoteApproval.close();
|
|
3311
|
-
} catch {
|
|
3312
|
-
// best-effort
|
|
3313
|
-
}
|
|
3314
|
-
}
|
|
3569
|
+
streamCleanup.setReason(
|
|
3570
|
+
pipeState.closed
|
|
3571
|
+
? "pipe_closed"
|
|
3572
|
+
: options.signal?.aborted
|
|
3573
|
+
? "aborted"
|
|
3574
|
+
: inputDone
|
|
3575
|
+
? "stdin_closed"
|
|
3576
|
+
: "completed",
|
|
3577
|
+
);
|
|
3578
|
+
await streamCleanup.cleanup();
|
|
3315
3579
|
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
try {
|
|
3319
|
-
const { runObserveHooks } =
|
|
3320
|
-
await import("../lib/settings-hook-events.js");
|
|
3321
|
-
runObserveHooks(
|
|
3322
|
-
settingsHooks,
|
|
3323
|
-
"SessionEnd",
|
|
3324
|
-
{ reason: "stdin_closed", cwd, session_id: sessionId },
|
|
3325
|
-
{ cwd },
|
|
3326
|
-
);
|
|
3327
|
-
} catch {
|
|
3328
|
-
// observe-only
|
|
3329
|
-
}
|
|
3580
|
+
if (!pipeState.closed) {
|
|
3581
|
+
emit({ type: "system", subtype: "end", session_id: sessionId, turns });
|
|
3330
3582
|
}
|
|
3331
|
-
|
|
3332
|
-
emit({ type: "system", subtype: "end", session_id: sessionId, turns });
|
|
3333
|
-
return { exitCode: sawError ? 1 : 0, turns };
|
|
3583
|
+
return { exitCode: pipeState.closed ? 0 : sawError ? 1 : 0, turns };
|
|
3334
3584
|
}
|