chainlesschain 0.166.86 → 0.166.88

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 (190) hide show
  1. package/README.md +26 -15
  2. package/package.json +1 -1
  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-DZwiXAIh.js → AIOps-QzeGep9J.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-aNzXoIJP.js → ActionButton-Dfc5bx7S.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-ETQk4ZXt.js → Analytics-tn-_ZG2E.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-D5oEbeEC.js → AppLayout-Deg3WAK8.js} +3 -3
  9. package/src/assets/web-panel/assets/{Artifacts-ja48FAne.js → Artifacts-KU05t0a6.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-DlN0YnDt.js → Audit-CkSZf54T.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-CzvyNsRg.js → BackgroundAgents-i7ivfXF0.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-DXgEC2MQ.js → Backup-QcVUKtf0.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-D9XqejLx.js → BaseInput-B3h5ZJ0g.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-BTwuYUlN.js → Chat-D7AVz0xi.js} +5 -5
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-0anIC2Wn.js → ChatBubbleRenderer-B0-euPW7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-CLuaQbDt.js → Checkbox-H0p0TMlD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-KwQUZs8A.js → Codegen-B6HOmAY3.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-BCmROkzc.js → Col-n_64Fog2.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-CXlUEHR4.js → Community-CX0JGgj0.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-Dzx-lWI2.js → Compact-C4JWUZlx.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-CfXW82FF.js → Compliance-DKyTZakB.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-DIISTRm2.js → Cowork-C0joBMci.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-nyJ-KcFE.js → Cron-D6VkYpxK.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-Dtv1E4cV.js → Crosschain-7b6Uu8jc.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-BCTpektS.js → DID-C8YPKqzY.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-C1Q_m0So.js → Dashboard-DJsOiEry.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BrQ5_PPL.js → Dropdown-CyStFY-4.js} +1 -1
  28. package/src/assets/web-panel/assets/EmailListRenderer-COrIx2Rg.js +1 -0
  29. package/src/assets/web-panel/assets/{EvolutionSettings-DaGaE6bX.js → EvolutionSettings-DpxORusH.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-nJDWBECt.js → FamilyGuardDashboard-5BYZdMG0.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-DhMUY_wG.js → Federation-s1kS0ekU.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-CbONJPuc.js → FormItemContext-CmgoH9HV.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-CDdX4dX-.js → GenericCardRenderer-DSRWrvcL.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-DXbDVJdR.js → Git-Cz3EgnS1.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-DbAfAvs1.js → Governance-De4atTe7.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-Dy-fGea2.js → Inference-DoitBBxJ.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-DAxRpGUF.js → KnowledgeGraph-CIdmJ1pH.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-5L1UCR8X.js → Logs-Coa_qNhU.js} +2 -2
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-u0FPafvT.js → MarkdownRenderer-CeT_RocE.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-DUk_McDG.js → Marketplace-C6kbAQoM.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-B6PNsZ_p.js → McpTools-C2TZn8D-.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-BUUs8j5F.js → Memory-DYdEKDuB.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-pXRsgyuO.js → MobileBridge-pKLeVviZ.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-D4bWcHA_.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-Deaj4faB.js → Mtc-IEoVRV29.js} +4 -4
  46. package/src/assets/web-panel/assets/{MtcAudit-wUV0VUH1.js → MtcAudit-Cov-yYTY.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-C67IIkts.js → Multisig--Jr7OCmp.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-BCA_CWrW.js → NLProgramming-D2gXnYAA.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-D9eu14hQ.js → Notes-hk8pMyve.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-Cnd-J4LM.js → NotificationSettings-D26Nc7MU.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-C4pHUuyZ.js → OrderTableRenderer-DmzHMEOa.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-4YExAbnp.js → Organization-Cn-o6mHT.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-BF-wFuZz.js → Overflow-DP6xpDak.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-CdiajqCT.js → P2P-C9WAjG-I.js} +2 -2
  55. package/src/assets/web-panel/assets/PdhVaultBrowser-DxZb0Ux8.js +7 -0
  56. package/src/assets/web-panel/assets/{Permissions-DrZ4D78_.js → Permissions-BFBN4-IL.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-lDc6OXjz.js → PersonalDataHub-BEDvoAiz.js} +6 -6
  58. package/src/assets/web-panel/assets/{Pipeline-DqDS9ON1.js → Pipeline-Co2Ze_rR.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-BMekZRZu.js → Privacy-BOTn1EId.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-LYS7NFvJ.js → ProjectInit-CObyrZYm.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CcJNHk9A.js → ProjectSettings-DVTN31rd.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-DrfAHgdF.js → Projects-DQSEaVjE.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-aqsly9SR.js → Providers-BRIKWIdQ.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-ZWvR3zqg.js → QrScannerModal-3nxaEXxN.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BT5CgsvW.js → QuickAsk-iwZJEE9z.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-Cz8Dz2RN.js → Recommend-D2_EEbvc.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-BlxPVbtQ.js → RemoteSession-S4w2mUfq.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-B3VGBE-1.js → Reputation-CstUvfTC.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-Bwv7vSEA.js → Row-DEGHFpxz.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DHI085r_.js → RssFeed-DGdZtJQl.js} +2 -2
  71. package/src/assets/web-panel/assets/{Search-DBler5T0.js → Search-DhfXi99U.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-BZdw43NW.js → Security-BbzISrgX.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Cslk5lUj.js → Services-CFjP2sQ3.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-Bur-C-25.js → Skeleton-CFn5wbvm.js} +1 -1
  75. package/src/assets/web-panel/assets/Skills-fVbT8RcW.js +1 -0
  76. package/src/assets/web-panel/assets/{Sla-B1OWgQ51.js → Sla-D6OtC0MT.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-CaBcEaV4.js → SpeechSettings-D0kteBjU.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-CBbG8L6J.js → SyncSettings-BGEWCtPh.js} +2 -2
  79. package/src/assets/web-panel/assets/Tasks-B1xZUG4D.js +1 -0
  80. package/src/assets/web-panel/assets/{Templates-VBBOZ1H5.js → Templates-COlorjqb.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CtQTj7IF.js → Tenant-yLkwfuo3.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-DXVTQjnl.js → Terminal-CAmkq1wf.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-BRIno0aN.js → TimelineRenderer-CcKYq1Ue.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-uiiAfkYN.js → Tokens-9hIqn_LE.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-CPApN8o6.js → Trigger-Dsdkb74C.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-T2jKVwCE.js → Trust-DC4GuE3C.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-C2U_gbzP.js → UkeySign-CSlh00wf.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-BCdlr3Kj.js → VideoEditing-QEWLo3QY.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-CWnjoSc1.js → Wallet-BkPNQgmg.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-CqSbYqHq.js → WebAuthn-7---jCBl.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-Dr_I3jcr.js → WorkflowEditor-Dq6Yiu8E.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-Cg21FKdE.js → chat-CTYIMpWD.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-CK85tY9e.js → colors-C8JtYlDN.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-m-XYPC7W.js → compact-item-spXpnsNC.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BmiEeNvs.js → createContext-D04ewPuL.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-3-s4adfp.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-CCw4KAoc.js → hasIn-DZblOKXx.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Br9t_I1X.js → index-749P1pkM.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BvjC3t35.js → index-B-cKXztT.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BiVPFsat.js → index-B57W1RB6.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-8KzhlvJ9.js → index-B7RA974g.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-OIbfsi-o.js → index-BKfR2eSQ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BGb1j2z9.js → index-BLv-KSGc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-yYmjkf38.js → index-BOuUUW2U.js} +3 -3
  105. package/src/assets/web-panel/assets/{index-J81uvUMN.js → index-BSO33_O2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DI9GJFcn.js → index-B_65aY6c.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BHsiSoGY.js → index-BjMY3Y_L.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-6jXf-Lln.js → index-Bm0z1M6s.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BGUYgc96.js → index-Bw-3CtK2.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-sWUmvT8H.js → index-CE3TYhl0.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CN2xbLGz.js → index-CHtwoTKX.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D7gS_TJl.js → index-CLkua5sJ.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BStyjmLG.js → index-COvZnoIg.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DmSgfXuz.js → index-CZmBlh5P.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-lhoexBDH.js → index-Cfk4o9eI.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DMbrl43d.js → index-Cgztj1JO.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DxRhnsEC.js → index-Cz0gkRz_.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DAlGVix-.js → index-DHOV24VR.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DIlGxS2W.js → index-DLUHbPl3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CYEzWoyZ.js → index-DSoyEHi2.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CBcgIWOe.js → index-D_Md0Jhp.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-D1sU5-XA.js → index-Dcd-qZ68.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B8IC9ZeZ.js → index-DcjouIsi.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ByVvAXdl.js → index-DdC0OsNh.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BtvVupUL.js → index-DruABY-g.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-IskAKXhx.js → index-Dssnz_1x.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DpIy2HzE.js → index-DtSzmzFF.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BIOTRzaF.js → index-DwIEfKo7.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B7xJkhtJ.js → index-EM4_wLPi.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Bv90WEWa.js → index-IFEbaISP.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cf5arJie.js → index-KIoJ2eCK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BUYyhYP6.js → index-Mxj-qi1G.js} +1 -1
  133. package/src/assets/web-panel/assets/index-ZMf_BGlO.js +1 -0
  134. package/src/assets/web-panel/assets/index-jvp8bJBF.js +1 -0
  135. package/src/assets/web-panel/assets/{index-Br0ZNdu1.js → index-rU6_An6N.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-BcfVHmFK.js → index-rVEqWa0_.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-Cc1XOmNe.js → initDefaultProps-Dl0wiMxn.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BehsX88u.js → motion-BFmZYrGO.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-BPx2YsqY.js → move-Cjs64yWq.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-BSFJgFQA.js → mtc-parser-NeQsnBuP.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-DBN5KUeo.js → omit-4Rs-rfs9.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BDK1yZ-9.js → pickAttrs-CUhx2rDY.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-C4rMmKNJ.js → placementArrow-DbIM_OB2.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-BoeoOnxX.js → responsiveObserve-B_TGx9AN.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-BKlr1bl9.js → slide-C46cEP5t.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-Ky1apWPI.js → statusUtils-DqeksICX.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DxxR7uXk.js → styleChecker-2rrypo5u.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-DmsUqVe9.js → useFlexGapSupport-RRe1Edsg.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-CwkG7sOg.js → useFs-CB0oxU1U.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-CddgeEfF.js → usePersonalDataHub-B98WdlUE.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-C_-H8i4Y.js → vnode-CY8AoD95.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-aAsHUMNE.js → zoom-BnT-0MbP.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +1 -1
  155. package/src/commands/eval.js +116 -67
  156. package/src/commands/memory.js +34 -15
  157. package/src/commands/sandbox.js +9 -0
  158. package/src/data/changelog.json +26 -0
  159. package/src/lib/causal-observability.js +6 -45
  160. package/src/lib/context-memory-kernel/durable-memory-port.js +49 -10
  161. package/src/lib/context-memory-kernel/memory-query-index.js +278 -0
  162. package/src/lib/context-memory-kernel/memory-service.js +17 -2
  163. package/src/lib/context-memory-kernel/segmented-memory-port.js +277 -9
  164. package/src/lib/eval/outcomes.js +20 -10
  165. package/src/lib/eval/runner.js +49 -5
  166. package/src/lib/eval/stream-terminal.js +51 -0
  167. package/src/lib/eval/tasks.js +8 -3
  168. package/src/lib/eval/verify01-contracts.js +349 -0
  169. package/src/lib/eval/verify01-execution.js +611 -0
  170. package/src/lib/eval/verify01-host-evidence.js +604 -0
  171. package/src/lib/execution-support.js +58 -0
  172. package/src/lib/llm-pricing.js +98 -11
  173. package/src/lib/model-catalog-review.js +116 -0
  174. package/src/lib/model-context-catalog.js +23 -1
  175. package/src/lib/openai-responses.js +39 -0
  176. package/src/lib/process-execution-broker/index.js +8 -0
  177. package/src/lib/process-execution-broker/linux-subreaper-process.js +24 -2
  178. package/src/lib/process-execution-broker/process-ownership-journal.js +168 -7
  179. package/src/lib/process-execution-broker/process-ownership-quarantine.js +56 -1
  180. package/src/lib/process-execution-broker/process-recovery-cgroup.js +272 -0
  181. package/src/runtime/agent-core.js +9 -24
  182. package/src/runtime/permission-authority-host.js +14 -0
  183. package/src/assets/web-panel/assets/EmailListRenderer-DjoNlONP.js +0 -1
  184. package/src/assets/web-panel/assets/MobileProjects-D7v-2Hwm.js +0 -1
  185. package/src/assets/web-panel/assets/PdhVaultBrowser-BkjfS6Th.js +0 -7
  186. package/src/assets/web-panel/assets/Skills-v0zgLy0X.js +0 -1
  187. package/src/assets/web-panel/assets/Tasks-C7EjXrnN.js +0 -1
  188. package/src/assets/web-panel/assets/devWarning-CkMEODFC.js +0 -1
  189. package/src/assets/web-panel/assets/index-BjE5qaKn.js +0 -1
  190. package/src/assets/web-panel/assets/index-CsFH-2Zk.js +0 -1
@@ -40,6 +40,7 @@ export const PRICE_TABLE = Object.freeze({
40
40
  match,
41
41
  ...model.pricing,
42
42
  exact: true,
43
+ ...(model.pricingTerms ? { terms: model.pricingTerms } : {}),
43
44
  })),
