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.
- package/README.md +19 -23
- package/package.json +1 -1
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DCIQFtF1.js → AIOps-Cd4iUOPt.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BxhHU3nE.js → ActionButton--ucr-zko.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DdM_307O.js → Analytics-DbejYMWk.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-C43-kSrh.js → AppLayout-CLgKxeGw.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B2Vp2Am6.js → Artifacts-CTT5BIL5.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-s-lYUfOp.js → Audit-DP-WBWe9.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DTE7Kzio.js → BackgroundAgents-B6VqheJk.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-9k1q4Mt6.js → Backup-VWJK5zim.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DlpUtK5R.js → BaseInput-YGFO9RHd.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CR9S8Rmb.js → Chat-CVfydnCd.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BICpB-qU.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DpFRu7Df.js → Checkbox-Bd5vKRMk.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BIl72E4Y.js → Codegen-DHNgPHvg.js} +1 -1
- package/src/assets/web-panel/assets/{Col-91tl_err.js → Col-CA2BYQ8T.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CswahO9-.js → Community-DnKJ-qpI.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-D9pfHmaM.js → Compact-C9BZ8t4r.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CXSZzAO9.js → Compliance-ByyQ2FOl.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CuT9RWTn.js → Cowork-rXTwXE_c.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-B71aJWDV.js → Cron-BuW-HODy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CcUuWyx8.js → Crosschain-OudNtbYW.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CtVVGOPL.js → DID-BQ6BxYNN.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CV7ZCYQq.js → Dashboard-Cz5HG8tz.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DKHxwLgE.js → Dropdown-BzclHOVv.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Bd03UIvv.js → EmailListRenderer-CbJETFdy.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-CTrG03B_.js → EvolutionSettings-Dx_pJG3d.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DXS4bS6Q.js → FamilyGuardDashboard-6JCS1MNg.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BODG2Szj.js → Federation-BrPkMYaf.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D32ccUqD.js → FormItemContext-Bhc9pobs.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-ClsyrKvF.js → GenericCardRenderer-BxOh07uQ.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DcM2yhbL.js → Git-D_idoujr.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BhUzM87n.js → Governance-ZGfIRE-x.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dq1n0Ifg.js → Inference-DpAmcwbw.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-dmmPwEks.js → KnowledgeGraph-D1S1UTgP.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CBSYrPmh.js → Logs-2sc8V5XV.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-575jjYE6.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Cfw7XLck.js → Marketplace-0xlFUKbe.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CNrZRy4n.js → McpTools-D25eJLGm.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BESjTxdd.js → Memory-BLRGd9hM.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Boyjo07i.js → MobileBridge-zpFINGzn.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BmxmpTWz.js → MobileProjects-Cbyd-8kx.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CBkrD0Fq.js → Mtc-DgXgUlHc.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BA7cAK8h.js → MtcAudit-DzcL-dKH.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-m0RGzkKO.js → Multisig-C3OrZ6VN.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D_TgzifU.js → NLProgramming-Bqp_vWA7.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Dr-Yr9LL.js → Notes-Dyn45-Ht.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DGanpkqO.js → NotificationSettings-CLjafGZr.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-D1FX50QY.js → OrderTableRenderer-Bx8wMauC.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DRbPg-gs.js → Organization-5gr9hyLm.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-flEO37z6.js → Overflow-BRdU02hT.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DqfqFbCW.js → P2P-DIi7fzh6.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Cmi5a5dW.js → PdhVaultBrowser-BCbS1KpA.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DBVRlvBW.js → Permissions-BjeP9VtA.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-gQqjPr9X.js → PersonalDataHub-y8PXOQUc.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-6HlifUc9.js → Pipeline-B0fL5uxY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-bm_2-Zwg.js → Privacy-C8jCDn8Z.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BJW3isuq.js → ProjectInit-B_L6Dc6V.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DD3yolz7.js → ProjectSettings-Bb1CYbZh.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CUSV10Cn.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CQA6WAK7.js → Providers-mBSTDJ0E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DOAwp5Xo.js → QrScannerModal-CHxgalvt.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-qeFXsAZT.js → QuickAsk-DI9KIMEV.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-zDWXwZN8.js → Recommend-B5_zW1JH.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-toe6Ip06.js → RemoteSession-BkH4bmM5.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-DRDi_Eqp.js → Reputation-DJrAqwAq.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Do2UbYkf.js → Row-xZ3MAM34.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B57C6_Sa.js → RssFeed-CCsrLLiu.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DfDyBpe9.js → Search-CTCRKvaP.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CulNxeAM.js → Security-D7joyfp2.js} +4 -4
- package/src/assets/web-panel/assets/{Services-COfAYvs4.js → Services-oqHPmTG4.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-0fn0T146.js → Skeleton-BR_32bTG.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-pPQgAhvJ.js → Skills-BoRz9mln.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CIsRmePR.js → Sla-UAGUHZ9b.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Bn01d-8b.js → SpeechSettings-DeP_rMgv.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Cx_Znk7L.js → SyncSettings-CSzzMmeA.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DvaskzpG.js → Tasks-CcqOLsLB.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DmHCEiDO.js → Templates-cDbkGSDG.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CqHyvnbW.js → Tenant-DmOy58cq.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DTt3yqWL.js → Terminal-CsRZH5vr.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BhkIxcR3.js → TimelineRenderer-BgJrk6HG.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-mhjYcBBP.js → Tokens-CCQglKDE.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-CdlMQfwX.js → Trigger-t-Gt3oBY.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Bzovg_Gw.js → Trust-DQgu2kI0.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-ph3EuYi7.js → UkeySign-Cod2WUGj.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bo2B4VZE.js → VideoEditing-SGN5zaVK.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BQTKsSUT.js → Wallet-CnLEL-LD.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-nJxsXNHV.js → WebAuthn-C2keUpD6.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CjH8g2N7.js → WorkflowEditor-B1GvrwWJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CkbNmnQD.js → chat-1E9_P_qY.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BY9JcObR.js → colors-DuU6Os4q.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Dzzq-d8n.js → compact-item-C5NfOAcM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DiJxxdTx.js → createContext-D4Fxz9qQ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-zDWbYMr7.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DaXPOw3D.js → hasIn-C6C49iFk.js} +1 -1
- package/src/assets/web-panel/assets/{index-Uh9SjtgW.js → index-AO6iDCSL.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4Sf1AMk.js → index-B-bb-R99.js} +1 -1
- package/src/assets/web-panel/assets/{index-cu1J4avY.js → index-B5lzRoHp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaylJfw6.js → index-BBVqlelF.js} +1 -1
- package/src/assets/web-panel/assets/index-BPBsZZnT.js +1 -0
- package/src/assets/web-panel/assets/{index-CWLpEg34.js → index-BU5mPkNX.js} +1 -1
- package/src/assets/web-panel/assets/{index-LRZSVBxC.js → index-BULggEX6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Djeh6rAb.js → index-BVE2wCeb.js} +1 -1
- package/src/assets/web-panel/assets/{index-B31oMRmK.js → index-BYg1dtne.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSqQyS9-.js → index-BZKRZYTX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnLO1_yN.js → index-B_ON9La1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Jmlk_lDX.js → index-Bk-paNL3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQvtlYUd.js → index-BlHkc48f.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvgMt6Io.js → index-BmvU4Tp_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbOOm8I8.js → index-BsH8mFp4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C_OMH_FT.js → index-Bu6qMjf4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BycyBM6g.js → index-C2nO02uW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlWg1bRA.js → index-C7mh6xlu.js} +1 -1
- package/src/assets/web-panel/assets/{index-i9eu2Kir.js → index-CDVwN9Sv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWT9-E5b.js → index-CJS6GTpv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqOkm6kW.js → index-CQJoh5rw.js} +1 -1
- package/src/assets/web-panel/assets/{index-7YVCjSqG.js → index-CXb8gEWh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDnqjZa2.js → index-CXn-e3ki.js} +1 -1
- package/src/assets/web-panel/assets/{index-Igq-72Ep.js → index-CpiOzt7U.js} +1 -1
- package/src/assets/web-panel/assets/index-CtGQDg7m.js +1 -0
- package/src/assets/web-panel/assets/{index-BqCHe05H.js → index-D1TXgNPA.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_Eoh740.js → index-DFK6PTGJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-EiaWq1TH.js → index-DP2DCKD-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVblRqUN.js → index-DPzunJER.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bhsxh-rH.js → index-DSypQU1h.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbmHmeP-.js → index-DZgT7pH-.js} +1 -1
- package/src/assets/web-panel/assets/{index-dC2JACyJ.js → index-Dh-vezHe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHeHyLRM.js → index-DpaGe-dr.js} +3 -3
- package/src/assets/web-panel/assets/{index-6Z6Z4UwN.js → index-HQXFl8fh.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGvIb1Sr.js → index-bW6vfpLH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DObXhPhH.js → index-cnDfwWU5.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dl8U-0hn.js → index-gh11zJ9h.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAzfu6k5.js → index-jFg3CPlQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-C6XSCXeb.js → index-lNmDaf3J.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B0WuG3fa.js → initDefaultProps-3DSfnIpD.js} +1 -1
- package/src/assets/web-panel/assets/{motion-1r5YB22w.js → motion-DxGLmgA0.js} +1 -1
- package/src/assets/web-panel/assets/{move-CvtXWA_V.js → move-DrlLG6m5.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-ChedmEE_.js → mtc-parser-BITbrJSb.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DpEA3MP0.js → omit-D7k5vIbk.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BWgrUZF6.js → pickAttrs-BJSvYFWo.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BWfo_VbI.js → placementArrow-Bf4to1jA.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CRft03Vk.js → responsiveObserve-BXzeyzTa.js} +1 -1
- package/src/assets/web-panel/assets/{slide-l5LeXusH.js → slide-DLzNUNdj.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CCEC0JR-.js → statusUtils-wBBnrRm_.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Bw5Gw_2w.js → styleChecker-BnmJzXNr.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BAuxWB7K.js → useFlexGapSupport-DrN8MrJb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CxUP97Cw.js → useFs-dnkYGkjY.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BJDjT4Sy.js → usePersonalDataHub-k_xkv7-k.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BcCsFzIs.js → vnode-B-v8PXpK.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-MLmG09h6.js → zoom-Coue8wAK.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +26 -0
- package/src/harness/worktree-isolator.js +20 -8
- package/src/lib/chat-core.js +57 -25
- package/src/lib/cost-budget.js +8 -0
- package/src/lib/eval/verify01-execution-window.js +70 -0
- package/src/lib/eval/verify01-execution.js +9 -1
- package/src/lib/eval/verify01-host-capture.js +6 -2
- package/src/lib/llm-pricing.js +61 -7
- package/src/lib/model-capabilities.js +10 -2
- package/src/lib/model-catalog-review.js +1 -0
- package/src/lib/model-context-catalog.js +26 -1
- package/src/lib/provider-http-error.js +16 -0
- package/src/lib/provider-options.js +38 -1
- package/src/lib/search-command.js +4 -1
- package/src/lib/stream-retry.js +209 -2
- package/src/lib/usage-pricing-context.js +100 -10
- package/src/runtime/agent-core.js +170 -38
- package/src/runtime/headless-runner.js +17 -0
- package/src/runtime/headless-stream.js +17 -0
- package/src/runtime/provider-stream-state.js +7 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Xtgfw3-c.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-CRoDI77y.js +0 -1
- package/src/assets/web-panel/assets/Projects-BF3GtWny.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D502_Z3w.js +0 -1
- package/src/assets/web-panel/assets/index-BrQ4nI4W.js +0 -1
- package/src/assets/web-panel/assets/index-C0_sewGO.js +0 -1
package/src/lib/llm-pricing.js
CHANGED
|
@@ -216,13 +216,18 @@ export function normalizePricingTerms(value) {
|
|
|
216
216
|
const allowed = new Set([
|
|
217
217
|
"cacheReadMultiplier",
|
|
218
218
|
"cacheWriteMultiplier",
|
|
219
|
+
"cacheWrite1hMultiplier",
|
|
219
220
|
"longContext",
|
|
220
221
|
"serviceMultipliers",
|
|
221
222
|
]);
|
|
222
223
|
if (!object(value) || Reflect.ownKeys(value).some((key) => !allowed.has(key)))
|
|
223
224
|
fail();
|
|
224
225
|
const result = {};
|
|
225
|
-
for (const key of [
|
|
226
|
+
for (const key of [
|
|
227
|
+
"cacheReadMultiplier",
|
|
228
|
+
"cacheWriteMultiplier",
|
|
229
|
+
"cacheWrite1hMultiplier",
|
|
230
|
+
]) {
|
|
226
231
|
if (!Object.hasOwn(value, key)) continue;
|
|
227
232
|
if (!finite(value[key])) fail();
|
|
228
233
|
result[key] = value[key];
|
|
@@ -289,8 +294,15 @@ export function lookupRate(provider, model, table = PRICE_TABLE) {
|
|
|
289
294
|
// An unrecognized new generation must not inherit an older family price.
|
|
290
295
|
// Explicit operator overrides remain authoritative.
|
|
291
296
|
if (
|
|
292
|
-
|
|
293
|
-
|
|
297
|
+
e.match === "haiku" &&
|
|
298
|
+
/(?:^|[.:/])(?:claude-)?haiku-(?:[5-9]|\d{2,})(?:[.-]|$)/u.test(m) &&
|
|
299
|
+
!e.explicitOverride
|
|
300
|
+
)
|
|
301
|
+
continue;
|
|
302
|
+
if (
|
|
303
|
+
["opus", "sonnet", "haiku"].includes(e.match) &&
|
|
304
|
+
Number(/^claude-(?:opus|sonnet|haiku)-(\d+)(?:[.-]|$)/u.exec(m)?.[1]) >=
|
|
305
|
+
5 &&
|
|
294
306
|
!e.explicitOverride
|
|
295
307
|
)
|
|
296
308
|
continue;
|
|
@@ -337,18 +349,42 @@ export function estimateCost({
|
|
|
337
349
|
outputTokens = 0,
|
|
338
350
|
cacheReadTokens = 0,
|
|
339
351
|
cacheCreationTokens = 0,
|
|
352
|
+
cacheCreation5mTokens,
|
|
353
|
+
cacheCreation1hTokens,
|
|
354
|
+
cacheCreationInvalid = false,
|
|
355
|
+
pricingContextInvalid = false,
|
|
340
356
|
requestInputTokens,
|
|
341
357
|
serviceTier = "standard",
|
|
342
358
|
regionalProcessing = false,
|
|
343
359
|
table,
|
|
344
360
|
} = {}) {
|
|
345
361
|
const rate = lookupRate(provider, model, table);
|
|
362
|
+
const splitPresent =
|
|
363
|
+
cacheCreation5mTokens != null || cacheCreation1hTokens != null;
|
|
364
|
+
const splitValid =
|
|
365
|
+
splitPresent &&
|
|
366
|
+
Number.isSafeInteger(cacheCreation5mTokens) &&
|
|
367
|
+
cacheCreation5mTokens >= 0 &&
|
|
368
|
+
Number.isSafeInteger(cacheCreation1hTokens) &&
|
|
369
|
+
cacheCreation1hTokens >= 0 &&
|
|
370
|
+
cacheCreation5mTokens + cacheCreation1hTokens === cacheCreationTokens;
|
|
371
|
+
const missingCacheEvidence =
|
|
372
|
+
cacheCreationInvalid ||
|
|
373
|
+
(splitPresent && !splitValid) ||
|
|
374
|
+
(rate?.terms?.cacheWrite1hMultiplier != null &&
|
|
375
|
+
cacheCreationTokens > 0 &&
|
|
376
|
+
!splitValid);
|
|
346
377
|
const tierMultiplier = rate?.terms?.serviceMultipliers
|
|
347
378
|
? Object.hasOwn(rate.terms.serviceMultipliers, serviceTier)
|
|
348
379
|
? rate.terms.serviceMultipliers[serviceTier]
|
|
349
380
|
: null
|
|
350
381
|
: 1;
|
|
351
|
-
if (
|
|
382
|
+
if (
|
|
383
|
+
!rate ||
|
|
384
|
+
tierMultiplier == null ||
|
|
385
|
+
missingCacheEvidence ||
|
|
386
|
+
pricingContextInvalid
|
|
387
|
+
) {
|
|
352
388
|
return {
|
|
353
389
|
inputCost: 0,
|
|
354
390
|
outputCost: 0,
|
|
@@ -384,9 +420,14 @@ export function estimateCost({
|
|
|
384
420
|
inputMultiplier *
|
|
385
421
|
multiplier;
|
|
386
422
|
const cacheCreationCost =
|
|
387
|
-
(
|
|
423
|
+
((splitValid
|
|
424
|
+
? cacheCreation5mTokens *
|
|
425
|
+
(rate.terms?.cacheWriteMultiplier ?? CACHE_WRITE_MULTIPLIER) +
|
|
426
|
+
cacheCreation1hTokens * (rate.terms?.cacheWrite1hMultiplier ?? 2)
|
|
427
|
+
: Number(cacheCreationTokens) *
|
|
428
|
+
(rate.terms?.cacheWriteMultiplier ?? CACHE_WRITE_MULTIPLIER)) /
|
|
429
|
+
1e6) *
|
|
388
430
|
rate.in *
|
|
389
|
-
(rate.terms?.cacheWriteMultiplier ?? CACHE_WRITE_MULTIPLIER) *
|
|
390
431
|
inputMultiplier *
|
|
391
432
|
multiplier;
|
|
392
433
|
return {
|
|
@@ -419,6 +460,15 @@ export function priceRollup(aggregate, { table } = {}) {
|
|
|
419
460
|
outputTokens: row.outputTokens,
|
|
420
461
|
cacheReadTokens: row.cacheReadTokens,
|
|
421
462
|
cacheCreationTokens: row.cacheCreationTokens,
|
|
463
|
+
cacheCreation5mTokens: row.cacheCreation5mTokens,
|
|
464
|
+
cacheCreation1hTokens: row.cacheCreation1hTokens,
|
|
465
|
+
cacheCreationInvalid: row.cacheCreationInvalid,
|
|
466
|
+
pricingContextInvalid:
|
|
467
|
+
row.pricingContextInvalid === true ||
|
|
468
|
+
(String(row.provider).toLowerCase() === "anthropic" &&
|
|
469
|
+
String(row.model).toLowerCase() === "claude-haiku-5-5" &&
|
|
470
|
+
row.regionalProcessing == null &&
|
|
471
|
+
row.regional_processing == null),
|
|
422
472
|
serviceTier: row.serviceTier ?? row.service_tier ?? "standard",
|
|
423
473
|
regionalProcessing:
|
|
424
474
|
row.regionalProcessing ?? row.regional_processing ?? false,
|
|
@@ -479,7 +529,11 @@ export function priceRollup(aggregate, { table } = {}) {
|
|
|
479
529
|
for (const row of byModel) {
|
|
480
530
|
if (row.matched) {
|
|
481
531
|
totalCost += row.cost;
|
|
482
|
-
} else if (
|
|
532
|
+
} else if (
|
|
533
|
+
row.totalTokens > 0 ||
|
|
534
|
+
row.cacheReadTokens > 0 ||
|
|
535
|
+
row.cacheCreationTokens > 0
|
|
536
|
+
) {
|
|
483
537
|
unpriced.push({
|
|
484
538
|
provider: row.provider,
|
|
485
539
|
model: row.model,
|
|
@@ -98,15 +98,17 @@ export function resolveAgentOutputBudget({
|
|
|
98
98
|
const effectiveModel = model || "claude-sonnet-4-6";
|
|
99
99
|
const { maxTokens } = mergeProviderOptions("anthropic", effectiveModel);
|
|
100
100
|
const defaultCap = maxTokens || 8192;
|
|
101
|
+
const explicitCap =
|
|
102
|
+
effectiveModel === "claude-haiku-5-5" ? 128000 : defaultCap;
|
|
101
103
|
const requestMaxOutputTokens =
|
|
102
|
-
requested === null ? defaultCap : Math.min(
|
|
104
|
+
requested === null ? defaultCap : Math.min(explicitCap, requested);
|
|
103
105
|
return Object.freeze({
|
|
104
106
|
requestMaxOutputTokens,
|
|
105
107
|
plannedOutputReserveTokens: requestMaxOutputTokens,
|
|
106
108
|
outputReserveSource:
|
|
107
109
|
requested === null
|
|
108
110
|
? "anthropic-request-default"
|
|
109
|
-
: requested >
|
|
111
|
+
: requested > explicitCap
|
|
110
112
|
? "anthropic-request-clamp"
|
|
111
113
|
: "explicit-request-cap",
|
|
112
114
|
});
|
|
@@ -271,6 +273,12 @@ export function resolveModelCapabilityProfile({
|
|
|
271
273
|
runtimeVerified: false,
|
|
272
274
|
...output,
|
|
273
275
|
advertisedMaxOutputTokens: documented?.advertisedMaxOutputTokens ?? null,
|
|
276
|
+
...(documented?.adaptiveThinkingDefault
|
|
277
|
+
? {
|
|
278
|
+
adaptiveThinkingDefault: true,
|
|
279
|
+
defaultReasoningEffort: documented.defaultReasoningEffort,
|
|
280
|
+
}
|
|
281
|
+
: {}),
|
|
274
282
|
...(documented?.reasoningEfforts
|
|
275
283
|
? { reasoningEfforts: [...documented.reasoningEfforts] }
|
|
276
284
|
: {}),
|
|
@@ -144,13 +144,38 @@ export const DOCUMENTED_OPENAI_MODELS = Object.freeze({
|
|
|
144
144
|
});
|
|
145
145
|
|
|
146
146
|
export const DOCUMENTED_ANTHROPIC_MODELS = Object.freeze({
|
|
147
|
+
"claude-haiku-5-5": Object.freeze({
|
|
148
|
+
contextWindowTokens: 1000000,
|
|
149
|
+
advertisedMaxOutputTokens: 128000,
|
|
150
|
+
reasoningEfforts: Object.freeze(["low", "medium", "high", "xhigh", "max"]),
|
|
151
|
+
defaultReasoningEffort: "medium",
|
|
152
|
+
adaptiveThinkingDefault: true,
|
|
153
|
+
pricing: Object.freeze({ in: 0.1, out: 0.5 }),
|
|
154
|
+
pricingTerms: Object.freeze({
|
|
155
|
+
cacheReadMultiplier: 0.1,
|
|
156
|
+
cacheWriteMultiplier: 1.25,
|
|
157
|
+
cacheWrite1hMultiplier: 2,
|
|
158
|
+
longContext: Object.freeze({
|
|
159
|
+
threshold: 100000,
|
|
160
|
+
inputMultiplier: 5,
|
|
161
|
+
outputMultiplier: 5,
|
|
162
|
+
}),
|
|
163
|
+
serviceMultipliers: Object.freeze({ standard: 1, default: 1 }),
|
|
164
|
+
}),
|
|
165
|
+
sources: Object.freeze([
|
|
166
|
+
"https://platform.claude.com/docs/en/models/haiku-5-5/overview",
|
|
167
|
+
"https://platform.claude.com/docs/en/models/haiku-5-5/migration-guide",
|
|
168
|
+
"https://platform.claude.com/docs/en/about-claude/pricing",
|
|
169
|
+
]),
|
|
170
|
+
}),
|
|
147
171
|
"claude-sonnet-5-5": Object.freeze({
|
|
148
172
|
contextWindowTokens: 1000000,
|
|
149
173
|
advertisedMaxOutputTokens: null,
|
|
150
174
|
pricing: Object.freeze({ in: 2, out: 10 }),
|
|
151
|
-
pricingTerms: Object.freeze({ cacheReadMultiplier: 0.
|
|
175
|
+
pricingTerms: Object.freeze({ cacheReadMultiplier: 0.05 }),
|
|
152
176
|
sources: Object.freeze([
|
|
153
177
|
"https://code.claude.com/docs/en/changelog#2-1-284",
|
|
178
|
+
"https://platform.claude.com/docs/en/about-claude/pricing",
|
|
154
179
|
]),
|
|
155
180
|
}),
|
|
156
181
|
"claude-opus-5-5": Object.freeze({
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
* Keep structured provider diagnostics while redacting credential-shaped text.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
attachStreamRetryMetadata,
|
|
8
|
+
captureStreamRetryMetadata,
|
|
9
|
+
} from "./stream-retry.js";
|
|
10
|
+
|
|
6
11
|
function safePart(value, secrets = []) {
|
|
7
12
|
if (value == null) return "";
|
|
8
13
|
let text = String(value);
|
|
@@ -111,3 +116,14 @@ export async function formatProviderResponseError(
|
|
|
111
116
|
secrets,
|
|
112
117
|
});
|
|
113
118
|
}
|
|
119
|
+
|
|
120
|
+
/** Keep response status authoritative even if reading its error body fails. */
|
|
121
|
+
export async function createProviderResponseError(provider, response, options) {
|
|
122
|
+
const metadata = captureStreamRetryMetadata(response);
|
|
123
|
+
let message = await formatProviderResponseError(provider, response, options);
|
|
124
|
+
const remaining = metadata.retryAfterAt - Date.now();
|
|
125
|
+
if (Number.isFinite(remaining) && remaining > 0) {
|
|
126
|
+
message += ` Retry-After: wait at least ${Math.ceil(remaining / 1000)}s before an explicit retry.`;
|
|
127
|
+
}
|
|
128
|
+
return attachStreamRetryMetadata(new Error(message), metadata);
|
|
129
|
+
}
|
|
@@ -78,7 +78,11 @@ export function inferModelOverrides(modelId) {
|
|
|
78
78
|
return { maxTokens: 16384 };
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
if (modelId === "claude-haiku-5-5") {
|
|
82
|
+
return { maxTokens: 4096, temperature: undefined };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Older Claude Haiku — smaller output by default.
|
|
82
86
|
if (id.includes("haiku")) {
|
|
83
87
|
return { maxTokens: 4096 };
|
|
84
88
|
}
|
|
@@ -136,6 +140,39 @@ export function mergeProviderOptions(provider, modelId, callOverrides = {}) {
|
|
|
136
140
|
return deepMerge(defaults, modelLayer, callOverrides || {});
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
/** Exact Haiku 5.5 request contract; null leaves older model behavior intact. */
|
|
144
|
+
export function haiku55ThinkingParams(model, options = {}) {
|
|
145
|
+
if (model !== "claude-haiku-5-5") return null;
|
|
146
|
+
if (options.thinkingBudget != null) {
|
|
147
|
+
throw new TypeError(
|
|
148
|
+
"Haiku 5.5 supports adaptive thinking, not thinkingBudget",
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const intensity = {
|
|
152
|
+
think: "medium",
|
|
153
|
+
hard: "high",
|
|
154
|
+
"think-hard": "high",
|
|
155
|
+
harder: "high",
|
|
156
|
+
ultra: "xhigh",
|
|
157
|
+
ultrathink: "xhigh",
|
|
158
|
+
true: "high",
|
|
159
|
+
};
|
|
160
|
+
const effort =
|
|
161
|
+
options.thinkingEffort ?? intensity[options.thinking] ?? "medium";
|
|
162
|
+
if (!["low", "medium", "high", "xhigh", "max"].includes(effort)) {
|
|
163
|
+
throw new TypeError(`Unsupported Haiku 5.5 reasoning effort: ${effort}`);
|
|
164
|
+
}
|
|
165
|
+
if (options.thinking === false && ["xhigh", "max"].includes(effort)) {
|
|
166
|
+
throw new TypeError(
|
|
167
|
+
"Haiku 5.5 cannot disable thinking at xhigh or max effort",
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
thinking: { type: options.thinking === false ? "disabled" : "adaptive" },
|
|
172
|
+
output_config: { effort },
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
139
176
|
// =====================================================================
|
|
140
177
|
// provider-options V2 governance overlay (iter27)
|
|
141
178
|
// =====================================================================
|
|
@@ -37,7 +37,10 @@ export function buildSearchCommand({
|
|
|
37
37
|
isContent,
|
|
38
38
|
platform = process.platform,
|
|
39
39
|
}) {
|
|
40
|
-
|
|
40
|
+
if (typeof pattern !== "string" || pattern.length === 0) {
|
|
41
|
+
return { error: "search_files requires a non-empty string pattern" };
|
|
42
|
+
}
|
|
43
|
+
const pat = pattern;
|
|
41
44
|
|
|
42
45
|
if (platform === "win32") {
|
|
43
46
|
// cmd.exe has no reliable way to escape an embedded double-quote, and the
|
package/src/lib/stream-retry.js
CHANGED
|
@@ -12,11 +12,196 @@
|
|
|
12
12
|
* agent runtime.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
createAbortError,
|
|
17
|
+
isAbortError,
|
|
18
|
+
raceWithAbort,
|
|
19
|
+
throwIfAborted,
|
|
20
|
+
} from "./abort-utils.js";
|
|
16
21
|
|
|
17
22
|
/** Bounded auto-retry budget for streaming connection drops (Claude-Code 2.1.181). */
|
|
18
23
|
export const STREAM_RETRY_MAX = 2;
|
|
19
24
|
export const STREAM_RETRY_BASE_MS = 400;
|
|
25
|
+
export const STREAM_RETRY_MAX_DELAY_MS = 60_000;
|
|
26
|
+
|
|
27
|
+
function isFailureStatus(status) {
|
|
28
|
+
return Number.isInteger(status) && status >= 400 && status <= 599;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function retryAfterHeader(headers) {
|
|
32
|
+
if (!headers) return undefined;
|
|
33
|
+
if (typeof headers.get === "function") return headers.get("retry-after");
|
|
34
|
+
const entries = Object.entries(headers).filter(
|
|
35
|
+
([name]) => name.toLowerCase() === "retry-after",
|
|
36
|
+
);
|
|
37
|
+
// Multiple spellings or a list of values are ambiguous, not a delay.
|
|
38
|
+
return entries.length === 1 ? entries[0][1] : undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function httpDate(value, now) {
|
|
42
|
+
// Accept the three HTTP-date wire formats, not Date.parse's permissive
|
|
43
|
+
// numeric/local-date syntax (e.g. "-1", "1.5", or "2026-10-12").
|
|
44
|
+
const weekday = "(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)";
|
|
45
|
+
const month = "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
|
|
46
|
+
let match = new RegExp(
|
|
47
|
+
`^(${weekday}), (\\d{2}) ${month} (\\d{4}) (\\d{2}):(\\d{2}):(\\d{2}) GMT$`,
|
|
48
|
+
).exec(value);
|
|
49
|
+
let day, monthName, year, hour, minute, second, dayName;
|
|
50
|
+
if (match) {
|
|
51
|
+
[, dayName, day, monthName, year, hour, minute, second] = match;
|
|
52
|
+
} else {
|
|
53
|
+
match = new RegExp(
|
|
54
|
+
`^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\\d{2})-${month}-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2}) GMT$`,
|
|
55
|
+
).exec(value);
|
|
56
|
+
if (match) {
|
|
57
|
+
[, dayName, day, monthName, year, hour, minute, second] = match;
|
|
58
|
+
const currentYear = new Date(now).getUTCFullYear();
|
|
59
|
+
year = Math.floor(currentYear / 100) * 100 + Number(year);
|
|
60
|
+
if (year > currentYear + 50) year -= 100;
|
|
61
|
+
} else {
|
|
62
|
+
match = new RegExp(
|
|
63
|
+
`^(${weekday}) ${month} ( [1-9]|[12]\\d|3[01]) (\\d{2}):(\\d{2}):(\\d{2}) (\\d{4})$`,
|
|
64
|
+
).exec(value);
|
|
65
|
+
if (!match) return undefined;
|
|
66
|
+
[, dayName, monthName, day, hour, minute, second, year] = match;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const months = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ");
|
|
70
|
+
const monthIndex = months.indexOf(monthName);
|
|
71
|
+
const date = new Date(0);
|
|
72
|
+
date.setUTCFullYear(Number(year), monthIndex, Number(day));
|
|
73
|
+
date.setUTCHours(Number(hour), Number(minute), Number(second), 0);
|
|
74
|
+
// Reject normalized invalid calendar dates/times and mismatched weekdays.
|
|
75
|
+
if (
|
|
76
|
+
date.getUTCFullYear() !== Number(year) ||
|
|
77
|
+
date.getUTCMonth() !== monthIndex ||
|
|
78
|
+
date.getUTCDate() !== Number(day) ||
|
|
79
|
+
date.getUTCHours() !== Number(hour) ||
|
|
80
|
+
date.getUTCMinutes() !== Number(minute) ||
|
|
81
|
+
date.getUTCSeconds() !== Number(second) ||
|
|
82
|
+
date.toUTCString().slice(0, 3) !== dayName.slice(0, 3)
|
|
83
|
+
) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
return date.getTime();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Capture a deadline when headers arrive, before reading a slow response body.
|
|
90
|
+
* No metadata here grants permission to retry an HTTP/provider verdict.
|
|
91
|
+
*/
|
|
92
|
+
export function captureStreamRetryMetadata(response, now = Date.now()) {
|
|
93
|
+
const metadata = {};
|
|
94
|
+
if (Number.isInteger(response?.status)) metadata.status = response.status;
|
|
95
|
+
const raw = retryAfterHeader(response?.headers);
|
|
96
|
+
if (typeof raw !== "string" || !Number.isFinite(now)) return metadata;
|
|
97
|
+
const value = raw.trim();
|
|
98
|
+
if (/^\d+$/.test(value)) {
|
|
99
|
+
const seconds = Number(value);
|
|
100
|
+
const deadline = now + seconds * 1000;
|
|
101
|
+
// A valid but unrepresentably large delay is a refusal to retry within our
|
|
102
|
+
// budget, NOT a missing header. Infinity is an internal fail-closed sentinel.
|
|
103
|
+
metadata.retryAfterAt = Number.isSafeInteger(deadline)
|
|
104
|
+
? deadline
|
|
105
|
+
: Infinity;
|
|
106
|
+
} else {
|
|
107
|
+
const deadline = httpDate(value, now);
|
|
108
|
+
if (deadline !== undefined) metadata.retryAfterAt = deadline;
|
|
109
|
+
}
|
|
110
|
+
return metadata;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Preserve the original Error identity/code and the strongest known verdict. */
|
|
114
|
+
export function attachStreamRetryMetadata(error, metadata = {}) {
|
|
115
|
+
if (!error || (typeof error !== "object" && typeof error !== "function"))
|
|
116
|
+
return error;
|
|
117
|
+
const hasFailureStatus = [
|
|
118
|
+
error.status,
|
|
119
|
+
error.statusCode,
|
|
120
|
+
error.cause?.status,
|
|
121
|
+
error.cause?.statusCode,
|
|
122
|
+
].some(isFailureStatus);
|
|
123
|
+
if (!hasFailureStatus && Number.isInteger(metadata.status)) {
|
|
124
|
+
error.status = metadata.status;
|
|
125
|
+
}
|
|
126
|
+
if (
|
|
127
|
+
typeof metadata.retryAfterAt === "number" &&
|
|
128
|
+
!Number.isNaN(metadata.retryAfterAt) &&
|
|
129
|
+
metadata.retryAfterAt !== -Infinity
|
|
130
|
+
) {
|
|
131
|
+
const previous = [error.retryAfterAt, error.cause?.retryAfterAt].filter(
|
|
132
|
+
(value) => typeof value === "number" && !Number.isNaN(value),
|
|
133
|
+
);
|
|
134
|
+
error.retryAfterAt = Math.max(metadata.retryAfterAt, ...previous);
|
|
135
|
+
}
|
|
136
|
+
return error;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Resolve the wait AFTER retry eligibility is checked; null means give up.
|
|
140
|
+
* Never clamp a server deadline to a shorter wait or authorize an HTTP replay.
|
|
141
|
+
* Attempt 1 is the first retry, matching the existing retry observer contract.
|
|
142
|
+
*/
|
|
143
|
+
export function resolveStreamRetryDelay(error, attempt, options = {}) {
|
|
144
|
+
const base = options.baseDelayMs ?? STREAM_RETRY_BASE_MS;
|
|
145
|
+
const now = options.now ?? Date.now();
|
|
146
|
+
const max = options.maxDelayMs ?? STREAM_RETRY_MAX_DELAY_MS;
|
|
147
|
+
if (
|
|
148
|
+
!Number.isInteger(attempt) ||
|
|
149
|
+
attempt < 1 ||
|
|
150
|
+
!Number.isFinite(base) ||
|
|
151
|
+
base < 0 ||
|
|
152
|
+
!Number.isFinite(now) ||
|
|
153
|
+
!Number.isFinite(max) ||
|
|
154
|
+
max < 0
|
|
155
|
+
)
|
|
156
|
+
return null;
|
|
157
|
+
const deadlines = [error?.retryAfterAt, error?.cause?.retryAfterAt].filter(
|
|
158
|
+
(value) => typeof value === "number" && !Number.isNaN(value),
|
|
159
|
+
);
|
|
160
|
+
const delay = Math.ceil(
|
|
161
|
+
Math.max(base * 2 ** (attempt - 1), 0, ...deadlines.map((at) => at - now)),
|
|
162
|
+
);
|
|
163
|
+
// Node clamps overflowing setTimeout delays to 1ms. Reject rather than
|
|
164
|
+
// accidentally turning a requested long delay into an immediate replay.
|
|
165
|
+
return Number.isFinite(delay) && delay <= max && delay <= 2_147_483_647
|
|
166
|
+
? delay
|
|
167
|
+
: null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** Wait without keeping an obsolete backoff alive after user cancellation. */
|
|
171
|
+
export async function waitForStreamRetry(ms, signal, { sleep } = {}) {
|
|
172
|
+
throwIfAborted(signal);
|
|
173
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > 2_147_483_647)
|
|
174
|
+
throw new RangeError("Invalid streaming retry delay");
|
|
175
|
+
if (sleep) {
|
|
176
|
+
await raceWithAbort(
|
|
177
|
+
Promise.resolve().then(() => {
|
|
178
|
+
throwIfAborted(signal);
|
|
179
|
+
return sleep(ms);
|
|
180
|
+
}),
|
|
181
|
+
signal,
|
|
182
|
+
);
|
|
183
|
+
throwIfAborted(signal);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
await new Promise((resolve, reject) => {
|
|
187
|
+
let timer;
|
|
188
|
+
const cleanup = () => {
|
|
189
|
+
clearTimeout(timer);
|
|
190
|
+
signal?.removeEventListener?.("abort", onAbort);
|
|
191
|
+
};
|
|
192
|
+
const onAbort = () => {
|
|
193
|
+
cleanup();
|
|
194
|
+
reject(signal.reason || createAbortError());
|
|
195
|
+
};
|
|
196
|
+
timer = setTimeout(() => {
|
|
197
|
+
cleanup();
|
|
198
|
+
resolve();
|
|
199
|
+
}, ms);
|
|
200
|
+
signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
201
|
+
if (signal?.aborted) onAbort();
|
|
202
|
+
});
|
|
203
|
+
throwIfAborted(signal);
|
|
204
|
+
}
|
|
20
205
|
|
|
21
206
|
/**
|
|
22
207
|
* Hard ceiling on the *configurable* retry budget (Claude-Code 2.1.186:
|
|
@@ -61,6 +246,29 @@ export function isRetryableStreamError(err, signal) {
|
|
|
61
246
|
if (isAbortError(err)) return false;
|
|
62
247
|
if (signal && signal.aborted) return false;
|
|
63
248
|
if (!err) return false;
|
|
249
|
+
if (
|
|
250
|
+
[err, err.cause].some(
|
|
251
|
+
(error) =>
|
|
252
|
+
error?.noReplay === true ||
|
|
253
|
+
error?.streamOutputVisible === true ||
|
|
254
|
+
error?.isOutputBackpressureFailure === true,
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
return false;
|
|
258
|
+
const msg = String(err.message || err).toLowerCase();
|
|
259
|
+
// A provider verdict stays terminal even when its detail mentions a timeout,
|
|
260
|
+
// reset or network failure. Inspect it before transport codes and wording so
|
|
261
|
+
// formatted HTTP diagnostics and failed Responses cannot trigger a replay.
|
|
262
|
+
if (
|
|
263
|
+
err.code === "CC_OPENAI_RESPONSES_FAILED" ||
|
|
264
|
+
err.cause?.code === "CC_OPENAI_RESPONSES_FAILED" ||
|
|
265
|
+
[err.status, err.statusCode, err.cause?.status, err.cause?.statusCode].some(
|
|
266
|
+
(status) => Number.isInteger(status) && status >= 400 && status <= 599,
|
|
267
|
+
) ||
|
|
268
|
+
/\bhttp\s+[45]\d{2}\b/.test(msg)
|
|
269
|
+
) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
64
272
|
const code = String(err.code || err.cause?.code || "").toUpperCase();
|
|
65
273
|
if (
|
|
66
274
|
[
|
|
@@ -76,7 +284,6 @@ export function isRetryableStreamError(err, signal) {
|
|
|
76
284
|
) {
|
|
77
285
|
return true;
|
|
78
286
|
}
|
|
79
|
-
const msg = String(err.message || err).toLowerCase();
|
|
80
287
|
return /econnreset|etimedout|econnrefused|eai_again|socket hang ?up|terminated|fetch failed|network error|timed?\s*out|premature close/.test(
|
|
81
288
|
msg,
|
|
82
289
|
);
|