@providerkit/core 0.1.0 → 0.3.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.
Files changed (61) hide show
  1. package/README.md +35 -158
  2. package/dist/context.d.ts.map +1 -1
  3. package/dist/context.js +8 -0
  4. package/dist/context.js.map +1 -1
  5. package/dist/errors.d.ts +36 -0
  6. package/dist/errors.d.ts.map +1 -1
  7. package/dist/errors.js +75 -2
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +4 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/key-pool.d.ts +60 -0
  14. package/dist/key-pool.d.ts.map +1 -0
  15. package/dist/key-pool.js +235 -0
  16. package/dist/key-pool.js.map +1 -0
  17. package/dist/providers/anthropic.d.ts +10 -6
  18. package/dist/providers/anthropic.d.ts.map +1 -1
  19. package/dist/providers/anthropic.js +30 -14
  20. package/dist/providers/anthropic.js.map +1 -1
  21. package/dist/providers/gemini.d.ts +40 -0
  22. package/dist/providers/gemini.d.ts.map +1 -0
  23. package/dist/providers/gemini.js +303 -0
  24. package/dist/providers/gemini.js.map +1 -0
  25. package/dist/providers/openai.d.ts +38 -1
  26. package/dist/providers/openai.d.ts.map +1 -1
  27. package/dist/providers/openai.js +122 -16
  28. package/dist/providers/openai.js.map +1 -1
  29. package/dist/providers/responses.d.ts +38 -0
  30. package/dist/providers/responses.d.ts.map +1 -0
  31. package/dist/providers/responses.js +341 -0
  32. package/dist/providers/responses.js.map +1 -0
  33. package/dist/rate-limit.d.ts +29 -0
  34. package/dist/rate-limit.d.ts.map +1 -0
  35. package/dist/rate-limit.js +194 -0
  36. package/dist/rate-limit.js.map +1 -0
  37. package/dist/transport.d.ts +18 -5
  38. package/dist/transport.d.ts.map +1 -1
  39. package/dist/transport.js +61 -35
  40. package/dist/transport.js.map +1 -1
  41. package/dist/types.d.ts +13 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js +7 -2
  44. package/dist/types.js.map +1 -1
  45. package/dist/zod.d.ts +8 -1
  46. package/dist/zod.d.ts.map +1 -1
  47. package/dist/zod.js +9 -2
  48. package/dist/zod.js.map +1 -1
  49. package/package.json +2 -2
  50. package/src/context.ts +7 -0
  51. package/src/errors.ts +82 -2
  52. package/src/index.ts +4 -0
  53. package/src/key-pool.ts +272 -0
  54. package/src/providers/anthropic.ts +41 -20
  55. package/src/providers/gemini.ts +386 -0
  56. package/src/providers/openai.ts +153 -16
  57. package/src/providers/responses.ts +455 -0
  58. package/src/rate-limit.ts +217 -0
  59. package/src/transport.ts +61 -35
  60. package/src/types.ts +19 -2
  61. package/src/zod.ts +12 -2
