@wudao-org/providers 0.0.0-stage → 0.4.21

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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +8 -2
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/anthropic.d.ts +19 -0
  5. package/dist/anthropic.d.ts.map +1 -0
  6. package/dist/anthropic.js +621 -0
  7. package/dist/anthropic.js.map +1 -0
  8. package/dist/balance.d.ts +28 -0
  9. package/dist/balance.d.ts.map +1 -0
  10. package/dist/balance.js +105 -0
  11. package/dist/balance.js.map +1 -0
  12. package/dist/config.d.ts +328 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +623 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/dispatcher.d.ts +5 -0
  17. package/dist/dispatcher.d.ts.map +1 -0
  18. package/dist/dispatcher.js +21 -0
  19. package/dist/dispatcher.js.map +1 -0
  20. package/dist/effort-catalog.d.ts +17 -0
  21. package/dist/effort-catalog.d.ts.map +1 -0
  22. package/dist/effort-catalog.js +73 -0
  23. package/dist/effort-catalog.js.map +1 -0
  24. package/dist/error-body.d.ts +32 -0
  25. package/dist/error-body.d.ts.map +1 -0
  26. package/dist/error-body.js +74 -0
  27. package/dist/error-body.js.map +1 -0
  28. package/dist/header-validation.d.ts +57 -0
  29. package/dist/header-validation.d.ts.map +1 -0
  30. package/dist/header-validation.js +130 -0
  31. package/dist/header-validation.js.map +1 -0
  32. package/dist/index.d.ts +42 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +110 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/json-arguments.d.ts +17 -0
  37. package/dist/json-arguments.d.ts.map +1 -0
  38. package/dist/json-arguments.js +227 -0
  39. package/dist/json-arguments.js.map +1 -0
  40. package/dist/key-pool.d.ts +66 -0
  41. package/dist/key-pool.d.ts.map +1 -0
  42. package/dist/key-pool.js +207 -0
  43. package/dist/key-pool.js.map +1 -0
  44. package/dist/missing-reasoning-circuit.d.ts +17 -0
  45. package/dist/missing-reasoning-circuit.d.ts.map +1 -0
  46. package/dist/missing-reasoning-circuit.js +38 -0
  47. package/dist/missing-reasoning-circuit.js.map +1 -0
  48. package/dist/model-failure.d.ts +156 -0
  49. package/dist/model-failure.d.ts.map +1 -0
  50. package/dist/model-failure.js +253 -0
  51. package/dist/model-failure.js.map +1 -0
  52. package/dist/model-fallback.d.ts +18 -0
  53. package/dist/model-fallback.d.ts.map +1 -0
  54. package/dist/model-fallback.js +87 -0
  55. package/dist/model-fallback.js.map +1 -0
  56. package/dist/models.d.ts +20 -0
  57. package/dist/models.d.ts.map +1 -0
  58. package/dist/models.js +55 -0
  59. package/dist/models.js.map +1 -0
  60. package/dist/openai-compatible.d.ts +87 -0
  61. package/dist/openai-compatible.d.ts.map +1 -0
  62. package/dist/openai-compatible.js +368 -0
  63. package/dist/openai-compatible.js.map +1 -0
  64. package/dist/openai-engine.d.ts +18 -0
  65. package/dist/openai-engine.d.ts.map +1 -0
  66. package/dist/openai-engine.js +515 -0
  67. package/dist/openai-engine.js.map +1 -0
  68. package/dist/openai-images.d.ts +38 -0
  69. package/dist/openai-images.d.ts.map +1 -0
  70. package/dist/openai-images.js +301 -0
  71. package/dist/openai-images.js.map +1 -0
  72. package/dist/openai-messages.d.ts +40 -0
  73. package/dist/openai-messages.d.ts.map +1 -0
  74. package/dist/openai-messages.js +135 -0
  75. package/dist/openai-messages.js.map +1 -0
  76. package/dist/openai-wire.d.ts +93 -0
  77. package/dist/openai-wire.d.ts.map +1 -0
  78. package/dist/openai-wire.js +151 -0
  79. package/dist/openai-wire.js.map +1 -0
  80. package/dist/persona/apply.d.ts +19 -0
  81. package/dist/persona/apply.d.ts.map +1 -0
  82. package/dist/persona/apply.js +98 -0
  83. package/dist/persona/apply.js.map +1 -0
  84. package/dist/persona/builtins.d.ts +3 -0
  85. package/dist/persona/builtins.d.ts.map +1 -0
  86. package/dist/persona/builtins.js +180 -0
  87. package/dist/persona/builtins.js.map +1 -0
  88. package/dist/persona/decorator.d.ts +4 -0
  89. package/dist/persona/decorator.d.ts.map +1 -0
  90. package/dist/persona/decorator.js +112 -0
  91. package/dist/persona/decorator.js.map +1 -0
  92. package/dist/persona/files.d.ts +20 -0
  93. package/dist/persona/files.d.ts.map +1 -0
  94. package/dist/persona/files.js +84 -0
  95. package/dist/persona/files.js.map +1 -0
  96. package/dist/persona/ids.d.ts +9 -0
  97. package/dist/persona/ids.d.ts.map +1 -0
  98. package/dist/persona/ids.js +11 -0
  99. package/dist/persona/ids.js.map +1 -0
  100. package/dist/persona/registry.d.ts +12 -0
  101. package/dist/persona/registry.d.ts.map +1 -0
  102. package/dist/persona/registry.js +54 -0
  103. package/dist/persona/registry.js.map +1 -0
  104. package/dist/persona/runtime.d.ts +23 -0
  105. package/dist/persona/runtime.d.ts.map +1 -0
  106. package/dist/persona/runtime.js +32 -0
  107. package/dist/persona/runtime.js.map +1 -0
  108. package/dist/persona/schema.d.ts +27 -0
  109. package/dist/persona/schema.d.ts.map +1 -0
  110. package/dist/persona/schema.js +165 -0
  111. package/dist/persona/schema.js.map +1 -0
  112. package/dist/persona/types.d.ts +38 -0
  113. package/dist/persona/types.d.ts.map +1 -0
  114. package/dist/persona/types.js +2 -0
  115. package/dist/persona/types.js.map +1 -0
  116. package/dist/pricing.d.ts +40 -0
  117. package/dist/pricing.d.ts.map +1 -0
  118. package/dist/pricing.js +70 -0
  119. package/dist/pricing.js.map +1 -0
  120. package/dist/quota-park.d.ts +53 -0
  121. package/dist/quota-park.d.ts.map +1 -0
  122. package/dist/quota-park.js +135 -0
  123. package/dist/quota-park.js.map +1 -0
  124. package/dist/rate-pause.d.ts +28 -0
  125. package/dist/rate-pause.d.ts.map +1 -0
  126. package/dist/rate-pause.js +72 -0
  127. package/dist/rate-pause.js.map +1 -0
  128. package/dist/registry.d.ts +142 -0
  129. package/dist/registry.d.ts.map +1 -0
  130. package/dist/registry.js +471 -0
  131. package/dist/registry.js.map +1 -0
  132. package/dist/responses.d.ts +5 -0
  133. package/dist/responses.d.ts.map +1 -0
  134. package/dist/responses.js +290 -0
  135. package/dist/responses.js.map +1 -0
  136. package/dist/retry-after.d.ts +13 -0
  137. package/dist/retry-after.d.ts.map +1 -0
  138. package/dist/retry-after.js +64 -0
  139. package/dist/retry-after.js.map +1 -0
  140. package/dist/retry-ladder.d.ts +176 -0
  141. package/dist/retry-ladder.d.ts.map +1 -0
  142. package/dist/retry-ladder.js +664 -0
  143. package/dist/retry-ladder.js.map +1 -0
  144. package/dist/split-inband-thinking.d.ts +35 -0
  145. package/dist/split-inband-thinking.d.ts.map +1 -0
  146. package/dist/split-inband-thinking.js +117 -0
  147. package/dist/split-inband-thinking.js.map +1 -0
  148. package/dist/stream-idle.d.ts +97 -0
  149. package/dist/stream-idle.d.ts.map +1 -0
  150. package/dist/stream-idle.js +127 -0
  151. package/dist/stream-idle.js.map +1 -0
  152. package/dist/tool-call-ids.d.ts +16 -0
  153. package/dist/tool-call-ids.d.ts.map +1 -0
  154. package/dist/tool-call-ids.js +36 -0
  155. package/dist/tool-call-ids.js.map +1 -0
  156. package/package.json +32 -3
