chainlesschain 0.166.115 → 0.166.118
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -5
- package/package.json +4 -4
- 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/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BsoSoDNb.js → AIOps-BGySwMIP.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Dcx7Gm5t.js → ActionButton-Chn7fBLr.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-S1hsBIz3.js → Analytics-ORH7UkGa.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B2j067qM.js → AppLayout-8xV4jWjP.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D5iGV9ic.js → Artifacts-26SBK-x-.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C8ChVvXu.js → Audit-CtXpqbXg.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Cg97AAJS.js → BackgroundAgents-C5zLvQis.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CyxU9IUg.js → Backup-C93xY4vO.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CKlWjA8I.js → BaseInput-DpVCHfAn.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-C-EqZza6.js → Chat-DM0LblR2.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BRFiXKPX.js → ChatBubbleRenderer-unlQUF1T.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-kkI13tSJ.js → Checkbox-BsAt3cKR.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-NlqEDwHK.js → Codegen-E_kp4KFd.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CfepEu79.js → Col-6msR3T6I.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BRo0qLXM.js → Community-PyX9c5D-.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BMu8TP0E.js → Compact-7G1bVDSH.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B7Q3Moef.js → Compliance-DcHN7GlD.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BVwt7Xmc.js → Cowork-WUIHJYDx.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CgBv20Qy.js → Cron-CWgCbptg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CwcSBJk2.js → Crosschain-BzKZ6roD.js} +1 -1
- package/src/assets/web-panel/assets/{DID-d20rCiIm.js → DID-r7zxeItn.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-PpZaUYpS.js → Dashboard-D3pBiN2H.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DjsLdX_Z.js → Dropdown-C4otRJlZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CaPkrtxn.js → EmailListRenderer-CzDTC8lm.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DDY8cQnE.js → EvolutionSettings-DGkXiIs-.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-VQavMjyj.js → FamilyGuardDashboard-BKdEyuiR.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0GvKQgI.js → Federation-dsI-xcpf.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dl_TWHmb.js → FormItemContext-CEEb1fMR.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bny2uagG.js → GenericCardRenderer-D_mfO3Ts.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B01KXq47.js → Git-CBwr2ZI3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-F4c4Vwo1.js → Governance-D-Wy2Jjr.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-_025Q-8K.js → Inference-B4Yk_IRx.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DwbTmQb1.js → KnowledgeGraph-DoI7bi6m.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CnNo0hCm.js → Logs-Ce1IiKAj.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-GND_8y0V.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Dkz5bv7F.js → Marketplace-CsIEByzK.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CBtRwDW_.js → McpTools-_DRzjcIn.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-Y9jnyTb7.js → Memory-zvLpyi__.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Br1urkOz.js → MobileBridge-DXd1ik2Z.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DnsyuerX.js → MobileProjects-DKh2q-Y9.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-he3ZzieF.js → Mtc-Ct-fhtIx.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BadphAuN.js → MtcAudit-J4zY3Oqk.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-3_pVLymK.js → Multisig-B2HJMCKe.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DmtmHfsI.js → NLProgramming-CwcSmU4q.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CE4L2O55.js → Notes-Da53L6wb.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-B7QmfJn9.js → NotificationSettings-BxhufdrA.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-O0wRSyJ0.js → OrderTableRenderer-BoFwohAi.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BrlMSsyT.js → Organization-MIsMrUes.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CY4ULPrZ.js → Overflow-Dy2P4v3q.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-kIANZYKd.js → P2P-CD9Sxn2y.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DEgB4rvF.js → PdhVaultBrowser-BvBWgfG0.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-CWxywRp5.js → Permissions-CwOlDRis.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DAg7iCbr.js → PersonalDataHub-CZYaxEpv.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Brc6ONnR.js → Pipeline-kLU7PUbB.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CcinYTL8.js → Privacy-BVRycSiI.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bz8XEsom.js → ProjectInit-DP3pr7uJ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CsOMlSTZ.js → ProjectSettings-CACaDYjs.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CB1k4zTC.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CeunOQiH.js → Providers-D7Y9WHRE.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CN2a2_Fb.js → QrScannerModal-CeP8xzs1.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CVeLif3e.js → QuickAsk-iJVFrhZ2.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-1k9WOEGM.js → Recommend-DmTpnagw.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Q8UCqIMw.js → RemoteSession-C6ek8Uni.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CkrCgXKM.js → Reputation-CPfwc9de.js} +1 -1
- package/src/assets/web-panel/assets/{Row-JFdvuTzi.js → Row-C1wwtSMJ.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C74JHCmk.js → RssFeed-BiDJsqaH.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DrJiVO1T.js → Search-BF6Aon95.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BJzNlSJq.js → Security-Bps0XnV4.js} +3 -3
- package/src/assets/web-panel/assets/{Services-D4TLMnJm.js → Services-uf92smGR.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-cswTDqhh.js → Skeleton-DQd4eVWW.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Bv0rM1BS.js → Skills-DgamiYa5.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-D9rE7hNh.js → Sla-CF1IVIrm.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-Bzxmjbpc.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-BwnMG8kq.js → SyncSettings-B8zKauiq.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-wJvU24cB.js → Tasks-DPKV_xSt.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CZbRU3tN.js → Templates-BikeSZIF.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-_jbpFJPZ.js → Tenant-CEaUaDkJ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BzNm5WKZ.js → Terminal-ZPgOSQ_q.js} +3 -3
- package/src/assets/web-panel/assets/{TimelineRenderer-bmybWjuS.js → TimelineRenderer-DmyB4Udk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-o1WDcqVQ.js → Tokens-g85Pm5TO.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BB1D6sIB.js → Trigger-D202hx9a.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CLxdCfy2.js → Trust-DzvQYVFy.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B9LS6vS0.js → UkeySign-KRzwddVg.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bg0-wxjz.js → VideoEditing-IRBXLO2z.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Bw0G2F6P.js → Wallet-DSf5KPgQ.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-irEiNY9b.js → WebAuthn-DNPxLTCc.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Bh08FbJs.js → WorkflowEditor-C3wAtVcK.js} +1 -1
- package/src/assets/web-panel/assets/{addon-fit-CK6X9sAG.js → addon-fit-CbkjSUJl.js} +1 -1
- package/src/assets/web-panel/assets/{chat-De-FPjVT.js → chat-q3XXUtv2.js} +1 -1
- package/src/assets/web-panel/assets/{colors-ygdyvinU.js → colors-CF54SNei.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BQ9jH9KV.js → compact-item-BaRkvZuT.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BFuVSyox.js → createContext-CDR9hsfs.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-1LO-NplX.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i19GtR1P.js → hasIn-DlC--S8R.js} +1 -1
- package/src/assets/web-panel/assets/{index-DS1IwwGL.js → index-B0Ptc7yu.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1IsP_JO.js → index-B0V9rgdu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWfgeaG4.js → index-BEiUlFKb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTY20pWu.js → index-BJO0n1LQ.js} +1 -1
- package/src/assets/web-panel/assets/index-BLaJsev4.js +1 -0
- package/src/assets/web-panel/assets/index-BLmviChG.js +1 -0
- package/src/assets/web-panel/assets/{index-IXkif6J_.js → index-BU5DJqk7.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVhtukYX.js → index-BY-Tf3OM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKlU5VZy.js → index-BZrE0Go8.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bw5pTpnI.js → index-BizdX2X5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGMxK155.js → index-C87Yr3h1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVnFgasM.js → index-C9Wypz9e.js} +1 -1
- package/src/assets/web-panel/assets/{index-C61w3omz.js → index-CAoG_E-q.js} +1 -1
- package/src/assets/web-panel/assets/{index-l5-J0jHx.js → index-CAxSyMrF.js} +1 -1
- package/src/assets/web-panel/assets/{index-28DjsABm.js → index-CC5HjNM6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPUCvc8i.js → index-CNZQEZ9g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpdXhhMY.js → index-CPvIhha6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAboGZTw.js → index-CR_wqMGy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DL7ewjD2.js → index-CSClXoB3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bhf-MuUh.js → index-CZ8azVgB.js} +3 -3
- package/src/assets/web-panel/assets/{index-BaaydJcC.js → index-Ccc5z8eJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2LieObB.js → index-CeiKbM3a.js} +1 -1
- package/src/assets/web-panel/assets/{index-We2nK3ju.js → index-Cl6av3X7.js} +1 -1
- package/src/assets/web-panel/assets/{index-m8waSAyv.js → index-CtGfeD7E.js} +1 -1
- package/src/assets/web-panel/assets/{index-cDJsyAkI.js → index-Ctid12Gq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlwxUZQL.js → index-D0H-N0uG.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBYiCI1d.js → index-D0vIgprF.js} +1 -1
- package/src/assets/web-panel/assets/{index-_9tUBcLm.js → index-D4wUDFRg.js} +1 -1
- package/src/assets/web-panel/assets/{index-4HoFz1MA.js → index-DJFipyK7.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cq9k4-Ws.js → index-DX2REKNp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuuOX5u3.js → index-Dc3gD0cw.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgjLaB7k.js → index-DiQzer2R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMNjaSir.js → index-DntKLOs9.js} +1 -1
- package/src/assets/web-panel/assets/{index-vXtH3o6O.js → index-Dplhl6gh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLMtCKAY.js → index-Dq8q_PWB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXrk8OYO.js → index-IVQdOBNN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBVcGaxk.js → index-Kerduyao.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKblSCL9.js → index-W6cLGjpW.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgoSgmjK.js → index-qZDNFll9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B_EZHeqN.js → initDefaultProps-Ccz7v71u.js} +1 -1
- package/src/assets/web-panel/assets/{markdown-Yo_c6Krv.js → markdown-Bq2x0XsR.js} +1 -1
- package/src/assets/web-panel/assets/markdown-DUKxbhE4.js +51 -0
- package/src/assets/web-panel/assets/{motion-BrVb_Gy1.js → motion-BlCLpVDp.js} +1 -1
- package/src/assets/web-panel/assets/{move-CKxVRL_J.js → move-B80G7fLU.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C80rvQ1J.js → mtc-parser-Djw08NJh.js} +1 -1
- package/src/assets/web-panel/assets/{omit-De5vD7BR.js → omit-Bg_G1eUr.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTyEDjth.js → pickAttrs-Df9zYUg2.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BWR94AjR.js → placementArrow-DjCDLhJ4.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-1g-Vnibk.js → responsiveObserve--Naz7NgY.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dmg6dYuF.js → slide-CHn3ald-.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Ddj6rSab.js → statusUtils-BiGwoIK_.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DyP1mPDf.js → styleChecker-Zf2dQx1j.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D3d_0YuY.js → useFlexGapSupport-sLES8nyD.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-M3vq-gE2.js → useFs-DV1Hl4qu.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-GtP2TgtK.js → usePersonalDataHub-CZXr2Qxg.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BurE2ATQ.js → vnode-e8Eo3Oyl.js} +1 -1
- package/src/assets/web-panel/assets/{xterm-BZcWGsqw.js → xterm-zbskxxGA.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Ch-ViiDe.js → zoom-B8A6xKMF.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/compact.js +7 -2
- package/src/data/changelog.json +27 -1
- package/src/harness/jsonl-session-store.js +80 -74
- package/src/harness/prompt-compressor.js +57 -3
- package/src/lib/artifact-store.js +129 -20
- package/src/lib/bounded-artifact-file-read.js +128 -46
- package/src/lib/context-memory-kernel/context-image-transport.js +248 -0
- package/src/lib/context-memory-kernel/jsonl-session-context-port.js +4 -1
- package/src/lib/context-memory-kernel/live-compaction.js +40 -10
- package/src/lib/context-memory-kernel/message-adapter.js +80 -10
- package/src/lib/context-memory-kernel/message-bundle-store.js +1140 -0
- package/src/lib/context-memory-kernel/provider-context.js +23 -8
- package/src/lib/evolution/agent-evolution-ingress.js +103 -19
- package/src/lib/evolution/agent-evolution-runtime-composition.js +65 -27
- package/src/lib/evolution/agent-model-projection.js +90 -18
- package/src/lib/evolution/evidence-json-text.js +341 -42
- package/src/lib/evolution/evolution-artifact-ports.js +1005 -83
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +59 -15
- package/src/lib/evolution/evolution-evidence-projector.js +153 -16
- package/src/lib/evolution/evolution-evidence-storage-layout.js +115 -0
- package/src/lib/evolution/evolution-file-witness.js +7 -3
- package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +6 -2
- package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +6 -2
- package/src/lib/evolution/evolution-ledger.js +226 -55
- package/src/lib/evolution/evolution-private-storage.js +20 -0
- package/src/lib/evolution/evolution-run-ledger-adapter.js +298 -11
- package/src/lib/evolution/evolution-windows-directory-durability.js +215 -32
- package/src/lib/evolution/local-ui-evolution-runtime.js +3 -38
- package/src/lib/evolution/local-ui-signing-authority.js +69 -0
- package/src/lib/image-token-estimate.js +59 -0
- package/src/lib/ollama-provider-fetch.js +33 -0
- package/src/lib/provider-stream.js +14 -13
- package/src/lib/read-file-loop-guard.js +7 -4
- package/src/lib/session-history-origins.js +94 -35
- package/src/lib/session-message-provenance.js +26 -2
- package/src/lib/session-runtime-retention.js +10 -1
- package/src/lib/session-transcript-history.js +5 -1
- package/src/lib/session-transcript-migration.js +67 -12
- package/src/lib/storage-failure-cause-codes.js +449 -0
- package/src/lib/tool-result-preview.js +276 -0
- package/src/runtime/agent-core.js +111 -92
- package/src/runtime/headless-stream.js +121 -27
- package/src/assets/web-panel/assets/MarkdownRenderer-D8_iZief.js +0 -1
- package/src/assets/web-panel/assets/Projects-BeSOM6wi.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-Bfhvin8B.js +0 -1
- package/src/assets/web-panel/assets/devWarning-c2I2Rn4_.js +0 -1
- package/src/assets/web-panel/assets/index-CTs4dYcV.js +0 -1
- package/src/assets/web-panel/assets/index-DeuvaW15.js +0 -1
- package/src/assets/web-panel/assets/markdown-CsiA8-E5.js +0 -50
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createEvidenceJsonTextBoundary,
|
|
3
|
+
AGENT_CODE_TEXT_RESULT_TOOLS,
|
|
4
|
+
} from "./evolution/evidence-json-text.js";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
|
|
7
|
+
// Keep host identity outside the JSON evidence object. External JSON results
|
|
8
|
+
// cannot nominate a digest or borrow an earlier command's output identity.
|
|
9
|
+
const HOST_OUTPUT_IDENTITIES = new WeakMap();
|
|
10
|
+
export function registerHostToolOutput(result, output) {
|
|
11
|
+
HOST_OUTPUT_IDENTITIES.set(
|
|
12
|
+
result,
|
|
13
|
+
Object.freeze({
|
|
14
|
+
chars: output.length,
|
|
15
|
+
digest: createHash("sha256").update(output).digest("hex"),
|
|
16
|
+
visibleOutput: result.output,
|
|
17
|
+
}),
|
|
18
|
+
);
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
export function copyHostToolOutputIdentity(result, source) {
|
|
22
|
+
const identity = HOST_OUTPUT_IDENTITIES.get(source);
|
|
23
|
+
if (identity) HOST_OUTPUT_IDENTITIES.set(result, identity);
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
export function hostToolOutputIdentity(result) {
|
|
27
|
+
const identity = HOST_OUTPUT_IDENTITIES.get(result);
|
|
28
|
+
return identity?.visibleOutput === result?.output ? identity : undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const PREVIEW_HINT =
|
|
32
|
+
"Tool output truncated. Narrow the request: filter/count locally, select fields, search_files, or read_file with offset/limit. Omitted text is not full-output evidence.";
|
|
33
|
+
|
|
34
|
+
/** Check only host-created excerpts; original uncut tool text still reaches ingress. */
|
|
35
|
+
function completeExcerpt(text, tool) {
|
|
36
|
+
const scan = createEvidenceJsonTextBoundary((message) => new Error(message));
|
|
37
|
+
const visit = (value, layer) => {
|
|
38
|
+
if (typeof value === "string") return project(value, layer);
|
|
39
|
+
if (Array.isArray(value)) return value.map((child) => visit(child, layer));
|
|
40
|
+
if (value && typeof value === "object") {
|
|
41
|
+
return Object.fromEntries(
|
|
42
|
+
Object.entries(value).map(([key, child]) => [key, visit(child, layer)]),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
};
|
|
47
|
+
const project = (value, layer = 0) =>
|
|
48
|
+
scan(value, {
|
|
49
|
+
layer,
|
|
50
|
+
codeText: AGENT_CODE_TEXT_RESULT_TOOLS.includes(tool),
|
|
51
|
+
visit,
|
|
52
|
+
plain: (plain) => plain,
|
|
53
|
+
equal: (left, right) => JSON.stringify(left) === JSON.stringify(right),
|
|
54
|
+
});
|
|
55
|
+
try {
|
|
56
|
+
project(text);
|
|
57
|
+
return true;
|
|
58
|
+
} catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function omitted(chars) {
|
|
64
|
+
return `Text omitted (${chars} chars); narrow the request to inspect a complete value.`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const STATUS_KEYS = new Set([
|
|
68
|
+
"success",
|
|
69
|
+
"error",
|
|
70
|
+
"exitCode",
|
|
71
|
+
"status",
|
|
72
|
+
"code",
|
|
73
|
+
"signal",
|
|
74
|
+
"path",
|
|
75
|
+
"range",
|
|
76
|
+
"nextRead",
|
|
77
|
+
"duration",
|
|
78
|
+
"language",
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
// Native JSON.parse is used only after checking its lossy cases: duplicate
|
|
82
|
+
// decoded keys and non-finite/unsafe numbers must never turn into a safe-looking
|
|
83
|
+
// preview. This pass does not repair syntax or decode text leaves.
|
|
84
|
+
function parsePreviewJson(text) {
|
|
85
|
+
const value = JSON.parse(text);
|
|
86
|
+
const stack = [];
|
|
87
|
+
for (let index = 0; index < text.length; index++) {
|
|
88
|
+
const char = text[index];
|
|
89
|
+
if (char === '"') {
|
|
90
|
+
const start = index;
|
|
91
|
+
while (++index < text.length) {
|
|
92
|
+
if (text[index] === "\\") index++;
|
|
93
|
+
else if (text[index] === '"') break;
|
|
94
|
+
}
|
|
95
|
+
const object = stack.at(-1);
|
|
96
|
+
if (object?.key) {
|
|
97
|
+
const key = JSON.parse(text.slice(start, index + 1));
|
|
98
|
+
if (object.keys.has(key)) throw new TypeError("Ambiguous JSON keys");
|
|
99
|
+
object.keys.add(key);
|
|
100
|
+
object.key = false;
|
|
101
|
+
}
|
|
102
|
+
} else if (char === "{") stack.push({ keys: new Set(), key: true });
|
|
103
|
+
else if (char === "[") stack.push(null);
|
|
104
|
+
else if (char === "}" || char === "]") stack.pop();
|
|
105
|
+
else if (char === "," && stack.at(-1)) stack.at(-1).key = true;
|
|
106
|
+
else if (/[\d-]/u.test(char)) {
|
|
107
|
+
const token = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/u.exec(
|
|
108
|
+
text.slice(index),
|
|
109
|
+
)[0];
|
|
110
|
+
const number = Number(token);
|
|
111
|
+
if (
|
|
112
|
+
!Number.isFinite(number) ||
|
|
113
|
+
(Number.isInteger(number) && !Number.isSafeInteger(number))
|
|
114
|
+
)
|
|
115
|
+
throw new TypeError("Unsafe JSON number");
|
|
116
|
+
index += token.length - 1;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Produce complete JSON values, never prefixes of a JSON leaf. */
|
|
123
|
+
export function boundedToolResultText(text, max) {
|
|
124
|
+
if (text.length <= max) return text;
|
|
125
|
+
let original;
|
|
126
|
+
try {
|
|
127
|
+
original = parsePreviewJson(text);
|
|
128
|
+
} catch {
|
|
129
|
+
// Plain output can retain a prefix only when it cannot contain a sliced
|
|
130
|
+
// structured span. In particular, do not hide broken JSON in a preview.
|
|
131
|
+
if (!/[{}\[\]"']/u.test(text)) {
|
|
132
|
+
const marker = `\nTool output truncated (${text.length} chars). Narrow the request.`;
|
|
133
|
+
if (marker.length < max) {
|
|
134
|
+
let end = max - marker.length;
|
|
135
|
+
if (/[\uD800-\uDBFF]/u.test(text[end - 1] ?? "")) end--;
|
|
136
|
+
return text.slice(0, end) + marker;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
original = omitted(text.length);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const limit of [8192, 2048, 512, 128, 0]) {
|
|
143
|
+
let nodes = 0;
|
|
144
|
+
const preview = (value, depth = 0) => {
|
|
145
|
+
if (++nodes > 128 || depth > 6)
|
|
146
|
+
return "Value omitted; select a smaller subtree.";
|
|
147
|
+
if (typeof value === "string")
|
|
148
|
+
return JSON.stringify(value).length > limit
|
|
149
|
+
? omitted(value.length)
|
|
150
|
+
: value;
|
|
151
|
+
if (!value || typeof value !== "object") return value;
|
|
152
|
+
if (Array.isArray(value)) {
|
|
153
|
+
const kept = [];
|
|
154
|
+
for (const child of value) {
|
|
155
|
+
if (kept.length >= 32 || nodes >= 128) break;
|
|
156
|
+
kept.push(preview(child, depth + 1));
|
|
157
|
+
}
|
|
158
|
+
if (kept.length < value.length)
|
|
159
|
+
kept.push(
|
|
160
|
+
`Items omitted (${value.length - kept.length}); narrow the request.`,
|
|
161
|
+
);
|
|
162
|
+
return kept;
|
|
163
|
+
}
|
|
164
|
+
const kept = Object.create(null);
|
|
165
|
+
const entries = Object.entries(value).sort(
|
|
166
|
+
([a], [b]) => Number(STATUS_KEYS.has(b)) - Number(STATUS_KEYS.has(a)),
|
|
167
|
+
);
|
|
168
|
+
let count = 0;
|
|
169
|
+
for (const [key, child] of entries) {
|
|
170
|
+
if (count >= 32 || nodes >= 128) break;
|
|
171
|
+
if (key.length > 256) continue;
|
|
172
|
+
Object.defineProperty(kept, key, {
|
|
173
|
+
enumerable: true,
|
|
174
|
+
value: preview(child, depth + 1),
|
|
175
|
+
});
|
|
176
|
+
count++;
|
|
177
|
+
}
|
|
178
|
+
if (count < entries.length) {
|
|
179
|
+
let marker = "_omittedFields";
|
|
180
|
+
while (Object.hasOwn(kept, marker)) marker += "_";
|
|
181
|
+
Object.defineProperty(kept, marker, {
|
|
182
|
+
enumerable: true,
|
|
183
|
+
value: entries.length - count,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return kept;
|
|
187
|
+
};
|
|
188
|
+
const value = preview(original);
|
|
189
|
+
const result =
|
|
190
|
+
value && !Array.isArray(value) && typeof value === "object"
|
|
191
|
+
? value
|
|
192
|
+
: { preview: value };
|
|
193
|
+
let marker = "_toolOutputPreview";
|
|
194
|
+
while (Object.hasOwn(result, marker)) marker += "_";
|
|
195
|
+
Object.defineProperty(result, marker, {
|
|
196
|
+
enumerable: true,
|
|
197
|
+
value: {
|
|
198
|
+
truncated: true,
|
|
199
|
+
originalChars: text.length,
|
|
200
|
+
hint: PREVIEW_HINT,
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
const serialized = JSON.stringify(result);
|
|
204
|
+
if (serialized.length <= max) return serialized;
|
|
205
|
+
}
|
|
206
|
+
const summary = JSON.stringify({
|
|
207
|
+
truncated: true,
|
|
208
|
+
originalChars: text.length,
|
|
209
|
+
hint: PREVIEW_HINT,
|
|
210
|
+
});
|
|
211
|
+
if (summary.length <= max) return summary;
|
|
212
|
+
if (max >= 18) return '{"truncated":true}';
|
|
213
|
+
return max >= 4 ? "null" : max >= 2 ? "{}" : "0";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Keep cursors/status, but remove JSON fragments created by host paging. */
|
|
217
|
+
export function safeHostToolResultForModel(tool, result) {
|
|
218
|
+
if (!result || typeof result !== "object" || Array.isArray(result))
|
|
219
|
+
return result;
|
|
220
|
+
const fields = [];
|
|
221
|
+
if (
|
|
222
|
+
tool === "read_file" &&
|
|
223
|
+
(result.truncated || result.range || result.nextRead)
|
|
224
|
+
)
|
|
225
|
+
fields.push("content");
|
|
226
|
+
if (tool === "run_code" && result.truncated) fields.push("output");
|
|
227
|
+
if (tool === "check_shell") fields.push("stdout", "stderr");
|
|
228
|
+
if (tool === "run_shell" || tool === "git") {
|
|
229
|
+
for (const field of ["stdout", "stderr"])
|
|
230
|
+
if (result[`${field}_truncated`])
|
|
231
|
+
fields.push(field, `${field}_diagnostics`);
|
|
232
|
+
}
|
|
233
|
+
let safe = result;
|
|
234
|
+
for (const field of fields) {
|
|
235
|
+
const text = result[field];
|
|
236
|
+
if (typeof text !== "string" || completeExcerpt(text, tool)) continue;
|
|
237
|
+
if (safe === result) safe = { ...result };
|
|
238
|
+
safe[field] = omitted(text.length);
|
|
239
|
+
safe[`${field}Omitted`] = true;
|
|
240
|
+
safe[`${field}OmittedChars`] = text.length;
|
|
241
|
+
}
|
|
242
|
+
return safe;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Prefer a whole JSON tree over slicing stdout through an embedded value. */
|
|
246
|
+
export function boundedCommandOutput(output, max, tool = "run_code") {
|
|
247
|
+
const encoded = JSON.stringify(output);
|
|
248
|
+
if (encoded.length <= max) return output;
|
|
249
|
+
// If stdout itself is JSON, preview that tree rather than its quoted form.
|
|
250
|
+
let json = false;
|
|
251
|
+
try {
|
|
252
|
+
parsePreviewJson(output);
|
|
253
|
+
json = true;
|
|
254
|
+
} catch {
|
|
255
|
+
/* Plain command text. */
|
|
256
|
+
}
|
|
257
|
+
if (json) {
|
|
258
|
+
const preview = boundedToolResultText(
|
|
259
|
+
output,
|
|
260
|
+
Math.max(1, Math.floor(max / 2)),
|
|
261
|
+
);
|
|
262
|
+
if (JSON.stringify(preview).length <= max && completeExcerpt(preview, tool))
|
|
263
|
+
return preview;
|
|
264
|
+
} else if (!/[{}\[\]"']/u.test(output)) {
|
|
265
|
+
let low = 0;
|
|
266
|
+
let high = Math.min(output.length, max);
|
|
267
|
+
while (low < high) {
|
|
268
|
+
const middle = Math.ceil((low + high) / 2);
|
|
269
|
+
if (JSON.stringify(output.slice(0, middle)).length <= max) low = middle;
|
|
270
|
+
else high = middle - 1;
|
|
271
|
+
}
|
|
272
|
+
if (/[\uD800-\uDBFF]/u.test(output[low - 1] ?? "")) low--;
|
|
273
|
+
return output.slice(0, low);
|
|
274
|
+
}
|
|
275
|
+
return omitted(output.length);
|
|
276
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
} from "../lib/formal-budget-provider-scope.js";
|
|
5
5
|
import { isFormalBudgetError } from "../lib/formal-budget-errors.js";
|
|
6
6
|
import { normalizeOllamaBaseUrl } from "../lib/ollama-base-url.js";
|
|
7
|
+
import { ollamaProviderFetch } from "../lib/ollama-provider-fetch.js";
|
|
7
8
|
import {
|
|
8
9
|
normalizeProviderBaseUrl,
|
|
9
10
|
openAICompatibleBaseUrl,
|
|
@@ -56,6 +57,13 @@ import { ReadFileLoopGuard } from "../lib/read-file-loop-guard.js";
|
|
|
56
57
|
const READ_FILE_REQUEST_CONTEXT = Symbol("read-file-request-context");
|
|
57
58
|
import { gitToolInputError } from "../lib/git-tool-input.js";
|
|
58
59
|
import { shellOutputPage, shellOutputPreview } from "../lib/shell-output.js";
|
|
60
|
+
import {
|
|
61
|
+
boundedToolResultText,
|
|
62
|
+
boundedCommandOutput,
|
|
63
|
+
safeHostToolResultForModel,
|
|
64
|
+
registerHostToolOutput,
|
|
65
|
+
copyHostToolOutputIdentity,
|
|
66
|
+
} from "../lib/tool-result-preview.js";
|
|
59
67
|
import { DIAGNOSTIC_WORKFLOW_GUIDANCE } from "../lib/diagnostic-workflow.js";
|
|
60
68
|
import { CODING_TASK_QUALITY_GUIDANCE } from "../lib/coding-task-guidance.js";
|
|
61
69
|
import { RemoteReadLoopGuard } from "../lib/remote-read-loop-guard.js";
|
|
@@ -5741,7 +5749,12 @@ async function executeToolInner(
|
|
|
5741
5749
|
const descriptorPayload = buildPayload(runtimeDescriptor);
|
|
5742
5750
|
const attachDescriptor = (payload, overrideDescriptor = null) => {
|
|
5743
5751
|
const descriptor = buildPayload(overrideDescriptor || runtimeDescriptor);
|
|
5744
|
-
return descriptor
|
|
5752
|
+
return descriptor
|
|
5753
|
+
? copyHostToolOutputIdentity(
|
|
5754
|
+
{ ...payload, toolDescriptor: descriptor },
|
|
5755
|
+
payload,
|
|
5756
|
+
)
|
|
5757
|
+
: payload;
|
|
5745
5758
|
};
|
|
5746
5759
|
const localToolExecutor =
|
|
5747
5760
|
externalToolExecutors && typeof externalToolExecutors === "object"
|
|
@@ -7706,8 +7719,8 @@ async function executeToolInner(
|
|
|
7706
7719
|
) {
|
|
7707
7720
|
return attachDescriptor({
|
|
7708
7721
|
success: true,
|
|
7709
|
-
|
|
7710
|
-
|
|
7722
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7723
|
+
...shellOutputPreview(res.stderr, "stderr", 2000),
|
|
7711
7724
|
exitCode: res.status,
|
|
7712
7725
|
command: normalizedCommand,
|
|
7713
7726
|
readOnly: true,
|
|
@@ -7716,11 +7729,13 @@ async function executeToolInner(
|
|
|
7716
7729
|
});
|
|
7717
7730
|
}
|
|
7718
7731
|
if (res.status !== 0) {
|
|
7719
|
-
const stderr = String(res.stderr || "")
|
|
7732
|
+
const stderr = String(res.stderr || "");
|
|
7720
7733
|
return attachDescriptor({
|
|
7721
|
-
error:
|
|
7722
|
-
|
|
7723
|
-
|
|
7734
|
+
error:
|
|
7735
|
+
boundedCommandOutput(stderr, 2000) ||
|
|
7736
|
+
`git exited with code ${res.status}`,
|
|
7737
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7738
|
+
...shellOutputPreview(stderr, "stderr", 2000),
|
|
7724
7739
|
exitCode: res.status,
|
|
7725
7740
|
command: normalizedCommand,
|
|
7726
7741
|
readOnly,
|
|
@@ -7734,7 +7749,7 @@ async function executeToolInner(
|
|
|
7734
7749
|
});
|
|
7735
7750
|
}
|
|
7736
7751
|
return attachDescriptor({
|
|
7737
|
-
|
|
7752
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7738
7753
|
exitCode: 0,
|
|
7739
7754
|
command: normalizedCommand,
|
|
7740
7755
|
readOnly,
|
|
@@ -10332,8 +10347,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10332
10347
|
outcome: "disabled",
|
|
10333
10348
|
});
|
|
10334
10349
|
return {
|
|
10335
|
-
error: (stderr || message
|
|
10336
|
-
stderr: stderr
|
|
10350
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10351
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10337
10352
|
exitCode: err.status ?? null,
|
|
10338
10353
|
language: lang,
|
|
10339
10354
|
...classified,
|
|
@@ -10349,8 +10364,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10349
10364
|
outcome: "blocked",
|
|
10350
10365
|
});
|
|
10351
10366
|
return {
|
|
10352
|
-
error: (stderr || message
|
|
10353
|
-
stderr: stderr
|
|
10367
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10368
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10354
10369
|
exitCode: err.status ?? null,
|
|
10355
10370
|
language: lang,
|
|
10356
10371
|
...classified,
|
|
@@ -10405,8 +10420,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10405
10420
|
),
|
|
10406
10421
|
);
|
|
10407
10422
|
return {
|
|
10408
|
-
error: (stderr || message
|
|
10409
|
-
stderr: stderr
|
|
10423
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10424
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10410
10425
|
exitCode: err.status ?? null,
|
|
10411
10426
|
language: lang,
|
|
10412
10427
|
...classified,
|
|
@@ -10462,14 +10477,13 @@ async function _executeRunCode(args, cwd) {
|
|
|
10462
10477
|
);
|
|
10463
10478
|
const retryDuration = Date.now() - retryStart;
|
|
10464
10479
|
|
|
10465
|
-
return {
|
|
10480
|
+
return Object.assign(boundedCodeOutput(retryOutput), {
|
|
10466
10481
|
success: true,
|
|
10467
|
-
...boundedCodeOutput(retryOutput),
|
|
10468
10482
|
language: lang,
|
|
10469
10483
|
duration: `${retryDuration}ms`,
|
|
10470
10484
|
autoInstalled: [packageName],
|
|
10471
10485
|
...(persist ? { scriptPath } : {}),
|
|
10472
|
-
};
|
|
10486
|
+
});
|
|
10473
10487
|
} catch (retryErr) {
|
|
10474
10488
|
rethrowRunCodeSandboxFailure(retryErr);
|
|
10475
10489
|
const retryStderr = (retryErr.stderr || "").toString();
|
|
@@ -10481,8 +10495,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10481
10495
|
lang,
|
|
10482
10496
|
);
|
|
10483
10497
|
return {
|
|
10484
|
-
error: (retryStderr || retryMessage
|
|
10485
|
-
stderr: retryStderr
|
|
10498
|
+
error: boundedCommandOutput(retryStderr || retryMessage, 5000),
|
|
10499
|
+
stderr: boundedCommandOutput(retryStderr, 5000),
|
|
10486
10500
|
exitCode: retryErr.status ?? null,
|
|
10487
10501
|
language: lang,
|
|
10488
10502
|
...retryClassified,
|
|
@@ -10495,8 +10509,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10495
10509
|
}
|
|
10496
10510
|
|
|
10497
10511
|
return {
|
|
10498
|
-
error: (stderr || message
|
|
10499
|
-
stderr: stderr
|
|
10512
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10513
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10500
10514
|
exitCode: err.status ?? null,
|
|
10501
10515
|
language: lang,
|
|
10502
10516
|
...classified,
|
|
@@ -10505,13 +10519,12 @@ async function _executeRunCode(args, cwd) {
|
|
|
10505
10519
|
}
|
|
10506
10520
|
|
|
10507
10521
|
const duration = Date.now() - start;
|
|
10508
|
-
return {
|
|
10522
|
+
return Object.assign(boundedCodeOutput(output), {
|
|
10509
10523
|
success: true,
|
|
10510
|
-
...boundedCodeOutput(output),
|
|
10511
10524
|
language: lang,
|
|
10512
10525
|
duration: `${duration}ms`,
|
|
10513
10526
|
...(persist ? { scriptPath } : {}),
|
|
10514
|
-
};
|
|
10527
|
+
});
|
|
10515
10528
|
} finally {
|
|
10516
10529
|
// Only clean up if not persisting
|
|
10517
10530
|
if (!persist) {
|
|
@@ -10546,14 +10559,9 @@ export const MAX_SUB_AGENT_DEPTH = 5;
|
|
|
10546
10559
|
export const MAX_SUB_AGENTS_PER_RUN = 32;
|
|
10547
10560
|
|
|
10548
10561
|
/**
|
|
10549
|
-
*
|
|
10550
|
-
*
|
|
10551
|
-
*
|
|
10552
|
-
* `substring(0, 5000)` that sliced mid-content with no marker and undercut even
|
|
10553
|
-
* read_file's own 50k self-limit. Tools that self-limit (read_file, notebook
|
|
10554
|
-
* render) stay below this; it is the final safety net for the ones that don't
|
|
10555
|
-
* (run_shell, search_files, run_code, MCP). CC_MAX_TOOL_RESULT_CHARS may only
|
|
10556
|
-
* tighten the host ceiling; it cannot raise or disable it.
|
|
10562
|
+
* Total character cap fed back to the model, including truncation metadata.
|
|
10563
|
+
* Complete JSON previews retain status and small fields while omitting large
|
|
10564
|
+
* leaves. CC_MAX_TOOL_RESULT_CHARS may only tighten the host ceiling.
|
|
10557
10565
|
*/
|
|
10558
10566
|
export const MAX_TOOL_RESULT_CHARS_HARD_LIMIT = 50000;
|
|
10559
10567
|
|
|
@@ -10569,47 +10577,38 @@ export const MAX_TOOL_RESULT_CHARS = resolveMaxToolResultChars(
|
|
|
10569
10577
|
);
|
|
10570
10578
|
|
|
10571
10579
|
/**
|
|
10572
|
-
* Cap a serialized tool result
|
|
10573
|
-
*
|
|
10574
|
-
* so the model never silently receives a mid-content slice. Pure; exported for
|
|
10575
|
-
* tests.
|
|
10580
|
+
* Cap a serialized tool result without splitting JSON values. Plain prefixes
|
|
10581
|
+
* are allowed only when they cannot contain a truncated structured span.
|
|
10576
10582
|
*/
|
|
10577
10583
|
export function capToolResultString(serialized, max = MAX_TOOL_RESULT_CHARS) {
|
|
10578
10584
|
const s = String(serialized ?? "");
|
|
10579
10585
|
const effectiveMax = resolveMaxToolResultChars(max);
|
|
10580
|
-
|
|
10581
|
-
return (
|
|
10582
|
-
s.slice(0, effectiveMax) +
|
|
10583
|
-
`\n…[tool output truncated: showing the first ${effectiveMax} of ${s.length} chars` +
|
|
10584
|
-
` — narrow the request (read a line range, grep, or paginate) to see the rest]`
|
|
10585
|
-
);
|
|
10586
|
+
return boundedToolResultText(s, effectiveMax);
|
|
10586
10587
|
}
|
|
10587
10588
|
|
|
10588
10589
|
/** Leave room for JSON escaping and execution metadata, including the hint. */
|
|
10589
10590
|
export function boundedCodeOutput(value) {
|
|
10590
10591
|
const output = String(value ?? "");
|
|
10591
10592
|
const budget = Math.max(0, MAX_TOOL_RESULT_CHARS - 4096);
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
|
|
10602
|
-
|
|
10603
|
-
|
|
10604
|
-
returnedChars: low,
|
|
10605
|
-
hint: "Only an output prefix is shown. Do not rerun the same full-file print: filter/count locally and print a bounded summary with source line numbers, or use read_file with offset/limit for a missing section. This prefix is not evidence of the entire file.",
|
|
10606
|
-
output: output.slice(0, low),
|
|
10607
|
-
};
|
|
10593
|
+
if (JSON.stringify(output).length <= budget) return { output };
|
|
10594
|
+
const preview = boundedCommandOutput(output, Math.max(1, budget));
|
|
10595
|
+
return registerHostToolOutput(
|
|
10596
|
+
{
|
|
10597
|
+
truncated: true,
|
|
10598
|
+
outputChars: output.length,
|
|
10599
|
+
returnedChars: preview.length,
|
|
10600
|
+
hint: "Output is incomplete. Do not rerun the same full-file print: filter/count locally and print a bounded summary with source line numbers, or use read_file with offset/limit for a missing section. Omitted text is not evidence of the entire file.",
|
|
10601
|
+
output: preview,
|
|
10602
|
+
},
|
|
10603
|
+
output,
|
|
10604
|
+
);
|
|
10608
10605
|
}
|
|
10609
10606
|
|
|
10610
10607
|
/** Avoid injecting the same file page twice while its original is still visible. */
|
|
10611
10608
|
export function toolResultForModel(tool, result, messages) {
|
|
10612
|
-
const serialized = capToolResultString(
|
|
10609
|
+
const serialized = capToolResultString(
|
|
10610
|
+
safeStringifyToolResult(safeHostToolResultForModel(tool, result)),
|
|
10611
|
+
);
|
|
10613
10612
|
if (
|
|
10614
10613
|
(tool === "run_code" || tool === "run_shell") &&
|
|
10615
10614
|
!result?.error &&
|
|
@@ -12215,7 +12214,7 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12215
12214
|
},
|
|
12216
12215
|
);
|
|
12217
12216
|
}
|
|
12218
|
-
const response = await
|
|
12217
|
+
const response = await ollamaProviderFetch(apiUrl, {
|
|
12219
12218
|
method: "POST",
|
|
12220
12219
|
headers: { "Content-Type": "application/json" },
|
|
12221
12220
|
signal,
|
|
@@ -12624,7 +12623,12 @@ export async function chatWithTools(rawMessages, options) {
|
|
|
12624
12623
|
throw new TypeError("Invalid API response: unsupported assistant message");
|
|
12625
12624
|
}
|
|
12626
12625
|
// Provider reasoning text is not part of the governed replay protocol.
|
|
12627
|
-
|
|
12626
|
+
// Tool-only responses may omit content. Keep the live message JSON-safe for
|
|
12627
|
+
// canonical tool-round settlement instead of introducing an undefined field.
|
|
12628
|
+
const message = {
|
|
12629
|
+
role: "assistant",
|
|
12630
|
+
content: providerMessage.content ?? null,
|
|
12631
|
+
};
|
|
12628
12632
|
if (Object.hasOwn(providerMessage, "tool_calls")) {
|
|
12629
12633
|
message.tool_calls = providerMessage.tool_calls;
|
|
12630
12634
|
}
|
|
@@ -13055,7 +13059,7 @@ async function _chatOllamaStreaming(
|
|
|
13055
13059
|
stallMs,
|
|
13056
13060
|
stallTimeoutMs,
|
|
13057
13061
|
) {
|
|
13058
|
-
const response = await
|
|
13062
|
+
const response = await ollamaProviderFetch(apiUrl, {
|
|
13059
13063
|
method: "POST",
|
|
13060
13064
|
headers: { "Content-Type": "application/json" },
|
|
13061
13065
|
signal,
|
|
@@ -15284,38 +15288,53 @@ export async function* agentLoop(messages, options) {
|
|
|
15284
15288
|
typeof options.runtimeResultRetention === "object"
|
|
15285
15289
|
? options.runtimeResultRetention
|
|
15286
15290
|
: options.runtimeResultRetentionOptions;
|
|
15287
|
-
const
|
|
15291
|
+
const candidate = releaseOldLiveSessionResults(messages, retentionConfig);
|
|
15288
15292
|
if (
|
|
15289
|
-
|
|
15290
|
-
!_sameMessageSnapshot(
|
|
15293
|
+
candidate.stats.released > 0 &&
|
|
15294
|
+
!_sameMessageSnapshot(candidate.messages, messages)
|
|
15291
15295
|
) {
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
|
|
15295
|
-
|
|
15296
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15296
|
+
// Complete tool effects must be durable before a retention checkpoint
|
|
15297
|
+
// can compare against them. Let a host settlement failure propagate
|
|
15298
|
+
// before another provider call, just as semantic compaction does.
|
|
15299
|
+
options.onBeforeCompaction?.();
|
|
15300
|
+
// The host hook may update live context. Derive both the candidate and
|
|
15301
|
+
// the expected snapshots from the state after that boundary.
|
|
15302
|
+
const retained = releaseOldLiveSessionResults(
|
|
15303
|
+
messages,
|
|
15304
|
+
retentionConfig,
|
|
15305
|
+
);
|
|
15306
|
+
if (
|
|
15307
|
+
retained.stats.released > 0 &&
|
|
15308
|
+
!_sameMessageSnapshot(retained.messages, messages)
|
|
15309
|
+
) {
|
|
15310
|
+
const authorityExpectedMessages = [...messages];
|
|
15311
|
+
const liveExpectedMessages = [...messages];
|
|
15312
|
+
try {
|
|
15313
|
+
await _settleAutomaticCompaction({
|
|
15314
|
+
messages,
|
|
15315
|
+
liveExpectedMessages,
|
|
15316
|
+
authorityExpectedMessages,
|
|
15317
|
+
compacted: retained.messages,
|
|
15318
|
+
stats: retained.stats,
|
|
15319
|
+
options,
|
|
15320
|
+
trigger: "runtime-retention",
|
|
15321
|
+
});
|
|
15322
|
+
yield {
|
|
15323
|
+
type: "session-runtime-retention",
|
|
15324
|
+
runId,
|
|
15325
|
+
stats: retained.stats,
|
|
15326
|
+
};
|
|
15327
|
+
} catch (error) {
|
|
15328
|
+
yield {
|
|
15329
|
+
type: "session-runtime-retention-degraded",
|
|
15330
|
+
runId,
|
|
15331
|
+
reason:
|
|
15332
|
+
error?.code === "SESSION_REVISION_STALE"
|
|
15333
|
+
? "session_messages_changed_during_retention"
|
|
15334
|
+
: "canonical_retention_settlement_failed",
|
|
15335
|
+
code: error?.code || "CC_SESSION_RETENTION_SETTLEMENT_FAILED",
|
|
15336
|
+
};
|
|
15337
|
+
}
|
|
15319
15338
|
}
|
|
15320
15339
|
}
|
|
15321
15340
|
}
|