@@ -0,0 +1,303 @@
1
+ // Gemini adapter — SSE from POST /v1beta/models/{model}:streamGenerateContent.
2
+ //
3
+ // Native Gemini, not its OpenAI-compatible shim: only this endpoint carries
4
+ // thought signatures, and a signature dropped on the way back costs the model
5
+ // its own chain of thought on the next turn. Written straight against the REST
6
+ // wire rather than @google/genai, because this package ships zero dependencies
7
+ // and the SDK is a Node-shaped one.
8
+ import { streamError } from "../errors.js";
9
+ import { parseToolArgs } from "../tool-args.js";
10
+ import { streamSse, apiUrl } from "../transport.js";
11
+ const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com";
12
+ /**
13
+ * Gemini 3's thinking dial. `none` is MINIMAL rather than a 0 budget: the Pro
14
+ * models reject a hard 0, so the only way to say "think as little as possible"
15
+ * without a 400 is the lowest level.
16
+ *
17
+ * Sent as the REST enum NAMES. The SDK's `ThinkingLevel` members serialize to
18
+ * exactly these strings, so nothing is lost by writing them out.
19
+ */
20
+ const THINKING_LEVEL = {
21
+ none: "MINIMAL",
22
+ low: "LOW",
23
+ medium: "MEDIUM",
24
+ high: "HIGH",
25
+ max: "HIGH",
26
+ };
27
+ function isJsonObject(value) {
28
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29
+ }
30
+ /**
31
+ * Tool-call arguments as the OBJECT Gemini's `functionCall.args` requires.
32
+ *
33
+ * A bare JSON scalar or array is wrapped rather than rejected — the shared
34
+ * `parseToolArgs` drops a non-object as a protocol violation, which is right
35
+ * for reading a fresh tool call and wrong here, where replaying `{}` deletes an
36
+ * argument the model did send. Everything else defers to it, so a truncated or
37
+ * double-escaped argument string is salvaged on replay rather than degraded to
38
+ * `{}`.
39
+ */
40
+ function parseArgs(json) {
41
+ try {
42
+ const parsed = JSON.parse(json);
43
+ if (!isJsonObject(parsed))
44
+ return { value: parsed };
45
+ }
46
+ catch {
47
+ // Unparseable — the salvage below is the whole point.
48
+ }
49
+ return parseToolArgs(json);
50
+ }
51
+ /** Same rule for a tool RESULT, which `functionResponse.response` also requires
52
+ * as an object. Plain text (the common case) rides under `output`. */
53
+ function toResponseObject(content) {
54
+ try {
55
+ const parsed = JSON.parse(content);
56
+ return isJsonObject(parsed) ? parsed : { output: parsed };
57
+ }
58
+ catch {
59
+ return { output: content };
60
+ }
61
+ }
62
+ /**
63
+ * Our messages → Gemini contents.
64
+ *
65
+ * Three shape differences the rest of the adapter must not have to know about:
66
+ * system text is lifted out and merged into ONE instruction (Gemini takes a
67
+ * single one, not a role in the turn list); assistant turns are role `model`
68
+ * and carry tool calls as `functionCall` parts with the thought signature
69
+ * beside them; tool results are role `user` with a `functionResponse` part
70
+ * naming the FUNCTION, since Gemini pairs a result to its call by name.
71
+ */
72
+ export function toGeminiContents(messages) {
73
+ let system = "";
74
+ const contents = [];
75
+ for (const message of messages) {
76
+ switch (message.role) {
77
+ case "system":
78
+ system = system ? `${system}\n\n${message.content}` : message.content;
79
+ break;
80
+ case "user":
81
+ contents.push({
82
+ role: "user",
83
+ parts: typeof message.content === "string"
84
+ ? [{ text: message.content }]
85
+ : message.content.map((part) => part.type === "text"
86
+ ? { text: part.text }
87
+ : { inlineData: { mimeType: part.mimeType, data: part.data } }),
88
+ });
89
+ break;
90
+ case "assistant": {
91
+ const parts = [];
92
+ if (message.content)
93
+ parts.push({ text: message.content });
94
+ for (const call of message.toolCalls ?? []) {
95
+ parts.push({
96
+ functionCall: { id: call.id, name: call.name, args: parseArgs(call.arguments) },
97
+ // Replayed verbatim: this is the model's own reasoning token, and
98
+ // without it the next turn starts from a chain of thought that
99
+ // no longer includes the call it just made.
100
+ ...(call.thoughtSignature ? { thoughtSignature: call.thoughtSignature } : {}),
101
+ });
102
+ }
103
+ // An assistant turn with neither text nor calls has no representation
104
+ // here, and an empty `parts` is a 400.
105
+ if (parts.length > 0)
106
+ contents.push({ role: "model", parts });
107
+ break;
108
+ }
109
+ case "tool":
110
+ contents.push({
111
+ role: "user",
112
+ parts: [
113
+ {
114
+ functionResponse: {
115
+ id: message.toolCallId,
116
+ name: message.name,
117
+ response: toResponseObject(message.content),
118
+ },
119
+ },
120
+ ...(message.images ?? []).map((image) => ({
121
+ inlineData: { mimeType: image.mimeType, data: image.data },
122
+ })),
123
+ ],
124
+ });
125
+ break;
126
+ }
127
+ }
128
+ return { ...(system ? { system } : {}), contents };
129
+ }
130
+ /**
131
+ * `auto` and an absent choice are Gemini's own default, so the field is omitted
132
+ * rather than sent as AUTO. `required` and a pinned tool are both mode ANY —
133
+ * the pin is the allow-list, not the mode.
134
+ */
135
+ function toToolConfig(choice) {
136
+ if (choice === undefined || choice === "auto")
137
+ return undefined;
138
+ if (choice === "none")
139
+ return { functionCallingConfig: { mode: "NONE" } };
140
+ if (choice === "required")
141
+ return { functionCallingConfig: { mode: "ANY" } };
142
+ return { functionCallingConfig: { mode: "ANY", allowedFunctionNames: [choice.name] } };
143
+ }
144
+ function mapFinishReason(reason) {
145
+ switch (reason) {
146
+ case "MAX_TOKENS":
147
+ return "length";
148
+ case "SAFETY":
149
+ case "PROHIBITED_CONTENT":
150
+ return "content_filter";
151
+ default:
152
+ return "stop";
153
+ }
154
+ }
155
+ export function createGeminiProvider(config) {
156
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
157
+ const id = config.id ?? "gemini";
158
+ return {
159
+ id,
160
+ model: config.model,
161
+ async *createStream(messages, tools, opts = {}) {
162
+ const effort = opts.effort ?? config.effort;
163
+ const maxTokens = opts.maxTokens ?? config.maxTokens;
164
+ const { system, contents } = toGeminiContents(messages);
165
+ const generationConfig = {};
166
+ if (maxTokens !== undefined)
167
+ generationConfig.maxOutputTokens = maxTokens;
168
+ if (opts.temperature !== undefined)
169
+ generationConfig.temperature = opts.temperature;
170
+ // No effort means the model's own dynamic thinking. Sending MINIMAL here
171
+ // would switch that off for a caller who never asked, which is the whole
172
+ // reason the seam treats an absent effort as "never sent".
173
+ if (effort)
174
+ generationConfig.thinkingConfig = { thinkingLevel: THINKING_LEVEL[effort] };
175
+ if (opts.json) {
176
+ generationConfig.responseMimeType = "application/json";
177
+ // `responseJsonSchema` takes JSON Schema as written; `responseSchema`
178
+ // is Gemini's own trimmed dialect and rejects most of what a real
179
+ // schema carries.
180
+ generationConfig.responseJsonSchema = opts.json.schema;
181
+ }
182
+ const request = { contents, generationConfig };
183
+ // A Content, not the bare string the SDK accepts — REST rejects a string.
184
+ if (system)
185
+ request.systemInstruction = { parts: [{ text: system }] };
186
+ if (tools.length > 0) {
187
+ request.tools = [
188
+ {
189
+ functionDeclarations: tools.map((tool) => ({
190
+ name: tool.name,
191
+ description: tool.description,
192
+ // Same rule as the response schema: `parameters` is the trimmed
193
+ // dialect, `parametersJsonSchema` is the schema we actually wrote.
194
+ parametersJsonSchema: tool.inputSchema,
195
+ })),
196
+ },
197
+ ];
198
+ // Pointless without declarations, and Gemini 400s on a tool config that
199
+ // names a function it was never given.
200
+ const toolConfig = toToolConfig(opts.toolChoice);
201
+ if (toolConfig)
202
+ request.toolConfig = toolConfig;
203
+ }
204
+ // A model id copied out of Gemini's docs is often already `models/…`, and
205
+ // the doubled segment 404s as "model not found" — a confusing way to
206
+ // learn about a prefix.
207
+ const model = (opts.model ?? config.model).replace(/^models\//, "");
208
+ // Gemini reports the finish reason on a candidate that can arrive AFTER
209
+ // the chunk carrying the function calls, so a turn's tool use has to be
210
+ // remembered rather than read off the final chunk.
211
+ let sawFunctionCalls = false;
212
+ let callIndex = 0;
213
+ for await (const data of streamSse({
214
+ // Without `?alt=sse` the response is one long JSON array that only
215
+ // parses once complete, which is not a stream.
216
+ url: apiUrl(baseUrl, `/v1beta/models/${model}:streamGenerateContent?alt=sse`),
217
+ headers: { "x-goog-api-key": config.apiKey, ...config.headers },
218
+ body: request,
219
+ provider: id,
220
+ ...(opts.signal ? { signal: opts.signal } : {}),
221
+ ...(config.fetchImpl ? { fetchImpl: config.fetchImpl } : {}),
222
+ })) {
223
+ let chunk;
224
+ try {
225
+ chunk = JSON.parse(data);
226
+ }
227
+ catch {
228
+ continue;
229
+ }
230
+ // `?alt=sse` commits to 200 the moment the headers go out, so a
231
+ // throttle or an overload landing after that arrives here as a
232
+ // google.rpc.Status in the body rather than as a status line.
233
+ if (chunk.error)
234
+ throw streamError(id, chunk.error);
235
+ if (chunk.usageMetadata) {
236
+ const usage = chunk.usageMetadata;
237
+ yield {
238
+ type: "usage",
239
+ usage: {
240
+ inputTokens: usage.promptTokenCount ?? 0,
241
+ // Thoughts bill as OUTPUT, and Gemini reports them OUTSIDE
242
+ // candidatesTokenCount — leaving them out undercounts a thinking
243
+ // turn by most of what it cost.
244
+ outputTokens: (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0),
245
+ cachedInputTokens: usage.cachedContentTokenCount ?? 0,
246
+ },
247
+ };
248
+ }
249
+ const candidate = chunk.candidates?.[0];
250
+ if (!candidate)
251
+ continue;
252
+ // One chunk can carry several parts of each kind. They are coalesced
253
+ // per kind so the seam sees one reasoning delta and one content delta
254
+ // per chunk, in that order, rather than interleaved fragments.
255
+ let reasoning = "";
256
+ let content = "";
257
+ const toolCalls = [];
258
+ for (const part of candidate.content?.parts ?? []) {
259
+ if (part.text) {
260
+ if (part.thought)
261
+ reasoning += part.text;
262
+ else
263
+ content += part.text;
264
+ continue;
265
+ }
266
+ const call = part.functionCall;
267
+ if (!call)
268
+ continue;
269
+ const index = callIndex++;
270
+ toolCalls.push({
271
+ index,
272
+ // Gemini omits the id on a single-call turn, and the seam's
273
+ // consumers pair a result back to its call by id.
274
+ id: call.id ?? `call_${index}`,
275
+ ...(call.name ? { name: call.name } : {}),
276
+ // Whole and already assembled — unlike the OpenAI shape, Gemini
277
+ // never fragments an argument object across chunks.
278
+ arguments: JSON.stringify(call.args ?? {}),
279
+ ...(part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}),
280
+ });
281
+ }
282
+ if (reasoning)
283
+ yield { type: "delta", reasoning };
284
+ if (content)
285
+ yield { type: "delta", content };
286
+ if (toolCalls.length > 0) {
287
+ sawFunctionCalls = true;
288
+ yield { type: "delta", toolCalls };
289
+ }
290
+ if (candidate.finishReason) {
291
+ yield {
292
+ type: "finish",
293
+ // A turn that called tools finishes as tool_calls whatever the
294
+ // candidate says — Gemini routinely reports STOP there, and a
295
+ // caller reading that as "done" drops the tool round entirely.
296
+ finishReason: sawFunctionCalls ? "tool_calls" : mapFinishReason(candidate.finishReason),
297
+ };
298
+ }
299
+ }
300
+ },
301
+ };
302
+ }
303
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,22 @@ export interface OpenAIConfig {
4
4
  model: string;
5
5
  /** Any OpenAI-compatible endpoint. Defaults to OpenAI itself. */
6
6
  baseUrl?: string;
7
- /** Names the provider in errors and logs — "openrouter", "deepseek", … */
7
+ /** Names the provider in errors and logs — "openrouter", "deepseek", … It
8
+ * also picks the effort dialect below, unless `effortDialect` overrides. */
8
9
  id?: string;
9
10
  effort?: Effort;
11
+ /**
12
+ * Which spelling of "think this hard" this endpoint accepts. Inferred from
13
+ * `id`; set it when the gateway is not named after its dialect, or to `off`
14
+ * for one that rejects the field outright.
15
+ */
16
+ effortDialect?: EffortDialect;
17
+ /**
18
+ * `schema` sends a `json_schema` response format, `object` plain JSON mode.
19
+ * Defaults to `schema` for OpenAI itself and `object` everywhere else, which
20
+ * is the only setting every gateway accepts.
21
+ */
22
+ jsonMode?: "schema" | "object";
10
23
  maxTokens?: number;
11
24
  fetchImpl?: typeof fetch;
12
25
  headers?: Record<string, string>;
@@ -19,6 +32,30 @@ export interface OpenAIConfig {
19
32
  */
20
33
  providerOrder?: string[];
21
34
  }
35
+ /** The spellings of "think this hard" across the dialects that share this
36
+ * adapter. `off` sends nothing and leaves the model on its own default. */
37
+ export type EffortDialect = "openai" | "openrouter" | "deepseek" | "off";
38
+ /**
39
+ * Effort → the request fields THIS endpoint accepts.
40
+ *
41
+ * One knob, three incompatible spellings, and the differences are not cosmetic:
42
+ *
43
+ * - **OpenRouter has no off switch.** `reasoning.enabled: false` is refused by
44
+ * models that always think — GLM 5.3 Flash answers `400 "Reasoning is
45
+ * mandatory for this endpoint and cannot be disabled."` — so `none` is
46
+ * floored at `low` rather than sent. Named rather than omitted, because
47
+ * letting the endpoint pick leaves cost and latency unpinned on exactly the
48
+ * tasks that asked for neither. Measured against the live endpoint, and it
49
+ * cost one app its onboarding read before it was.
50
+ * - **DeepSeek V4 defaults thinking ON**, so `none` has to be an explicit
51
+ * refusal. That is the case proving OpenRouter's floor is a constraint and
52
+ * not a preference for always thinking.
53
+ * - **OpenAI** takes `reasoning_effort` and nothing at all for `none`.
54
+ *
55
+ * An absent effort sends nothing on every dialect: the seam's rule is that a
56
+ * knob the caller never touched is a knob the provider still owns.
57
+ */
58
+ export declare function effortParams(dialect: EffortDialect, effort: Effort | undefined): Record<string, unknown>;
22
59
  /**
23
60
  * Assistant turns carry `reasoning_content` when the history has it — thinking
24
61
  * providers require the prior turn's chain-of-thought replayed on a turn that
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EAEN,QAAQ,EAIT,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AA6BD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,EAAE,CA4B5E;AAuBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CA0HnE"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EAEN,QAAQ,EAIT,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;iFAC6E;IAC7E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID;4EAC4E;AAC5E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBzB;AAmCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,EAAE,CAyD5E;AA+BD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,QAAQ,CAsJnE"}
@@ -3,9 +3,63 @@
3
3
  // This is the dialect most gateways speak, so one adapter serves OpenAI,
4
4
  // OpenRouter, DeepSeek, GLM, Kimi, Groq, Together, vLLM, Ollama and LM Studio.
5
5
  // Their divergences are small and named where they appear.
6
+ import { streamError } from "../errors.js";
6
7
  import { streamSse, apiUrl } from "../transport.js";
7
8
  import { toDataUri } from "../types.js";
8
9
  const DEFAULT_BASE_URL = "https://api.openai.com";
10
+ /**
11
+ * Effort → the request fields THIS endpoint accepts.
12
+ *
13
+ * One knob, three incompatible spellings, and the differences are not cosmetic:
14
+ *
15
+ * - **OpenRouter has no off switch.** `reasoning.enabled: false` is refused by
16
+ * models that always think — GLM 5.3 Flash answers `400 "Reasoning is
17
+ * mandatory for this endpoint and cannot be disabled."` — so `none` is
18
+ * floored at `low` rather than sent. Named rather than omitted, because
19
+ * letting the endpoint pick leaves cost and latency unpinned on exactly the
20
+ * tasks that asked for neither. Measured against the live endpoint, and it
21
+ * cost one app its onboarding read before it was.
22
+ * - **DeepSeek V4 defaults thinking ON**, so `none` has to be an explicit
23
+ * refusal. That is the case proving OpenRouter's floor is a constraint and
24
+ * not a preference for always thinking.
25
+ * - **OpenAI** takes `reasoning_effort` and nothing at all for `none`.
26
+ *
27
+ * An absent effort sends nothing on every dialect: the seam's rule is that a
28
+ * knob the caller never touched is a knob the provider still owns.
29
+ */
30
+ export function effortParams(dialect, effort) {
31
+ if (!effort)
32
+ return {};
33
+ const level = effort === "max" ? "high" : effort === "none" ? null : effort;
34
+ switch (dialect) {
35
+ case "deepseek":
36
+ if (level === null)
37
+ return { thinking: { type: "disabled" } };
38
+ // A graded level rides only when it asks for LESS. DeepSeek auto-bumps a
39
+ // complex agent or tool request past its own default, and naming the top
40
+ // tier here caps exactly the turns that most need the bump — so `high`
41
+ // and `max` say "on" and leave the ceiling where DeepSeek puts it, while
42
+ // `low` and `medium` mean what they say.
43
+ return level === "high"
44
+ ? { thinking: { type: "enabled" } }
45
+ : { thinking: { type: "enabled" }, reasoning_effort: level };
46
+ case "openrouter":
47
+ return { reasoning: { effort: level ?? "low" } };
48
+ case "openai":
49
+ return level === null ? {} : { reasoning_effort: level };
50
+ case "off":
51
+ return {};
52
+ }
53
+ }
54
+ /** Gateways named after their dialect get it for free; everything else keeps
55
+ * the dialect this adapter is named for. */
56
+ function dialectFor(id) {
57
+ if (id === "openrouter")
58
+ return "openrouter";
59
+ if (id === "deepseek")
60
+ return "deepseek";
61
+ return "openai";
62
+ }
9
63
  function mapFinishReason(reason) {
10
64
  switch (reason) {
11
65
  case "stop":
@@ -35,34 +89,60 @@ function partsToOpenAI(content) {
35
89
  * first (`stripReasoning`); the two cannot be mixed.
36
90
  */
37
91
  export function toOpenAIMessages(messages) {
38
- return messages.map((message) => {
92
+ const out = [];
93
+ for (const message of messages) {
39
94
  switch (message.role) {
40
95
  case "system":
41
- return { role: "system", content: message.content };
96
+ out.push({ role: "system", content: message.content });
97
+ break;
42
98
  case "user":
43
- return { role: "user", content: partsToOpenAI(message.content) };
99
+ out.push({ role: "user", content: partsToOpenAI(message.content) });
100
+ break;
44
101
  case "tool":
45
- return { role: "tool", tool_call_id: message.toolCallId, content: message.content };
102
+ out.push({ role: "tool", tool_call_id: message.toolCallId, content: message.content });
103
+ // This dialect has no image slot on a tool message — a `tool` role takes
104
+ // text and nothing else. A screenshot a tool hands back therefore
105
+ // follows as its own user message, which is the only way the model ever
106
+ // sees it. Dropped instead, the turn reads as a tool that returned
107
+ // words about a picture nobody was shown.
108
+ if (message.images?.length) {
109
+ out.push({
110
+ role: "user",
111
+ content: message.images.map((image) => ({
112
+ type: "image_url",
113
+ image_url: { url: toDataUri(image) },
114
+ })),
115
+ });
116
+ }
117
+ break;
46
118
  case "assistant": {
47
- const out = {
119
+ const assistant = {
48
120
  role: "assistant",
49
121
  // Nullable content beside tool_calls is what this shape expects, but
50
122
  // several gateways reject a bare null — "" satisfies both.
51
123
  content: message.content || "",
52
124
  };
53
125
  if (message.reasoning)
54
- out.reasoning_content = message.reasoning;
126
+ assistant.reasoning_content = message.reasoning;
127
+ // Verbatim, under the name the gateway gave it. Reshaped or dropped, the
128
+ // model loses its own record of how it reached the tool round it is
129
+ // being asked to continue.
130
+ if (message.reasoningDetails?.length) {
131
+ assistant.reasoning_details = message.reasoningDetails;
132
+ }
55
133
  if (message.toolCalls?.length) {
56
- out.tool_calls = message.toolCalls.map((call) => ({
134
+ assistant.tool_calls = message.toolCalls.map((call) => ({
57
135
  id: call.id,
58
136
  type: "function",
59
137
  function: { name: call.name, arguments: call.arguments },
60
138
  }));
61
139
  }
62
- return out;
140
+ out.push(assistant);
141
+ break;
63
142
  }
64
143
  }
65
- });
144
+ }
145
+ return out;
66
146
  }
67
147
  export function createOpenAIProvider(config) {
68
148
  const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
@@ -85,8 +165,7 @@ export function createOpenAIProvider(config) {
85
165
  request.max_tokens = maxTokens;
86
166
  if (opts.temperature !== undefined)
87
167
  request.temperature = opts.temperature;
88
- if (effort && effort !== "none")
89
- request.reasoning_effort = effort;
168
+ Object.assign(request, effortParams(config.effortDialect ?? dialectFor(id), effort));
90
169
  if (tools.length > 0) {
91
170
  request.tools = tools.map((tool) => ({
92
171
  type: "function",
@@ -104,10 +183,19 @@ export function createOpenAIProvider(config) {
104
183
  : { type: "function", function: { name: opts.toolChoice.name } };
105
184
  }
106
185
  if (opts.json) {
107
- request.response_format = {
108
- type: "json_schema",
109
- json_schema: { name: opts.json.name, schema: opts.json.schema, strict: true },
110
- };
186
+ request.response_format =
187
+ (config.jsonMode ?? (id === "openai" ? "schema" : "object")) === "schema"
188
+ ? {
189
+ type: "json_schema",
190
+ json_schema: { name: opts.json.name, schema: opts.json.schema, strict: true },
191
+ }
192
+ : // Everything else gets plain JSON mode. Schema ENFORCEMENT is
193
+ // OpenAI's; the gateways and the vendors behind them offer JSON
194
+ // mode at best, and several answer a flat 400 to a `json_schema`
195
+ // block. The seam's rule makes this safe either way: a provider's
196
+ // "guaranteed" JSON is not one, so the caller validates
197
+ // regardless — this only decides whether the request is accepted.
198
+ { type: "json_object" };
111
199
  }
112
200
  if (config.providerOrder?.length) {
113
201
  request.provider = { order: config.providerOrder, allow_fallbacks: true };
@@ -127,10 +215,24 @@ export function createOpenAIProvider(config) {
127
215
  catch {
128
216
  continue;
129
217
  }
218
+ // A failure the backend reports after its headers went out. The
219
+ // gateways speaking this dialect — OpenRouter above all — report a
220
+ // throttle or an upstream outage this way rather than as a status
221
+ // line, and a frame carrying `error` carries no choices: unread, it
222
+ // falls through both branches below and the turn ends as a successful
223
+ // zero-token completion nobody retries.
224
+ if (chunk.error)
225
+ throw streamError(id, chunk.error);
130
226
  // A usage-only frame carries no choices — this shape sends it last.
131
227
  if (chunk.usage) {
132
228
  const input = chunk.usage.prompt_tokens ?? 0;
133
- const cached = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;
229
+ // Two spellings for the same subset. DeepSeek's native endpoint uses
230
+ // its own field, and reading only the standard one bills every cached
231
+ // token at the full input rate — on an agent loop, where the re-sent
232
+ // prefix is overwhelmingly hits, that overstates a run by up to 10×.
233
+ const cached = chunk.usage.prompt_tokens_details?.cached_tokens ??
234
+ chunk.usage.prompt_cache_hit_tokens ??
235
+ 0;
134
236
  yield {
135
237
  type: "usage",
136
238
  usage: {
@@ -160,6 +262,10 @@ export function createOpenAIProvider(config) {
160
262
  out.reasoning = reasoning;
161
263
  has = true;
162
264
  }
265
+ if (delta.reasoning_details?.length) {
266
+ out.reasoningDetails = delta.reasoning_details;
267
+ has = true;
268
+ }
163
269
  if (delta.tool_calls?.length) {
164
270
  out.toolCalls = delta.tool_calls.map((call, position) => ({
165
271
  // Some gateways omit `index` entirely on single-tool turns.
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,yEAAyE;AACzE,+EAA+E;AAC/E,2DAA2D;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAWpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAuBxC,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAElD,SAAS,eAAe,CAAC,MAAiC;IACxD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,YAAY,CAAC;QAClB,KAAK,eAAe;YAClB,OAAO,YAAY,CAAC;QACtB,KAAK,gBAAgB;YACnB,OAAO,gBAAgB,CAAC;QAC1B;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAA+B;IACpD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAC1B,IAAI,CAAC,IAAI,KAAK,MAAM;QAClB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;QACnC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAC/D,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgC;IAC/D,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,QAAQ;gBACX,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACtD,KAAK,MAAM;gBACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnE,KAAK,MAAM;gBACT,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACtF,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,MAAM,GAAG,GAA4B;oBACnC,IAAI,EAAE,WAAW;oBACjB,qEAAqE;oBACrE,2DAA2D;oBAC3D,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;iBAC/B,CAAC;gBACF,IAAI,OAAO,CAAC,SAAS;oBAAE,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC;gBACjE,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;oBAC9B,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;wBAChD,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,UAAU;wBAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;qBACzD,CAAC,CAAC,CAAC;gBACN,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAuBD,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACnD,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,QAAQ,CAAC;IAEjC,OAAO;QACL,EAAE;QACF,KAAK,EAAE,MAAM,CAAC,KAAK;QAEnB,KAAK,CAAC,CAAC,YAAY,CACjB,QAAuB,EACvB,KAAuB,EACvB,OAAsB,EAAE;YAExB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC;YAE5C,MAAM,OAAO,GAA4B;gBACvC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;gBACjC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC;gBACpC,MAAM,EAAE,IAAI;gBACZ,mEAAmE;gBACnE,6CAA6C;gBAC7C,cAAc,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;aACxC,CAAC;YACF,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;YACrD,IAAI,SAAS,KAAK,SAAS;gBAAE,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;YAC5D,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;gBAAE,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YAC3E,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM;gBAAE,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC;YACnE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACnC,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE;wBACR,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,UAAU,EAAE,IAAI,CAAC,WAAW;qBAC7B;iBACF,CAAC,CAAC,CAAC;YACN,CAAC;YACD,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;gBAClD,OAAO,CAAC,WAAW;oBACjB,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;wBACjC,CAAC,CAAC,IAAI,CAAC,UAAU;wBACjB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;YACvE,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,eAAe,GAAG;oBACxB,IAAI,EAAE,aAAa;oBACnB,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;iBAC9E,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;gBACjC,OAAO,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,aAAa,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;YAC5E,CAAC;YAED,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,SAAS,CAAC;gBACjC,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,sBAAsB,CAAC;gBAC5C,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE;gBACxE,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,EAAE;gBACZ,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/C,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC7D,CAAC,EAAE,CAAC;gBACH,IAAI,KAAkB,CAAC;gBACvB,IAAI,CAAC;oBACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAgB,CAAC;gBAC1C,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBAED,oEAAoE;gBACpE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBAChB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;oBAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,qBAAqB,EAAE,aAAa,IAAI,CAAC,CAAC;oBACrE,MAAM;wBACJ,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE;4BACL,WAAW,EAAE,KAAK;4BAClB,2DAA2D;4BAC3D,0DAA0D;4BAC1D,iBAAiB,EAAE,MAAM;4BACzB,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC;yBACjD;qBACF,CAAC;gBACJ,CAAC;gBAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;gBAClC,IAAI,CAAC,MAAM;oBAAE,SAAS;gBAEtB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;gBAC3B,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,GAAG,GAAkB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oBAC7C,IAAI,GAAG,GAAG,KAAK,CAAC;oBAChB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;wBAClB,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;wBAC5B,GAAG,GAAG,IAAI,CAAC;oBACb,CAAC;oBACD,0DAA0D;oBAC1D,oEAAoE;oBACpE,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,SAAS,CAAC;oBAC7D,IAAI,SAAS,EAAE,CAAC;wBACd,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;wBAC1B,GAAG,GAAG,IAAI,CAAC;oBACb,CAAC;oBACD,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;wBAC7B,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;4BACxD,4DAA4D;4BAC5D,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,QAAQ;4BAC7B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACnC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BAC5D,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS;gCACxC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE;gCACxC,CAAC,CAAC,EAAE,CAAC;yBACR,CAAC,CAAC,CAAC;wBACJ,GAAG,GAAG,IAAI,CAAC;oBACb,CAAC;oBACD,IAAI,GAAG;wBAAE,MAAM,GAAG,CAAC;gBACrB,CAAC;gBAED,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;gBAC3D,IAAI,YAAY;oBAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;YAC3D,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"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"}