chainlesschain 0.162.197 → 0.162.200
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/bin/chainlesschain.js +14 -6
- package/package.json +4 -1
- package/scripts/command-lifecycle-report.mjs +94 -0
- package/src/assets/web-panel/assets/{AIOps-D3Gu1a5d.js → AIOps-DcQ0bWKy.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DrwAoKaz.js → ActionButton-GecwfFPt.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C7Q-gd_3.js → Analytics-CD6iSt9v.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DgBtae-n.js → AppLayout-CDEtuEYf.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-pQ6LcA-W.js → Artifacts-DS3jAjeW.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DK61tocB.js → Audit-CcSJA048.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BOKgDFRh.js → BackgroundAgents-DRo9Morb.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Bo9G4vTP.js → Backup-Vw5MrWft.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Do_dE9_v.js → BaseInput-DNHIu823.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-COVvZzOL.js → Chat-DvAsO8-b.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-9aDuObay.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Z9MJMolt.js → Checkbox-CKCa7tvn.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BVzWKVbf.js → Codegen-CIFvZdaT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C8MnYcbT.js → Col-C79yz7bK.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DQxqw15l.js → Community-DVvZskLJ.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BAUmrh3y.js → Compact-oaew61hV.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-jPAkQ3zK.js → Compliance-DqA7wmRx.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BBQyxbh8.js → Cowork-B-qGadxa.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-W5koq8Z5.js → Cron-CUlCl4sS.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BQhnu5hS.js → Crosschain-CNOlr9DU.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DD7PlI18.js → DID-DJqFCT_3.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-w_ILuwKI.js → Dashboard-CznGpphf.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-qiDUAyAo.js → Dropdown-_cJw218E.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-PDeBcI5H.js → EmailListRenderer-Dr-1BZ9C.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-SuArscRM.js → FamilyGuardDashboard-Dxf4xtSk.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BCovZaUn.js → Federation-DOiG3i_1.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DjlFdVFk.js → FormItemContext-BzbMcFB9.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DoEZ7fcS.js → GenericCardRenderer-VbBrYttP.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CV0-6GPI.js → Git-CLG8E6ED.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-B_SFN50w.js → Governance-LGJQfk_q.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-heI0Eo6k.js → Inference-DlQKx9lF.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cz5INS5p.js → KnowledgeGraph-DU8vEouV.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BSFxiHkg.js → Logs-FZIQOdln.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BJNWIrbw.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-0TWTpE7k.js → Marketplace-C_xd-zZI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CV4-wBLm.js → McpTools-q-YktphS.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-x5bH5rw5.js → Memory-Cq9OhDin.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DaBmUu9G.js → MobileBridge-B03_R98T.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-DZrk-qmF.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B_zKEBif.js → Mtc-BidCKW28.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BCfKD2yg.js → MtcAudit-r-iaMVM7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DgYfj6c_.js → Multisig-CgTUFvff.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dz09lFUm.js → NLProgramming-B7NvzfAV.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cuj6ugBE.js → Notes-80CWNqJI.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DK2WXjhg.js → NotificationSettings-0H6xdiY3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-D1IAOQoo.js → OrderTableRenderer-CKP4AFWy.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-9fqnPvTw.js → Organization-B8sxCV_h.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-n5xHkhow.js → Overflow-CW9JBBhQ.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B5AUWwH-.js → P2P-bdSQV7oZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CoUDV6dy.js → PdhVaultBrowser-DQad42nW.js} +4 -4
- package/src/assets/web-panel/assets/{Permissions-DPRmQf_H.js → Permissions-CueexxTR.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B37bsbEN.js → PersonalDataHub-fqxflhR8.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-CCAuPqu9.js → Pipeline-KFwwnIMC.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B81msZdv.js → Privacy-ClnD9buY.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B-Py2NbF.js → ProjectInit-CZEz6sm3.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CYsneiRB.js → ProjectSettings-B6NzpmOI.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Y975Mh6R.js → Projects-DYyuwPCs.js} +1 -1
- package/src/assets/web-panel/assets/Providers-C3tz_jdh.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-Bj_6gJ0l.js → QrScannerModal-BzuOBbqB.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BgpBCMPE.js → QuickAsk-CmNO9qSj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DhUW3YUA.js → Recommend-VJNj3_NF.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DdeyfbkA.js → RemoteSession-CrbdbSBF.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-fxW421xd.js → Reputation-DTyMd45j.js} +1 -1
- package/src/assets/web-panel/assets/{Row-De73w1og.js → Row-DHrQ-Icz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-3US_Q_lj.js → RssFeed-DqWxY9c5.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DbZ_DU74.js → Search-ctF1Ks3J.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DoIU1vMF.js → Security-BrQz8uo5.js} +4 -4
- package/src/assets/web-panel/assets/{Services-DB_RGqpc.js → Services-D4scVFar.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DnzLaayC.js → Skeleton-oUScaOjv.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-VzVXHENF.js → Skills-CL-y0eLt.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DMfvjCAI.js → Sla-DQExhwXj.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DQQOYWbF.js → SpeechSettings-iNp_I7kN.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Bmx3FG1P.js → SyncSettings-CTDlMo0A.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DOQyfb-2.js → Tasks-4kb8l3sc.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D6hTRT7c.js → Templates-BXcL9oXW.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CTPQZAzs.js → Tenant-DLE8eS0D.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B7vII3oH.js → Terminal-DGpUZPPK.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BkiFJeXV.js → TimelineRenderer-C1pWXGPC.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BPPdQMNo.js → Tokens-BYfbfqhZ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BxG8JAEI.js → Trigger-K9YfLOCw.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DHD7nMpM.js → Trust-Ctkq77Hy.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B4BJpU47.js → UkeySign-C6_CSe9J.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CRiGpFx2.js → VideoEditing-Be3rpOWs.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BSDSNiem.js → Wallet-D0UIplxk.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DLTUh5Zv.js → WebAuthn-CF9bM9I3.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-tW2MwjhD.js → WorkflowEditor-D0H1XVPY.js} +1 -1
- package/src/assets/web-panel/assets/{chat-SgsLQ3FC.js → chat-Cgzzbe0o.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BHjjLIKO.js → colors-BwNxEVS0.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-VceErdKq.js → compact-item-D60Z4Hhs.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BZ332MYl.js → createContext-MFk58XB0.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BJiw369i.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CBTjJOjn.js → hasIn-CRj2SvGO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaCCy6lq.js → index--s45_1cb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMVvxIS8.js → index--tquQ2ZG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BhXZEUAc.js → index-1T1rhokn.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQSmZGgs.js → index-B-M82_rx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BeiqkxJG.js → index-BE_el1Zs.js} +1 -1
- package/src/assets/web-panel/assets/{index-29wVzi-k.js → index-BhRkR7IO.js} +1 -1
- package/src/assets/web-panel/assets/{index-iYQNU9za.js → index-Bo0y96-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRWhLbWF.js → index-CJgu5JUK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPXFLYdW.js → index-CLWwdebO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr4rjlW5.js → index-CNAK5QG_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaIS_TNX.js → index-CQjJjPRD.js} +1 -1
- package/src/assets/web-panel/assets/{index-1n7xjKDU.js → index-CTDbAfae.js} +1 -1
- package/src/assets/web-panel/assets/{index-BETEjuNr.js → index-CVI_9sRK.js} +1 -1
- package/src/assets/web-panel/assets/{index-By5jBtkV.js → index-CY14oMQK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgPvuIn2.js → index-CbiTJkZf.js} +1 -1
- package/src/assets/web-panel/assets/index-CiMouosn.js +1 -0
- package/src/assets/web-panel/assets/{index-CawpdGTW.js → index-CqWpxMqx.js} +1 -1
- package/src/assets/web-panel/assets/{index-_PHrIO4O.js → index-CvB8lYUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOtvPdHt.js → index-D51XwtCY.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrUgDQkf.js → index-D6HvK_1O.js} +1 -1
- package/src/assets/web-panel/assets/{index-BY1wexYG.js → index-D9jVIwLJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_B9rFQE.js → index-DA4tE98u.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5KAGxNo.js → index-DBwOtXw0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC1xuQgX.js → index-DKdNzTIb.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2u26AS3.js → index-DRySdmvN.js} +1 -1
- package/src/assets/web-panel/assets/{index-DePOeMDM.js → index-DWzyTev7.js} +1 -1
- package/src/assets/web-panel/assets/index-DXcKlwy7.js +1 -0
- package/src/assets/web-panel/assets/{index-BTlc-Bve.js → index-DYjs7jAP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLc19alH.js → index-DbROzMBp.js} +1 -1
- package/src/assets/web-panel/assets/{index-fU7wNHDB.js → index-DhFtk5PR.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_SePDWj.js → index-Di2AbMLg.js} +1 -1
- package/src/assets/web-panel/assets/{index-vIXOpcjD.js → index-DvmocQsM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcUenmCX.js → index-Dw-o0zEF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUkVN794.js → index-DysPoP38.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtjLcCNU.js → index-LX9pJxm_.js} +1 -1
- package/src/assets/web-panel/assets/{index-B40dQn0G.js → index-OI_fXWx0.js} +3 -3
- package/src/assets/web-panel/assets/{index-FJ3zC9LK.js → index-eDTOX8Xj.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdefYBSw.js → index-gWKDsTzF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpumS98o.js → index-q_GDUVAA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D1oZNz0D.js → initDefaultProps-C61kZqEd.js} +1 -1
- package/src/assets/web-panel/assets/{motion-C8k6doMO.js → motion-DZnT5U1L.js} +1 -1
- package/src/assets/web-panel/assets/{move-DJ4qSbYt.js → move-L8wzwbel.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CdpJD85j.js → mtc-parser-DLdYSejc.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B0V4slKA.js → omit-D53cbS59.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Di5NiW1F.js → pickAttrs-Bbc5HPtu.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B5OMHgEM.js → placementArrow-BkvmO860.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C6U9IWql.js → responsiveObserve-u2y1ryS1.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BMyTH3rN.js → slide-BBqj7svU.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C7d6BG7Z.js → statusUtils-GN0mqu2d.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CR50QnQy.js → styleChecker-BvwPKoBT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DBEeoMb8.js → useFlexGapSupport-CCt8tnfY.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-3r099cjv.js → useFs-DXAxl2SV.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-C5IYNdTK.js → usePersonalDataHub-DihlR2dj.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DmEOLRHf.js → vnode-D7BOX2gi.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DnpUiVCB.js → zoom-CVbO-nL7.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +4 -4
- package/src/commands/agent.js +3 -3
- package/src/commands/background-session.js +145 -0
- package/src/commands/mcp.js +244 -7
- package/src/commands/serve.js +1 -1
- package/src/commands/session-show.js +129 -0
- package/src/commands/session.js +97 -145
- package/src/commands/skill.js +87 -50
- package/src/data/changelog.json +40 -1
- package/src/gateways/ws/session-protocol.js +14 -4
- package/src/gateways/ws/ws-agent-handler.js +39 -1
- package/src/harness/jsonl-session-store.js +1547 -127
- package/src/harness/mcp-client.js +2690 -409
- package/src/harness/session-index.js +80 -80
- package/src/harness/session-list-index.js +210 -7
- package/src/lazy-dispatch.js +76 -8
- package/src/lib/abort-utils.js +68 -0
- package/src/lib/agent-core.js +1 -59
- package/src/lib/background-interaction-journal.js +2 -2
- package/src/lib/chat-core.js +24 -6
- package/src/lib/command-lifecycle-report.js +516 -0
- package/src/lib/cowork-mcp-tools.js +47 -2
- package/src/lib/cowork-task-runner.js +11 -3
- package/src/lib/doctor-checkup.js +9 -7
- package/src/lib/learning/skill-improver.js +21 -2
- package/src/lib/mcp-call-ledger-store.js +116 -3
- package/src/lib/mcp-call-ledger.js +59 -14
- package/src/lib/mcp-client.js +1 -0
- package/src/lib/mcp-stdio-environment.js +48 -0
- package/src/lib/mcp-stdio-executable-identity.js +1133 -0
- package/src/lib/mcp-stdio-execution-authority.js +363 -0
- package/src/lib/mcp-stdio-package-materialization.js +1424 -0
- package/src/lib/mcp-tool-metadata.js +436 -0
- package/src/lib/mcp-tool-result.js +367 -0
- package/src/lib/observability/index.js +71 -0
- package/src/lib/packer/native-update-state.js +979 -1
- package/src/lib/packer/pack-update-applier.js +1050 -125
- package/src/lib/packer/pkg-config-generator.js +1 -0
- package/src/lib/paths.js +53 -0
- package/src/lib/pr-link-ledger.js +8 -27
- package/src/lib/pr-link-store.js +26 -0
- package/src/lib/process-execution-broker/index.js +192 -35
- package/src/lib/process-execution-broker/platform-sandbox.js +291 -24
- package/src/lib/process-tree-termination.js +253 -0
- package/src/lib/recent-session.js +17 -17
- package/src/lib/secure-file-identity.js +47 -0
- package/src/lib/secure-fs.js +21 -2
- package/src/lib/session-anti-rollback-anchor.js +766 -0
- package/src/lib/session-host-lease.js +492 -0
- package/src/lib/session-host-snapshot.js +9 -5
- package/src/lib/session-persistence-failure.js +109 -0
- package/src/lib/session-picker.js +26 -3
- package/src/lib/session-projection.js +5 -1
- package/src/lib/session-search.js +25 -11
- package/src/lib/session-tail.js +31 -1
- package/src/lib/side-effect-ledger-store.js +2 -2
- package/src/lib/skill-budget.js +222 -0
- package/src/lib/skill-execution-authority.js +385 -0
- package/src/lib/skill-execution-identity.js +39 -2
- package/src/lib/skill-loader.js +322 -86
- package/src/lib/skill-mcp.js +43 -1
- package/src/lib/turn-binding-store.js +2 -2
- package/src/repl/agent-repl.js +483 -77
- package/src/repl/bg-dashboard.js +81 -28
- package/src/repl/chat-repl.js +77 -12
- package/src/runtime/agent-core.js +428 -113
- package/src/runtime/agent-runtime.js +26 -3
- package/src/runtime/cleanup-deadline.js +143 -0
- package/src/runtime/headless-runner.js +494 -149
- package/src/runtime/headless-stream.js +504 -75
- package/src/runtime/mcp-config.js +157 -10
- package/src/runtime/mcp-tool-search.js +0 -0
- package/src/runtime/output-backpressure.js +419 -0
- package/src/runtime/pipe-safety.js +56 -21
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BUUyJ5QO.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-1mNozZ8v.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DqnoFPgR.js +0 -1
- package/src/assets/web-panel/assets/Providers-uO-10aP1.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DosMaL-k.js +0 -1
- package/src/assets/web-panel/assets/index-0O5ePnUq.js +0 -1
- package/src/assets/web-panel/assets/index-ChAzPigF.js +0 -1
- package/src/lib/skill-process-broker.js +0 -85
|
@@ -36,6 +36,11 @@ import {
|
|
|
36
36
|
} from "../lib/lsp/workspace-roots.js";
|
|
37
37
|
import { getPlanModeManager } from "../lib/plan-mode.js";
|
|
38
38
|
import { CLISkillLoader } from "../lib/skill-loader.js";
|
|
39
|
+
import {
|
|
40
|
+
admitSkillPrompt,
|
|
41
|
+
debitSkillPromptBudget,
|
|
42
|
+
resolveSkillLimits,
|
|
43
|
+
} from "../lib/skill-budget.js";
|
|
39
44
|
import { executeHooks, HookEvents } from "../lib/hook-manager.js";
|
|
40
45
|
import { detectPython } from "../lib/cli-anything-bridge.js";
|
|
41
46
|
import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
|
|
@@ -52,7 +57,11 @@ import {
|
|
|
52
57
|
} from "./coding-agent-contract.js";
|
|
53
58
|
import { createToolContext } from "../tools/tool-context.js";
|
|
54
59
|
import { createToolTelemetryRecord } from "../tools/tool-telemetry.js";
|
|
55
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
isAbortError,
|
|
62
|
+
raceWithAbort,
|
|
63
|
+
throwIfAborted,
|
|
64
|
+
} from "../lib/abort-utils.js";
|
|
56
65
|
import {
|
|
57
66
|
classifyEditReplay,
|
|
58
67
|
editIdempotencyKey,
|
|
@@ -100,6 +109,10 @@ import {
|
|
|
100
109
|
McpEffect,
|
|
101
110
|
snapshotMcpJsonRpcInput,
|
|
102
111
|
} from "../lib/mcp-call-ledger.js";
|
|
112
|
+
import {
|
|
113
|
+
admitMcpToolResult,
|
|
114
|
+
isMcpToolResultAdmissionError,
|
|
115
|
+
} from "../lib/mcp-tool-result.js";
|
|
103
116
|
import {
|
|
104
117
|
MCP_OUTCOME_UNKNOWN_CODE,
|
|
105
118
|
markMcpLedgerOutcomeUnknown,
|
|
@@ -112,6 +125,7 @@ import {
|
|
|
112
125
|
buildExtractiveHandoff,
|
|
113
126
|
formatStructuredHandoff,
|
|
114
127
|
} from "../harness/structured-handoff.js";
|
|
128
|
+
import { isMcpRpcError } from "../harness/mcp-client.js";
|
|
115
129
|
import { projectCanonicalResumeMessages } from "../lib/session-message-provenance.js";
|
|
116
130
|
|
|
117
131
|
export { formatProviderHttpError };
|
|
@@ -968,11 +982,16 @@ export function getAgentToolDescriptors(options = {}) {
|
|
|
968
982
|
const _defaultSkillLoader = new CLISkillLoader();
|
|
969
983
|
|
|
970
984
|
/**
|
|
971
|
-
* Re-scan all skill layers (Claude-Code `/reload-skills` parity):
|
|
972
|
-
*
|
|
973
|
-
*
|
|
985
|
+
* Re-scan all skill layers (Claude-Code `/reload-skills` parity): revokes this
|
|
986
|
+
* process's Skill execution generation, then drops the default loader cache so
|
|
987
|
+
* newly added/edited SKILL.md dirs are picked up without restarting. Returns
|
|
988
|
+
* the resolved skill count.
|
|
974
989
|
*/
|
|
975
990
|
export function reloadSkills() {
|
|
991
|
+
_defaultSkillLoader.revokeExecutionAuthorizations({
|
|
992
|
+
message: "Skill execution authorization was revoked by /reload-skills",
|
|
993
|
+
reasonCode: "reload-skills",
|
|
994
|
+
});
|
|
976
995
|
_defaultSkillLoader.clearCache();
|
|
977
996
|
return _defaultSkillLoader.loadAll().length;
|
|
978
997
|
}
|
|
@@ -1246,13 +1265,34 @@ export function buildSystemPrompt(cwd, opts = {}) {
|
|
|
1246
1265
|
turnId: opts.turnId,
|
|
1247
1266
|
loadedBecause: "persona_auto",
|
|
1248
1267
|
});
|
|
1268
|
+
// Re-admit custom/injected loader output at the final model boundary. Do
|
|
1269
|
+
// the complete aggregate pass before appending anything so an oversized
|
|
1270
|
+
// later persona cannot leave an earlier partial projection in the prompt.
|
|
1271
|
+
const limits = resolveSkillLimits(loader.getLimits?.());
|
|
1272
|
+
const promptBudget = { limits, bytes: 0, tokens: 0 };
|
|
1273
|
+
const personaProjections = [];
|
|
1274
|
+
for (const personaSkill of personaSkills) {
|
|
1275
|
+
const displayName =
|
|
1276
|
+
typeof personaSkill?.displayName === "string"
|
|
1277
|
+
? personaSkill.displayName
|
|
1278
|
+
: typeof personaSkill?.id === "string"
|
|
1279
|
+
? personaSkill.id
|
|
1280
|
+
: "Skill";
|
|
1281
|
+
const body = personaSkill?.body;
|
|
1282
|
+
admitSkillPrompt(body, limits);
|
|
1283
|
+
if (!body.trim()) continue;
|
|
1284
|
+
const projection = `\n\n## Persona: ${displayName}\n${body}`;
|
|
1285
|
+
debitSkillPromptBudget(
|
|
1286
|
+
promptBudget,
|
|
1287
|
+
admitSkillPrompt(projection, limits),
|
|
1288
|
+
);
|
|
1289
|
+
personaProjections.push(projection);
|
|
1290
|
+
}
|
|
1249
1291
|
if (typeof opts.onSkillsLoaded === "function") {
|
|
1250
1292
|
opts.onSkillsLoaded(personaSkills, loader.getCacheLedger());
|
|
1251
1293
|
}
|
|
1252
|
-
for (const
|
|
1253
|
-
|
|
1254
|
-
prompt += `\n\n## Persona: ${p.displayName}\n${p.body}`;
|
|
1255
|
-
}
|
|
1294
|
+
for (const projection of personaProjections) {
|
|
1295
|
+
prompt += projection;
|
|
1256
1296
|
}
|
|
1257
1297
|
} catch {
|
|
1258
1298
|
// Non-critical — skill loader may not be available
|
|
@@ -1773,6 +1813,11 @@ export async function executeTool(name, args, context = {}) {
|
|
|
1773
1813
|
typeof context.externalToolDescriptors === "object"
|
|
1774
1814
|
? context.externalToolDescriptors[name] || null
|
|
1775
1815
|
: null;
|
|
1816
|
+
const localToolExecutor =
|
|
1817
|
+
context.externalToolExecutors &&
|
|
1818
|
+
typeof context.externalToolExecutors === "object"
|
|
1819
|
+
? context.externalToolExecutors[name] || null
|
|
1820
|
+
: null;
|
|
1776
1821
|
const runtimeDescriptor =
|
|
1777
1822
|
getRuntimeToolDescriptor(name) || localToolDescriptor;
|
|
1778
1823
|
const admission = context.toolAdmission;
|
|
@@ -2046,6 +2091,69 @@ export async function executeTool(name, args, context = {}) {
|
|
|
2046
2091
|
ruleAllowed = true;
|
|
2047
2092
|
}
|
|
2048
2093
|
|
|
2094
|
+
// MCP annotations are peer-provided hints, never execution authority. A
|
|
2095
|
+
// server that claims readOnlyHint=true therefore still needs a request-level
|
|
2096
|
+
// approval unless the host independently authorized this exact tool as a
|
|
2097
|
+
// trusted read. An explicit settings allow can suppress the default prompt,
|
|
2098
|
+
// but it cannot suppress a host-owned `ask`/requiresConfirmation decision.
|
|
2099
|
+
// Plan mode has already applied its stricter hard ceiling above, so this gate
|
|
2100
|
+
// covers normal interactive/Auto execution without creating a Plan escape.
|
|
2101
|
+
if (localToolExecutor?.kind === "mcp") {
|
|
2102
|
+
const mcpEffectContract = mcpLedgerEffectContract(
|
|
2103
|
+
localToolDescriptor,
|
|
2104
|
+
hostToolPolicy,
|
|
2105
|
+
);
|
|
2106
|
+
const trustedHostRead =
|
|
2107
|
+
mcpEffectContract.effect === McpEffect.READ &&
|
|
2108
|
+
mcpEffectContract.trusted === true;
|
|
2109
|
+
const settingsAskWasConfirmed =
|
|
2110
|
+
settingsVerdict.decision === "ask" && ruleAllowed;
|
|
2111
|
+
const hostRequiresConfirmation =
|
|
2112
|
+
!settingsAskWasConfirmed &&
|
|
2113
|
+
(hostToolPolicy?.requiresConfirmation === true ||
|
|
2114
|
+
hostToolPolicy?.decision === "ask");
|
|
2115
|
+
const defaultRequiresConfirmation = !trustedHostRead && !ruleAllowed;
|
|
2116
|
+
|
|
2117
|
+
if (hostRequiresConfirmation || defaultRequiresConfirmation) {
|
|
2118
|
+
const approved = await requestInteractivePermission(
|
|
2119
|
+
name,
|
|
2120
|
+
args,
|
|
2121
|
+
context,
|
|
2122
|
+
cwd,
|
|
2123
|
+
{
|
|
2124
|
+
tool: name,
|
|
2125
|
+
args,
|
|
2126
|
+
rule: null,
|
|
2127
|
+
reason: hostRequiresConfirmation
|
|
2128
|
+
? "host policy requires confirmation for this MCP tool"
|
|
2129
|
+
: `MCP effect is ${mcpEffectContract.effect} and lacks a trusted host read authorization`,
|
|
2130
|
+
source: hostRequiresConfirmation
|
|
2131
|
+
? "host-managed MCP policy"
|
|
2132
|
+
: "MCP effect contract",
|
|
2133
|
+
mcpEffect: mcpEffectContract.effect,
|
|
2134
|
+
mcpTrusted: mcpEffectContract.trusted === true,
|
|
2135
|
+
},
|
|
2136
|
+
);
|
|
2137
|
+
if (!approved) {
|
|
2138
|
+
return {
|
|
2139
|
+
error: `[MCP Permission] Tool "${name}" requires confirmation because its effect is ${mcpEffectContract.effect} and it does not have an applicable trusted host read authorization — denied.`,
|
|
2140
|
+
policy: {
|
|
2141
|
+
decision: "ask",
|
|
2142
|
+
via: hostRequiresConfirmation
|
|
2143
|
+
? "host-mcp-policy"
|
|
2144
|
+
: "mcp-effect-contract",
|
|
2145
|
+
code: "CC_MCP_EFFECT_CONFIRMATION_REQUIRED",
|
|
2146
|
+
effect: mcpEffectContract.effect,
|
|
2147
|
+
trusted: mcpEffectContract.trusted === true,
|
|
2148
|
+
},
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
// The approval is scoped to this request and also satisfies the later
|
|
2152
|
+
// generic external-tool/ApprovalGate prompt for the same invocation.
|
|
2153
|
+
ruleAllowed = true;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2049
2157
|
// Sensitive-file write guard (Claude-Code 2.1.160 parity): shell startup
|
|
2050
2158
|
// files / PowerShell profiles / git+husky hooks execute code on the user's
|
|
2051
2159
|
// next shell or commit — even otherwise-permitted edit flows confirm first.
|
|
@@ -3279,11 +3387,18 @@ function mcpLedgerEffectContract(descriptor, hostPolicy) {
|
|
|
3279
3387
|
)
|
|
3280
3388
|
? descriptorContract.declaredEffect
|
|
3281
3389
|
: "unknown";
|
|
3390
|
+
// Host authority may raise an unknown/read declaration to a stricter effect,
|
|
3391
|
+
// but it may never downgrade the conservative peer risk floor. In
|
|
3392
|
+
// particular, an accidentally stale host `read` policy cannot turn a newly
|
|
3393
|
+
// declared write/destructive tool into a trusted read.
|
|
3282
3394
|
const effect =
|
|
3283
|
-
authorizedEffect
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3395
|
+
declaredEffect === "destructive" || authorizedEffect === "destructive"
|
|
3396
|
+
? "destructive"
|
|
3397
|
+
: declaredEffect === "write" || authorizedEffect === "write"
|
|
3398
|
+
? "write"
|
|
3399
|
+
: declaredEffect === "unknown"
|
|
3400
|
+
? "unknown"
|
|
3401
|
+
: authorizedEffect || "unknown";
|
|
3287
3402
|
const annotations = descriptorContract.annotations || {};
|
|
3288
3403
|
|
|
3289
3404
|
return {
|
|
@@ -3301,7 +3416,15 @@ function mcpLedgerEffectContract(descriptor, hostPolicy) {
|
|
|
3301
3416
|
: null,
|
|
3302
3417
|
trusted:
|
|
3303
3418
|
authorizedEffect != null &&
|
|
3304
|
-
(hostContract.trusted === true || hostPolicy?.sourceTrusted === true)
|
|
3419
|
+
(hostContract.trusted === true || hostPolicy?.sourceTrusted === true) &&
|
|
3420
|
+
// Trust is valid only when the host authorization is at least as strict
|
|
3421
|
+
// as the merged effect. A stale host `read` classification cannot lend
|
|
3422
|
+
// trust to a server that now declares write/destructive behavior.
|
|
3423
|
+
authorizedEffect === effect &&
|
|
3424
|
+
// Trusted-read execution/parallelism requires the intersection promised
|
|
3425
|
+
// by the roadmap: a server read declaration plus host authorization.
|
|
3426
|
+
// An unmarked tool stays untrusted even when a host policy predicts read.
|
|
3427
|
+
(effect !== "read" || declaredEffect === "read"),
|
|
3305
3428
|
source:
|
|
3306
3429
|
hostContract.provenance ||
|
|
3307
3430
|
descriptorContract.provenance ||
|
|
@@ -3354,21 +3477,41 @@ const MCP_PROTOCOL_RESULT_INVALID_CODE = "CC_MCP_PROTOCOL_RESULT_INVALID";
|
|
|
3354
3477
|
const MCP_RESULT_PROJECTION_FAILED_CODE = "CC_MCP_RESULT_PROJECTION_FAILED";
|
|
3355
3478
|
|
|
3356
3479
|
function safeMcpProperty(value, property) {
|
|
3480
|
+
if (!value || (typeof value !== "object" && typeof value !== "function")) {
|
|
3481
|
+
return undefined;
|
|
3482
|
+
}
|
|
3357
3483
|
try {
|
|
3358
|
-
return
|
|
3484
|
+
if (isProxy(value)) return undefined;
|
|
3485
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, property);
|
|
3486
|
+
return descriptor && Object.hasOwn(descriptor, "value")
|
|
3487
|
+
? descriptor.value
|
|
3488
|
+
: undefined;
|
|
3359
3489
|
} catch {
|
|
3360
3490
|
return undefined;
|
|
3361
3491
|
}
|
|
3362
3492
|
}
|
|
3363
3493
|
|
|
3364
3494
|
function safeMcpErrorMessage(error) {
|
|
3495
|
+
if (safeMcpProperty(error, "mcpErrorCode") === "CC_MCP_RPC_ERROR") {
|
|
3496
|
+
const rpcCode = safeMcpProperty(error, "rpcCode");
|
|
3497
|
+
return Number.isSafeInteger(rpcCode)
|
|
3498
|
+
? `MCP server returned a JSON-RPC error (code ${rpcCode})`
|
|
3499
|
+
: "MCP server returned a JSON-RPC error";
|
|
3500
|
+
}
|
|
3501
|
+
// HTTP status bodies are peer-controlled. The production transport omits
|
|
3502
|
+
// them at source, and this boundary independently prevents any MCP client
|
|
3503
|
+
// honoring the stable transport error code from projecting one into tool
|
|
3504
|
+
// results, models, or sessions.
|
|
3505
|
+
if (safeMcpProperty(error, "code") === "CC_MCP_HTTP_STATUS") {
|
|
3506
|
+
const status = safeMcpProperty(error, "status");
|
|
3507
|
+
return Number.isInteger(status) && status >= 100 && status <= 599
|
|
3508
|
+
? `MCP HTTP request failed with status ${status}`
|
|
3509
|
+
: "MCP HTTP request failed";
|
|
3510
|
+
}
|
|
3365
3511
|
const message = safeMcpProperty(error, "message");
|
|
3366
3512
|
if (typeof message === "string" && message) return message;
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
} catch {
|
|
3370
|
-
return "unknown error";
|
|
3371
|
-
}
|
|
3513
|
+
if (typeof error === "string" && error) return error;
|
|
3514
|
+
return "unknown error";
|
|
3372
3515
|
}
|
|
3373
3516
|
|
|
3374
3517
|
function safeMcpErrorCode(error, fallback) {
|
|
@@ -3376,6 +3519,15 @@ function safeMcpErrorCode(error, fallback) {
|
|
|
3376
3519
|
return typeof code === "string" && code ? code : fallback;
|
|
3377
3520
|
}
|
|
3378
3521
|
|
|
3522
|
+
function projectMcpCallError(error) {
|
|
3523
|
+
const projected = new Error(safeMcpErrorMessage(error));
|
|
3524
|
+
const code = isMcpRpcError(error)
|
|
3525
|
+
? "CC_MCP_RPC_ERROR"
|
|
3526
|
+
: safeMcpErrorCode(error, null);
|
|
3527
|
+
if (code) projected.code = code;
|
|
3528
|
+
return projected;
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3379
3531
|
function invalidMcpProtocolResult(cause) {
|
|
3380
3532
|
const error = new TypeError("MCP result could not be inspected safely", {
|
|
3381
3533
|
cause,
|
|
@@ -5654,10 +5806,16 @@ async function executeToolInner(
|
|
|
5654
5806
|
}
|
|
5655
5807
|
|
|
5656
5808
|
case "run_skill": {
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5809
|
+
throwIfAborted(signal, "run_skill interrupted before discovery");
|
|
5810
|
+
const allSkills = await raceWithAbort(
|
|
5811
|
+
filterSkillsByCwd(
|
|
5812
|
+
skillLoader.getResolvedSkills().filter(skillAllowed),
|
|
5813
|
+
cwd,
|
|
5814
|
+
),
|
|
5815
|
+
signal,
|
|
5816
|
+
"run_skill interrupted during discovery",
|
|
5660
5817
|
);
|
|
5818
|
+
throwIfAborted(signal, "run_skill interrupted during discovery");
|
|
5661
5819
|
if (allSkills.length === 0) {
|
|
5662
5820
|
return attachDescriptor({
|
|
5663
5821
|
error: _skillAllowlist
|
|
@@ -5668,28 +5826,57 @@ async function executeToolInner(
|
|
|
5668
5826
|
let match = allSkills.find(
|
|
5669
5827
|
(s) => s.id === args.skill_name || s.dirName === args.skill_name,
|
|
5670
5828
|
);
|
|
5829
|
+
let admittedSkillBody = "";
|
|
5671
5830
|
if (!match || !match.hasHandler) {
|
|
5672
5831
|
return attachDescriptor({
|
|
5673
5832
|
error: `Skill "${args.skill_name}" not found or has no handler. Use list_skills to see available skills.`,
|
|
5674
5833
|
});
|
|
5675
5834
|
}
|
|
5835
|
+
const skillExecutionLease = skillLoader.acquireSkillExecution?.(match, {
|
|
5836
|
+
signal,
|
|
5837
|
+
});
|
|
5838
|
+
const skillExecutionSignal = skillExecutionLease?.signal || signal;
|
|
5676
5839
|
try {
|
|
5840
|
+
skillExecutionLease?.assertActive?.();
|
|
5677
5841
|
if (typeof skillLoader.materializeSkillForExecution === "function") {
|
|
5678
|
-
match = await
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5842
|
+
match = await raceWithAbort(
|
|
5843
|
+
skillLoader.materializeSkillForExecution(match, {
|
|
5844
|
+
sessionId,
|
|
5845
|
+
turnId,
|
|
5846
|
+
loadedBecause: "run_skill",
|
|
5847
|
+
bodyIncluded: true,
|
|
5848
|
+
signal: skillExecutionSignal,
|
|
5849
|
+
}),
|
|
5850
|
+
skillExecutionSignal,
|
|
5851
|
+
"run_skill interrupted during authorization",
|
|
5852
|
+
);
|
|
5684
5853
|
} else if (typeof skillLoader.materializeSkill === "function") {
|
|
5685
5854
|
match = skillLoader.materializeSkill(match, {
|
|
5686
5855
|
sessionId,
|
|
5687
5856
|
turnId,
|
|
5688
5857
|
loadedBecause: "run_skill",
|
|
5689
|
-
bodyIncluded:
|
|
5858
|
+
bodyIncluded: true,
|
|
5859
|
+
signal: skillExecutionSignal,
|
|
5690
5860
|
});
|
|
5691
5861
|
}
|
|
5862
|
+
skillExecutionLease?.assertActive?.();
|
|
5863
|
+
throwIfAborted(
|
|
5864
|
+
skillExecutionSignal,
|
|
5865
|
+
"run_skill interrupted during materialization",
|
|
5866
|
+
);
|
|
5867
|
+
// A custom loader is not an authority to raise host model-input caps.
|
|
5868
|
+
// Re-admit at the final consumer before constructing the child task.
|
|
5869
|
+
admittedSkillBody = match?.body;
|
|
5870
|
+
admitSkillPrompt(admittedSkillBody, skillLoader.getLimits?.());
|
|
5692
5871
|
} catch (error) {
|
|
5872
|
+
skillExecutionLease?.release?.();
|
|
5873
|
+
if (
|
|
5874
|
+
signal?.aborted ||
|
|
5875
|
+
skillExecutionSignal?.aborted ||
|
|
5876
|
+
isAbortError(error)
|
|
5877
|
+
) {
|
|
5878
|
+
throw error;
|
|
5879
|
+
}
|
|
5693
5880
|
return attachDescriptor({
|
|
5694
5881
|
error: `Skill "${args.skill_name}" body could not be loaded: ${error.message}`,
|
|
5695
5882
|
...(error?.code ? { code: error.code } : {}),
|
|
@@ -5721,67 +5908,84 @@ async function executeToolInner(
|
|
|
5721
5908
|
: null;
|
|
5722
5909
|
let skillSubRef = null;
|
|
5723
5910
|
// Run skill through isolated sub-agent context
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
`
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
: {}),
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
?
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5911
|
+
let subCtx;
|
|
5912
|
+
try {
|
|
5913
|
+
skillExecutionLease?.assertActive?.();
|
|
5914
|
+
subCtx = SubAgentContext.create({
|
|
5915
|
+
role: `skill-${args.skill_name}`,
|
|
5916
|
+
task:
|
|
5917
|
+
`Execute the "${args.skill_name}" skill using only the approved tools.\n\n` +
|
|
5918
|
+
`Authoritative skill instructions:\n${admittedSkillBody}\n\n` +
|
|
5919
|
+
`User input:\n${String(args.input || "").substring(0, 8000)}`,
|
|
5920
|
+
allowedTools: isolatedSkillTools,
|
|
5921
|
+
hookParentTraceId: hookTraceId || null,
|
|
5922
|
+
signal: skillExecutionSignal,
|
|
5923
|
+
toolAdmission,
|
|
5924
|
+
cwd,
|
|
5925
|
+
llmOptions: llmOptions || null,
|
|
5926
|
+
...(sessionBudget ? { sessionBudget } : {}),
|
|
5927
|
+
...(permissionRules ? { permissionRules } : {}),
|
|
5928
|
+
...(hostManagedToolPolicy
|
|
5929
|
+
? {
|
|
5930
|
+
hostManagedToolPolicy: {
|
|
5931
|
+
...hostManagedToolPolicy,
|
|
5932
|
+
toolDefinitions: [],
|
|
5933
|
+
},
|
|
5934
|
+
}
|
|
5935
|
+
: {}),
|
|
5936
|
+
...(planManager ? { planManager } : {}),
|
|
5937
|
+
...(sandbox ? { sandbox } : {}),
|
|
5938
|
+
...(Array.isArray(additionalDirectories)
|
|
5939
|
+
? { additionalDirectories: [...additionalDirectories] }
|
|
5940
|
+
: {}),
|
|
5941
|
+
...(approvalGate ? { approvalGate } : {}),
|
|
5942
|
+
...(shellPolicyOverrides ? { shellPolicyOverrides } : {}),
|
|
5943
|
+
...(classifyAllShell ? { classifyAllShell: true } : {}),
|
|
5944
|
+
...(unattendedActionPolicy ? { unattendedActionPolicy } : {}),
|
|
5945
|
+
...(mcpCallLedger ? { mcpCallLedger } : {}),
|
|
5946
|
+
...(mcpConflictScheduler ? { mcpConflictScheduler } : {}),
|
|
5947
|
+
onUsage: skillUsageSink
|
|
5948
|
+
? (u) => {
|
|
5949
|
+
try {
|
|
5950
|
+
skillUsageSink.push(
|
|
5951
|
+
u && u.attribution
|
|
5952
|
+
? u
|
|
5953
|
+
: {
|
|
5954
|
+
provider: u?.provider ?? null,
|
|
5955
|
+
model: u?.model ?? null,
|
|
5956
|
+
usage: u?.usage || null,
|
|
5957
|
+
...(u?.source ? { source: u.source } : {}),
|
|
5958
|
+
attribution: {
|
|
5959
|
+
origin: "skill",
|
|
5960
|
+
skill: args.skill_name,
|
|
5961
|
+
subagentId: skillSubRef?.id || null,
|
|
5962
|
+
parentSessionId: sessionId || null,
|
|
5963
|
+
depth: (subAgentDepth || 0) + 1,
|
|
5964
|
+
},
|
|
5773
5965
|
},
|
|
5774
|
-
|
|
5775
|
-
)
|
|
5776
|
-
|
|
5777
|
-
|
|
5966
|
+
);
|
|
5967
|
+
} catch (_e) {
|
|
5968
|
+
// usage forwarding is best-effort
|
|
5969
|
+
}
|
|
5778
5970
|
}
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
})
|
|
5971
|
+
: null,
|
|
5972
|
+
});
|
|
5973
|
+
} catch (error) {
|
|
5974
|
+
skillExecutionLease?.release?.();
|
|
5975
|
+
throw error;
|
|
5976
|
+
}
|
|
5782
5977
|
skillSubRef = subCtx;
|
|
5783
5978
|
try {
|
|
5784
|
-
const result = await
|
|
5979
|
+
const result = await raceWithAbort(
|
|
5980
|
+
subCtx.run(args.input),
|
|
5981
|
+
skillExecutionSignal,
|
|
5982
|
+
"run_skill interrupted while the isolated child was running",
|
|
5983
|
+
);
|
|
5984
|
+
skillExecutionLease?.assertActive?.();
|
|
5985
|
+
throwIfAborted(
|
|
5986
|
+
skillExecutionSignal,
|
|
5987
|
+
"run_skill interrupted before child handoff",
|
|
5988
|
+
);
|
|
5785
5989
|
const resolvedFailure =
|
|
5786
5990
|
subCtx.status === "failed" ||
|
|
5787
5991
|
result?.success === false ||
|
|
@@ -5809,6 +6013,13 @@ async function executeToolInner(
|
|
|
5809
6013
|
toolsUsed: result.toolsUsed,
|
|
5810
6014
|
});
|
|
5811
6015
|
} catch (err) {
|
|
6016
|
+
if (
|
|
6017
|
+
signal?.aborted ||
|
|
6018
|
+
skillExecutionSignal?.aborted ||
|
|
6019
|
+
isAbortError(err)
|
|
6020
|
+
) {
|
|
6021
|
+
throw err;
|
|
6022
|
+
}
|
|
5812
6023
|
return attachDescriptor({
|
|
5813
6024
|
success: false,
|
|
5814
6025
|
isolated: true,
|
|
@@ -5816,6 +6027,8 @@ async function executeToolInner(
|
|
|
5816
6027
|
code: err?.code || "CC_SKILL_ISOLATED_EXECUTION_FAILED",
|
|
5817
6028
|
error: `Isolated skill execution failed: ${err.message}`,
|
|
5818
6029
|
});
|
|
6030
|
+
} finally {
|
|
6031
|
+
skillExecutionLease?.release?.();
|
|
5819
6032
|
}
|
|
5820
6033
|
}
|
|
5821
6034
|
|
|
@@ -5823,6 +6036,7 @@ async function executeToolInner(
|
|
|
5823
6036
|
// reaching here. Keep the runtime fence explicit so a custom/legacy
|
|
5824
6037
|
// loader can never re-enable arbitrary handler.js imports in the CLI
|
|
5825
6038
|
// process or hand a Skill the raw MCP client/process broker.
|
|
6039
|
+
skillExecutionLease?.release?.();
|
|
5826
6040
|
return attachDescriptor({
|
|
5827
6041
|
error: `Skill "${args.skill_name}" cannot execute handler.js directly. Add isolation: true and use the controlled agent-tool path.`,
|
|
5828
6042
|
code: "CC_SKILL_DIRECT_HANDLER_BLOCKED",
|
|
@@ -5907,13 +6121,15 @@ async function executeToolInner(
|
|
|
5907
6121
|
error: `Could not resolve which MCP server owns resource "${uri}". Pass 'server' explicitly.`,
|
|
5908
6122
|
});
|
|
5909
6123
|
}
|
|
5910
|
-
const result =
|
|
6124
|
+
const result = signal
|
|
6125
|
+
? await mcpClient.readResource(server, uri, { signal })
|
|
6126
|
+
: await mcpClient.readResource(server, uri);
|
|
5911
6127
|
return attachDescriptor(
|
|
5912
6128
|
result && typeof result === "object" ? result : { result },
|
|
5913
6129
|
);
|
|
5914
6130
|
} catch (err) {
|
|
5915
6131
|
return attachDescriptor({
|
|
5916
|
-
error: `MCP resource access failed: ${err
|
|
6132
|
+
error: `MCP resource access failed: ${safeMcpErrorMessage(err)}`,
|
|
5917
6133
|
});
|
|
5918
6134
|
}
|
|
5919
6135
|
}
|
|
@@ -6015,19 +6231,31 @@ async function executeToolInner(
|
|
|
6015
6231
|
});
|
|
6016
6232
|
}
|
|
6017
6233
|
|
|
6018
|
-
const transportFailure = async (callError) => {
|
|
6019
|
-
|
|
6234
|
+
const transportFailure = async (callError, phase = "call") => {
|
|
6235
|
+
const definitiveRpcFailure = isMcpRpcError(callError);
|
|
6236
|
+
if (
|
|
6237
|
+
mcpTransportOutcomeIsUnsafe(ledgerEffectContract) &&
|
|
6238
|
+
!definitiveRpcFailure
|
|
6239
|
+
) {
|
|
6240
|
+
const resultAdmissionFailure =
|
|
6241
|
+
isMcpToolResultAdmissionError(callError);
|
|
6020
6242
|
return attachDescriptor(
|
|
6021
6243
|
mcpOutcomeUnknownPayload(ledger, ledgerTicket, {
|
|
6022
|
-
phase
|
|
6023
|
-
reasonCode:
|
|
6244
|
+
phase,
|
|
6245
|
+
reasonCode: resultAdmissionFailure
|
|
6246
|
+
? safeMcpErrorCode(
|
|
6247
|
+
callError,
|
|
6248
|
+
MCP_PROTOCOL_RESULT_INVALID_CODE,
|
|
6249
|
+
)
|
|
6250
|
+
: MCP_TRANSPORT_OUTCOME_UNKNOWN_CODE,
|
|
6024
6251
|
}),
|
|
6025
6252
|
);
|
|
6026
6253
|
}
|
|
6254
|
+
const projectedError = projectMcpCallError(callError);
|
|
6027
6255
|
try {
|
|
6028
6256
|
await ledgerTicket.settle({
|
|
6029
6257
|
status: "failed",
|
|
6030
|
-
error:
|
|
6258
|
+
error: projectedError,
|
|
6031
6259
|
});
|
|
6032
6260
|
} catch (ledgerError) {
|
|
6033
6261
|
return attachDescriptor(
|
|
@@ -6041,20 +6269,29 @@ async function executeToolInner(
|
|
|
6041
6269
|
);
|
|
6042
6270
|
}
|
|
6043
6271
|
return attachDescriptor({
|
|
6044
|
-
error: `MCP tool execution failed: ${
|
|
6272
|
+
error: `MCP tool execution failed: ${projectedError.message}`,
|
|
6045
6273
|
mcpLedgerId: safeMcpProperty(ledgerTicket, "ledgerId") || null,
|
|
6046
6274
|
});
|
|
6047
6275
|
};
|
|
6048
6276
|
|
|
6049
6277
|
let pendingResult;
|
|
6050
6278
|
try {
|
|
6051
|
-
|
|
6279
|
+
const callArguments = [
|
|
6052
6280
|
localToolExecutor.serverName,
|
|
6053
6281
|
localToolExecutor.toolName,
|
|
6054
6282
|
mcpWireInput,
|
|
6055
|
-
]
|
|
6283
|
+
];
|
|
6284
|
+
if (signal) callArguments.push({ signal });
|
|
6285
|
+
pendingResult = Reflect.apply(
|
|
6286
|
+
mcpClient.callTool,
|
|
6287
|
+
mcpClient,
|
|
6288
|
+
callArguments,
|
|
6289
|
+
);
|
|
6056
6290
|
} catch (callError) {
|
|
6057
|
-
return await transportFailure(
|
|
6291
|
+
return await transportFailure(
|
|
6292
|
+
callError,
|
|
6293
|
+
isMcpToolResultAdmissionError(callError) ? "result" : "call",
|
|
6294
|
+
);
|
|
6058
6295
|
}
|
|
6059
6296
|
|
|
6060
6297
|
let result;
|
|
@@ -6091,7 +6328,10 @@ async function executeToolInner(
|
|
|
6091
6328
|
try {
|
|
6092
6329
|
result = await pendingResult;
|
|
6093
6330
|
} catch (callError) {
|
|
6094
|
-
return await transportFailure(
|
|
6331
|
+
return await transportFailure(
|
|
6332
|
+
callError,
|
|
6333
|
+
isMcpToolResultAdmissionError(callError) ? "result" : "call",
|
|
6334
|
+
);
|
|
6095
6335
|
}
|
|
6096
6336
|
} else {
|
|
6097
6337
|
let then;
|
|
@@ -6136,6 +6376,16 @@ async function executeToolInner(
|
|
|
6136
6376
|
result = pendingResult;
|
|
6137
6377
|
}
|
|
6138
6378
|
|
|
6379
|
+
try {
|
|
6380
|
+
result = admitMcpToolResult(
|
|
6381
|
+
localToolExecutor.serverName,
|
|
6382
|
+
result,
|
|
6383
|
+
localToolExecutor.toolResultConfig,
|
|
6384
|
+
).result;
|
|
6385
|
+
} catch (resultError) {
|
|
6386
|
+
return await transportFailure(resultError, "result");
|
|
6387
|
+
}
|
|
6388
|
+
|
|
6139
6389
|
let protocolError;
|
|
6140
6390
|
try {
|
|
6141
6391
|
if (
|
|
@@ -6683,12 +6933,21 @@ export const MAX_SUB_AGENTS_PER_RUN = 32;
|
|
|
6683
6933
|
* `substring(0, 5000)` that sliced mid-content with no marker and undercut even
|
|
6684
6934
|
* read_file's own 50k self-limit. Tools that self-limit (read_file, notebook
|
|
6685
6935
|
* render) stay below this; it is the final safety net for the ones that don't
|
|
6686
|
-
* (run_shell, search_files, run_code, MCP).
|
|
6936
|
+
* (run_shell, search_files, run_code, MCP). CC_MAX_TOOL_RESULT_CHARS may only
|
|
6937
|
+
* tighten the host ceiling; it cannot raise or disable it.
|
|
6687
6938
|
*/
|
|
6688
|
-
export const
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6939
|
+
export const MAX_TOOL_RESULT_CHARS_HARD_LIMIT = 50000;
|
|
6940
|
+
|
|
6941
|
+
export function resolveMaxToolResultChars(configured) {
|
|
6942
|
+
const value = Number(configured);
|
|
6943
|
+
return Number.isFinite(value) && value > 0
|
|
6944
|
+
? Math.min(MAX_TOOL_RESULT_CHARS_HARD_LIMIT, Math.max(1, Math.floor(value)))
|
|
6945
|
+
: MAX_TOOL_RESULT_CHARS_HARD_LIMIT;
|
|
6946
|
+
}
|
|
6947
|
+
|
|
6948
|
+
export const MAX_TOOL_RESULT_CHARS = resolveMaxToolResultChars(
|
|
6949
|
+
process.env.CC_MAX_TOOL_RESULT_CHARS,
|
|
6950
|
+
);
|
|
6692
6951
|
|
|
6693
6952
|
/**
|
|
6694
6953
|
* Cap a serialized tool result to `max` chars, appending a visible truncation
|
|
@@ -6698,10 +6957,11 @@ export const MAX_TOOL_RESULT_CHARS = (() => {
|
|
|
6698
6957
|
*/
|
|
6699
6958
|
export function capToolResultString(serialized, max = MAX_TOOL_RESULT_CHARS) {
|
|
6700
6959
|
const s = String(serialized ?? "");
|
|
6701
|
-
|
|
6960
|
+
const effectiveMax = resolveMaxToolResultChars(max);
|
|
6961
|
+
if (s.length <= effectiveMax) return s;
|
|
6702
6962
|
return (
|
|
6703
|
-
s.slice(0,
|
|
6704
|
-
`\n…[tool output truncated: showing the first ${
|
|
6963
|
+
s.slice(0, effectiveMax) +
|
|
6964
|
+
`\n…[tool output truncated: showing the first ${effectiveMax} of ${s.length} chars` +
|
|
6705
6965
|
` — narrow the request (read a line range, grep, or paginate) to see the rest]`
|
|
6706
6966
|
);
|
|
6707
6967
|
}
|
|
@@ -8143,6 +8403,42 @@ function _ollamaInitState() {
|
|
|
8143
8403
|
};
|
|
8144
8404
|
}
|
|
8145
8405
|
|
|
8406
|
+
function _streamUiCallbacks(onToken, onThinking) {
|
|
8407
|
+
let pending = [];
|
|
8408
|
+
const capture = (callback) =>
|
|
8409
|
+
typeof callback === "function"
|
|
8410
|
+
? (value) => {
|
|
8411
|
+
try {
|
|
8412
|
+
const result = callback(value);
|
|
8413
|
+
if (result && typeof result.then === "function") {
|
|
8414
|
+
pending.push(Promise.resolve(result));
|
|
8415
|
+
}
|
|
8416
|
+
} catch (error) {
|
|
8417
|
+
pending.push(Promise.reject(error));
|
|
8418
|
+
}
|
|
8419
|
+
}
|
|
8420
|
+
: callback;
|
|
8421
|
+
return {
|
|
8422
|
+
onToken: capture(onToken),
|
|
8423
|
+
onThinking: capture(onThinking),
|
|
8424
|
+
async settle() {
|
|
8425
|
+
if (pending.length === 0) return;
|
|
8426
|
+
const current = pending;
|
|
8427
|
+
pending = [];
|
|
8428
|
+
const outcomes = await Promise.allSettled(current);
|
|
8429
|
+
const fatal = outcomes.find(
|
|
8430
|
+
(outcome) =>
|
|
8431
|
+
outcome.status === "rejected" &&
|
|
8432
|
+
outcome.reason?.isOutputBackpressureFailure === true,
|
|
8433
|
+
);
|
|
8434
|
+
if (fatal) throw fatal.reason;
|
|
8435
|
+
// Generic UI callback failures retain their historical best-effort
|
|
8436
|
+
// semantics. Branded output failures are lifecycle failures and abort the
|
|
8437
|
+
// provider stream instead of allowing its terminal queue to grow.
|
|
8438
|
+
},
|
|
8439
|
+
};
|
|
8440
|
+
}
|
|
8441
|
+
|
|
8146
8442
|
function _ollamaReduceLine(state, line, onToken) {
|
|
8147
8443
|
const s = (line || "").trim();
|
|
8148
8444
|
if (!s) return state;
|
|
@@ -8213,6 +8509,7 @@ export function _accumulateOllamaStream(lines, onToken) {
|
|
|
8213
8509
|
* showing raw errors"). Pure + exported for unit tests.
|
|
8214
8510
|
*/
|
|
8215
8511
|
export function _streamErrorDisposition(err, signal, partialText) {
|
|
8512
|
+
if (err?.isOutputBackpressureFailure === true) return "rethrow";
|
|
8216
8513
|
if (isAbortError(err)) return "rethrow";
|
|
8217
8514
|
if (signal && signal.aborted) return "rethrow";
|
|
8218
8515
|
if (typeof partialText === "string" && partialText.trim()) return "preserve";
|
|
@@ -8427,6 +8724,7 @@ async function _chatOllamaStreaming(
|
|
|
8427
8724
|
throw new Error(await formatProviderResponseError("ollama", response));
|
|
8428
8725
|
}
|
|
8429
8726
|
const state = _ollamaInitState();
|
|
8727
|
+
const ui = _streamUiCallbacks(onToken);
|
|
8430
8728
|
const reader = response.body.getReader();
|
|
8431
8729
|
const decoder = new TextDecoder();
|
|
8432
8730
|
let buf = "";
|
|
@@ -8439,11 +8737,15 @@ async function _chatOllamaStreaming(
|
|
|
8439
8737
|
buf += decoder.decode(value, { stream: true });
|
|
8440
8738
|
let idx;
|
|
8441
8739
|
while ((idx = buf.indexOf("\n")) >= 0) {
|
|
8442
|
-
_ollamaReduceLine(state, buf.slice(0, idx), onToken);
|
|
8740
|
+
_ollamaReduceLine(state, buf.slice(0, idx), ui.onToken);
|
|
8741
|
+
await ui.settle();
|
|
8443
8742
|
buf = buf.slice(idx + 1);
|
|
8444
8743
|
}
|
|
8445
8744
|
}
|
|
8446
|
-
if (buf.trim())
|
|
8745
|
+
if (buf.trim()) {
|
|
8746
|
+
_ollamaReduceLine(state, buf, ui.onToken);
|
|
8747
|
+
await ui.settle();
|
|
8748
|
+
}
|
|
8447
8749
|
} catch (err) {
|
|
8448
8750
|
if (_streamErrorDisposition(err, signal, state.content) === "rethrow")
|
|
8449
8751
|
throw err;
|
|
@@ -8613,6 +8915,7 @@ async function _chatAnthropicStreaming(
|
|
|
8613
8915
|
throw new Error(await formatProviderResponseError("anthropic", response));
|
|
8614
8916
|
}
|
|
8615
8917
|
const state = _anthropicInitState();
|
|
8918
|
+
const ui = _streamUiCallbacks(onToken, onThinking);
|
|
8616
8919
|
const reader = response.body.getReader();
|
|
8617
8920
|
const decoder = new TextDecoder();
|
|
8618
8921
|
let buf = "";
|
|
@@ -8625,10 +8928,15 @@ async function _chatAnthropicStreaming(
|
|
|
8625
8928
|
buf += decoder.decode(value, { stream: true });
|
|
8626
8929
|
const lines = buf.split("\n");
|
|
8627
8930
|
buf = lines.pop() || "";
|
|
8628
|
-
for (const line of lines)
|
|
8629
|
-
_anthropicReduceLine(state, line, onToken, onThinking);
|
|
8931
|
+
for (const line of lines) {
|
|
8932
|
+
_anthropicReduceLine(state, line, ui.onToken, ui.onThinking);
|
|
8933
|
+
await ui.settle();
|
|
8934
|
+
}
|
|
8935
|
+
}
|
|
8936
|
+
if (buf.trim()) {
|
|
8937
|
+
_anthropicReduceLine(state, buf, ui.onToken, ui.onThinking);
|
|
8938
|
+
await ui.settle();
|
|
8630
8939
|
}
|
|
8631
|
-
if (buf.trim()) _anthropicReduceLine(state, buf, onToken, onThinking);
|
|
8632
8940
|
} catch (err) {
|
|
8633
8941
|
if (_streamErrorDisposition(err, signal, state.text) === "rethrow")
|
|
8634
8942
|
throw err;
|
|
@@ -8765,6 +9073,7 @@ async function _chatOpenAIStreaming(
|
|
|
8765
9073
|
throw new Error(await formatProviderResponseError(provider, response));
|
|
8766
9074
|
}
|
|
8767
9075
|
const state = _openaiInitState();
|
|
9076
|
+
const ui = _streamUiCallbacks(onToken);
|
|
8768
9077
|
const reader = response.body.getReader();
|
|
8769
9078
|
const decoder = new TextDecoder();
|
|
8770
9079
|
let buf = "";
|
|
@@ -8777,9 +9086,15 @@ async function _chatOpenAIStreaming(
|
|
|
8777
9086
|
buf += decoder.decode(value, { stream: true });
|
|
8778
9087
|
const lines = buf.split("\n");
|
|
8779
9088
|
buf = lines.pop() || "";
|
|
8780
|
-
for (const line of lines)
|
|
9089
|
+
for (const line of lines) {
|
|
9090
|
+
_openaiReduceLine(state, line, ui.onToken);
|
|
9091
|
+
await ui.settle();
|
|
9092
|
+
}
|
|
9093
|
+
}
|
|
9094
|
+
if (buf.trim()) {
|
|
9095
|
+
_openaiReduceLine(state, buf, ui.onToken);
|
|
9096
|
+
await ui.settle();
|
|
8781
9097
|
}
|
|
8782
|
-
if (buf.trim()) _openaiReduceLine(state, buf, onToken);
|
|
8783
9098
|
} catch (err) {
|
|
8784
9099
|
if (_streamErrorDisposition(err, signal, state.text) === "rethrow")
|
|
8785
9100
|
throw err;
|