chainlesschain 0.166.115 → 0.166.117
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 +20 -4
- package/package.json +3 -3
- 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-BsoSoDNb.js → AIOps-C9tSCImB.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Dcx7Gm5t.js → ActionButton-CXKExmT_.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-S1hsBIz3.js → Analytics-DE8WBWHo.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B2j067qM.js → AppLayout-BdpwNM08.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D5iGV9ic.js → Artifacts-94TQpe38.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-C8ChVvXu.js → Audit-DdDEv5Ej.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Cg97AAJS.js → BackgroundAgents-TU9nlV7j.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CyxU9IUg.js → Backup-C0GPoUUq.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CKlWjA8I.js → BaseInput-iyrVn2I6.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-C-EqZza6.js → Chat-Dqo8spwp.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BRFiXKPX.js → ChatBubbleRenderer-CDqHSzc4.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-kkI13tSJ.js → Checkbox-BF_XJvQi.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-NlqEDwHK.js → Codegen-5tUWoOa9.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CfepEu79.js → Col-BQxSeRvG.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BRo0qLXM.js → Community-B2Ra7w-J.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BMu8TP0E.js → Compact-GjxJwlr0.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B7Q3Moef.js → Compliance-BTUP6RTA.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BVwt7Xmc.js → Cowork-DiwfL16s.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CgBv20Qy.js → Cron-1ceOo5ux.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CwcSBJk2.js → Crosschain-aHYxLu0u.js} +1 -1
- package/src/assets/web-panel/assets/{DID-d20rCiIm.js → DID-eeTjzOLV.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-PpZaUYpS.js → Dashboard-CT3fpkvX.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DjsLdX_Z.js → Dropdown-B3UpOy-N.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CaPkrtxn.js → EmailListRenderer-Ba2Rvoru.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DDY8cQnE.js → EvolutionSettings-CGtn93on.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-VQavMjyj.js → FamilyGuardDashboard-C0IUdHQt.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0GvKQgI.js → Federation-1QIDwemn.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dl_TWHmb.js → FormItemContext-NGbSsdje.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bny2uagG.js → GenericCardRenderer-DzVZc2Ba.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B01KXq47.js → Git-B_1TDbSr.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-F4c4Vwo1.js → Governance-BDl_ySyI.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-_025Q-8K.js → Inference-CAp-wcCK.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DwbTmQb1.js → KnowledgeGraph-DRjRcxul.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CnNo0hCm.js → Logs-qSuwMwk7.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-BgnYTegK.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Dkz5bv7F.js → Marketplace-DfiXL6UO.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CBtRwDW_.js → McpTools-D9rIvFjN.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-Y9jnyTb7.js → Memory-D-p7yDzj.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Br1urkOz.js → MobileBridge-D0XT5B6m.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DnsyuerX.js → MobileProjects-CL9cHVIk.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-he3ZzieF.js → Mtc-CME4kDmC.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-BadphAuN.js → MtcAudit-BjGOXFnn.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-3_pVLymK.js → Multisig-CSzc53e0.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DmtmHfsI.js → NLProgramming-BYjZnaH8.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CE4L2O55.js → Notes-BUPOYE0C.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-B7QmfJn9.js → NotificationSettings-BK8YADru.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-O0wRSyJ0.js → OrderTableRenderer-B5F8bnWt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BrlMSsyT.js → Organization-B0WNlhMd.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CY4ULPrZ.js → Overflow-CED6ZO87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-kIANZYKd.js → P2P-CBdc8fkP.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DEgB4rvF.js → PdhVaultBrowser-DuauYi03.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-CWxywRp5.js → Permissions-kfgY0ukN.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DAg7iCbr.js → PersonalDataHub-CDY3I1Do.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Brc6ONnR.js → Pipeline-B9x0wKSK.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CcinYTL8.js → Privacy-Cqhcr_Qv.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Bz8XEsom.js → ProjectInit-CFhoyo57.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CsOMlSTZ.js → ProjectSettings-DCBjV2Hm.js} +2 -2
- package/src/assets/web-panel/assets/Projects-C51w0LnM.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CeunOQiH.js → Providers-BuCIWZY1.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CN2a2_Fb.js → QrScannerModal-CEXNL5CB.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CVeLif3e.js → QuickAsk-DgK8aLAU.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-1k9WOEGM.js → Recommend-BxEYQRAs.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Q8UCqIMw.js → RemoteSession-PRsxNsYU.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CkrCgXKM.js → Reputation-S-tQH70r.js} +1 -1
- package/src/assets/web-panel/assets/{Row-JFdvuTzi.js → Row-U1Ws3CJl.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C74JHCmk.js → RssFeed-BftCyeii.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DrJiVO1T.js → Search-o4gK0cPy.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BJzNlSJq.js → Security-U2ZRpsbA.js} +3 -3
- package/src/assets/web-panel/assets/{Services-D4TLMnJm.js → Services-D0tRjWl_.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-cswTDqhh.js → Skeleton-DzZ8TFsB.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Bv0rM1BS.js → Skills-B1cC7rju.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-D9rE7hNh.js → Sla-CtIHOR0J.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-CD8ZlQpW.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-BwnMG8kq.js → SyncSettings-BilFQWQk.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-wJvU24cB.js → Tasks-Bmg2qLXl.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CZbRU3tN.js → Templates-D6yofyC1.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-_jbpFJPZ.js → Tenant-BzttD-Gp.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BzNm5WKZ.js → Terminal-DyRXeYuH.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-bmybWjuS.js → TimelineRenderer-Bdmkx-Tr.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-o1WDcqVQ.js → Tokens-10RcVAVJ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BB1D6sIB.js → Trigger-CKV-9DdV.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CLxdCfy2.js → Trust-BEc-sW1q.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B9LS6vS0.js → UkeySign-BSql8piX.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bg0-wxjz.js → VideoEditing-C4OH2f4s.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Bw0G2F6P.js → Wallet-BSSvWKmv.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-irEiNY9b.js → WebAuthn-LxIzXo9d.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Bh08FbJs.js → WorkflowEditor-DWwdfcte.js} +1 -1
- package/src/assets/web-panel/assets/{chat-De-FPjVT.js → chat-DWxYYLD5.js} +1 -1
- package/src/assets/web-panel/assets/{colors-ygdyvinU.js → colors-BxEcQqtg.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BQ9jH9KV.js → compact-item-DNbezFOJ.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BFuVSyox.js → createContext-DaJXc5nx.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CRyXoGo9.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i19GtR1P.js → hasIn-BMrw3sg3.js} +1 -1
- package/src/assets/web-panel/assets/{index-IXkif6J_.js → index-2c0bL3SE.js} +1 -1
- package/src/assets/web-panel/assets/{index-cDJsyAkI.js → index-6W0V5G2t.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2LieObB.js → index-7zzLqfvI.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGMxK155.js → index-B9b6UaZl.js} +1 -1
- package/src/assets/web-panel/assets/{index-DVnFgasM.js → index-BAV07GDK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBYiCI1d.js → index-BCCd8Rj6.js} +1 -1
- package/src/assets/web-panel/assets/{index-m8waSAyv.js → index-BNZDGV2q.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpdXhhMY.js → index-BR4nWOmR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C61w3omz.js → index-B_b9_6wQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlwxUZQL.js → index-BaByEdBj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cq9k4-Ws.js → index-BcuytRTa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPUCvc8i.js → index-Bs2QyMPQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgjLaB7k.js → index-Bum_aSyd.js} +1 -1
- package/src/assets/web-panel/assets/index-C-W0Ntk_.js +1 -0
- package/src/assets/web-panel/assets/{index-BaaydJcC.js → index-C25ig6EV.js} +1 -1
- package/src/assets/web-panel/assets/index-CCk_qhBx.js +1 -0
- package/src/assets/web-panel/assets/{index-_9tUBcLm.js → index-CL-36X3A.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLMtCKAY.js → index-Ca2hwPMo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMNjaSir.js → index-CaxzeSIM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgoSgmjK.js → index-CiEdfbB9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuuOX5u3.js → index-Cm9DYzhC.js} +1 -1
- package/src/assets/web-panel/assets/{index-We2nK3ju.js → index-CpwgF7vh.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWfgeaG4.js → index-DEvdSKT4.js} +1 -1
- package/src/assets/web-panel/assets/{index-4HoFz1MA.js → index-DL0k35f0.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXrk8OYO.js → index-DarVV5yG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DS1IwwGL.js → index-DpSp97J8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVhtukYX.js → index-Dr18agDl.js} +1 -1
- package/src/assets/web-panel/assets/{index-28DjsABm.js → index-Dwg38xTG.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1IsP_JO.js → index-DzZHBzCb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DL7ewjD2.js → index-IX0g0s2t.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bw5pTpnI.js → index-LRb0QX6S.js} +1 -1
- package/src/assets/web-panel/assets/{index-l5-J0jHx.js → index-NEW5EN2w.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKlU5VZy.js → index-T4T84G6X.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKblSCL9.js → index-VD-dTYQE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bhf-MuUh.js → index-cCqCEa9X.js} +3 -3
- package/src/assets/web-panel/assets/{index-vXtH3o6O.js → index-cKBpcInt.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAboGZTw.js → index-hPy_f08G.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTY20pWu.js → index-pzYLf5qu.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBVcGaxk.js → index-rFaCnjXi.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B_EZHeqN.js → initDefaultProps-BWVLgWhF.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BrVb_Gy1.js → motion-KJZ1xfDE.js} +1 -1
- package/src/assets/web-panel/assets/{move-CKxVRL_J.js → move-DGqU6H7M.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C80rvQ1J.js → mtc-parser-Dg0xkI5J.js} +1 -1
- package/src/assets/web-panel/assets/{omit-De5vD7BR.js → omit-B6RnMJAQ.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BTyEDjth.js → pickAttrs-Ctw2i3jb.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BWR94AjR.js → placementArrow-D3F3x8Jm.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-1g-Vnibk.js → responsiveObserve-W6eHE0nM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dmg6dYuF.js → slide-BlFf8sY5.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Ddj6rSab.js → statusUtils-Cd6LMwmy.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DyP1mPDf.js → styleChecker-Bg5-U4Y1.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D3d_0YuY.js → useFlexGapSupport-DTkLS3tn.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-M3vq-gE2.js → useFs-CwYGzoBt.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-GtP2TgtK.js → usePersonalDataHub-PCgFQXZP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BurE2ATQ.js → vnode-CJM7MkrB.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Ch-ViiDe.js → zoom-CP0mgaFi.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/compact.js +7 -2
- package/src/data/changelog.json +14 -1
- package/src/harness/jsonl-session-store.js +78 -73
- package/src/harness/prompt-compressor.js +57 -3
- 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 +62 -12
- package/src/lib/evolution/agent-model-projection.js +90 -18
- package/src/lib/evolution/evidence-json-text.js +279 -42
- package/src/lib/evolution/evolution-evidence-projector.js +121 -16
- package/src/lib/image-token-estimate.js +59 -0
- package/src/lib/read-file-loop-guard.js +7 -4
- package/src/lib/session-history-origins.js +25 -5
- package/src/lib/session-transcript-history.js +5 -1
- package/src/lib/tool-result-preview.js +276 -0
- package/src/runtime/agent-core.js +57 -59
- package/src/runtime/headless-stream.js +32 -17
- 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
|
@@ -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
|
+
}
|
|
@@ -56,6 +56,13 @@ import { ReadFileLoopGuard } from "../lib/read-file-loop-guard.js";
|
|
|
56
56
|
const READ_FILE_REQUEST_CONTEXT = Symbol("read-file-request-context");
|
|
57
57
|
import { gitToolInputError } from "../lib/git-tool-input.js";
|
|
58
58
|
import { shellOutputPage, shellOutputPreview } from "../lib/shell-output.js";
|
|
59
|
+
import {
|
|
60
|
+
boundedToolResultText,
|
|
61
|
+
boundedCommandOutput,
|
|
62
|
+
safeHostToolResultForModel,
|
|
63
|
+
registerHostToolOutput,
|
|
64
|
+
copyHostToolOutputIdentity,
|
|
65
|
+
} from "../lib/tool-result-preview.js";
|
|
59
66
|
import { DIAGNOSTIC_WORKFLOW_GUIDANCE } from "../lib/diagnostic-workflow.js";
|
|
60
67
|
import { CODING_TASK_QUALITY_GUIDANCE } from "../lib/coding-task-guidance.js";
|
|
61
68
|
import { RemoteReadLoopGuard } from "../lib/remote-read-loop-guard.js";
|
|
@@ -5741,7 +5748,12 @@ async function executeToolInner(
|
|
|
5741
5748
|
const descriptorPayload = buildPayload(runtimeDescriptor);
|
|
5742
5749
|
const attachDescriptor = (payload, overrideDescriptor = null) => {
|
|
5743
5750
|
const descriptor = buildPayload(overrideDescriptor || runtimeDescriptor);
|
|
5744
|
-
return descriptor
|
|
5751
|
+
return descriptor
|
|
5752
|
+
? copyHostToolOutputIdentity(
|
|
5753
|
+
{ ...payload, toolDescriptor: descriptor },
|
|
5754
|
+
payload,
|
|
5755
|
+
)
|
|
5756
|
+
: payload;
|
|
5745
5757
|
};
|
|
5746
5758
|
const localToolExecutor =
|
|
5747
5759
|
externalToolExecutors && typeof externalToolExecutors === "object"
|
|
@@ -7706,8 +7718,8 @@ async function executeToolInner(
|
|
|
7706
7718
|
) {
|
|
7707
7719
|
return attachDescriptor({
|
|
7708
7720
|
success: true,
|
|
7709
|
-
|
|
7710
|
-
|
|
7721
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7722
|
+
...shellOutputPreview(res.stderr, "stderr", 2000),
|
|
7711
7723
|
exitCode: res.status,
|
|
7712
7724
|
command: normalizedCommand,
|
|
7713
7725
|
readOnly: true,
|
|
@@ -7716,11 +7728,13 @@ async function executeToolInner(
|
|
|
7716
7728
|
});
|
|
7717
7729
|
}
|
|
7718
7730
|
if (res.status !== 0) {
|
|
7719
|
-
const stderr = String(res.stderr || "")
|
|
7731
|
+
const stderr = String(res.stderr || "");
|
|
7720
7732
|
return attachDescriptor({
|
|
7721
|
-
error:
|
|
7722
|
-
|
|
7723
|
-
|
|
7733
|
+
error:
|
|
7734
|
+
boundedCommandOutput(stderr, 2000) ||
|
|
7735
|
+
`git exited with code ${res.status}`,
|
|
7736
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7737
|
+
...shellOutputPreview(stderr, "stderr", 2000),
|
|
7724
7738
|
exitCode: res.status,
|
|
7725
7739
|
command: normalizedCommand,
|
|
7726
7740
|
readOnly,
|
|
@@ -7734,7 +7748,7 @@ async function executeToolInner(
|
|
|
7734
7748
|
});
|
|
7735
7749
|
}
|
|
7736
7750
|
return attachDescriptor({
|
|
7737
|
-
|
|
7751
|
+
...shellOutputPreview(res.stdout, "stdout", 30000),
|
|
7738
7752
|
exitCode: 0,
|
|
7739
7753
|
command: normalizedCommand,
|
|
7740
7754
|
readOnly,
|
|
@@ -10332,8 +10346,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10332
10346
|
outcome: "disabled",
|
|
10333
10347
|
});
|
|
10334
10348
|
return {
|
|
10335
|
-
error: (stderr || message
|
|
10336
|
-
stderr: stderr
|
|
10349
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10350
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10337
10351
|
exitCode: err.status ?? null,
|
|
10338
10352
|
language: lang,
|
|
10339
10353
|
...classified,
|
|
@@ -10349,8 +10363,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10349
10363
|
outcome: "blocked",
|
|
10350
10364
|
});
|
|
10351
10365
|
return {
|
|
10352
|
-
error: (stderr || message
|
|
10353
|
-
stderr: stderr
|
|
10366
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10367
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10354
10368
|
exitCode: err.status ?? null,
|
|
10355
10369
|
language: lang,
|
|
10356
10370
|
...classified,
|
|
@@ -10405,8 +10419,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10405
10419
|
),
|
|
10406
10420
|
);
|
|
10407
10421
|
return {
|
|
10408
|
-
error: (stderr || message
|
|
10409
|
-
stderr: stderr
|
|
10422
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10423
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10410
10424
|
exitCode: err.status ?? null,
|
|
10411
10425
|
language: lang,
|
|
10412
10426
|
...classified,
|
|
@@ -10462,14 +10476,13 @@ async function _executeRunCode(args, cwd) {
|
|
|
10462
10476
|
);
|
|
10463
10477
|
const retryDuration = Date.now() - retryStart;
|
|
10464
10478
|
|
|
10465
|
-
return {
|
|
10479
|
+
return Object.assign(boundedCodeOutput(retryOutput), {
|
|
10466
10480
|
success: true,
|
|
10467
|
-
...boundedCodeOutput(retryOutput),
|
|
10468
10481
|
language: lang,
|
|
10469
10482
|
duration: `${retryDuration}ms`,
|
|
10470
10483
|
autoInstalled: [packageName],
|
|
10471
10484
|
...(persist ? { scriptPath } : {}),
|
|
10472
|
-
};
|
|
10485
|
+
});
|
|
10473
10486
|
} catch (retryErr) {
|
|
10474
10487
|
rethrowRunCodeSandboxFailure(retryErr);
|
|
10475
10488
|
const retryStderr = (retryErr.stderr || "").toString();
|
|
@@ -10481,8 +10494,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10481
10494
|
lang,
|
|
10482
10495
|
);
|
|
10483
10496
|
return {
|
|
10484
|
-
error: (retryStderr || retryMessage
|
|
10485
|
-
stderr: retryStderr
|
|
10497
|
+
error: boundedCommandOutput(retryStderr || retryMessage, 5000),
|
|
10498
|
+
stderr: boundedCommandOutput(retryStderr, 5000),
|
|
10486
10499
|
exitCode: retryErr.status ?? null,
|
|
10487
10500
|
language: lang,
|
|
10488
10501
|
...retryClassified,
|
|
@@ -10495,8 +10508,8 @@ async function _executeRunCode(args, cwd) {
|
|
|
10495
10508
|
}
|
|
10496
10509
|
|
|
10497
10510
|
return {
|
|
10498
|
-
error: (stderr || message
|
|
10499
|
-
stderr: stderr
|
|
10511
|
+
error: boundedCommandOutput(stderr || message, 5000),
|
|
10512
|
+
stderr: boundedCommandOutput(stderr, 5000),
|
|
10500
10513
|
exitCode: err.status ?? null,
|
|
10501
10514
|
language: lang,
|
|
10502
10515
|
...classified,
|
|
@@ -10505,13 +10518,12 @@ async function _executeRunCode(args, cwd) {
|
|
|
10505
10518
|
}
|
|
10506
10519
|
|
|
10507
10520
|
const duration = Date.now() - start;
|
|
10508
|
-
return {
|
|
10521
|
+
return Object.assign(boundedCodeOutput(output), {
|
|
10509
10522
|
success: true,
|
|
10510
|
-
...boundedCodeOutput(output),
|
|
10511
10523
|
language: lang,
|
|
10512
10524
|
duration: `${duration}ms`,
|
|
10513
10525
|
...(persist ? { scriptPath } : {}),
|
|
10514
|
-
};
|
|
10526
|
+
});
|
|
10515
10527
|
} finally {
|
|
10516
10528
|
// Only clean up if not persisting
|
|
10517
10529
|
if (!persist) {
|
|
@@ -10546,14 +10558,9 @@ export const MAX_SUB_AGENT_DEPTH = 5;
|
|
|
10546
10558
|
export const MAX_SUB_AGENTS_PER_RUN = 32;
|
|
10547
10559
|
|
|
10548
10560
|
/**
|
|
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.
|
|
10561
|
+
* Total character cap fed back to the model, including truncation metadata.
|
|
10562
|
+
* Complete JSON previews retain status and small fields while omitting large
|
|
10563
|
+
* leaves. CC_MAX_TOOL_RESULT_CHARS may only tighten the host ceiling.
|
|
10557
10564
|
*/
|
|
10558
10565
|
export const MAX_TOOL_RESULT_CHARS_HARD_LIMIT = 50000;
|
|
10559
10566
|
|
|
@@ -10569,47 +10576,38 @@ export const MAX_TOOL_RESULT_CHARS = resolveMaxToolResultChars(
|
|
|
10569
10576
|
);
|
|
10570
10577
|
|
|
10571
10578
|
/**
|
|
10572
|
-
* Cap a serialized tool result
|
|
10573
|
-
*
|
|
10574
|
-
* so the model never silently receives a mid-content slice. Pure; exported for
|
|
10575
|
-
* tests.
|
|
10579
|
+
* Cap a serialized tool result without splitting JSON values. Plain prefixes
|
|
10580
|
+
* are allowed only when they cannot contain a truncated structured span.
|
|
10576
10581
|
*/
|
|
10577
10582
|
export function capToolResultString(serialized, max = MAX_TOOL_RESULT_CHARS) {
|
|
10578
10583
|
const s = String(serialized ?? "");
|
|
10579
10584
|
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
|
-
);
|
|
10585
|
+
return boundedToolResultText(s, effectiveMax);
|
|
10586
10586
|
}
|
|
10587
10587
|
|
|
10588
10588
|
/** Leave room for JSON escaping and execution metadata, including the hint. */
|
|
10589
10589
|
export function boundedCodeOutput(value) {
|
|
10590
10590
|
const output = String(value ?? "");
|
|
10591
10591
|
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
|
-
};
|
|
10592
|
+
if (JSON.stringify(output).length <= budget) return { output };
|
|
10593
|
+
const preview = boundedCommandOutput(output, Math.max(1, budget));
|
|
10594
|
+
return registerHostToolOutput(
|
|
10595
|
+
{
|
|
10596
|
+
truncated: true,
|
|
10597
|
+
outputChars: output.length,
|
|
10598
|
+
returnedChars: preview.length,
|
|
10599
|
+
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.",
|
|
10600
|
+
output: preview,
|
|
10601
|
+
},
|
|
10602
|
+
output,
|
|
10603
|
+
);
|
|
10608
10604
|
}
|
|
10609
10605
|
|
|
10610
10606
|
/** Avoid injecting the same file page twice while its original is still visible. */
|
|
10611
10607
|
export function toolResultForModel(tool, result, messages) {
|
|
10612
|
-
const serialized = capToolResultString(
|
|
10608
|
+
const serialized = capToolResultString(
|
|
10609
|
+
safeStringifyToolResult(safeHostToolResultForModel(tool, result)),
|
|
10610
|
+
);
|
|
10613
10611
|
if (
|
|
10614
10612
|
(tool === "run_code" || tool === "run_shell") &&
|
|
10615
10613
|
!result?.error &&
|
|
@@ -3826,6 +3826,21 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
3826
3826
|
return false;
|
|
3827
3827
|
}
|
|
3828
3828
|
};
|
|
3829
|
+
const repairAndSettleToolRoundsForHost = (phase) => {
|
|
3830
|
+
const originalMessages = new Set(messages);
|
|
3831
|
+
const balanced = sanitizeToolPairs(messages);
|
|
3832
|
+
for (const message of balanced) {
|
|
3833
|
+
if (
|
|
3834
|
+
!originalMessages.has(message) &&
|
|
3835
|
+
message.role === "assistant" &&
|
|
3836
|
+
!message.tool_calls?.length
|
|
3837
|
+
)
|
|
3838
|
+
markRuntimeOnlySessionMessage(message);
|
|
3839
|
+
}
|
|
3840
|
+
messages.length = 0;
|
|
3841
|
+
messages.push(...balanced);
|
|
3842
|
+
return settleToolRoundsForHost(phase);
|
|
3843
|
+
};
|
|
3829
3844
|
const loopOptionsBase = {
|
|
3830
3845
|
...(evolutionIngress === null ? {} : { evolutionIngress }),
|
|
3831
3846
|
model,
|
|
@@ -5637,6 +5652,12 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5637
5652
|
const turnWasAborted = currentAbort?.signal.aborted === true;
|
|
5638
5653
|
currentAbort = null;
|
|
5639
5654
|
if (err?.code === AGENT_EVOLUTION_INGRESS_FAILED_CODE) {
|
|
5655
|
+
evolutionIngressFailed = true;
|
|
5656
|
+
// Ingress can reject the next model request after a tool round has
|
|
5657
|
+
// already completed. Keep those completed effects in the canonical
|
|
5658
|
+
// session before terminating this Run; incomplete calls are removed
|
|
5659
|
+
// with the same pairing repair used for an interrupted turn.
|
|
5660
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5640
5661
|
emit({
|
|
5641
5662
|
type: "result",
|
|
5642
5663
|
subtype: "error_evolution_ingress",
|
|
@@ -5646,7 +5667,6 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5646
5667
|
turn: turns,
|
|
5647
5668
|
});
|
|
5648
5669
|
sawError = true;
|
|
5649
|
-
evolutionIngressFailed = true;
|
|
5650
5670
|
break;
|
|
5651
5671
|
}
|
|
5652
5672
|
if (persist) {
|
|
@@ -5677,6 +5697,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5677
5697
|
break;
|
|
5678
5698
|
}
|
|
5679
5699
|
if (err?.runtimeLedgerPersistence === true) {
|
|
5700
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5680
5701
|
emit({
|
|
5681
5702
|
type: "result",
|
|
5682
5703
|
subtype: "error_persistence",
|
|
@@ -5693,6 +5714,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5693
5714
|
err?.code === "CC_SESSION_BUDGET_USAGE_UNKNOWN" ||
|
|
5694
5715
|
options.sessionBudget?.signal?.aborted === true
|
|
5695
5716
|
) {
|
|
5717
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5696
5718
|
const budgetReason =
|
|
5697
5719
|
options.sessionBudget?.reason?.() ||
|
|
5698
5720
|
err.budgetReason ||
|
|
@@ -5729,21 +5751,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5729
5751
|
// the array length unchanged. sanitizeToolPairs is idempotent on an
|
|
5730
5752
|
// already-balanced array and leaves user/text turns untouched, so the
|
|
5731
5753
|
// intentional dangling-user state above is preserved.
|
|
5732
|
-
|
|
5733
|
-
const balanced = sanitizeToolPairs(messages);
|
|
5734
|
-
// Only the sanitizer's newly-created commentary for discarded calls
|
|
5735
|
-
// is ephemeral. Existing real messages retain their authority.
|
|
5736
|
-
for (const message of balanced) {
|
|
5737
|
-
if (
|
|
5738
|
-
!originalMessages.has(message) &&
|
|
5739
|
-
message.role === "assistant" &&
|
|
5740
|
-
!message.tool_calls?.length
|
|
5741
|
-
)
|
|
5742
|
-
markRuntimeOnlySessionMessage(message);
|
|
5743
|
-
}
|
|
5744
|
-
messages.length = 0;
|
|
5745
|
-
messages.push(...balanced);
|
|
5746
|
-
if (!settleToolRoundsForHost("after-model")) break;
|
|
5754
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5747
5755
|
emit({
|
|
5748
5756
|
type: "result",
|
|
5749
5757
|
subtype: "interrupted",
|
|
@@ -5754,7 +5762,12 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5754
5762
|
});
|
|
5755
5763
|
continue;
|
|
5756
5764
|
}
|
|
5757
|
-
if (isAbort)
|
|
5765
|
+
if (isAbort) {
|
|
5766
|
+
// Caller shutdown terminates the stream, but completed tool effects
|
|
5767
|
+
// from the in-flight turn still belong in the durable transcript.
|
|
5768
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5769
|
+
break;
|
|
5770
|
+
}
|
|
5758
5771
|
if (!settleToolRoundsForHost("after-model")) break;
|
|
5759
5772
|
const transportDetails = transportErrorDetails(err);
|
|
5760
5773
|
emit({
|
|
@@ -5771,6 +5784,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5771
5784
|
persistTurnBindingLog();
|
|
5772
5785
|
}
|
|
5773
5786
|
if (turnBindingPersistenceError) {
|
|
5787
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5774
5788
|
emitTurnBindingFailure();
|
|
5775
5789
|
sawError = true;
|
|
5776
5790
|
break;
|
|
@@ -5792,6 +5806,7 @@ async function runAgentHeadlessStreamInWorkspace(
|
|
|
5792
5806
|
}
|
|
5793
5807
|
|
|
5794
5808
|
if (outcome.endReason === "compaction-usage-unknown") {
|
|
5809
|
+
if (!repairAndSettleToolRoundsForHost("after-model")) break;
|
|
5795
5810
|
sawError = true;
|
|
5796
5811
|
emit({
|
|
5797
5812
|
type: "result",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{P as c,J as p,b as a}from"./vendor-Bn1JzzAn.js";import{r as s}from"./markdown-Yo_c6Krv.js";import{_ as d}from"./index-Bhf-MuUh.js";const _={__name:"MarkdownRenderer",props:{content:{type:String,default:""}},setup(t,{expose:o}){o();const e=t,r=a(()=>s(e.content||"")),n={props:e,rendered:r,computed:a,get renderMarkdown(){return s}};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}},i=["innerHTML"];function m(t,o,e,r,n,u){return c(),p("div",{class:"markdown-content",innerHTML:r.rendered},null,8,i)}const w=d(_,[["render",m],["__scopeId","data-v-0b0b9f63"],["__file","/tmp/cc-web-panel-jIIa0G/repo/packages/web-panel/src/components/MarkdownRenderer.vue"]]);export{w as M};
|