chainlesschain 0.166.98 → 0.166.100

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 (179) hide show
  1. package/README.md +19 -23
  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-DCIQFtF1.js → AIOps-Cd4iUOPt.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-BxhHU3nE.js → ActionButton--ucr-zko.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-DdM_307O.js → Analytics-DbejYMWk.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-C43-kSrh.js → AppLayout-CLgKxeGw.js} +5 -5
  9. package/src/assets/web-panel/assets/{Artifacts-B2Vp2Am6.js → Artifacts-CTT5BIL5.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-s-lYUfOp.js → Audit-DP-WBWe9.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-DTE7Kzio.js → BackgroundAgents-B6VqheJk.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-9k1q4Mt6.js → Backup-VWJK5zim.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-DlpUtK5R.js → BaseInput-YGFO9RHd.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-CR9S8Rmb.js → Chat-CVfydnCd.js} +5 -5
  15. package/src/assets/web-panel/assets/ChatBubbleRenderer-BICpB-qU.js +1 -0
  16. package/src/assets/web-panel/assets/{Checkbox-DpFRu7Df.js → Checkbox-Bd5vKRMk.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-BIl72E4Y.js → Codegen-DHNgPHvg.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-91tl_err.js → Col-CA2BYQ8T.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-CswahO9-.js → Community-DnKJ-qpI.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-D9pfHmaM.js → Compact-C9BZ8t4r.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-CXSZzAO9.js → Compliance-ByyQ2FOl.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-CuT9RWTn.js → Cowork-rXTwXE_c.js} +2 -2
  23. package/src/assets/web-panel/assets/{Cron-B71aJWDV.js → Cron-BuW-HODy.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-CcUuWyx8.js → Crosschain-OudNtbYW.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-CtVVGOPL.js → DID-BQ6BxYNN.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-CV7ZCYQq.js → Dashboard-Cz5HG8tz.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-DKHxwLgE.js → Dropdown-BzclHOVv.js} +1 -1
  28. package/src/assets/web-panel/assets/{EmailListRenderer-Bd03UIvv.js → EmailListRenderer-CbJETFdy.js} +1 -1
  29. package/src/assets/web-panel/assets/{EvolutionSettings-CTrG03B_.js → EvolutionSettings-Dx_pJG3d.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DXS4bS6Q.js → FamilyGuardDashboard-6JCS1MNg.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-BODG2Szj.js → Federation-BrPkMYaf.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-D32ccUqD.js → FormItemContext-Bhc9pobs.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-ClsyrKvF.js → GenericCardRenderer-BxOh07uQ.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-DcM2yhbL.js → Git-D_idoujr.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-BhUzM87n.js → Governance-ZGfIRE-x.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-Dq1n0Ifg.js → Inference-DpAmcwbw.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-dmmPwEks.js → KnowledgeGraph-D1S1UTgP.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-CBSYrPmh.js → Logs-2sc8V5XV.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-575jjYE6.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-Cfw7XLck.js → Marketplace-0xlFUKbe.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-CNrZRy4n.js → McpTools-D25eJLGm.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-BESjTxdd.js → Memory-BLRGd9hM.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-Boyjo07i.js → MobileBridge-zpFINGzn.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-BmxmpTWz.js → MobileProjects-Cbyd-8kx.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-CBkrD0Fq.js → Mtc-DgXgUlHc.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-BA7cAK8h.js → MtcAudit-DzcL-dKH.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-m0RGzkKO.js → Multisig-C3OrZ6VN.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-D_TgzifU.js → NLProgramming-Bqp_vWA7.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-Dr-Yr9LL.js → Notes-Dyn45-Ht.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-DGanpkqO.js → NotificationSettings-CLjafGZr.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-D1FX50QY.js → OrderTableRenderer-Bx8wMauC.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-DRbPg-gs.js → Organization-5gr9hyLm.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-flEO37z6.js → Overflow-BRdU02hT.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-DqfqFbCW.js → P2P-DIi7fzh6.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-Cmi5a5dW.js → PdhVaultBrowser-BCbS1KpA.js} +3 -3
  56. package/src/assets/web-panel/assets/{Permissions-DBVRlvBW.js → Permissions-BjeP9VtA.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-gQqjPr9X.js → PersonalDataHub-y8PXOQUc.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-6HlifUc9.js → Pipeline-B0fL5uxY.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-bm_2-Zwg.js → Privacy-C8jCDn8Z.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-BJW3isuq.js → ProjectInit-B_L6Dc6V.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-DD3yolz7.js → ProjectSettings-Bb1CYbZh.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-CUSV10Cn.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-CQA6WAK7.js → Providers-mBSTDJ0E.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-DOAwp5Xo.js → QrScannerModal-CHxgalvt.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-qeFXsAZT.js → QuickAsk-DI9KIMEV.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-zDWXwZN8.js → Recommend-B5_zW1JH.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-toe6Ip06.js → RemoteSession-BkH4bmM5.js} +3 -3
  68. package/src/assets/web-panel/assets/{Reputation-DRDi_Eqp.js → Reputation-DJrAqwAq.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-Do2UbYkf.js → Row-xZ3MAM34.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-B57C6_Sa.js → RssFeed-CCsrLLiu.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-DfDyBpe9.js → Search-CTCRKvaP.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-CulNxeAM.js → Security-D7joyfp2.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-COfAYvs4.js → Services-oqHPmTG4.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-0fn0T146.js → Skeleton-BR_32bTG.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-pPQgAhvJ.js → Skills-BoRz9mln.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-CIsRmePR.js → Sla-UAGUHZ9b.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-Bn01d-8b.js → SpeechSettings-DeP_rMgv.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-Cx_Znk7L.js → SyncSettings-CSzzMmeA.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-DvaskzpG.js → Tasks-CcqOLsLB.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-DmHCEiDO.js → Templates-cDbkGSDG.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CqHyvnbW.js → Tenant-DmOy58cq.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-DTt3yqWL.js → Terminal-CsRZH5vr.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-BhkIxcR3.js → TimelineRenderer-BgJrk6HG.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-mhjYcBBP.js → Tokens-CCQglKDE.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-CdlMQfwX.js → Trigger-t-Gt3oBY.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-Bzovg_Gw.js → Trust-DQgu2kI0.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-ph3EuYi7.js → UkeySign-Cod2WUGj.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-Bo2B4VZE.js → VideoEditing-SGN5zaVK.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-BQTKsSUT.js → Wallet-CnLEL-LD.js} +3 -3
  90. package/src/assets/web-panel/assets/{WebAuthn-nJxsXNHV.js → WebAuthn-C2keUpD6.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-CjH8g2N7.js → WorkflowEditor-B1GvrwWJ.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-CkbNmnQD.js → chat-1E9_P_qY.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-BY9JcObR.js → colors-DuU6Os4q.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-Dzzq-d8n.js → compact-item-C5NfOAcM.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-DiJxxdTx.js → createContext-D4Fxz9qQ.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-zDWbYMr7.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-DaXPOw3D.js → hasIn-C6C49iFk.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Uh9SjtgW.js → index-AO6iDCSL.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-B4Sf1AMk.js → index-B-bb-R99.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-cu1J4avY.js → index-B5lzRoHp.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DaylJfw6.js → index-BBVqlelF.js} +1 -1
  102. package/src/assets/web-panel/assets/index-BPBsZZnT.js +1 -0
  103. package/src/assets/web-panel/assets/{index-CWLpEg34.js → index-BU5mPkNX.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-LRZSVBxC.js → index-BULggEX6.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Djeh6rAb.js → index-BVE2wCeb.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-B31oMRmK.js → index-BYg1dtne.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DSqQyS9-.js → index-BZKRZYTX.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CnLO1_yN.js → index-B_ON9La1.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Jmlk_lDX.js → index-Bk-paNL3.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BQvtlYUd.js → index-BlHkc48f.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BvgMt6Io.js → index-BmvU4Tp_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CbOOm8I8.js → index-BsH8mFp4.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C_OMH_FT.js → index-Bu6qMjf4.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BycyBM6g.js → index-C2nO02uW.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BlWg1bRA.js → index-C7mh6xlu.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-i9eu2Kir.js → index-CDVwN9Sv.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DWT9-E5b.js → index-CJS6GTpv.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CqOkm6kW.js → index-CQJoh5rw.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-7YVCjSqG.js → index-CXb8gEWh.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DDnqjZa2.js → index-CXn-e3ki.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Igq-72Ep.js → index-CpiOzt7U.js} +1 -1
  122. package/src/assets/web-panel/assets/index-CtGQDg7m.js +1 -0
  123. package/src/assets/web-panel/assets/{index-BqCHe05H.js → index-D1TXgNPA.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-D_Eoh740.js → index-DFK6PTGJ.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-EiaWq1TH.js → index-DP2DCKD-.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CVblRqUN.js → index-DPzunJER.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-Bhsxh-rH.js → index-DSypQU1h.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DbmHmeP-.js → index-DZgT7pH-.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-dC2JACyJ.js → index-Dh-vezHe.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BHeHyLRM.js → index-DpaGe-dr.js} +3 -3
  131. package/src/assets/web-panel/assets/{index-6Z6Z4UwN.js → index-HQXFl8fh.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BGvIb1Sr.js → index-bW6vfpLH.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DObXhPhH.js → index-cnDfwWU5.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-Dl8U-0hn.js → index-gh11zJ9h.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-CAzfu6k5.js → index-jFg3CPlQ.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-C6XSCXeb.js → index-lNmDaf3J.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-B0WuG3fa.js → initDefaultProps-3DSfnIpD.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-1r5YB22w.js → motion-DxGLmgA0.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-CvtXWA_V.js → move-DrlLG6m5.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-ChedmEE_.js → mtc-parser-BITbrJSb.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-DpEA3MP0.js → omit-D7k5vIbk.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BWgrUZF6.js → pickAttrs-BJSvYFWo.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BWfo_VbI.js → placementArrow-Bf4to1jA.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-CRft03Vk.js → responsiveObserve-BXzeyzTa.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-l5LeXusH.js → slide-DLzNUNdj.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-CCEC0JR-.js → statusUtils-wBBnrRm_.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-Bw5Gw_2w.js → styleChecker-BnmJzXNr.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-BAuxWB7K.js → useFlexGapSupport-DrN8MrJb.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-CxUP97Cw.js → useFs-dnkYGkjY.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BJDjT4Sy.js → usePersonalDataHub-k_xkv7-k.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BcCsFzIs.js → vnode-B-v8PXpK.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-MLmG09h6.js → zoom-Coue8wAK.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/data/changelog.json +26 -0
  155. package/src/harness/worktree-isolator.js +20 -8
  156. package/src/lib/chat-core.js +57 -25
  157. package/src/lib/cost-budget.js +8 -0
  158. package/src/lib/eval/verify01-execution-window.js +70 -0
  159. package/src/lib/eval/verify01-execution.js +9 -1
  160. package/src/lib/eval/verify01-host-capture.js +6 -2
  161. package/src/lib/llm-pricing.js +61 -7
  162. package/src/lib/model-capabilities.js +10 -2
  163. package/src/lib/model-catalog-review.js +1 -0
  164. package/src/lib/model-context-catalog.js +26 -1
  165. package/src/lib/provider-http-error.js +16 -0
  166. package/src/lib/provider-options.js +38 -1
  167. package/src/lib/search-command.js +4 -1
  168. package/src/lib/stream-retry.js +209 -2
  169. package/src/lib/usage-pricing-context.js +100 -10
  170. package/src/runtime/agent-core.js +170 -38
  171. package/src/runtime/headless-runner.js +17 -0
  172. package/src/runtime/headless-stream.js +17 -0
  173. package/src/runtime/provider-stream-state.js +7 -0
  174. package/src/assets/web-panel/assets/ChatBubbleRenderer-Xtgfw3-c.js +0 -1
  175. package/src/assets/web-panel/assets/MarkdownRenderer-CRoDI77y.js +0 -1
  176. package/src/assets/web-panel/assets/Projects-BF3GtWny.js +0 -1
  177. package/src/assets/web-panel/assets/devWarning-D502_Z3w.js +0 -1
  178. package/src/assets/web-panel/assets/index-BrQ4nI4W.js +0 -1
  179. package/src/assets/web-panel/assets/index-C0_sewGO.js +0 -1
@@ -1,11 +1,52 @@
1
1
  import {
2
2
  DOCUMENTED_OPENAI_MODELS,
3
+ DOCUMENTED_ANTHROPIC_MODELS,
3
4
  GPT6_PRICING_TERMS,
4
5
  } from "./model-context-catalog.js";
5
6
 
7
+ /** Keep TTL evidence distinct from the aggregate cache-write count. */
8
+ export function projectCacheCreationUsage(usage = {}) {
9
+ if (usage.cacheCreationInvalid === true)
10
+ return { cacheCreationInvalid: true };
11
+ if (
12
+ Object.hasOwn(usage, "cache_creation_input_tokens") &&
13
+ Object.hasOwn(usage, "cacheCreationTokens") &&
14
+ usage.cache_creation_input_tokens !== usage.cacheCreationTokens
15
+ )
16
+ return { cacheCreationInvalid: true };
17
+ const nested = usage.cache_creation;
18
+ const hasFlat =
19
+ Object.hasOwn(usage, "cacheCreation5mTokens") ||
20
+ Object.hasOwn(usage, "cacheCreation1hTokens");
21
+ if (!Object.hasOwn(usage, "cache_creation") && !hasFlat) return {};
22
+ if (
23
+ Object.hasOwn(usage, "cache_creation") &&
24
+ (nested === null || typeof nested !== "object" || Array.isArray(nested))
25
+ )
26
+ return { cacheCreationInvalid: true };
27
+ const five = nested?.ephemeral_5m_input_tokens ?? usage.cacheCreation5mTokens;
28
+ const hour = nested?.ephemeral_1h_input_tokens ?? usage.cacheCreation1hTokens;
29
+ const total = usage.cache_creation_input_tokens ?? usage.cacheCreationTokens;
30
+ if (
31
+ ![five, hour, total].every(
32
+ (value) => Number.isSafeInteger(value) && value >= 0,
33
+ ) ||
34
+ five + hour !== total ||
35
+ (hasFlat &&
36
+ nested != null &&
37
+ (five !== usage.cacheCreation5mTokens ||
38
+ hour !== usage.cacheCreation1hTokens))
39
+ ) {
40
+ return { cacheCreationInvalid: true };
41
+ }
42
+ return { cacheCreation5mTokens: five, cacheCreation1hTokens: hour };
43
+ }
44
+
6
45
  /** Only bounded, non-secret pricing labels may enter the durable usage ledger. */
7
46
  export function projectUsagePricingContext(usage = {}) {
8
- const projected = {};
47
+ const projected = projectCacheCreationUsage(usage);
48
+ if (usage.pricingContextInvalid === true)
49
+ projected.pricingContextInvalid = true;
9
50
  for (const [key, alias] of [
10
51
  ["service_tier", "serviceTier"],
11
52
  ["regional_processing", "regionalProcessing"],
@@ -31,23 +72,56 @@ export function projectUsagePricingContext(usage = {}) {
31
72
  projected[key] = value;
32
73
  }
33
74
  }
75
+ if (Object.hasOwn(usage, "inference_geo")) {
76
+ const geo = usage.inference_geo;
77
+ if (geo !== "us" && geo !== "global") {
78
+ projected.inference_geo = "unknown";
79
+ projected.pricingContextInvalid = true;
80
+ } else {
81
+ if (
82
+ Object.hasOwn(projected, "regional_processing") &&
83
+ projected.regional_processing !== (geo === "us")
84
+ ) {
85
+ throw new TypeError(
86
+ "usage inference_geo conflicts with regional processing",
87
+ );
88
+ }
89
+ projected.inference_geo = geo;
90
+ projected.regional_processing = geo === "us";
91
+ }
92
+ }
34
93
  return projected;
35
94
  }
36
95
 
37
96
  /** Preserve per-request thresholds in a bounded set of aggregate price buckets. */
38
97
  export function mergeUsagePricingBucket(entry, usage) {
39
- if (
40
- String(entry.provider).toLowerCase() !== "openai" ||
41
- !DOCUMENTED_OPENAI_MODELS[String(entry.model).toLowerCase()]?.pricing
42
- )
43
- return;
98
+ const provider = String(entry.provider).toLowerCase();
99
+ const model = String(entry.model).toLowerCase();
100
+ const terms =
101
+ provider === "openai" && DOCUMENTED_OPENAI_MODELS[model]?.pricing
102
+ ? GPT6_PRICING_TERMS
103
+ : provider === "anthropic"
104
+ ? DOCUMENTED_ANTHROPIC_MODELS[model]?.pricingTerms
105
+ : null;
106
+ if (!terms?.longContext) return;
44
107
  const metadata = projectUsagePricingContext(usage);
108
+ const pricingContextInvalid =
109
+ metadata.pricingContextInvalid === true ||
110
+ (provider === "anthropic" &&
111
+ model === "claude-haiku-5-5" &&
112
+ metadata.regional_processing == null);
45
113
  const promptTokens =
46
114
  usage.requestInputTokens ??
47
115
  usage.inputTokens +
48
116
  (usage.cacheReadTokens || 0) +
49
117
  (usage.cacheCreationTokens || 0);
50
- const long = promptTokens > GPT6_PRICING_TERMS.longContext.threshold;
118
+ const long = promptTokens > terms.longContext.threshold;
119
+ const cache = projectCacheCreationUsage(usage);
120
+ const cacheEvidence = cache.cacheCreationInvalid
121
+ ? "invalid"
122
+ : cache.cacheCreation5mTokens != null
123
+ ? "split"
124
+ : "missing";
51
125
  const serviceTier = metadata.service_tier || "standard";
52
126
  const regionalProcessing = metadata.regional_processing === true;
53
127
  entry.pricingBuckets ||= [];
@@ -55,8 +129,9 @@ export function mergeUsagePricingBucket(entry, usage) {
55
129
  (item) =>
56
130
  item.serviceTier === serviceTier &&
57
131
  item.regionalProcessing === regionalProcessing &&
58
- item.requestInputTokens > GPT6_PRICING_TERMS.longContext.threshold ===
59
- long,
132
+ (item.pricingContextInvalid === true) === pricingContextInvalid &&
133
+ (item.cacheEvidence || "missing") === cacheEvidence &&
134
+ item.requestInputTokens > terms.longContext.threshold === long,
60
135
  );
61
136
  if (!bucket) {
62
137
  bucket = {
@@ -69,6 +144,18 @@ export function mergeUsagePricingBucket(entry, usage) {
69
144
  serviceTier,
70
145
  regionalProcessing,
71
146
  requestInputTokens: promptTokens,
147
+ ...(pricingContextInvalid ? { pricingContextInvalid: true } : {}),
148
+ ...(provider === "anthropic"
149
+ ? {
150
+ cacheEvidence,
151
+ ...(cacheEvidence === "split"
152
+ ? { cacheCreation5mTokens: 0, cacheCreation1hTokens: 0 }
153
+ : {}),
154
+ ...(cacheEvidence === "invalid"
155
+ ? { cacheCreationInvalid: true }
156
+ : {}),
157
+ }
158
+ : {}),
72
159
  };
73
160
  entry.pricingBuckets.push(bucket);
74
161
  }
@@ -79,8 +166,11 @@ export function mergeUsagePricingBucket(entry, usage) {
79
166
  "cacheCreationTokens",
80
167
  "totalTokens",
81
168
  "calls",
169
+ ...(cacheEvidence === "split"
170
+ ? ["cacheCreation5mTokens", "cacheCreation1hTokens"]
171
+ : []),
82
172
  ]) {
83
- const value = usage[key] ?? (key === "calls" ? 1 : 0);
173
+ const value = cache[key] ?? usage[key] ?? (key === "calls" ? 1 : 0);
84
174
  if (
85
175
  !Number.isSafeInteger(value) ||
86
176
  value < 0 ||
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import fs from "fs";
18
+ import { isUtf8 } from "node:buffer";
18
19
  import {
19
20
  _isNonNegativeSafeInteger,
20
21
  _providerUsageCount,
@@ -59,6 +60,8 @@ import {
59
60
  TASK_RECOVERY_TOOLS,
60
61
  } from "../lib/task-progress-tracker.js";
61
62
  import { TOOL_RECOVERY_PAUSED_CODE } from "../lib/tool-recovery-result.js";
63
+ import { haiku55ThinkingParams } from "../lib/provider-options.js";
64
+ import { projectUsagePricingContext } from "../lib/usage-pricing-context.js";
62
65
  import broker from "../lib/process-execution-broker/index.js";
63
66
  import os from "os";
64
67
  import { createHash, randomUUID } from "node:crypto";
@@ -153,6 +156,10 @@ import {
153
156
  isRetryableStreamError,
154
157
  STREAM_RETRY_BASE_MS,
155
158
  resolveStreamRetryMax,
159
+ captureStreamRetryMetadata,
160
+ attachStreamRetryMetadata,
161
+ resolveStreamRetryDelay,
162
+ waitForStreamRetry,
156
163
  } from "../lib/stream-retry.js";
157
164
  import {
158
165
  annotateLines,
@@ -181,7 +188,7 @@ import {
181
188
  } from "../lib/unattended-action-policy.js";
182
189
  import {
183
190
  formatProviderHttpError,
184
- formatProviderResponseError,
191
+ createProviderResponseError,
185
192
  } from "../lib/provider-http-error.js";
186
193
  import { buildPermissionDecision } from "../lib/permission-decision.js";
187
194
  import { resolveSandboxPolicyPath } from "../lib/agent-sandbox.js";
@@ -2024,6 +2031,20 @@ function applyLiteralEdit(content, oldStr, newStr, replaceAll) {
2024
2031
  return { count, newContent };
2025
2032
  }
2026
2033
 
2034
+ // Edits derive their output from the entire existing file. A replacement
2035
+ // decoder would silently rewrite unrelated legacy or malformed bytes.
2036
+ function readUtf8ForEdit(filePath) {
2037
+ const bytes = fs.readFileSync(filePath);
2038
+ if (!isUtf8(bytes)) {
2039
+ return {
2040
+ error: "File is not valid UTF-8; text edits require valid UTF-8 bytes.",
2041
+ code: "CC_EDIT_INVALID_UTF8",
2042
+ };
2043
+ }
2044
+ // Buffer decoding preserves a valid UTF-8 BOM and literal U+FFFD characters.
2045
+ return { content: bytes.toString("utf8") };
2046
+ }
2047
+
2027
2048
  /**
2028
2049
  * Compute the content an edit tool WOULD write, without writing it — the
2029
2050
  * left/right sides for an IDE diff review. Mirrors the corresponding
@@ -2085,7 +2106,9 @@ export function computeProposedEdit(name, args = {}, cwd = process.cwd()) {
2085
2106
  }
2086
2107
  if (name === "edit_file") {
2087
2108
  if (!fs.existsSync(filePath)) return null;
2088
- const content = fs.readFileSync(filePath, "utf8");
2109
+ const decoded = readUtf8ForEdit(filePath);
2110
+ if (decoded.error) return null;
2111
+ const content = decoded.content;
2089
2112
  if (
2090
2113
  typeof args.old_string !== "string" ||
2091
2114
  args.old_string === "" ||
@@ -2113,7 +2136,9 @@ export function computeProposedEdit(name, args = {}, cwd = process.cwd()) {
2113
2136
  if (name === "edit_file_hashed") {
2114
2137
  if (!fs.existsSync(filePath)) return null;
2115
2138
  if (!args.anchor_hash || typeof args.new_line !== "string") return null;
2116
- const original = fs.readFileSync(filePath, "utf8");
2139
+ const decoded = readUtf8ForEdit(filePath);
2140
+ if (decoded.error) return null;
2141
+ const original = decoded.content;
2117
2142
  const result = replaceByHash(original, {
2118
2143
  anchorHash: args.anchor_hash,
2119
2144
  expectedLine: args.expected_line,
@@ -5835,7 +5860,9 @@ async function executeToolInner(
5835
5860
  if (!fs.existsSync(filePath)) {
5836
5861
  return attachDescriptor({ error: `Notebook not found: ${filePath}` });
5837
5862
  }
5838
- const original = fs.readFileSync(filePath, "utf8");
5863
+ const decoded = readUtf8ForEdit(filePath);
5864
+ if (decoded.error) return attachDescriptor(decoded);
5865
+ const original = decoded.content;
5839
5866
  const res = editNotebookCell(original, args);
5840
5867
  if (res.error) return attachDescriptor({ error: res.error });
5841
5868
  const wrote = writeFileVerified(filePath, res.text);
@@ -5871,7 +5898,9 @@ async function executeToolInner(
5871
5898
  }
5872
5899
  const staleEdit = _checkFileFreshness(filePath);
5873
5900
  if (staleEdit) return attachDescriptor({ error: staleEdit });
5874
- const content = fs.readFileSync(filePath, "utf8");
5901
+ const decoded = readUtf8ForEdit(filePath);
5902
+ if (decoded.error) return attachDescriptor(decoded);
5903
+ const content = decoded.content;
5875
5904
  const replaceAll = args.replace_all === true;
5876
5905
  const { count, newContent } = applyLiteralEdit(
5877
5906
  content,
@@ -5971,7 +6000,9 @@ async function executeToolInner(
5971
6000
  }
5972
6001
  const staleHashed = _checkFileFreshness(filePath);
5973
6002
  if (staleHashed) return attachDescriptor({ error: staleHashed });
5974
- const original = fs.readFileSync(filePath, "utf8");
6003
+ const decoded = readUtf8ForEdit(filePath);
6004
+ if (decoded.error) return attachDescriptor(decoded);
6005
+ const original = decoded.content;
5975
6006
  const result = replaceByHash(original, {
5976
6007
  anchorHash: args.anchor_hash,
5977
6008
  expectedLine: args.expected_line,
@@ -11893,7 +11924,7 @@ export async function chatWithTools(rawMessages, options) {
11893
11924
  }),
11894
11925
  });
11895
11926
  if (!response.ok) {
11896
- throw new Error(await formatProviderResponseError("ollama", response));
11927
+ throw await createProviderResponseError("ollama", response);
11897
11928
  }
11898
11929
  const data = await response.json();
11899
11930
  if (
@@ -11962,10 +11993,16 @@ export async function chatWithTools(rawMessages, options) {
11962
11993
  messages: _toAnthropicMessages(otherMsgs),
11963
11994
  tools: anthropicTools,
11964
11995
  };
11965
- // Extended thinking — OPT-IN via options.thinking; off by default so the
11966
- // request is byte-identical to before. Model-aware (adaptive+effort on Opus
11967
- // 4.6+/Sonnet 4.6, legacy enabled+budget else; nothing on Haiku). temperature
11968
- // is never sent. RUNTIME-UNVERIFIED: no Anthropic key here to E2E the
11996
+ if (
11997
+ effModel.toLowerCase() === "claude-haiku-5-5" &&
11998
+ body.messages.at(-1)?.role === "assistant"
11999
+ ) {
12000
+ throw new TypeError("Haiku 5.5 does not support assistant prefill.");
12001
+ }
12002
+ // Legacy models retain opt-in thinking. Exact Haiku 5.5 uses its documented
12003
+ // adaptive/medium default and accepts an explicit disabled setting.
12004
+ // Sampling parameters are never sent. RUNTIME-UNVERIFIED: no Anthropic key
12005
+ // here to E2E the
11969
12006
  // thinking-block signature replay (see cli_claude_code_parity_landed memory).
11970
12007
  const thinkingParams = _anthropicThinkingParams(
11971
12008
  effModel,
@@ -12040,12 +12077,17 @@ export async function chatWithTools(rawMessages, options) {
12040
12077
  });
12041
12078
 
12042
12079
  if (!response.ok) {
12043
- throw new Error(await formatProviderResponseError("anthropic", response));
12080
+ throw await createProviderResponseError("anthropic", response);
12044
12081
  }
12045
12082
 
12046
12083
  const data = await response.json();
12047
12084
  const normalized = _normalizeAnthropicResponse(data);
12048
12085
  if (_hasCompleteProviderUsage(data.usage)) {
12086
+ const cacheCreationTokens = _optionalProviderUsageCount(
12087
+ data.usage,
12088
+ "cache_creation_input_tokens",
12089
+ "cache_creation_tokens",
12090
+ );
12049
12091
  normalized.usage = {
12050
12092
  // With prompt caching, Anthropic splits input into uncached
12051
12093
  // `input_tokens` + cache read/write — capture all three so cost
@@ -12066,11 +12108,11 @@ export async function chatWithTools(rawMessages, options) {
12066
12108
  "cache_read_input_tokens",
12067
12109
  "cache_read_tokens",
12068
12110
  ),
12069
- cache_creation_input_tokens: _optionalProviderUsageCount(
12070
- data.usage,
12071
- "cache_creation_input_tokens",
12072
- "cache_creation_tokens",
12073
- ),
12111
+ cache_creation_input_tokens: cacheCreationTokens,
12112
+ ...projectUsagePricingContext({
12113
+ ...data.usage,
12114
+ cache_creation_input_tokens: cacheCreationTokens,
12115
+ }),
12074
12116
  };
12075
12117
  }
12076
12118
  return normalized;
@@ -12191,7 +12233,7 @@ export async function chatWithTools(rawMessages, options) {
12191
12233
  body: JSON.stringify(responseBody),
12192
12234
  });
12193
12235
  if (!response.ok) {
12194
- throw new Error(await formatProviderResponseError(provider, response));
12236
+ throw await createProviderResponseError(provider, response);
12195
12237
  }
12196
12238
  const data = await response.json();
12197
12239
  const out = normalizeOpenAIResponsesResponse(data);
@@ -12272,7 +12314,7 @@ export async function chatWithTools(rawMessages, options) {
12272
12314
  });
12273
12315
 
12274
12316
  if (!response.ok) {
12275
- throw new Error(await formatProviderResponseError(provider, response));
12317
+ throw await createProviderResponseError(provider, response);
12276
12318
  }
12277
12319
 
12278
12320
  const data = await response.json();
@@ -12359,9 +12401,11 @@ function _ollamaInitState() {
12359
12401
 
12360
12402
  function _streamUiCallbacks(onToken, onThinking) {
12361
12403
  let pending = [];
12404
+ let visible = false;
12362
12405
  const capture = (callback) =>
12363
12406
  typeof callback === "function"
12364
12407
  ? (value) => {
12408
+ if (typeof value === "string" && value.length > 0) visible = true;
12365
12409
  try {
12366
12410
  const result = callback(value);
12367
12411
  if (result && typeof result.then === "function") {
@@ -12375,6 +12419,7 @@ function _streamUiCallbacks(onToken, onThinking) {
12375
12419
  return {
12376
12420
  onToken: capture(onToken),
12377
12421
  onThinking: capture(onThinking),
12422
+ hasVisibleOutput: () => visible,
12378
12423
  async settle() {
12379
12424
  if (pending.length === 0) return;
12380
12425
  const current = pending;
@@ -12478,11 +12523,17 @@ export function _accumulateOllamaStream(lines, onToken) {
12478
12523
  * Parity with Claude-Code 2.1.179 ("preserving partial responses instead of
12479
12524
  * showing raw errors"). Pure + exported for unit tests.
12480
12525
  */
12481
- export function _streamErrorDisposition(err, signal, partialText) {
12526
+ export function _streamErrorDisposition(
12527
+ err,
12528
+ signal,
12529
+ partialText,
12530
+ visible = false,
12531
+ ) {
12482
12532
  if (err?.isOutputBackpressureFailure === true) return "rethrow";
12483
12533
  if (isAbortError(err)) return "rethrow";
12484
12534
  if (signal && signal.aborted) return "rethrow";
12485
- if (typeof partialText === "string" && partialText.trim()) return "preserve";
12535
+ if (visible || (typeof partialText === "string" && partialText.length > 0))
12536
+ return "preserve";
12486
12537
  return "rethrow";
12487
12538
  }
12488
12539
 
@@ -12547,16 +12598,22 @@ export async function _retryStreamingChat(streamFn, opts = {}) {
12547
12598
  const retries = opts.retries ?? resolveStreamRetryMax();
12548
12599
  const base = opts.baseDelayMs ?? STREAM_RETRY_BASE_MS;
12549
12600
  const signal = opts.signal;
12550
- const sleep = opts.sleep || ((ms) => new Promise((r) => setTimeout(r, ms)));
12551
12601
  const now = typeof opts.now === "function" ? opts.now : Date.now;
12552
12602
  let attempt = 0;
12553
12603
  for (;;) {
12604
+ throwIfAborted(signal);
12554
12605
  const attemptStartedAt = now();
12555
12606
  try {
12556
12607
  return await streamFn(attempt);
12557
12608
  } catch (err) {
12558
12609
  if (attempt >= retries || !_isRetryableStreamError(err, signal))
12559
12610
  throw err;
12611
+ const attemptEndedAt = now();
12612
+ const delayMs = resolveStreamRetryDelay(err, attempt + 1, {
12613
+ baseDelayMs: base,
12614
+ now: attemptEndedAt,
12615
+ });
12616
+ if (delayMs === null) throw err;
12560
12617
  attempt++;
12561
12618
  if (
12562
12619
  opts.strictRetryObserver === true &&
@@ -12571,7 +12628,7 @@ export async function _retryStreamingChat(streamFn, opts = {}) {
12571
12628
  if (typeof opts.onRetry === "function") {
12572
12629
  try {
12573
12630
  const observation = opts.onRetry(attempt, err, {
12574
- durationMs: Math.max(0, now() - attemptStartedAt),
12631
+ durationMs: Math.max(0, attemptEndedAt - attemptStartedAt),
12575
12632
  });
12576
12633
  if (observation && typeof observation.then === "function") {
12577
12634
  void Promise.resolve(observation).catch(() => {});
@@ -12600,8 +12657,7 @@ export async function _retryStreamingChat(streamFn, opts = {}) {
12600
12657
  }
12601
12658
  }
12602
12659
  }
12603
- await sleep(base * Math.pow(2, attempt - 1));
12604
- if (signal && signal.aborted) throw err; // user bailed during backoff
12660
+ await waitForStreamRetry(delayMs, signal, { sleep: opts.sleep });
12605
12661
  }
12606
12662
  }
12607
12663
  }
@@ -12724,8 +12780,9 @@ async function _chatOllamaStreaming(
12724
12780
  body: JSON.stringify({ ...body, stream: true }),
12725
12781
  });
12726
12782
  if (!response.ok) {
12727
- throw new Error(await formatProviderResponseError("ollama", response));
12783
+ throw await createProviderResponseError("ollama", response);
12728
12784
  }
12785
+ const retryMetadata = captureStreamRetryMetadata(response);
12729
12786
  const state = _ollamaInitState();
12730
12787
  const ui = _streamUiCallbacks(onToken);
12731
12788
  const reader = response.body.getReader();
@@ -12750,7 +12807,17 @@ async function _chatOllamaStreaming(
12750
12807
  await ui.settle();
12751
12808
  }
12752
12809
  } catch (err) {
12753
- if (_streamErrorDisposition(err, signal, state.content) === "rethrow")
12810
+ attachStreamRetryMetadata(err, retryMetadata);
12811
+ if (!ui.hasVisibleOutput() && !state.content && state.toolCalls?.length)
12812
+ err.noReplay = true;
12813
+ if (
12814
+ _streamErrorDisposition(
12815
+ err,
12816
+ signal,
12817
+ state.content,
12818
+ ui.hasVisibleOutput(),
12819
+ ) === "rethrow"
12820
+ )
12754
12821
  throw err;
12755
12822
  return _finalizeTruncatedStream(_ollamaFinalize, state);
12756
12823
  }
@@ -12775,8 +12842,9 @@ async function _chatAnthropicStreaming(
12775
12842
  body: JSON.stringify(body),
12776
12843
  });
12777
12844
  if (!response.ok) {
12778
- throw new Error(await formatProviderResponseError("anthropic", response));
12845
+ throw await createProviderResponseError("anthropic", response);
12779
12846
  }
12847
+ const retryMetadata = captureStreamRetryMetadata(response);
12780
12848
  const state = _anthropicInitState();
12781
12849
  const ui = _streamUiCallbacks(onToken, onThinking);
12782
12850
  const reader = response.body.getReader();
@@ -12801,7 +12869,21 @@ async function _chatAnthropicStreaming(
12801
12869
  await ui.settle();
12802
12870
  }
12803
12871
  } catch (err) {
12804
- if (_streamErrorDisposition(err, signal, state.text) === "rethrow")
12872
+ attachStreamRetryMetadata(err, retryMetadata);
12873
+ if (
12874
+ !ui.hasVisibleOutput() &&
12875
+ !state.text &&
12876
+ Object.values(state.blocks).some((block) => block.type === "tool_use")
12877
+ )
12878
+ err.noReplay = true;
12879
+ if (
12880
+ _streamErrorDisposition(
12881
+ err,
12882
+ signal,
12883
+ state.text,
12884
+ ui.hasVisibleOutput(),
12885
+ ) === "rethrow"
12886
+ )
12805
12887
  throw err;
12806
12888
  return _finalizeTruncatedStream(_anthropicFinalize, state);
12807
12889
  }
@@ -12833,8 +12915,9 @@ async function _chatOpenAIStreaming(
12833
12915
  body: JSON.stringify(body),
12834
12916
  });
12835
12917
  if (!response.ok) {
12836
- throw new Error(await formatProviderResponseError(provider, response));
12918
+ throw await createProviderResponseError(provider, response);
12837
12919
  }
12920
+ const retryMetadata = captureStreamRetryMetadata(response);
12838
12921
  const state = _openaiInitState();
12839
12922
  const ui = _streamUiCallbacks(onToken);
12840
12923
  const reader = response.body.getReader();
@@ -12859,7 +12942,17 @@ async function _chatOpenAIStreaming(
12859
12942
  await ui.settle();
12860
12943
  }
12861
12944
  } catch (err) {
12862
- if (_streamErrorDisposition(err, signal, state.text) === "rethrow")
12945
+ attachStreamRetryMetadata(err, retryMetadata);
12946
+ if (!ui.hasVisibleOutput() && !state.text && state.tools.length)
12947
+ err.noReplay = true;
12948
+ if (
12949
+ _streamErrorDisposition(
12950
+ err,
12951
+ signal,
12952
+ state.text,
12953
+ ui.hasVisibleOutput(),
12954
+ ) === "rethrow"
12955
+ )
12863
12956
  throw err;
12864
12957
  const out = _finalizeTruncatedStream(_openaiFinalize, state);
12865
12958
  const providerReceipt = _openAIProviderRequestReceipt(
@@ -12905,8 +12998,9 @@ async function _chatOpenAIResponsesStreaming(
12905
12998
  body: JSON.stringify(body),
12906
12999
  });
12907
13000
  if (!response.ok) {
12908
- throw new Error(await formatProviderResponseError("openai", response));
13001
+ throw await createProviderResponseError("openai", response);
12909
13002
  }
13003
+ const retryMetadata = captureStreamRetryMetadata(response);
12910
13004
  const state = createOpenAIResponsesStreamState();
12911
13005
  const ui = _streamUiCallbacks(onToken, onThinking);
12912
13006
  const reader = response.body.getReader();
@@ -12931,10 +13025,31 @@ async function _chatOpenAIResponsesStreaming(
12931
13025
  await ui.settle();
12932
13026
  }
12933
13027
  } catch (error) {
12934
- if (_streamErrorDisposition(error, signal, state.text) === "rethrow") {
13028
+ if (state.terminalError) throw state.terminalError;
13029
+ attachStreamRetryMetadata(error, retryMetadata);
13030
+ if (
13031
+ !ui.hasVisibleOutput() &&
13032
+ !state.text &&
13033
+ state.outputItems.some((item) => item?.type === "function_call")
13034
+ )
13035
+ error.noReplay = true;
13036
+ if (
13037
+ !state.normalized &&
13038
+ _streamErrorDisposition(
13039
+ error,
13040
+ signal,
13041
+ state.text,
13042
+ ui.hasVisibleOutput(),
13043
+ ) === "rethrow"
13044
+ ) {
12935
13045
  throw error;
12936
13046
  }
12937
- const out = _finalizeTruncatedStream(finalizeOpenAIResponsesStream, state);
13047
+ throwIfAborted(signal);
13048
+ if (isAbortError(error) || error?.isOutputBackpressureFailure === true)
13049
+ throw error;
13050
+ const out = state.normalized
13051
+ ? finalizeOpenAIResponsesStream(state)
13052
+ : _finalizeTruncatedStream(finalizeOpenAIResponsesStream, state);
12938
13053
  const responseId = out.responseId || state.responseId;
12939
13054
  delete out.responseId;
12940
13055
  const providerReceipt = _openAIProviderRequestReceipt(
@@ -13067,11 +13182,12 @@ export function _openAIResponsesReasoningParams(
13067
13182
 
13068
13183
  /**
13069
13184
  * Decide the Anthropic `thinking` request params for a model. Returns null
13070
- * (off) unless the caller opts in via options.thinking (true | "think" |
13071
- * "hard" | "ultra"). Model-aware per the Claude API:
13185
+ * (off) on legacy models unless the caller opts in via options.thinking
13186
+ * (true | "think" | "hard" | "ultra"). Model-aware per the Claude API:
13187
+ * - exact Haiku 5.5 → adaptive/medium by default, explicitly disableable
13072
13188
  * - Opus 4.6/4.7/4.8, Sonnet 4.6 → adaptive thinking + output_config.effort
13073
13189
  * - Sonnet 4.5 / Opus 4.0-4.5 / older → legacy enabled+budget (< max_tokens)
13074
- * - anything else (e.g. Haiku) → null (no thinking)
13190
+ * - other models, including older Haiku → null (no explicit thinking)
13075
13191
  * temperature is never added (it 400s on Opus 4.7/4.8). Note: `xhigh`/`max`
13076
13192
  * effort are Opus-tier — on Sonnet they may error; left to the caller's intent.
13077
13193
  * RUNTIME-UNVERIFIED — no Anthropic key to validate the wire shape live.
@@ -13082,9 +13198,10 @@ export function _anthropicThinkingParams(
13082
13198
  options = {},
13083
13199
  maxTokens = 8192,
13084
13200
  ) {
13201
+ const m = String(model || "").toLowerCase();
13202
+ if (m === "claude-haiku-5-5") return haiku55ThinkingParams(m, options);
13085
13203
  const want = options?.thinking;
13086
13204
  if (!want) return null; // off by default → request unchanged
13087
- const m = String(model || "").toLowerCase();
13088
13205
  const adaptive = /opus-4-(6|7|8)/.test(m) || /sonnet-4-6/.test(m);
13089
13206
  const legacy =
13090
13207
  /sonnet-4-5/.test(m) ||
@@ -16320,12 +16437,27 @@ export async function* agentLoop(messages, options) {
16320
16437
  toolName,
16321
16438
  earlyAuthorityDenial,
16322
16439
  );
16440
+ const preExecutionDenied =
16441
+ earlyAuthorityDenial.code === TOOL_RECOVERY_PAUSED_CODE;
16442
+ if (preExecutionDenied) {
16443
+ // Declare the rejected request without an execution/ledger boundary
16444
+ // or its arguments. Consumers can pair the refusal by provider ID.
16445
+ yield {
16446
+ type: "tool-pre-execution-denied",
16447
+ tool: toolName,
16448
+ tool_use_id: call.id,
16449
+ turn_id: `${runId}:t${budget.consumed}`,
16450
+ preExecutionDenied: true,
16451
+ execution_started: false,
16452
+ };
16453
+ }
16323
16454
  yield {
16324
16455
  type: "tool-result",
16325
16456
  tool: toolName,
16326
16457
  result: earlyAuthorityDenial,
16327
16458
  error: earlyAuthorityDenial.error,
16328
16459
  execution_started: false,
16460
+ ...(preExecutionDenied ? { preExecutionDenied: true } : {}),
16329
16461
  tool_use_id: call.id,
16330
16462
  turn_id: `${runId}:t${budget.consumed}`,
16331
16463
  permission_decision_id: decision?.id || null,
@@ -3231,6 +3231,19 @@ async function runAgentHeadlessInWorkspace(
3231
3231
  });
3232
3232
  break;
3233
3233
  }
3234
+ case "tool-pre-execution-denied": {
3235
+ // A request declaration is not an invocation: do not start a
3236
+ // side effect, telemetry call, or persisted compact tool record.
3237
+ emitStream({
3238
+ type: "tool_use",
3239
+ id: event.tool_use_id,
3240
+ tool: event.tool,
3241
+ args: {},
3242
+ preExecutionDenied: true,
3243
+ execution_started: false,
3244
+ });
3245
+ break;
3246
+ }
3234
3247
  case "tool-executing": {
3235
3248
  const telemetryToolId = runtimeToolCallId(event.tool_use_id);
3236
3249
  const line = ` [${event.tool}] ${formatToolArgs(event.tool, event.args)}`;
@@ -3352,6 +3365,10 @@ async function runAgentHeadlessInWorkspace(
3352
3365
  ...(event.execution_started === false
3353
3366
  ? { execution_started: false }
3354
3367
  : {}),
3368
+ ...(event.preExecutionDenied === true &&
3369
+ event.execution_started === false
3370
+ ? { preExecutionDenied: true }
3371
+ : {}),
3355
3372
  error: err,
3356
3373
  result: event.result,
3357
3374
  ...(event.permission_decision_id
@@ -990,6 +990,19 @@ async function runTurn(
990
990
  }
991
991
  turnBindingFeed?.handleEvent(event);
992
992
  switch (event.type) {
993
+ case "tool-pre-execution-denied": {
994
+ // Keep the request/result pair visible without plan/ledger execution
995
+ // bookkeeping and without exposing rejected request arguments.
996
+ emit({
997
+ type: "tool_use",
998
+ id: event.tool_use_id,
999
+ tool: event.tool,
1000
+ args: {},
1001
+ preExecutionDenied: true,
1002
+ execution_started: false,
1003
+ });
1004
+ break;
1005
+ }
993
1006
  case "tool-executing": {
994
1007
  // Additive protocol-v1 correlation id ("tu-<n>", session-scoped —
995
1008
  // agent-sdk docs/PROTOCOL.md §1.2.1): the matching tool_result below
@@ -1129,6 +1142,10 @@ async function runTurn(
1129
1142
  ...(event.execution_started === false
1130
1143
  ? { execution_started: false }
1131
1144
  : {}),
1145
+ ...(event.preExecutionDenied === true &&
1146
+ event.execution_started === false
1147
+ ? { preExecutionDenied: true }
1148
+ : {}),
1132
1149
  error: err,
1133
1150
  result: event.result,
1134
1151
  ...(event.permission_decision_id