@wrongstack/providers 0.73.1 → 0.82.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -57,10 +57,10 @@ declare abstract class WireAdapter implements Provider {
57
57
 
58
58
  interface AnthropicProviderOptions {
59
59
  apiKey: string;
60
- baseUrl?: string;
61
- apiVersion?: string;
62
- beta?: string[];
63
- fetchImpl?: typeof fetch;
60
+ baseUrl?: string | undefined;
61
+ apiVersion?: string | undefined;
62
+ beta?: string[] | undefined;
63
+ fetchImpl?: typeof fetch | undefined;
64
64
  }
65
65
  declare class AnthropicProvider extends WireAdapter {
66
66
  readonly id = "anthropic";
@@ -86,10 +86,10 @@ interface OpenAIToolSchema {
86
86
  declare function toolsToOpenAI(tools: Tool[]): OpenAIToolSchema[];
87
87
  interface OpenAIMessage {
88
88
  role: 'system' | 'user' | 'assistant' | 'tool';
89
- content?: string | OpenAIContent[];
90
- tool_calls?: OpenAIToolCall[];
91
- tool_call_id?: string;
92
- name?: string;
89
+ content?: string | OpenAIContent[] | undefined;
90
+ tool_calls?: OpenAIToolCall[] | undefined;
91
+ tool_call_id?: string | undefined;
92
+ name?: string | undefined;
93
93
  /**
94
94
  * DeepSeek (and other OpenAI-compatible thinking-mode models) require the
95
95
  * previous assistant's chain-of-thought to be echoed back on the next
@@ -99,13 +99,13 @@ interface OpenAIMessage {
99
99
  * back to the API". Vanilla OpenAI ignores this field, so emitting it
100
100
  * unconditionally is safe.
101
101
  */
102
- reasoning_content?: string;
102
+ reasoning_content?: string | undefined;
103
103
  }
104
104
  interface OpenAIContent {
105
105
  type: 'text' | 'image_url';
106
- text?: string;
106
+ text?: string | undefined;
107
107
  image_url?: {
108
- url: string;
108
+ url: string | undefined;
109
109
  };
110
110
  }
111
111
  interface OpenAIToolCall {
@@ -117,24 +117,24 @@ interface OpenAIToolCall {
117
117
  };
118
118
  }
119
119
  interface ConvertOptions {
120
- flattenContentToString?: boolean;
121
- stripCacheControl?: boolean;
122
- systemAsMessage?: boolean;
123
- emptyToolCallContent?: 'null' | 'empty_string';
120
+ flattenContentToString?: boolean | undefined;
121
+ stripCacheControl?: boolean | undefined;
122
+ systemAsMessage?: boolean | undefined;
123
+ emptyToolCallContent?: 'null' | 'empty_string' | undefined;
124
124
  }
125
125
  declare function messagesToOpenAI(system: TextBlock[] | undefined, messages: Message[], opts?: ConvertOptions): OpenAIMessage[];
126
126
 
127
127
  interface OpenAIProviderOptions {
128
128
  apiKey: string;
129
- baseUrl?: string;
130
- organization?: string;
131
- fetchImpl?: typeof fetch;
129
+ baseUrl?: string | undefined;
130
+ organization?: string | undefined;
131
+ fetchImpl?: typeof fetch | undefined;
132
132
  quirks?: ConvertOptions & {
133
- parallelToolsDisabled?: boolean;
134
- jsonArgumentsBuggy?: boolean;
135
- };
136
- id?: string;
137
- capabilities?: Partial<Capabilities>;
133
+ parallelToolsDisabled?: boolean | undefined;
134
+ jsonArgumentsBuggy?: boolean | undefined;
135
+ } | undefined;
136
+ id?: string | undefined;
137
+ capabilities?: Partial<Capabilities> | undefined;
138
138
  }
139
139
  declare class OpenAIProvider extends WireAdapter {
140
140
  readonly id: string;
@@ -157,28 +157,28 @@ declare class OpenAIProvider extends WireAdapter {
157
157
  }
158
158
 
159
159
  interface CompatibilityQuirks {
160
- stripCacheControl?: boolean;
161
- systemAsMessage?: boolean;
162
- flattenContentToString?: boolean;
163
- preserveToolCallIds?: boolean;
164
- parallelToolsDisabled?: boolean;
165
- jsonArgumentsBuggy?: boolean;
166
- emptyToolCallContent?: 'null' | 'empty_string';
160
+ stripCacheControl?: boolean | undefined;
161
+ systemAsMessage?: boolean | undefined;
162
+ flattenContentToString?: boolean | undefined;
163
+ preserveToolCallIds?: boolean | undefined;
164
+ parallelToolsDisabled?: boolean | undefined;
165
+ jsonArgumentsBuggy?: boolean | undefined;
166
+ emptyToolCallContent?: 'null' | 'empty_string' | undefined;
167
167
  }
168
168
  interface OpenAICompatibleOptions {
169
169
  id: string;
170
170
  apiKey: string;
171
171
  baseUrl: string;
172
- headers?: Record<string, string>;
173
- quirks?: CompatibilityQuirks;
174
- capabilities?: Partial<Capabilities>;
175
- fetchImpl?: typeof fetch;
172
+ headers?: Record<string, string> | undefined;
173
+ quirks?: CompatibilityQuirks | undefined;
174
+ capabilities?: Partial<Capabilities> | undefined;
175
+ fetchImpl?: typeof fetch | undefined;
176
176
  /**
177
177
  * Optional override for URL construction. Receives the base URL and request,
178
178
  * returns the full URL to use. Allows custom providers with non-standard
179
179
  * URL structures (e.g. Google with model-in-path, Anthropic with /v1/messages).
180
180
  */
181
- urlOverride?: (baseUrl: string, req: Request) => string;
181
+ urlOverride?: ((baseUrl: string, req: Request) => string) | undefined;
182
182
  }
183
183
  declare class OpenAICompatibleProvider extends OpenAIProvider {
184
184
  private readonly extraHeaders?;
@@ -208,10 +208,10 @@ declare class OpenAICompatibleProvider extends OpenAIProvider {
208
208
  */
209
209
  interface GoogleProviderOptions {
210
210
  apiKey: string;
211
- baseUrl?: string;
212
- fetchImpl?: typeof fetch;
213
- id?: string;
214
- capabilities?: Partial<Capabilities>;
211
+ baseUrl?: string | undefined;
212
+ fetchImpl?: typeof fetch | undefined;
213
+ id?: string | undefined;
214
+ capabilities?: Partial<Capabilities> | undefined;
215
215
  }
216
216
  declare class GoogleProvider extends WireAdapter {
217
217
  readonly id: string;
@@ -285,8 +285,8 @@ declare class WireFormatProvider<S = Record<string, unknown>> extends WireAdapte
285
285
  private readonly cfg;
286
286
  constructor(cfg: WireFormatConfig<S>, opts: {
287
287
  apiKey: string;
288
- baseUrl?: string;
289
- fetchImpl?: typeof fetch;
288
+ baseUrl?: string | undefined;
289
+ fetchImpl?: typeof fetch | undefined;
290
290
  });
291
291
  protected buildUrl(req: Request): string;
292
292
  protected buildHeaders(req: Request): Record<string, string>;
@@ -313,9 +313,9 @@ interface WireFactoryOptions {
313
313
  * reads `cfg.apiKey` (passed in at create time by the registry / config
314
314
  * loader). Setting this here is useful in tests.
315
315
  */
316
- apiKey?: string;
316
+ apiKey?: string | undefined;
317
317
  /** Override the base URL at factory build time. */
318
- baseUrl?: string;
318
+ baseUrl?: string | undefined;
319
319
  }
320
320
  /**
321
321
  * Build a `ProviderFactory` from a declarative wire-format. Plug into
@@ -328,8 +328,8 @@ interface MistralStreamState {
328
328
  model: string;
329
329
  started: boolean;
330
330
  toolCalls: Map<number, {
331
- id?: string;
332
- name?: string;
331
+ id?: string | undefined;
332
+ name?: string | undefined;
333
333
  partial: string;
334
334
  emittedStart: boolean;
335
335
  emittedArgLength: number;
@@ -346,8 +346,8 @@ interface AnthropicStreamState {
346
346
  stopped: boolean;
347
347
  blocks: Map<number, {
348
348
  kind: BlockKind;
349
- id?: string;
350
- name?: string;
349
+ id?: string | undefined;
350
+ name?: string | undefined;
351
351
  partial: string;
352
352
  }>;
353
353
  }
@@ -361,8 +361,8 @@ interface OpenAIStreamState {
361
361
  textOpen: boolean;
362
362
  thinkingOpen: boolean;
363
363
  toolByIndex: Map<number, {
364
- id?: string;
365
- name?: string;
364
+ id?: string | undefined;
365
+ name?: string | undefined;
366
366
  argBuf: string;
367
367
  emittedStart: boolean;
368
368
  emittedArgLength: number;
@@ -419,20 +419,20 @@ declare function toolsToAnthropic(tools: Tool[]): AnthropicToolSchema[];
419
419
 
420
420
  interface AnthropicBlock {
421
421
  type: string;
422
- text?: string;
423
- id?: string;
424
- name?: string;
425
- input?: unknown;
426
- content?: unknown;
427
- tool_use_id?: string;
428
- is_error?: boolean;
429
- thinking?: string;
430
- signature?: string;
422
+ text?: string | undefined;
423
+ id?: string | undefined;
424
+ name?: string | undefined;
425
+ input?: unknown | undefined;
426
+ content?: unknown | undefined;
427
+ tool_use_id?: string | undefined;
428
+ is_error?: boolean | undefined;
429
+ thinking?: string | undefined;
430
+ signature?: string | undefined;
431
431
  source?: {
432
- type?: 'base64' | 'url';
433
- media_type?: string;
434
- data?: string;
435
- url?: string;
432
+ type?: 'base64' | 'url' | undefined;
433
+ media_type?: string | undefined;
434
+ data?: string | undefined;
435
+ url?: string | undefined;
436
436
  };
437
437
  }
438
438
  interface FromAnthropicOptions {
@@ -452,7 +452,7 @@ interface OpenAIChoice {
452
452
  message: {
453
453
  role: string;
454
454
  content: string | null;
455
- tool_calls?: OpenAIToolCall[];
455
+ tool_calls?: OpenAIToolCall[] | undefined;
456
456
  };
457
457
  finish_reason: string | null;
458
458
  }
@@ -462,7 +462,7 @@ interface FromOpenAIOptions {
462
462
  * backward compatibility; the value is ignored.
463
463
  * TODO(breaking): remove in next major release.
464
464
  */
465
- jsonArgumentsBuggy?: boolean;
465
+ jsonArgumentsBuggy?: boolean | undefined;
466
466
  /**
467
467
  * Called when a tool call's `arguments` field can't be parsed even after
468
468
  * the sanitizer pass. Callers can use this to emit a structured event,
@@ -482,7 +482,7 @@ declare function contentFromOpenAI(choice: OpenAIChoice, opts?: FromOpenAIOption
482
482
  interface BuildFactoriesOptions {
483
483
  registry: ModelsRegistry;
484
484
  /** Used to log unsupported families during boot. */
485
- log?: Logger;
485
+ log?: Logger | undefined;
486
486
  }
487
487
  /**
488
488
  * Build one ProviderFactory per provider known to models.dev. The factory's
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ProviderError, safeParse, sanitizeJsonString } from '@wrongstack/core';
1
+ import { ProviderError, safeParse, sanitizeJsonString, WrongStackError, ERROR_CODES } from '@wrongstack/core';
2
2
  import { randomUUID } from 'crypto';
3
3
 
4
4
  var __defProp = Object.defineProperty;
@@ -129,6 +129,12 @@ var aggregate_exports = {};
129
129
  __export(aggregate_exports, {
130
130
  aggregateStream: () => aggregateStream
131
131
  });
132
+ function expectDefined(value) {
133
+ if (value === null || value === void 0) {
134
+ throw new Error("Expected value to be defined");
135
+ }
136
+ return value;
137
+ }
132
138
  async function aggregateStream(stream, onEvent) {
133
139
  let model = "";
134
140
  let stopReason = "end_turn";
@@ -187,7 +193,7 @@ async function aggregateStream(stream, onEvent) {
187
193
  thinkingBuffers.push({ textBuf: "" });
188
194
  }
189
195
  if (ev.providerMeta && currentThinkingIndex >= 0) {
190
- thinkingBuffers[currentThinkingIndex].providerMeta = ev.providerMeta;
196
+ expectDefined(thinkingBuffers[currentThinkingIndex]).providerMeta = ev.providerMeta;
191
197
  }
192
198
  blockOrder.push({ kind: "thinking", idx: currentThinkingIndex });
193
199
  break;
@@ -968,9 +974,11 @@ async function* parseGoogleStream(body, fallbackModel) {
968
974
  if (typeof part.text === "string" && part.text.length > 0) {
969
975
  yield { type: "text_delta", text: part.text };
970
976
  } else if (part.functionCall) {
977
+ const name = part.functionCall.name;
978
+ if (typeof name !== "string" || name.length === 0) continue;
971
979
  sawFunctionCall = true;
972
980
  const id = randomUUID();
973
- yield { type: "tool_use_start", id, name: part.functionCall.name };
981
+ yield { type: "tool_use_start", id, name };
974
982
  const providerMeta = typeof part.thoughtSignature === "string" ? { "google.thoughtSignature": part.thoughtSignature } : void 0;
975
983
  yield {
976
984
  type: "tool_use_stop",
@@ -1291,6 +1299,29 @@ async function* parseOpenAIStream(body, fallbackModel) {
1291
1299
  }
1292
1300
 
1293
1301
  // src/openai-compatible.ts
1302
+ var VALID_QUIRK_KEYS = /* @__PURE__ */ new Set([
1303
+ "stripCacheControl",
1304
+ "systemAsMessage",
1305
+ "flattenContentToString",
1306
+ "preserveToolCallIds",
1307
+ "parallelToolsDisabled",
1308
+ "jsonArgumentsBuggy",
1309
+ "emptyToolCallContent"
1310
+ ]);
1311
+ function isCompatibilityQuirks(value) {
1312
+ if (value === void 0) return true;
1313
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
1314
+ const obj = value;
1315
+ for (const [key, v] of Object.entries(obj)) {
1316
+ if (!VALID_QUIRK_KEYS.has(key)) return false;
1317
+ if (key === "emptyToolCallContent") {
1318
+ if (v !== "null" && v !== "empty_string") return false;
1319
+ } else if (typeof v !== "boolean") {
1320
+ return false;
1321
+ }
1322
+ }
1323
+ return true;
1324
+ }
1294
1325
  var OpenAICompatibleProvider = class extends OpenAIProvider {
1295
1326
  extraHeaders;
1296
1327
  urlOverride;
@@ -1887,9 +1918,11 @@ var googleWireFormat = defineWireFormat({
1887
1918
  if (typeof part.text === "string" && part.text.length > 0) {
1888
1919
  out.push({ type: "text_delta", text: part.text });
1889
1920
  } else if (part.functionCall) {
1921
+ const name = part.functionCall.name;
1922
+ if (typeof name !== "string" || name.length === 0) continue;
1890
1923
  state.sawFunctionCall = true;
1891
- const id = `${part.functionCall.name}_${randomUUID().slice(0, 8)}`;
1892
- out.push({ type: "tool_use_start", id, name: part.functionCall.name });
1924
+ const id = `${name}_${randomUUID().slice(0, 8)}`;
1925
+ out.push({ type: "tool_use_start", id, name });
1893
1926
  const providerMeta = typeof part.thoughtSignature === "string" ? { "google.thoughtSignature": part.thoughtSignature } : void 0;
1894
1927
  out.push({
1895
1928
  type: "tool_use_stop",
@@ -2190,6 +2223,12 @@ function parseToolArguments(raw, toolName, toolCallId, opts) {
2190
2223
  }
2191
2224
 
2192
2225
  // src/index.ts
2226
+ function expectDefined2(value) {
2227
+ if (value === null || value === void 0) {
2228
+ throw new Error("Expected value to be defined");
2229
+ }
2230
+ return value;
2231
+ }
2193
2232
  async function buildProviderFactoriesFromRegistry(opts) {
2194
2233
  const providers = await opts.registry.listProviders();
2195
2234
  const factories = [];
@@ -2213,7 +2252,7 @@ async function buildProviderFactoriesFromRegistry(opts) {
2213
2252
  apiKey: requireKey(cfg),
2214
2253
  baseUrl: cfg.baseUrl ?? "",
2215
2254
  headers: cfg.headers,
2216
- quirks: cfg.quirks
2255
+ quirks: validateQuirks("openai-compatible", cfg.quirks)
2217
2256
  })
2218
2257
  });
2219
2258
  if (unsupported.length > 0 && opts.log) {
@@ -2245,24 +2284,24 @@ function makeProvider(p, cfg) {
2245
2284
  }
2246
2285
  switch (family) {
2247
2286
  case "anthropic":
2248
- return new AnthropicProvider({ apiKey, baseUrl });
2287
+ return new AnthropicProvider({ apiKey: expectDefined2(apiKey), baseUrl });
2249
2288
  case "openai":
2250
2289
  return new OpenAIProvider({
2251
- apiKey,
2290
+ apiKey: expectDefined2(apiKey),
2252
2291
  baseUrl,
2253
2292
  id: p.id,
2254
- quirks: cfg.quirks
2293
+ quirks: validateQuirks(p.id, cfg.quirks)
2255
2294
  });
2256
2295
  case "openai-compatible":
2257
2296
  return new OpenAICompatibleProvider({
2258
2297
  id: p.id,
2259
- apiKey,
2298
+ apiKey: expectDefined2(apiKey),
2260
2299
  baseUrl: baseUrl ?? "",
2261
2300
  headers: cfg.headers,
2262
- quirks: cfg.quirks
2301
+ quirks: validateQuirks(p.id, cfg.quirks)
2263
2302
  });
2264
2303
  case "google":
2265
- return new GoogleProvider({ id: p.id, apiKey, baseUrl });
2304
+ return new GoogleProvider({ id: p.id, apiKey: expectDefined2(apiKey), baseUrl });
2266
2305
  }
2267
2306
  }
2268
2307
  function makeProviderFromConfig(id, cfg) {
@@ -2292,6 +2331,15 @@ function requireKey(cfg) {
2292
2331
  if (cfg.apiKey) return cfg.apiKey;
2293
2332
  throw new Error("Provider config requires apiKey (or set the corresponding env var).");
2294
2333
  }
2334
+ function validateQuirks(providerId, quirks) {
2335
+ if (quirks === void 0) return void 0;
2336
+ if (isCompatibilityQuirks(quirks)) return quirks;
2337
+ throw new WrongStackError({
2338
+ message: `Invalid quirks for provider "${providerId}". Expected CompatibilityQuirks.`,
2339
+ code: ERROR_CODES.CONFIG_INVALID,
2340
+ subsystem: "provider"
2341
+ });
2342
+ }
2295
2343
 
2296
2344
  export { AnthropicProvider, CAPABILITIES_BY_FAMILY, GoogleProvider, OpenAICompatibleProvider, OpenAIProvider, WireAdapter, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, capabilitiesForFamily, contentFromAnthropic, contentFromOpenAI, createWireFormatFactory, defineWireFormat, googleWireFormat, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, toolsToAnthropic, toolsToOpenAI };
2297
2345
  //# sourceMappingURL=index.js.map