@reinsjs/lowering-fetch 0.2.0

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.
@@ -0,0 +1,855 @@
1
+ import * as _reinsjs_core from '@reinsjs/core';
2
+ import { Event, ContentPart, SystemNotePayload, LandingRecord, TokenUsage, LoweringStreamContext, CoreEventDraft, LoweringOutcome, LandingSpec, ModelRef, LoweringCapabilities, ToolSpec, BoundModel, Lowering, ToRequestInput, LoweredRequest, LossMatrix } from '@reinsjs/core';
3
+
4
+ /**
5
+ * 事件 → 中间表示(IR):三条线协议共用的一趟遍历。
6
+ *
7
+ * 这一步只做与协议无关的事:
8
+ * 1. **分组**——连续的 model 事件(thinking / text / tool_call)合成一条 assistant 轮,遇到非 model 事件或来源变了就收口;
9
+ * 2. **后移**——"同批 tool_result 必须紧跟 tool_use"是厂商硬规则,而时间线里说明、摘要、用户插话都可能落在两者之间;
10
+ * 结果没到齐时它们先攒着,到齐后按原顺序放出(`deferred: true`)。日志顺序不动(宪法二),只在翻译产物里挪位;
11
+ * 3. **trust 标注**——untrusted 内容包 `<untrusted source=…>`(core 的同一份纯函数),转义过的记 `escaped`。
12
+ *
13
+ * 每种事件落到线协议的哪个位置、算 exact 还是 lossy,由各协议的 encoder 决定并记 LandingRecord;IR 只提供判定所需的事实。
14
+ * 输出顺序就是线上顺序;`orderLandings` 把 encoder 记下的落点按输入事件顺序排回去(LoweredRequest.landings 的契约)。
15
+ */
16
+
17
+ /** 模型事件 replay 里记录的来源,产出与回放两头共用(与 lowering-pi 同字段,两条路线的事件可互换) */
18
+ interface ModelOrigin {
19
+ provider: string;
20
+ api: string;
21
+ model: string;
22
+ }
23
+ type IrBlock = {
24
+ type: "thinking";
25
+ event: Event;
26
+ text: string;
27
+ replay: Record<string, unknown>;
28
+ } | {
29
+ type: "text";
30
+ event: Event;
31
+ text: string;
32
+ replay: Record<string, unknown>;
33
+ } | {
34
+ type: "tool_call";
35
+ event: Event;
36
+ id: string;
37
+ name: string;
38
+ args: unknown;
39
+ replay: Record<string, unknown>;
40
+ };
41
+ type IrItem = {
42
+ kind: "user";
43
+ event: Event;
44
+ parts: ContentPart[];
45
+ escaped: boolean;
46
+ deferred: boolean;
47
+ } | {
48
+ kind: "assistant";
49
+ origin: ModelOrigin;
50
+ blocks: IrBlock[];
51
+ at: number;
52
+ } | {
53
+ kind: "tool_result";
54
+ event: Event;
55
+ toolCallId: string;
56
+ name: string;
57
+ parts: ContentPart[];
58
+ isError: boolean;
59
+ escaped: boolean;
60
+ } | {
61
+ kind: "system_note";
62
+ event: Event;
63
+ noteKind: SystemNotePayload["kind"];
64
+ text: string;
65
+ escaped: boolean;
66
+ deferred: boolean;
67
+ } | {
68
+ kind: "compaction";
69
+ event: Event;
70
+ text: string;
71
+ escaped: boolean;
72
+ deferred: boolean;
73
+ }
74
+ /** 运维事件与 ext.*:不下发,encoder 只记落点 */
75
+ | {
76
+ kind: "dropped";
77
+ event: Event;
78
+ note: string;
79
+ };
80
+ interface IrInput {
81
+ events: readonly Event[];
82
+ /** 当前请求的目标模型:replay 没写来源的模型事件按它算 */
83
+ target: ModelOrigin;
84
+ /** trust=untrusted 的内容包 <untrusted source=…>(§14)。缺省 true;关掉是宿主自担风险 */
85
+ trustMarkers?: boolean;
86
+ }
87
+ declare function sameOrigin(a: ModelOrigin, b: ModelOrigin): boolean;
88
+ /**
89
+ * 是否来自别家:只比 provider 与 api。响应里报告的模型 id 常与请求的不同(日期后缀、别名、网关改名),
90
+ * 同家同协议下回放数据仍可用,不算有损。
91
+ */
92
+ declare function foreignOrigin(a: ModelOrigin, target: ModelOrigin): boolean;
93
+ declare function eventsToIr(input: IrInput): IrItem[];
94
+ /** 把 encoder 记下的落点按输入事件顺序排回去:LoweredRequest.landings 承诺"每条输入事件一条记录,顺序与输入一致" */
95
+ declare function orderLandings(events: readonly Event[], landings: readonly LandingRecord[]): LandingRecord[];
96
+
97
+ /**
98
+ * Server-Sent Events 解析(WHATWG 规范的字段子集):`event:` / `data:` / `id:`,多行 data 以 \n 拼接,
99
+ * 空行分发一条消息,`:` 开头是注释,`retry:` 与未知字段忽略。行尾兼容 \r\n、\n、\r。
100
+ *
101
+ * 比规范宽一处:流结束时缓冲区里还有没被空行收口的消息,也照样分发——部分上游最后一条事件后不发空行。
102
+ * `data` 的 JSON 解析不在这里做:`[DONE]` 这类哨兵是各协议自己的约定。
103
+ */
104
+ interface SseMessage {
105
+ event?: string;
106
+ data: string;
107
+ id?: string;
108
+ }
109
+ declare function parseSse(body: ReadableStream<Uint8Array>): AsyncGenerator<SseMessage>;
110
+
111
+ /**
112
+ * 用量与成本(三线共用)。`TokenUsage` 语义跟随 core:`input` 是**未命中缓存**的输入 token,缓存读 / 写另计。
113
+ * 各协议的原生用量字段在各自 from-stream 里换算成这个形状,这里只算钱。
114
+ */
115
+
116
+ /** 每百万 token 的美元价。厂商有峰谷价的(DeepSeek)内置表存峰值价,算出来的是估算上限 */
117
+ interface ModelCost {
118
+ input: number;
119
+ output: number;
120
+ cacheRead: number;
121
+ cacheWrite: number;
122
+ }
123
+ /** 算不出(没有价目)返回 undefined,LoweringOutcome.costUsd 相应缺省 */
124
+ declare function costOf(usage: TokenUsage, cost: ModelCost | undefined): number | undefined;
125
+
126
+ /**
127
+ * Anthropic Messages 流 → 事件草稿。
128
+ *
129
+ * 只在流收尾时按拼好的内容块产出草稿(signature 在 content_block_stop 前才齐),增量经 onDelta 给 UI。
130
+ * 中断或出错时把已拼出的部分内容也交出去——日志要记录"发生过什么",是否继续由循环决定。
131
+ *
132
+ * 事件形状(厂商 SSE,按 data.type 分派,不看 event: 行;F0 A7 实测):
133
+ * message_start{ message: { id, model, usage: { input_tokens, cache_creation_input_tokens, cache_read_input_tokens } } }
134
+ * content_block_start{ index, content_block: text | thinking | redacted_thinking | tool_use }
135
+ * content_block_delta{ index, delta: text_delta | thinking_delta | signature_delta | input_json_delta }
136
+ * content_block_stop{ index }
137
+ * message_delta{ delta: { stop_reason, stop_sequence, stop_details? }, usage: { output_tokens, … } }
138
+ * message_stop / ping / error{ error: { type, message } }
139
+ * 未知字段一律忽略(厂商自带 "p" 填充;CF 网关原样透传)。
140
+ */
141
+
142
+ interface AnthropicUsage {
143
+ input_tokens?: unknown;
144
+ output_tokens?: unknown;
145
+ cache_creation_input_tokens?: unknown;
146
+ cache_read_input_tokens?: unknown;
147
+ }
148
+ interface AnthropicStreamInput {
149
+ messages: AsyncIterable<SseMessage>;
150
+ origin: ModelOrigin;
151
+ cost?: ModelCost;
152
+ signal?: AbortSignal;
153
+ timedOut?: () => boolean;
154
+ timeoutMs?: number;
155
+ }
156
+ /**
157
+ * Anthropic 的 input_tokens 本就不含缓存部分(与 core 语义一致);message_start 报输入侧,message_delta 报输出
158
+ * (累计值)并可能再报一次输入侧,以后到的为准。
159
+ */
160
+ declare function usageOf$2(start: AnthropicUsage | undefined, delta: AnthropicUsage | undefined): TokenUsage;
161
+ declare function consumeAnthropicStream(input: AnthropicStreamInput, ctx?: LoweringStreamContext): AsyncGenerator<CoreEventDraft, LoweringOutcome>;
162
+
163
+ /**
164
+ * Anthropic Messages 的有损矩阵(P7:有损必声明)。每条实际落点必须命中其中一条,矩阵里不能有死条目(loss-matrix.test.ts)。
165
+ * 与 lowering-pi 的 "anthropic-messages" 表逐格对照:能 exact 的一样(user / assistant-text / tool_use / tool_result /
166
+ * thinking-block / system),不同处只有三格——无签名 thinking 这里 dropped 而非 pi-ai 的"降为正文"、redacted 单列、
167
+ * tool_result 图片按模型能力处置。
168
+ */
169
+
170
+ declare const ANTHROPIC_LOSS_MATRIX: Readonly<Record<string, readonly LandingSpec[]>>;
171
+
172
+ /**
173
+ * 模型表与解析。只放一张**最小表**(上下文窗口、能力位、价目),`ModelRef` 找不到就抛;宿主用 `models` 选项
174
+ * 声明表外模型或覆盖表内字段(DECISIONS 2026-09-14 立项:表过期不阻塞使用)。
175
+ *
176
+ * 表里的数字来自厂商公开文档(2026-09-14 查阅);价目是每百万 token 美元,DeepSeek 有峰谷价、存的是峰值价。
177
+ */
178
+
179
+ /** 本包实现的三条线协议(F1 Chat Completions、F2 Anthropic Messages、F3 OpenAI Responses) */
180
+ type FetchApi = "openai-chat" | "anthropic-messages" | "openai-responses";
181
+ /** 当前已实现、可发请求的协议;toRequest / stream 遇到别的就抛 unsupported_api */
182
+ declare const SUPPORTED_APIS: ReadonlySet<string>;
183
+ /** 一个模型在本降级层眼里的全部描述。字段与 LoweringCapabilities 对齐,方言开关单独成组 */
184
+ interface FetchModel {
185
+ provider: string;
186
+ id: string;
187
+ api: FetchApi;
188
+ /** 协议根地址:Chat 在其后接 /chat/completions(OpenAI 给到 …/v1,DeepSeek 给到域名即可) */
189
+ baseUrl: string;
190
+ contextWindow: number;
191
+ maxOutputTokens: number;
192
+ /** 模型会产出 thinking / reasoning */
193
+ reasoning: boolean;
194
+ images?: boolean;
195
+ cost?: ModelCost;
196
+ /** 额外请求头(私有网关鉴权等),与降级层级别的 headers 合并、以模型级为准 */
197
+ headers?: Record<string, string>;
198
+ name?: string;
199
+ /**
200
+ * 是否接受会话中途的 `role:"system"` 消息(system_note 的 exact 落点)。缺省按协议定:Chat 为 true
201
+ * (OpenAI 官方经 CF 网关、DeepSeek 直连 2026-09-14 均实测到达)。
202
+ */
203
+ midConversationSystem?: boolean;
204
+ /**
205
+ * 凭证怎么带。缺省按协议:Chat / Responses 用 `Authorization: Bearer`,Anthropic 用 `x-api-key`。
206
+ * "none" 表示凭证在 headers 里(如 Cloudflare AI Gateway 的 cf-aig-authorization),不再向 apiKey 回调要 key。
207
+ */
208
+ auth?: "bearer" | "x-api-key" | "none";
209
+ /** Chat Completions 方言,只收已验证的扩展(Boss 定:严格按 OpenAI 规范,方言等真有人用再加) */
210
+ chat?: ChatDialect;
211
+ /** Anthropic Messages 线的请求整形选项(beta 头、缓存断点处置) */
212
+ anthropic?: AnthropicDialect;
213
+ /** OpenAI Responses 线的请求整形选项(说明角色、加密推理项) */
214
+ responses?: ResponsesDialect;
215
+ }
216
+ interface ResponsesDialect {
217
+ /**
218
+ * 系统提示与 system_note 用哪个角色。缺省:推理模型 developer、其它 system(与 lowering-pi 同一选择,矩阵同格)。
219
+ * 第三方 Responses 兼容上游不认 developer 时改 "system"。
220
+ */
221
+ systemRole?: "developer" | "system";
222
+ /**
223
+ * 推理模型是否带 `include: ["reasoning.encrypted_content"]`(缺省 true)。`store: false` 下 OpenAI 不保存推理状态,
224
+ * 只有加密项能把上一轮推理带回下一轮(F0 R3 实测回放接受、伪造 400);不带则 reasoning 项无法回放、一律 dropped。
225
+ * 第三方兼容上游不认 include 参数时可关。
226
+ */
227
+ encryptedReasoning?: boolean;
228
+ }
229
+ interface ChatDialect {
230
+ /**
231
+ * DeepSeek 的 `reasoning_content`(2026-09-14 直连实测):响应里思考正文与 `content` 平级;带 `tools` 的请求里
232
+ * **每条** assistant 消息都必须回传该字段(缺了 400,空串可过),不带 tools 时忽略。开了:读侧 → core.model_thinking,
233
+ * 写侧把自家 thinking 回填、没有就回空串。关着(OpenAI 官方):thinking 无处可放,矩阵记 dropped。
234
+ */
235
+ reasoningContent?: boolean;
236
+ }
237
+ /**
238
+ * 感知说明殿后(messages 末条是 system)时,"最后一条 user 末块"的断点没处打,B1 实测三种处置(spikes/b1-perception-cache):
239
+ * - "automatic"(缺省):改在请求顶层放 `cache_control`(Anthropic 自动缓存:断点落在最后一个可缓存块上),命中率与不注入持平;
240
+ * - "previous-user":仍打在最后一条 user 的末块上,实测低 3~6 个点(后续请求对不上前一次写入的前缀);
241
+ * - "drop":不打。只在上游自己会补自动缓存(如 DeepSeek 的兼容端口)时不吃亏。
242
+ * 把断点留在 system 消息上实测几乎零命中,不提供。
243
+ */
244
+ type MidSystemCacheBreakpoint = "automatic" | "previous-user" | "drop";
245
+ interface AnthropicDialect {
246
+ /**
247
+ * `anthropic-beta` 头的取值,用到才带(F0 结论:中途 system 不需要 beta;某些 beta 会抬高 reasoning_extraction
248
+ * 拒答率)。模型级 `headers["anthropic-beta"]` 若也给了,以 headers 为准。
249
+ */
250
+ betas?: readonly string[];
251
+ /** 是否打缓存断点(system 末块、tools 末项、最后一条 user 末块)。缺省 true;上游不认断点时可关 */
252
+ cacheBreakpoints?: boolean;
253
+ /** 断点存活期,缺省 5 分钟(不发 ttl 字段);"1h" 走 `{ type: "ephemeral", ttl: "1h" }` */
254
+ cacheTtl?: "5m" | "1h";
255
+ /** 说明殿后时的断点处置,缺省 "automatic" */
256
+ midSystemCacheBreakpoint?: MidSystemCacheBreakpoint;
257
+ /**
258
+ * 是否走 `defer_loading` + `tool_reference` 的原生延迟加载(L1,2026-09-15 经 CF 网关实测 Haiku 4.5 / Opus 5 均支持、GA 无 beta 头)。
259
+ * 缺省:provider 为 "anthropic" 时开,第三方 Anthropic 协议上游(DeepSeek 兼容端口等)关——它们对这两个字段的态度各异,
260
+ * 宿主实测接受后再显式打开。关着时 deferLoading 的工具不发、引用段展开成文本
261
+ */
262
+ deferredTools?: boolean;
263
+ }
264
+ /**
265
+ * 内置最小表。同一 provider + id 可能两条协议各一份(OpenAI 的 gpt-4o-mini 等既能走 Chat 也能走 Responses):
266
+ * `findBuiltin` 带 api 时精确取(工厂函数总是带),不带时取先列的一份——OpenAI 官方 id 的 Responses 条目列在前,所以
267
+ * `resolveModel({ provider: "openai", id })` 缺省走 OpenAI 的主协议 Responses(F3 起;F1 时只有 Chat 条目),要走 Chat 用
268
+ * `openaiChat()` 或在 `models` 里自己声明。Anthropic 列当前一代 + 常用上一代。
269
+ */
270
+ declare const BUILTIN_MODELS: readonly FetchModel[];
271
+ /** 带 api 精确取该协议的条目;不带取先列的一份 */
272
+ declare function findBuiltin(provider: string, id: string, api?: FetchApi): FetchModel | undefined;
273
+ /** 宿主声明的优先于内置表 */
274
+ declare function resolveModel(ref: ModelRef, extra?: readonly FetchModel[]): FetchModel;
275
+ /** 协议端点:baseUrl 去掉尾部斜杠再接路径 */
276
+ declare function endpointOf(model: FetchModel): string;
277
+
278
+ /**
279
+ * IR → Anthropic Messages 请求体,并为每条事件记落点。
280
+ *
281
+ * 与 Chat 线相比 Anthropic 规矩最多,这里逐条落实(规则原文 F0 实测,spikes/cf-gateway-fidelity):
282
+ * - **tool_result 紧跟**:同批 tool_result 必须在 tool_use 所在 assistant 的下一条 user 里;后移由 IR 完成,这里只把连续的
283
+ * user 侧内容(tool_result、用户消息、摘要)并进同一条 user(F0 A5b 实测同条 user 里 tool_result 后接文本可达);
284
+ * - **中途 system 摆放**(S1):不能是首条、必须紧跟 user(含只带 tool_result 的 user)、后接 assistant 或收尾。所以说明
285
+ * 一律攒到"下一条 assistant 之前"或末尾再放出;此刻前一条不是 user(是 assistant 或什么都没有)就退成 `<system_note>`
286
+ * 框住的 user 文本,记 lossy(user-role)。放出位置比时间线晚了一条 user 的,仍算 exact(说明只换位置,见 CLAUDE.md);
287
+ * - **thinking 回放**:带 signature 原样回放(F0 A7b 接受、伪造签名 400);无签名(流中断)与来自别家的一律 dropped 声明——
288
+ * 不像 pi-ai 那样降成正文,模型的私下推理不该以它"说过的话"出现在历史里;`redacted_thinking` 用 data 原样回放;
289
+ * - **缓存断点**:最多 4 个。我们打三处——system 末块、tools 末项、最后一条 user 末块(厂商按前缀向前找命中,20 块回看窗口);
290
+ * 说明殿后(末条是 system)时按 `midSystemCacheBreakpoint` 处置,缺省顶层 `cache_control`(B1 实测与不注入持平);
291
+ * - `max_tokens` 必填:宿主 requestOptions 没给就用模型声明的 maxOutputTokens;`thinking` 不缺省设置——Opus 5 起厂商缺省
292
+ * 就是 adaptive,是否开、开多深由宿主按模型代次决定(Fable 5.1 对 `type:"disabled"` 400);
293
+ * - **延迟加载**(L1,spikes/l1-deferred-tools 实测):`ToolSpec.deferLoading` → `defer_loading: true`,工具留在 tools 块里、
294
+ * 表整段不变;结果里的 `tool_reference` 段 → `tool_reference` 块由厂商就地展开。厂商规矩:tool_result 内引用不能与文本混放
295
+ * (文本段改放同条 user 里紧随的 text 块,记 lossy);引用指向 tools 里没有的名字 400(整段历史都校验,所以未绑定的引用一律
296
+ * 展开成文本);全部工具 defer_loading 400(此时不延迟);defer_loading 工具不能带 cache_control(断点打在最后一个非延迟工具上)。
297
+ * 能力位关着(第三方上游)时 deferLoading 的工具不发、引用段展开成文本。
298
+ */
299
+
300
+ interface AnthropicCacheControl {
301
+ type: "ephemeral";
302
+ ttl?: "5m" | "1h";
303
+ }
304
+ type AnthropicUserBlock = {
305
+ type: "text";
306
+ text: string;
307
+ cache_control?: AnthropicCacheControl;
308
+ } | {
309
+ type: "image";
310
+ source: {
311
+ type: "base64";
312
+ media_type: string;
313
+ data: string;
314
+ };
315
+ cache_control?: AnthropicCacheControl;
316
+ } | {
317
+ type: "tool_result";
318
+ tool_use_id: string;
319
+ content?: AnthropicToolResultBlock[];
320
+ is_error?: true;
321
+ cache_control?: AnthropicCacheControl;
322
+ };
323
+ /** 文本与图片块:user 消息与 tool_result 内容共用的形状 */
324
+ type AnthropicContentBlock = {
325
+ type: "text";
326
+ text: string;
327
+ } | {
328
+ type: "image";
329
+ source: {
330
+ type: "base64";
331
+ media_type: string;
332
+ data: string;
333
+ };
334
+ };
335
+ type AnthropicToolResultBlock = AnthropicContentBlock
336
+ /** 工具定义引用:厂商就地展开成完整定义,不能与其他块混放(L1) */
337
+ | {
338
+ type: "tool_reference";
339
+ tool_name: string;
340
+ };
341
+ type AnthropicAssistantBlock = {
342
+ type: "text";
343
+ text: string;
344
+ } | {
345
+ type: "thinking";
346
+ thinking: string;
347
+ signature: string;
348
+ } | {
349
+ type: "redacted_thinking";
350
+ data: string;
351
+ } | {
352
+ type: "tool_use";
353
+ id: string;
354
+ name: string;
355
+ input: Record<string, unknown>;
356
+ };
357
+ type AnthropicMessage = {
358
+ role: "user";
359
+ content: AnthropicUserBlock[];
360
+ } | {
361
+ role: "assistant";
362
+ content: AnthropicAssistantBlock[];
363
+ } | {
364
+ role: "system";
365
+ content: {
366
+ type: "text";
367
+ text: string;
368
+ }[];
369
+ };
370
+ interface AnthropicTool {
371
+ name: string;
372
+ description: string;
373
+ input_schema: Record<string, unknown>;
374
+ /** 声明但不载入上下文,历史里出现 tool_reference 后才可见;不能与 cache_control 同在(L1) */
375
+ defer_loading?: true;
376
+ cache_control?: AnthropicCacheControl;
377
+ }
378
+ /** 发出去的请求体本体。宿主的 requestOptions 先铺、我们的字段后盖:model / messages / system / tools / stream 不可被覆盖 */
379
+ interface AnthropicRequestBody extends Record<string, unknown> {
380
+ model: string;
381
+ max_tokens: number;
382
+ system?: {
383
+ type: "text";
384
+ text: string;
385
+ cache_control?: AnthropicCacheControl;
386
+ }[];
387
+ messages: AnthropicMessage[];
388
+ tools?: AnthropicTool[];
389
+ stream: true;
390
+ cache_control?: AnthropicCacheControl;
391
+ }
392
+ interface AnthropicEncodeInput {
393
+ ir: readonly IrItem[];
394
+ events: readonly Event[];
395
+ model: FetchModel;
396
+ capabilities: LoweringCapabilities;
397
+ tools?: readonly ToolSpec[];
398
+ systemPrompt?: string;
399
+ requestOptions?: Record<string, unknown>;
400
+ }
401
+ /** Anthropic 每个请求最多 4 个断点(顶层自动缓存也占一个),超出即 400 */
402
+ declare const MAX_ANTHROPIC_BREAKPOINTS = 4;
403
+ declare function encodeAnthropicRequest(input: AnthropicEncodeInput): {
404
+ body: AnthropicRequestBody;
405
+ landings: LandingRecord[];
406
+ };
407
+
408
+ /**
409
+ * 按模型声明能力(技术方案 §11)。脑子模块只看这些布尔值,不看模型名。
410
+ */
411
+
412
+ declare function capabilitiesOf(model: FetchModel): LoweringCapabilities;
413
+
414
+ /**
415
+ * Chat Completions 流 → 事件草稿。
416
+ *
417
+ * 只在流收尾时按拼好的块产出草稿(与 lowering-pi 同策略:日志里只存完整块),增量经 onDelta 给 UI。
418
+ * 中断或出错时把已拼出的部分内容也交出去——日志要记录"发生过什么",是否继续由循环决定。
419
+ *
420
+ * chunk 形状(OpenAI 规范 + DeepSeek 已验证的 `delta.reasoning_content`):
421
+ * choices[0].delta.{ content, reasoning_content, tool_calls[{ index, id?, function: { name?, arguments? } }] }
422
+ * choices[0].finish_reason 在末块;usage 在带 stream_options.include_usage 的最后一个 chunk(choices 可能为空数组)
423
+ * `data: [DONE]` 收尾。未知字段一律忽略(CF 网关会多个 "p",OpenAI 常带 system_fingerprint / obfuscation)。
424
+ */
425
+
426
+ interface ChatUsage {
427
+ prompt_tokens?: unknown;
428
+ completion_tokens?: unknown;
429
+ prompt_tokens_details?: {
430
+ cached_tokens?: unknown;
431
+ } | null;
432
+ /** DeepSeek 原生字段,与 prompt_tokens_details.cached_tokens 同值 */
433
+ prompt_cache_hit_tokens?: unknown;
434
+ }
435
+ interface ChatStreamInput {
436
+ messages: AsyncIterable<SseMessage>;
437
+ origin: ModelOrigin;
438
+ cost?: ModelCost;
439
+ /** 宿主中止信号:读流被中止时据此判"aborted"还是本地超时 */
440
+ signal?: AbortSignal;
441
+ timedOut?: () => boolean;
442
+ timeoutMs?: number;
443
+ }
444
+ /** OpenAI 的 prompt_tokens 含缓存命中部分;core 的 input 是未命中数,所以要减掉 */
445
+ declare function usageOf$1(u: ChatUsage | undefined): TokenUsage;
446
+ declare function consumeChatStream(input: ChatStreamInput, ctx?: LoweringStreamContext): AsyncGenerator<CoreEventDraft, LoweringOutcome>;
447
+
448
+ /**
449
+ * Chat Completions 的有损矩阵(P7:有损必声明)。事件 type → 可能落点;toRequest 记录的每条实际落点必须命中其中一条,
450
+ * 矩阵里不能有从未命中的死条目(loss-matrix.test.ts)。新增事件类型或改落点不补表,测试就红。
451
+ */
452
+
453
+ declare const CHAT_LOSS_MATRIX: Readonly<Record<string, readonly LandingSpec[]>>;
454
+
455
+ /**
456
+ * IR → OpenAI Chat Completions 请求体,并为每条事件记落点。
457
+ *
458
+ * 严格按 OpenAI 官方规范(Boss 定),方言只收 DeepSeek 已验证的 `reasoning_content`(见 models.ts ChatDialect)。
459
+ * 角色只有 system / user / assistant / tool 四种,这是全包唯一出现"角色"的地方之一(宪法二)。
460
+ *
461
+ * Chat 线天然有损、矩阵里如实声明:
462
+ * - thinking 没有回放位(无签名、无加密项)——除 DeepSeek 方言外 dropped;
463
+ * - 没有显式缓存断点——什么都不做(厂商自动前缀缓存);
464
+ * - assistant 的 content 是单个字符串(DeepSeek 只接受 string | null)——同一轮多段正文合并,lossy(merged-text);
465
+ * - tool 消息没有错误位——isError 以文本前缀表达,lossy;tool 消息只收文本——图片换成占位文本,lossy。
466
+ */
467
+
468
+ type ChatContentPart = {
469
+ type: "text";
470
+ text: string;
471
+ } | {
472
+ type: "image_url";
473
+ image_url: {
474
+ url: string;
475
+ };
476
+ };
477
+ interface ChatToolCall {
478
+ id: string;
479
+ type: "function";
480
+ function: {
481
+ name: string;
482
+ arguments: string;
483
+ };
484
+ }
485
+ type ChatMessage = {
486
+ role: "system";
487
+ content: string;
488
+ } | {
489
+ role: "user";
490
+ content: string | ChatContentPart[];
491
+ } | {
492
+ role: "assistant";
493
+ content: string | null;
494
+ tool_calls?: ChatToolCall[];
495
+ reasoning_content?: string;
496
+ } | {
497
+ role: "tool";
498
+ tool_call_id: string;
499
+ content: string;
500
+ };
501
+ interface ChatTool {
502
+ type: "function";
503
+ function: {
504
+ name: string;
505
+ description: string;
506
+ parameters: Record<string, unknown>;
507
+ };
508
+ }
509
+ /** 发出去的请求体本体。宿主的 requestOptions 先铺、我们的字段后盖:messages / tools / model / stream 不可被覆盖 */
510
+ interface ChatRequestBody extends Record<string, unknown> {
511
+ model: string;
512
+ messages: ChatMessage[];
513
+ tools?: ChatTool[];
514
+ stream: true;
515
+ stream_options: {
516
+ include_usage: true;
517
+ };
518
+ }
519
+ interface ChatEncodeInput {
520
+ ir: readonly IrItem[];
521
+ events: readonly Event[];
522
+ model: FetchModel;
523
+ capabilities: LoweringCapabilities;
524
+ tools?: readonly ToolSpec[];
525
+ systemPrompt?: string;
526
+ requestOptions?: Record<string, unknown>;
527
+ }
528
+ declare function encodeChatRequest(input: ChatEncodeInput): {
529
+ body: ChatRequestBody;
530
+ landings: LandingRecord[];
531
+ };
532
+
533
+ /**
534
+ * 一行拿到"模型 + 降级层":`deepseek("deepseek-flash", { apiKey })`、`openaiChat("gpt-4o-mini", { apiKey })`、
535
+ * `openai("gpt-5-mini", { apiKey })`(Responses)、`anthropic("claude-opus-5", { apiKey })`;任何 OpenAI 兼容端点用
536
+ * `chatCompletions("qwen-max", { provider: "qwen", baseUrl, apiKey })`,任何 Anthropic 协议端点(DeepSeek 兼容端口、CF 网关)用
537
+ * `anthropicMessages(id, { provider, baseUrl, apiKey })`,任何 Responses 协议端点用 `openaiResponses(id, { provider, baseUrl, apiKey })`。
538
+ * 返回 BoundModel,直接给 `createAgent({ model })`;要多模型共享一个降级层就自己 new FetchLowering。
539
+ *
540
+ * 表内模型取内置定义再按选项覆盖;表外模型用保守缺省(128k 窗口、16k 输出、无推理、不收图),宿主按需覆盖。
541
+ * 本包不读环境变量,apiKey 必填、由宿主决定来源(auth:"none" 时可给空串占位)。
542
+ */
543
+
544
+ interface ModelOptions {
545
+ apiKey: string;
546
+ /** 协议根地址(Chat 在其后接 /chat/completions,Anthropic 接 /messages);表内模型缺省用厂商官方地址 */
547
+ baseUrl?: string;
548
+ contextWindow?: number;
549
+ maxOutputTokens?: number;
550
+ reasoning?: boolean;
551
+ images?: boolean;
552
+ cost?: ModelCost;
553
+ /** 上游是否接受中途 role:"system";Chat 缺省 true,Anthropic 按模型族推断 */
554
+ midConversationSystem?: boolean;
555
+ /** Chat 方言开关,见 models.ts ChatDialect */
556
+ chat?: ChatDialect;
557
+ /** Anthropic 线的 beta 头与缓存断点处置,见 models.ts AnthropicDialect */
558
+ anthropic?: AnthropicDialect;
559
+ /** Responses 线的说明角色与加密推理项开关,见 models.ts ResponsesDialect */
560
+ responses?: ResponsesDialect;
561
+ /** 凭证怎么带;网关自带凭证头时用 "none" 并把头放 headers */
562
+ auth?: FetchModel["auth"];
563
+ headers?: Record<string, string>;
564
+ /** 铺进请求体的额外字段(max_tokens、temperature、thinking …) */
565
+ requestOptions?: Record<string, unknown>;
566
+ fetch?: typeof globalThis.fetch;
567
+ timeoutMs?: number;
568
+ trustMarkers?: boolean;
569
+ }
570
+ /** @deprecated 改名为 ModelOptions(三条线共用同一组选项),保留别名 */
571
+ type ChatModelOptions = ModelOptions;
572
+ interface ProviderModelOptions extends ModelOptions {
573
+ /** 用作 ModelRef.provider 与 apiKey 回调的键;表外厂商必填 */
574
+ provider: string;
575
+ }
576
+ /** @deprecated 改名为 ProviderModelOptions */
577
+ type ChatCompletionsOptions = ProviderModelOptions;
578
+ /** 内置定义打底,选项里给了的字段覆盖;表外模型从保守缺省起 */
579
+ declare function definitionOf(provider: string, id: string, api: FetchApi, opts: Omit<ModelOptions, "apiKey" | "requestOptions" | "fetch" | "timeoutMs" | "trustMarkers">): FetchModel;
580
+ /** 任何 OpenAI Chat Completions 兼容端点 */
581
+ declare function chatCompletions(id: string, opts: ProviderModelOptions): BoundModel;
582
+ /** DeepSeek 直连:缺省官方地址、开 reasoning_content 方言(带 tools 时缺它 400) */
583
+ declare function deepseek(id: string, opts: ModelOptions): BoundModel;
584
+ /** OpenAI 官方 Chat Completions(推理系列请用 Responses 线的 openai()) */
585
+ declare function openaiChat(id: string, opts: ModelOptions): BoundModel;
586
+ /**
587
+ * 任何 OpenAI Responses 协议端点:Cloudflare AI Gateway 透传路径(`auth: "none"` + `cf-aig-authorization` 头)、
588
+ * 兼容网关。表外模型从保守缺省起(reasoning 假、不收图),宿主按需声明;不认 developer 角色或 include 参数的上游用 `responses` 方言关掉。
589
+ */
590
+ declare function openaiResponses(id: string, opts: ProviderModelOptions): BoundModel;
591
+ /**
592
+ * OpenAI 官方 Responses:缺省官方地址、Bearer 鉴权;表内模型带价目与能力位。`reasoning` 参数不缺省设置——
593
+ * gpt-5 缺省 medium、gpt-5.1 起缺省 none,开不开、开多深由宿主按型号在 requestOptions 里定(与 Anthropic 线的 thinking 同一原则)。
594
+ */
595
+ declare function openai(id: string, opts: ModelOptions): BoundModel;
596
+ /**
597
+ * 任何 Anthropic Messages 协议端点:DeepSeek 的兼容端口(`provider: "deepseek", baseUrl: "https://api.deepseek.com/anthropic"`)、
598
+ * Cloudflare AI Gateway 透传路径(`auth: "none"` + `cf-aig-authorization` 头)。表外模型从保守缺省起(reasoning 假、不收图),宿主按需声明。
599
+ */
600
+ declare function anthropicMessages(id: string, opts: ProviderModelOptions): BoundModel;
601
+ /** Anthropic 官方直连:缺省官方地址、x-api-key 鉴权;表内模型带价目与能力位 */
602
+ declare function anthropic(id: string, opts: ModelOptions): BoundModel;
603
+
604
+ /**
605
+ * 三线共用的 fetch 封装:超时、宿主中止、非 2xx 转成带状态码的错误。
606
+ *
607
+ * 错误文案刻意用 "<status> <body>" 格式(与两家官方 SDK 同款):core 的瞬断判据(retry.ts)先看错误对象上的
608
+ * `status` / `headers`,再看文案开头的三位数字,所以这里抛出的错误不用任何额外约定就能被正确判成
609
+ * "429 / 5xx 重试、400 不重试"。`headers` 保留原样,`x-should-retry` 由 core 自己读。
610
+ *
611
+ * 不读环境变量、不碰 node:*,Workers / Deno / 浏览器同一份代码。
612
+ */
613
+ declare class HttpError extends Error {
614
+ readonly status: number;
615
+ readonly headers: Headers;
616
+ /** 响应正文原文(厂商错误体或网关信封,不假定形状) */
617
+ readonly body: string;
618
+ readonly url: string;
619
+ readonly name = "HttpError";
620
+ constructor(status: number, headers: Headers,
621
+ /** 响应正文原文(厂商错误体或网关信封,不假定形状) */
622
+ body: string, url: string);
623
+ }
624
+ /** 一次请求的时限(整条响应,含流式读完),与两家 SDK 缺省一致 */
625
+ declare const DEFAULT_TIMEOUT_MS = 600000;
626
+ interface RequestSignals {
627
+ /** 交给 fetch 与流读取的组合信号 */
628
+ signal: AbortSignal;
629
+ /** 中止后判定是哪一方:宿主中止(ctx.signal)还是本地超时 */
630
+ timedOut: () => boolean;
631
+ }
632
+ /**
633
+ * 把宿主的 signal 与本地超时合成一个信号。超时到点后 `timedOut()` 为真;宿主中止优先(两者都发生时算宿主中止,
634
+ * 因为宿主中止是有意为之、不该被当成瞬断重试)。
635
+ */
636
+ declare function requestSignals(hostSignal: AbortSignal | undefined, timeoutMs: number): RequestSignals;
637
+ interface PostJsonInput {
638
+ url: string;
639
+ headers: Record<string, string>;
640
+ body: unknown;
641
+ signal: AbortSignal;
642
+ fetch?: typeof globalThis.fetch;
643
+ }
644
+ /**
645
+ * POST JSON;非 2xx 读完正文抛 HttpError。网络层失败(DNS、连接被掐、超时)由 fetch 自己抛出,原样上抛——
646
+ * 那些错误对象上的 `cause.code` / `name` 正是 core 判瞬断要看的东西,包一层反而会盖掉。
647
+ */
648
+ declare function postJson(input: PostJsonInput): Promise<Response>;
649
+
650
+ /**
651
+ * FetchLowering:@reinsjs/core 的 Lowering 接口只用 fetch 的实现(零依赖、零 node:*)。
652
+ *
653
+ * 与 lowering-pi 的分工见 DECISIONS 2026-09-14「lowering-fetch 立项」:两包并存,宿主 import 谁用谁。
654
+ * 这里 `LoweredRequest.payload.body` 就是真正发出去的请求体——没有第二跳改写,排查 400 直接看它。
655
+ */
656
+
657
+ /** Anthropic Messages 的协议版本头,当前唯一稳定值 */
658
+ declare const ANTHROPIC_VERSION = "2023-06-01";
659
+ interface FetchLoweringOptions {
660
+ /** 按 provider 取 key;返回 undefined 视为未配置。本包不读环境变量,由宿主决定来源 */
661
+ apiKey: (provider: string) => string | undefined;
662
+ /** 自定义 fetch(测试注入、代理、Workers 绑定);缺省 globalThis.fetch */
663
+ fetch?: typeof globalThis.fetch;
664
+ /** 附加请求头,所有请求都带;模型级 headers 优先 */
665
+ headers?: Record<string, string>;
666
+ /** 内置表之外的模型,或覆盖表内同名模型 */
667
+ models?: readonly FetchModel[];
668
+ /**
669
+ * 铺进请求体的额外字段(max_tokens、temperature、DeepSeek 的 thinking / reasoning_effort、OpenAI 的
670
+ * parallel_tool_calls …),键名以厂商文档为准。按模型返回,便于分族配置。messages / tools / model / stream 不可覆盖。
671
+ */
672
+ requestOptions?: (model: ModelRef) => Record<string, unknown>;
673
+ /** 整条请求(含读完流)的时限,缺省 600 000 ms;到点判 error(可重试),宿主 signal 中止判 aborted */
674
+ timeoutMs?: number;
675
+ /**
676
+ * trust 标注(技术方案 §14):trust=untrusted 的事件翻译时包上 `<untrusted source="tool:<name>">…</untrusted>`,
677
+ * 事件本身不动。缺省 true;传 false 关掉是宿主自担提示注入风险
678
+ */
679
+ trustMarkers?: boolean;
680
+ }
681
+ /** 对外暴露的请求体:就是要 POST 的 JSON,鉴权头与 URL 在 stream 时才拼(不进 payload,日志里不落凭证) */
682
+ interface FetchLoweredPayload {
683
+ api: FetchApi;
684
+ body: Record<string, unknown>;
685
+ }
686
+ declare class FetchLowering implements Lowering<FetchLoweredPayload> {
687
+ private readonly opts;
688
+ private readonly extraModels;
689
+ private readonly timeoutMs;
690
+ constructor(opts: FetchLoweringOptions);
691
+ capabilities(ref: ModelRef): LoweringCapabilities;
692
+ toRequest(input: ToRequestInput): LoweredRequest<FetchLoweredPayload>;
693
+ stream(req: LoweredRequest<FetchLoweredPayload>, ctx?: LoweringStreamContext): AsyncGenerator<CoreEventDraft, LoweringOutcome>;
694
+ /**
695
+ * 鉴权头按协议缺省(Chat / Responses bearer、Anthropic x-api-key),模型声明 auth:"none" 时凭证由 headers 自带。
696
+ * Anthropic 线固定带 `anthropic-version`,`anthropic-beta` 只在模型声明了 betas 时带(F0 结论:用到才带);模型级 headers 最后盖。
697
+ */
698
+ private headersFor;
699
+ }
700
+
701
+ /**
702
+ * OpenAI Responses 流 → 事件草稿。
703
+ *
704
+ * 只在流收尾时按拼好的输出项产出草稿(reasoning 项的 encrypted_content 在 output_item.done 才齐),增量经 onDelta 给 UI。
705
+ * 中断或出错时把已拼出的部分内容也交出去——日志要记录"发生过什么",是否继续由循环决定。
706
+ *
707
+ * 事件形状(厂商 SSE,按 data.type 分派;F0 R2 实测事件序列完整):
708
+ * response.created / response.in_progress { response: { id, model } }
709
+ * response.output_item.added { output_index, item: reasoning | message | function_call | … }
710
+ * response.reasoning_summary_part.added / response.reasoning_summary_text.delta { output_index, delta } / response.reasoning_text.delta
711
+ * response.output_text.delta / response.refusal.delta { output_index, delta }
712
+ * response.function_call_arguments.delta { output_index, delta } / response.function_call_arguments.done { arguments }
713
+ * response.output_item.done { output_index, item } ← 项的最终形状(reasoning 带 encrypted_content、message 带 id)
714
+ * response.completed / response.incomplete { response: { status, incomplete_details, usage, output } }
715
+ * response.failed { response: { error: { code, message } } } / error { code, message }
716
+ * 未知字段一律忽略(CF 网关会多个 "p")。
717
+ */
718
+
719
+ interface ResponsesUsage {
720
+ input_tokens?: unknown;
721
+ output_tokens?: unknown;
722
+ input_tokens_details?: {
723
+ cached_tokens?: unknown;
724
+ cache_write_tokens?: unknown;
725
+ } | null;
726
+ output_tokens_details?: {
727
+ reasoning_tokens?: unknown;
728
+ } | null;
729
+ }
730
+ interface ResponsesStreamInput {
731
+ messages: AsyncIterable<SseMessage>;
732
+ origin: ModelOrigin;
733
+ cost?: ModelCost;
734
+ signal?: AbortSignal;
735
+ timedOut?: () => boolean;
736
+ timeoutMs?: number;
737
+ }
738
+ /**
739
+ * OpenAI 的 input_tokens 含缓存命中与缓存写入部分(F0 R1 / R4 实测 `input_tokens_details.cached_tokens` / `cache_write_tokens`),
740
+ * core 的 input 是未命中数,所以两者都要减掉。
741
+ */
742
+ declare function usageOf(u: ResponsesUsage | undefined): TokenUsage;
743
+ declare function consumeResponsesStream(input: ResponsesStreamInput, ctx?: LoweringStreamContext): AsyncGenerator<CoreEventDraft, LoweringOutcome>;
744
+
745
+ /**
746
+ * OpenAI Responses 的有损矩阵(P7:有损必声明)。每条实际落点必须命中其中一条,矩阵里不能有死条目(loss-matrix.test.ts)。
747
+ * 与 lowering-pi 的 "openai-responses" 表逐格对照:能 exact 的一样(user / assistant-message / reasoning-item / function_call /
748
+ * function_call_output / developer / system)。不同处三格——无加密项或别家的 reasoning 这里 dropped 而非 pi-ai 的
749
+ * "降为正文 / 厂商看着办"、tool_call 入参不是对象也照发(arguments 本就是 JSON 字符串,不必包 { value })、
750
+ * tool_result 的 isError 以前缀表达(协议没有错误位)并按模型能力处置图片。
751
+ */
752
+
753
+ declare const RESPONSES_LOSS_MATRIX: Readonly<Record<string, readonly LandingSpec[]>>;
754
+
755
+ /**
756
+ * IR → OpenAI Responses 请求体,并为每条事件记落点。
757
+ *
758
+ * Responses 是三条线里规矩最少的一条,但有两处与"时间线是唯一真源"直接相关,这里逐条落实(规则原文 F0 实测,
759
+ * spikes/cf-gateway-fidelity 的 R2 / R3 / R3b):
760
+ * - **服务端不留状态**:`store: false` 强制、宿主传的 `previous_response_id` 剥掉。每个请求把模型该看到的历史全量放进 `input`,
761
+ * 与别的两条线同一形状;OpenAI 侧的会话状态永远不是我们依赖的东西。
762
+ * - **reasoning 回放判据是 encrypted_content**:推理模型缺省带 `include: ["reasoning.encrypted_content"]`,上一轮的 reasoning 项
763
+ * (整项 JSON 存在事件 `replay.thinkingSignature` 里,与 lowering-pi 同字段)原样放回 `input`;没有加密项(未开 include、流中断)
764
+ * 或来自别家的一律 dropped 声明,不降成正文。伪造的加密项厂商回原文 400,所以回放的必须是原件。
765
+ * - **中途 system 不用归位**:`developer` / `system` 消息在 `input` 里任意位置合法(F0 R3 中途 developer 到达);推理模型用
766
+ * developer、其它用 system(与 pi 版矩阵同格),宿主可用 `responses.systemRole` 钉死。
767
+ * - **工具调用两个 id**:`call_id`(配对 function_call_output 用)是 core 的 toolCallId;`fc_` 项 id 存 `replay.itemId`,只在同一模型
768
+ * 回放时带回——OpenAI 会校验 fc 项与 rs 项的配对,换了模型就不带(与 pi-ai 同一取向)。
769
+ * - `reasoning` / `max_output_tokens` 不缺省设置:gpt-5 缺省 medium、gpt-5.1 起缺省 none,开不开由宿主按型号在 requestOptions 里定
770
+ * (与 Anthropic 线的 thinking 同一原则)。
771
+ */
772
+
773
+ type ResponsesInputContent = {
774
+ type: "input_text";
775
+ text: string;
776
+ } | {
777
+ type: "input_image";
778
+ image_url: string;
779
+ detail: "auto";
780
+ };
781
+ type ResponsesInputItem =
782
+ /** user / developer / system 消息 */
783
+ {
784
+ role: "user" | "developer" | "system";
785
+ content: ResponsesInputContent[];
786
+ }
787
+ /** 上一轮的 assistant 正文:type:message 输出项原样放回 */
788
+ | {
789
+ type: "message";
790
+ role: "assistant";
791
+ id: string;
792
+ status: "completed";
793
+ content: {
794
+ type: "output_text";
795
+ text: string;
796
+ annotations: [];
797
+ }[];
798
+ phase?: string;
799
+ }
800
+ /** 上一轮的 reasoning 项:整项原样放回(id / summary / encrypted_content 等字段以厂商给的为准) */
801
+ | {
802
+ type: "reasoning";
803
+ id: string;
804
+ encrypted_content: string;
805
+ [k: string]: unknown;
806
+ } | {
807
+ type: "function_call";
808
+ id?: string;
809
+ call_id: string;
810
+ name: string;
811
+ arguments: string;
812
+ } | {
813
+ type: "function_call_output";
814
+ call_id: string;
815
+ output: string | ResponsesInputContent[];
816
+ };
817
+ interface ResponsesTool {
818
+ type: "function";
819
+ name: string;
820
+ description: string;
821
+ parameters: Record<string, unknown>;
822
+ /** 我们的 JSON Schema 不保证满足 strict 模式(additionalProperties:false、全部 required),一律不开 */
823
+ strict: false;
824
+ }
825
+ /** 发出去的请求体本体。宿主的 requestOptions 先铺、我们的字段后盖:model / input / tools / stream / store 不可被覆盖 */
826
+ interface ResponsesRequestBody extends Record<string, unknown> {
827
+ model: string;
828
+ input: ResponsesInputItem[];
829
+ tools?: ResponsesTool[];
830
+ stream: true;
831
+ store: false;
832
+ include?: string[];
833
+ }
834
+ interface ResponsesEncodeInput {
835
+ ir: readonly IrItem[];
836
+ events: readonly Event[];
837
+ model: FetchModel;
838
+ capabilities: LoweringCapabilities;
839
+ tools?: readonly ToolSpec[];
840
+ systemPrompt?: string;
841
+ requestOptions?: Record<string, unknown>;
842
+ }
843
+ /** replay.thinkingSignature 里存的 reasoning 项:必须是带非空 encrypted_content 的对象才可回放 */
844
+ declare function reasoningItemOf(replay: Record<string, unknown>): Record<string, unknown> | undefined;
845
+ declare function encodeResponsesRequest(input: ResponsesEncodeInput): {
846
+ body: ResponsesRequestBody;
847
+ landings: LandingRecord[];
848
+ };
849
+
850
+ /** api → 事件 type → 可能落点;与 lowering-pi 的 LOSS_MATRIX 同形,逐格对照用 */
851
+ declare const LOSS_MATRIX: LossMatrix;
852
+ /** 查某 api 下某事件 type 的声明落点;ext.* 归到通配项 */
853
+ declare function declaredLandings(api: string, type: string): readonly _reinsjs_core.LandingSpec[];
854
+
855
+ export { ANTHROPIC_LOSS_MATRIX, ANTHROPIC_VERSION, type AnthropicAssistantBlock, type AnthropicCacheControl, type AnthropicDialect, type AnthropicMessage, type AnthropicRequestBody, type AnthropicTool, type AnthropicUserBlock, BUILTIN_MODELS, CHAT_LOSS_MATRIX, type ChatCompletionsOptions, type ChatContentPart, type ChatDialect, type ChatMessage, type ChatModelOptions, type ChatRequestBody, type ChatTool, type ChatToolCall, DEFAULT_TIMEOUT_MS, type FetchApi, type FetchLoweredPayload, FetchLowering, type FetchLoweringOptions, type FetchModel, HttpError, type IrBlock, type IrItem, LOSS_MATRIX, MAX_ANTHROPIC_BREAKPOINTS, type MidSystemCacheBreakpoint, type ModelCost, type ModelOptions, type ModelOrigin, type ProviderModelOptions, RESPONSES_LOSS_MATRIX, type ResponsesDialect, type ResponsesInputContent, type ResponsesInputItem, type ResponsesRequestBody, type ResponsesTool, SUPPORTED_APIS, type SseMessage, anthropic, anthropicMessages, usageOf$2 as anthropicUsageOf, capabilitiesOf, chatCompletions, usageOf$1 as chatUsageOf, consumeAnthropicStream, consumeChatStream, consumeResponsesStream, costOf, declaredLandings, deepseek, definitionOf, encodeAnthropicRequest, encodeChatRequest, encodeResponsesRequest, endpointOf, eventsToIr, findBuiltin, foreignOrigin, openai, openaiChat, openaiResponses, orderLandings, parseSse, postJson, reasoningItemOf, requestSignals, resolveModel, usageOf as responsesUsageOf, sameOrigin };