44
45
  // Current Anthropic list prices (USD per 1M tokens), verified 2026-06-21
45
46
  // against the claude-api reference. The Opus tier dropped to $5/$25 with
@@ -64,7 +65,12 @@ export const PRICE_TABLE = Object.freeze({
64
65
  match,
65
66
  ...model.pricing,
66
67
  exact: true,
67
- terms: GPT6_PRICING_TERMS,
68
+ terms: Object.freeze({
69
+ ...GPT6_PRICING_TERMS,
70
+ ...(model.cacheReadMultiplier == null
71
+ ? {}
72
+ : { cacheReadMultiplier: model.cacheReadMultiplier }),
73
+ }),
68
74
  })),
69
75
  // GPT-5 family (2026). Matching is longest-pattern-first, so dated/variant
70
76
  // ids (gpt-5.5, gpt-5.5-pro, gpt-5.5-instant, …) resolve to the most
@@ -120,14 +126,16 @@ export const PRICE_TABLE = Object.freeze({
120
126
  /**
121
127
  * Merge user-supplied price overrides (typically `config.llm.pricing`) onto the
122
128
  * built-in table. Override shape mirrors PRICE_TABLE:
123
- * { "<provider>": [ { match: "<substr>", in: <num>, out: <num> }, ... ] }
129
+ * { "<provider>": [ { match: "<model>", in: <num>, out: <num>, exact?, terms? }, ... ] }
124
130
  *
125
131
  * Per provider, a user entry whose `match` equals a built-in pattern REPLACES
126
132
  * it; brand-new patterns are prepended so they win ties; unknown providers are
127
133
  * added. Malformed entries (missing match / non-numeric / negative / Infinity
128
134
  * rate) are skipped so a bad config line can't crash cost reporting or produce a
129
135
  * negative cost that undercounts spend. Returns a new table; never mutates
130
- * PRICE_TABLE or the input.
136
+ * PRICE_TABLE or the input. Explicit terms replace (rather than partly inherit)
137
+ * the matched terms. Invalid terms throw: silently ignoring a requested tier
138
+ * or cache policy can materially misstate a hard budget.
131
139
  *
132
140
  * @param {object} [overrides]
133
141
  * @param {object} [base=PRICE_TABLE]
@@ -168,6 +176,12 @@ export function mergePricing(overrides, base = PRICE_TABLE) {
168
176
  match: e.match.toLowerCase(),
169
177
  in: Number(e.in),
170
178
  out: Number(e.out),
179
+ ...(Object.hasOwn(e, "exact")
180
+ ? { exact: validateExactMatch(e.exact) }
181
+ : {}),
182
+ ...(Object.hasOwn(e, "terms")
183
+ ? { terms: normalizePricingTerms(e.terms) }
184
+ : {}),
171
185
  explicitOverride: true,
172
186
  }));
173
187
  if (valid.length === 0) continue;
@@ -180,6 +194,79 @@ export function mergePricing(overrides, base = PRICE_TABLE) {
180
194
  return merged;
181
195
  }
182
196
 
197
+ function validateExactMatch(value) {
198
+ if (typeof value !== "boolean")
199
+ throw new TypeError("pricing exact must be a boolean");
200
+ return value;
201
+ }
202
+
203
+ /** Validate and copy the documented request-level override schema. */
204
+ export function normalizePricingTerms(value) {
205
+ const object = (v) =>
206
+ v !== null &&
207
+ typeof v === "object" &&
208
+ (Object.getPrototypeOf(v) === Object.prototype ||
209
+ Object.getPrototypeOf(v) === null);
210
+ const finite = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
211
+ const fail = () => {
212
+ throw new TypeError(
213
+ "Invalid pricing terms: expected finite non-negative multipliers and a positive long-context threshold",
214
+ );
215
+ };
216
+ const allowed = new Set([
217
+ "cacheReadMultiplier",
218
+ "cacheWriteMultiplier",
219
+ "longContext",
220
+ "serviceMultipliers",
221
+ ]);
222
+ if (!object(value) || Reflect.ownKeys(value).some((key) => !allowed.has(key)))
223
+ fail();
224
+ const result = {};
225
+ for (const key of ["cacheReadMultiplier", "cacheWriteMultiplier"]) {
226
+ if (!Object.hasOwn(value, key)) continue;
227
+ if (!finite(value[key])) fail();
228
+ result[key] = value[key];
229
+ }
230
+ if (Object.hasOwn(value, "longContext")) {
231
+ const tier = value.longContext;
232
+ if (
233
+ !object(tier) ||
234
+ Reflect.ownKeys(tier).some(
235
+ (key) =>
236
+ !["threshold", "inputMultiplier", "outputMultiplier"].includes(key),
237
+ ) ||
238
+ !Number.isSafeInteger(tier.threshold) ||
239
+ tier.threshold <= 0 ||
240
+ !finite(tier.inputMultiplier) ||
241
+ !finite(tier.outputMultiplier)
242
+ )
243
+ fail();
244
+ result.longContext = Object.freeze({
245
+ threshold: tier.threshold,
246
+ inputMultiplier: tier.inputMultiplier,
247
+ outputMultiplier: tier.outputMultiplier,
248
+ });
249
+ }
250
+ if (Object.hasOwn(value, "serviceMultipliers")) {
251
+ const tiers = value.serviceMultipliers;
252
+ if (
253
+ !object(tiers) ||
254
+ Reflect.ownKeys(tiers).length === 0 ||
255
+ Reflect.ownKeys(tiers).some(
256
+ (key) =>
257
+ !["standard", "default", "auto", "batch", "flex", "fast"].includes(
258
+ key,
259
+ ) || !finite(tiers[key]),
260
+ )
261
+ )
262
+ fail();
263
+ result.serviceMultipliers = Object.freeze(
264
+ Object.fromEntries(Object.entries(tiers)),
265
+ );
266
+ }
267
+ return Object.freeze(result);
268
+ }
269
+
183
270
  /**
184
271
  * Look up the rate for a provider/model, or null if unpriced.
185
272
  * @param {string} provider
@@ -199,14 +286,12 @@ export function lookupRate(provider, model, table = PRICE_TABLE) {
199
286
  const sorted = [...entries].sort((a, b) => b.match.length - a.match.length);
200
287
  for (const e of sorted) {
201
288
  if (e.exact ? m === e.match : m.includes(e.match)) {
202
- // An unrecognized new version must not inherit an older Opus price.
289
+ // An unrecognized new generation must not inherit an older family price.
203
290
  // Explicit operator overrides remain authoritative.
204
291
  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
292
+ ["opus", "sonnet"].includes(e.match) &&
293
+ Number(/^claude-(?:opus|sonnet)-(\d+)(?:[.-]|$)/u.exec(m)?.[1]) >= 5 &&
294
+ !e.explicitOverride
210
295
  )
211
296
  continue;
212
297
  return {
@@ -258,7 +343,7 @@ export function estimateCost({
258
343
  table,
259
344
  } = {}) {
260
345
  const rate = lookupRate(provider, model, table);
261
- const tierMultiplier = rate?.terms
346
+ const tierMultiplier = rate?.terms?.serviceMultipliers
262
347
  ? Object.hasOwn(rate.terms.serviceMultipliers, serviceTier)
263
348
  ? rate.terms.serviceMultipliers[serviceTier]
264
349
  : null
@@ -359,7 +444,9 @@ export function priceRollup(aggregate, { table } = {}) {
359
444
  est[field] = estimates.reduce((sum, entry) => sum + entry[field], 0);
360
445
  }
361
446
  } else if (
362
- lookupRate(row.provider, row.model, table)?.terms &&
447
+ (lookupRate(row.provider, row.model, table)?.terms?.longContext ||
448
+ lookupRate(row.provider, row.model, table)?.terms
449
+ ?.serviceMultipliers) &&
363
450
  row.calls > 1
364
451
  ) {
365
452
  // A legacy aggregate cannot establish which individual requests crossed
@@ -0,0 +1,116 @@
1
+ import { resolveModelCapabilityProfile } from "./model-capabilities.js";
2
+ import { lookupRate } from "./llm-pricing.js";
3
+ import { isDeepStrictEqual } from "node:util";
4
+
5
+ /** Compare reviewed release facts with local behavior; never change a catalog. */
6
+ export function reviewModelCatalog(review, snapshots = {}) {
7
+ if (
8
+ review?.schema !== "chainlesschain.model-catalog-review/v1" ||
9
+ !Array.isArray(review.models) ||
10
+ !review.models.length
11
+ ) {
12
+ throw new TypeError("Invalid reviewed model catalog");
13
+ }
14
+ const mismatches = [];
15
+ for (const expected of review.models) {
16
+ const actual = resolveModelCapabilityProfile(expected);
17
+ const rate = lookupRate(expected.provider, expected.model);
18
+ for (const field of [
19
+ "runtimeProtocol",
20
+ "contextWindowTokens",
21
+ "advertisedMaxOutputTokens",
22
+ ]) {
23
+ if (Object.hasOwn(expected, field) && actual[field] !== expected[field])
24
+ mismatches.push({
25
+ model: expected.model,
26
+ field,
27
+ expected: expected[field],
28
+ actual: actual[field],
29
+ });
30
+ }
31
+ if (!actual.sources.length)
32
+ mismatches.push({
33
+ model: expected.model,
34
+ field: "official-source",
35
+ actual: null,
36
+ });
37
+ for (const field of ["in", "out"]) {
38
+ if (rate?.[field] !== expected.pricing[field])
39
+ mismatches.push({
40
+ model: expected.model,
41
+ field,
42
+ expected: expected.pricing[field],
43
+ actual: rate?.[field] ?? null,
44
+ });
45
+ }
46
+ for (const field of [
47
+ "cacheReadMultiplier",
48
+ "cacheWriteMultiplier",
49
+ "longContext",
50
+ "serviceMultipliers",
51
+ ]) {
52
+ if (
53
+ Object.hasOwn(expected.pricing, field) &&
54
+ !isDeepStrictEqual(
55
+ rate?.terms?.[field] ?? null,
56
+ expected.pricing[field],
57
+ )
58
+ ) {
59
+ mismatches.push({
60
+ model: expected.model,
61
+ field,
62
+ expected: expected.pricing[field],
63
+ actual: rate?.terms?.[field] ?? null,
64
+ });
65
+ }
66
+ }
67
+ if (
68
+ expected.reasoningEfforts &&
69
+ JSON.stringify(actual.reasoningEfforts) !==
70
+ JSON.stringify(expected.reasoningEfforts)
71
+ )
72
+ mismatches.push({
73
+ model: expected.model,
74
+ field: "reasoningEfforts",
75
+ expected: expected.reasoningEfforts,
76
+ actual: actual.reasoningEfforts ?? null,
77
+ });
78
+ }
79
+ const upstream = [];
80
+ for (const [name, source] of Object.entries(snapshots)) {
81
+ if (
82
+ !["codex", "claude"].includes(name) ||
83
+ typeof source !== "string" ||
84
+ source.length > 16 * 1024 * 1024
85
+ )
86
+ throw new TypeError("Invalid upstream release snapshot");
87
+ const text = source
88
+ .replace(/<(script|style)\b[^>]*>[\s\S]*?<\/\1>/gi, "")
89
+ .replace(/<[^>]+>/g, " ");
90
+ const version =
91
+ name === "codex"
92
+ ? /Codex CLI\s+(\d+\.\d+\.\d+)/.exec(text)?.[1]
93
+ : /<Update\s+label="(\d+\.\d+\.\d+)"/u.exec(source)?.[1] ||
94
+ /^##\s+(\d+\.\d+\.\d+)/m.exec(text)?.[1];
95
+ if (!version)
96
+ throw new Error(
97
+ `Cannot identify the ${name} release in the official snapshot`,
98
+ );
99
+ upstream.push({
100
+ name,
101
+ reviewedVersion: review.upstream[name],
102
+ observedVersion: version,
103
+ reviewRequired: version !== review.upstream[name],
104
+ });
105
+ }
106
+ return {
107
+ schema: "chainlesschain.model-catalog-review-result/v1",
108
+ reviewedAt: review.reviewedAt,
109
+ localContractPassed: mismatches.length === 0,
110
+ mismatches,
111
+ upstream,
112
+ reviewRequired:
113
+ mismatches.length > 0 || upstream.some((row) => row.reviewRequired),
114
+ automaticEnablement: false,
115
+ };
116
+ }
@@ -45,7 +45,7 @@ export const CONTEXT_WINDOWS = Object.freeze({
45
45
  }),
46
46
  });
