chainlesschain 0.166.76 → 0.166.78

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 (230) hide show
  1. package/README.md +19 -8
  2. package/completions/_cc +1 -1
  3. package/completions/cc.bash +1 -1
  4. package/completions/cc.fish +1 -1
  5. package/completions/cc.ps1 +1 -1
  6. package/package.json +1 -1
  7. package/src/assets/linux-subreaper/linux-arm64/manifest.json +10 -0
  8. package/src/assets/linux-subreaper/linux-arm64/supervisor +0 -0
  9. package/src/assets/linux-subreaper/linux-x64/manifest.json +10 -0
  10. package/src/assets/linux-subreaper/linux-x64/supervisor +0 -0
  11. package/src/assets/web-panel/assets/{AIOps-CNaejClV.js → AIOps-DSyZEY2G.js} +1 -1
  12. package/src/assets/web-panel/assets/{ActionButton-CF_CVKT_.js → ActionButton-DhNyZ577.js} +1 -1
  13. package/src/assets/web-panel/assets/{Analytics-a3Z6J7gv.js → Analytics-HMMpxmyi.js} +3 -3
  14. package/src/assets/web-panel/assets/{AppLayout-BFtWEnct.js → AppLayout-CwKMM5Ie.js} +5 -5
  15. package/src/assets/web-panel/assets/{Artifacts-BQ8oeMvX.js → Artifacts-CNzDmph7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Audit-NOo9bmgk.js → Audit-DxWpUW3V.js} +1 -1
  17. package/src/assets/web-panel/assets/{BackgroundAgents-QRc7F3Tp.js → BackgroundAgents-C1R2ST-P.js} +1 -1
  18. package/src/assets/web-panel/assets/{Backup-UlVgLn2P.js → Backup-B6biTaEV.js} +1 -1
  19. package/src/assets/web-panel/assets/{BaseInput-BER9LJAr.js → BaseInput-CVnkD2Z5.js} +1 -1
  20. package/src/assets/web-panel/assets/{Chat-Z8z2Fdfz.js → Chat-Dbewl4Je.js} +6 -6
  21. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DdmuBrdQ.js → ChatBubbleRenderer-DVZ6SwC5.js} +1 -1
  22. package/src/assets/web-panel/assets/{Checkbox-CXPgyB8L.js → Checkbox-BqqiF1JE.js} +1 -1
  23. package/src/assets/web-panel/assets/{Codegen-D1vOsLJ7.js → Codegen-BVMkGumc.js} +1 -1
  24. package/src/assets/web-panel/assets/{Col-ucLnUJC7.js → Col-DmiRHy96.js} +1 -1
  25. package/src/assets/web-panel/assets/{Community-COsV9n9t.js → Community-BDlpygqA.js} +1 -1
  26. package/src/assets/web-panel/assets/{Compact-D0EkBEYh.js → Compact-B2NME_m-.js} +1 -1
  27. package/src/assets/web-panel/assets/{Compliance-C8w9SUjt.js → Compliance-BlzDLE-R.js} +1 -1
  28. package/src/assets/web-panel/assets/{Cowork-CmVaKEJS.js → Cowork-C8raPybB.js} +3 -3
  29. package/src/assets/web-panel/assets/{Cron-B_FiMMV2.js → Cron-DA8Py0zP.js} +2 -2
  30. package/src/assets/web-panel/assets/{Crosschain-ByO3YL8N.js → Crosschain-DU2XyHqB.js} +1 -1
  31. package/src/assets/web-panel/assets/{DID-DwpsLM9r.js → DID-Df098fT_.js} +2 -2
  32. package/src/assets/web-panel/assets/{Dashboard-B_8IUvM_.js → Dashboard-D1rT702x.js} +2 -2
  33. package/src/assets/web-panel/assets/{Dropdown-Bo6WQkuX.js → Dropdown-BweXGo1O.js} +1 -1
  34. package/src/assets/web-panel/assets/{EmailListRenderer-C9LiQesx.js → EmailListRenderer-B9ShbgJH.js} +1 -1
  35. package/src/assets/web-panel/assets/EvolutionSettings-D75_iBoc.js +1 -0
  36. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dst6VUnO.js → FamilyGuardDashboard-DrznZFVs.js} +1 -1
  37. package/src/assets/web-panel/assets/{Federation-Ci7CoLkJ.js → Federation-DQZ2adIA.js} +1 -1
  38. package/src/assets/web-panel/assets/{FormItemContext-bdDyUhUM.js → FormItemContext-DN30Dowh.js} +1 -1
  39. package/src/assets/web-panel/assets/{GenericCardRenderer-CrRwOUVi.js → GenericCardRenderer-DRdt0j1e.js} +1 -1
  40. package/src/assets/web-panel/assets/{Git-Dis8h-Z-.js → Git-wwRgStzk.js} +2 -2
  41. package/src/assets/web-panel/assets/{Governance-DX7OH5w2.js → Governance-CI4Uw0Nh.js} +1 -1
  42. package/src/assets/web-panel/assets/{Inference-Cavv_Q_Z.js → Inference-5TuE2AJI.js} +1 -1
  43. package/src/assets/web-panel/assets/{KnowledgeGraph-Cck8tnZn.js → KnowledgeGraph-oXyvmFSR.js} +1 -1
  44. package/src/assets/web-panel/assets/{Logs-BQt3aGMu.js → Logs-ewudSWuv.js} +2 -2
  45. package/src/assets/web-panel/assets/MarkdownRenderer-Cz5nyufm.js +1 -0
  46. package/src/assets/web-panel/assets/{Marketplace-CdmAKNSN.js → Marketplace-DcZeWFrs.js} +1 -1
  47. package/src/assets/web-panel/assets/{McpTools-BUlJdyPY.js → McpTools-BcV9p1RS.js} +3 -3
  48. package/src/assets/web-panel/assets/{Memory-DQRTQDr-.js → Memory-CMhYvugt.js} +2 -2
  49. package/src/assets/web-panel/assets/{MobileBridge-C0dnxgsl.js → MobileBridge-5RP2uwvT.js} +1 -1
  50. package/src/assets/web-panel/assets/{MobileProjects-DQ5Gy7fa.js → MobileProjects-BIuM9Ze4.js} +1 -1
  51. package/src/assets/web-panel/assets/{Mtc-Xl7u2isS.js → Mtc-DmBszTDe.js} +5 -5
  52. package/src/assets/web-panel/assets/{MtcAudit-C3KX0574.js → MtcAudit-Czdp5ZGt.js} +2 -2
  53. package/src/assets/web-panel/assets/{Multisig-CHEhfkn8.js → Multisig-DRWUuNr-.js} +3 -3
  54. package/src/assets/web-panel/assets/{NLProgramming-Ce38mH-8.js → NLProgramming-IRQQN0-c.js} +1 -1
  55. package/src/assets/web-panel/assets/{Notes-C7nuTd7c.js → Notes-CGhD1lW9.js} +4 -4
  56. package/src/assets/web-panel/assets/{NotificationSettings-BcoEcyq8.js → NotificationSettings-BtyPgQAh.js} +1 -1
  57. package/src/assets/web-panel/assets/{OrderTableRenderer-D-t5hKkx.js → OrderTableRenderer-yUaqwCty.js} +1 -1
  58. package/src/assets/web-panel/assets/{Organization-C_BGi4xi.js → Organization-C3kTVn5i.js} +4 -4
  59. package/src/assets/web-panel/assets/{Overflow-BodhraDq.js → Overflow-C2-0iZhq.js} +1 -1
  60. package/src/assets/web-panel/assets/{P2P-BTa3sAIy.js → P2P-CISoEUxA.js} +2 -2
  61. package/src/assets/web-panel/assets/{PdhVaultBrowser-BjZslP9T.js → PdhVaultBrowser-NfTVtvKQ.js} +5 -5
  62. package/src/assets/web-panel/assets/{Permissions-u3UDzGef.js → Permissions-CfK0jJhm.js} +3 -3
  63. package/src/assets/web-panel/assets/{PersonalDataHub-Cb7ybv65.js → PersonalDataHub-OsVxxh_j.js} +4 -4
  64. package/src/assets/web-panel/assets/{Pipeline-CS24k-P7.js → Pipeline-DEmK_Ch2.js} +1 -1
  65. package/src/assets/web-panel/assets/{Privacy-Ddj6Kqs7.js → Privacy-D61s73b0.js} +1 -1
  66. package/src/assets/web-panel/assets/{ProjectInit-Bg5uQIgg.js → ProjectInit-DkLF5gHb.js} +2 -2
  67. package/src/assets/web-panel/assets/{ProjectSettings-AmPR8T12.js → ProjectSettings-BA7odTrI.js} +2 -2
  68. package/src/assets/web-panel/assets/{Projects-DGSbAyTK.js → Projects-CdI1GcAG.js} +1 -1
  69. package/src/assets/web-panel/assets/{Providers-Dc1C3lbB.js → Providers-D9BYyP1r.js} +1 -1
  70. package/src/assets/web-panel/assets/{QrScannerModal-Cv3HXpce.js → QrScannerModal-CXMItUDD.js} +1 -1
  71. package/src/assets/web-panel/assets/{QuickAsk-3dpbXARb.js → QuickAsk-8-tF9ffZ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Recommend-5aGRVnJK.js → Recommend-C2QGWOSi.js} +1 -1
  73. package/src/assets/web-panel/assets/{RemoteSession-CTS2jx0p.js → RemoteSession-B1M_v1lx.js} +2 -2
  74. package/src/assets/web-panel/assets/{Reputation-BxaKI0hY.js → Reputation-D0WZHgv1.js} +1 -1
  75. package/src/assets/web-panel/assets/{Row-C23uQdwd.js → Row-D6nf9-c-.js} +1 -1
  76. package/src/assets/web-panel/assets/{RssFeed-ssX9YOhm.js → RssFeed-ClZ6M-mN.js} +3 -3
  77. package/src/assets/web-panel/assets/{Search-C24GogII.js → Search-ZWkt8vuO.js} +1 -1
  78. package/src/assets/web-panel/assets/{Security-DdAcGKkk.js → Security-BUlQut2m.js} +3 -3
  79. package/src/assets/web-panel/assets/{Services-D0dCiEuq.js → Services-Cd_3xJOc.js} +2 -2
  80. package/src/assets/web-panel/assets/{Skeleton-DEY44o0v.js → Skeleton-C8e2-cHW.js} +1 -1
  81. package/src/assets/web-panel/assets/Skills-DucVRJp1.js +1 -0
  82. package/src/assets/web-panel/assets/{Sla-B_bbo2vB.js → Sla-Csr5pUwI.js} +1 -1
  83. package/src/assets/web-panel/assets/SpeechSettings-CXvyaRAT.js +1 -0
  84. package/src/assets/web-panel/assets/{SyncSettings-CpIXql0Z.js → SyncSettings-KdsIcV5h.js} +2 -2
  85. package/src/assets/web-panel/assets/Tasks-B-eHmJm9.js +1 -0
  86. package/src/assets/web-panel/assets/{Templates-C_44nVPq.js → Templates-BglVeaLK.js} +1 -1
  87. package/src/assets/web-panel/assets/{Tenant-CyZ2ey2P.js → Tenant-BBbQ8qan.js} +1 -1
  88. package/src/assets/web-panel/assets/{Terminal-DwGNHWnp.js → Terminal-Ca_pCVBi.js} +2 -2
  89. package/src/assets/web-panel/assets/{TimelineRenderer-BTAHNkqU.js → TimelineRenderer-YD6XG_vZ.js} +1 -1
  90. package/src/assets/web-panel/assets/{Tokens-DCJWkUwc.js → Tokens-2lRoeVli.js} +1 -1
  91. package/src/assets/web-panel/assets/{Trigger-BCjDO9-E.js → Trigger-C-3XNAU9.js} +1 -1
  92. package/src/assets/web-panel/assets/{Trust-_YS8WbRb.js → Trust-k-1PxdLG.js} +1 -1
  93. package/src/assets/web-panel/assets/{UkeySign-m6R8xGq7.js → UkeySign-FG-qW646.js} +1 -1
  94. package/src/assets/web-panel/assets/{VideoEditing-xOfk29c4.js → VideoEditing-BNOe1cmd.js} +1 -1
  95. package/src/assets/web-panel/assets/{Wallet-B1Gw0awc.js → Wallet-D5C3i2Kw.js} +4 -4
  96. package/src/assets/web-panel/assets/{WebAuthn-CHK5ft18.js → WebAuthn-BOpztqd3.js} +4 -4
  97. package/src/assets/web-panel/assets/{WorkflowEditor-DEp1ukQQ.js → WorkflowEditor-BpVrpUEv.js} +1 -1
  98. package/src/assets/web-panel/assets/{chat-B2sFizun.js → chat-DIuMHb38.js} +1 -1
  99. package/src/assets/web-panel/assets/{colors-DJ17YV1E.js → colors-CTFJPyzQ.js} +1 -1
  100. package/src/assets/web-panel/assets/{compact-item-CBhJJgEC.js → compact-item-CONfmJcW.js} +1 -1
  101. package/src/assets/web-panel/assets/{createContext-BZkpvNJy.js → createContext-RkW5CRrz.js} +1 -1
  102. package/src/assets/web-panel/assets/devWarning-DaEBln_q.js +1 -0
  103. package/src/assets/web-panel/assets/{hasIn-C0ZKo6Ei.js → hasIn-CW4XOjDC.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Bc3vVG2X.js → index-7wMSBCU7.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-vFMwiAN4.js → index-Akmg1WdH.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DOBXNMdh.js → index-B54qoVff.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DLo8Ls9u.js → index-B8r2t0Ch.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-C7gv9dvb.js → index-B9XoBoty.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-DHtpMr1G.js → index-B9aS2VLu.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Dxe0YlZe.js → index-BFs1Tznc.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DumLgj1t.js → index-BKgaRT0b.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BNp6HKFh.js → index-BM7bOUvu.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DM0rWF6z.js → index-BMg2JFmW.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-4oULtRqE.js → index-BRZsPxNn.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-LPPe0val.js → index-Bf19fKef.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-Ctguam0K.js → index-BkAbfBF-.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DrU5xVpF.js → index-CBjb2A5R.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CCOr6Q27.js → index-CEZWQthY.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-C9gYiACH.js → index-CFGLf88d.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CZW84cEf.js → index-CLUa68JH.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-BoDUYyuo.js → index-CM2X25Er.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DyiCbHeL.js → index-CX4T2uKN.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CW5o1Gar.js → index-CixqfdRk.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-5K2z_tgO.js → index-CkRojEip.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BOfPp5OV.js → index-Cvmc3f25.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CdxJm-HB.js → index-D-lpTPS8.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-8ueG48gl.js → index-D59GbWCN.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BMxOoITz.js → index-DAESljiJ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DLMr5KMd.js → index-DDHUx4Yz.js} +1 -1
  130. package/src/assets/web-panel/assets/index-DG1mcYTa.js +1 -0
  131. package/src/assets/web-panel/assets/{index-BGIvhCPl.js → index-DP5pPedy.js} +1 -1
  132. package/src/assets/web-panel/assets/index-DRs5Pe8u.js +1 -0
  133. package/src/assets/web-panel/assets/{index-DjdSFO0d.js → index-DSlXL6Ju.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Cn5UzvgR.js → index-DWCJnn2O.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-Chct9tL8.js → index-DWY7YwDu.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-BEnd5fiz.js → index-DZTwP364.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-KzNhWykP.js → index-DidrMvOx.js} +1 -1
  138. package/src/assets/web-panel/assets/{index-BpyrhOeh.js → index-Dj3K5kHs.js} +1 -1
  139. package/src/assets/web-panel/assets/{index-CZlkPrxb.js → index-YaeGscSw.js} +1 -1
  140. package/src/assets/web-panel/assets/{index-Dfgxe-fw.js → index-YlMnFNOi.js} +1 -1
  141. package/src/assets/web-panel/assets/{index-IHgzfc1u.js → index-asWsB34i.js} +1 -1
  142. package/src/assets/web-panel/assets/{index-DJkoJzTU.js → index-gkjiFjQd.js} +1 -1
  143. package/src/assets/web-panel/assets/{initDefaultProps-Cqfoq0TJ.js → initDefaultProps-BOr4igh3.js} +1 -1
  144. package/src/assets/web-panel/assets/{motion-CIiVJHNu.js → motion-CK469n2j.js} +1 -1
  145. package/src/assets/web-panel/assets/{move-CFl1o_A8.js → move-DzjudlYQ.js} +1 -1
  146. package/src/assets/web-panel/assets/{mtc-parser-DYoCxcZ1.js → mtc-parser-BQaKUxC6.js} +1 -1
  147. package/src/assets/web-panel/assets/{omit-C1P2q5TY.js → omit-MciovCFD.js} +1 -1
  148. package/src/assets/web-panel/assets/{pickAttrs-BtTRpJtC.js → pickAttrs-DDPJ4zAz.js} +1 -1
  149. package/src/assets/web-panel/assets/{placementArrow-Cst2PcNM.js → placementArrow-Cznyb-jI.js} +1 -1
  150. package/src/assets/web-panel/assets/{responsiveObserve-CF5kalV2.js → responsiveObserve-AJK3SLzJ.js} +1 -1
  151. package/src/assets/web-panel/assets/{slide-CtHGqpXN.js → slide-CPQ28wu7.js} +1 -1
  152. package/src/assets/web-panel/assets/{statusUtils-N__biHXf.js → statusUtils-CFjzvqf_.js} +1 -1
  153. package/src/assets/web-panel/assets/{styleChecker-DR8V_H-i.js → styleChecker-BPyFfTuR.js} +1 -1
  154. package/src/assets/web-panel/assets/{useFlexGapSupport-D274dqun.js → useFlexGapSupport-Dq7N6R05.js} +1 -1
  155. package/src/assets/web-panel/assets/{useFs-BwHLYU5b.js → useFs-C3GS0uTc.js} +1 -1
  156. package/src/assets/web-panel/assets/{usePersonalDataHub-BiA-hVqt.js → usePersonalDataHub-BhgIVzP_.js} +1 -1
  157. package/src/assets/web-panel/assets/{vnode-Bugl94dy.js → vnode-4ZD9-MDr.js} +1 -1
  158. package/src/assets/web-panel/assets/{zoom-DEFl8GCu.js → zoom-Bx4MRVNW.js} +1 -1
  159. package/src/assets/web-panel/index.html +1 -1
  160. package/src/command-help-index.json +1 -1
  161. package/src/command-manifest.json +1 -1
  162. package/src/commands/checkpoint.js +42 -7
  163. package/src/commands/orchestrate.js +85 -25
  164. package/src/commands/session-location.js +5 -0
  165. package/src/commands/session-show.js +109 -1
  166. package/src/commands/session.js +26 -2
  167. package/src/commands/tokens.js +9 -4
  168. package/src/data/changelog.json +26 -0
  169. package/src/generated/cc-agent-protocol.schema.json +71 -0
  170. package/src/harness/jsonl-session-store.js +357 -114
  171. package/src/harness/mcp-client.js +44 -1
  172. package/src/lib/agent-router.js +35 -7
  173. package/src/lib/app-server/server.js +14 -0
  174. package/src/lib/background-agent-supervisor.js +14 -4
  175. package/src/lib/causal-observability.js +64 -1
  176. package/src/lib/checkpoint-summary-projection.js +98 -0
  177. package/src/lib/checkpoint-timeline-authority.js +15 -51
  178. package/src/lib/claude-code-bridge.js +302 -60
  179. package/src/lib/codex-app-server-adapter.js +161 -35
  180. package/src/lib/cost-budget.js +4 -0
  181. package/src/lib/decision-layer/providers.js +84 -9
  182. package/src/lib/decision-layer/runtime.js +86 -49
  183. package/src/lib/direct-model-usage.js +14 -3
  184. package/src/lib/doctor-checkup.js +31 -2
  185. package/src/lib/durable-security-store.js +6 -1
  186. package/src/lib/evolution/evolution-artifact-identity.js +21 -0
  187. package/src/lib/evolution/evolution-artifact-ports.js +5 -11
  188. package/src/lib/evolution/evolution-eval-cohort-receipt-reconciliation.js +389 -0
  189. package/src/lib/execution-location-failure-site.js +63 -0
  190. package/src/lib/execution-location-target.js +102 -8
  191. package/src/lib/external-agent-adapters.js +2 -0
  192. package/src/lib/image-file-boundary.js +154 -0
  193. package/src/lib/image-input.js +16 -3
  194. package/src/lib/llm-pricing.js +114 -8
  195. package/src/lib/mcp-call-ledger-store.js +7 -2
  196. package/src/lib/model-capabilities.js +21 -10
  197. package/src/lib/model-context-catalog.js +60 -1
  198. package/src/lib/openai-responses.js +7 -1
  199. package/src/lib/orchestrator.js +8 -2
  200. package/src/lib/process-execution-broker/index.js +93 -1
  201. package/src/lib/process-execution-broker/linux-subreaper-artifact.js +120 -0
  202. package/src/lib/process-execution-broker/linux-subreaper-helper.js +344 -0
  203. package/src/lib/process-execution-broker/linux-subreaper-process.js +326 -0
  204. package/src/lib/process-execution-broker/linux-subreaper-supervisor.c +360 -0
  205. package/src/lib/process-execution-broker/owned-posix-process-group-worker.mjs +131 -0
  206. package/src/lib/process-execution-broker/owned-posix-process-group.js +267 -0
  207. package/src/lib/process-execution-broker/process-ownership-journal.js +297 -0
  208. package/src/lib/process-execution-broker/process-ownership-quarantine.js +91 -0
  209. package/src/lib/runtime-usage-ledger.js +3 -0
  210. package/src/lib/secure-fs.js +158 -42
  211. package/src/lib/session-branch-history.js +240 -0
  212. package/src/lib/session-history-origins.js +285 -0
  213. package/src/lib/session-input-receipt.js +110 -0
  214. package/src/lib/session-resource-budget.js +8 -8
  215. package/src/lib/session-transcript-history.js +456 -0
  216. package/src/lib/session-transcript-page.js +164 -0
  217. package/src/lib/session-transcript-reference.js +38 -0
  218. package/src/lib/session-usage.js +8 -0
  219. package/src/lib/token-tracker.js +32 -54
  220. package/src/lib/usage-pricing-context.js +93 -0
  221. package/src/runtime/headless-runner.js +8 -0
  222. package/src/runtime/headless-stream.js +202 -4
  223. package/src/assets/web-panel/assets/EvolutionSettings-Pc1IpRfk.js +0 -1
  224. package/src/assets/web-panel/assets/MarkdownRenderer-BIUeeiVA.js +0 -1
  225. package/src/assets/web-panel/assets/Skills-CYt0Mu2W.js +0 -1
  226. package/src/assets/web-panel/assets/SpeechSettings-a2BBjtTL.js +0 -1
  227. package/src/assets/web-panel/assets/Tasks-BYQKU-GL.js +0 -1
  228. package/src/assets/web-panel/assets/devWarning-DZhu13vj.js +0 -1
  229. package/src/assets/web-panel/assets/index-C6iFyQYz.js +0 -1
  230. package/src/assets/web-panel/assets/index-CztThH9f.js +0 -1
