chainlesschain 0.166.9 → 0.166.13
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 +33 -0
- package/bin/chainlesschain.js +5 -0
- package/package.json +5 -2
- package/src/assets/web-panel/assets/{AIOps-DJvpifGx.js → AIOps-BN25cNOD.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-D2UhuF_A.js → ActionButton-Da9IP-m5.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C9ho9obu.js → Analytics-D7hkEvQm.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BvRCpFK3.js → AppLayout-CCV4Xnbc.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-jxrySvpk.js → Artifacts-CVSnVJeA.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-ovEw0ZYl.js → Audit-CuYdw5Ag.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D7H5z6zS.js → BackgroundAgents-DZCnK-Tf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BuXob8za.js → Backup-cV9FdpTy.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CtnszuQ2.js → BaseInput-BRnv6YSp.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-B_mYE8fJ.js → Chat-Bw5w87P4.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-C0GjtUAw.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-ierdtcJD.js → Checkbox-DaoTqcdt.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-3VKPJD_B.js → Codegen-B4dYcEIi.js} +1 -1
- package/src/assets/web-panel/assets/{Col-1EdMyf5P.js → Col-mAhuOeuD.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D6H7UA8K.js → Community-BK6KEdBk.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BBAZvYIm.js → Compact-CCglmNu5.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CgsTrAoj.js → Compliance-Cm8S4of7.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-tnZgLoTE.js → Cowork-Dhs1QLMe.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CPpZw2Nh.js → Cron-CLlhmXWk.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BymBcp5z.js → Crosschain-BnHVbaNs.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DKPxS_K1.js → DID-UzQP9-0O.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DvJhEmH9.js → Dashboard-CBdlPClz.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-b8iQyQIZ.js → Dropdown-axIRPdq1.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer--0-A-zKb.js → EmailListRenderer-DUalW5rx.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-C12iDN06.js → FamilyGuardDashboard-Bl4W9luY.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BRhaE2Z8.js → Federation-C1yP-uEu.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C4dnq7yf.js → FormItemContext-Xh6Ig5q8.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CGAdbR5n.js → GenericCardRenderer-C2cz3bt2.js} +1 -1
- package/src/assets/web-panel/assets/{Git-4eA2fYzL.js → Git-C_z63ixg.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJuY9Y-9.js → Governance-BYqB33_3.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DZ5Dy4up.js → Inference-CEULuArm.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BMTjRs4A.js → KnowledgeGraph-fgMsu-0H.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BKEeQEfJ.js → Logs-DO9Hdcec.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BkrK04xW.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Dhho4fEg.js → Marketplace-B8zyLiFe.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BW6xxSlU.js → McpTools-BLAN2mWW.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-mPqlpSkq.js → Memory-CrQcFM7u.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Cb9N_DQI.js → MobileBridge-DVnyiiU-.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BNs8tah_.js → MobileProjects-qjCME5OD.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CaxBt8tn.js → Mtc-4JE3C3It.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-DRPQbp3t.js → MtcAudit-CjBuak9I.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CRm-d8bK.js → Multisig-BtPcYQcC.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BCCk3LPs.js → NLProgramming-Cx653_Ba.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cv8SN8gN.js → Notes-CkuD3YzS.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-CggIvTh5.js → NotificationSettings-BgNgU7HH.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BW3_bV12.js → OrderTableRenderer-BTC8W0a-.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BuRE-VCO.js → Organization-Dmd4Hjxz.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DBrm1gju.js → Overflow-C_5DA-G0.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CWVnDYgS.js → P2P-uwslV4XC.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-8RKUIpte.js → PdhVaultBrowser-CuNgwVnX.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-tDUAxogW.js → Permissions-CJayVX9H.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Dv2-CFis.js → PersonalDataHub-Cb05H5go.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-DM6kvFni.js → Pipeline-BZlGKapZ.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzK-yL0d.js → Privacy-BIzZWYzd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B5UrNpkj.js → ProjectInit-vEYYyQXQ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CxJD43oW.js → ProjectSettings-MZqTy5CC.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CRARUOl8.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CYl4jRYK.js → Providers-80VAK8PX.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DeH2T0fH.js → QrScannerModal-CzRSoIwK.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bw9k_kTk.js → QuickAsk-BpwQ2n4C.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bl_jGwoi.js → Recommend-BC03TZ79.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-d6u01Kq0.js → RemoteSession-DE59-jaa.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-Ds_Dfr-k.js → Reputation-DOHmeWyA.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BpQUQTNj.js → Row-hc5RZl1D.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BatpZBGt.js → RssFeed-Cv5uMP7E.js} +3 -3
- package/src/assets/web-panel/assets/{Search-D7hOObzi.js → Search-qohu7Ug0.js} +1 -1
- package/src/assets/web-panel/assets/{Security-dXQ4FKNt.js → Security-drCPFWV5.js} +4 -4
- package/src/assets/web-panel/assets/{Services-D8wInGPa.js → Services-BAEgUeRy.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DXQCoYpM.js → Skeleton-CkJkKBlo.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-D3oLRIVn.js → Skills-bMuKEpez.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BmP4-LnJ.js → Sla-DxWQVHRC.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DLj-xzro.js → SpeechSettings-BpS8idmV.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-8KKaaRMr.js → SyncSettings-BPBLlW5v.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-GyK42I7C.js → Tasks-C4SLEeUh.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-n1y_8UBG.js → Templates-r-wfU39U.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-B39nBph8.js → Tenant-C7vjRmLN.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DCQoOKXe.js → Terminal-DdzeFCV2.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BkhbDfXk.js → TimelineRenderer-CYyWN2KD.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BeHIIU8D.js → Tokens-D8A9osUg.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BHvWXVOb.js → Trigger-DBvrNlyS.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-y2WaOSto.js → Trust-DBVAGc7o.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DBFeJBzt.js → UkeySign-C1vQUCRJ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BEOWitC-.js → VideoEditing-BKs4dah4.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BITedTe6.js → Wallet-ByIuj3lD.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DMwlJVin.js → WebAuthn-DYlAFCm9.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-CKfGFEu1.js → WorkflowEditor-Dwyadd0c.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DR6gnBGF.js → chat-Bm2f3s08.js} +1 -1
- package/src/assets/web-panel/assets/{colors-C_Hw5NCn.js → colors-C8ORSh7V.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B8IPwsEu.js → compact-item-1iVlnsM-.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D-u4JVnJ.js → createContext-CmqNyUSL.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-B69RCDDH.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CZubdS4D.js → hasIn-rUMaX3Ul.js} +1 -1
- package/src/assets/web-panel/assets/index-9biMQ-tw.js +1 -0
- package/src/assets/web-panel/assets/{index-C25rOz7O.js → index-B53c3diB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CfniPP5p.js → index-B59OWAs7.js} +1 -1
- package/src/assets/web-panel/assets/{index-11ASqx-A.js → index-B8BrB0Ls.js} +1 -1
- package/src/assets/web-panel/assets/{index-auyNYjLo.js → index-BC32_0xT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ctje8Vl3.js → index-BC8Wb6cy.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cg2bCeol.js → index-BCOhTILd.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1w96gg9.js → index-BFniLMn9.js} +1 -1
- package/src/assets/web-panel/assets/{index-k1Xa5iw1.js → index-BIvM-uAX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuOU5apg.js → index-BK-RY0-7.js} +1 -1
- package/src/assets/web-panel/assets/{index-D47jt8ET.js → index-BQL9r73Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-C2VmtNaQ.js → index-BVtnizyC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bizm87cX.js → index-Bf1PlIHp.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dt-w3xQ7.js → index-Bgw4Y2rU.js} +1 -1
- package/src/assets/web-panel/assets/{index-ffe7bvqP.js → index-BgwLNxmr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cl5RpreD.js → index-C-J5-pGH.js} +1 -1
- package/src/assets/web-panel/assets/{index-idZKyADQ.js → index-C-ZIHi42.js} +1 -1
- package/src/assets/web-panel/assets/{index-LvjAKDSl.js → index-C3B1S-mW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmRcgiYT.js → index-C5RfRciU.js} +1 -1
- package/src/assets/web-panel/assets/{index-rYBHSDcJ.js → index-CCEyz58d.js} +1 -1
- package/src/assets/web-panel/assets/index-COie87kl.js +1 -0
- package/src/assets/web-panel/assets/{index-DcFjRT-K.js → index-CTfEmKK0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjRrqooR.js → index-CfiHyVyl.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpjHpRoq.js → index-CkFvuAex.js} +3 -3
- package/src/assets/web-panel/assets/{index-BzoFanEQ.js → index-D98FXb0w.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cbm8F0M2.js → index-DDHk911Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXS6wYJZ.js → index-DJxtPFOh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DY6MHo9D.js → index-DVJ1uKf4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiXkhOkY.js → index-Dcck8QfW.js} +1 -1
- package/src/assets/web-panel/assets/{index-mYZJxGH6.js → index-DgUE51Pz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqmLw8cs.js → index-Dsve5Gkv.js} +1 -1
- package/src/assets/web-panel/assets/{index-xoNssgz_.js → index-DvedhJeM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfnzrUxU.js → index-DwMdWKiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi21Etg4.js → index-OcbzdRpT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJ6pG79m.js → index-fPK6GFEg.js} +1 -1
- package/src/assets/web-panel/assets/{index-_nL79NT8.js → index-geQinnns.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTosx2Wu.js → index-pHWA7bmM.js} +1 -1
- package/src/assets/web-panel/assets/{index-cVqbas5C.js → index-reUHhuz8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bv2132PO.js → index-tqTx5wXo.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-lcU_dT2r.js → initDefaultProps-CuA-cpkL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Dc7UNXZ1.js → motion-CimmE_9b.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cll8ZXaL.js → move-DlGlrltz.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CAb_yLIM.js → mtc-parser-CK6BJQ07.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DurYMyTe.js → omit-BKjBfZfB.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BITQyOlw.js → pickAttrs-B2chVYw9.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Dg1rH91i.js → placementArrow-BW8aLJJ3.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D_EWIeac.js → responsiveObserve-dXlPl66S.js} +1 -1
- package/src/assets/web-panel/assets/{slide-lK4d3zsh.js → slide-hSa89S4G.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Bflq-Git.js → statusUtils-DM6KLt-s.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Ccp0I-wt.js → styleChecker-C9MQAK15.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CYZbByYA.js → useFlexGapSupport-BpQDpP0z.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B_x0nxFD.js → useFs-C7rtRViA.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DW55rL85.js → usePersonalDataHub-Dm15xafq.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Ca6MH3W8.js → vnode-mEiEytw4.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-NdHelOog.js → zoom-DzPxflhY.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 +51 -20
- package/src/commands/compact.js +349 -3
- package/src/commands/context.js +72 -1
- package/src/commands/graph.js +26 -15
- package/src/commands/hmemory.js +21 -0
- package/src/commands/hook.js +256 -28
- package/src/commands/memory.js +209 -42
- package/src/commands/promcomp.js +17 -0
- package/src/commands/serve.js +94 -10
- package/src/commands/session.js +2 -3
- package/src/commands/team.js +7 -1
- package/src/data/changelog.json +41 -2
- package/src/gateways/ws/session-core-protocol.js +62 -3
- package/src/gateways/ws/session-protocol.js +123 -15
- package/src/gateways/ws/ws-agent-handler.js +157 -9
- package/src/gateways/ws/ws-session-gateway.js +204 -30
- package/src/generated/cc-agent-protocol.schema.json +2094 -4
- package/src/harness/prompt-compressor.js +5 -55
- package/src/lib/agent-sandbox.js +14 -4
- package/src/lib/agent-team/team-distributed-graph-bridge.js +3 -3
- package/src/lib/app-server/context-memory-notifications.js +54 -0
- package/src/lib/app-server/rollout-store-factory.js +115 -0
- package/src/lib/app-server/rollout-store.js +310 -23
- package/src/lib/app-server/server.js +184 -7
- package/src/lib/app-server/sqlite-rollout-store.js +59 -16
- package/src/lib/auto-mode-config.js +26 -0
- package/src/lib/causal-observability.js +13 -1
- package/src/lib/context-memory-kernel/authority.js +95 -0
- package/src/lib/context-memory-kernel/durable-memory-port.js +296 -0
- package/src/lib/context-memory-kernel/index.js +8 -0
- package/src/lib/context-memory-kernel/jsonl-session-context-port.js +232 -0
- package/src/lib/context-memory-kernel/live-compaction.js +375 -0
- package/src/lib/context-memory-kernel/memory-service.js +667 -0
- package/src/lib/context-memory-kernel/message-adapter.js +451 -0
- package/src/lib/context-memory-kernel/privacy-purge-port.js +244 -0
- package/src/lib/context-memory-kernel/provider-context.js +192 -0
- package/src/lib/context-memory-kernel/runtime.js +61 -0
- package/src/lib/direct-model-usage.js +22 -18
- package/src/lib/graph-kernel/cutover-authority-resolver.js +4 -5
- package/src/lib/graph-kernel/cutover-ledger.js +2 -2
- package/src/lib/graph-kernel/event-store.js +3 -5
- package/src/lib/graph-kernel/index.js +2 -0
- package/src/lib/graph-kernel/migration-saga.js +2 -2
- package/src/lib/graph-kernel/production-cutover-evidence.js +976 -0
- package/src/lib/graph-kernel/retirement-evidence.js +12 -4
- package/src/lib/hierarchical-memory.js +22 -0
- package/src/lib/hook-audit-store.js +170 -0
- package/src/lib/hook-event-bus.cjs +0 -0
- package/src/lib/hook-manager.js +25 -83
- package/src/lib/hook-runtime-adapters.js +233 -0
- package/src/lib/hook-runtime-contract.cjs +291 -0
- package/src/lib/hook-runtime-contract.js +21 -0
- package/src/lib/hook-trust.js +210 -0
- package/src/lib/hooks-v2-producers.js +52 -6
- package/src/lib/hooks-v2-runtime.js +443 -178
- package/src/lib/llm-pricing.js +10 -0
- package/src/lib/memory-manager.js +29 -4
- package/src/lib/model-context-window.js +52 -0
- package/src/lib/permanent-memory.js +17 -0
- package/src/lib/plan-mode.js +8 -4
- package/src/lib/process-execution-broker/index.js +208 -16
- package/src/lib/runtime-usage-ledger.js +20 -0
- package/src/lib/session-consolidator.js +59 -0
- package/src/lib/session-core-singletons.js +17 -4
- package/src/lib/session-hooks.js +29 -2
- package/src/lib/session-transcript-migration.js +188 -0
- package/src/lib/settings-hook-events.cjs +37 -401
- package/src/lib/settings-hook-events.js +210 -8
- package/src/lib/settings-hooks.cjs +42 -83
- package/src/lib/ws-session-manager.js +4 -1
- package/src/repl/agent-repl.js +186 -53
- package/src/runtime/agent-core.js +376 -350
- package/src/runtime/headless-runner.js +40 -33
- package/src/runtime/headless-stream.js +131 -30
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DaiA6CsX.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +0 -1
- package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +0 -1
- package/src/assets/web-panel/assets/index-BQ3213fz.js +0 -1
- package/src/assets/web-panel/assets/index-vJagfET2.js +0 -1
|
@@ -24,7 +24,6 @@ import sharedCodingAgentPolicy from "./coding-agent-policy.cjs";
|
|
|
24
24
|
import sharedShellPolicy from "./coding-agent-shell-policy.cjs";
|
|
25
25
|
import sharedPermissionRules from "../lib/permission-rules.cjs";
|
|
26
26
|
import sharedSettingsHooks from "../lib/settings-hooks.cjs";
|
|
27
|
-
import sharedHookRunner from "../lib/hook-runner.js";
|
|
28
27
|
import sharedHookEvents from "../lib/settings-hook-events.js";
|
|
29
28
|
import { mergeProviderOptions } from "../lib/provider-options.js";
|
|
30
29
|
import { applyCredentialProxy } from "../lib/credential-proxy.js";
|
|
@@ -48,7 +47,6 @@ import {
|
|
|
48
47
|
debitSkillPromptBudget,
|
|
49
48
|
resolveSkillLimits,
|
|
50
49
|
} from "../lib/skill-budget.js";
|
|
51
|
-
import { executeHooks, HookEvents } from "../lib/hook-manager.js";
|
|
52
50
|
import { detectPython } from "../lib/cli-anything-bridge.js";
|
|
53
51
|
import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
|
|
54
52
|
import { SubAgentContext } from "../lib/sub-agent-context.js";
|
|
@@ -179,14 +177,8 @@ const { isDangerousGitCommand, isReadOnlyGitCommand, normalizeGitCommand } =
|
|
|
179
177
|
sharedCodingAgentPolicy;
|
|
180
178
|
const { evaluateShellCommandPolicy } = sharedShellPolicy;
|
|
181
179
|
const { evaluatePermissionRules } = sharedPermissionRules;
|
|
182
|
-
const {
|
|
183
|
-
const {
|
|
184
|
-
const {
|
|
185
|
-
runObserveHooks,
|
|
186
|
-
aggregateContext,
|
|
187
|
-
partitionAsyncHooks,
|
|
188
|
-
withDeliveryId,
|
|
189
|
-
} = sharedHookEvents;
|
|
180
|
+
const { umbrellaFor } = sharedSettingsHooks;
|
|
181
|
+
const { runObserveHooks, aggregateContext } = sharedHookEvents;
|
|
190
182
|
|
|
191
183
|
const searchProcessRunner = broker.execSync.bind(broker);
|
|
192
184
|
const runCodeProcessRunner = broker.execFileSync.bind(broker);
|
|
@@ -764,156 +756,6 @@ function _resolveShellTimeout(raw) {
|
|
|
764
756
|
return Math.min(Math.floor(n), MAX_SHELL_TIMEOUT_MS);
|
|
765
757
|
}
|
|
766
758
|
|
|
767
|
-
/**
|
|
768
|
-
* Run settings.json `PreToolUse` hooks (decision-capable). DB hooks are handled
|
|
769
|
-
* separately + stay observe-only. A `block` decision stops the tool; an `ask`
|
|
770
|
-
* routes to the confirmer (headless without one falls closed). spawnSync is
|
|
771
|
-
* synchronous but each hook is timeout-capped.
|
|
772
|
-
* @returns {Promise<{blocked:boolean, reason?:string, hook?:string}>}
|
|
773
|
-
*/
|
|
774
|
-
async function runSettingsPreToolUseHooks(name, args, context, cwd) {
|
|
775
|
-
const matched = collectHooks(context.settingsHooks, "PreToolUse", name);
|
|
776
|
-
if (!matched || matched.length === 0) return { blocked: false };
|
|
777
|
-
// Unified-bus envelope (P2): stamps event_id + threads trace_id (this run) /
|
|
778
|
-
// parent_id (spawning run) from the loop context. Additive fields — a hook
|
|
779
|
-
// that ignores them is unaffected; absent context omits them entirely.
|
|
780
|
-
const payload = withDeliveryId(
|
|
781
|
-
"PreToolUse",
|
|
782
|
-
{
|
|
783
|
-
hook_event_name: "PreToolUse",
|
|
784
|
-
tool_name: umbrellaFor(name),
|
|
785
|
-
raw_tool_name: name,
|
|
786
|
-
tool_input: args,
|
|
787
|
-
cwd,
|
|
788
|
-
session_id: context.sessionId || null,
|
|
789
|
-
},
|
|
790
|
-
{
|
|
791
|
-
sessionId: context.sessionId || null,
|
|
792
|
-
traceId: context.hookTraceId || null,
|
|
793
|
-
parentId: context.hookParentId || null,
|
|
794
|
-
},
|
|
795
|
-
);
|
|
796
|
-
// Run every matching authority-bearing hook in configured order, then merge
|
|
797
|
-
// the outcomes with block > ask > allow > continue. Sequential execution
|
|
798
|
-
// preserves the documented hook side-effect order while preventing an early
|
|
799
|
-
// ask/allow from masking a later block. Environment variables cannot weaken
|
|
800
|
-
// this permission boundary.
|
|
801
|
-
const outcome = runCommandHooks(matched, payload, {
|
|
802
|
-
cwd,
|
|
803
|
-
event: "PreToolUse",
|
|
804
|
-
mergeStrict: true,
|
|
805
|
-
failClosed: true,
|
|
806
|
-
broker,
|
|
807
|
-
});
|
|
808
|
-
if (outcome.decision === "block") {
|
|
809
|
-
return { blocked: true, reason: outcome.reason, hook: outcome.hook };
|
|
810
|
-
}
|
|
811
|
-
if (outcome.decision === "ask") {
|
|
812
|
-
// File edits in an interactive session with an IDE bridge: route the ask
|
|
813
|
-
// through the editor's openDiff review (same machinery as settings ask —
|
|
814
|
-
// accepted means the IDE wrote the file, so the caller must skip
|
|
815
|
-
// execution; see tryIdeDiffApprovalForEdit).
|
|
816
|
-
const ide = await tryIdeDiffApprovalForEdit(name, args, context, cwd, {
|
|
817
|
-
rule: `hook:${outcome.hook}`,
|
|
818
|
-
source: "PreToolUse hook",
|
|
819
|
-
});
|
|
820
|
-
if (ide?.outcome === "accepted") {
|
|
821
|
-
return { blocked: false, ideApplied: ide.result };
|
|
822
|
-
}
|
|
823
|
-
// Both rejected and changes-requested mean "not applied + feed the
|
|
824
|
-
// verdict's message back" — same control flow, different message body.
|
|
825
|
-
if (ide?.outcome === "rejected" || ide?.outcome === "changes-requested") {
|
|
826
|
-
return {
|
|
827
|
-
blocked: true,
|
|
828
|
-
reason: ide.result.error,
|
|
829
|
-
hook: outcome.hook,
|
|
830
|
-
ideResult: ide.result,
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
const ok = await requestInteractivePermission(name, args, context, cwd, {
|
|
834
|
-
tool: name,
|
|
835
|
-
args,
|
|
836
|
-
rule: `hook:${outcome.hook}`,
|
|
837
|
-
reason: outcome.reason || "a PreToolUse hook requests confirmation",
|
|
838
|
-
});
|
|
839
|
-
return ok
|
|
840
|
-
? { blocked: false }
|
|
841
|
-
: {
|
|
842
|
-
blocked: true,
|
|
843
|
-
reason: outcome.reason || "PreToolUse hook ask denied",
|
|
844
|
-
hook: outcome.hook,
|
|
845
|
-
};
|
|
846
|
-
}
|
|
847
|
-
return { blocked: false };
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/**
|
|
851
|
-
* Run settings.json `PermissionRequest` hooks (Claude-Code parity). Fires at the
|
|
852
|
-
* exact moment a tool call would prompt the user for approval — BEFORE the
|
|
853
|
-
* prompt — so a policy hook can auto-approve (`allow`/`approve`), auto-reject
|
|
854
|
-
* (`deny`/`block`), or defer (`ask` / no decision) to the normal prompt.
|
|
855
|
-
* Returns `{ decision: "allow" | "deny" | null }`. No matching hook (or no
|
|
856
|
-
* `settingsHooks`) → `{ decision: null }` and the caller prompts exactly as
|
|
857
|
-
* before (default behaviour is byte-for-byte unchanged).
|
|
858
|
-
* @returns {{decision:("allow"|"deny"|null), reason?:string, hook?:string}}
|
|
859
|
-
*/
|
|
860
|
-
function runSettingsPermissionRequestHooks(name, args, context, cwd, reason) {
|
|
861
|
-
// Command hooks are arbitrary processes. Until a host-enforced read-only
|
|
862
|
-
// hook sandbox exists, no command hook may execute inside the planning-only
|
|
863
|
-
// capability fence (even when the underlying tool is read-only).
|
|
864
|
-
if (context.planReadOnlyFenceActive === true) return { decision: null };
|
|
865
|
-
const matched = collectHooks(
|
|
866
|
-
context.settingsHooks,
|
|
867
|
-
"PermissionRequest",
|
|
868
|
-
name,
|
|
869
|
-
);
|
|
870
|
-
if (!matched || matched.length === 0) return { decision: null };
|
|
871
|
-
const payload = withDeliveryId(
|
|
872
|
-
"PermissionRequest",
|
|
873
|
-
{
|
|
874
|
-
hook_event_name: "PermissionRequest",
|
|
875
|
-
tool_name: umbrellaFor(name),
|
|
876
|
-
raw_tool_name: name,
|
|
877
|
-
tool_input: args,
|
|
878
|
-
permission_reason: reason || null,
|
|
879
|
-
cwd,
|
|
880
|
-
session_id: context.sessionId || null,
|
|
881
|
-
},
|
|
882
|
-
{
|
|
883
|
-
sessionId: context.sessionId || null,
|
|
884
|
-
traceId: context.hookTraceId || null,
|
|
885
|
-
parentId: context.hookParentId || null,
|
|
886
|
-
},
|
|
887
|
-
);
|
|
888
|
-
const outcome = runCommandHooks(matched, payload, {
|
|
889
|
-
cwd,
|
|
890
|
-
event: "PermissionRequest",
|
|
891
|
-
mergeStrict: true,
|
|
892
|
-
failClosed: true,
|
|
893
|
-
broker,
|
|
894
|
-
});
|
|
895
|
-
// Precedence: deny > ask > allow > defer. The runner normalizes deny/block →
|
|
896
|
-
// "block" and short-circuits block/ask, but it COLLAPSES an "allow" into the
|
|
897
|
-
// aggregate "continue" (it only short-circuits block/ask) — so an explicit
|
|
898
|
-
// auto-approve must be recovered from the per-hook `results`. A deny or ask
|
|
899
|
-
// by any hook still wins over an allow (safety: never let an allow override a
|
|
900
|
-
// gate that another hook wanted to block or prompt for).
|
|
901
|
-
if (outcome.decision === "block") {
|
|
902
|
-
return { decision: "deny", reason: outcome.reason, hook: outcome.hook };
|
|
903
|
-
}
|
|
904
|
-
if (outcome.decision === "ask") {
|
|
905
|
-
return { decision: null }; // a hook asked → defer to the confirmer
|
|
906
|
-
}
|
|
907
|
-
const allowHook =
|
|
908
|
-
outcome.decision === "allow"
|
|
909
|
-
? { command: outcome.hook }
|
|
910
|
-
: (outcome.results || []).find((r) => r && r.decision === "allow");
|
|
911
|
-
if (allowHook) {
|
|
912
|
-
return { decision: "allow", hook: allowHook.command || null };
|
|
913
|
-
}
|
|
914
|
-
return { decision: null }; // no actionable decision → defer to the confirmer
|
|
915
|
-
}
|
|
916
|
-
|
|
917
759
|
/**
|
|
918
760
|
* Resolve an interactive permission gate. Gives `PermissionRequest` hooks first
|
|
919
761
|
* say (auto-allow → true without prompting, auto-deny → false without
|
|
@@ -946,6 +788,12 @@ async function requestInteractivePermission(
|
|
|
946
788
|
? Boolean(await confirm(confirmArgs))
|
|
947
789
|
: false;
|
|
948
790
|
}
|
|
791
|
+
if (context.planReadOnlyFenceActive === true) {
|
|
792
|
+
const confirm = context.permissionConfirm || context.shellConfirm || null;
|
|
793
|
+
return typeof confirm === "function"
|
|
794
|
+
? Boolean(await confirm(confirmArgs))
|
|
795
|
+
: false;
|
|
796
|
+
}
|
|
949
797
|
const hooksV2 = await executeHooksV2Event(
|
|
950
798
|
"PermissionRequest",
|
|
951
799
|
{
|
|
@@ -954,14 +802,21 @@ async function requestInteractivePermission(
|
|
|
954
802
|
turn_id: context.turnId || null,
|
|
955
803
|
tool_use_id: context.toolCallId || null,
|
|
956
804
|
tool_name: name,
|
|
805
|
+
raw_tool_name: name,
|
|
806
|
+
tool_input: args,
|
|
957
807
|
input_keys:
|
|
958
808
|
args && typeof args === "object" ? Object.keys(args).sort() : [],
|
|
959
809
|
reason: confirmArgs?.reason || null,
|
|
960
810
|
cwd,
|
|
961
|
-
trace_id: context.hookTraceId
|
|
962
|
-
parent_id: context.hookParentId
|
|
811
|
+
...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
|
|
812
|
+
...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
failClosed: true,
|
|
816
|
+
settingsHooks: context.settingsHooks,
|
|
817
|
+
matchTarget: name,
|
|
818
|
+
cwd,
|
|
963
819
|
},
|
|
964
|
-
{ failClosed: true },
|
|
965
820
|
);
|
|
966
821
|
if (hooksV2.decision === "allow") return true;
|
|
967
822
|
if (hooksV2.blocked || hooksV2.decision === "block") {
|
|
@@ -975,25 +830,6 @@ async function requestInteractivePermission(
|
|
|
975
830
|
});
|
|
976
831
|
return false;
|
|
977
832
|
}
|
|
978
|
-
const verdict = runSettingsPermissionRequestHooks(
|
|
979
|
-
name,
|
|
980
|
-
args,
|
|
981
|
-
context,
|
|
982
|
-
cwd,
|
|
983
|
-
confirmArgs?.reason,
|
|
984
|
-
);
|
|
985
|
-
if (verdict.decision === "allow") return true;
|
|
986
|
-
if (verdict.decision === "deny") {
|
|
987
|
-
emitHooksV2Event("PermissionDenied", {
|
|
988
|
-
schema_version: 1,
|
|
989
|
-
session_id: context.sessionId || null,
|
|
990
|
-
turn_id: context.turnId || null,
|
|
991
|
-
tool_use_id: context.toolCallId || null,
|
|
992
|
-
tool_name: name,
|
|
993
|
-
source: "settings-hook",
|
|
994
|
-
});
|
|
995
|
-
return false;
|
|
996
|
-
}
|
|
997
833
|
const confirm = context.permissionConfirm || context.shellConfirm || null;
|
|
998
834
|
const approved =
|
|
999
835
|
typeof confirm === "function" ? await confirm(confirmArgs) : false;
|
|
@@ -2750,6 +2586,25 @@ export async function executeTool(name, args, context = {}) {
|
|
|
2750
2586
|
typeof context.externalToolExecutors === "object"
|
|
2751
2587
|
? context.externalToolExecutors[name] || null
|
|
2752
2588
|
: null;
|
|
2589
|
+
// Bind MCP arguments to one strict immutable JSON snapshot before any
|
|
2590
|
+
// asynchronous permission or Hook boundary. This prevents accessors,
|
|
2591
|
+
// functions, or later caller mutation from changing the request that was
|
|
2592
|
+
// approved, recorded in the ledger, and sent over the wire.
|
|
2593
|
+
if (localToolExecutor?.kind === "mcp") {
|
|
2594
|
+
try {
|
|
2595
|
+
args = snapshotMcpJsonRpcInput(args || {});
|
|
2596
|
+
} catch (error) {
|
|
2597
|
+
return {
|
|
2598
|
+
error:
|
|
2599
|
+
"MCP tool blocked because its input is not strict immutable JSON data",
|
|
2600
|
+
policy: {
|
|
2601
|
+
decision: "blocked",
|
|
2602
|
+
via: "mcp-wire-input",
|
|
2603
|
+
code: safeMcpErrorCode(error, "CC_MCP_WIRE_INPUT_INVALID"),
|
|
2604
|
+
},
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2753
2608
|
const runtimeDescriptor =
|
|
2754
2609
|
getRuntimeToolDescriptor(name) || localToolDescriptor;
|
|
2755
2610
|
let admittedToolAdmissionDigest = null;
|
|
@@ -2852,6 +2707,8 @@ export async function executeTool(name, args, context = {}) {
|
|
|
2852
2707
|
turn_id: context.turnId || null,
|
|
2853
2708
|
tool_use_id: context.toolCallId || null,
|
|
2854
2709
|
tool_name: name,
|
|
2710
|
+
raw_tool_name: name,
|
|
2711
|
+
tool_input: args,
|
|
2855
2712
|
hook_event_name: event,
|
|
2856
2713
|
hook_source: source,
|
|
2857
2714
|
incident_code: incident.code,
|
|
@@ -3553,6 +3410,7 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3553
3410
|
"PreToolUse",
|
|
3554
3411
|
{
|
|
3555
3412
|
schema_version: 1,
|
|
3413
|
+
event_id: `evt_${randomUUID().replaceAll("-", "").slice(0, 16)}`,
|
|
3556
3414
|
session_id: context.sessionId || null,
|
|
3557
3415
|
turn_id: context.turnId || null,
|
|
3558
3416
|
tool_use_id: context.toolCallId || null,
|
|
@@ -3560,28 +3418,69 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3560
3418
|
input_keys:
|
|
3561
3419
|
args && typeof args === "object" ? Object.keys(args).sort() : [],
|
|
3562
3420
|
cwd,
|
|
3563
|
-
trace_id: context.hookTraceId
|
|
3564
|
-
parent_id: context.hookParentId
|
|
3421
|
+
...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
|
|
3422
|
+
...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
|
|
3423
|
+
},
|
|
3424
|
+
{
|
|
3425
|
+
failClosed: true,
|
|
3426
|
+
settingsHooks: context.settingsHooks,
|
|
3427
|
+
hookDb,
|
|
3428
|
+
matchTarget: name,
|
|
3429
|
+
cwd,
|
|
3565
3430
|
},
|
|
3566
|
-
{ failClosed: true },
|
|
3567
3431
|
);
|
|
3568
3432
|
if (hooksV2Pre.blocked || hooksV2Pre.decision === "block") {
|
|
3433
|
+
const blockingHook = hooksV2Pre.results?.find(
|
|
3434
|
+
(entry) => entry.decision === "block",
|
|
3435
|
+
);
|
|
3436
|
+
const blockingReason =
|
|
3437
|
+
blockingHook?.result?.reason ||
|
|
3438
|
+
hooksV2Pre.blockingResult?.reason ||
|
|
3439
|
+
blockingHook?.error ||
|
|
3440
|
+
null;
|
|
3569
3441
|
return {
|
|
3570
|
-
error: `[Hook
|
|
3571
|
-
policy: {
|
|
3442
|
+
error: `[Hook] PreToolUse blocked "${name}"${blockingReason ? `: ${blockingReason}` : ""}`,
|
|
3443
|
+
policy: {
|
|
3444
|
+
decision: "block",
|
|
3445
|
+
via: "hook",
|
|
3446
|
+
hook: blockingHook?.hookId || null,
|
|
3447
|
+
code:
|
|
3448
|
+
hooksV2Pre.errorCode ||
|
|
3449
|
+
hooksV2Pre.auditError ||
|
|
3450
|
+
hooksV2Pre.blockingResult?.code ||
|
|
3451
|
+
null,
|
|
3452
|
+
},
|
|
3572
3453
|
};
|
|
3573
3454
|
}
|
|
3574
3455
|
if (hooksV2Pre.requiresApproval || hooksV2Pre.decision === "ask") {
|
|
3575
|
-
const
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3456
|
+
const askingHook = hooksV2Pre.results?.find(
|
|
3457
|
+
(entry) => entry.decision === "ask",
|
|
3458
|
+
);
|
|
3459
|
+
const reason =
|
|
3460
|
+
askingHook?.result?.reason ||
|
|
3461
|
+
hooksV2Pre.blockingResult?.reason ||
|
|
3462
|
+
"A PreToolUse Hook requests confirmation";
|
|
3463
|
+
const ide = await tryIdeDiffApprovalForEdit(name, args, context, cwd, {
|
|
3464
|
+
rule: `hook:${askingHook?.hookId || "canonical"}`,
|
|
3465
|
+
source: "PreToolUse Hook",
|
|
3466
|
+
});
|
|
3467
|
+
if (ide?.outcome === "accepted") return ide.result;
|
|
3468
|
+
if (ide?.outcome === "rejected" || ide?.outcome === "changes-requested") {
|
|
3469
|
+
return ide.result;
|
|
3470
|
+
}
|
|
3471
|
+
const approved = await requestInteractivePermission(
|
|
3472
|
+
name,
|
|
3473
|
+
args,
|
|
3474
|
+
context,
|
|
3475
|
+
cwd,
|
|
3476
|
+
{
|
|
3477
|
+
tool: name,
|
|
3478
|
+
args,
|
|
3479
|
+
rule: `hook:${askingHook?.hookId || "canonical"}`,
|
|
3480
|
+
reason,
|
|
3481
|
+
source: "hooks-v2",
|
|
3482
|
+
},
|
|
3483
|
+
);
|
|
3585
3484
|
if (!approved) {
|
|
3586
3485
|
emitHooksV2Event("PermissionDenied", {
|
|
3587
3486
|
schema_version: 1,
|
|
@@ -3592,35 +3491,8 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3592
3491
|
source: "hooks-v2",
|
|
3593
3492
|
});
|
|
3594
3493
|
return {
|
|
3595
|
-
error: `[Hook
|
|
3596
|
-
policy: { decision: "deny", via: "
|
|
3597
|
-
};
|
|
3598
|
-
}
|
|
3599
|
-
}
|
|
3600
|
-
if (hookDb) {
|
|
3601
|
-
try {
|
|
3602
|
-
await executeHooks(hookDb, HookEvents.PreToolUse, {
|
|
3603
|
-
tool: name,
|
|
3604
|
-
args,
|
|
3605
|
-
timestamp: new Date().toISOString(),
|
|
3606
|
-
descriptor: runtimeDescriptor,
|
|
3607
|
-
context: toolContext,
|
|
3608
|
-
});
|
|
3609
|
-
} catch (error) {
|
|
3610
|
-
recordObserveHookIncident("PreToolUse", "database", error);
|
|
3611
|
-
}
|
|
3612
|
-
}
|
|
3613
|
-
if (context.settingsHooks) {
|
|
3614
|
-
const pre = await runSettingsPreToolUseHooks(name, args, context, cwd);
|
|
3615
|
-
// A hook `ask` resolved by the IDE diff review: accepted → the IDE
|
|
3616
|
-
// already wrote the file, return the synthetic result and skip the tool;
|
|
3617
|
-
// rejected → the ide-diff deny shape (via:"ide-diff", not via:"hook").
|
|
3618
|
-
if (pre.ideApplied) return pre.ideApplied;
|
|
3619
|
-
if (pre.blocked) {
|
|
3620
|
-
if (pre.ideResult) return pre.ideResult;
|
|
3621
|
-
return {
|
|
3622
|
-
error: `[Hook] PreToolUse blocked "${name}"${pre.reason ? ": " + pre.reason : ""}`,
|
|
3623
|
-
policy: { decision: "block", via: "hook", hook: pre.hook || null },
|
|
3494
|
+
error: `[Hook] PreToolUse blocked "${name}": confirmation denied`,
|
|
3495
|
+
policy: { decision: "deny", via: "hook" },
|
|
3624
3496
|
};
|
|
3625
3497
|
}
|
|
3626
3498
|
}
|
|
@@ -3741,19 +3613,26 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3741
3613
|
context.browserReplayAllowCredentials === true,
|
|
3742
3614
|
});
|
|
3743
3615
|
} catch (err) {
|
|
3744
|
-
if (
|
|
3745
|
-
hookDb &&
|
|
3746
|
-
!planReadOnlyFenceActive &&
|
|
3747
|
-
context.hermeticExecution !== true
|
|
3748
|
-
) {
|
|
3616
|
+
if (!planReadOnlyFenceActive && context.hermeticExecution !== true) {
|
|
3749
3617
|
try {
|
|
3750
|
-
await
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3618
|
+
await executeHooksV2Event(
|
|
3619
|
+
"ToolError",
|
|
3620
|
+
{
|
|
3621
|
+
tool: name,
|
|
3622
|
+
tool_name: name,
|
|
3623
|
+
tool_input: args,
|
|
3624
|
+
error: err.message,
|
|
3625
|
+
cwd,
|
|
3626
|
+
},
|
|
3627
|
+
{
|
|
3628
|
+
hookDb,
|
|
3629
|
+
settingsHooks: context.settingsHooks,
|
|
3630
|
+
matchTarget: name,
|
|
3631
|
+
cwd,
|
|
3632
|
+
},
|
|
3633
|
+
);
|
|
3755
3634
|
} catch (error) {
|
|
3756
|
-
recordObserveHookIncident("ToolError", "
|
|
3635
|
+
recordObserveHookIncident("ToolError", "canonical", error);
|
|
3757
3636
|
}
|
|
3758
3637
|
}
|
|
3759
3638
|
throw err;
|
|
@@ -3777,96 +3656,76 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3777
3656
|
}
|
|
3778
3657
|
}
|
|
3779
3658
|
|
|
3780
|
-
// PostToolUse
|
|
3781
|
-
|
|
3782
|
-
hookDb &&
|
|
3783
|
-
!planReadOnlyFenceActive &&
|
|
3784
|
-
context.hermeticExecution !== true
|
|
3785
|
-
) {
|
|
3786
|
-
try {
|
|
3787
|
-
await executeHooks(hookDb, HookEvents.PostToolUse, {
|
|
3788
|
-
tool: name,
|
|
3789
|
-
args,
|
|
3790
|
-
result:
|
|
3791
|
-
typeof toolResult === "object"
|
|
3792
|
-
? JSON.stringify(toolResult).substring(0, 500)
|
|
3793
|
-
: String(toolResult).substring(0, 500),
|
|
3794
|
-
descriptor: runtimeDescriptor,
|
|
3795
|
-
context: toolContext,
|
|
3796
|
-
});
|
|
3797
|
-
} catch (error) {
|
|
3798
|
-
recordObserveHookIncident("PostToolUse", "database", error);
|
|
3799
|
-
}
|
|
3800
|
-
}
|
|
3801
|
-
// settings.json PostToolUse hooks: can't un-run the tool, but a `block`
|
|
3802
|
-
// reason is attached as `hookFeedback` to be surfaced back to the model.
|
|
3659
|
+
// Canonical PostToolUse dispatch. SQLite and settings definitions are input
|
|
3660
|
+
// adapters; Hooks v2 is the only scheduler/decision/audit runtime.
|
|
3803
3661
|
if (
|
|
3804
3662
|
!planReadOnlyFenceActive &&
|
|
3805
3663
|
context.hermeticExecution !== true &&
|
|
3806
|
-
context.settingsHooks &&
|
|
3807
3664
|
toolResult &&
|
|
3808
3665
|
typeof toolResult === "object"
|
|
3809
3666
|
) {
|
|
3810
3667
|
try {
|
|
3811
|
-
const
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
"settings-command",
|
|
3854
|
-
hookResult.reason || hookResult.error || "hook command failed",
|
|
3855
|
-
);
|
|
3856
|
-
}
|
|
3857
|
-
}
|
|
3858
|
-
if (outcome.decision === "block" && outcome.reason) {
|
|
3859
|
-
toolResult.hookFeedback = outcome.reason;
|
|
3860
|
-
}
|
|
3861
|
-
}
|
|
3862
|
-
// Fire-and-forget the async hooks onto the REPL-owned supervisor when
|
|
3863
|
-
// one is wired; results/rewakes drain into the next turn's context.
|
|
3864
|
-
if (asyncHooks.length > 0 && context.hookSupervisor) {
|
|
3865
|
-
context.hookSupervisor.dispatch(asyncHooks, payload, { cwd, broker });
|
|
3668
|
+
const outcome = await executeHooksV2Event(
|
|
3669
|
+
"PostToolUse",
|
|
3670
|
+
{
|
|
3671
|
+
schema_version: 1,
|
|
3672
|
+
event_id: `evt_${randomUUID().replaceAll("-", "").slice(0, 16)}`,
|
|
3673
|
+
hook_event_name: "PostToolUse",
|
|
3674
|
+
tool_name: umbrellaFor(name),
|
|
3675
|
+
raw_tool_name: name,
|
|
3676
|
+
tool_input: args,
|
|
3677
|
+
tool_response: JSON.stringify(toolResult).substring(0, 2000),
|
|
3678
|
+
cwd,
|
|
3679
|
+
session_id: context.sessionId || null,
|
|
3680
|
+
...(context.hookTraceId ? { trace_id: context.hookTraceId } : {}),
|
|
3681
|
+
...(context.hookParentId ? { parent_id: context.hookParentId } : {}),
|
|
3682
|
+
},
|
|
3683
|
+
{
|
|
3684
|
+
settingsHooks: context.settingsHooks,
|
|
3685
|
+
hookDb,
|
|
3686
|
+
matchTarget: name,
|
|
3687
|
+
cwd,
|
|
3688
|
+
asyncDispatcher:
|
|
3689
|
+
context.hookSupervisor &&
|
|
3690
|
+
typeof context.hookSupervisor.dispatch === "function"
|
|
3691
|
+
? (hook, payload) =>
|
|
3692
|
+
context.hookSupervisor.dispatch(
|
|
3693
|
+
[hook.legacyHook || hook],
|
|
3694
|
+
payload,
|
|
3695
|
+
{ cwd, broker },
|
|
3696
|
+
)
|
|
3697
|
+
: null,
|
|
3698
|
+
},
|
|
3699
|
+
);
|
|
3700
|
+
for (const hookResult of outcome.results || []) {
|
|
3701
|
+
if (
|
|
3702
|
+
hookResult?.status === "error" &&
|
|
3703
|
+
String(hookResult.hookId || "").startsWith("settings:")
|
|
3704
|
+
) {
|
|
3705
|
+
recordObserveHookIncident(
|
|
3706
|
+
"PostToolUse",
|
|
3707
|
+
"settings-command",
|
|
3708
|
+
hookResult.error || "hook command failed",
|
|
3709
|
+
);
|
|
3866
3710
|
}
|
|
3867
3711
|
}
|
|
3712
|
+
const feedback = outcome.results?.find(
|
|
3713
|
+
(entry) =>
|
|
3714
|
+
entry.status === "success" &&
|
|
3715
|
+
entry.result &&
|
|
3716
|
+
["block", "deny"].includes(
|
|
3717
|
+
String(
|
|
3718
|
+
entry.result.decision ||
|
|
3719
|
+
entry.result.permissionDecision ||
|
|
3720
|
+
entry.result.hookSpecificOutput?.permissionDecision ||
|
|
3721
|
+
"",
|
|
3722
|
+
).toLowerCase(),
|
|
3723
|
+
),
|
|
3724
|
+
);
|
|
3725
|
+
const reason = feedback?.result?.reason;
|
|
3726
|
+
if (reason) toolResult.hookFeedback = reason;
|
|
3868
3727
|
} catch (error) {
|
|
3869
|
-
recordObserveHookIncident("PostToolUse", "
|
|
3728
|
+
recordObserveHookIncident("PostToolUse", "canonical", error);
|
|
3870
3729
|
}
|
|
3871
3730
|
}
|
|
3872
3731
|
|
|
@@ -3885,7 +3744,7 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3885
3744
|
!(toolResult.background === true && toolResult.status === "running")
|
|
3886
3745
|
) {
|
|
3887
3746
|
try {
|
|
3888
|
-
const outcome = runObserveHooks(
|
|
3747
|
+
const outcome = await runObserveHooks(
|
|
3889
3748
|
context.settingsHooks,
|
|
3890
3749
|
"SubagentStop",
|
|
3891
3750
|
{
|
|
@@ -5813,7 +5672,7 @@ async function executeToolInner(
|
|
|
5813
5672
|
// below so an allow rule can never re-enable a blocked unsafe command.
|
|
5814
5673
|
const requestShellApproval = async (operationArgs) => {
|
|
5815
5674
|
await shellDispatchPolicyAuthority?.revalidate?.();
|
|
5816
|
-
if (
|
|
5675
|
+
if (!ruleAllowed) {
|
|
5817
5676
|
const approvalPolicyVersion = `${shellDispatchPolicyAuthority?.policyVersion || "cc-shell-policy-authority/v1:unobserved"}:shell:${shellPolicy.decision}:${shellPolicy.ruleId || "none"}`;
|
|
5818
5677
|
const gated = await evaluateShellCommandWithApproval({
|
|
5819
5678
|
command: args.command,
|
|
@@ -6209,6 +6068,43 @@ async function executeToolInner(
|
|
|
6209
6068
|
);
|
|
6210
6069
|
if (approvalDenial) return approvalDenial;
|
|
6211
6070
|
|
|
6071
|
+
const createShellProcessAuditContext = () => {
|
|
6072
|
+
const authorization = approvalOutcome || {
|
|
6073
|
+
decision: "allow",
|
|
6074
|
+
via: ruleAllowed ? "settings-rule" : "shell-policy",
|
|
6075
|
+
riskLevel: null,
|
|
6076
|
+
policy: null,
|
|
6077
|
+
};
|
|
6078
|
+
const policyDigest = createHash("sha256")
|
|
6079
|
+
.update(
|
|
6080
|
+
JSON.stringify({
|
|
6081
|
+
authorityVersion:
|
|
6082
|
+
shellDispatchPolicyAuthority?.policyVersion || null,
|
|
6083
|
+
shellDecision: shellPolicy.decision || null,
|
|
6084
|
+
shellRuleId: shellPolicy.ruleId || null,
|
|
6085
|
+
authorization,
|
|
6086
|
+
}),
|
|
6087
|
+
"utf8",
|
|
6088
|
+
)
|
|
6089
|
+
.digest("hex");
|
|
6090
|
+
return Object.freeze({
|
|
6091
|
+
actor: "agent",
|
|
6092
|
+
sessionId: sessionId ? String(sessionId) : null,
|
|
6093
|
+
authorization: Object.freeze({ ...authorization }),
|
|
6094
|
+
policyDigest,
|
|
6095
|
+
});
|
|
6096
|
+
};
|
|
6097
|
+
const shellProcessAuditRedactArgIndexes = () => {
|
|
6098
|
+
const auditArgs = pluginBinInvocation
|
|
6099
|
+
? executionPlugin?.argv
|
|
6100
|
+
: shellInv.useDefaultShell
|
|
6101
|
+
? []
|
|
6102
|
+
: shellInv.argv;
|
|
6103
|
+
return Array.isArray(auditArgs)
|
|
6104
|
+
? auditArgs.map((_, index) => index)
|
|
6105
|
+
: [];
|
|
6106
|
+
};
|
|
6107
|
+
|
|
6212
6108
|
let shellDispatchAdmitted = false;
|
|
6213
6109
|
const admitShellDispatch = async () => {
|
|
6214
6110
|
if (shellDispatchAdmitted) {
|
|
@@ -6337,6 +6233,10 @@ async function executeToolInner(
|
|
|
6337
6233
|
policy: "allow",
|
|
6338
6234
|
scope: "agent",
|
|
6339
6235
|
sandboxPolicy: pluginBinSandboxPolicy,
|
|
6236
|
+
requirePersistentAudit: true,
|
|
6237
|
+
auditRedactCommand: true,
|
|
6238
|
+
auditRedactArgIndexes: [launchArgs.length - 1],
|
|
6239
|
+
auditContext: createShellProcessAuditContext(),
|
|
6340
6240
|
};
|
|
6341
6241
|
const issuer =
|
|
6342
6242
|
_backgroundProcessDeps.issueLinuxWorkspaceSandboxExecutionContract;
|
|
@@ -6447,6 +6347,10 @@ async function executeToolInner(
|
|
|
6447
6347
|
origin: processOrigin,
|
|
6448
6348
|
policy: "allow",
|
|
6449
6349
|
scope: "agent",
|
|
6350
|
+
requirePersistentAudit: true,
|
|
6351
|
+
auditRedactCommand: true,
|
|
6352
|
+
auditRedactArgIndexes: shellProcessAuditRedactArgIndexes(),
|
|
6353
|
+
auditContext: createShellProcessAuditContext(),
|
|
6450
6354
|
...processProvenance,
|
|
6451
6355
|
}
|
|
6452
6356
|
: null;
|
|
@@ -6638,6 +6542,7 @@ async function executeToolInner(
|
|
|
6638
6542
|
maxBuffer: 1024 * 1024,
|
|
6639
6543
|
egressProxy,
|
|
6640
6544
|
env: sandboxChildEnvironment,
|
|
6545
|
+
auditContext: createShellProcessAuditContext(),
|
|
6641
6546
|
});
|
|
6642
6547
|
} finally {
|
|
6643
6548
|
if (proxyHandle) {
|
|
@@ -6697,6 +6602,10 @@ async function executeToolInner(
|
|
|
6697
6602
|
origin: processOrigin,
|
|
6698
6603
|
policy: "allow",
|
|
6699
6604
|
scope: "agent",
|
|
6605
|
+
requirePersistentAudit: true,
|
|
6606
|
+
auditRedactCommand: true,
|
|
6607
|
+
auditRedactArgIndexes: shellProcessAuditRedactArgIndexes(),
|
|
6608
|
+
auditContext: createShellProcessAuditContext(),
|
|
6700
6609
|
...processProvenance,
|
|
6701
6610
|
};
|
|
6702
6611
|
if (pluginBinInvocation) {
|
|
@@ -8358,20 +8267,9 @@ async function executeToolInner(
|
|
|
8358
8267
|
return attachDescriptor(deferredGate);
|
|
8359
8268
|
}
|
|
8360
8269
|
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
} catch (error) {
|
|
8365
|
-
return attachDescriptor({
|
|
8366
|
-
error:
|
|
8367
|
-
"MCP tool blocked because its input is not strict immutable JSON data",
|
|
8368
|
-
policy: {
|
|
8369
|
-
decision: "blocked",
|
|
8370
|
-
via: "mcp-wire-input",
|
|
8371
|
-
code: safeMcpErrorCode(error, "CC_MCP_WIRE_INPUT_INVALID"),
|
|
8372
|
-
},
|
|
8373
|
-
});
|
|
8374
|
-
}
|
|
8270
|
+
// executeTool admitted this immutable snapshot before permission and
|
|
8271
|
+
// Hook processing; reuse the exact object for ledger and transport.
|
|
8272
|
+
const mcpWireInput = args;
|
|
8375
8273
|
|
|
8376
8274
|
if (
|
|
8377
8275
|
mcpDispatchAdmission !== null &&
|
|
@@ -9885,7 +9783,7 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9885
9783
|
// returns). Best-effort — a hook error never blocks the spawn.
|
|
9886
9784
|
if (ctx.settingsHooks) {
|
|
9887
9785
|
try {
|
|
9888
|
-
const startOutcome = runObserveHooks(
|
|
9786
|
+
const startOutcome = await runObserveHooks(
|
|
9889
9787
|
ctx.settingsHooks,
|
|
9890
9788
|
"SubagentStart",
|
|
9891
9789
|
{
|
|
@@ -10650,14 +10548,40 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
10650
10548
|
options.providerRequestId,
|
|
10651
10549
|
);
|
|
10652
10550
|
|
|
10653
|
-
|
|
10551
|
+
let tools = getEffectiveToolDefinitions(options);
|
|
10552
|
+
if (Array.isArray(options.contextMemorySelectedToolNames)) {
|
|
10553
|
+
const selected = new Set(options.contextMemorySelectedToolNames);
|
|
10554
|
+
tools = tools.filter((tool) => selected.has(tool?.function?.name));
|
|
10555
|
+
}
|
|
10654
10556
|
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10660
|
-
|
|
10557
|
+
let providerMessages = rawMessages;
|
|
10558
|
+
let canonicalPlan = null;
|
|
10559
|
+
if (
|
|
10560
|
+
options.contextMemoryPreplanned !== true &&
|
|
10561
|
+
options.contextMemorySkipPlanning !== true
|
|
10562
|
+
) {
|
|
10563
|
+
const { prepareCanonicalProviderContext } =
|
|
10564
|
+
await import("../lib/context-memory-kernel/provider-context.js");
|
|
10565
|
+
const prepared = await prepareCanonicalProviderContext(rawMessages, {
|
|
10566
|
+
...options,
|
|
10567
|
+
contextMemoryToolDefinitions: tools,
|
|
10568
|
+
});
|
|
10569
|
+
providerMessages = prepared.messages;
|
|
10570
|
+
canonicalPlan = prepared.plan;
|
|
10571
|
+
if (canonicalPlan) {
|
|
10572
|
+
const selected = new Set(prepared.selectedToolNames);
|
|
10573
|
+
tools = tools.filter((tool) => selected.has(tool?.function?.name));
|
|
10574
|
+
}
|
|
10575
|
+
}
|
|
10576
|
+
const lastUserMsg = [...providerMessages]
|
|
10577
|
+
.reverse()
|
|
10578
|
+
.find((m) => m.role === "user");
|
|
10579
|
+
const messages =
|
|
10580
|
+
ce && !canonicalPlan
|
|
10581
|
+
? ce.buildOptimizedMessages(providerMessages, {
|
|
10582
|
+
userQuery: lastUserMsg?.content,
|
|
10583
|
+
})
|
|
10584
|
+
: providerMessages;
|
|
10661
10585
|
|
|
10662
10586
|
throwIfAborted(signal);
|
|
10663
10587
|
|
|
@@ -12775,9 +12699,19 @@ async function _getAutoCompactor(options) {
|
|
|
12775
12699
|
return _instrumentAutoCompactorUsage(options._autoCompactor, options);
|
|
12776
12700
|
}
|
|
12777
12701
|
let compressor = null;
|
|
12702
|
+
let canonicalRequired = false;
|
|
12778
12703
|
try {
|
|
12779
12704
|
const { feature } = await import("../lib/feature-flags.js");
|
|
12780
|
-
|
|
12705
|
+
const { resolveCliContextMemoryCutover } =
|
|
12706
|
+
await import("../lib/context-memory-kernel/authority.js");
|
|
12707
|
+
const cutover = resolveCliContextMemoryCutover({
|
|
12708
|
+
env: options.contextMemoryEnv || process.env,
|
|
12709
|
+
scopeKey: options.sessionId
|
|
12710
|
+
? `cli:session:${options.sessionId}`
|
|
12711
|
+
: "cli:live-session",
|
|
12712
|
+
});
|
|
12713
|
+
canonicalRequired = cutover.canonical;
|
|
12714
|
+
if (feature("PROMPT_COMPRESSOR") || cutover.canonical) {
|
|
12781
12715
|
const { PromptCompressor } =
|
|
12782
12716
|
await import("../harness/prompt-compressor.js");
|
|
12783
12717
|
const llmQuery =
|
|
@@ -12798,6 +12732,7 @@ async function _getAutoCompactor(options) {
|
|
|
12798
12732
|
{
|
|
12799
12733
|
...options,
|
|
12800
12734
|
contextEngine: null,
|
|
12735
|
+
contextMemorySkipPlanning: true,
|
|
12801
12736
|
enabledToolNames: [],
|
|
12802
12737
|
extraToolDefinitions: [],
|
|
12803
12738
|
hostManagedToolPolicy: null,
|
|
@@ -12824,8 +12759,35 @@ async function _getAutoCompactor(options) {
|
|
|
12824
12759
|
summaryInputMaxChars: options.compactionInputMaxChars,
|
|
12825
12760
|
});
|
|
12826
12761
|
compressor = _instrumentAutoCompactorUsage(compressor, options);
|
|
12762
|
+
if (cutover.canonical) {
|
|
12763
|
+
const compatibilitySummarizer = compressor;
|
|
12764
|
+
const { compactLiveMessagesCanonical } =
|
|
12765
|
+
await import("../lib/context-memory-kernel/live-compaction.js");
|
|
12766
|
+
compressor = {
|
|
12767
|
+
canonicalKernel: true,
|
|
12768
|
+
shouldAutoCompact: (messages) =>
|
|
12769
|
+
compatibilitySummarizer.shouldAutoCompact(messages),
|
|
12770
|
+
compress: async (messages, compressOptions = {}) => {
|
|
12771
|
+
return compactLiveMessagesCanonical(messages, {
|
|
12772
|
+
compressor: compatibilitySummarizer,
|
|
12773
|
+
compressOptions,
|
|
12774
|
+
sessionId: options.sessionId,
|
|
12775
|
+
operationId: `auto-${randomUUID()}`,
|
|
12776
|
+
provider: options.provider,
|
|
12777
|
+
model: options.model,
|
|
12778
|
+
env: options.contextMemoryEnv || process.env,
|
|
12779
|
+
persist: options.persistCompaction !== false,
|
|
12780
|
+
trigger: "auto",
|
|
12781
|
+
...(typeof options.onCompaction === "function"
|
|
12782
|
+
? { commit: options.onCompaction }
|
|
12783
|
+
: {}),
|
|
12784
|
+
});
|
|
12785
|
+
},
|
|
12786
|
+
};
|
|
12787
|
+
}
|
|
12827
12788
|
}
|
|
12828
|
-
} catch {
|
|
12789
|
+
} catch (error) {
|
|
12790
|
+
if (canonicalRequired) throw error;
|
|
12829
12791
|
compressor = null;
|
|
12830
12792
|
}
|
|
12831
12793
|
try {
|
|
@@ -12906,7 +12868,9 @@ async function _settleAutomaticCompaction({
|
|
|
12906
12868
|
}
|
|
12907
12869
|
|
|
12908
12870
|
let settlement = null;
|
|
12909
|
-
if (
|
|
12871
|
+
if (stats?.canonicalAlreadySettled === true) {
|
|
12872
|
+
settlement = stats.canonicalReceipt || null;
|
|
12873
|
+
} else if (typeof options.onCompaction === "function") {
|
|
12910
12874
|
if (options.onCompaction.constructor?.name === "AsyncFunction") {
|
|
12911
12875
|
throw _compactionSettlementError(
|
|
12912
12876
|
"CC_COMPACTION_SETTLEMENT_ASYNC",
|
|
@@ -13597,7 +13561,10 @@ export async function* agentLoop(messages, options) {
|
|
|
13597
13561
|
// the full compaction below is skipped this round — so heavy-tool
|
|
13598
13562
|
// conversations rarely hit a full summarize. Opt out:
|
|
13599
13563
|
// autoMicroCompact: false.
|
|
13600
|
-
if (
|
|
13564
|
+
if (
|
|
13565
|
+
options.autoMicroCompact !== false &&
|
|
13566
|
+
compactor.canonicalKernel !== true
|
|
13567
|
+
) {
|
|
13601
13568
|
try {
|
|
13602
13569
|
const { microCompact } = await import("../lib/micro-compact.js");
|
|
13603
13570
|
const mc = microCompact(messages);
|
|
@@ -13623,7 +13590,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13623
13590
|
let preCompactReason = null;
|
|
13624
13591
|
if (!hermeticExecution && needFull && options.settingsHooks) {
|
|
13625
13592
|
try {
|
|
13626
|
-
const pc = runObserveHooks(
|
|
13593
|
+
const pc = await runObserveHooks(
|
|
13627
13594
|
options.settingsHooks,
|
|
13628
13595
|
"PreCompact",
|
|
13629
13596
|
{
|
|
@@ -13670,6 +13637,31 @@ export async function* agentLoop(messages, options) {
|
|
|
13670
13637
|
preserveToolPairs: true,
|
|
13671
13638
|
...pinOpts,
|
|
13672
13639
|
});
|
|
13640
|
+
if (
|
|
13641
|
+
stats?.canonicalReceipt &&
|
|
13642
|
+
!["committed", "degraded"].includes(stats.canonicalReceipt.status)
|
|
13643
|
+
) {
|
|
13644
|
+
automaticCompactionSettlementBlocked = true;
|
|
13645
|
+
yield {
|
|
13646
|
+
type: "compaction-degraded",
|
|
13647
|
+
runId,
|
|
13648
|
+
reason:
|
|
13649
|
+
stats.canonicalReceipt.status === "stale"
|
|
13650
|
+
? "session_messages_changed_during_compaction"
|
|
13651
|
+
: "canonical_compaction_reconciliation_required",
|
|
13652
|
+
summaryMode: "none",
|
|
13653
|
+
code:
|
|
13654
|
+
stats.canonicalReceipt.status === "stale"
|
|
13655
|
+
? "SESSION_REVISION_STALE"
|
|
13656
|
+
: "CC_COMPACTION_RECONCILIATION_REQUIRED",
|
|
13657
|
+
receipt: stats.canonicalReceipt,
|
|
13658
|
+
};
|
|
13659
|
+
await _awaitBackgroundUsageSettlement(
|
|
13660
|
+
backgroundSubAgents,
|
|
13661
|
+
backgroundUsageFailureState,
|
|
13662
|
+
);
|
|
13663
|
+
return;
|
|
13664
|
+
}
|
|
13673
13665
|
const observerFailure = compactionUsageState.calls.find(
|
|
13674
13666
|
(call) => call.observerFailed,
|
|
13675
13667
|
);
|
|
@@ -13937,7 +13929,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13937
13929
|
// spawn-time handle skips it); a block reason rides along as feedback.
|
|
13938
13930
|
if (!hermeticExecution && options.settingsHooks) {
|
|
13939
13931
|
try {
|
|
13940
|
-
const outcome = runObserveHooks(
|
|
13932
|
+
const outcome = await runObserveHooks(
|
|
13941
13933
|
options.settingsHooks,
|
|
13942
13934
|
"SubagentStop",
|
|
13943
13935
|
{
|
|
@@ -13982,6 +13974,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13982
13974
|
// prepareCall runs fresh each iteration and returns an ephemeral
|
|
13983
13975
|
// system-message supplement that is NOT persisted to messages history.
|
|
13984
13976
|
let callMessages = messages;
|
|
13977
|
+
const contextMemoryTrustedSystemIndexes = [];
|
|
13985
13978
|
if (!hermeticExecution && typeof options.prepareCall === "function") {
|
|
13986
13979
|
try {
|
|
13987
13980
|
const hook = await options.prepareCall({
|
|
@@ -13998,6 +13991,7 @@ export async function* agentLoop(messages, options) {
|
|
|
13998
13991
|
...messages,
|
|
13999
13992
|
{ role: "system", content: hook.systemSuffix },
|
|
14000
13993
|
];
|
|
13994
|
+
contextMemoryTrustedSystemIndexes.push(callMessages.length - 1);
|
|
14001
13995
|
}
|
|
14002
13996
|
} catch (_e) {
|
|
14003
13997
|
// prepareCall failures are non-critical — proceed with original messages
|
|
@@ -14010,6 +14004,29 @@ export async function* agentLoop(messages, options) {
|
|
|
14010
14004
|
// model request within that turn. Normalized through buildTelemetryAttributes
|
|
14011
14005
|
// so they get the same charset-sanitized + cardinality-bounded treatment as
|
|
14012
14006
|
// the run-level ids (turn.id correlates with the agent.iteration counter).
|
|
14007
|
+
let canonicalProviderContext = null;
|
|
14008
|
+
if (options.contextMemorySkipPlanning !== true) {
|
|
14009
|
+
const { prepareCanonicalProviderContext } =
|
|
14010
|
+
await import("../lib/context-memory-kernel/provider-context.js");
|
|
14011
|
+
canonicalProviderContext = await prepareCanonicalProviderContext(
|
|
14012
|
+
callMessages,
|
|
14013
|
+
{
|
|
14014
|
+
...options,
|
|
14015
|
+
contextMemoryToolDefinitions:
|
|
14016
|
+
getEffectiveToolDefinitions(effectiveToolOptions),
|
|
14017
|
+
contextMemoryTrustedSystemIndexes,
|
|
14018
|
+
},
|
|
14019
|
+
);
|
|
14020
|
+
if (canonicalProviderContext.plan) {
|
|
14021
|
+
callMessages = canonicalProviderContext.messages;
|
|
14022
|
+
yield {
|
|
14023
|
+
type: "context.plan.created",
|
|
14024
|
+
plan: canonicalProviderContext.plan,
|
|
14025
|
+
recallDigest: canonicalProviderContext.recall?.digest || null,
|
|
14026
|
+
};
|
|
14027
|
+
}
|
|
14028
|
+
}
|
|
14029
|
+
|
|
14013
14030
|
const modelIdAttrs = recorder
|
|
14014
14031
|
? buildTelemetryAttributes({
|
|
14015
14032
|
turnId: `${runId}:t${budget.consumed}`,
|
|
@@ -14024,9 +14041,18 @@ export async function* agentLoop(messages, options) {
|
|
|
14024
14041
|
"model",
|
|
14025
14042
|
budget.consumed,
|
|
14026
14043
|
);
|
|
14027
|
-
const
|
|
14028
|
-
? {
|
|
14044
|
+
const plannedProviderOptions = canonicalProviderContext?.plan
|
|
14045
|
+
? {
|
|
14046
|
+
...effectiveToolOptions,
|
|
14047
|
+
contextEngine: null,
|
|
14048
|
+
contextMemoryPreplanned: true,
|
|
14049
|
+
contextMemorySelectedToolNames:
|
|
14050
|
+
canonicalProviderContext.selectedToolNames,
|
|
14051
|
+
}
|
|
14029
14052
|
: effectiveToolOptions;
|
|
14053
|
+
const providerCallOptions = providerRequestId
|
|
14054
|
+
? { ...plannedProviderOptions, providerRequestId }
|
|
14055
|
+
: plannedProviderOptions;
|
|
14030
14056
|
const modelUsageCall = {
|
|
14031
14057
|
type: "model-usage-started",
|
|
14032
14058
|
callId: _newModelUsageCallId("model"),
|
|
@@ -14275,7 +14301,7 @@ export async function* agentLoop(messages, options) {
|
|
|
14275
14301
|
if (!hermeticExecution && options.settingsHooks) {
|
|
14276
14302
|
let stopOutcome = null;
|
|
14277
14303
|
try {
|
|
14278
|
-
stopOutcome = runObserveHooks(
|
|
14304
|
+
stopOutcome = await runObserveHooks(
|
|
14279
14305
|
options.settingsHooks,
|
|
14280
14306
|
"Stop",
|
|
14281
14307
|
{
|