47
47
 
48
- export const MODEL_CAPABILITY_CATALOG_VERSION = "2026-09-27";
48
+ export const MODEL_CAPABILITY_CATALOG_VERSION = "2026-10-05";
49
49
 
50
50
  // Explicit ownership prevents a model name served by an unrelated provider
51
51
  // from silently inheriting another provider's catalog window.
@@ -85,6 +85,18 @@ export const LEGACY_MODEL_PROVIDERS = Object.freeze({
85
85
  // Official pages reviewed on the catalog version date. These describe the
86
86
  // named models, not endpoint access, account entitlement, or a live CLI run.
87
87
  export const DOCUMENTED_OPENAI_MODELS = Object.freeze({
88
+ "gpt-6.1-sol": Object.freeze({
89
+ contextWindowTokens: 1050000,
90
+ advertisedMaxOutputTokens: 128000,
91
+ requiresResponsesForTools: true,
92
+ reasoningEfforts: Object.freeze(["low", "medium", "high", "xhigh", "max"]),
93
+ pricing: Object.freeze({ in: 2, out: 10 }),
94
+ // This generation has a 5% cache-read rate, unlike GPT-6 Sol's 10%.
95
+ cacheReadMultiplier: 0.05,
96
+ sources: Object.freeze([
97
+ "https://developers.openai.com/api/docs/models/gpt-6.1-sol",
98
+ ]),
99
+ }),
88
100
  "gpt-4o": Object.freeze({
89
101
  contextWindowTokens: 128000,
90
102
  advertisedMaxOutputTokens: 16384,
@@ -132,11 +144,21 @@ export const DOCUMENTED_OPENAI_MODELS = Object.freeze({
132
144
  });
133
145
 
134
146
  export const DOCUMENTED_ANTHROPIC_MODELS = Object.freeze({
147
+ "claude-sonnet-5-5": Object.freeze({
148
+ contextWindowTokens: 1000000,
149
+ advertisedMaxOutputTokens: null,
150
+ pricing: Object.freeze({ in: 2, out: 10 }),
151
+ pricingTerms: Object.freeze({ cacheReadMultiplier: 0.1 }),
152
+ sources: Object.freeze([
153
+ "https://code.claude.com/docs/en/changelog#2-1-284",
154
+ ]),
155
+ }),
135
156
  "claude-opus-5-5": Object.freeze({
136
157
  contextWindowTokens: 1000000,
137
158
  // The release notes establish the window and pricing, not an output cap.
138
159
  advertisedMaxOutputTokens: null,
139
160
  pricing: Object.freeze({ in: 4, out: 20 }),
161
+ pricingTerms: Object.freeze({ cacheReadMultiplier: 0.05 }),
140
162
  sources: Object.freeze([
141
163
  "https://code.claude.com/docs/en/changelog#2-1-280",
142
164
  ]),
@@ -176,7 +176,16 @@ export function createOpenAIResponsesBody({
176
176
  maxOutputTokens = null,
177
177
  reasoning = null,
178
178
  stream = false,
179
+ modelProfile = null,
179
180
  }) {
181
+ if (
182
+ modelProfile?.advertisedMaxOutputTokens != null &&
183
+ maxOutputTokens > modelProfile.advertisedMaxOutputTokens
184
+ ) {
185
+ throw new RangeError(
186
+ `maxOutputTokens exceeds the documented limit (${modelProfile.advertisedMaxOutputTokens}) for ${model}`,
187
+ );
188
+ }
180
189
  return {
181
190
  model,
182
191
  input: toOpenAIResponsesInput(messages),
@@ -189,6 +198,36 @@ export function createOpenAIResponsesBody({
189
198
  };
190
199
  }
191
200
 
201
+ /** Translate UI intensity without sending an effort rejected by the model. */
202
+ export function createOpenAIResponsesReasoning(
203
+ options = {},
204
+ modelProfile = null,
205
+ ) {
206
+ const want = options.thinking;
207
+ if (!want || want === "off" || want === "none") return null;
208
+ const requested =
209
+ typeof options.thinkingEffort === "string"
210
+ ? options.thinkingEffort.toLowerCase()
211
+ : null;
212
+ const fallback = ["ultra", "ultrathink"].includes(String(want))
213
+ ? "xhigh"
214
+ : want === "think"
215
+ ? "medium"
216
+ : "high";
217
+ const generic = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
218
+ const effort =
219
+ requested && generic.includes(requested) ? requested : fallback;
220
+ if (
221
+ modelProfile?.reasoningEfforts &&
222
+ !modelProfile.reasoningEfforts.includes(requested || effort)
223
+ ) {
224
+ throw new RangeError(
225
+ `Unsupported reasoning effort for ${modelProfile.model}; allowed: ${modelProfile.reasoningEfforts.join(", ")}`,
226
+ );
227
+ }
228
+ return { effort, summary: "auto" };
229
+ }
230
+
192
231
  export function normalizeOpenAIResponsesUsage(usage) {
193
232
  if (!usage || typeof usage !== "object" || Array.isArray(usage)) return null;
194
233
  const input = nonNegativeInteger(usage.input_tokens);
@@ -53,6 +53,7 @@ import {
53
53
  getProcessOwnershipStatus,
54
54
  observeProcessOwnership,
55
55
  prepareProcessOwnership,
56
+ recoverProcessOwnership,
56
57
  } from "./process-ownership-quarantine.js";
57
58
  import {
58
59
  MACOS_MCP_LAUNCHER_INPUTS,
@@ -4525,6 +4526,10 @@ class ProcessExecutionBroker extends EventEmitter {
4525
4526
  return getProcessOwnershipStatus();
4526
4527
  }
4527
4528
 
4529
+ recoverProcessOwnership(executionId, options) {
4530
+ return recoverProcessOwnership(executionId, options);
4531
+ }
4532
+
4528
4533
  listWorkspaceTransactions(options = {}) {
4529
4534
  return this._workspaceTransactionManager(
4530
4535
  options.stateDir,
@@ -4873,6 +4878,9 @@ class ProcessExecutionBroker extends EventEmitter {
4873
4878
  cwd: path.resolve(optsForSpawn.cwd || cwd),
4874
4879
  env: optsForSpawn.env || process.env,
4875
4880
  graceMs: request.graceMs,
4881
+ ...(ownershipLease?.beforeLaunch
4882
+ ? { beforeLaunch: ownershipLease.beforeLaunch }
4883
+ : {}),
4876
4884
  helper,
4877
4885
  },
4878
4886
  {
@@ -96,10 +96,22 @@ export function spawnLinuxSubreaper(command, args, options, native) {
96
96
  if (
97
97
  Object.keys(options).some(
98
98
  (key) =>
99
- !["cwd", "env", "graceMs", "helperPath", "helper"].includes(key),
99
+ ![
100
+ "cwd",
101
+ "env",
102
+ "graceMs",
103
+ "helperPath",
104
+ "helper",
105
+ "beforeLaunch",
106
+ ].includes(key),
100
107
  )
101
108
  )
102
109
  throw new TypeError("Unsupported Linux subreaper option");
110
+ if (
111
+ options.beforeLaunch !== undefined &&
112
+ typeof options.beforeLaunch !== "function"
113
+ )
114
+ throw new TypeError("Invalid trusted before-launch hook");
103
115
  launch = encodeLinuxSubreaperLaunch(command, args, options);
104
116
  child = native.spawn(helper ? "/proc/self/fd/4" : options.helperPath, [], {
105
117
  cwd: options.cwd,
@@ -249,7 +261,17 @@ export function spawnLinuxSubreaper(command, args, options, native) {
249
261
  });
250
262
  });
251
263
  });
252
- control.write(launch);
264
+ try {
265
+ const result = options.beforeLaunch?.(child);
266
+ if (result && typeof result.then === "function")
267
+ throw new TypeError("Before-launch hook must be synchronous");
268
+ control.write(launch);
269
+ } catch (error) {
270
+ // No launch frame was sent. Closing the private control channel releases
271
+ // the blocked supervisor without executing the target.
272
+ control.destroy();
273
+ throw error;
274
+ }
253
275
  return Object.freeze({ child, terminate, completion });
254
276
  }
255
277