@@ -0,0 +1,290 @@
1
+ import { UnsupportedContentError, offloadRequestFiles } from "@wudao-org/core";
2
+ import { createKeyPool, cooldownClassForStatus } from "./key-pool.js";
3
+ import { createRatePauseWindow, DEFAULT_RATE_PAUSE_MS } from "./rate-pause.js";
4
+ import { validatedInputEffort, effectiveReasoningEffort } from "./config.js";
5
+ import { applyWirePersona, mergeBodyOverlay } from "./persona/apply.js";
6
+ import { gatewayExtraHeaders } from "./header-validation.js";
7
+ import { ProviderHttpError, isContextLengthFailure, parseContextLimitBody, ContextLengthError } from "./openai-compatible.js";
8
+ // OOM 上限(r1a task 2):与 openai 引擎同一常量、同一截断方向(逐字照抄其用法,
9
+ // 不自创第二语义)——只截断响应侧本地解析缓冲,永不触碰请求构造/序列化。
10
+ import { capAccumulated } from "./openai-compatible.js";
11
+ // 加固移植(r8 §4.1):共享梯子 + M58 §B idle 看门狗 —— 与 openai 引擎同一套部件,
12
+ // 零新分类逻辑(本适配器抛的 ProviderHttpError 消息本就匹配梯子的 regex)。
13
+ // ω99-315:看门狗双档化的共享部件在 stream-idle.ts。
14
+ import { withRetry, withRetryStream, TruncatedStreamError, } from "./openai-compatible.js";
15
+ import { resolveStreamIdleBudget } from "./stream-idle.js";
16
+ // r1a Task 3:共享的 M62 §7 有序模型 fallback 链装饰器(同一链、同一语义)。
17
+ import { withModelFallback } from "./model-fallback.js";
18
+ // r1a Task 4:429 Retry-After 解析(只读响应头,与 openai 引擎同一解析器)。
19
+ import { parseRetryAfterMs } from "./retry-after.js";
20
+ import { tryQuotaParkError } from "./quota-park.js";
21
+ import { readErrorBody } from "./error-body.js";
22
+ import { sseDataLines } from "./anthropic.js";
23
+ function responsesUrl(baseURL) {
24
+ return baseURL.endsWith("/v1") ? `${baseURL}/responses` : `${baseURL}/v1/responses`;
25
+ }
26
+ /** Messages → Responses input items:user/assistant 文本保持 role 形状,assistant 的
27
+ * tool_calls 与 tool 结果翻成 function_call / function_call_output 项。 */
28
+ function toResponsesInput(messages) {
29
+ const out = [];
30
+ for (const m of messages) {
31
+ if (m.role === "user")
32
+ out.push({ role: "user", content: m.content });
33
+ else if (m.role === "assistant") {
34
+ if (m.content !== "")
35
+ out.push({ role: "assistant", content: m.content });
36
+ for (const tc of m.toolCalls ?? [])
37
+ out.push({ type: "function_call", call_id: tc.id, name: tc.name, arguments: JSON.stringify(tc.arguments) });
38
+ }
39
+ else {
40
+ out.push({ type: "function_call_output", call_id: m.toolCallId, output: m.content });
41
+ }
42
+ }
43
+ return out;
44
+ }
45
+ // R2 T1 — fail-closed images gate. toResponsesInput emits role/text and
46
+ // function_call items ONLY: an AgentMessage.images block riding the input
47
+ // would be silently DROPPED by the converter (live data loss, not a
48
+ // degradation). Same M79 typed family as the openai engine's
49
+ // assertImagesSupported, with a structural reason: switching MODELS can
50
+ // never fix it (the wire itself carries no image parts), so the model-
51
+ // fallback chain correctly leaves it alone. Fires in the request builder —
52
+ // BEFORE any network call, before a single image byte is read; postResponses
53
+ // (shared by generate and stream) builds through here.
54
+ function assertNoImages(wire, input) {
55
+ for (const m of input.messages) {
56
+ const imgs = m.images;
57
+ if (Array.isArray(imgs) && imgs.length > 0) {
58
+ throw new UnsupportedContentError("wire-no-images", `the "${wire}" wire does not carry image blocks — switch wire (openai-chat) or drop the images (images are never silently dropped)`);
59
+ }
60
+ }
61
+ }
62
+ function buildResponsesRequestBody(config, input) {
63
+ assertNoImages("responses", input);
64
+ // ω99-55: FILE blocks project to handle text before the wire converter
65
+ // (same request-build point the images gate sits at — no provider receives
66
+ // file bytes; text rides every wire, so unlike images there is nothing to
67
+ // refuse). Identity when nothing rides files: byte-identical bodies.
68
+ const messages = offloadRequestFiles(input.messages);
69
+ // R2 T2 — effort → reasoning: { effort } (the responses API's native
70
+ // same-name enum), the value passed through verbatim. "none" has no enum
71
+ // member on this wire → no field (provider default). The key appears ONLY
72
+ // when an effort is explicit (prefix-cache red line: absent effort =
73
+ // byte-identical body).
74
+ const effort = effectiveReasoningEffort(input, config);
75
+ return {
76
+ model: config.model,
77
+ instructions: input.systemPrompt,
78
+ input: toResponsesInput(messages),
79
+ tools: input.tools.map((t) => ({ type: "function", name: t.name, description: t.description, parameters: t.parameters, strict: false })),
80
+ ...(effort !== undefined && effort !== "none" ? { reasoning: { effort } } : {}),
81
+ };
82
+ }
83
+ function parseToolCallArgs(raw) {
84
+ if (typeof raw !== "string" || raw === "")
85
+ return {};
86
+ // OOM fix:字符串参数先过共享上限(同一常量、同一 in-band 标记)——解析输入与
87
+ // _unparsed 兜底都有界;截断+标记不再是合法 JSON 时落 _unparsed(照抄 openai
88
+ // 引擎"截断后解析失败走既有兜底"的用法)。
89
+ const capped = capAccumulated(raw);
90
+ try {
91
+ return JSON.parse(capped);
92
+ }
93
+ catch {
94
+ return { _unparsed: capped };
95
+ }
96
+ }
97
+ /** 聚合 output 数组(generate 的 payload.output,或流上收集的 done items)为一条
98
+ * AssistantMessage:message→text、reasoning→reasoning、function_call→toolCalls。 */
99
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
+ function fromResponsesOutput(output) {
101
+ const items = Array.isArray(output) ? output : [];
102
+ // OOM fix:output_text / summary 的逐项拼接是本适配器的 text/reasoning 累积点
103
+ // (generate 与 stream 的 done 聚合共用这里)——完成态累积器走 capAccumulated。
104
+ const text = capAccumulated(items.filter((i) => i?.type === "message").map((i) => (Array.isArray(i.content) ? i.content.filter((c) => c?.type === "output_text").map((c) => c.text ?? "").join("") : "")).join(""));
105
+ const reasoning = capAccumulated(items.filter((i) => i?.type === "reasoning").map((i) => (Array.isArray(i.summary) ? i.summary.map((s) => s?.text ?? "").join("") : "")).join(""));
106
+ const toolCalls = items.filter((i) => i?.type === "function_call").map((i) => ({ id: String(i.call_id), name: String(i.name), arguments: parseToolCallArgs(i.arguments) }));
107
+ return {
108
+ role: "assistant",
109
+ content: text,
110
+ ...(reasoning !== "" ? { reasoning } : {}),
111
+ ...(toolCalls.length > 0 ? { toolCalls } : {}),
112
+ stopReason: toolCalls.length > 0 ? "tool_calls" : "stop",
113
+ };
114
+ }
115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+ function responsesUsage(payload, durationMs) {
117
+ const inputTokens = payload?.usage?.input_tokens ?? 0;
118
+ const cached = payload?.usage?.input_tokens_details?.cached_tokens ?? 0;
119
+ return { promptTokens: inputTokens, cacheHitTokens: cached, cacheMissTokens: Math.max(0, inputTokens - cached), completionTokens: payload?.usage?.output_tokens ?? 0, durationMs };
120
+ }
121
+ /** 发请求 + 统一错误路径(generate/stream 共用)。persona 在 fetch 入口逐调用读取
122
+ * (不在工厂期缓存);overlay 走 mergeBodyOverlay(base 键序保持,overlay 追加其后),
123
+ * stream 标志最后叠加、适配器始终拥有它。 */
124
+ async function postResponses(config, input, doFetch, keyPool, ratePause, persona, stream) {
125
+ const wire = applyWirePersona(persona, "responses", config.provider);
126
+ const base = buildResponsesRequestBody(config, input);
127
+ const body = { ...(wire?.bodyOverlay !== undefined ? mergeBodyOverlay(base, wire.bodyOverlay) : base), ...(stream ? { stream: true } : {}) };
128
+ const apiKey = keyPool.select();
129
+ const res = await doFetch(responsesUrl(config.baseURL), {
130
+ method: "POST",
131
+ headers: {
132
+ "content-type": "application/json",
133
+ authorization: `Bearer ${apiKey}`,
134
+ // ω99-64: registry card headers (per-provider baseline) spread after
135
+ // adapter auth and before persona wire.headers — adapter auth >
136
+ // persona > registry. gatewayExtraHeaders skips the full
137
+ // FORBIDDEN_HEADER_KEYS set (14 keys — single source
138
+ // header-validation.ts, ω99-69) so auth stays structurally the key
139
+ // pool's.
140
+ ...gatewayExtraHeaders(config.extraHeaders),
141
+ ...(wire?.headers ?? {}),
142
+ },
143
+ body: JSON.stringify(body),
144
+ signal: input.signal,
145
+ });
146
+ if (!res.ok) {
147
+ // 夜移 007: status-classed cooldowns — auth (401/403) cools LONG, rate
148
+ // (429) keeps 60s, provider-side statuses never touch the key.
149
+ const cooldownClass = cooldownClassForStatus(res.status);
150
+ if (cooldownClass !== null)
151
+ keyPool.markCooldown(apiKey, cooldownClass);
152
+ const text = await readErrorBody(res); // 波次 8 #42: 有界错误体读取
153
+ // M58 §A(与 anthropic.ts 同序):429 冷却 → 溢出分类 → 通用 ProviderHttpError。
154
+ // loop 的 compact-once-retry 只认 err.name === "ContextLengthError"(core 的
155
+ // isContextLengthError),裸 ProviderHttpError 对它不透明。
156
+ if (isContextLengthFailure(res.status, text)) {
157
+ throw new ContextLengthError(res.status, text, parseContextLimitBody(text, input.maxTokens ?? config.maxTokens));
158
+ }
159
+ // 构造器实参以真实签名为准:which/status/body(与 anthropic.ts 的错误路径同构)。
160
+ // r1a Task 4:响应头的 Retry-After 随错误携带(只读响应头;generate/stream
161
+ // 共用本发请求函数,一处接线两路生效)。
162
+ // 波次 7 #37:同一 deadline 也设置 provider 级暂停窗(仅当键池无备键可换时)。
163
+ const retryAfterMs = parseRetryAfterMs(res.headers);
164
+ if (res.status === 429 && keyPool.snapshot().available === 0) {
165
+ ratePause.trip(retryAfterMs ?? DEFAULT_RATE_PAUSE_MS);
166
+ }
167
+ // 113-B3: 账户级配额 429 在通用错误之前分类(一处接线,generate/stream
168
+ // 两路生效——与 anthropic/openai 引擎同位同门)。
169
+ const quotaPark = tryQuotaParkError("request", res.status, text, retryAfterMs, { provider: config.provider, model: config.model });
170
+ if (quotaPark !== undefined)
171
+ throw quotaPark;
172
+ throw new ProviderHttpError("request", res.status, text, retryAfterMs, { provider: config.provider, model: config.model }); // v7 γ4: 失败腿的 provider/model 身份(结构化字段+消息尾)
173
+ }
174
+ // 波次 7 #37:2xx 证明暂停已过期(一处清窗,两路生效)。
175
+ ratePause.clear();
176
+ return res;
177
+ }
178
+ async function generateResponsesOnce(config, input, doFetch, keyPool, ratePause, persona) {
179
+ const startedAt = Date.now();
180
+ const res = await postResponses(config, input, doFetch, keyPool, ratePause, persona, false);
181
+ // res.json() 在本 lib 下类型为 {};payload?.output 需要显式 any(同 anthropic.ts 的宽松解析)。
182
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
183
+ const payload = await res.json();
184
+ input.onUsage?.(responsesUsage(payload, Date.now() - startedAt));
185
+ return fromResponsesOutput(payload?.output);
186
+ }
187
+ async function* streamResponsesOnce(config, input, doFetch, keyPool, ratePause, persona, streamIdle) {
188
+ const startedAt = Date.now();
189
+ const res = await postResponses(config, input, doFetch, keyPool, ratePause, persona, true);
190
+ const items = [];
191
+ let finalUsage;
192
+ // ω99-44: terminal tracking + attribution chars — EOF with sawTerminal=false
193
+ // is a cut, not a completion (see isResponsesStreamTerminal below).
194
+ let sawTerminal = false;
195
+ let sawChars = 0;
196
+ // M58 §B / ω99-315 双档 idle 看门狗随共享的 sseDataLines(见 anthropic.ts)。
197
+ for await (const data of sseDataLines(res, input.signal, streamIdle)) {
198
+ sawChars += data.length;
199
+ let ev;
200
+ try {
201
+ ev = JSON.parse(data);
202
+ }
203
+ catch {
204
+ continue;
205
+ }
206
+ if (isResponsesStreamTerminal(ev))
207
+ sawTerminal = true;
208
+ if (ev?.type === "response.output_text.delta" && typeof ev.delta === "string") {
209
+ yield { type: "text_delta", text: ev.delta };
210
+ }
211
+ else if (ev?.type === "response.reasoning_summary_text.delta" && typeof ev.delta === "string") {
212
+ yield { type: "reasoning_delta", text: ev.delta };
213
+ }
214
+ else if (ev?.type === "response.output_item.done" && ev?.item) {
215
+ items.push(ev.item);
216
+ }
217
+ else if (ev?.type === "response.completed") {
218
+ finalUsage = ev.response?.usage;
219
+ // 兜底:没有 output_item.done 的实现仍能从 completed 的整体 output 聚合。
220
+ if (Array.isArray(ev.response?.output) && items.length === 0)
221
+ items.push(...ev.response.output);
222
+ }
223
+ }
224
+ // ω99-44 (pi ebc374490): EOF without a terminal lifecycle event = the stream
225
+ // was cut. No synthetic done, no fabricated usage — the typed error walks the
226
+ // ladder as retryable transport (same seam/streamOnce semantics).
227
+ if (!sawTerminal)
228
+ throw new TruncatedStreamError("responses", sawChars);
229
+ input.onUsage?.(responsesUsage({ usage: finalUsage }, Date.now() - startedAt));
230
+ yield { type: "done", message: fromResponsesOutput(items) };
231
+ }
232
+ /** ω99-44: the Responses wire's terminal lifecycle events — completed /
233
+ * failed / incomplete all prove the server FINISHED speaking (a cut stream
234
+ * carries none of them). Only response.completed carries usage/aggregation;
235
+ * the failure forms keep their existing partial-done handling — this
236
+ * predicate decides "was the stream cut", never "did it succeed".
237
+ * Per-adapter on purpose (see isAnthropicStreamTerminal). */
238
+ function isResponsesStreamTerminal(ev) {
239
+ return ev.type === "response.completed" || ev.type === "response.failed" || ev.type === "response.incomplete";
240
+ }
241
+ export function createResponsesProvider(config, options = {}) {
242
+ const doFetch = options.fetch ?? fetch;
243
+ const keyPool = options.keyPool ?? createKeyPool(config.apiKeys ?? [config.apiKey]);
244
+ // 波次 7 #37 (CodeWhale C1):provider 级 429 暂停窗(同 openai-compatible 引擎)。
245
+ const ratePause = options.ratePauseWindow ?? createRatePauseWindow();
246
+ const persona = options.personaRuntime;
247
+ // 加固移植(r8 §4.1):梯子与看门狗选项此前被忽略 —— 现在与 openai 引擎同解析
248
+ // (工厂期一次):onRetry 合并进梯子选项。ω99-315:idle 预算双档化(soft 90s
249
+ // warn / hard 300s abort;legacy 选项与 env 仍是 hard 档覆盖),同一
250
+ // resolveStreamIdleBudget。
251
+ const retry = {
252
+ ...options.retry,
253
+ ...(options.onRetry !== undefined ? { onRetry: options.onRetry } : {}),
254
+ // 121 项 1:容量观察者同 onRetry 一并合并进梯子选项。
255
+ ...(options.onOverload !== undefined ? { onOverload: options.onOverload } : {}),
256
+ };
257
+ const streamIdle = {
258
+ ...resolveStreamIdleBudget({
259
+ softMs: options.streamIdleSoftMs,
260
+ hardMs: options.streamIdleHardMs,
261
+ legacyTimeoutMs: options.streamIdleTimeoutMs,
262
+ }),
263
+ ...(options.onStreamIdleWarning !== undefined ? { onSoftWarning: options.onStreamIdleWarning } : {}),
264
+ };
265
+ // r1a Task 3:responses 适配器经共享装饰器获得模型 fallback 能力 —— 与
266
+ // openai 引擎同一链、同一语义(config.fallbackModels,过滤与主模型相同的
267
+ // 项;sticky streak=2;key-class/abort/上下文溢出永不 fallback)。本工厂
268
+ // 只提供「一个模型的一条腿」:共享梯子在腿内,请求构造/序列化零改动。
269
+ const legClient = (cfg) => ({
270
+ modelId: cfg.model,
271
+ // 共享梯子包两条路径(M26 P11);querySource 从 ModelInput 穿进梯子选项
272
+ // (M70 §3:后台来源不重试 overload,照抄 openai-compatible 引擎的接法)。
273
+ async generate(input) {
274
+ // R2 T2 (M58 §C, engine parity): junk per-input effort fails fast
275
+ // BEFORE the ladder — parse errors are never retried, never on the wire.
276
+ const validated = validatedInputEffort(input);
277
+ // 波次 7 #37:腿入口门 —— 并发请求在此等暂停窗;发起者的梯子重试在腿内,不门。
278
+ await ratePause.wait(input.signal);
279
+ return withRetry(() => generateResponsesOnce(cfg, validated, doFetch, keyPool, ratePause, persona), { ...retry, querySource: input.querySource });
280
+ },
281
+ async *stream(input) {
282
+ const validated = validatedInputEffort(input);
283
+ // 波次 7 #37:同 generate 的入口门(首 delta 之前)。
284
+ await ratePause.wait(input.signal);
285
+ yield* withRetryStream(() => streamResponsesOnce(cfg, validated, doFetch, keyPool, ratePause, persona, streamIdle), { ...retry, querySource: input.querySource });
286
+ },
287
+ });
288
+ return withModelFallback(legClient, config);
289
+ }
290
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","sourceRoot":"","sources":["../src/responses.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** The smallest structural need: a header lookup. Real `Headers` satisfies it
2
+ * (and is case-insensitive itself); test mocks may pass a plain object. */
3
+ export interface RetryAfterHeadersLike {
4
+ get(name: string): string | null | undefined;
5
+ }
6
+ /** The ladder's fail cap: a server deadline beyond 60s is honored as a hard
7
+ * stop (no retry, the original error surfaces). Exactly 60_000 IS allowed —
8
+ * the comparison is `>`, not `>=`. */
9
+ export declare const RETRY_AFTER_FAIL_CAP_MS = 60000;
10
+ /** Parse a response's retry-after / retry-after-ms headers into a wait in ms.
11
+ * Fail-closed: anything unparseable, negative, or non-finite → undefined. */
12
+ export declare function parseRetryAfterMs(headers: RetryAfterHeadersLike | undefined): number | undefined;
13
+ //# sourceMappingURL=retry-after.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-after.d.ts","sourceRoot":"","sources":["../src/retry-after.ts"],"names":[],"mappings":"AAmBA;4EAC4E;AAC5E,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC9C;AAED;;uCAEuC;AACvC,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAgB9C;8EAC8E;AAC9E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAqBhG"}
@@ -0,0 +1,64 @@
1
+ // packages/providers/src/retry-after.ts — r1a Task 4: 429 Retry-After 解析。
2
+ //
3
+ // 纯函数模块(零 openai-compatible 依赖,无环):只读响应头,永不触碰请求
4
+ // 序列化(前缀缓存字节稳定红线)。上限裁决在梯子(RETRY_AFTER_FAIL_CAP_MS),
5
+ // 解析器对超过上限的值原样返回 —— ">60s 不重试"是梯子的决定。
6
+ //
7
+ // 支持的响应头(头名大小写不敏感 —— 既是 Headers.get 的既有语义,也是本
8
+ // 解析器自己的探测矩阵,duck-typed 的大小写敏感 get 实现同样受益):
9
+ // retry-after IETF 标准(RFC 9110 §10.2.3):整数秒,或 HTTP-date
10
+ // retry-after-ms 网关方言:毫秒
11
+ // 标准头优先(两头同在时以 retry-after 为准)。
12
+ //
13
+ // 解析规则全部 fail-closed(→ undefined):空串/畸形/非十进制数字 → undefined;
14
+ // 负值/NaN/非有限 → undefined;HTTP-date 在过去(差为负)→ undefined;
15
+ // HTTP-date → Date.parse 与 now 的差(向上取整 —— 绝不早于服务器期限);
16
+ // 小数秒 × 1000 取整(r1b:Math.round —— 消浮点尘,如 0.5678×1000 的
17
+ // 567.8000…01;与 date 形态"取整、绝不早于期限"的精神对齐)。
18
+ // 0 是合法值(服务器明示"可立即重试")。
19
+ /** The ladder's fail cap: a server deadline beyond 60s is honored as a hard
20
+ * stop (no retry, the original error surfaces). Exactly 60_000 IS allowed —
21
+ * the comparison is `>`, not `>=`. */
22
+ export const RETRY_AFTER_FAIL_CAP_MS = 60_000;
23
+ /** Decimal seconds/ms only (`^\d+(\.\d+)?$` after trim): hex, exponents,
24
+ * signs, unit suffixes, and empty/whitespace values are all malformed. */
25
+ const DECIMAL_RE = /^\d+(?:\.\d+)?$/;
26
+ /** 头名大小写变体:小写 / 首字母大写(HTTP 惯用拼写)/ 全大写(网关方言)。 */
27
+ function lookup(headers, name) {
28
+ const variants = [name.toLowerCase(), name.toUpperCase(), name.replace(/(^|-)[a-z]/g, (c) => c.toUpperCase())];
29
+ for (const v of variants) {
30
+ const raw = headers.get(v);
31
+ if (raw !== null && raw !== undefined && raw.trim() !== "")
32
+ return raw.trim();
33
+ }
34
+ return undefined;
35
+ }
36
+ /** Parse a response's retry-after / retry-after-ms headers into a wait in ms.
37
+ * Fail-closed: anything unparseable, negative, or non-finite → undefined. */
38
+ export function parseRetryAfterMs(headers) {
39
+ if (headers === undefined)
40
+ return undefined;
41
+ // The standard header first (seconds or HTTP-date); the ms dialect is the
42
+ // fallback for gateways that send only it.
43
+ const seconds = lookup(headers, "retry-after");
44
+ if (seconds !== undefined) {
45
+ // r1b: round the ×1000 product — the raw float64 multiply can leak sub-ms
46
+ // dust (0.5678 → 567.8000…01) into the ladder's sleep. Whole ms, never
47
+ // early beyond rounding (aligned with the date form's ceil spirit).
48
+ if (DECIMAL_RE.test(seconds))
49
+ return Math.round(Number(seconds) * 1000);
50
+ // HTTP-date form: wait until the given instant.
51
+ const at = Date.parse(seconds);
52
+ if (Number.isFinite(at)) {
53
+ const diff = at - Date.now();
54
+ if (Number.isFinite(diff) && diff >= 0)
55
+ return Math.ceil(diff);
56
+ }
57
+ return undefined;
58
+ }
59
+ const ms = lookup(headers, "retry-after-ms");
60
+ if (ms === undefined || !DECIMAL_RE.test(ms))
61
+ return undefined;
62
+ return Number(ms);
63
+ }
64
+ //# sourceMappingURL=retry-after.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-after.js","sourceRoot":"","sources":["../src/retry-after.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,gDAAgD;AAChD,oDAAoD;AACpD,sCAAsC;AACtC,EAAE;AACF,8CAA8C;AAC9C,4CAA4C;AAC5C,+DAA+D;AAC/D,6BAA6B;AAC7B,gCAAgC;AAChC,EAAE;AACF,4DAA4D;AAC5D,wDAAwD;AACxD,sDAAsD;AACtD,uDAAuD;AACvD,0CAA0C;AAC1C,wBAAwB;AAQxB;;uCAEuC;AACvC,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE9C;2EAC2E;AAC3E,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC,gDAAgD;AAChD,SAAS,MAAM,CAAC,OAA8B,EAAE,IAAY;IAC1D,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC/G,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;8EAC8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,OAA0C;IAC1E,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,0EAA0E;IAC1E,2CAA2C;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,0EAA0E;QAC1E,uEAAuE;QACvE,oEAAoE;QACpE,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACxE,gDAAgD;QAChD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC7C,IAAI,EAAE,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,176 @@
1
+ import type { ModelInput } from "@wudao-org/core";
2
+ import type { ProviderConfig } from "./config.js";
3
+ import { ContextLengthError, ProviderHttpError } from "./model-failure.js";
4
+ /** Observability callback: attempt number (1-based), wait before it, why. */ export type RetryObserver = (n: number, delayMs: number, reason: string) => void;
5
+ export interface RetryLadderOptions {
6
+ /** Additional attempts after the first; default 4 (env WUDAO_MAX_RETRIES). */
7
+ readonly maxRetries?: number;
8
+ /** First wait, ms; default 500. */
9
+ readonly baseDelayMs?: number;
10
+ /** Wait cap, ms; default 32_000. */
11
+ readonly maxDelayMs?: number;
12
+ /** Jitter fraction around the scheduled wait; default 0.25 (±25%). */
13
+ readonly jitterRatio?: number;
14
+ /** Injectable randomness (tests); default Math.random. */
15
+ readonly random?: () => number;
16
+ /** Injectable sleep (tests); default setTimeout-based. */
17
+ readonly sleep?: (ms: number) => Promise<void>;
18
+ readonly onRetry?: RetryObserver;
19
+ /** M47 §7: first wait for OVERLOAD-class failures, ms; default 2_000. The
20
+ * overload branch never rotates keys — same key, longer doubling ladder. */
21
+ readonly overloadBaseDelayMs?: number;
22
+ /** M70 §3: the call's QuerySource (threaded from ModelInput.querySource).
23
+ * A background source never retries an overload-class failure — it bails
24
+ * immediately with BackgroundOverloadError (see the allowlist block). */
25
+ readonly querySource?: string;
26
+ /** 121 项 1(CodeWhale 498490680 形)— 容量观察者:catch 里判定为
27
+ * overload-class(isOverloadClassFailure:429/503/529/overload 体)时同
28
+ * 步发射一次——无论该失败随后走重试、后台 bail 还是重抛。纯观察:绝不
29
+ * 影响梯子自身的任何决策;部署层把它接到 AIMD 并发门的 onThrottle,
30
+ * 429 就从「人肉调参」变成「容量信号」。每个 overload 尝试各发一次
31
+ * (同一次调用连续 4 个 429 = 4 次——每一次都是真实的容量证据)。 */
32
+ readonly onOverload?: () => void;
33
+ /** 124 项 2 — the network-outage grace window. When enabled, network-class
34
+ * failures (isNetworkClassFailure — fetch reject, DNS, socket hang up,
35
+ * network timeouts; NOT 4xx/5xx business errors) widen the ladder:
36
+ * effective retries = maxRetries × retryMultiplier (default ×3 = 12),
37
+ * single-wait cap bumps to maxDelayMsMs (default 5min). 4xx/5xx keep the
38
+ * exact pre-grace semantics. Opt-in; off by default. */
39
+ readonly networkGrace?: {
40
+ readonly enabled?: boolean;
41
+ readonly retryMultiplier?: number;
42
+ readonly maxDelayMsMs?: number;
43
+ /** Fires the FIRST time a failure inside the grace window is classified
44
+ * as network-class — the UI seam for "网络似乎不稳定——正在耐心重试
45
+ * (最长 N 分钟)". One-shot per retry-lifetime (idempotent). */
46
+ readonly onEnter?: () => void;
47
+ };
48
+ }
49
+ /** True iff `err` looks like a transient network-class failure (NOT a
50
+ * business-class HTTP error and NOT a deterministic fetch failure). */
51
+ export declare function isNetworkClassFailure(err: unknown): boolean;
52
+ export declare const DEFAULT_NETWORK_GRACE_RETRY_MULTIPLIER = 3;
53
+ export declare const DEFAULT_NETWORK_GRACE_MAX_DELAY_MS: number;
54
+ /** The context-length body vocabulary, vendor-anchored. */
55
+ export declare const CONTEXT_LENGTH_BODY_SIGNATURES: readonly RegExp[];
56
+ /** "input length N exceeds [the] maximum [context] length M" — N and M are
57
+ * literal token counts; the gap tolerators keep "the"/extra spaces; the
58
+ * optional "context" admits the "maximum context length" spelling (which the
59
+ * generic /context length/i signature already classifies — there the pair
60
+ * only feeds the trusted parse). */
61
+ export declare const CONTEXT_LIMIT_INPUT_LENGTH_RE: RegExp;
62
+ /** The parsed (inputTokens, maximumLength) pair when the body carries the
63
+ * GLM/vLLM spelling AND the strictness invariant holds (input > maximum,
64
+ * both finite and positive); undefined for every near-miss — numberless
65
+ * ("Input length is too long"), equal, or inverted pairs. */
66
+ export declare function matchContextLimitInputLength(body: string): {
67
+ inputTokens: number;
68
+ maximumLength: number;
69
+ } | undefined;
70
+ /** True when a response body carries a known context-length signature. */
71
+ export declare function sniffContextLengthBody(body: string): boolean;
72
+ /** True iff the status/body pair means "the prompt does not fit the window":
73
+ * HTTP 413 outright, or a 400/500 whose body carries the vocabulary above. */
74
+ export declare function isContextLengthFailure(status: number, body: string): boolean;
75
+ /** Parse a classified context-length body for the observed (promptTokens,
76
+ * windowTokens) pair. `maxTokens` is the completion cap THIS request carried
77
+ * (the effective one — a per-input override beats the config's): the prose
78
+ * "you requested M" counts prompt + completion, so the prompt is M − maxTokens
79
+ * when a cap was sent; without one the provider auto-allocated a completion
80
+ * budget and counted it against the request, so M itself is the conservative
81
+ * prompt figure (over-counting is the safe direction for the clip ladder).
82
+ * Undefined when either number is missing or unparseable — trusted-parse-only. */
83
+ export declare function parseContextLimitBody(body: string, maxTokens?: number): {
84
+ promptTokens: number;
85
+ windowTokens: number;
86
+ } | undefined;
87
+ /** Parse a 400 body for the (inputTokens, contextLimit) pair; undefined when
88
+ * EITHER number is missing or unparseable. */
89
+ export declare function parseMaxTokensOverflow(body: string): {
90
+ inputTokens: number;
91
+ contextLimit: number;
92
+ } | undefined;
93
+ /** The repaired completion cap: max(3000, contextLimit - inputTokens - 1000,
94
+ * thinkingBudget + 1). No thinking budget is configured today (0 — the term
95
+ * is CC's forward-looking floor: a thinking-capable model must keep at least
96
+ * budget+1 tokens or the request fails for a different reason). */
97
+ export declare function selfRepairMaxTokensValue(parsed: {
98
+ inputTokens: number;
99
+ contextLimit: number;
100
+ }, thinkingBudget?: number): number;
101
+ /** True when the error is a 400 the self-repair can parse (the retry-once
102
+ * trigger; everything else keeps its existing path). */
103
+ export declare function isMaxTokensOverflow400(err: unknown): err is ProviderHttpError;
104
+ /** ω-2b (I1-a): classify + stamp in one step — the trusted-parse observation
105
+ * rides the typed error when the body carried the numbers. The effective
106
+ * completion cap (per-input maxTokens override beats the config's) decides
107
+ * how the prose figures decompose into a prompt size. */
108
+ export declare function classifyContextLength(status: number, detail: string, config: ProviderConfig, input: ModelInput): ContextLengthError;
109
+ /** The QuerySource allow-set that may retry on overload. Untagged calls are
110
+ * foreground by default (every pre-M70 caller keeps today's behavior).
111
+ * ω99-8b: "subagent" joins — core's runSubagent stamps child calls, and the
112
+ * waiting parent (often blocking a human) is foreground; leaving the tag out
113
+ * would silently demote child overload failures to background bail-out, a
114
+ * behavior change beyond ω99-8b's cost-partitioning scope. */
115
+ export declare const FOREGROUND_QUERY_SOURCES: ReadonlySet<string>;
116
+ /** True when the failure means "the gateway is out of capacity": the
117
+ * overload-status family (429 / 503 / 529, including a 529 folded into the
118
+ * message body) or a 429 whose body sniffs as fleet overload. */
119
+ export declare function isOverloadClassFailure(err: unknown): boolean;
120
+ /** The typed SSE line-buffer overflow abort (r1b). A live stream that keeps
121
+ * delivering bytes but never emits a line/event boundary grows the line
122
+ * buffer without bound — a hole the idle watchdog cannot catch (every read
123
+ * resolves on time; the stream never goes quiet). Fail-loud, NEVER truncate:
124
+ * slicing an SSE line mid-event would fabricate garbage events downstream.
125
+ * Same ladder family as StreamIdleError: retryable transport class (the
126
+ * replay is byte-identical, the prefix cache is unaffected). */
127
+ export declare class StreamOverflowError extends Error {
128
+ readonly maxChars: number;
129
+ constructor(maxChars: number);
130
+ }
131
+ /** ω99-44 (pi ebc374490): the typed EOF-without-terminal abort. The stream
132
+ * ended CLEANLY (read → done, no transport error) but no finish/stop
133
+ * semantics ever arrived — byte-indistinguishable from a proxy EOF cut, so
134
+ * it fails LOUD instead of completing: a synthetic done would lose
135
+ * finish_reason (blinding the M70 stop-reason/truncated-tool-call guard),
136
+ * lose usage (the metering row), and feed empty completions into the
137
+ * zero-output heuristics. Attribution: which adapter's wire, and how many
138
+ * payload bytes arrived before the cut (the shared-sseDataLines consumers
139
+ * count decoded data-line chars — attribution granularity, not an exact
140
+ * wire count). Same ladder family as StreamIdleError/StreamOverflowError:
141
+ * retryable transport class — the pre-first-delta replay is byte-identical
142
+ * (prefix-cache safe); a post-delta cut propagates to the loop untouched
143
+ * (the ω99-9 midstream-recovery surface). */
144
+ export declare class TruncatedStreamError extends Error {
145
+ readonly provider: string;
146
+ readonly sawBytes: number;
147
+ constructor(provider: string, sawBytes: number);
148
+ }
149
+ /** Overload-class predicate for the ladder branch (and callers rendering
150
+ * retry state): true only for the 429+signature pair. */
151
+ export declare function isOverloadError(err: unknown): boolean;
152
+ /** WUDAO_MAX_RETRIES (integer ≥ 0); falls back to the default on junk. */
153
+ export declare function defaultMaxRetries(env?: NodeJS.ProcessEnv): number;
154
+ /** Scheduled wait for the n-th retry (0-based): 500ms × 2ⁿ, capped, jittered. */
155
+ export declare function backoffDelayMs(attempt: number, opts?: Pick<RetryLadderOptions, "baseDelayMs" | "maxDelayMs" | "jitterRatio" | "random">): number;
156
+ /** The overload branch's wait (M47 §7): same doubling/cap/jitter shape as the
157
+ * generic ladder, but from the 2s overload base — a fleet-wide signal earns a
158
+ * longer first pause than a per-key rate limit. Same key, never rotate. */
159
+ export declare function overloadBackoffDelayMs(attempt: number, opts?: Pick<RetryLadderOptions, "overloadBaseDelayMs" | "baseDelayMs" | "maxDelayMs" | "jitterRatio" | "random">): number;
160
+ export declare function isRetryableProviderError(err: unknown): boolean;
161
+ /** Retry a promise-returning attempt on the ladder. M47 §7: overload-class
162
+ * failures take the overload branch (same key, longer doubling waits).
163
+ * M70 §3: a background QuerySource never retries an overload — it fails
164
+ * immediately with the typed reason (no wait, no re-issue).
165
+ * r1a Task 4: a server Retry-After beyond the fail cap (60s) is honored as a
166
+ * hard stop — no retry, the original error surfaces as-is; within it, the
167
+ * deadline replaces the backoff value (the wait source only — same sleep,
168
+ * same ladder slots, zero second time mechanism). */
169
+ export declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryLadderOptions): Promise<T>;
170
+ /** Retry a generator-producing attempt — but ONLY until the first event has
171
+ * been yielded downstream. After that, an error is rethrown untouched: a
172
+ * replay would duplicate already-delivered output.
173
+ * r1a Task 4: same Retry-After semantics as withRetry (fail cap + the
174
+ * deadline replacing the backoff value; pre-delta retries only). */
175
+ export declare function withRetryStream<T>(fn: () => AsyncGenerator<T>, opts?: RetryLadderOptions): AsyncGenerator<T>;
176
+ //# sourceMappingURL=retry-ladder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-ladder.d.ts","sourceRoot":"","sources":["../src/retry-ladder.ts"],"names":[],"mappings":"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"}