chainlesschain 0.166.102 → 0.166.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-CyHIMEd8.js → AIOps-Bah3HREy.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-vuNxDpHm.js → ActionButton-DY2aeZMc.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D0quEM0q.js → Analytics-BFly8Xaa.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-xRSVpbCs.js → AppLayout-dp0Zz-JM.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-ktfVAZBC.js → Artifacts-DcIg09ai.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-UJW6maH4.js → Audit-DkN-lsjZ.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BYrfdCoT.js → BackgroundAgents-BjzgusLx.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-IBgsJ7BK.js → Backup-CU8S6qu9.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BmP8_zxy.js → BaseInput-B1pC2gjL.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-urkw8_BF.js → Chat-B6xFp6gD.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Cw44zZbh.js → ChatBubbleRenderer-DxNCLZ_X.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-CYboo-__.js → Checkbox-QHw7Vc4U.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DaqR_Ay8.js → Codegen-gdecsfjg.js} +1 -1
- package/src/assets/web-panel/assets/{Col-04BSIj_z.js → Col-B0_JmAmc.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DxFk7Trv.js → Community-DRCcP5xR.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-mjgWlMCB.js → Compact-DZtoGzhX.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CC5ee7QV.js → Compliance-BfNTvEnT.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BK4BhHZd.js → Cowork-CDXTLm84.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CP6jAxq0.js → Cron-Big35CbN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DJPaViZS.js → Crosschain-C8ArrAVr.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BTLxkuOj.js → DID-D_77BI2O.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Djkiqh3d.js → Dashboard-D2SxTzEp.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-t_eUhqom.js → Dropdown-mR1-b9ud.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-7w6USx_J.js → EmailListRenderer-DPl7TE1c.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-mU5IHEk5.js → EvolutionSettings-BxRYLRSH.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BCh-VBBC.js → FamilyGuardDashboard-rnGtXJ5Z.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-Be_VpjI2.js → Federation-BpxenYK8.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D_lzQ7PI.js → FormItemContext-Cz1kDf6l.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-LYu3KapV.js → GenericCardRenderer-CGV3KN6U.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BBeF-PP4.js → Git-CIRP4UTx.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CoF8Kzg7.js → Governance-DX4r8Vmt.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C4DLMnXS.js → Inference-DQKk02Hl.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B2mlNewk.js → KnowledgeGraph-DdD6J-By.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DMZ_44Ya.js → Logs-DA2w-1_m.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-Ck7Iv_9e.js → MarkdownRenderer-C9aSGETh.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BqDzTew_.js → Marketplace-BsJ6_6KW.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BbwSbDN9.js → McpTools-_6k30z6u.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-DAaTWgrm.js → Memory-C0_dYY0A.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BjbTGxoR.js → MobileBridge-CCTnVqiC.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DMODOBr-.js → MobileProjects-RZdxDSwC.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DT9N2rCs.js → Mtc-D4Ys8lvX.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-DagMfUVv.js → MtcAudit-BKTC--a2.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-C1BKP6nM.js → Multisig-CGR1qOe1.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B5LFh72i.js → NLProgramming-hKKD4qWb.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Q77V3ltW.js → Notes-pCn7Ec40.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-HxdpNIBs.js → NotificationSettings-B9eEJXEs.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Dc0DpvBH.js → OrderTableRenderer-CmJuhaT2.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-QL3NZ7uW.js → Organization-CcQbrnwW.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-B_gqOKho.js → Overflow-HmD4Mn72.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BBJubU8Z.js → P2P-B7LIgx5H.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CFnGd-2E.js → PdhVaultBrowser-CXiHnBfX.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BKkznIUM.js → Permissions-CQRI3y_l.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DYK7ZAcd.js → PersonalDataHub-1EeHmsy5.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-CoeKpjoN.js → Pipeline-BFyoIdn8.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Diw4G-92.js → Privacy-BxWthXMF.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CHBOFkma.js → ProjectInit-DfigBilu.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BJIsgdOf.js → ProjectSettings-CFmIcVc-.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CR7H59v3.js +1 -0
- package/src/assets/web-panel/assets/{Providers-o8QCimor.js → Providers-2ulom-76.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-z2W-zvhW.js → QrScannerModal-BwhO07b_.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-_yubhsna.js → QuickAsk-_Wg34OwF.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CucgJwih.js → Recommend-D_jq6Svg.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-EzfIIRg1.js → RemoteSession-BlzvEfsa.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-_shttE67.js → Reputation-9CTXHfL4.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DQA_S8-9.js → Row-DlCYCN-t.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BOqWawXT.js → RssFeed-BvlInFCH.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Dx1v2xOq.js → Search-CfaUzKuL.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bt4HHsT4.js → Security-bAWgLyve.js} +4 -4
- package/src/assets/web-panel/assets/{Services-sruHiQ-r.js → Services-C4LOGACW.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CiBxvmOJ.js → Skeleton-Dd0Uwh3_.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-De9qKODU.js → Skills-ZYF1kYCU.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-B_6yn8Wp.js → Sla-DpsmIaEo.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C2CafExS.js → SpeechSettings-BBXoJ4yc.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Dhh3Qmb0.js → SyncSettings-SOnROi2Y.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Mvo5mTWm.js → Tasks-HFA_ZlDk.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D7WVTQQy.js → Templates-fsK-RCEc.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-7ur9Yfxd.js → Tenant-CuqYxamb.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BgzrOA6k.js → Terminal-GKlI2R5F.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Dco20pT1.js → TimelineRenderer-DMDMHLeY.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-hN6qBPag.js → Tokens-BoV60rh3.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C4f_twAM.js → Trigger-CE344-Ws.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Wf1SMypp.js → Trust-DENwgkVc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DUXSyg3N.js → UkeySign-FrcM7yfm.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BvqsJaL0.js → VideoEditing-DAY9WaC2.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CgAbcjKl.js → Wallet-BuUR5i82.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DaLT0W3s.js → WebAuthn-nfSQuq85.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-CQqAXoaS.js → WorkflowEditor-DHhPOp9l.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BhlohFTB.js → chat-C4nsLzYy.js} +1 -1
- package/src/assets/web-panel/assets/{colors-D7HqXIL8.js → colors-BwXH0Wjn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Bqk4FCLY.js → compact-item-uApFG30S.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CEmWrWf0.js → createContext-BpyYs4fe.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Bk6HGn3N.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CDY0pFi2.js → hasIn-MXCLi00p.js} +1 -1
- package/src/assets/web-panel/assets/{index-e9oCy7_4.js → index-1LxX2IwJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DEzL7s7P.js → index-61CBBrHE.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0nfNmbq.js → index-B0P1Z_oa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiLu-ImR.js → index-B7jojVc7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqK0J4Sj.js → index-BEGMfaOo.js} +1 -1
- package/src/assets/web-panel/assets/{index-aBHlgMrq.js → index-BOhjapd5.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPBoWNwq.js → index-BaBwXpAp.js} +1 -1
- package/src/assets/web-panel/assets/index-Bb1LPYdi.js +1 -0
- package/src/assets/web-panel/assets/{index-BxXFRLTZ.js → index-Btv--Nnt.js} +1 -1
- package/src/assets/web-panel/assets/index-C-FsTuFG.js +1 -0
- package/src/assets/web-panel/assets/{index-BxYO6nde.js → index-CF0bUOP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGKRAO61.js → index-CNjUPfJP.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkjgSHVz.js → index-CRmNdEk_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrsM-oiD.js → index-C_oOpXhP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNrvBWDS.js → index-ChUTKrOq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYcjOnDX.js → index-CiIpIYhs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C02yDu4f.js → index-CwVvk2i7.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmKdCWq1.js → index-D3_tj06B.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkqBoCiu.js → index-DE4W4vLO.js} +3 -3
- package/src/assets/web-panel/assets/{index-B8L3_-sG.js → index-DLxKx5_J.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dwob5XoD.js → index-DTXi_gQh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuMt3ewl.js → index-Daco83me.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpI1LqJX.js → index-DffWVpZv.js} +1 -1
- package/src/assets/web-panel/assets/{index-lBAbMOzg.js → index-Dkncxel3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRcDWMwP.js → index-Dn12gJJU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVrwozwH.js → index-Dt-nq2eF.js} +1 -1
- package/src/assets/web-panel/assets/{index-C3opQg47.js → index-Du01X9N9.js} +1 -1
- package/src/assets/web-panel/assets/{index-o_lc3eww.js → index-DucLR6YX.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cur88hoN.js → index-Gz2rGWef.js} +1 -1
- package/src/assets/web-panel/assets/{index-XErJQ1yF.js → index-IvgszJ3C.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuKGuH_y.js → index-S80LLjdx.js} +1 -1
- package/src/assets/web-panel/assets/{index-Chxt0t-A.js → index-WKbnwbKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-1HBam9t1.js → index-XHBXtvqp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXRooi-O.js → index-nn22NSDK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHGOdvOQ.js → index-pCIAE2yS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf1ha8l0.js → index-pRpMLhMt.js} +1 -1
- package/src/assets/web-panel/assets/{index-6f6n0KFR.js → index-pgHGBAoF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPmRkxeX.js → index-ugIUt5TL.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9mvnSii.js → index-xLGf7f9K.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CIeEUxIN.js → initDefaultProps-C58CkKEo.js} +1 -1
- package/src/assets/web-panel/assets/{motion-IPIj1ZtP.js → motion-BLWPO2NV.js} +1 -1
- package/src/assets/web-panel/assets/{move-BfSeXZ-f.js → move-BgrFMwYp.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DX03-Xp4.js → mtc-parser-Cq2AuGzl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-z9EannfX.js → omit-Bb-9L7if.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DXKmRkqZ.js → pickAttrs-vLmOxYr1.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-k2HV7cIU.js → placementArrow-BNySU_dJ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-bX7CsyWy.js → responsiveObserve-xnbwagnm.js} +1 -1
- package/src/assets/web-panel/assets/{slide-NskjQLbJ.js → slide-BccbY5Cn.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B3IoG-Er.js → statusUtils-DOp9d2-w.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DHv_UilX.js → styleChecker-Bu1w6ho9.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DEqGB5Ng.js → useFlexGapSupport-ZsUOrVdL.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Bl9CbrqZ.js → useFs-C0zpzKtO.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-O-Ukv93M.js → usePersonalDataHub-DO1OdgXK.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-hGCHTaZt.js → vnode-jTIRyhR5.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BWhIVeKQ.js → zoom-DKvS7-Qs.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +56 -20
- package/src/commands/ask.js +6 -4
- package/src/commands/batch.js +17 -12
- package/src/commands/eval.js +24 -8
- package/src/commands/team.js +28 -19
- package/src/data/changelog.json +26 -0
- package/src/harness/mcp-client.js +187 -26
- package/src/harness/prompt-compressor.js +2 -0
- package/src/lib/advisor-runtime.js +4 -2
- package/src/lib/agent-ipc-bus.js +2 -0
- package/src/lib/background-agent-keeper-client.js +3 -0
- package/src/lib/background-session-transport.js +21 -5
- package/src/lib/browser-automation.js +4 -0
- package/src/lib/cc-android-bridge.js +4 -0
- package/src/lib/chat-core.js +11 -9
- package/src/lib/cloud/cloud-client.js +10 -1
- package/src/lib/cowork-adapter.js +4 -3
- package/src/lib/decision-layer/providers.js +16 -11
- package/src/lib/decision-layer/runtime.js +180 -10
- package/src/lib/direct-model-usage.js +34 -0
- package/src/lib/evolution/agent-evolution-ingress.js +63 -7
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +10 -0
- package/src/lib/evolution/evolution-evidence-projector.js +46 -7
- package/src/lib/evolution/governed-hub-llm.js +31 -16
- package/src/lib/evolution/governed-hub-resolver.js +4 -0
- package/src/lib/evolution/governed-skill-synthesis-process-grader.js +4 -0
- package/src/lib/evolution/skill-decision-projection.js +211 -0
- package/src/lib/evolution/skill-retrieval-revocation-authority.js +17 -2
- package/src/lib/evomap-client.js +14 -2
- package/src/lib/formal-budget-authority.js +191 -59
- package/src/lib/formal-budget-contract.js +7 -13
- package/src/lib/formal-budget-errors.js +31 -0
- package/src/lib/formal-budget-lineage-registry.js +612 -0
- package/src/lib/formal-budget-provider-scope.js +143 -0
- package/src/lib/formal-budget-transport.js +235 -100
- package/src/lib/gateway-client-resilience.js +5 -0
- package/src/lib/hub-llm-client.js +25 -16
- package/src/lib/llm-connection-probe.js +17 -10
- package/src/lib/llm-providers.js +4 -1
- package/src/lib/model-failure-policy.js +2 -0
- package/src/lib/plugin-runtime/marketplace-network.js +9 -5
- package/src/lib/process-execution-broker/credential-agent.js +7 -2
- package/src/lib/process-execution-broker/credential-transport.js +4 -0
- package/src/lib/process-execution-broker/index.js +8 -0
- package/src/lib/provider-stream.js +28 -13
- package/src/lib/sandbox-egress-worker.js +3 -0
- package/src/lib/skill-loader.js +16 -0
- package/src/lib/stream-retry.js +2 -0
- package/src/lib/sub-agent-context.js +6 -3
- package/src/lib/web-fetch.js +2 -0
- package/src/lib/web-search.js +5 -0
- package/src/repl/agent-repl.js +86 -7
- package/src/runtime/agent-core.js +141 -22
- package/src/runtime/headless-runner.js +212 -22
- package/src/runtime/headless-stream.js +189 -25
- package/src/runtime/mcp-config.js +26 -17
- package/src/runtime/mcp-tool-search.js +44 -14
- package/src/assets/web-panel/assets/Projects-GJjItXIk.js +0 -1
- package/src/assets/web-panel/assets/devWarning-YPX_TU7w.js +0 -1
- package/src/assets/web-panel/assets/index-D53szVZQ.js +0 -1
- package/src/assets/web-panel/assets/index-Ub2nJbV2.js +0 -1
package/src/data/changelog.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.166.104",
|
|
7
|
+
"cliVersions": ["0.166.104"],
|
|
8
|
+
"date": null,
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Fixed - cc CLI 0.166.104: recover governed sessions safely",
|
|
13
|
+
"body": "- Verify Jev model usage starts and settlements before resuming a durable\n session; stop further provider calls when usage or persistence is unresolved.\n- Bind session budget roots to verified JSONL for single-prompt, stream-json and\n REPL entry points, retaining the original limits across resume.\n- Preserve UTF-8 in background, batch and SDK process streams; reject malformed\n background frames and stale MCP tool catalogs before dispatch.\n- Publish Agent SDK 0.2.15 before this CLI release, then pair VS Code 0.37.149\n and JetBrains 0.4.166 with CLI 0.166.104 after exact-commit gates and public\n npm readback. Formal paid evaluation remains NOT_RUN."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"productVersion": null,
|
|
19
|
+
"cliVersion": "0.166.103",
|
|
20
|
+
"cliVersions": ["0.166.103"],
|
|
21
|
+
"date": null,
|
|
22
|
+
"title": "",
|
|
23
|
+
"sections": [
|
|
24
|
+
{
|
|
25
|
+
"heading": "Fixed - cc CLI 0.166.103: reject ungoverned formal budget exits",
|
|
26
|
+
"body": "- Keep formal paid evaluation closed while budgeted requests lack production\n account, checkpoint and host isolation evidence.\n- Reject direct Agent tools, subprocess and worker launches, credential and\n network paths when entered from the formal budget scope; propagate rejection\n through parallel tool execution.\n- Bind the frozen all-Volcengine 36-task and 9-first-run plan to its exact\n model, endpoint and shared historical $99 budget without counting diagnostic\n calls as formal observations.\n- Pair VS Code 0.37.147 and JetBrains 0.4.165 with CLI 0.166.103 only after\n the exact release commit passes its complete Actions gates and npm readback."
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
4
30
|
{
|
|
5
31
|
"productVersion": null,
|
|
6
32
|
"cliVersion": "0.166.102",
|
|
@@ -744,6 +744,51 @@ function mcpTransportError(code, message, details = {}) {
|
|
|
744
744
|
return error;
|
|
745
745
|
}
|
|
746
746
|
|
|
747
|
+
function pendingToolFailure(error, entry, method, dispatched) {
|
|
748
|
+
const httpStatus = safeRpcProperty(error, "status");
|
|
749
|
+
if (
|
|
750
|
+
method !== "tools/call" ||
|
|
751
|
+
!dispatched ||
|
|
752
|
+
isMcpRpcError(error) ||
|
|
753
|
+
safeRpcProperty(error, "outcomeUnknown") != null ||
|
|
754
|
+
(safeRpcProperty(error, "code") === "CC_MCP_HTTP_STATUS" &&
|
|
755
|
+
(httpStatus === 401 || httpStatus === 403 || httpStatus === 404))
|
|
756
|
+
) {
|
|
757
|
+
return error;
|
|
758
|
+
}
|
|
759
|
+
const originalCode = safeRpcProperty(error, "code");
|
|
760
|
+
if (
|
|
761
|
+
typeof originalCode === "string" &&
|
|
762
|
+
originalCode.startsWith("CC_MCP_") &&
|
|
763
|
+
!isProxy(error) &&
|
|
764
|
+
error instanceof Error
|
|
765
|
+
) {
|
|
766
|
+
try {
|
|
767
|
+
error.dispatched = true;
|
|
768
|
+
error.outcomeUnknown = true;
|
|
769
|
+
return error;
|
|
770
|
+
} catch {
|
|
771
|
+
// A frozen host error still needs a public uncertainty marker.
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const message = safeRpcErrorText(error) || "MCP tool request failed";
|
|
775
|
+
return mcpTransportError(
|
|
776
|
+
typeof originalCode === "string" && originalCode.startsWith("CC_MCP_")
|
|
777
|
+
? originalCode
|
|
778
|
+
: "CC_MCP_TOOL_OUTCOME_UNKNOWN",
|
|
779
|
+
`${message}; tool outcome is unknown and was not replayed`,
|
|
780
|
+
{
|
|
781
|
+
transport: entry?.transportKind,
|
|
782
|
+
url: entry?.config?.url,
|
|
783
|
+
status: httpStatus,
|
|
784
|
+
closeCode: safeRpcProperty(error, "closeCode"),
|
|
785
|
+
limitBytes: safeRpcProperty(error, "limitBytes"),
|
|
786
|
+
dispatched: true,
|
|
787
|
+
outcomeUnknown: true,
|
|
788
|
+
},
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
|
|
747
792
|
function dispatchMcpToolRequest(options, metadata, dispatch) {
|
|
748
793
|
const admission = options?.dispatchAdmission ?? null;
|
|
749
794
|
if (metadata.method !== "tools/call" || admission === null) {
|
|
@@ -916,8 +961,8 @@ function mcpInboundBudgetError(serverName, entry, budget) {
|
|
|
916
961
|
function mcpJsonBudgetError(serverName, entry, budget) {
|
|
917
962
|
const dispatched = Boolean(
|
|
918
963
|
(entry?._pending instanceof Map && entry._pending.size > 0) ||
|
|
919
|
-
|
|
920
|
-
|
|
964
|
+
(entry?._httpRequestControllers instanceof Set &&
|
|
965
|
+
entry._httpRequestControllers.size > 0),
|
|
921
966
|
);
|
|
922
967
|
if (budget === "depth") {
|
|
923
968
|
const limitDepth = mcpJsonDepthLimit(entry?.config?.maxJsonDepth);
|
|
@@ -956,6 +1001,15 @@ function mcpSseEventTimeoutError(timeoutMs) {
|
|
|
956
1001
|
return error;
|
|
957
1002
|
}
|
|
958
1003
|
|
|
1004
|
+
function mcpSseHeaderTimeoutError(timeoutMs) {
|
|
1005
|
+
const error = new Error(
|
|
1006
|
+
`MCP HTTP message stream headers exceeded the ${timeoutMs}ms host deadline`,
|
|
1007
|
+
);
|
|
1008
|
+
error.code = "CC_MCP_SSE_HEADER_TIMEOUT";
|
|
1009
|
+
error.timeoutMs = timeoutMs;
|
|
1010
|
+
return error;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
959
1013
|
function mcpHttpResponseTimeoutError(
|
|
960
1014
|
serverName,
|
|
961
1015
|
entry,
|
|
@@ -999,6 +1053,7 @@ const MCP_NON_RETRYABLE_PROTOCOL_ERROR_CODES = new Set([
|
|
|
999
1053
|
"CC_MCP_HTTP_RESPONSE_TIMEOUT",
|
|
1000
1054
|
"CC_MCP_HTTP_DISCARD_TIMEOUT",
|
|
1001
1055
|
"CC_MCP_SSE_EVENT_TIMEOUT",
|
|
1056
|
+
"CC_MCP_SSE_HEADER_TIMEOUT",
|
|
1002
1057
|
"CC_MCP_INBOUND_RATE_EXCEEDED",
|
|
1003
1058
|
"CC_MCP_INBOUND_TRAFFIC_EXCEEDED",
|
|
1004
1059
|
"CC_MCP_JSON_DEPTH_EXCEEDED",
|
|
@@ -1009,6 +1064,8 @@ const MCP_NON_RETRYABLE_PROTOCOL_ERROR_CODES = new Set([
|
|
|
1009
1064
|
"CC_MCP_RPC_ERROR_INVALID",
|
|
1010
1065
|
"CC_MCP_RPC_RESPONSE_INVALID",
|
|
1011
1066
|
"CC_MCP_RPC_MESSAGE_INVALID",
|
|
1067
|
+
"CC_MCP_TOOL_CATALOG_STALE",
|
|
1068
|
+
"CC_MCP_TOOL_NOT_ADVERTISED",
|
|
1012
1069
|
]);
|
|
1013
1070
|
|
|
1014
1071
|
function isMcpNonRetryableProtocolError(error) {
|
|
@@ -1422,6 +1479,7 @@ export class MCPClient extends EventEmitter {
|
|
|
1422
1479
|
this._toolMetadataBytes = 0;
|
|
1423
1480
|
this._nextId = 1;
|
|
1424
1481
|
this._reconnectors = new Map(); // name → async () => config|null
|
|
1482
|
+
this._unknownOutcomeRecovery = new Set(); // reconnect only for future explicit calls
|
|
1425
1483
|
this._reconnecting = new Map(); // name → in-flight reconnect promise
|
|
1426
1484
|
// progressToken → reset-idle callback for in-flight tools/call requests.
|
|
1427
1485
|
// Tokens are generated by this client and are removed on every terminal
|
|
@@ -2162,15 +2220,25 @@ export class MCPClient extends EventEmitter {
|
|
|
2162
2220
|
* Register a reconnector for a server: an async function that returns a
|
|
2163
2221
|
* FRESH connection config (or null when the server can't be found anymore).
|
|
2164
2222
|
* When a `callTool` on that server fails with a connection-shaped error,
|
|
2165
|
-
* the client re-resolves the config
|
|
2223
|
+
* the client re-resolves the config. An opt-in bridge may also reconnect
|
|
2224
|
+
* after an unknown tool outcome, without replaying that call.
|
|
2166
2225
|
*
|
|
2167
2226
|
* Used by the IDE bridge: a window reload / extension update restarts the
|
|
2168
2227
|
* editor's MCP server on a new port with a new token, so the original
|
|
2169
2228
|
* config is permanently dead but a lockfile re-scan finds the new one.
|
|
2170
2229
|
*/
|
|
2171
|
-
setReconnector(name, fn) {
|
|
2172
|
-
if (typeof fn === "function")
|
|
2173
|
-
|
|
2230
|
+
setReconnector(name, fn, options = {}) {
|
|
2231
|
+
if (typeof fn === "function") {
|
|
2232
|
+
this._reconnectors.set(name, fn);
|
|
2233
|
+
if (options.recoverUnknownOutcome === true) {
|
|
2234
|
+
this._unknownOutcomeRecovery.add(name);
|
|
2235
|
+
} else {
|
|
2236
|
+
this._unknownOutcomeRecovery.delete(name);
|
|
2237
|
+
}
|
|
2238
|
+
} else {
|
|
2239
|
+
this._reconnectors.delete(name);
|
|
2240
|
+
this._unknownOutcomeRecovery.delete(name);
|
|
2241
|
+
}
|
|
2174
2242
|
}
|
|
2175
2243
|
|
|
2176
2244
|
/** Return the opaque host authority used to resolve policy-bearing MCP cwd. */
|
|
@@ -3057,6 +3125,7 @@ export class MCPClient extends EventEmitter {
|
|
|
3057
3125
|
this._replaceToolInventory(name, entry, toolsResult?.tools || []);
|
|
3058
3126
|
} catch (err) {
|
|
3059
3127
|
if (isMcpFatalDiscoveryError(err)) throw err;
|
|
3128
|
+
entry._toolInventoryReady = true;
|
|
3060
3129
|
if (advertisesTools) {
|
|
3061
3130
|
toolsDiscoveryFailed = true;
|
|
3062
3131
|
entry.toolsError = err?.message || String(err);
|
|
@@ -3464,6 +3533,7 @@ export class MCPClient extends EventEmitter {
|
|
|
3464
3533
|
clientBytesUsed,
|
|
3465
3534
|
});
|
|
3466
3535
|
entry.tools = admitted.tools;
|
|
3536
|
+
entry._toolInventoryReady = true;
|
|
3467
3537
|
entry._toolMetadataBytes = admitted.metadataBytes;
|
|
3468
3538
|
this._toolMetadataBytes = clientBytesUsed + admitted.metadataBytes;
|
|
3469
3539
|
return entry.tools;
|
|
@@ -3525,9 +3595,9 @@ export class MCPClient extends EventEmitter {
|
|
|
3525
3595
|
* Call a tool on a specific server. If the server has a registered
|
|
3526
3596
|
* reconnector and the call fails with a connection-shaped error (server
|
|
3527
3597
|
* restarted / token rotated / entry dropped), re-resolve the config,
|
|
3528
|
-
* reconnect, and retry
|
|
3529
|
-
*
|
|
3530
|
-
*
|
|
3598
|
+
* reconnect, and retry a call only when its outcome is known not to have
|
|
3599
|
+
* occurred. An already-dispatched tool with an unknown outcome may refresh
|
|
3600
|
+
* the connection for a later explicit call, but is never replayed here.
|
|
3531
3601
|
* @param {string} serverName - Server name
|
|
3532
3602
|
* @param {string} toolName - Tool name
|
|
3533
3603
|
* @param {object} args - Tool arguments
|
|
@@ -3589,7 +3659,28 @@ export class MCPClient extends EventEmitter {
|
|
|
3589
3659
|
// Retry exactly once after every out-of-band flow reports completion.
|
|
3590
3660
|
return this._callToolOnce(serverName, toolName, args, options);
|
|
3591
3661
|
}
|
|
3592
|
-
if (safeRpcProperty(err, "outcomeUnknown") === true)
|
|
3662
|
+
if (safeRpcProperty(err, "outcomeUnknown") === true) {
|
|
3663
|
+
if (
|
|
3664
|
+
!options?.signal?.aborted &&
|
|
3665
|
+
isLikelyConnectionError(err) &&
|
|
3666
|
+
this._unknownOutcomeRecovery.has(serverName)
|
|
3667
|
+
) {
|
|
3668
|
+
const current = this.servers.get(serverName);
|
|
3669
|
+
const recovered =
|
|
3670
|
+
current && current !== attemptedEntry
|
|
3671
|
+
? current.state === ServerState.CONNECTED
|
|
3672
|
+
: await this._tryReconnect(serverName, {
|
|
3673
|
+
connectAuthRetryUsed: true,
|
|
3674
|
+
expectedEntry: attemptedEntry,
|
|
3675
|
+
});
|
|
3676
|
+
try {
|
|
3677
|
+
err.connectionRecovered = Boolean(recovered);
|
|
3678
|
+
} catch {
|
|
3679
|
+
// A frozen error still retains its original unknown-outcome marker.
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
throw err;
|
|
3683
|
+
}
|
|
3593
3684
|
if (
|
|
3594
3685
|
!this._reconnectors.has(serverName) &&
|
|
3595
3686
|
!this.servers.get(serverName)?.config?.headersHelper
|
|
@@ -3704,6 +3795,23 @@ export class MCPClient extends EventEmitter {
|
|
|
3704
3795
|
if (entry.state !== ServerState.CONNECTED) {
|
|
3705
3796
|
throw new Error(`Server "${serverName}" is not connected`);
|
|
3706
3797
|
}
|
|
3798
|
+
if (entry._toolInventoryDirty) {
|
|
3799
|
+
throw mcpTransportError(
|
|
3800
|
+
"CC_MCP_TOOL_CATALOG_STALE",
|
|
3801
|
+
`MCP tool catalog for server "${serverName}" is refreshing; retry after it settles`,
|
|
3802
|
+
{ transport: entry.transportKind, dispatched: false },
|
|
3803
|
+
);
|
|
3804
|
+
}
|
|
3805
|
+
if (
|
|
3806
|
+
entry._toolInventoryReady &&
|
|
3807
|
+
!entry.tools.some((tool) => tool.name === toolName)
|
|
3808
|
+
) {
|
|
3809
|
+
throw mcpTransportError(
|
|
3810
|
+
"CC_MCP_TOOL_NOT_ADVERTISED",
|
|
3811
|
+
`MCP tool "${toolName}" is not advertised by server "${serverName}"`,
|
|
3812
|
+
{ transport: entry.transportKind, dispatched: false },
|
|
3813
|
+
);
|
|
3814
|
+
}
|
|
3707
3815
|
|
|
3708
3816
|
const timeoutMs = mcpToolIdleTimeoutMs(entry.config, options);
|
|
3709
3817
|
const progressToken = `cc:${randomUUID()}`;
|
|
@@ -4137,7 +4245,8 @@ export class MCPClient extends EventEmitter {
|
|
|
4137
4245
|
};
|
|
4138
4246
|
const pending = {
|
|
4139
4247
|
resolve: (value) => settle(resolve, value),
|
|
4140
|
-
reject: (error) =>
|
|
4248
|
+
reject: (error) =>
|
|
4249
|
+
settle(reject, pendingToolFailure(error, entry, method, dispatched)),
|
|
4141
4250
|
};
|
|
4142
4251
|
entry._pending.set(id, pending);
|
|
4143
4252
|
|
|
@@ -4184,7 +4293,7 @@ export class MCPClient extends EventEmitter {
|
|
|
4184
4293
|
if (!longRunning && timeoutMs > 0) {
|
|
4185
4294
|
timeout = setTimeout(() => {
|
|
4186
4295
|
const timeoutError = new Error(`Request timeout: ${method}`);
|
|
4187
|
-
if (!
|
|
4296
|
+
if (!pending.reject(timeoutError)) return;
|
|
4188
4297
|
this._sendRequestCancellation(
|
|
4189
4298
|
serverName,
|
|
4190
4299
|
method,
|
|
@@ -4276,7 +4385,8 @@ export class MCPClient extends EventEmitter {
|
|
|
4276
4385
|
};
|
|
4277
4386
|
const pending = {
|
|
4278
4387
|
resolve: (value) => settle(resolve, value),
|
|
4279
|
-
reject: (error) =>
|
|
4388
|
+
reject: (error) =>
|
|
4389
|
+
settle(reject, pendingToolFailure(error, entry, method, dispatched)),
|
|
4280
4390
|
};
|
|
4281
4391
|
entry._pending.set(id, pending);
|
|
4282
4392
|
|
|
@@ -4314,7 +4424,7 @@ export class MCPClient extends EventEmitter {
|
|
|
4314
4424
|
`Request timeout: ${method} (WebSocket, no response in ${timeoutMs}ms)`,
|
|
4315
4425
|
{ transport: entry.transportKind, url: entry.config?.url },
|
|
4316
4426
|
);
|
|
4317
|
-
if (!
|
|
4427
|
+
if (!pending.reject(timeoutError)) return;
|
|
4318
4428
|
this._sendRequestCancellation(
|
|
4319
4429
|
serverName,
|
|
4320
4430
|
method,
|
|
@@ -4472,7 +4582,10 @@ export class MCPClient extends EventEmitter {
|
|
|
4472
4582
|
? { dispatcher: entry._httpDispatcher }
|
|
4473
4583
|
: {}),
|
|
4474
4584
|
}),
|
|
4475
|
-
|
|
4585
|
+
{
|
|
4586
|
+
controller: stream.controller,
|
|
4587
|
+
timeoutMs: _sseEventTimeout(entry.config?.requestTimeoutMs),
|
|
4588
|
+
},
|
|
4476
4589
|
);
|
|
4477
4590
|
if (response.status === 405) {
|
|
4478
4591
|
_cancelHttpResponseBody(response);
|
|
@@ -4547,6 +4660,7 @@ export class MCPClient extends EventEmitter {
|
|
|
4547
4660
|
return;
|
|
4548
4661
|
}
|
|
4549
4662
|
if (error?.code === "CC_MCP_SSE_EVENT_TIMEOUT") return;
|
|
4663
|
+
if (error?.code === "CC_MCP_SSE_HEADER_TIMEOUT") return;
|
|
4550
4664
|
if (error?.code === "CC_MCP_INBOUND_RATE_EXCEEDED") return;
|
|
4551
4665
|
if (error?.code === "CC_MCP_INBOUND_TRAFFIC_EXCEEDED") return;
|
|
4552
4666
|
if (error?.code === "CC_MCP_JSON_DEPTH_EXCEEDED") return;
|
|
@@ -4853,10 +4967,15 @@ export class MCPClient extends EventEmitter {
|
|
|
4853
4967
|
throwIfAborted();
|
|
4854
4968
|
} catch (abortError) {
|
|
4855
4969
|
settleLifecycle("failed-closed");
|
|
4856
|
-
throw
|
|
4970
|
+
throw pendingToolFailure(
|
|
4971
|
+
abortError,
|
|
4972
|
+
entry,
|
|
4973
|
+
method,
|
|
4974
|
+
request?.dispatched,
|
|
4975
|
+
);
|
|
4857
4976
|
}
|
|
4858
4977
|
settleLifecycle("failed-closed");
|
|
4859
|
-
throw err;
|
|
4978
|
+
throw pendingToolFailure(err, entry, method, request?.dispatched);
|
|
4860
4979
|
} finally {
|
|
4861
4980
|
if (timer) clearTimeout(timer);
|
|
4862
4981
|
if (responseTimer) clearTimeout(responseTimer);
|
|
@@ -5272,15 +5391,22 @@ export class MCPClient extends EventEmitter {
|
|
|
5272
5391
|
async _refreshServerList(serverName, kind) {
|
|
5273
5392
|
const entry = this.servers.get(serverName);
|
|
5274
5393
|
if (!entry) return;
|
|
5394
|
+
if (kind === "tools") {
|
|
5395
|
+
entry._toolInventoryDirty = true;
|
|
5396
|
+
}
|
|
5275
5397
|
const flags = (entry._listRefresh = entry._listRefresh || {});
|
|
5276
5398
|
if (flags[`${kind}Running`]) {
|
|
5277
5399
|
flags[`${kind}Dirty`] = true;
|
|
5278
5400
|
return;
|
|
5279
5401
|
}
|
|
5280
5402
|
flags[`${kind}Running`] = true;
|
|
5403
|
+
let refreshed = false;
|
|
5404
|
+
let toolCount = 0;
|
|
5281
5405
|
try {
|
|
5282
5406
|
do {
|
|
5407
|
+
if (this.servers.get(serverName) !== entry) return;
|
|
5283
5408
|
flags[`${kind}Dirty`] = false;
|
|
5409
|
+
refreshed = false;
|
|
5284
5410
|
try {
|
|
5285
5411
|
const method =
|
|
5286
5412
|
kind === "tools"
|
|
@@ -5289,6 +5415,10 @@ export class MCPClient extends EventEmitter {
|
|
|
5289
5415
|
? "resources/templates/list"
|
|
5290
5416
|
: "resources/list";
|
|
5291
5417
|
const result = await this._sendRequest(serverName, method, {});
|
|
5418
|
+
// A reconnect can replace this entry while the old list request is
|
|
5419
|
+
// pending. Never let its late result mutate the replacement's global
|
|
5420
|
+
// metadata budget or publish a stale inventory event.
|
|
5421
|
+
if (this.servers.get(serverName) !== entry) return;
|
|
5292
5422
|
const list =
|
|
5293
5423
|
(kind === "tools"
|
|
5294
5424
|
? result?.tools
|
|
@@ -5298,14 +5428,17 @@ export class MCPClient extends EventEmitter {
|
|
|
5298
5428
|
if (kind === "tools") {
|
|
5299
5429
|
this._replaceToolInventory(serverName, entry, list);
|
|
5300
5430
|
entry.toolsError = null;
|
|
5431
|
+
toolCount = list.length;
|
|
5301
5432
|
} else {
|
|
5302
5433
|
entry[kind] = list;
|
|
5434
|
+
this.emit(`${kind}-changed`, {
|
|
5435
|
+
server: serverName,
|
|
5436
|
+
count: list.length,
|
|
5437
|
+
});
|
|
5303
5438
|
}
|
|
5304
|
-
|
|
5305
|
-
server: serverName,
|
|
5306
|
-
count: list.length,
|
|
5307
|
-
});
|
|
5439
|
+
refreshed = true;
|
|
5308
5440
|
} catch (error) {
|
|
5441
|
+
if (this.servers.get(serverName) !== entry) return;
|
|
5309
5442
|
if (kind === "tools" && isMcpToolMetadataError(error)) {
|
|
5310
5443
|
entry.toolsError = error.message;
|
|
5311
5444
|
this.emit("server-error", {
|
|
@@ -5331,6 +5464,19 @@ export class MCPClient extends EventEmitter {
|
|
|
5331
5464
|
} while (flags[`${kind}Dirty`]);
|
|
5332
5465
|
} finally {
|
|
5333
5466
|
flags[`${kind}Running`] = false;
|
|
5467
|
+
if (
|
|
5468
|
+
kind === "tools" &&
|
|
5469
|
+
refreshed &&
|
|
5470
|
+
this.servers.get(serverName) === entry
|
|
5471
|
+
) {
|
|
5472
|
+
// Event listeners may call a newly advertised tool immediately.
|
|
5473
|
+
entry._toolInventoryDirty = false;
|
|
5474
|
+
try {
|
|
5475
|
+
this.emit("tools-changed", { server: serverName, count: toolCount });
|
|
5476
|
+
} catch {
|
|
5477
|
+
// An observer cannot make a successfully refreshed catalog stale.
|
|
5478
|
+
}
|
|
5479
|
+
}
|
|
5334
5480
|
}
|
|
5335
5481
|
}
|
|
5336
5482
|
|
|
@@ -5601,9 +5747,12 @@ function _readHttpReaderChunk(reader, signal) {
|
|
|
5601
5747
|
});
|
|
5602
5748
|
}
|
|
5603
5749
|
|
|
5604
|
-
function _waitForHttpMessageStreamResponse(
|
|
5605
|
-
|
|
5606
|
-
|
|
5750
|
+
function _waitForHttpMessageStreamResponse(
|
|
5751
|
+
responsePromise,
|
|
5752
|
+
{ controller, timeoutMs } = {},
|
|
5753
|
+
) {
|
|
5754
|
+
const signal = controller?.signal;
|
|
5755
|
+
if (signal?.aborted) {
|
|
5607
5756
|
Promise.resolve(responsePromise).then(
|
|
5608
5757
|
(response) => _cancelHttpResponseBody(response),
|
|
5609
5758
|
() => {},
|
|
@@ -5613,7 +5762,11 @@ function _waitForHttpMessageStreamResponse(responsePromise, signal) {
|
|
|
5613
5762
|
return new Promise((resolve, reject) => {
|
|
5614
5763
|
let settled = false;
|
|
5615
5764
|
let aborted = false;
|
|
5616
|
-
|
|
5765
|
+
let timer;
|
|
5766
|
+
const cleanup = () => {
|
|
5767
|
+
clearTimeout(timer);
|
|
5768
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
5769
|
+
};
|
|
5617
5770
|
const finish = (settler, value) => {
|
|
5618
5771
|
if (settled) return false;
|
|
5619
5772
|
settled = true;
|
|
@@ -5625,7 +5778,15 @@ function _waitForHttpMessageStreamResponse(responsePromise, signal) {
|
|
|
5625
5778
|
aborted = true;
|
|
5626
5779
|
finish(reject, _httpReadAbortedError());
|
|
5627
5780
|
};
|
|
5628
|
-
|
|
5781
|
+
if (Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
5782
|
+
timer = setTimeout(() => {
|
|
5783
|
+
aborted = true;
|
|
5784
|
+
if (finish(reject, mcpSseHeaderTimeoutError(timeoutMs))) {
|
|
5785
|
+
controller?.abort();
|
|
5786
|
+
}
|
|
5787
|
+
}, timeoutMs);
|
|
5788
|
+
}
|
|
5789
|
+
signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
5629
5790
|
Promise.resolve(responsePromise).then(
|
|
5630
5791
|
(response) => {
|
|
5631
5792
|
if (!finish(resolve, response) && aborted) {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from "../lib/read-file-page.js";
|
|
18
18
|
import { feature, featureVariant } from "../lib/feature-flags.js";
|
|
19
19
|
import { isAbortError } from "../lib/abort-utils.js";
|
|
20
|
+
import { isFormalBudgetError } from "../lib/formal-budget-errors.js";
|
|
20
21
|
import {
|
|
21
22
|
CONTEXT_WINDOWS,
|
|
22
23
|
getContextWindow,
|
|
@@ -680,6 +681,7 @@ export class PromptCompressor {
|
|
|
680
681
|
// A durable-ledger write failure is authoritative too. Falling back here
|
|
681
682
|
// would let the host continue after losing the model-call boundary.
|
|
682
683
|
if (error?.runtimeLedgerPersistence === true) throw error;
|
|
684
|
+
if (isFormalBudgetError(error)) throw error;
|
|
683
685
|
if (error?.code === "CC_AGENT_EVOLUTION_INGRESS_FAILED") throw error;
|
|
684
686
|
// A workflow-bound query may already have reached the provider. An
|
|
685
687
|
// extractive fallback would make the outer durable effect look completed
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
11
|
import { CostBudget } from "./cost-budget.js";
|
|
12
|
+
import { isFormalBudgetError } from "./formal-budget-errors.js";
|
|
12
13
|
import { FREE_PROVIDERS, mergePricing } from "./llm-pricing.js";
|
|
13
14
|
import { redactSecrets } from "./secret-scan.js";
|
|
14
15
|
import { firstBalancedJson } from "./json-schema-output.js";
|
|
@@ -179,8 +180,8 @@ export function resolveAdvisorConfig({
|
|
|
179
180
|
);
|
|
180
181
|
const hasManagedAdvisorPolicy = Boolean(
|
|
181
182
|
Object.keys(managedAdvisor).length > 0 ||
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
managed?.advisorAllowedProviders !== undefined ||
|
|
184
|
+
managed?.advisorAllowedModels !== undefined,
|
|
184
185
|
);
|
|
185
186
|
let policyReason = null;
|
|
186
187
|
if (managedAdvisor.enabled === false) {
|
|
@@ -937,6 +938,7 @@ export class AdvisorRuntime {
|
|
|
937
938
|
};
|
|
938
939
|
} catch (error) {
|
|
939
940
|
if (error?.runtimeLedgerPersistence === true) throw error;
|
|
941
|
+
if (isFormalBudgetError(error)) throw error;
|
|
940
942
|
if (error?.code === "CC_AGENT_EVOLUTION_INGRESS_FAILED") throw error;
|
|
941
943
|
const failure = {
|
|
942
944
|
callId,
|
package/src/lib/agent-ipc-bus.js
CHANGED
|
@@ -13,6 +13,7 @@ import { EventEmitter } from "node:events";
|
|
|
13
13
|
import crypto from "node:crypto";
|
|
14
14
|
import { EventRuntimeProducer } from "./event-runtime-producer.js";
|
|
15
15
|
import { EventRuntimeStore } from "./event-runtime-store.js";
|
|
16
|
+
import { requireUnscopedDescendantControl } from "./formal-budget-provider-scope.js";
|
|
16
17
|
import executionBroker from "./process-execution-broker/index.js";
|
|
17
18
|
import {
|
|
18
19
|
AGENT_IPC_DEFAULT_LIMITS,
|
|
@@ -284,6 +285,7 @@ class AgentIPCBus extends EventEmitter {
|
|
|
284
285
|
* @returns {Promise<{process: ChildProcess, agentId: string}>}
|
|
285
286
|
*/
|
|
286
287
|
async spawnAgentProcess(command, args = [], options = {}) {
|
|
288
|
+
requireUnscopedDescendantControl();
|
|
287
289
|
const agentId = options.agentId || crypto.randomUUID();
|
|
288
290
|
if (
|
|
289
291
|
this._childTransports.has(agentId) ||
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
2
|
import { randomBytes } from "node:crypto";
|
|
3
3
|
import { createNdjsonReader } from "./background-session-transport.js";
|
|
4
|
+
import { requireUnscopedDescendantControl } from "./formal-budget-provider-scope.js";
|
|
4
5
|
import {
|
|
5
6
|
BACKGROUND_AGENT_KEEPER_ARM,
|
|
6
7
|
BACKGROUND_AGENT_KEEPER_ARMED,
|
|
@@ -67,6 +68,7 @@ async function connectWithDeadline(pipePath, timeoutMs) {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
export async function connectBackgroundAgentKeeper(options = {}) {
|
|
71
|
+
requireUnscopedDescendantControl();
|
|
70
72
|
const hello = normalizeBackgroundAgentKeeperHello(options);
|
|
71
73
|
const connectTimeoutMs = Math.max(
|
|
72
74
|
1,
|
|
@@ -234,6 +236,7 @@ export async function connectBackgroundAgentKeeper(options = {}) {
|
|
|
234
236
|
|
|
235
237
|
return Object.freeze({
|
|
236
238
|
async arm(turn) {
|
|
239
|
+
requireUnscopedDescendantControl();
|
|
237
240
|
const normalized = normalizeBackgroundAgentKeeperTurn(turn);
|
|
238
241
|
if (activeTurn) {
|
|
239
242
|
throw keeperError(
|
|
@@ -50,17 +50,28 @@ export function transportPipePath(id, dir, options = {}) {
|
|
|
50
50
|
*/
|
|
51
51
|
export function createNdjsonReader(onMessage, onError = () => {}) {
|
|
52
52
|
let carry = "";
|
|
53
|
+
let droppingOversizedLine = false;
|
|
54
|
+
const decoder = new TextDecoder("utf-8");
|
|
53
55
|
return (chunk) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
let text =
|
|
57
|
+
typeof chunk === "string"
|
|
58
|
+
? chunk
|
|
59
|
+
: decoder.decode(chunk, { stream: true });
|
|
60
|
+
if (droppingOversizedLine) {
|
|
61
|
+
const end = text.indexOf("\n");
|
|
62
|
+
if (end < 0) return;
|
|
63
|
+
droppingOversizedLine = false;
|
|
64
|
+
text = text.slice(end + 1);
|
|
59
65
|
}
|
|
66
|
+
carry += text;
|
|
60
67
|
let index;
|
|
61
68
|
while ((index = carry.indexOf("\n")) !== -1) {
|
|
62
69
|
const line = carry.slice(0, index).replace(/\r$/, "");
|
|
63
70
|
carry = carry.slice(index + 1);
|
|
71
|
+
if (Buffer.byteLength(line, "utf8") > MAX_LINE_BYTES) {
|
|
72
|
+
onError(new Error("line too long"));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
64
75
|
if (!line.trim()) continue;
|
|
65
76
|
let message;
|
|
66
77
|
try {
|
|
@@ -71,6 +82,11 @@ export function createNdjsonReader(onMessage, onError = () => {}) {
|
|
|
71
82
|
}
|
|
72
83
|
onMessage(message);
|
|
73
84
|
}
|
|
85
|
+
if (Buffer.byteLength(carry, "utf8") > MAX_LINE_BYTES) {
|
|
86
|
+
carry = "";
|
|
87
|
+
droppingOversizedLine = true;
|
|
88
|
+
onError(new Error("line too long"));
|
|
89
|
+
}
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
92
|
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
* Uses built-in fetch for basic operations, optional playwright for screenshots.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { requireUnscopedExternalToolAccess } from "./formal-budget-provider-scope.js";
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Fetch a URL and return the raw HTML.
|
|
8
10
|
*/
|
|
9
11
|
export async function fetchPage(url, options = {}) {
|
|
12
|
+
requireUnscopedExternalToolAccess();
|
|
10
13
|
const timeout = options.timeout || 30000;
|
|
11
14
|
const controller = new AbortController();
|
|
12
15
|
const timer = setTimeout(() => controller.abort(), timeout);
|
|
@@ -179,6 +182,7 @@ export function extractLinks(html, baseUrl) {
|
|
|
179
182
|
* Returns null if playwright is not installed.
|
|
180
183
|
*/
|
|
181
184
|
export async function takeScreenshot(url, outputPath, options = {}) {
|
|
185
|
+
requireUnscopedExternalToolAccess();
|
|
182
186
|
try {
|
|
183
187
|
const { chromium } = await import("playwright");
|
|
184
188
|
const browser = await chromium.launch({ headless: true });
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
import { readFileSync, existsSync } from "node:fs";
|
|
34
34
|
import { join, dirname } from "node:path";
|
|
35
|
+
import { requireUnscopedExternalToolAccess } from "./formal-budget-provider-scope.js";
|
|
35
36
|
|
|
36
37
|
const ANDROID_PREFIX = "/data/data/com.chainlesschain.android/";
|
|
37
38
|
|
|
@@ -72,6 +73,7 @@ function resolveBridgeConfigDir() {
|
|
|
72
73
|
* (server not started yet, or running off-device without override).
|
|
73
74
|
*/
|
|
74
75
|
export function loadBridgeConfig() {
|
|
76
|
+
requireUnscopedExternalToolAccess();
|
|
75
77
|
const dir = resolveBridgeConfigDir();
|
|
76
78
|
if (!dir) return null;
|
|
77
79
|
try {
|
|
@@ -109,6 +111,7 @@ export class AndroidBridgeUnavailableError extends Error {
|
|
|
109
111
|
* - Method name unknown (server returns {"error": "UNKNOWN_METHOD"})
|
|
110
112
|
*/
|
|
111
113
|
export async function invoke(method, params = {}) {
|
|
114
|
+
requireUnscopedExternalToolAccess();
|
|
112
115
|
if (typeof method !== "string" || method.length === 0) {
|
|
113
116
|
throw new TypeError(
|
|
114
117
|
"cc-android-bridge.invoke: method must be non-empty string",
|
|
@@ -170,6 +173,7 @@ export async function invoke(method, params = {}) {
|
|
|
170
173
|
* Returns `{ available: boolean, reason?: string, port?: number }`.
|
|
171
174
|
*/
|
|
172
175
|
export function caps() {
|
|
176
|
+
requireUnscopedExternalToolAccess();
|
|
173
177
|
if (process.env.CC_ANDROID_BRIDGE_OVERRIDE === "1") {
|
|
174
178
|
return { available: true, reason: "test-override" };
|
|
175
179
|
}
|