@@ -4,6 +4,10 @@ import { tmpdir } from "node:os";
4
4
  import path from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { TextDecoder } from "node:util";
7
+ import {
8
+ readExecutionLocationFailureSite,
9
+ readExecutionLocationStorageFailure,
10
+ } from "./execution-location-failure-site.js";
7
11
  import {
8
12
  EXECUTION_LOCATION_TARGET_ATTESTATION_SCHEMA,
9
13
  createExecutionLocationTargetAttestation,
@@ -18,7 +22,11 @@ import {
18
22
  import { canonicalJson } from "./scheduler-kernel/contract.js";
19
23
  import { executionBroker } from "./process-execution-broker/index.js";
20
24
  import { assertExecutionLocationRunnerLeaseAuthority } from "./execution-location-runner-lifecycle.js";
21
- import { ensurePrivateDirectory, repairPrivatePaths } from "./secure-fs.js";
25
+ import {
26
+ _resolveWindowsAclTimeout,
27
+ ensurePrivateDirectory,
28
+ repairPrivatePaths,
29
+ } from "./secure-fs.js";
22
30
  import { getSessionAntiRollbackDirectory } from "./session-anti-rollback-anchor.js";
23
31
  import {
24
32
  MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
@@ -657,6 +665,11 @@ function localTargetEnvironment(profile, lifecycleEnvironment) {
657
665
  // Windows. Keep all CLI state beneath a dedicated child directory.
658
666
  CHAINLESSCHAIN_HOME: path.join(profile.transport.home, ".chainlesschain"),
659
667
  CHAINLESSCHAIN_SECURITY_ANCHOR_HOME: profile.transport.securityHome,
668
+ // This numeric, bounded operation allowance is part of local storage
669
+ // configuration. Forward no other caller-specific environment or secrets.
670
+ CC_SECURE_FS_WINDOWS_ACL_TIMEOUT_MS: String(
671
+ _resolveWindowsAclTimeout(15_000),
672
+ ),
660
673
  FORCE_COLOR: "0",
661
674
  HOME: profile.transport.home,
662
675
  LOCALAPPDATA: path.join(profile.transport.home, "AppData", "Local"),
@@ -706,6 +719,7 @@ export function prepareLocalTargetState(profile, cliArgs, deps = {}) {
706
719
  anchorBase: profile.transport.securityHome,
707
720
  });
708
721
  const sessionDigest = createHash("sha256").update(sessionId).digest("hex");
722
+ const platform = deps.platform || process.platform;
709
723
  const directories = [
710
724
  stateHome,
711
725
  path.join(stateHome, "sessions"),
@@ -715,11 +729,19 @@ export function prepareLocalTargetState(profile, cliArgs, deps = {}) {
715
729
  path.join(antiRollbackDirectory, "namespace"),
716
730
  path.join(antiRollbackDirectory, "records"),
717
731
  path.join(antiRollbackDirectory, "records", sessionDigest.slice(0, 2)),
732
+ // Windows known-folder APIs can return an empty path for nonexistent
733
+ // isolated profile directories, making first-use caches relative to cwd.
734
+ ...(platform === "win32"
735
+ ? [
736
+ path.join(profile.transport.home, "AppData"),
737
+ path.join(profile.transport.home, "AppData", "Local"),
738
+ path.join(profile.transport.home, "AppData", "Roaming"),
739
+ ]
740
+ : []),
718
741
  ];
719
742
  const uniqueDirectories = [...new Set(directories)];
720
743
  const ensure = deps.ensurePrivateDirectory || ensurePrivateDirectory;
721
744
  const repair = deps.repairPrivatePaths || repairPrivatePaths;
722
- const platform = deps.platform || process.platform;
723
745
  for (const directory of uniqueDirectories) {
724
746
  ensure(
725
747
  directory,
@@ -961,6 +983,65 @@ function targetInvocation(profile, cliArgs, deps = {}, options = {}) {
961
983
  });
962
984
  }
963
985
 
986
+ // Target output can contain session text, paths, or credentials. Report only
987
+ // a fixed diagnostic category; this is never an authorization/retry decision.
988
+ function targetCommandFailureCategory(result) {
989
+ const stderr = String(result?.stderr || "").slice(0, MAX_PROBE_BYTES);
990
+ if (readExecutionLocationStorageFailure(stderr)) return "windows-acl";
991
+ const categories = [
992
+ ["stdin-empty", /session replica stdin is empty/u],
993
+ ["stdin-read-unavailable", /(?:EAGAIN|EINVAL)[^\r\n]*read/u],
994
+ ["stdin-identity", /local target stdin file (?:is invalid|changed)/u],
995
+ [
996
+ "target-facts-changed",
997
+ /target facts changed before location handoff append/u,
998
+ ],
999
+ ["filesystem-access", /\b(?:EACCES|EPERM)\b|Access is denied/iu],
1000
+ ["filesystem-missing", /\bENOENT\b/u],
1001
+ ["module-load", /\b(?:ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND)\b/u],
1002
+ [
1003
+ "file-identity",
1004
+ /(?:identity changed|pathname and descriptor identities differ|physical, non-symlink|single-link file)/u,
1005
+ ],
1006
+ [
1007
+ "storage-integrity",
1008
+ /(?:[Aa]nti-rollback|[Tt]ranscript digest|[Hh]ash chain|[Aa]nchor|[Rr]eplica)[^\r\n]*(?:invalid|mismatch|failed|conflict)/u,
1009
+ ],
1010
+ [
1011
+ "deployment-authority",
1012
+ /(?:authenticated evolution ingress|evolution deployment)/u,
1013
+ ],
1014
+ ["memory-limit", /heap out of memory|Reached heap limit/iu],
1015
+ ];
1016
+ return (
1017
+ categories.find(([, pattern]) => pattern.test(stderr))?.[0] || "unknown"
1018
+ );
1019
+ }
1020
+
1021
+ function targetProcessFailure(result) {
1022
+ // Native spawn errors include executable paths and argv. Preserve only fixed
1023
+ // categories and the same content-free diagnostics as a nonzero target exit.
1024
+ // A timeout is an unknown outcome: this function never retries the command.
1025
+ const categories = new Map([
1026
+ ["ETIMEDOUT", "process-timeout"],
1027
+ ["ENOBUFS", "process-output-limit"],
1028
+ ["ENOENT", "process-unavailable"],
1029
+ ["EACCES", "process-access"],
1030
+ ["EPERM", "process-access"],
1031
+ ]);
1032
+ const failureCategory = categories.get(result.error.code) || "process-spawn";
1033
+ const failureSite = readExecutionLocationFailureSite(result.stderr);
1034
+ const storageFailure = readExecutionLocationStorageFailure(result.stderr);
1035
+ const error = new Error(
1036
+ `target process failed (${failureCategory})${failureSite ? ` at ${failureSite}` : ""}${storageFailure ? ` [${storageFailure}]` : ""}`,
1037
+ );
1038
+ error.code = "CC_EXECUTION_LOCATION_TARGET_COMMAND_FAILED";
1039
+ error.failureCategory = failureCategory;
1040
+ if (failureSite) error.failureSite = failureSite;
1041
+ if (storageFailure) error.storageFailure = storageFailure;
1042
+ return error;
1043
+ }
1044
+
964
1045
  function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
965
1046
  const invocation = targetInvocation(profile, cliArgs, deps, options);
966
1047
  const spawnSync =
@@ -976,9 +1057,14 @@ function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
976
1057
  ) {
977
1058
  throw new Error("target command output boundary is invalid");
978
1059
  }
979
- const timeoutMs = Number(
980
- options.timeoutMs ?? DEFAULT_TARGET_COMMAND_TIMEOUT_MS,
981
- );
1060
+ // Hosted Windows Local targets can spend most of the generic 30-second
1061
+ // window on owner-only ACL checks before the CLI command runs. Keep the
1062
+ // existing bounded 120-second ceiling for this attested target platform.
1063
+ const defaultTimeoutMs =
1064
+ profile.target === "local" && profile.expected.platform === "win32"
1065
+ ? MAX_TARGET_COMMAND_TIMEOUT_MS
1066
+ : DEFAULT_TARGET_COMMAND_TIMEOUT_MS;
1067
+ const timeoutMs = Number(options.timeoutMs ?? defaultTimeoutMs);
982
1068
  if (
983
1069
  !Number.isSafeInteger(timeoutMs) ||
984
1070
  timeoutMs < 1 ||
@@ -1008,12 +1094,20 @@ function runTargetCommand(profile, cliArgs, deps = {}, options = {}) {
1008
1094
  ],
1009
1095
  ...(invocation.spawnOptions || {}),
1010
1096
  });
1011
- if (result?.error) throw result.error;
1097
+ if (result?.error) throw targetProcessFailure(result);
1012
1098
  if (!result || result.status !== 0) {
1099
+ const failureCategory = targetCommandFailureCategory(result);
1100
+ const failureSite = readExecutionLocationFailureSite(result?.stderr);
1101
+ const storageFailure = readExecutionLocationStorageFailure(
1102
+ result?.stderr,
1103
+ );
1013
1104
  const error = new Error(
1014
- `target command failed with status ${result?.status ?? "unknown"}`,
1105
+ `target command failed with status ${result?.status ?? "unknown"} (${failureCategory})${failureSite ? ` at ${failureSite}` : ""}${storageFailure ? ` [${storageFailure}]` : ""}`,
1015
1106
  );
1016
1107
  error.code = "CC_EXECUTION_LOCATION_TARGET_COMMAND_FAILED";
1108
+ error.failureCategory = failureCategory;
1109
+ if (failureSite) error.failureSite = failureSite;
1110
+ if (storageFailure) error.storageFailure = storageFailure;
1017
1111
  throw error;
1018
1112
  }
1019
1113
  return options.interactive ? null : result.stdout;
@@ -1187,7 +1281,7 @@ export function probeExecutionLocationTargetResourceLimit(
1187
1281
  } finally {
1188
1282
  invocation.cleanup?.();
1189
1283
  }
1190
- if (result?.error) throw result.error;
1284
+ if (result?.error) throw targetProcessFailure(result);
1191
1285
  const expectedMarker = `CC_EXECUTION_LOCATION_RESOURCE_PROBE_ARMED:${kind}`;
1192
1286
  const status = Number(result?.status);
1193
1287
  const signal = result?.signal == null ? null : String(result.signal);
@@ -15,6 +15,8 @@ export const EXTERNAL_AGENT_ERROR = Object.freeze({
15
15
  TIMEOUT: "EXTERNAL_AGENT_TIMEOUT",
16
16
  EXIT_NONZERO: "EXTERNAL_AGENT_EXIT_NONZERO",
17
17
  SPAWN_FAILED: "EXTERNAL_AGENT_SPAWN_FAILED",
18
+ CLEANUP_UNCONFIRMED: "EXTERNAL_AGENT_CLEANUP_UNCONFIRMED",
19
+ EXECUTION_BLOCKED: "EXTERNAL_AGENT_EXECUTION_BLOCKED",
18
20
  PROTOCOL_FAILED: "EXTERNAL_AGENT_PROTOCOL_FAILED",
19
21
  UNSUPPORTED_OPTION: "EXTERNAL_AGENT_UNSUPPORTED_OPTION",
20
22
  });
@@ -0,0 +1,154 @@
1
+ import fs from "node:fs";
2
+
3
+ // CLI keeps its existing eight-image allowance; IDE composers admit four.
4
+ export const MAX_INPUT_IMAGES = 8;
5
+ export const MAX_INPUT_IMAGE_BYTES = 20 * 1024 * 1024;
6
+ export const MAX_INPUT_IMAGE_PIXELS = 40_000_000;
7
+ const MAX_HEADER_BYTES = 1024 * 1024;
8
+
9
+ /** Header admission only, not a full codec decode or animation-frame budget. */
10
+ export function inspectImageHeader(data) {
11
+ const ascii = (start, end) => data.toString("ascii", start, end);
12
+ if (
13
+ data.length >= 33 &&
14
+ data
15
+ .subarray(0, 8)
16
+ .equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) &&
17
+ data.readUInt32BE(8) === 13 &&
18
+ ascii(12, 16) === "IHDR"
19
+ ) {
20
+ return {
21
+ mediaType: "image/png",
22
+ width: data.readUInt32BE(16),
23
+ height: data.readUInt32BE(20),
24
+ };
25
+ }
26
+ if (data.length >= 13 && ["GIF87a", "GIF89a"].includes(ascii(0, 6))) {
27
+ return {
28
+ mediaType: "image/gif",
29
+ width: data.readUInt16LE(6),
30
+ height: data.readUInt16LE(8),
31
+ };
32
+ }
33
+ if (data.length >= 30 && ascii(0, 4) === "RIFF" && ascii(8, 12) === "WEBP") {
34
+ const kind = ascii(12, 16);
35
+ if (kind === "VP8X")
36
+ return {
37
+ mediaType: "image/webp",
38
+ width: data.readUIntLE(24, 3) + 1,
39
+ height: data.readUIntLE(27, 3) + 1,
40
+ };
41
+ if (
42
+ kind === "VP8 " &&
43
+ data[23] === 157 &&
44
+ data[24] === 1 &&
45
+ data[25] === 42
46
+ )
47
+ return {
48
+ mediaType: "image/webp",
49
+ width: data.readUInt16LE(26) & 16383,
50
+ height: data.readUInt16LE(28) & 16383,
51
+ };
52
+ if (kind === "VP8L" && data[20] === 47) {
53
+ const bits = data.readUInt32LE(21);
54
+ return {
55
+ mediaType: "image/webp",
56
+ width: (bits & 16383) + 1,
57
+ height: ((bits >>> 14) & 16383) + 1,
58
+ };
59
+ }
60
+ }
61
+ if (data.length >= 4 && data[0] === 255 && data[1] === 216) {
62
+ let offset = 2;
63
+ while (offset + 4 <= data.length) {
64
+ if (data[offset++] !== 255) break;
65
+ while (data[offset] === 255) offset++;
66
+ const marker = data[offset++];
67
+ if (marker === 217 || marker === 218) break;
68
+ if (marker === 1 || (marker >= 208 && marker <= 215)) continue;
69
+ if (offset + 2 > data.length) break;
70
+ const length = data.readUInt16BE(offset);
71
+ if (length < 2 || offset + length > data.length) break;
72
+ if (
73
+ [
74
+ 192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207,
75
+ ].includes(marker) &&
76
+ length >= 8
77
+ ) {
78
+ return {
79
+ mediaType: "image/jpeg",
80
+ width: data.readUInt16BE(offset + 5),
81
+ height: data.readUInt16BE(offset + 3),
82
+ };
83
+ }
84
+ offset += length;
85
+ }
86
+ }
87
+ throw new Error(
88
+ "Unsupported or malformed image header (dimensions must occur within the first 1 MiB)",
89
+ );
90
+ }
91
+
92
+ function readAtMost(io, fd, data) {
93
+ let offset = 0;
94
+ while (offset < data.length) {
95
+ const count = io.readSync(fd, data, offset, data.length - offset, offset);
96
+ if (count === 0) break;
97
+ offset += count;
98
+ }
99
+ return offset;
100
+ }
101
+
102
+ /** Pin one regular-file descriptor and cap allocation/read even if it grows. */
103
+ export function readBoundedImage(
104
+ file,
105
+ expectedMediaType,
106
+ remainingBytes,
107
+ io = fs,
108
+ ) {
109
+ // O_NONBLOCK avoids hanging while opening a FIFO on POSIX. fstat then
110
+ // rejects all non-regular files; Windows has no O_NONBLOCK flag here.
111
+ const fd = io.openSync(
112
+ file,
113
+ fs.constants.O_RDONLY | (fs.constants.O_NONBLOCK || 0),
114
+ );
115
+ try {
116
+ const before = io.fstatSync(fd);
117
+ if (!before.isFile()) throw new Error("Image input must be a regular file");
118
+ if (
119
+ !Number.isSafeInteger(before.size) ||
120
+ before.size <= 0 ||
121
+ before.size > MAX_INPUT_IMAGE_BYTES
122
+ )
123
+ throw new Error("Image must contain 1 byte to 20 MiB");
124
+ if (before.size > remainingBytes)
125
+ throw new Error("Total image attachments exceed 20 MiB per message");
126
+ const header = Buffer.alloc(Math.min(before.size, MAX_HEADER_BYTES));
127
+ const headerSize = readAtMost(io, fd, header);
128
+ const info = inspectImageHeader(header.subarray(0, headerSize));
129
+ if (info.mediaType !== expectedMediaType)
130
+ throw new Error("Image extension does not match its file header");
131
+ if (
132
+ !info.width ||
133
+ !info.height ||
134
+ info.width * info.height > MAX_INPUT_IMAGE_PIXELS
135
+ )
136
+ throw new Error(
137
+ "Image dimensions must be positive and at most 40 megapixels",
138
+ );
139
+ const data = Buffer.alloc(before.size + 1);
140
+ const count = readAtMost(io, fd, data);
141
+ const after = io.fstatSync(fd);
142
+ if (
143
+ count !== before.size ||
144
+ after.size !== before.size ||
145
+ after.mtimeMs !== before.mtimeMs ||
146
+ after.ctimeMs !== before.ctimeMs ||
147
+ !data.subarray(0, headerSize).equals(header.subarray(0, headerSize))
148
+ )
149
+ throw new Error("Image changed while being read; select it again");
150
+ return data.subarray(0, count);
151
+ } finally {
152
+ io.closeSync(fd);
153
+ }
154
+ }
@@ -15,6 +15,11 @@
15
15
  import fs from "fs";
16
16
  import path from "path";
17
17
  import os from "os";
18
+ import {
19
+ MAX_INPUT_IMAGES,
20
+ MAX_INPUT_IMAGE_BYTES,
21
+ readBoundedImage,
22
+ } from "./image-file-boundary.js";
18
23
 
19
24
  /**
20
25
  * Candidate on-disk forms for a path token typed in a prompt, so a path copied
@@ -66,7 +71,10 @@ const EXT_MEDIA = {
66
71
  export function resolveImages(paths, deps = {}) {
67
72
  const _fs = deps.fs || fs;
68
73
  if (!Array.isArray(paths) || paths.length === 0) return [];
69
- return paths.map((p) => {
74
+ if (paths.length > MAX_INPUT_IMAGES)
75
+ throw new Error(`Attach at most ${MAX_INPUT_IMAGES} images per message`);
76
+ let remainingBytes = MAX_INPUT_IMAGE_BYTES;
77
+ return paths.map((p, index) => {
70
78
  const ext = path.extname(String(p)).toLowerCase();
71
79
  const mediaType = EXT_MEDIA[ext];
72
80
  if (!mediaType) {
@@ -74,8 +82,13 @@ export function resolveImages(paths, deps = {}) {
74
82
  `Unsupported image type "${ext || p}" — use png/jpg/jpeg/gif/webp.`,
75
83
  );
76
84
  }
77
- const data = _fs.readFileSync(p).toString("base64");
78
- return { mediaType, data };
85
+ try {
86
+ const data = readBoundedImage(p, mediaType, remainingBytes, _fs);
87
+ remainingBytes -= data.length;
88
+ return { mediaType, data: data.toString("base64") };
89
+ } catch (error) {
90
+ throw new Error(`Image ${index + 1}: ${error.message}`, { cause: error });
91
+ }
79
92
  });
80
93
  }
81
94
 
@@ -15,6 +15,12 @@
15
15
  * substring against the model id.
16
16
  */
17
17
 
18
+ import {
19
+ DOCUMENTED_OPENAI_MODELS,
20
+ DOCUMENTED_ANTHROPIC_MODELS,
21
+ GPT6_PRICING_TERMS,
22
+ } from "./model-context-catalog.js";
23
+
18
24
  /** Providers whose models run locally and cost nothing to call. */
19
25
  export const FREE_PROVIDERS = Object.freeze([
20
26
  "ollama",
@@ -30,6 +36,11 @@ export const FREE_PROVIDERS = Object.freeze([
30
36
  */
31
37
  export const PRICE_TABLE = Object.freeze({
32
38
  anthropic: [
39
+ ...Object.entries(DOCUMENTED_ANTHROPIC_MODELS).map(([match, model]) => ({
40
+ match,
41
+ ...model.pricing,
42
+ exact: true,
43
+ })),
33
44
  // Current Anthropic list prices (USD per 1M tokens), verified 2026-06-21
34
45
  // against the claude-api reference. The Opus tier dropped to $5/$25 with
35
46
  // Opus 4.5 (Nov 2025) — the old $15/$75 applies only to the retired
@@ -47,6 +58,14 @@ export const PRICE_TABLE = Object.freeze({
47
58
  { match: "haiku", in: 1, out: 5 },
48
59
  ],
49
60
  openai: [
61
+ ...Object.entries(DOCUMENTED_OPENAI_MODELS)
62
+ .filter(([, model]) => model.pricing)
63
+ .map(([match, model]) => ({
64
+ match,
65
+ ...model.pricing,
66
+ exact: true,
67
+ terms: GPT6_PRICING_TERMS,
68
+ })),
50
69
  // GPT-5 family (2026). Matching is longest-pattern-first, so dated/variant
51
70
  // ids (gpt-5.5, gpt-5.5-pro, gpt-5.5-instant, …) resolve to the most
52
71
  // specific rate; bare "gpt-5" is the catch-all base rate.
@@ -64,6 +83,10 @@ export const PRICE_TABLE = Object.freeze({
64
83
  { match: "o1-mini", in: 1.1, out: 4.4 },
65
84
  { match: "o1", in: 15, out: 60 },
66
85
  ],
86
+ dashscope: [
87
+ { match: "qwen-turbo", in: 0.3, out: 0.6 },
88
+ { match: "qwen-plus", in: 0.8, out: 2 },
89
+ ],
67
90
  deepseek: [
68
91
  // DeepSeek V4 launch-list rates for the versioned 2026-04 model ids.
69
92
  // Keep these ahead of the legacy aliases so formal budget gates never
@@ -139,9 +162,13 @@ export function mergePricing(overrides, base = PRICE_TABLE) {
139
162
  Number(e.out) >= 0,
140
163
  )
141
164
  .map((e) => ({
165
+ ...(base[providerKey]?.find(
166
+ (entry) => entry.match === e.match.toLowerCase(),
167
+ ) || {}),
142
168
  match: e.match.toLowerCase(),
143
169
  in: Number(e.in),
144
170
  out: Number(e.out),
171
+ explicitOverride: true,
145
172
  }));
146
173
  if (valid.length === 0) continue;
147
174
  const overridden = new Set(valid.map((v) => v.match));
@@ -171,8 +198,23 @@ export function lookupRate(provider, model, table = PRICE_TABLE) {
171
198
  // Longest pattern first so specific beats generic regardless of table order.
172
199
  const sorted = [...entries].sort((a, b) => b.match.length - a.match.length);
173
200
  for (const e of sorted) {
174
- if (m.includes(e.match)) {
175
- return { in: e.in, out: e.out, pattern: e.match };
201
+ if (e.exact ? m === e.match : m.includes(e.match)) {
202
+ // An unrecognized new version must not inherit an older Opus price.
203
+ // Explicit operator overrides remain authoritative.
204
+ if (
205
+ e.match === "opus" &&
206
+ Number(/^claude-opus-(\d+)(?:[.-]|$)/u.exec(m)?.[1]) >= 5 &&
207
+ !e.explicitOverride &&
208
+ e.in === 5 &&
209
+ e.out === 25
210
+ )
211
+ continue;
212
+ return {
213
+ in: e.in,
214
+ out: e.out,
215
+ pattern: e.match,
216
+ ...(e.terms ? { terms: e.terms } : {}),
217
+ };
176
218
  }
177
219
  }
178
220
  return null;
@@ -210,10 +252,18 @@ export function estimateCost({
210
252
  outputTokens = 0,
211
253
  cacheReadTokens = 0,
212
254
  cacheCreationTokens = 0,
255
+ requestInputTokens,
256
+ serviceTier = "standard",
257
+ regionalProcessing = false,
213
258
  table,
214
259
  } = {}) {
215
260
  const rate = lookupRate(provider, model, table);
216
- if (!rate) {
261
+ const tierMultiplier = rate?.terms
262
+ ? Object.hasOwn(rate.terms.serviceMultipliers, serviceTier)
263
+ ? rate.terms.serviceMultipliers[serviceTier]
264
+ : null
265
+ : 1;
266
+ if (!rate || tierMultiplier == null) {
217
267
  return {
218
268
  inputCost: 0,
219
269
  outputCost: 0,
@@ -226,16 +276,34 @@ export function estimateCost({
226
276
  rate: null,
227
277
  };
228
278
  }
279
+ const promptTokens =
280
+ requestInputTokens ??
281
+ Number(inputTokens) + Number(cacheReadTokens) + Number(cacheCreationTokens);
282
+ const longContext = rate.terms?.longContext;
283
+ const longPrompt = longContext && promptTokens > longContext.threshold;
284
+ const inputMultiplier = longPrompt ? longContext.inputMultiplier : 1;
285
+ const outputMultiplier = longPrompt ? longContext.outputMultiplier : 1;
286
+ const multiplier = tierMultiplier * (regionalProcessing ? 1.1 : 1);
229
287
  // Keep full IEEE-754 precision throughout authority and budget arithmetic.
230
288
  // Rounding each component to six decimals lets a real sub-microdollar call
231
289
  // become zero and can make a hard `maxUsd` gate pass incorrectly. Display
232
290
  // surfaces may format these values, but safety decisions consume the raw sum.
233
- const inputCost = (Number(inputTokens) / 1e6) * rate.in;
234
- const outputCost = (Number(outputTokens) / 1e6) * rate.out;
291
+ const inputCost =
292
+ (Number(inputTokens) / 1e6) * rate.in * inputMultiplier * multiplier;
293
+ const outputCost =
294
+ (Number(outputTokens) / 1e6) * rate.out * outputMultiplier * multiplier;
235
295
  const cacheReadCost =
236
- (Number(cacheReadTokens) / 1e6) * rate.in * cacheReadMultiplier(provider);
296
+ (Number(cacheReadTokens) / 1e6) *
297
+ rate.in *
298
+ (rate.terms?.cacheReadMultiplier ?? cacheReadMultiplier(provider)) *
299
+ inputMultiplier *
300
+ multiplier;
237
301
  const cacheCreationCost =
238
- (Number(cacheCreationTokens) / 1e6) * rate.in * CACHE_WRITE_MULTIPLIER;
302
+ (Number(cacheCreationTokens) / 1e6) *
303
+ rate.in *
304
+ (rate.terms?.cacheWriteMultiplier ?? CACHE_WRITE_MULTIPLIER) *
305
+ inputMultiplier *
306
+ multiplier;
239
307
  return {
240
308
  inputCost,
241
309
  outputCost,
@@ -259,15 +327,53 @@ export function estimateCost({
259
327
  */
260
328
  export function priceRollup(aggregate, { table } = {}) {
261
329
  const byModel = (aggregate?.byModel || []).map((row) => {
262
- const est = estimateCost({
330
+ let est = estimateCost({
263
331
  provider: row.provider,
264
332
  model: row.model,
265
333
  inputTokens: row.inputTokens,
266
334
  outputTokens: row.outputTokens,
267
335
  cacheReadTokens: row.cacheReadTokens,
268
336
  cacheCreationTokens: row.cacheCreationTokens,
337
+ serviceTier: row.serviceTier ?? row.service_tier ?? "standard",
338
+ regionalProcessing:
339
+ row.regionalProcessing ?? row.regional_processing ?? false,
269
340
  table,
270
341
  });
342
+ if (Array.isArray(row.pricingBuckets)) {
343
+ const estimates = row.pricingBuckets.map((bucket) =>
344
+ estimateCost({
345
+ provider: row.provider,
346
+ model: row.model,
347
+ ...bucket,
348
+ table,
349
+ }),
350
+ );
351
+ est = { ...est, matched: estimates.every((entry) => entry.matched) };
352
+ for (const field of [
353
+ "inputCost",
354
+ "outputCost",
355
+ "cacheReadCost",
356
+ "cacheCreationCost",
357
+ "totalCost",
358
+ ]) {
359
+ est[field] = estimates.reduce((sum, entry) => sum + entry[field], 0);
360
+ }
361
+ } else if (
362
+ lookupRate(row.provider, row.model, table)?.terms &&
363
+ row.calls > 1
364
+ ) {
365
+ // A legacy aggregate cannot establish which individual requests crossed
366
+ // a pricing threshold. Exclude it rather than inventing a bill.
367
+ est = {
368
+ ...est,
369
+ matched: false,
370
+ inputCost: 0,
371
+ outputCost: 0,
372
+ cacheReadCost: 0,
373
+ cacheCreationCost: 0,
374
+ totalCost: 0,
375
+ };
376
+ }
271
377
  return {
272
378
  ...row,
273
379
  cost: est.totalCost,
@@ -685,10 +685,13 @@ export function assertMcpVerifiedProjectionAuthority(
685
685
  const descriptors = Object.getOwnPropertyDescriptors(authority);
686
686
  const fields = Object.keys(descriptors);
687
687
  if (
688
- fields.length !== VERIFIED_PROJECTION_AUTHORITY_FIELDS.size ||
688
+ fields.length !==
689
+ VERIFIED_PROJECTION_AUTHORITY_FIELDS.size +
690
+ (descriptors.replayEvents ? 1 : 0) ||
689
691
  fields.some(
690
692
  (field) =>
691
- !VERIFIED_PROJECTION_AUTHORITY_FIELDS.has(field) ||
693
+ (!VERIFIED_PROJECTION_AUTHORITY_FIELDS.has(field) &&
694
+ field !== "replayEvents") ||
692
695
  !("value" in descriptors[field]) ||
693
696
  !descriptors[field].enumerable,
694
697
  )
@@ -704,6 +707,8 @@ export function assertMcpVerifiedProjectionAuthority(
704
707
  !Number.isSafeInteger(projectedEventCount) ||
705
708
  projectedEventCount < 0 ||
706
709
  typeof descriptors.readMessages.value !== "function" ||
710
+ (descriptors.replayEvents &&
711
+ typeof descriptors.replayEvents.value !== "function") ||
707
712
  projectedEventCount !== acceptedCount ||
708
713
  projectedHeadHash !== headHash
709
714
  ) {