chainlesschain 0.166.114 → 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 (183) hide show
  1. package/README.md +23 -3
  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-CVac3rIN.js → AIOps-C9tSCImB.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-ChM9GxMl.js → ActionButton-CXKExmT_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-CV5399Js.js → Analytics-DE8WBWHo.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-CuonVXhg.js → AppLayout-BdpwNM08.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-D9qKfgb6.js → Artifacts-94TQpe38.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-DUvLysQc.js → Audit-DdDEv5Ej.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DfKohQeT.js → BackgroundAgents-TU9nlV7j.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-CohoEI8R.js → Backup-C0GPoUUq.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-BwdoA3xv.js → BaseInput-iyrVn2I6.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-DRkuz1d2.js → Chat-Dqo8spwp.js} +5 -5
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-v3pzeHNC.js → ChatBubbleRenderer-CDqHSzc4.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-B-GNGpKv.js → Checkbox-BF_XJvQi.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-Bs2lAsoZ.js → Codegen-5tUWoOa9.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-Bk1mJKDZ.js → Col-BQxSeRvG.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-B_FDSCOo.js → Community-B2Ra7w-J.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-No1qSLLH.js → Compact-GjxJwlr0.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-CcrG43-d.js → Compliance-BTUP6RTA.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-DLkj2ywK.js → Cowork-DiwfL16s.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-sQHELVEz.js → Cron-1ceOo5ux.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-CRTZ3GZg.js → Crosschain-aHYxLu0u.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-Ds2bjvxE.js → DID-eeTjzOLV.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-DOONG2NX.js → Dashboard-CT3fpkvX.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-Br3PNA2L.js → Dropdown-B3UpOy-N.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-DT6UUqjZ.js → EmailListRenderer-Ba2Rvoru.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-BSLuEjlT.js → EvolutionSettings-CGtn93on.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-2aEM9avE.js → FamilyGuardDashboard-C0IUdHQt.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D3B0tlQU.js → Federation-1QIDwemn.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-DTVkVVQP.js → FormItemContext-NGbSsdje.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-BgFEgP4y.js → GenericCardRenderer-DzVZc2Ba.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-3t71m6Xd.js → Git-B_1TDbSr.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-DS7WvlaX.js → Governance-BDl_ySyI.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-CeT-xWrI.js → Inference-CAp-wcCK.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-BQzMncp5.js → KnowledgeGraph-DRjRcxul.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-CC5DOKhV.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-CpYDyy3o.js → Marketplace-DfiXL6UO.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-DRdAZPMr.js → McpTools-D9rIvFjN.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CBLRr-l8.js → Memory-D-p7yDzj.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-Bnj9veNN.js → MobileBridge-D0XT5B6m.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-lYFPD24p.js → MobileProjects-CL9cHVIk.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-BMU_C9vD.js → Mtc-CME4kDmC.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-DQV-zumU.js → MtcAudit-BjGOXFnn.js} +4 -4
  47. package/src/assets/web-panel/assets/{Multisig-LpqpqV1d.js → Multisig-CSzc53e0.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-C4OMklSO.js → NLProgramming-BYjZnaH8.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-Cg0QCinP.js → Notes-BUPOYE0C.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-amoZoMna.js → NotificationSettings-BK8YADru.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-CxNvhf5n.js → OrderTableRenderer-B5F8bnWt.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-BetJmyX5.js → Organization-B0WNlhMd.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-DbeoPtVD.js → Overflow-CED6ZO87.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-B5sitQWT.js → P2P-CBdc8fkP.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-AP9SG2ic.js → PdhVaultBrowser-DuauYi03.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-Bc7fgNKx.js → Permissions-kfgY0ukN.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BwdGMcWZ.js → PersonalDataHub-CDY3I1Do.js} +3 -3
  58. package/src/assets/web-panel/assets/{Pipeline-DVuJA9BA.js → Pipeline-B9x0wKSK.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-BGzwOYRG.js → Privacy-Cqhcr_Qv.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-BpHcC5br.js → ProjectInit-CFhoyo57.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-BI5G5gsc.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-CRHCcLFS.js → Providers-BuCIWZY1.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-qSeg5xag.js → QrScannerModal-CEXNL5CB.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-CA8oSceR.js → QuickAsk-DgK8aLAU.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-DMvPodNo.js → Recommend-BxEYQRAs.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-BWsapEyN.js → RemoteSession-PRsxNsYU.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-BZJETVmC.js → Reputation-S-tQH70r.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-CUE1OSMp.js → Row-U1Ws3CJl.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DvMazcUD.js → RssFeed-BftCyeii.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-e1c-NXWv.js → Search-o4gK0cPy.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-Dc9GZsx2.js → Security-U2ZRpsbA.js} +3 -3
  73. package/src/assets/web-panel/assets/{Services-AFz6ke-4.js → Services-D0tRjWl_.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-gow6MYcY.js → Skeleton-DzZ8TFsB.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-h6AxYjUP.js → Skills-B1cC7rju.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-Cr4CkJ0O.js → Sla-CtIHOR0J.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-Bd5yuBtH.js → SpeechSettings-CD8ZlQpW.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-1t4QZMLW.js → SyncSettings-BilFQWQk.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-u-DrjLRM.js → Tasks-Bmg2qLXl.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-C0yLUC9b.js → Templates-D6yofyC1.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-ds1YT5iS.js → Tenant-BzttD-Gp.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-BoIskW2m.js → Terminal-DyRXeYuH.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-BkdVK24X.js → TimelineRenderer-Bdmkx-Tr.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-djyDgmfk.js → Tokens-10RcVAVJ.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-CYefDS3H.js → Trigger-CKV-9DdV.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-CE_dbep_.js → Trust-BEc-sW1q.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-DwVs_fey.js → UkeySign-BSql8piX.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-BTUqMHAV.js → VideoEditing-C4OH2f4s.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-Bu_E7Rrc.js → Wallet-BSSvWKmv.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-DTbre5AB.js → WebAuthn-LxIzXo9d.js} +5 -5
  91. package/src/assets/web-panel/assets/{WorkflowEditor-BsBzd3gt.js → WorkflowEditor-DWwdfcte.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-tdifQQvu.js → chat-DWxYYLD5.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-D3SNW2Vx.js → colors-BxEcQqtg.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-UBlCjrAW.js → compact-item-DNbezFOJ.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-DKsnEnFt.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-BkeySXWe.js → hasIn-BMrw3sg3.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CXkn77ZN.js → index-2c0bL3SE.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DtxUSZSS.js → index-6W0V5G2t.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DFMrIEIt.js → index-7zzLqfvI.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-D9m1HQzl.js → index-B9b6UaZl.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-bOIcWW8F.js → index-BAV07GDK.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BV2zQteq.js → index-BCCd8Rj6.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DlO6HdD9.js → index-BNZDGV2q.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DfrW-iVs.js → index-BR4nWOmR.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-PWScrdlX.js → index-B_b9_6wQ.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-SpQ26gD6.js → index-BaByEdBj.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-D5Umd_Z-.js → index-BcuytRTa.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dg8-Duze.js → index-Bs2QyMPQ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DlEIp1gJ.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-D6es7MSG.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-Bw0k3VgD.js → index-CL-36X3A.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DYFjOyTH.js → index-Ca2hwPMo.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BVvz3ntc.js → index-CaxzeSIM.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D9um0YVl.js → index-CiEdfbB9.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DugZRCiI.js → index-Cm9DYzhC.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-pgGKNvmm.js → index-CpwgF7vh.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-P-ailFQY.js → index-DEvdSKT4.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C9ImNw5O.js → index-DL0k35f0.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DSCiZJXb.js → index-DarVV5yG.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BIeFLaMV.js → index-DpSp97J8.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C-KTHSUE.js → index-Dr18agDl.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DiDgwRty.js → index-Dwg38xTG.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D93iSDUw.js → index-DzZHBzCb.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-6Nvzgytx.js → index-IX0g0s2t.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CG_b1xyX.js → index-LRb0QX6S.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-Cuz2QCFT.js → index-NEW5EN2w.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CUjyL0ZS.js → index-T4T84G6X.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DdyTv6yc.js → index-VD-dTYQE.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BEiHKah0.js → index-cCqCEa9X.js} +3 -3
  133. package/src/assets/web-panel/assets/{index-DD6dD3LV.js → index-cKBpcInt.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-TLBpgN30.js → index-hPy_f08G.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-DSe_7MSy.js → index-pzYLf5qu.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-CZ6JUooI.js → index-rFaCnjXi.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-CVCXG2Hv.js → initDefaultProps-BWVLgWhF.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-Dv00jw87.js → motion-KJZ1xfDE.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-BFz51iHf.js → move-DGqU6H7M.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-BK2woIDE.js → mtc-parser-Dg0xkI5J.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-D2X_Gwoo.js → omit-B6RnMJAQ.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-CLmFyJ1q.js → pickAttrs-Ctw2i3jb.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-CCzPddQm.js → placementArrow-D3F3x8Jm.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-hcm_Zlxd.js → responsiveObserve-W6eHE0nM.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-BxfZEFVp.js → slide-BlFf8sY5.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-kzB9pT-t.js → statusUtils-Cd6LMwmy.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-CDFd7YCI.js → styleChecker-Bg5-U4Y1.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-Czl7NNhS.js → useFlexGapSupport-DTkLS3tn.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-y0SAzirG.js → useFs-CwYGzoBt.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BvdPznrA.js → usePersonalDataHub-PCgFQXZP.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-D8mNbyZ7.js → vnode-CJM7MkrB.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-_hun6w9W.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 +28 -2
  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 +169 -26
  168. package/src/lib/evolution/governed-model-turn.js +2 -2
  169. package/src/lib/evolution/local-ui-evolution-deployment.js +2 -2
  170. package/src/lib/evolution/local-ui-evolution-runtime.js +4 -4
  171. package/src/lib/evolution/opaque-hex-id.js +8 -0
  172. package/src/lib/image-token-estimate.js +59 -0
  173. package/src/lib/read-file-loop-guard.js +9 -6
  174. package/src/lib/session-history-origins.js +25 -5
  175. package/src/lib/session-transcript-history.js +5 -1
  176. package/src/lib/tool-result-preview.js +276 -0
  177. package/src/runtime/agent-core.js +85 -78
  178. package/src/runtime/headless-stream.js +32 -17
  179. package/src/assets/web-panel/assets/MarkdownRenderer-5jYM4kYG.js +0 -1
  180. package/src/assets/web-panel/assets/Projects-Ce92-l1V.js +0 -1
  181. package/src/assets/web-panel/assets/devWarning-BBnVfJHh.js +0 -1
  182. package/src/assets/web-panel/assets/index-B2w_3mtS.js +0 -1
  183. package/src/assets/web-panel/assets/index-BoHurydC.js +0 -1
@@ -12,6 +12,22 @@ export const EVIDENCE_JSON_POLICY = Object.freeze({
12
12
  numbers: "finite-safe-integers-pii-to-string",
13
13
  });
14
14
 
15
+ export const AGENT_CODE_TEXT_RESULT_TOOLS = Object.freeze([
16
+ "run_code",
17
+ "read_file",
18
+ "run_shell",
19
+ "check_shell",
20
+ "git",
21
+ "search_files",
22
+ ]);
23
+
24
+ /* eslint-disable no-control-regex -- Quoted literals exclude unescaped control bytes. */
25
+ const JSON_STRING_PREFIX =
26
+ /^"(?:[^"\\\x00-\x1f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/u;
27
+ const CODE_DOUBLE_QUOTED_PREFIX = /^"(?:[^"\\\x00-\x1f]|\\[\s\S])*"/u;
28
+ const CODE_SINGLE_QUOTED_PREFIX = /^'(?:[^'\\\x00-\x1f]|\\[\s\S])*'/u;
29
+ /* eslint-enable no-control-regex */
30
+
15
31
  export function isAgentToolArgumentsPath(path) {
16
32
  return (
17
33
  path.length === 6 &&
@@ -35,15 +51,103 @@ function assignmentKeyBefore(text, start, end) {
35
51
  return keyEnd > index + 1 ? text.slice(index + 1, keyEnd) : undefined;
36
52
  }
37
53
 
38
- export function createEvidenceJsonTextBoundary(fail) {
54
+ export function createEvidenceJsonTextBoundary(
55
+ fail,
56
+ policy = EVIDENCE_JSON_POLICY,
57
+ ) {
39
58
  let nodes = 0;
40
59
  let bytes = 0;
41
- const reject = () => {
42
- throw fail(
43
- "Agent model JSON text is malformed, ambiguous or exceeds its budget",
60
+ const PARSE_FAILURE = Symbol("evidence-json-parse-failure");
61
+ const reject = (
62
+ message = "Agent model JSON text is malformed or ambiguous",
63
+ ) => {
64
+ throw fail(message);
65
+ };
66
+ const rejectParseFailure = (error) => {
67
+ reject(
68
+ error?.[PARSE_FAILURE] === "budget"
69
+ ? "Agent model JSON text exceeds its budget"
70
+ : "Agent model JSON text is malformed or ambiguous",
44
71
  );
45
72
  };
46
- const parser = (text, start) => {
73
+ const parserReject = (kind) => {
74
+ const error = new Error(kind);
75
+ Object.defineProperty(error, PARSE_FAILURE, { value: kind });
76
+ throw error;
77
+ };
78
+ const decodeSourceString = (literal, quote) => {
79
+ let output = "";
80
+ for (let index = 1; index < literal.length - 1; index++) {
81
+ const char = literal[index];
82
+ if (char !== "\\") {
83
+ output += char;
84
+ continue;
85
+ }
86
+ const escaped = literal[++index];
87
+ if (/[0-7]/u.test(escaped ?? "")) {
88
+ const digits = /^[0-7]{1,3}/u.exec(literal.slice(index))[0];
89
+ output += String.fromCodePoint(Number.parseInt(digits, 8));
90
+ index += digits.length - 1;
91
+ continue;
92
+ }
93
+ // Python named Unicode escapes require a Unicode-name database. Refuse
94
+ // them instead of treating an encoded sensitive key/value as plain text.
95
+ if (escaped === "N" && literal[index + 1] === "{")
96
+ return parserReject("syntax");
97
+ const simple = {
98
+ "'": "'",
99
+ '"': '"',
100
+ "\\": "\\",
101
+ b: "\b",
102
+ f: "\f",
103
+ n: "\n",
104
+ r: "\r",
105
+ t: "\t",
106
+ v: "\v",
107
+ 0: "\0",
108
+ };
109
+ if (escaped === quote || Object.hasOwn(simple, escaped)) {
110
+ output += simple[escaped] ?? escaped;
111
+ continue;
112
+ }
113
+ if (escaped === "x" || escaped === "u" || escaped === "U") {
114
+ if (escaped === "u" && literal[index + 1] === "{") {
115
+ const close = literal.indexOf("}", index + 2);
116
+ const digits = close < 0 ? "" : literal.slice(index + 2, close);
117
+ if (/^[0-9a-fA-F]{1,6}$/u.test(digits)) {
118
+ const codePoint = Number.parseInt(digits, 16);
119
+ if (codePoint <= 0x10ffff) {
120
+ output += String.fromCodePoint(codePoint);
121
+ index = close;
122
+ continue;
123
+ }
124
+ }
125
+ }
126
+ const count = escaped === "x" ? 2 : escaped === "u" ? 4 : 8;
127
+ const digits = literal.slice(index + 1, index + 1 + count);
128
+ if (new RegExp(`^[0-9a-fA-F]{${count}}$`, "u").test(digits)) {
129
+ const codePoint = Number.parseInt(digits, 16);
130
+ if (codePoint <= 0x10ffff) {
131
+ output += String.fromCodePoint(codePoint);
132
+ index += count;
133
+ continue;
134
+ }
135
+ }
136
+ output += `\\${escaped}`;
137
+ continue;
138
+ }
139
+ // Keep line continuations and language-specific escapes bounded to the
140
+ // source literal. The decoded value is used only for evidence scanning.
141
+ if (escaped === "\n") continue;
142
+ if (escaped === "\r" && literal[index + 1] === "\n") {
143
+ index++;
144
+ continue;
145
+ }
146
+ output += escaped;
147
+ }
148
+ return output;
149
+ };
150
+ const parser = (text, start, { allowSingleQuotedStrings = false } = {}) => {
47
151
  let index = start;
48
152
  const whitespace = () => {
49
153
  while (/[ \t\r\n]/u.test(text[index] ?? "x")) index++;
@@ -57,21 +161,32 @@ export function createEvidenceJsonTextBoundary(fail) {
57
161
  try {
58
162
  return JSON.parse(text.slice(begin, index));
59
163
  } catch {
60
- return reject();
164
+ if (allowSingleQuotedStrings)
165
+ return decodeSourceString(text.slice(begin, index), '"');
166
+ return parserReject("syntax");
61
167
  }
62
168
  }
63
169
  }
64
- return reject();
170
+ return parserReject("syntax");
171
+ };
172
+ const singleQuotedString = () => {
173
+ const begin = index++;
174
+ while (index < text.length) {
175
+ const char = text[index++];
176
+ if (char === "\\") index++;
177
+ else if (char === "'")
178
+ return decodeSourceString(text.slice(begin, index), "'");
179
+ }
180
+ return parserReject("syntax");
65
181
  };
66
182
  const value = (depth = 0) => {
67
- if (
68
- ++nodes > EVIDENCE_JSON_POLICY.maxNodes ||
69
- depth > EVIDENCE_JSON_POLICY.maxDepth
70
- )
71
- reject();
183
+ if (++nodes > policy.maxNodes || depth > policy.maxDepth)
184
+ parserReject("budget");
72
185
  whitespace();
73
186
  const char = text[index];
74
187
  if (char === '"') return string();
188
+ if (char === "'" && allowSingleQuotedStrings) return singleQuotedString();
189
+ if (char === "'") return parserReject("code-expression");
75
190
  if (char === "{" || char === "[") {
76
191
  const array = char === "[";
77
192
  const end = array ? "]" : "}";
@@ -85,11 +200,19 @@ export function createEvidenceJsonTextBoundary(fail) {
85
200
  while (index < text.length) {
86
201
  let key;
87
202
  if (!array) {
88
- if (text[index] !== '"') reject();
89
- key = string();
90
- if (Object.hasOwn(output, key)) reject();
203
+ if (
204
+ text[index] !== '"' &&
205
+ !(allowSingleQuotedStrings && text[index] === "'")
206
+ )
207
+ parserReject(
208
+ text[index] === "'" || /^[A-Za-z_$]/u.test(text[index] ?? "")
209
+ ? "code-expression"
210
+ : "syntax",
211
+ );
212
+ key = text[index] === "'" ? singleQuotedString() : string();
213
+ if (Object.hasOwn(output, key)) parserReject("ambiguous");
91
214
  whitespace();
92
- if (text[index++] !== ":") reject();
215
+ if (text[index++] !== ":") parserReject("syntax");
93
216
  }
94
217
  const child = value(depth + 1);
95
218
  if (array) output.push(child);
@@ -103,16 +226,34 @@ export function createEvidenceJsonTextBoundary(fail) {
103
226
  index++;
104
227
  return output;
105
228
  }
106
- if (text[index++] !== ",") reject();
229
+ if (text[index] !== ",") {
230
+ // Slices, comprehensions and member/call/arithmetic expressions
231
+ // are source syntax. Missing delimiters and trailing commas stay
232
+ // malformed JSON, including in run_code output.
233
+ parserReject(
234
+ (array && text[index] === ":") ||
235
+ /^[.(+*/?]/u.test(text[index] ?? "") ||
236
+ /^for\b/u.test(text.slice(index))
237
+ ? "code-expression"
238
+ : "syntax",
239
+ );
240
+ }
241
+ index++;
107
242
  whitespace();
108
243
  }
109
- return reject();
244
+ return parserReject("syntax");
110
245
  }
111
246
  const token =
112
247
  /^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/u.exec(
113
248
  text.slice(index),
114
249
  )?.[0];
115
- if (!token) return reject();
250
+ if (!token) {
251
+ return parserReject(
252
+ /^[A-Za-z_$][A-Za-z0-9_$]*|^\(/u.test(text.slice(index))
253
+ ? "code-expression"
254
+ : "syntax",
255
+ );
256
+ }
116
257
  index += token.length;
117
258
  const parsed = JSON.parse(token);
118
259
  if (
@@ -120,7 +261,7 @@ export function createEvidenceJsonTextBoundary(fail) {
120
261
  (!Number.isFinite(parsed) ||
121
262
  (Number.isInteger(parsed) && !Number.isSafeInteger(parsed)))
122
263
  )
123
- reject();
264
+ parserReject("budget");
124
265
  return parsed;
125
266
  };
126
267
  return {
@@ -130,16 +271,26 @@ export function createEvidenceJsonTextBoundary(fail) {
130
271
  };
131
272
  };
132
273
 
133
- return (text, { layer = 0, objectOnly = false, visit, plain, equal }) => {
274
+ return (
275
+ text,
276
+ { layer = 0, objectOnly = false, codeText = false, visit, plain, equal },
277
+ ) => {
134
278
  bytes += Buffer.byteLength(text, "utf8");
135
- if (bytes > EVIDENCE_JSON_POLICY.maxDecodedBytes) reject();
279
+ if (bytes > policy.maxDecodedBytes)
280
+ reject("Agent model JSON text exceeds its budget");
136
281
  const transform = (parsed) => {
137
- if (layer >= EVIDENCE_JSON_POLICY.maxLayers) reject();
282
+ if (layer >= policy.maxLayers)
283
+ reject("Agent model JSON text exceeds its budget");
138
284
  return visit(parsed, layer + 1);
139
285
  };
140
286
  if (objectOnly) {
141
287
  const reader = parser(text, 0);
142
- const parsed = reader.value();
288
+ let parsed;
289
+ try {
290
+ parsed = reader.value();
291
+ } catch (error) {
292
+ rejectParseFailure(error);
293
+ }
143
294
  reader.whitespace();
144
295
  if (
145
296
  reader.end() !== text.length ||
@@ -157,7 +308,7 @@ export function createEvidenceJsonTextBoundary(fail) {
157
308
  // as objects. Ordinary code braces and projection markers are not JSON.
158
309
  let output = "";
159
310
  let plainStart = 0;
160
- for (let index = 0; index < text.length;) {
311
+ for (let index = 0; index < text.length; ) {
161
312
  const char = text[index];
162
313
  const next =
163
314
  char === "{" || char === "["
@@ -173,7 +324,8 @@ export function createEvidenceJsonTextBoundary(fail) {
173
324
  /^\s*(?:-\d|(?:true|false|null)(?=[\s,\]]))/u.test(
174
325
  text.slice(index + 1),
175
326
  )));
176
- if (!container && char !== '"') {
327
+ const quoted = char === '"' || (codeText && char === "'");
328
+ if (!container && !quoted) {
177
329
  index++;
178
330
  continue;
179
331
  }
@@ -181,34 +333,110 @@ export function createEvidenceJsonTextBoundary(fail) {
181
333
  // lexically valid JSON string is a candidate outside JSON containers.
182
334
  if (
183
335
  !container &&
184
- // eslint-disable-next-line no-control-regex -- JSON strings exclude literal U+0000 through U+001F.
185
- !/^"(?:[^"\\\x00-\x1f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/u.test(
186
- text.slice(index),
187
- )
336
+ char === '"' &&
337
+ !(codeText
338
+ ? CODE_DOUBLE_QUOTED_PREFIX.test(text.slice(index))
339
+ : JSON_STRING_PREFIX.test(text.slice(index)))
188
340
  ) {
189
341
  index++;
190
342
  continue;
191
343
  }
192
- const reader = parser(text, index);
193
- let parsed = reader.value();
194
- const valueEnd = reader.end();
344
+ if (
345
+ codeText &&
346
+ char === "'" &&
347
+ !CODE_SINGLE_QUOTED_PREFIX.test(text.slice(index))
348
+ ) {
349
+ index++;
350
+ continue;
351
+ }
352
+ const reader = parser(text, index, {
353
+ // A recognized container is always tried as strict JSON first, even
354
+ // inside code. Only an explicit non-JSON token allows literal scanning.
355
+ allowSingleQuotedStrings: codeText && !container,
356
+ });
357
+ let parsed;
358
+ let valueEnd;
359
+ try {
360
+ parsed = reader.value();
361
+ valueEnd = reader.end();
362
+ } catch (error) {
363
+ const kind = error?.[PARSE_FAILURE];
364
+ if (!codeText || kind !== "code-expression") rejectParseFailure(error);
365
+ // Python/JavaScript containers may contain single quotes or expressions.
366
+ // Scan their literals individually, preserving nested strict JSON scans.
367
+ // Keep consumed nodes charged so repeated fallback cannot reset budgets.
368
+ index++;
369
+ continue;
370
+ }
195
371
  reader.whitespace();
196
- const pair = char === '"' && text[reader.end()] === ":";
372
+ let pair = quoted && text[reader.end()] === ":";
373
+ let pairValueEnd;
374
+ const requireSafeExpressionKey = () => {
375
+ // An expression cannot be visited as a decoded JSON value. Preserve
376
+ // the decoded key boundary: otherwise a password list/call expression
377
+ // could expose its string literals when scanning resumes inside it.
378
+ const probe = Object.defineProperty(Object.create(null), parsed, {
379
+ value: "source-expression",
380
+ enumerable: true,
381
+ });
382
+ if (!equal(probe, transform(probe)))
383
+ reject(
384
+ "Agent model code expression under a sensitive key cannot be safely projected",
385
+ );
386
+ };
387
+ if (pair) {
388
+ const rhsStart = reader.end() + 1;
389
+ const codeExpression = codeText
390
+ ? /^\s*([A-Za-z_$][A-Za-z0-9_$]*)/u.exec(text.slice(rhsStart))?.[1]
391
+ : undefined;
392
+ if (
393
+ codeExpression &&
394
+ !["true", "false", "null"].includes(codeExpression)
395
+ ) {
396
+ requireSafeExpressionKey();
397
+ pair = false;
398
+ } else {
399
+ try {
400
+ const rhsContainer = /^[ \t\r\n]*[\[{]/u.test(text.slice(rhsStart));
401
+ const rhs = parser(text, rhsStart, {
402
+ allowSingleQuotedStrings: codeText && !rhsContainer,
403
+ });
404
+ const entry = rhs.value();
405
+ const entryEnd = rhs.end();
406
+ rhs.whitespace();
407
+ if (
408
+ codeText &&
409
+ /^[+\-*/%?.([<>&|^=!"']/u.test(text[rhs.end()] ?? "")
410
+ )
411
+ requireSafeExpressionKey();
412
+ parsed = Object.defineProperty(Object.create(null), parsed, {
413
+ value: entry,
414
+ enumerable: true,
415
+ });
416
+ pairValueEnd = entryEnd;
417
+ } catch (error) {
418
+ const kind = error?.[PARSE_FAILURE];
419
+ if (kind === undefined) throw error;
420
+ if (!codeText || kind !== "code-expression")
421
+ rejectParseFailure(error);
422
+ // In a run_code source/result string, a quoted key followed by a
423
+ // Python/JavaScript expression is code, not a broken JSON pair.
424
+ // Resume the scan at the next literal so any string value still
425
+ // receives key-aware or ordinary secret scanning.
426
+ requireSafeExpressionKey();
427
+ pair = false;
428
+ }
429
+ }
430
+ }
197
431
  const assignmentKey =
198
- char === '"' && !pair
432
+ quoted && !pair
199
433
  ? // Scan backward once; an unanchored greedy key regex would retry at
200
434
  // every offset of a long ordinary prefix before a quoted fragment.
201
435
  assignmentKeyBefore(text, plainStart, index)
202
436
  : undefined;
203
437
  let end = valueEnd;
204
438
  if (pair) {
205
- const rhs = parser(text, reader.end() + 1);
206
- const entry = rhs.value();
207
- parsed = Object.defineProperty(Object.create(null), parsed, {
208
- value: entry,
209
- enumerable: true,
210
- });
211
- end = rhs.end();
439
+ end = pairValueEnd;
212
440
  } else if (assignmentKey) {
213
441
  // Bare assignments followed by a quoted value cross a text/JSON span.
214
442
  // Reuse decoded field rules rather than a second credential-key list.
@@ -218,6 +446,15 @@ export function createEvidenceJsonTextBoundary(fail) {
218
446
  });
219
447
  }
220
448
  const safe = transform(parsed);
449
+ if (
450
+ codeText &&
451
+ assignmentKey &&
452
+ !equal(parsed, safe) &&
453
+ /^\s*[+\-*/%?.([<>&|^=!"']/u.test(text.slice(end))
454
+ )
455
+ reject(
456
+ "Agent model code expression under a sensitive key cannot be safely projected",
457
+ );
221
458
  let replacement = text.slice(index, end);
222
459
  if (!equal(parsed, safe)) {
223
460
  replacement = JSON.stringify(safe);