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.
Files changed (180) hide show
  1. package/README.md +20 -4
  2. package/package.json +3 -3
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-BsoSoDNb.js → AIOps-C9tSCImB.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-Dcx7Gm5t.js → ActionButton-CXKExmT_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-S1hsBIz3.js → Analytics-DE8WBWHo.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-B2j067qM.js → AppLayout-BdpwNM08.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-D5iGV9ic.js → Artifacts-94TQpe38.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-C8ChVvXu.js → Audit-DdDEv5Ej.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-Cg97AAJS.js → BackgroundAgents-TU9nlV7j.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CyxU9IUg.js → Backup-C0GPoUUq.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-CKlWjA8I.js → BaseInput-iyrVn2I6.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-C-EqZza6.js → Chat-Dqo8spwp.js} +5 -5
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BRFiXKPX.js → ChatBubbleRenderer-CDqHSzc4.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-kkI13tSJ.js → Checkbox-BF_XJvQi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-NlqEDwHK.js → Codegen-5tUWoOa9.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-CfepEu79.js → Col-BQxSeRvG.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-BRo0qLXM.js → Community-B2Ra7w-J.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-BMu8TP0E.js → Compact-GjxJwlr0.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-B7Q3Moef.js → Compliance-BTUP6RTA.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-BVwt7Xmc.js → Cowork-DiwfL16s.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-CgBv20Qy.js → Cron-1ceOo5ux.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-CwcSBJk2.js → Crosschain-aHYxLu0u.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-d20rCiIm.js → DID-eeTjzOLV.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-PpZaUYpS.js → Dashboard-CT3fpkvX.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-DjsLdX_Z.js → Dropdown-B3UpOy-N.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-CaPkrtxn.js → EmailListRenderer-Ba2Rvoru.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-DDY8cQnE.js → EvolutionSettings-CGtn93on.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-VQavMjyj.js → FamilyGuardDashboard-C0IUdHQt.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D0GvKQgI.js → Federation-1QIDwemn.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-Dl_TWHmb.js → FormItemContext-NGbSsdje.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-Bny2uagG.js → GenericCardRenderer-DzVZc2Ba.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-B01KXq47.js → Git-B_1TDbSr.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-F4c4Vwo1.js → Governance-BDl_ySyI.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-_025Q-8K.js → Inference-CAp-wcCK.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-DwbTmQb1.js → KnowledgeGraph-DRjRcxul.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-CnNo0hCm.js → Logs-qSuwMwk7.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-BgnYTegK.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-Dkz5bv7F.js → Marketplace-DfiXL6UO.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-CBtRwDW_.js → McpTools-D9rIvFjN.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-Y9jnyTb7.js → Memory-D-p7yDzj.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-Br1urkOz.js → MobileBridge-D0XT5B6m.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-DnsyuerX.js → MobileProjects-CL9cHVIk.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-he3ZzieF.js → Mtc-CME4kDmC.js} +4 -4
  46. package/src/assets/web-panel/assets/{MtcAudit-BadphAuN.js → MtcAudit-BjGOXFnn.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-3_pVLymK.js → Multisig-CSzc53e0.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-DmtmHfsI.js → NLProgramming-BYjZnaH8.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-CE4L2O55.js → Notes-BUPOYE0C.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-B7QmfJn9.js → NotificationSettings-BK8YADru.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-O0wRSyJ0.js → OrderTableRenderer-B5F8bnWt.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-BrlMSsyT.js → Organization-B0WNlhMd.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-CY4ULPrZ.js → Overflow-CED6ZO87.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-kIANZYKd.js → P2P-CBdc8fkP.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DEgB4rvF.js → PdhVaultBrowser-DuauYi03.js} +5 -5
  56. package/src/assets/web-panel/assets/{Permissions-CWxywRp5.js → Permissions-kfgY0ukN.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-DAg7iCbr.js → PersonalDataHub-CDY3I1Do.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-Brc6ONnR.js → Pipeline-B9x0wKSK.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-CcinYTL8.js → Privacy-Cqhcr_Qv.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-Bz8XEsom.js → ProjectInit-CFhoyo57.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CsOMlSTZ.js → ProjectSettings-DCBjV2Hm.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-C51w0LnM.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-CeunOQiH.js → Providers-BuCIWZY1.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-CN2a2_Fb.js → QrScannerModal-CEXNL5CB.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-CVeLif3e.js → QuickAsk-DgK8aLAU.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-1k9WOEGM.js → Recommend-BxEYQRAs.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-Q8UCqIMw.js → RemoteSession-PRsxNsYU.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-CkrCgXKM.js → Reputation-S-tQH70r.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-JFdvuTzi.js → Row-U1Ws3CJl.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-C74JHCmk.js → RssFeed-BftCyeii.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-DrJiVO1T.js → Search-o4gK0cPy.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-BJzNlSJq.js → Security-U2ZRpsbA.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-D4TLMnJm.js → Services-D0tRjWl_.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-cswTDqhh.js → Skeleton-DzZ8TFsB.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-Bv0rM1BS.js → Skills-B1cC7rju.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-D9rE7hNh.js → Sla-CtIHOR0J.js} +1 -1
  77. package/src/assets/web-panel/assets/SpeechSettings-CD8ZlQpW.js +1 -0
  78. package/src/assets/web-panel/assets/{SyncSettings-BwnMG8kq.js → SyncSettings-BilFQWQk.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-wJvU24cB.js → Tasks-Bmg2qLXl.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-CZbRU3tN.js → Templates-D6yofyC1.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-_jbpFJPZ.js → Tenant-BzttD-Gp.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-BzNm5WKZ.js → Terminal-DyRXeYuH.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-bmybWjuS.js → TimelineRenderer-Bdmkx-Tr.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-o1WDcqVQ.js → Tokens-10RcVAVJ.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-BB1D6sIB.js → Trigger-CKV-9DdV.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-CLxdCfy2.js → Trust-BEc-sW1q.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-B9LS6vS0.js → UkeySign-BSql8piX.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-Bg0-wxjz.js → VideoEditing-C4OH2f4s.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-Bw0G2F6P.js → Wallet-BSSvWKmv.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-irEiNY9b.js → WebAuthn-LxIzXo9d.js} +5 -5
  91. package/src/assets/web-panel/assets/{WorkflowEditor-Bh08FbJs.js → WorkflowEditor-DWwdfcte.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-De-FPjVT.js → chat-DWxYYLD5.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-ygdyvinU.js → colors-BxEcQqtg.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-BQ9jH9KV.js → compact-item-DNbezFOJ.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BFuVSyox.js → createContext-DaJXc5nx.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-CRyXoGo9.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-i19GtR1P.js → hasIn-BMrw3sg3.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-IXkif6J_.js → index-2c0bL3SE.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-cDJsyAkI.js → index-6W0V5G2t.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-B2LieObB.js → index-7zzLqfvI.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BGMxK155.js → index-B9b6UaZl.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DVnFgasM.js → index-BAV07GDK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BBYiCI1d.js → index-BCCd8Rj6.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-m8waSAyv.js → index-BNZDGV2q.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-CpdXhhMY.js → index-BR4nWOmR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-C61w3omz.js → index-B_b9_6wQ.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DlwxUZQL.js → index-BaByEdBj.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Cq9k4-Ws.js → index-BcuytRTa.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BPUCvc8i.js → index-Bs2QyMPQ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DgjLaB7k.js → index-Bum_aSyd.js} +1 -1
  111. package/src/assets/web-panel/assets/index-C-W0Ntk_.js +1 -0
  112. package/src/assets/web-panel/assets/{index-BaaydJcC.js → index-C25ig6EV.js} +1 -1
  113. package/src/assets/web-panel/assets/index-CCk_qhBx.js +1 -0
  114. package/src/assets/web-panel/assets/{index-_9tUBcLm.js → index-CL-36X3A.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BLMtCKAY.js → index-Ca2hwPMo.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CMNjaSir.js → index-CaxzeSIM.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CgoSgmjK.js → index-CiEdfbB9.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DuuOX5u3.js → index-Cm9DYzhC.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-We2nK3ju.js → index-CpwgF7vh.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CWfgeaG4.js → index-DEvdSKT4.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-4HoFz1MA.js → index-DL0k35f0.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-CXrk8OYO.js → index-DarVV5yG.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DS1IwwGL.js → index-DpSp97J8.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BVhtukYX.js → index-Dr18agDl.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-28DjsABm.js → index-Dwg38xTG.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-B1IsP_JO.js → index-DzZHBzCb.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DL7ewjD2.js → index-IX0g0s2t.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Bw5pTpnI.js → index-LRb0QX6S.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-l5-J0jHx.js → index-NEW5EN2w.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BKlU5VZy.js → index-T4T84G6X.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BKblSCL9.js → index-VD-dTYQE.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-Bhf-MuUh.js → index-cCqCEa9X.js} +3 -3
  133. package/src/assets/web-panel/assets/{index-vXtH3o6O.js → index-cKBpcInt.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-DAboGZTw.js → index-hPy_f08G.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DTY20pWu.js → index-pzYLf5qu.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-CBVcGaxk.js → index-rFaCnjXi.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-B_EZHeqN.js → initDefaultProps-BWVLgWhF.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BrVb_Gy1.js → motion-KJZ1xfDE.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-CKxVRL_J.js → move-DGqU6H7M.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-C80rvQ1J.js → mtc-parser-Dg0xkI5J.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-De5vD7BR.js → omit-B6RnMJAQ.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BTyEDjth.js → pickAttrs-Ctw2i3jb.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BWR94AjR.js → placementArrow-D3F3x8Jm.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-1g-Vnibk.js → responsiveObserve-W6eHE0nM.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-Dmg6dYuF.js → slide-BlFf8sY5.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-Ddj6rSab.js → statusUtils-Cd6LMwmy.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DyP1mPDf.js → styleChecker-Bg5-U4Y1.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-D3d_0YuY.js → useFlexGapSupport-DTkLS3tn.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-M3vq-gE2.js → useFs-CwYGzoBt.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-GtP2TgtK.js → usePersonalDataHub-PCgFQXZP.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BurE2ATQ.js → vnode-CJM7MkrB.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-Ch-ViiDe.js → zoom-CP0mgaFi.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/commands/compact.js +7 -2
  155. package/src/data/changelog.json +14 -1
  156. package/src/harness/jsonl-session-store.js +78 -73
  157. package/src/harness/prompt-compressor.js +57 -3
  158. package/src/lib/context-memory-kernel/context-image-transport.js +248 -0
  159. package/src/lib/context-memory-kernel/jsonl-session-context-port.js +4 -1
  160. package/src/lib/context-memory-kernel/live-compaction.js +40 -10
  161. package/src/lib/context-memory-kernel/message-adapter.js +80 -10
  162. package/src/lib/context-memory-kernel/message-bundle-store.js +1140 -0
  163. package/src/lib/context-memory-kernel/provider-context.js +23 -8
  164. package/src/lib/evolution/agent-evolution-ingress.js +62 -12
  165. package/src/lib/evolution/agent-model-projection.js +90 -18
  166. package/src/lib/evolution/evidence-json-text.js +279 -42
  167. package/src/lib/evolution/evolution-evidence-projector.js +121 -16
  168. package/src/lib/image-token-estimate.js +59 -0
  169. package/src/lib/read-file-loop-guard.js +7 -4
  170. package/src/lib/session-history-origins.js +25 -5
  171. package/src/lib/session-transcript-history.js +5 -1
  172. package/src/lib/tool-result-preview.js +276 -0
  173. package/src/runtime/agent-core.js +57 -59
  174. package/src/runtime/headless-stream.js +32 -17
  175. package/src/assets/web-panel/assets/MarkdownRenderer-D8_iZief.js +0 -1
  176. package/src/assets/web-panel/assets/Projects-BeSOM6wi.js +0 -1
  177. package/src/assets/web-panel/assets/SpeechSettings-Bfhvin8B.js +0 -1
  178. package/src/assets/web-panel/assets/devWarning-c2I2Rn4_.js +0 -1
  179. package/src/assets/web-panel/assets/index-CTs4dYcV.js +0 -1
  180. package/src/assets/web-panel/assets/index-DeuvaW15.js +0 -1
@@ -11,6 +11,11 @@ import {
11
11
  memoryRecordsToContextItems,
12
12
  messagesToContextItems,
13
13
  } from "./message-adapter.js";
14
+ import {
15
+ adjustContextImageTokenEstimates,
16
+ captureContextImageTransport,
17
+ restoreContextImageTransport,
18
+ } from "./context-image-transport.js";
14
19
 
15
20
  export const SEMANTIC_CANDIDATE_REQUEST_SCHEMA =
16
21
  "chainlesschain.context-memory-semantic-candidate-request/v1";
@@ -217,12 +222,17 @@ export async function prepareCanonicalProviderContext(
217
222
  ),
218
223
  ...(semanticCandidates === undefined ? {} : { semanticCandidates }),
219
224
  });
