chainlesschain 0.166.46 → 0.166.47
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 +6 -4
- package/package.json +3 -1
- package/src/assets/web-panel/assets/{AIOps-Cp8KiMmv.js → AIOps-CDpT0WXV.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-B4d9BGsm.js → ActionButton-BNfUljWx.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Cf9yXTkv.js → Analytics-C9323DEx.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-40UkmxtP.js → AppLayout-CRrjb2db.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-Ckkb4oOA.js → Artifacts-Db-DGqJS.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Dnf569k5.js → Audit-CJdHRJ0W.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CA6bLem4.js → BackgroundAgents-_RSCnTYs.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-ChQU0I_Q.js → Backup-8GFQi-dM.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BHeZXnNN.js → BaseInput-C87NtgUZ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DcFVYB2E.js → Chat-DcTMWS8G.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-5ZDPTW_H.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-2PDbejv2.js → Checkbox-DM9EmYee.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DJBn1RAu.js → Codegen-M2YqDRNN.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CPRq7n6y.js → Col-oB1LLxyf.js} +1 -1
- package/src/assets/web-panel/assets/{Community-axvINFMi.js → Community-TcVZK5tF.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-_OX4Qbe0.js → Compact-XKmq-3K_.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DWAkvzRL.js → Compliance-C6CBiDRy.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CUIJ25oj.js → Cowork-Dz9CGqXH.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-nR0m7H3_.js → Cron-CxJDgDVL.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CgTLXzh_.js → Crosschain-DMP0JsaQ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BllzRB6Q.js → DID-I5IQeogb.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C9f0IIBN.js → Dashboard-BfLW2MXj.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BkahetiO.js → Dropdown-BK8EjAlh.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-rartVC-k.js → EmailListRenderer-C3iqSv5I.js} +1 -1
- package/src/assets/web-panel/assets/EvolutionSettings-BJmBzpW6.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgUdFvw1.js → FamilyGuardDashboard-T19rnqm-.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-oFpIQU6g.js → Federation-CozrbPMy.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BUH5xlyP.js → FormItemContext-k1dCLNNJ.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-ilRa-ueg.js → GenericCardRenderer-DbaW_Jvt.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DlHHSF8j.js → Git-CQHRyEIt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-yQiiXIWe.js → Governance-BMJYZgMy.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BUDRVGOP.js → Inference-B7mpNU7V.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BaGyIoN1.js → KnowledgeGraph-Br0Blg6B.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C1cO6zE0.js → Logs-HIdk0S6M.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-_z_Iaoes.js → MarkdownRenderer-HxeocBHy.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CM8cGL0K.js → Marketplace-Bkfq69UP.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CDqAMU0U.js → McpTools-dtmx0bHO.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CfB0-Ofv.js → Memory-CrRlOuEf.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BL18ytvB.js → MobileBridge-D4ZIZiAH.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-PIyyxbuJ.js → MobileProjects-C90Rw7GE.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BTTrFCol.js → Mtc-CC6k_uh4.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-JHZn037c.js → MtcAudit-T_CUIYUy.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-CMf9NEdB.js → Multisig-N_e0RRWk.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dhk3qaus.js → NLProgramming-Iq3VzEv0.js} +1 -1
- package/src/assets/web-panel/assets/Notes-B5sKJUJt.js +7 -0
- package/src/assets/web-panel/assets/{NotificationSettings-gxdaVEit.js → NotificationSettings-K8UVp8qQ.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BWNyM-6m.js +1 -0
- package/src/assets/web-panel/assets/{Organization-CzvHcDNO.js → Organization-DMO1NJxI.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Dclx30Vv.js → Overflow-BBY6b31Z.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CM0Wm9vZ.js → P2P-DmsL0y0v.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-fYmQzmTA.js → PdhVaultBrowser-C65AX_RY.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B_oATenG.js → Permissions-CWcpRtWa.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CptiVBh5.js → PersonalDataHub--ZNDIdsn.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DkHzgyyI.js → Pipeline-DCdj5NGb.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzZvwcKh.js → Privacy-BRKu7Q3E.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CzkCs-5G.js → ProjectInit-BJ7ozIAb.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BB8dcxRD.js → ProjectSettings-B2cVLiXW.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-B7PW9CFY.js → Projects-Ce9r_W-p.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Tfx-ti1V.js → Providers-BDespvGZ.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-EvWlNhfX.js → QrScannerModal-BUNO4fDU.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CUspgbNC.js → QuickAsk-D2TUqeBV.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-COY2g77J.js → Recommend-BNNQPHBH.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BzMBU6E6.js → RemoteSession-D2t1V_Cm.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-RtYRF4YP.js → Reputation-DVK5hEqI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Bva3l9Lc.js → Row-BB9RTwmE.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BhjzLvW3.js → RssFeed-DmEO7liZ.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BYzT2PTR.js → Search-UwEYjnDB.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bcl4-KTv.js → Security-DebqSsMp.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BRRa4A0f.js → Services-CuuPts3C.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DYQ016qy.js → Skeleton-DbWpmbgf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CAUKL9JA.js → Skills-BaK7SxzT.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BTyUqfuD.js → Sla-BFHv51Jb.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CUjMihrs.js → SpeechSettings-B9b1R6uK.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CvfOSupr.js → SyncSettings-BnO0CN02.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-EvjNXrWH.js → Tasks-Dy01Vq49.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-wPAp0EoM.js → Templates-BCy2AMHc.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CP0D-q9Q.js → Tenant-4Tx9y_Y1.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CQ0f2iFg.js → Terminal-CPOoUH8J.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D3JrGSPb.js → TimelineRenderer-C85GlJzu.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-yXf2PPp9.js → Tokens-_xneFBGF.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DfmMOoZ2.js → Trigger-BizG4rTr.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BTCyMgf1.js → Trust-Dh8EIn3n.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DKCwIBHi.js → UkeySign-C5NWoHWQ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CQpDSzLO.js → VideoEditing-0YfrySL6.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CyFrzC3K.js → Wallet-BZVH8Ags.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-D6Nr_1kd.js → WebAuthn-kNofa6vm.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-CgR9tNrB.js → WorkflowEditor-BNO34_j0.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CRG_IeyP.js → chat-ifQ2FlwD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-MdE3TStI.js → colors-1TL8H6EH.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B0LRuiNV.js → compact-item-DBfRjs_T.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-B_V5fjcX.js → createContext-Bs6V4iBf.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BHnbnuYL.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DSL-c_hr.js → hasIn-Bz6LMY_0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE7bSYmW.js → index--WvT2Il3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBwBZwio.js → index-84mi5rsv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsAEd-Do.js → index-B5SJCUZ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdHMc9LQ.js → index-B6RClMZl.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3iW-mhn.js → index-BB1Af7Fv.js} +1 -1
- package/src/assets/web-panel/assets/{index-C67dPW0L.js → index-BQL_tldd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpwGsAA-.js → index-BXJXMaZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZICtYJ0.js → index-BhPDhmvN.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbZZ7P_c.js → index-BiZ7Nz5-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Didyuq2Z.js → index-BoCTDcn6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNhWoD6d.js → index-BxqC3LiO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRRY44XP.js → index-C6c0j-Ki.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3pJBTvo.js → index-C7d6QlfR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdplnAS9.js → index-C9QYxq61.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPYshcic.js → index-CBh48_Mh.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkN53KiJ.js → index-CNKHoXWI.js} +1 -1
- package/src/assets/web-panel/assets/{index-OBhlHSMN.js → index-CXVBQ82k.js} +3 -3
- package/src/assets/web-panel/assets/{index-DtOTppk8.js → index-CXtiLagi.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNytQuFq.js → index-Cn7EIWmI.js} +1 -1
- package/src/assets/web-panel/assets/index-CsRz9-ZH.js +1 -0
- package/src/assets/web-panel/assets/{index-BIDCNwy6.js → index-CtB45Hok.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQAsL19t.js → index-Cu_V6ZJH.js} +1 -1
- package/src/assets/web-panel/assets/{index-c8OqO3rq.js → index-Cykt9BbN.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq8-2Ibv.js → index-DDhy4eCS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXMeisJK.js → index-DEPPzM8I.js} +1 -1
- package/src/assets/web-panel/assets/{index-BD0w-888.js → index-DMVktlxG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVDi4rS9.js → index-DOww5Qny.js} +1 -1
- package/src/assets/web-panel/assets/{index-Tg3yl8wc.js → index-DWPp-d07.js} +1 -1
- package/src/assets/web-panel/assets/index-DnjMFf3m.js +1 -0
- package/src/assets/web-panel/assets/{index-DVgTf7CZ.js → index-DvM2xBUA.js} +1 -1
- package/src/assets/web-panel/assets/{index-SmQfEHjp.js → index-EK3XtMxA.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5dqieYX.js → index-XJIV7HEw.js} +1 -1
- package/src/assets/web-panel/assets/{index-0200QxC4.js → index-cNwsev6n.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-aKWR2v.js → index-f_7L9GvP.js} +1 -1
- package/src/assets/web-panel/assets/{index-KaSejHjf.js → index-lUL3bD2z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CS3bOhV7.js → index-pOUFfRdN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEOAZm5j.js → index-rGhS02f8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMm8tO2X.js → index-vHtnQsnV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHp1nSur.js → index-vb1XIxEB.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-P8SBN6Di.js → initDefaultProps-DpRIjwTt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BubbjUT_.js → motion-CG4_9o-Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Chcykv0I.js → move-Dku1fXtf.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DyiYuGDu.js → mtc-parser-BvAVeX-3.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Rdwb_Neb.js → omit-DFu0x78D.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CCr0MYHl.js → pickAttrs-CmI-FNcK.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B1ZXz3bb.js → placementArrow-CGERYewB.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BGEdwej6.js → responsiveObserve-D7G8bF5J.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CpnsUMaT.js → slide-B2sXwWXy.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C7x-TVp_.js → statusUtils-DI5yh0n3.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CC5k_791.js → styleChecker-deGJ5dp_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BpZFKsJW.js → useFlexGapSupport-OqHBXEmi.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CVq5HySy.js → useFs-Dqgx0Qv_.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BGkdLryu.js → usePersonalDataHub-Be-lveh2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-uLtOUEK-.js → vnode-CFxB876W.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BfVC9iUs.js → zoom-BFOYrl4e.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +8 -0
- package/src/commands/background-session.js +31 -3
- package/src/commands/chat.js +5 -1
- package/src/commands/eval.js +86 -28
- package/src/commands/llm.js +104 -1
- package/src/commands/plugin.js +130 -1
- package/src/commands/sandbox.js +121 -2
- package/src/commands/serve.js +11 -2
- package/src/commands/skill.js +29 -0
- package/src/data/changelog.json +13 -0
- package/src/gateways/ws/session-protocol.js +13 -0
- package/src/gateways/ws/ws-agent-handler.js +17 -0
- package/src/gateways/ws/ws-server.js +3 -0
- package/src/gateways/ws/ws-session-state.js +131 -0
- package/src/generated/cc-agent-protocol.schema.json +4 -0
- package/src/lazy-dispatch.js +8 -1
- package/src/lib/agent-sandbox.js +337 -53
- package/src/lib/app-server/cli-agent-kernel-adapter.js +28 -0
- package/src/lib/app-server/server.js +93 -0
- package/src/lib/background-agent-keeper-client.js +2 -0
- package/src/lib/background-agent-keeper-protocol.js +7 -0
- package/src/lib/background-agent-supervisor.js +194 -47
- package/src/lib/codex-app-server-adapter.js +81 -27
- package/src/lib/context-memory-kernel/durable-memory-port.js +31 -8
- package/src/lib/context-memory-kernel/provider-context.js +53 -19
- package/src/lib/deferred-question-context.js +122 -0
- package/src/lib/eval/evidence.js +202 -64
- package/src/lib/eval/plugin-suite.js +917 -0
- package/src/lib/eval/runner.js +10 -3
- package/src/lib/evolution/agent-evolution-runtime-composition.js +236 -1
- package/src/lib/evolution/agent-model-projection.js +97 -1
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +154 -1
- package/src/lib/evolution/evolution-artifact-ports.js +6 -0
- package/src/lib/evolution/evolution-deployment-loader.js +87 -3
- package/src/lib/evolution/evolution-eval-gate.js +8 -0
- package/src/lib/evolution/evolution-eval-runtime-composition.js +255 -0
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +58 -2
- package/src/lib/evolution/evolution-ledger-file-backend.js +23 -2
- package/src/lib/evolution/evolution-ledger-manifest-chain.js +223 -7
- package/src/lib/evolution/evolution-ledger-v2-journal.js +525 -0
- package/src/lib/evolution/evolution-ledger-v2-manifest-backend.js +46 -2
- package/src/lib/evolution/evolution-ledger.js +57 -1
- package/src/lib/evolution/evolution-run-ledger-adapter.js +93 -0
- package/src/lib/evolution/evolution-run-wiki-evidence-resolver.js +259 -0
- package/src/lib/evolution/governed-hub-llm.js +238 -5
- package/src/lib/evolution/governed-hub-resolver.js +82 -4
- package/src/lib/evolution/governed-hub-skill.js +11 -5
- package/src/lib/evolution/governed-skill-synthesis-provider-chat.js +10 -1
- package/src/lib/evolution/skill-runtime-revalidation-ledger-adapter.js +254 -0
- package/src/lib/evolution/skill-runtime-revalidation.js +530 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +4 -4
- package/src/lib/evolution/wiki-evidence-commit-guard.js +366 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +13 -1
- package/src/lib/goal-context.js +14 -5
- package/src/lib/interaction-adapter.js +166 -1
- package/src/lib/model-capabilities.js +271 -0
- package/src/lib/model-context-catalog.js +105 -0
- package/src/lib/model-context-window.js +4 -49
- package/src/lib/openai-responses.js +428 -0
- package/src/lib/plugin-runtime/scopes.js +7 -1
- package/src/lib/remote-read-loop-guard.js +2 -2
- package/src/lib/runtime-usage-ledger.js +16 -0
- package/src/lib/skill-loader.js +12 -0
- package/src/lib/with-file-lock.js +3 -1
- package/src/repl/agent-repl.js +5 -1
- package/src/runtime/agent-core.js +348 -23
- package/src/runtime/agent-runtime.js +7 -0
- package/src/runtime/coding-agent-contract-shared.cjs +13 -1
- package/src/runtime/headless-runner.js +4 -1
- package/src/runtime/headless-stream.js +133 -44
- package/src/runtime/runtime-factory.js +26 -2
- package/src/workers/background-agent-keeper.js +23 -13
- package/src/workers/background-agent-worker.js +27 -13
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Bi2SY9E_.js +0 -1
- package/src/assets/web-panel/assets/EvolutionSettings-BqpG3XHV.js +0 -1
- package/src/assets/web-panel/assets/Notes-6F8EarNN.js +0 -7
- package/src/assets/web-panel/assets/OrderTableRenderer-gVgXQWdc.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BtFLt3qI.js +0 -1
- package/src/assets/web-panel/assets/index-BhuWQHeG.js +0 -1
- package/src/assets/web-panel/assets/index-D-4tFek3.js +0 -1
|
@@ -2,6 +2,7 @@ import { PassThrough } from "node:stream";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import {
|
|
4
4
|
assertSandboxAvailable,
|
|
5
|
+
assertSandboxCapabilities,
|
|
5
6
|
normalizeAgentSandboxMode,
|
|
6
7
|
} from "../agent-sandbox.js";
|
|
7
8
|
|
|
@@ -127,6 +128,7 @@ export class CliAgentKernelAdapter {
|
|
|
127
128
|
},
|
|
128
129
|
},
|
|
129
130
|
);
|
|
131
|
+
assertSandboxCapabilities(sandbox);
|
|
130
132
|
assertSandboxAvailable(sandbox);
|
|
131
133
|
|
|
132
134
|
const input = new PassThrough();
|
|
@@ -166,6 +168,26 @@ export class CliAgentKernelAdapter {
|
|
|
166
168
|
binding: event.binding,
|
|
167
169
|
});
|
|
168
170
|
}
|
|
171
|
+
if (event.type === "question_request") {
|
|
172
|
+
const answerQuestion = async () => {
|
|
173
|
+
let answer = null;
|
|
174
|
+
try {
|
|
175
|
+
answer = await current.requestQuestion(event);
|
|
176
|
+
} catch {
|
|
177
|
+
// A missing/rejecting host is cancellation, never implicit consent.
|
|
178
|
+
}
|
|
179
|
+
writeLine(input, {
|
|
180
|
+
type: "answer",
|
|
181
|
+
id: event.id,
|
|
182
|
+
answer,
|
|
183
|
+
binding: event.binding,
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
// The Headless runtime owns blocking semantics and its timeout. Keep
|
|
187
|
+
// the transport event chain free so a timed-out question can emit
|
|
188
|
+
// question_resolved/result even while a slow host request is pending.
|
|
189
|
+
void answerQuestion().catch(() => {});
|
|
190
|
+
}
|
|
169
191
|
if (event.type === "result") {
|
|
170
192
|
session.current = null;
|
|
171
193
|
current.resolve(event);
|
|
@@ -194,6 +216,7 @@ export class CliAgentKernelAdapter {
|
|
|
194
216
|
permissionMode,
|
|
195
217
|
sandbox,
|
|
196
218
|
interactiveApprovals: true,
|
|
219
|
+
interactiveQuestions: turnOptions.interactiveQuestions === true,
|
|
197
220
|
includePartialMessages: true,
|
|
198
221
|
ephemeral: false,
|
|
199
222
|
evolutionIngress:
|
|
@@ -263,6 +286,7 @@ export class CliAgentKernelAdapter {
|
|
|
263
286
|
options = {},
|
|
264
287
|
emit,
|
|
265
288
|
requestApproval,
|
|
289
|
+
requestQuestion,
|
|
266
290
|
}) {
|
|
267
291
|
const session = await this._session(threadId, options);
|
|
268
292
|
if (session.current) {
|
|
@@ -283,6 +307,10 @@ export class CliAgentKernelAdapter {
|
|
|
283
307
|
turnId,
|
|
284
308
|
emit,
|
|
285
309
|
requestApproval,
|
|
310
|
+
requestQuestion:
|
|
311
|
+
typeof requestQuestion === "function"
|
|
312
|
+
? requestQuestion
|
|
313
|
+
: async () => null,
|
|
286
314
|
resolve,
|
|
287
315
|
reject,
|
|
288
316
|
};
|
|
@@ -10,6 +10,7 @@ import { AppServerGraphRuntime } from "./graph-runtime.js";
|
|
|
10
10
|
import { captureAgentSkillOutcomeIndex } from "../evolution/agent-evolution-runtime-composition-brand.js";
|
|
11
11
|
import { captureSkillVectorAuthority } from "../skill-vector-authority.js";
|
|
12
12
|
import { captureSkillRetrievalRevocationReader } from "../evolution/skill-retrieval-revocation-authority.js";
|
|
13
|
+
import { sameInteractionBinding } from "../interaction-binding.js";
|
|
13
14
|
import { compileGraphDefinition } from "../graph-kernel/compiler.js";
|
|
14
15
|
import { createCliContextMemoryRuntime } from "../context-memory-kernel/runtime.js";
|
|
15
16
|
import { isEvolutionWorkbenchCliHost } from "../evolution/evolution-workbench-cli-host.js";
|
|
@@ -882,6 +883,10 @@ export class CcAppServer {
|
|
|
882
883
|
turnOptions.skillRetrievalRevocationReader =
|
|
883
884
|
skillRetrievalRevocationReader;
|
|
884
885
|
}
|
|
886
|
+
if (this.negotiated) {
|
|
887
|
+
turnOptions.interactiveQuestions =
|
|
888
|
+
this.negotiated.features.includes("deferred_questions");
|
|
889
|
+
}
|
|
885
890
|
const result = await this.kernel.startTurn({
|
|
886
891
|
threadId,
|
|
887
892
|
turnId: attempt.id,
|
|
@@ -896,6 +901,7 @@ export class CcAppServer {
|
|
|
896
901
|
event,
|
|
897
902
|
}),
|
|
898
903
|
requestApproval: (event) => this._requestApproval(turn, event),
|
|
904
|
+
requestQuestion: (event) => this._requestQuestion(turn, event),
|
|
899
905
|
});
|
|
900
906
|
const failed = result?.is_error === true || result?.subtype === "error";
|
|
901
907
|
const output = typeof result?.result === "string" ? result.result : "";
|
|
@@ -1137,6 +1143,8 @@ export class CcAppServer {
|
|
|
1137
1143
|
turnOptions.skillRetrievalRevocationReader =
|
|
1138
1144
|
this.skillRetrievalRevocationReader;
|
|
1139
1145
|
}
|
|
1146
|
+
turnOptions.interactiveQuestions =
|
|
1147
|
+
this.negotiated?.features.includes("deferred_questions") === true;
|
|
1140
1148
|
const result = await this.kernel.startTurn({
|
|
1141
1149
|
threadId: turn.threadId,
|
|
1142
1150
|
turnId: turn.id,
|
|
@@ -1144,6 +1152,7 @@ export class CcAppServer {
|
|
|
1144
1152
|
options: turnOptions,
|
|
1145
1153
|
emit: (event) => this._emitKernelEvent(turn, event),
|
|
1146
1154
|
requestApproval: (event) => this._requestApproval(turn, event),
|
|
1155
|
+
requestQuestion: (event) => this._requestQuestion(turn, event),
|
|
1147
1156
|
});
|
|
1148
1157
|
if (turn.interruptRequested) {
|
|
1149
1158
|
await this._completeTurn(turn, "interrupted", result);
|
|
@@ -1321,6 +1330,48 @@ export class CcAppServer {
|
|
|
1321
1330
|
);
|
|
1322
1331
|
return;
|
|
1323
1332
|
}
|
|
1333
|
+
if (event?.type === "question_request") {
|
|
1334
|
+
if (!this.negotiated?.features.includes("deferred_questions")) return;
|
|
1335
|
+
const blocking = event.blocking !== false && event.mode !== "deferred";
|
|
1336
|
+
if (blocking) turn.status = "waiting_input";
|
|
1337
|
+
turn.revision += 1;
|
|
1338
|
+
await this._notify(
|
|
1339
|
+
"question/requested",
|
|
1340
|
+
{ request: this._questionRequest(turn, event) },
|
|
1341
|
+
{
|
|
1342
|
+
threadId: turn.threadId,
|
|
1343
|
+
turnId: turn.id,
|
|
1344
|
+
itemId: `${turn.id}:question:${safeId(event.id, "question")}`,
|
|
1345
|
+
traceId,
|
|
1346
|
+
idempotencyKey: `question-requested:${turn.id}:${event.id}`,
|
|
1347
|
+
},
|
|
1348
|
+
);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (event?.type === "question_resolved") {
|
|
1352
|
+
if (!this.negotiated?.features.includes("deferred_questions")) return;
|
|
1353
|
+
if (event.blocking !== false && event.mode !== "deferred") {
|
|
1354
|
+
turn.status = "running";
|
|
1355
|
+
}
|
|
1356
|
+
turn.revision += 1;
|
|
1357
|
+
await this._notify(
|
|
1358
|
+
"question/resolved",
|
|
1359
|
+
{
|
|
1360
|
+
threadId: turn.threadId,
|
|
1361
|
+
turnId: turn.id,
|
|
1362
|
+
questionId: safeId(event.id, `${turn.id}:question`),
|
|
1363
|
+
mode: event.mode === "deferred" ? "deferred" : "blocking",
|
|
1364
|
+
via: event.via || "unknown",
|
|
1365
|
+
},
|
|
1366
|
+
{
|
|
1367
|
+
threadId: turn.threadId,
|
|
1368
|
+
turnId: turn.id,
|
|
1369
|
+
traceId,
|
|
1370
|
+
idempotencyKey: `question-resolved:${turn.id}:${event.id}:${event.via}`,
|
|
1371
|
+
},
|
|
1372
|
+
);
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1324
1375
|
if (event?.type === "plan_update") {
|
|
1325
1376
|
await this._notify(
|
|
1326
1377
|
"item/completed",
|
|
@@ -1394,6 +1445,48 @@ export class CcAppServer {
|
|
|
1394
1445
|
return result;
|
|
1395
1446
|
}
|
|
1396
1447
|
|
|
1448
|
+
_questionRequest(turn, event) {
|
|
1449
|
+
const id = safeId(event.id, `${turn.id}:question`);
|
|
1450
|
+
return {
|
|
1451
|
+
id,
|
|
1452
|
+
threadId: turn.threadId,
|
|
1453
|
+
turnId: turn.id,
|
|
1454
|
+
binding: event.binding || null,
|
|
1455
|
+
question: String(event.question || "").slice(0, 16_384),
|
|
1456
|
+
options: Array.isArray(event.options)
|
|
1457
|
+
? event.options.slice(0, 128)
|
|
1458
|
+
: null,
|
|
1459
|
+
multiSelect: event.multiSelect === true,
|
|
1460
|
+
mode: event.mode === "deferred" ? "deferred" : "blocking",
|
|
1461
|
+
blocking: event.blocking !== false && event.mode !== "deferred",
|
|
1462
|
+
purpose: event.purpose || "decision",
|
|
1463
|
+
contextRevision: Number.isSafeInteger(event.context_revision)
|
|
1464
|
+
? event.context_revision
|
|
1465
|
+
: null,
|
|
1466
|
+
expiresAt: new Date(this.now() + this.requestTimeoutMs).toISOString(),
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
async _requestQuestion(turn, event) {
|
|
1471
|
+
if (!this.negotiated?.features.includes("deferred_questions")) return null;
|
|
1472
|
+
const request = this._questionRequest(turn, event);
|
|
1473
|
+
const result = requireObject(
|
|
1474
|
+
await this._requestClient("question/answer", { request }),
|
|
1475
|
+
"question answer",
|
|
1476
|
+
);
|
|
1477
|
+
if (
|
|
1478
|
+
result.questionId !== request.id ||
|
|
1479
|
+
!request.binding ||
|
|
1480
|
+
!sameInteractionBinding(request.binding, result.binding)
|
|
1481
|
+
) {
|
|
1482
|
+
throw new JsonRpcError(
|
|
1483
|
+
JSON_RPC_ERROR.INVALID_PARAMS,
|
|
1484
|
+
"client returned an invalid or stale question answer",
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
return Object.hasOwn(result, "answer") ? result.answer : null;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1397
1490
|
async _requestHumanTask({ task }) {
|
|
1398
1491
|
const result = await this._requestClient("humanTask/decide", { task });
|
|
1399
1492
|
const response = requireObject(result, "humanTask decision");
|
|
@@ -4,6 +4,7 @@ import { createNdjsonReader } from "./background-session-transport.js";
|
|
|
4
4
|
import {
|
|
5
5
|
BACKGROUND_AGENT_KEEPER_ARM,
|
|
6
6
|
BACKGROUND_AGENT_KEEPER_ARMED,
|
|
7
|
+
BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS,
|
|
7
8
|
BACKGROUND_AGENT_KEEPER_HELLO,
|
|
8
9
|
BACKGROUND_AGENT_KEEPER_HEARTBEAT,
|
|
9
10
|
BACKGROUND_AGENT_KEEPER_HEARTBEAT_INTERVAL_MS,
|
|
@@ -244,6 +245,7 @@ export async function connectBackgroundAgentKeeper(options = {}) {
|
|
|
244
245
|
BACKGROUND_AGENT_KEEPER_ARM,
|
|
245
246
|
BACKGROUND_AGENT_KEEPER_ARMED,
|
|
246
247
|
normalized,
|
|
248
|
+
BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS,
|
|
247
249
|
);
|
|
248
250
|
activeTurn = normalized;
|
|
249
251
|
return normalized;
|
|
@@ -50,6 +50,13 @@ export const BACKGROUND_AGENT_KEEPER_IDENTITY_PROBE_TIMEOUT_MS =
|
|
|
50
50
|
export const BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS = 5_000;
|
|
51
51
|
export const BACKGROUND_AGENT_KEEPER_PERSIST_RETRY_TIMEOUT_MS =
|
|
52
52
|
3 * BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS;
|
|
53
|
+
// ARM durably binds a newly spawned turn. It can contend with a strict state
|
|
54
|
+
// lock and, on Windows, an incumbent identity probe. Keep this deadline
|
|
55
|
+
// independent from short HELLO requests and long destructive RETIRE cleanup.
|
|
56
|
+
export const BACKGROUND_AGENT_KEEPER_ARM_TIMEOUT_MS =
|
|
57
|
+
BACKGROUND_AGENT_KEEPER_IDENTITY_PROBE_TIMEOUT_MS +
|
|
58
|
+
BACKGROUND_AGENT_KEEPER_STATE_LOCK_TIMEOUT_MS +
|
|
59
|
+
10_000;
|
|
53
60
|
// A 20-Agent macOS formal run can leave successfully SIGKILLed process groups
|
|
54
61
|
// observable for several seconds while launchd reaps their orphaned leaders.
|
|
55
62
|
// Two seconds made that bounded kernel/reaper delay look like an escaped tree.
|
|
@@ -63,6 +63,8 @@ import {
|
|
|
63
63
|
|
|
64
64
|
export const DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
|
|
65
65
|
export const DEFAULT_HEARTBEAT_STALE_MS = 120000;
|
|
66
|
+
export const DEFAULT_BACKGROUND_AGENT_PAGE_LIMIT = 50;
|
|
67
|
+
export const MAX_BACKGROUND_AGENT_PAGE_LIMIT = 200;
|
|
66
68
|
|
|
67
69
|
/**
|
|
68
70
|
* Pid identity tolerance (Gap 1: OS pid reuse). A pid alone does not identify
|
|
@@ -1370,7 +1372,14 @@ export function mutateBackgroundAgentState(id, updater, options = {}) {
|
|
|
1370
1372
|
// A live numeric pid can belong to a later process after the lock owner
|
|
1371
1373
|
// was killed. Use the lock acquisition timestamp as a one-sided identity
|
|
1372
1374
|
// fence so only an owner which existed before acquisition still blocks.
|
|
1373
|
-
|
|
1375
|
+
// Periodic telemetry may request a strict try-lock. In that mode an
|
|
1376
|
+
// incumbent is deliberately retained without a Windows PID/start-time
|
|
1377
|
+
// probe: a heartbeat must never synchronously stall a control channel
|
|
1378
|
+
// merely to determine whether it could reclaim a lock.
|
|
1379
|
+
_isOwnerAlive:
|
|
1380
|
+
options.probeLockOwner === false
|
|
1381
|
+
? () => true
|
|
1382
|
+
: isBackgroundAgentStateLockOwnerAlive,
|
|
1374
1383
|
},
|
|
1375
1384
|
);
|
|
1376
1385
|
}
|
|
@@ -1458,57 +1467,65 @@ export async function deliverBackgroundNeedsInputNotification(
|
|
|
1458
1467
|
* the only authority to start or continue a turn: a terminal, deleted,
|
|
1459
1468
|
* corrupt, differently-generated or already-owned record is never revived.
|
|
1460
1469
|
*/
|
|
1461
|
-
export function claimBackgroundAgentHeartbeat(
|
|
1470
|
+
export function claimBackgroundAgentHeartbeat(
|
|
1471
|
+
id,
|
|
1472
|
+
heartbeat = {},
|
|
1473
|
+
options = {},
|
|
1474
|
+
) {
|
|
1462
1475
|
const workerPid = Number(heartbeat.workerPid ?? heartbeat.pid);
|
|
1463
1476
|
const workerGeneration = heartbeat.workerGeneration;
|
|
1464
1477
|
if (!Number.isInteger(workerPid) || workerPid <= 0) {
|
|
1465
1478
|
throw new Error(`Invalid background worker pid: ${heartbeat.workerPid}`);
|
|
1466
1479
|
}
|
|
1467
|
-
return mutateBackgroundAgentState(
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
current.
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
current.workerClaimedPid
|
|
1479
|
-
|
|
1480
|
-
claimedWorkerPid > 0 &&
|
|
1481
|
-
claimedWorkerPid !== workerPid
|
|
1482
|
-
) {
|
|
1483
|
-
return null;
|
|
1484
|
-
}
|
|
1485
|
-
const currentWorkerPid = Number(current.workerPid ?? current.pid);
|
|
1486
|
-
if (
|
|
1487
|
-
!current.workerGeneration &&
|
|
1488
|
-
Number.isInteger(currentWorkerPid) &&
|
|
1489
|
-
currentWorkerPid > 0 &&
|
|
1490
|
-
currentWorkerPid !== workerPid &&
|
|
1491
|
-
current.launchFinalizationUncertain !== true
|
|
1492
|
-
) {
|
|
1493
|
-
return null;
|
|
1494
|
-
}
|
|
1495
|
-
return {
|
|
1496
|
-
...current,
|
|
1497
|
-
...heartbeat,
|
|
1498
|
-
id,
|
|
1499
|
-
pid: workerPid,
|
|
1500
|
-
workerPid,
|
|
1501
|
-
workerClaimedPid:
|
|
1480
|
+
return mutateBackgroundAgentState(
|
|
1481
|
+
id,
|
|
1482
|
+
(current) => {
|
|
1483
|
+
if (!current || current.status !== "running") return null;
|
|
1484
|
+
if (current.stopRequestedAt) return null;
|
|
1485
|
+
if (
|
|
1486
|
+
current.workerGeneration &&
|
|
1487
|
+
current.workerGeneration !== workerGeneration
|
|
1488
|
+
) {
|
|
1489
|
+
return null;
|
|
1490
|
+
}
|
|
1491
|
+
const claimedWorkerPid = Number(current.workerClaimedPid);
|
|
1492
|
+
if (
|
|
1502
1493
|
current.workerClaimedPid != null &&
|
|
1503
1494
|
Number.isInteger(claimedWorkerPid) &&
|
|
1504
|
-
claimedWorkerPid > 0
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1495
|
+
claimedWorkerPid > 0 &&
|
|
1496
|
+
claimedWorkerPid !== workerPid
|
|
1497
|
+
) {
|
|
1498
|
+
return null;
|
|
1499
|
+
}
|
|
1500
|
+
const currentWorkerPid = Number(current.workerPid ?? current.pid);
|
|
1501
|
+
if (
|
|
1502
|
+
!current.workerGeneration &&
|
|
1503
|
+
Number.isInteger(currentWorkerPid) &&
|
|
1504
|
+
currentWorkerPid > 0 &&
|
|
1505
|
+
currentWorkerPid !== workerPid &&
|
|
1506
|
+
current.launchFinalizationUncertain !== true
|
|
1507
|
+
) {
|
|
1508
|
+
return null;
|
|
1509
|
+
}
|
|
1510
|
+
return {
|
|
1511
|
+
...current,
|
|
1512
|
+
...heartbeat,
|
|
1513
|
+
id,
|
|
1514
|
+
pid: workerPid,
|
|
1515
|
+
workerPid,
|
|
1516
|
+
workerClaimedPid:
|
|
1517
|
+
current.workerClaimedPid != null &&
|
|
1518
|
+
Number.isInteger(claimedWorkerPid) &&
|
|
1519
|
+
claimedWorkerPid > 0
|
|
1520
|
+
? claimedWorkerPid
|
|
1521
|
+
: workerPid,
|
|
1522
|
+
workerClaimedAt: current.workerClaimedAt || Date.now(),
|
|
1523
|
+
status: "running",
|
|
1524
|
+
heartbeatAt: heartbeat.heartbeatAt ?? Date.now(),
|
|
1525
|
+
};
|
|
1526
|
+
},
|
|
1527
|
+
options,
|
|
1528
|
+
);
|
|
1512
1529
|
}
|
|
1513
1530
|
|
|
1514
1531
|
function deleteBackgroundAgentState(id, predicate = () => true) {
|
|
@@ -2038,7 +2055,21 @@ export function effectiveBackgroundAgentState(state, options = {}) {
|
|
|
2038
2055
|
return next;
|
|
2039
2056
|
}
|
|
2040
2057
|
|
|
2041
|
-
|
|
2058
|
+
function backgroundAgentStartedAt(state) {
|
|
2059
|
+
const startedAt = Number(state?.startedAt);
|
|
2060
|
+
return Number.isFinite(startedAt) && startedAt >= 0 ? startedAt : 0;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
function compareBackgroundAgentListEntries(a, b) {
|
|
2064
|
+
const newestFirst = backgroundAgentStartedAt(b) - backgroundAgentStartedAt(a);
|
|
2065
|
+
if (newestFirst !== 0) return newestFirst;
|
|
2066
|
+
return String(a.id).localeCompare(String(b.id));
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
function listBackgroundAgentEntries(
|
|
2070
|
+
options = {},
|
|
2071
|
+
{ stableTieBreak = false } = {},
|
|
2072
|
+
) {
|
|
2042
2073
|
return (
|
|
2043
2074
|
readdirSync(backgroundAgentsDir())
|
|
2044
2075
|
.filter((name) => name.endsWith(".json") && !name.includes(".job."))
|
|
@@ -2046,7 +2077,11 @@ export function listBackgroundAgents(options = {}) {
|
|
|
2046
2077
|
.filter(Boolean)
|
|
2047
2078
|
.map((state) => effectiveBackgroundAgentState(state, options))
|
|
2048
2079
|
.filter((state) => options.all || state.status === "running")
|
|
2049
|
-
.sort(
|
|
2080
|
+
.sort(
|
|
2081
|
+
stableTieBreak
|
|
2082
|
+
? compareBackgroundAgentListEntries
|
|
2083
|
+
: (a, b) => (b.startedAt || 0) - (a.startedAt || 0),
|
|
2084
|
+
)
|
|
2050
2085
|
// Display-only enrichment: attach the canonical unified lifecycle state.
|
|
2051
2086
|
// This is a list feed (never written back to disk), so the derived field
|
|
2052
2087
|
// cannot leak into the on-disk schema the way it would in the mutate paths.
|
|
@@ -2054,6 +2089,118 @@ export function listBackgroundAgents(options = {}) {
|
|
|
2054
2089
|
);
|
|
2055
2090
|
}
|
|
2056
2091
|
|
|
2092
|
+
function normalizeBackgroundAgentPageLimit(value) {
|
|
2093
|
+
if (value === undefined || value === null) {
|
|
2094
|
+
return DEFAULT_BACKGROUND_AGENT_PAGE_LIMIT;
|
|
2095
|
+
}
|
|
2096
|
+
const limit =
|
|
2097
|
+
typeof value === "string" && /^\d+$/u.test(value) ? Number(value) : value;
|
|
2098
|
+
if (
|
|
2099
|
+
!Number.isSafeInteger(limit) ||
|
|
2100
|
+
limit < 1 ||
|
|
2101
|
+
limit > MAX_BACKGROUND_AGENT_PAGE_LIMIT
|
|
2102
|
+
) {
|
|
2103
|
+
throw new TypeError(
|
|
2104
|
+
`background agent page limit must be an integer from 1 to ${MAX_BACKGROUND_AGENT_PAGE_LIMIT}`,
|
|
2105
|
+
);
|
|
2106
|
+
}
|
|
2107
|
+
return limit;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
function encodeBackgroundAgentPageCursor(state, all) {
|
|
2111
|
+
const payload = JSON.stringify({
|
|
2112
|
+
version: 1,
|
|
2113
|
+
all: all === true,
|
|
2114
|
+
startedAt: backgroundAgentStartedAt(state),
|
|
2115
|
+
id: safeId(state?.id),
|
|
2116
|
+
});
|
|
2117
|
+
return `bg1.${Buffer.from(payload).toString("base64url")}`;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
function decodeBackgroundAgentPageCursor(value) {
|
|
2121
|
+
if (value === undefined || value === null) return null;
|
|
2122
|
+
if (
|
|
2123
|
+
typeof value !== "string" ||
|
|
2124
|
+
value.length > 768 ||
|
|
2125
|
+
!/^bg1\.[A-Za-z0-9_-]+$/u.test(value)
|
|
2126
|
+
) {
|
|
2127
|
+
throw new TypeError("background agent page cursor is invalid");
|
|
2128
|
+
}
|
|
2129
|
+
let payload;
|
|
2130
|
+
try {
|
|
2131
|
+
const encoded = value.slice(4);
|
|
2132
|
+
const decoded = Buffer.from(encoded, "base64url");
|
|
2133
|
+
if (decoded.toString("base64url") !== encoded) {
|
|
2134
|
+
throw new Error("cursor encoding is not canonical");
|
|
2135
|
+
}
|
|
2136
|
+
payload = JSON.parse(decoded.toString("utf8"));
|
|
2137
|
+
} catch {
|
|
2138
|
+
throw new TypeError("background agent page cursor is invalid");
|
|
2139
|
+
}
|
|
2140
|
+
if (
|
|
2141
|
+
!payload ||
|
|
2142
|
+
typeof payload !== "object" ||
|
|
2143
|
+
Array.isArray(payload) ||
|
|
2144
|
+
Object.keys(payload).length !== 4 ||
|
|
2145
|
+
payload.version !== 1 ||
|
|
2146
|
+
typeof payload.all !== "boolean" ||
|
|
2147
|
+
!Number.isSafeInteger(payload.startedAt) ||
|
|
2148
|
+
payload.startedAt < 0
|
|
2149
|
+
) {
|
|
2150
|
+
throw new TypeError("background agent page cursor is invalid");
|
|
2151
|
+
}
|
|
2152
|
+
let id;
|
|
2153
|
+
try {
|
|
2154
|
+
id = safeId(payload.id);
|
|
2155
|
+
} catch {
|
|
2156
|
+
throw new TypeError("background agent page cursor is invalid");
|
|
2157
|
+
}
|
|
2158
|
+
return { all: payload.all, startedAt: payload.startedAt, id };
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
function isBackgroundAgentAfterCursor(state, cursor) {
|
|
2162
|
+
const startedAt = backgroundAgentStartedAt(state);
|
|
2163
|
+
if (startedAt !== cursor.startedAt) return startedAt < cursor.startedAt;
|
|
2164
|
+
return String(state.id).localeCompare(cursor.id) > 0;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
/**
|
|
2168
|
+
* Return one stable, bounded page from the newest-first background session
|
|
2169
|
+
* feed. The cursor is an opaque ordering fence, not an authority token.
|
|
2170
|
+
*
|
|
2171
|
+
* State files are still read to preserve the current authoritative lifecycle
|
|
2172
|
+
* reconciliation. A future read-only index may reduce that I/O, but this API
|
|
2173
|
+
* immediately bounds the object graph and protocol response retained by a
|
|
2174
|
+
* caller.
|
|
2175
|
+
*/
|
|
2176
|
+
export function listBackgroundAgentsPage(options = {}) {
|
|
2177
|
+
const limit = normalizeBackgroundAgentPageLimit(options.limit);
|
|
2178
|
+
const cursor = decodeBackgroundAgentPageCursor(options.cursor);
|
|
2179
|
+
if (cursor && cursor.all !== (options.all === true)) {
|
|
2180
|
+
throw new TypeError(
|
|
2181
|
+
"background agent page cursor does not match the requested filter",
|
|
2182
|
+
);
|
|
2183
|
+
}
|
|
2184
|
+
const eligible = cursor
|
|
2185
|
+
? listBackgroundAgentEntries(options, { stableTieBreak: true }).filter(
|
|
2186
|
+
(state) => isBackgroundAgentAfterCursor(state, cursor),
|
|
2187
|
+
)
|
|
2188
|
+
: listBackgroundAgentEntries(options, { stableTieBreak: true });
|
|
2189
|
+
const sessions = eligible.slice(0, limit);
|
|
2190
|
+
const nextCursor =
|
|
2191
|
+
eligible.length > sessions.length
|
|
2192
|
+
? encodeBackgroundAgentPageCursor(sessions.at(-1), options.all)
|
|
2193
|
+
: null;
|
|
2194
|
+
return Object.freeze({
|
|
2195
|
+
sessions: Object.freeze(sessions),
|
|
2196
|
+
nextCursor,
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
export function listBackgroundAgents(options = {}) {
|
|
2201
|
+
return listBackgroundAgentEntries(options);
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2057
2204
|
function sleepSyncMs(ms) {
|
|
2058
2205
|
try {
|
|
2059
2206
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
@@ -66,18 +66,40 @@ function projectNotification(notification) {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
if (method === "turn/completed" || method === "turn/failed") {
|
|
69
|
-
const
|
|
69
|
+
const turn = params.turn || {};
|
|
70
|
+
const reportedStatus =
|
|
71
|
+
method === "turn/failed" ? "failed" : String(turn.status || "");
|
|
72
|
+
const terminalStatus = ["completed", "failed", "interrupted"].includes(
|
|
73
|
+
reportedStatus,
|
|
74
|
+
)
|
|
75
|
+
? reportedStatus
|
|
76
|
+
: "failed";
|
|
77
|
+
const protocolError =
|
|
78
|
+
terminalStatus === "failed" && reportedStatus !== "failed"
|
|
79
|
+
? {
|
|
80
|
+
code: "CC_CODEX_APP_SERVER_INVALID_TERMINAL_STATUS",
|
|
81
|
+
message:
|
|
82
|
+
"Codex App Server emitted turn/completed without a supported terminal status",
|
|
83
|
+
}
|
|
84
|
+
: null;
|
|
85
|
+
const terminalError =
|
|
86
|
+
terminalStatus === "failed"
|
|
87
|
+
? turn.error ||
|
|
88
|
+
params.error ||
|
|
89
|
+
protocolError ||
|
|
90
|
+
"Codex App Server turn failed"
|
|
91
|
+
: turn.error || params.error || null;
|
|
70
92
|
return {
|
|
71
93
|
method: "turn/completed",
|
|
72
94
|
params: {
|
|
73
95
|
turn: {
|
|
74
|
-
...
|
|
75
|
-
status:
|
|
96
|
+
...turn,
|
|
97
|
+
status: terminalStatus,
|
|
76
98
|
},
|
|
77
99
|
},
|
|
78
|
-
terminal:
|
|
79
|
-
error:
|
|
80
|
-
usage: params.usage || null,
|
|
100
|
+
terminal: terminalStatus,
|
|
101
|
+
error: terminalError,
|
|
102
|
+
usage: params.usage || turn.usage || null,
|
|
81
103
|
};
|
|
82
104
|
}
|
|
83
105
|
return { unknownMethod: String(method || "<missing>") };
|
|
@@ -138,6 +160,10 @@ export class CodexAppServerAdapter extends EventEmitter {
|
|
|
138
160
|
const notifications = [];
|
|
139
161
|
const unknownMethods = new Set();
|
|
140
162
|
let output = "";
|
|
163
|
+
let activeThreadId = threadId;
|
|
164
|
+
let submissionStarted = false;
|
|
165
|
+
let admissionObserved = false;
|
|
166
|
+
let observedTerminal = null;
|
|
141
167
|
let terminalResolve;
|
|
142
168
|
let terminalReject;
|
|
143
169
|
const terminal = new Promise((resolve, reject) => {
|
|
@@ -162,16 +188,38 @@ export class CodexAppServerAdapter extends EventEmitter {
|
|
|
162
188
|
notifications.push(projected);
|
|
163
189
|
this.emit("notification", projected);
|
|
164
190
|
}
|
|
191
|
+
if (
|
|
192
|
+
submissionStarted &&
|
|
193
|
+
(projected.method === "turn/started" ||
|
|
194
|
+
projected.method?.startsWith("item/") ||
|
|
195
|
+
Boolean(projected.terminal))
|
|
196
|
+
) {
|
|
197
|
+
admissionObserved = true;
|
|
198
|
+
}
|
|
165
199
|
if (projected.output) output = projected.output;
|
|
166
|
-
if (projected.terminal)
|
|
200
|
+
if (projected.terminal) {
|
|
201
|
+
observedTerminal = projected;
|
|
202
|
+
terminalResolve(projected);
|
|
203
|
+
}
|
|
167
204
|
};
|
|
168
205
|
this.client.on?.("notification", onNotification);
|
|
169
|
-
|
|
206
|
+
const buildResult = (terminalEvent) =>
|
|
207
|
+
Object.freeze({
|
|
208
|
+
protocol: CODEX_APP_SERVER_PROTOCOL,
|
|
209
|
+
threadId: activeThreadId,
|
|
210
|
+
terminal: terminalEvent.terminal,
|
|
211
|
+
output,
|
|
212
|
+
error: terminalEvent.error || null,
|
|
213
|
+
usage: terminalEvent.usage || null,
|
|
214
|
+
notifications: Object.freeze(notifications),
|
|
215
|
+
unknownMethods: Object.freeze([...unknownMethods].sort()),
|
|
216
|
+
fallback: false,
|
|
217
|
+
authoritative: false,
|
|
218
|
+
});
|
|
170
219
|
try {
|
|
171
220
|
if (!this.client.running && typeof this.client.start === "function") {
|
|
172
221
|
await this.client.start();
|
|
173
222
|
}
|
|
174
|
-
let activeThreadId = threadId;
|
|
175
223
|
if (!activeThreadId) {
|
|
176
224
|
const started = await this.client.request("thread/start", {
|
|
177
225
|
ephemeral: false,
|
|
@@ -185,31 +233,37 @@ export class CodexAppServerAdapter extends EventEmitter {
|
|
|
185
233
|
"Codex App Server did not return a thread identity",
|
|
186
234
|
);
|
|
187
235
|
}
|
|
236
|
+
// Once turn/start begins, a rejected client promise cannot prove that
|
|
237
|
+
// the server did not accept the input. Never launch a second execution
|
|
238
|
+
// path from that ambiguous state.
|
|
239
|
+
submissionStarted = true;
|
|
188
240
|
const started = await this.client.request("turn/start", {
|
|
189
241
|
threadId: activeThreadId,
|
|
190
242
|
input: [{ type: "text", text: String(prompt || "") }],
|
|
191
243
|
});
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
usage: terminalEvent.usage || null,
|
|
204
|
-
notifications: Object.freeze(notifications),
|
|
205
|
-
unknownMethods: Object.freeze([...unknownMethods].sort()),
|
|
206
|
-
fallback: false,
|
|
207
|
-
authoritative: false,
|
|
208
|
-
});
|
|
244
|
+
admissionObserved = true;
|
|
245
|
+
const initialStatus = String(started?.turn?.status || "");
|
|
246
|
+
const terminalEvent = ["completed", "failed", "interrupted"].includes(
|
|
247
|
+
initialStatus,
|
|
248
|
+
)
|
|
249
|
+
? projectNotification({
|
|
250
|
+
method: "turn/completed",
|
|
251
|
+
params: { turn: started.turn, usage: started.turn.usage || null },
|
|
252
|
+
})
|
|
253
|
+
: await terminal;
|
|
254
|
+
return buildResult(terminalEvent);
|
|
209
255
|
} catch (error) {
|
|
210
|
-
if (!
|
|
256
|
+
if (!submissionStarted) {
|
|
211
257
|
return this._fallback(prompt, options, error?.code || "startup_failed");
|
|
212
258
|
}
|
|
259
|
+
if (observedTerminal) return buildResult(observedTerminal);
|
|
260
|
+
if (!admissionObserved) {
|
|
261
|
+
throw adapterError(
|
|
262
|
+
"CC_CODEX_APP_SERVER_SUBMISSION_UNKNOWN",
|
|
263
|
+
"Codex App Server turn submission outcome is unknown; fallback was suppressed to prevent duplicate effects",
|
|
264
|
+
{ cause: error },
|
|
265
|
+
);
|
|
266
|
+
}
|
|
213
267
|
throw adapterError(
|
|
214
268
|
"CC_CODEX_APP_SERVER_FAILED_AFTER_ADMISSION",
|
|
215
269
|
"Codex App Server failed after the turn was admitted; fallback was suppressed to prevent duplicate effects",
|