220
- const messageItems = messagesToContextItems(messages, {
221
- sessionId,
222
- allowedSinks: [sink],
223
- trustCurrentSystemPolicy: true,
224
- trustedSystemIndexes: options.contextMemoryTrustedSystemIndexes,
225
- });
225
+ const imageTransport = captureContextImageTransport(messages);
226
+ const messageItems = adjustContextImageTokenEstimates(
227
+ messagesToContextItems(imageTransport.messages, {
228
+ sessionId,
229
+ allowedSinks: [sink],
230
+ trustCurrentSystemPolicy: true,
231
+ trustedSystemIndexes: options.contextMemoryTrustedSystemIndexes,
232
+ allowExternalization: false,
233
+ }),
234
+ imageTransport.captures,
235
+ );
226
236
  const memoryItems = memoryRecordsToContextItems(
227
237
  recall.results.map((entry) => entry.record),
228
238
  { insertionSequence: Math.max(0, messages.length - 1) },
@@ -290,9 +300,14 @@ export async function prepareCanonicalProviderContext(
290
300
  sessionHead,
291
301
  memoryRevision: recall.memoryRevision,
292
302
  });
303
+ const selectedMessages = contextItemsToMessages(
304
+ plan.selected.filter((item) => item.kind !== "tool-schema"),
305
+ { sessionId },
306
+ );
293
307
  return {
294
- messages: contextItemsToMessages(
295
- plan.selected.filter((item) => item.kind !== "tool-schema"),
308
+ messages: restoreContextImageTransport(
309
+ selectedMessages,
310
+ imageTransport.captures,
296
311
  ),
297
312
  selectedToolNames: toolItems
298
313
  .filter((item) => plan.selectedItemIds.includes(item.itemId))
@@ -15,6 +15,7 @@ import { captureEvolutionReleaseTrain } from "./evolution-release-train.js";
15
15
  import {
16
16
  snapshotAgentModelRequest,
17
17
  buildAgentModelRequest,
18
+ projectAgentOpaqueTransportBlock,
18
19
  } from "./agent-model-projection.js";
19
20
  import {
20
21
  snapshotSkillDecisionRequest,
@@ -28,8 +29,7 @@ export const AGENT_EVOLUTION_INGRESS_SCHEMA =
28
29
  export const AGENT_EVOLUTION_INGRESS_FAILED_CODE =
29
30
  "CC_AGENT_EVOLUTION_INGRESS_FAILED";
30
31
 
31
- const RESPONSE_CACHE_RECORD_SCHEMA =
32
- "chainlesschain.model-response-cache/v2";
32
+ const RESPONSE_CACHE_RECORD_SCHEMA = "chainlesschain.model-response-cache/v2";
33
33
  const LEGACY_RESPONSE_CACHE_RECORD_SCHEMA =
34
34
  "chainlesschain.model-response-cache/v1";
35
35
  const RESPONSE_CACHE_IDENTIFIER_BINDING_SCHEMA =
@@ -294,8 +294,7 @@ export function createAgentEvolutionIngress({
294
294
  const payload = cacheRecord
295
295
  ? {
296
296
  schema: RESPONSE_CACHE_RECORD_SCHEMA,
297
- identifierBindingSchema:
298
- RESPONSE_CACHE_IDENTIFIER_BINDING_SCHEMA,
297
+ identifierBindingSchema: RESPONSE_CACHE_IDENTIFIER_BINDING_SCHEMA,
299
298
  requestKeyBinding: cacheIdentifierBinding(
300
299
  "request key",
301
300
  evidence.requestKey,
@@ -537,12 +536,11 @@ export function createAgentEvolutionIngress({
537
536
  throw new Error(
538
537
  "Cache response projection is not safe or request-bound",
539
538
  );
540
- const responseEvent = loaded.events.find(
541
- (item) =>
542
- legacyRecord
543
- ? item.eventId === record.sourceEventId
544
- : cacheIdentifierBinding("source event ID", item.eventId) ===
545
- record.sourceEventIdBinding,
539
+ const responseEvent = loaded.events.find((item) =>
540
+ legacyRecord
541
+ ? item.eventId === record.sourceEventId
542
+ : cacheIdentifierBinding("source event ID", item.eventId) ===
543
+ record.sourceEventIdBinding,
546
544
  );
547
545
  if (
548
546
  responseEvent?.data?.evidenceKind !== "response-completed" ||
@@ -589,8 +587,60 @@ export function createAgentEvolutionIngress({
589
587
  }
590
588
  return ingest("model-input", snapshot, {}, snapshot);
591
589
  },
592
- ingestUserPrompt: async (input, options) =>
593
- ingest("user-prompt", { input: cloneEvidence(input) }, options),
590
+ ingestUserPrompt: async (input, options) => {
591
+ const snapshot = cloneEvidence(input);
592
+ try {
593
+ if (
594
+ Array.isArray(snapshot?.messages) &&
595
+ typeof snapshot.source === "string"
596
+ ) {
597
+ const captured = snapshotAgentModelRequest({
598
+ messages: snapshot.messages,
599
+ tools: [],
600
+ });
601
+ // User-prompt is a small event, not a second image transport. Bind
602
+ // each image to its complete original block; model-input admission
603
+ // separately retains the original image in encrypted Raw evidence.
604
+ snapshot.messages = captured.messages.map(
605
+ (message, messageIndex) => ({
606
+ ...message,
607
+ ...(Array.isArray(message.content)
608
+ ? {
609
+ content: message.content.map((block, blockIndex) =>
610
+ block.type === "image_url"
611
+ ? projectAgentOpaqueTransportBlock(
612
+ block,
613
+ `messages.${messageIndex}.content.${blockIndex}`,
614
+ )
615
+ : block,
616
+ ),
617
+ }
618
+ : {}),
619
+ }),
620
+ );
621
+ } else if (Array.isArray(snapshot?.content)) {
622
+ const captured = snapshotAgentModelRequest({
623
+ messages: [{ role: "user", content: snapshot.content }],
624
+ tools: [],
625
+ });
626
+ // REPL callers pass the current user content directly, without a
627
+ // source label or a messages wrapper. Apply the same image binding.
628
+ snapshot.content = captured.messages[0].content.map(
629
+ (block, blockIndex) =>
630
+ block.type === "image_url"
631
+ ? projectAgentOpaqueTransportBlock(
632
+ block,
633
+ `messages.0.content.${blockIndex}`,
634
+ )
635
+ : block,
636
+ );
637
+ }
638
+ } catch (error) {
639
+ admissionFailure ??= ingressFailure(error);
640
+ throw admissionFailure;
641
+ }
642
+ return ingest("user-prompt", { input: snapshot }, options);
643
+ },
594
644
  ingestAgentEvent: async (event, options) => {
595
645
  if (admissionFailure !== null) throw admissionFailure;
596
646
  let type;
@@ -1,9 +1,26 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { types } from "node:util";
3
3
  import { isAgentToolArgumentsPath } from "./evidence-json-text.js";
4
+ import {
5
+ MAX_INPUT_IMAGES,
6
+ MAX_INPUT_IMAGE_BYTES,
7
+ } from "../image-file-boundary.js";
4
8
 
5
- const MAX_NODES = 32_768;
6
- const MAX_BYTES = 1024 * 1024;
9
+ export const AGENT_MODEL_REQUEST_LIMITS = Object.freeze({
10
+ maxNodes: 32_768,
11
+ maxBytes: 1024 * 1024,
12
+ maxDepth: 24,
13
+ });
14
+ export const AGENT_MODEL_IMAGE_LIMITS = Object.freeze({
15
+ maxImageBytes: MAX_INPUT_IMAGE_BYTES,
16
+ maxMessageImageBytes: MAX_INPUT_IMAGE_BYTES,
17
+ maxMessageImages: MAX_INPUT_IMAGES,
18
+ maxRequestImageBytes: 40 * 1024 * 1024,
19
+ // Includes bounded base64 expansion, the text allocation and URL headers.
20
+ maxCanonicalRequestBytes: 56 * 1024 * 1024,
21
+ });
22
+ const MAX_NODES = AGENT_MODEL_REQUEST_LIMITS.maxNodes;
23
+ const MAX_BYTES = AGENT_MODEL_REQUEST_LIMITS.maxBytes;
7
24
  const MESSAGE_KEYS = new Set([
8
25
  "role",
9
26
  "content",
@@ -59,6 +76,32 @@ function blockDigest(value) {
59
76
  .digest("hex")}`;
60
77
  }
61
78
 
79
+ function imageDataUrlBudget(url) {
80
+ if (
81
+ typeof url !== "string" ||
82
+ url.length > Math.ceil(AGENT_MODEL_IMAGE_LIMITS.maxImageBytes / 3) * 4 + 128
83
+ )
84
+ throw new TypeError(
85
+ `Agent image exceeds its ${AGENT_MODEL_IMAGE_LIMITS.maxImageBytes / 1024 / 1024} MiB image byte budget`,
86
+ );
87
+ const match = /^data:([^;,]+);base64,([A-Za-z0-9+/]*={0,2})$/u.exec(url);
88
+ if (!match || !IMAGE_MEDIA_TYPES.has(match[1]) || match[2].length % 4 !== 0)
89
+ throw new TypeError(
90
+ "Agent image block requires a supported base64 data URL",
91
+ );
92
+ const decodedBytes =
93
+ (match[2].length / 4) * 3 -
94
+ (match[2].endsWith("==") ? 2 : match[2].endsWith("=") ? 1 : 0);
95
+ if (decodedBytes > AGENT_MODEL_IMAGE_LIMITS.maxImageBytes)
96
+ throw new TypeError(
97
+ `Agent image exceeds its ${AGENT_MODEL_IMAGE_LIMITS.maxImageBytes / 1024 / 1024} MiB image byte budget`,
98
+ );
99
+ const decoded = Buffer.from(match[2], "base64");
100
+ if (!decoded.length || decoded.toString("base64") !== match[2])
101
+ throw new TypeError("Agent image block contains non-canonical base64");
102
+ return { decodedBytes, encodedBytes: match[2].length };
103
+ }
104
+
62
105
  function imageBlock(value) {
63
106
  if (!exactKeys(value, new Set(["type", "image_url"]))) return null;
64
107
  const imageKeys = new Set(
@@ -74,18 +117,7 @@ function imageBlock(value) {
74
117
  ) {
75
118
  throw new TypeError("Agent image block has an unsupported protocol shape");
76
119
  }
77
- const match = /^data:([^;,]+);base64,([A-Za-z0-9+/]*={0,2})$/u.exec(
78
- value.image_url.url,
79
- );
80
- if (!match || !IMAGE_MEDIA_TYPES.has(match[1]) || match[2].length % 4 !== 0) {
81
- throw new TypeError(
82
- "Agent image block requires a supported base64 data URL",
83
- );
84
- }
85
- const decoded = Buffer.from(match[2], "base64");
86
- if (!decoded.length || decoded.toString("base64") !== match[2]) {
87
- throw new TypeError("Agent image block contains non-canonical base64");
88
- }
120
+ imageDataUrlBudget(value.image_url.url);
89
121
  return value;
90
122
  }
91
123
 
@@ -319,18 +351,54 @@ export function snapshotAgentModelRequest(
319
351
  ) {
320
352
  let nodes = 0;
321
353
  let bytes = 0;
354
+ let imageBytes = 0;
355
+ let encodedImageBytes = 0;
356
+ const messageImageBudgets = new Map();
322
357
  const seen = new Set();
323
358
  const visit = (entry, depth, path = "") => {
324
- if (++nodes > MAX_NODES || depth > 24) {
359
+ if (++nodes > MAX_NODES || depth > AGENT_MODEL_REQUEST_LIMITS.maxDepth) {
325
360
  throw new TypeError("Agent model request exceeds the input budget");
326
361
  }
327
362
  if (typeof entry === "string") {
328
- if (entry.length > 8192 && !textPath(path, allowStructuredArgumentText)) {
363
+ const imageUrl = /^messages\.\d+\.content\.\d+\.image_url\.url$/u.test(
364
+ path,
365
+ );
366
+ let imageBudget = null;
367
+ if (imageUrl) {
368
+ imageBudget = imageDataUrlBudget(entry);
369
+ const messageIndex = path.split(".")[1];
370
+ const messageBudget = messageImageBudgets.get(messageIndex) ?? {
371
+ bytes: 0,
372
+ count: 0,
373
+ };
374
+ messageBudget.bytes += imageBudget.decodedBytes;
375
+ messageBudget.count++;
376
+ messageImageBudgets.set(messageIndex, messageBudget);
377
+ if (
378
+ messageBudget.bytes > AGENT_MODEL_IMAGE_LIMITS.maxMessageImageBytes ||
379
+ messageBudget.count > AGENT_MODEL_IMAGE_LIMITS.maxMessageImages
380
+ )
381
+ throw new TypeError(
382
+ `Agent images exceed the per-message image budget (${AGENT_MODEL_IMAGE_LIMITS.maxMessageImages} images / ${AGENT_MODEL_IMAGE_LIMITS.maxMessageImageBytes / 1024 / 1024} MiB)`,
383
+ );
384
+ imageBytes += imageBudget.decodedBytes;
385
+ encodedImageBytes += imageBudget.encodedBytes;
386
+ if (imageBytes > AGENT_MODEL_IMAGE_LIMITS.maxRequestImageBytes)
387
+ throw new TypeError(
388
+ `Agent images exceed the ${AGENT_MODEL_IMAGE_LIMITS.maxRequestImageBytes / 1024 / 1024} MiB request image byte budget`,
389
+ );
390
+ }
391
+ if (
392
+ entry.length > 8192 &&
393
+ !imageUrl &&
394
+ !textPath(path, allowStructuredArgumentText)
395
+ ) {
329
396
  throw new TypeError(
330
397
  "Agent model protocol metadata exceeds the text budget",
331
398
  );
332
399
  }
333
- bytes += Buffer.byteLength(entry, "utf8");
400
+ bytes +=
401
+ Buffer.byteLength(entry, "utf8") - (imageBudget?.encodedBytes ?? 0);
334
402
  if (bytes > MAX_BYTES)
335
403
  throw new TypeError("Agent model request is too large");
336
404
  return entry;
@@ -405,7 +473,11 @@ export function snapshotAgentModelRequest(
405
473
  );
406
474
  // Include escaping, punctuation and numeric values in the transport/storage
407
475
  // budget, not just string values. Whole fields are never split or truncated.
408
- if (Buffer.byteLength(JSON.stringify(request), "utf8") > MAX_BYTES) {
476
+ const canonicalBytes = Buffer.byteLength(JSON.stringify(request), "utf8");
477
+ if (
478
+ canonicalBytes - encodedImageBytes > MAX_BYTES ||
479
+ canonicalBytes > AGENT_MODEL_IMAGE_LIMITS.maxCanonicalRequestBytes
480
+ ) {
409
481
  throw new TypeError("Agent model request is too large");
410
482
  }
411
483
  return request;