@ai-sdk/openai-compatible 1.0.37 → 1.0.39

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @ai-sdk/openai-compatible
2
2
 
3
+ ## 1.0.39
4
+
5
+ ### Patch Changes
6
+
7
+ - cb61408: feat(vertex): add grok models to vertex provider
8
+
9
+ ## 1.0.38
10
+
11
+ ### Patch Changes
12
+
13
+ - 783fa6c: chore: ensure consistent import handling and avoid import duplicates or cycles
14
+ - Updated dependencies [783fa6c]
15
+ - @ai-sdk/provider-utils@3.0.25
16
+ - @ai-sdk/provider@2.0.3
17
+
3
18
  ## 1.0.37
4
19
 
5
20
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { SharedV2ProviderMetadata, LanguageModelV2, EmbeddingModelV2, ImageModelV2, ProviderV2 } from '@ai-sdk/provider';
1
+ import { SharedV2ProviderMetadata, LanguageModelV2, LanguageModelV2Usage, EmbeddingModelV2, ImageModelV2, ProviderV2 } from '@ai-sdk/provider';
2
2
  import { FetchFunction } from '@ai-sdk/provider-utils';
3
3
  import { z, ZodType } from 'zod/v4';
4
4
 
@@ -87,6 +87,17 @@ type OpenAICompatibleChatConfig = {
87
87
  * The supported URLs for the model.
88
88
  */
89
89
  supportedUrls?: () => LanguageModelV2['supportedUrls'];
90
+ /**
91
+ * Optional function to transform the request body before sending it to the API.
92
+ * This is useful for proxy providers that may require a different request format
93
+ * than the official OpenAI API.
94
+ */
95
+ transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
96
+ /**
97
+ * Optional usage converter for OpenAI-compatible providers with different
98
+ * token accounting semantics.
99
+ */
100
+ convertUsage?: (usage: z.infer<typeof openaiCompatibleTokenUsageSchema>) => LanguageModelV2Usage;
90
101
  };
91
102
  declare class OpenAICompatibleChatLanguageModel implements LanguageModelV2 {
92
103
  readonly specificationVersion = "v2";
@@ -99,10 +110,25 @@ declare class OpenAICompatibleChatLanguageModel implements LanguageModelV2 {
99
110
  get provider(): string;
100
111
  private get providerOptionsName();
101
112
  get supportedUrls(): Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;
113
+ private transformRequestBody;
114
+ private convertUsage;
102
115
  private getArgs;
103
116
  doGenerate(options: Parameters<LanguageModelV2['doGenerate']>[0]): Promise<Awaited<ReturnType<LanguageModelV2['doGenerate']>>>;
104
117
  doStream(options: Parameters<LanguageModelV2['doStream']>[0]): Promise<Awaited<ReturnType<LanguageModelV2['doStream']>>>;
105
118
  }
119
+ declare const openaiCompatibleTokenUsageSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
120
+ prompt_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
121
+ completion_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
122
+ total_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
123
+ prompt_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
124
+ cached_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
125
+ }, z.core.$strip>>>;
126
+ completion_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
127
+ reasoning_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
128
+ accepted_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
129
+ rejected_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
130
+ }, z.core.$strip>>>;
131
+ }, z.core.$strip>>>;
106
132
 
107
133
  type OpenAICompatibleCompletionModelId = string;
108
134
  declare const openaiCompatibleCompletionProviderOptions: z.ZodObject<{
@@ -254,6 +280,27 @@ interface OpenAICompatibleProviderSettings {
254
280
  * Whether the provider supports structured outputs in chat models.
255
281
  */
256
282
  supportsStructuredOutputs?: boolean;
283
+ /**
284
+ * Optional function to transform the request body before sending it to the API.
285
+ * This is useful for proxy providers that may require a different request format
286
+ * than the official OpenAI API.
287
+ */
288
+ transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
289
+ /**
290
+ * Optional metadata extractor to capture provider-specific metadata from API responses.
291
+ * This is useful for extracting non-standard fields, experimental features,
292
+ * or provider-specific metrics from both streaming and non-streaming responses.
293
+ */
294
+ metadataExtractor?: MetadataExtractor;
295
+ /**
296
+ * The supported URLs for chat models.
297
+ */
298
+ supportedUrls?: OpenAICompatibleChatConfig['supportedUrls'];
299
+ /**
300
+ * Optional usage converter for providers with token accounting semantics that
301
+ * differ from the default OpenAI-compatible shape.
302
+ */
303
+ convertUsage?: OpenAICompatibleChatConfig['convertUsage'];
257
304
  }
258
305
  /**
259
306
  Create an OpenAICompatible provider instance.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SharedV2ProviderMetadata, LanguageModelV2, EmbeddingModelV2, ImageModelV2, ProviderV2 } from '@ai-sdk/provider';
1
+ import { SharedV2ProviderMetadata, LanguageModelV2, LanguageModelV2Usage, EmbeddingModelV2, ImageModelV2, ProviderV2 } from '@ai-sdk/provider';
2
2
  import { FetchFunction } from '@ai-sdk/provider-utils';
3
3
  import { z, ZodType } from 'zod/v4';
4
4
 
@@ -87,6 +87,17 @@ type OpenAICompatibleChatConfig = {
87
87
  * The supported URLs for the model.
88
88
  */
89
89
  supportedUrls?: () => LanguageModelV2['supportedUrls'];
90
+ /**
91
+ * Optional function to transform the request body before sending it to the API.
92
+ * This is useful for proxy providers that may require a different request format
93
+ * than the official OpenAI API.
94
+ */
95
+ transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
96
+ /**
97
+ * Optional usage converter for OpenAI-compatible providers with different
98
+ * token accounting semantics.
99
+ */
100
+ convertUsage?: (usage: z.infer<typeof openaiCompatibleTokenUsageSchema>) => LanguageModelV2Usage;
90
101
  };
91
102
  declare class OpenAICompatibleChatLanguageModel implements LanguageModelV2 {
92
103
  readonly specificationVersion = "v2";
@@ -99,10 +110,25 @@ declare class OpenAICompatibleChatLanguageModel implements LanguageModelV2 {
99
110
  get provider(): string;
100
111
  private get providerOptionsName();
101
112
  get supportedUrls(): Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;
113
+ private transformRequestBody;
114
+ private convertUsage;
102
115
  private getArgs;
103
116
  doGenerate(options: Parameters<LanguageModelV2['doGenerate']>[0]): Promise<Awaited<ReturnType<LanguageModelV2['doGenerate']>>>;
104
117
  doStream(options: Parameters<LanguageModelV2['doStream']>[0]): Promise<Awaited<ReturnType<LanguageModelV2['doStream']>>>;
105
118
  }
119
+ declare const openaiCompatibleTokenUsageSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
120
+ prompt_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
121
+ completion_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
122
+ total_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
123
+ prompt_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
124
+ cached_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
125
+ }, z.core.$strip>>>;
126
+ completion_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
127
+ reasoning_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
128
+ accepted_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
129
+ rejected_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
130
+ }, z.core.$strip>>>;
131
+ }, z.core.$strip>>>;
106
132
 
107
133
  type OpenAICompatibleCompletionModelId = string;
108
134
  declare const openaiCompatibleCompletionProviderOptions: z.ZodObject<{
@@ -254,6 +280,27 @@ interface OpenAICompatibleProviderSettings {
254
280
  * Whether the provider supports structured outputs in chat models.
255
281
  */
256
282
  supportsStructuredOutputs?: boolean;
283
+ /**
284
+ * Optional function to transform the request body before sending it to the API.
285
+ * This is useful for proxy providers that may require a different request format
286
+ * than the official OpenAI API.
287
+ */
288
+ transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
289
+ /**
290
+ * Optional metadata extractor to capture provider-specific metadata from API responses.
291
+ * This is useful for extracting non-standard fields, experimental features,
292
+ * or provider-specific metrics from both streaming and non-streaming responses.
293
+ */
294
+ metadataExtractor?: MetadataExtractor;
295
+ /**
296
+ * The supported URLs for chat models.
297
+ */
298
+ supportedUrls?: OpenAICompatibleChatConfig['supportedUrls'];
299
+ /**
300
+ * Optional usage converter for providers with token accounting semantics that
301
+ * differ from the default OpenAI-compatible shape.
302
+ */
303
+ convertUsage?: OpenAICompatibleChatConfig['convertUsage'];
257
304
  }
258
305
  /**
259
306
  Create an OpenAICompatible provider instance.
package/dist/index.js CHANGED
@@ -305,6 +305,14 @@ var OpenAICompatibleChatLanguageModel = class {
305
305
  var _a, _b, _c;
306
306
  return (_c = (_b = (_a = this.config).supportedUrls) == null ? void 0 : _b.call(_a)) != null ? _c : {};
307
307
  }
308
+ transformRequestBody(args) {
309
+ var _a, _b, _c;
310
+ return (_c = (_b = (_a = this.config).transformRequestBody) == null ? void 0 : _b.call(_a, args)) != null ? _c : args;
311
+ }
312
+ convertUsage(usage) {
313
+ var _a, _b, _c;
314
+ return (_c = (_b = (_a = this.config).convertUsage) == null ? void 0 : _b.call(_a, usage)) != null ? _c : convertOpenAICompatibleChatUsage(usage);
315
+ }
308
316
  async getArgs({
309
317
  prompt,
310
318
  maxOutputTokens,
@@ -393,9 +401,10 @@ var OpenAICompatibleChatLanguageModel = class {
393
401
  };
394
402
  }
395
403
  async doGenerate(options) {
396
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
404
+ var _a, _b, _c, _d, _e;
397
405
  const { args, warnings } = await this.getArgs({ ...options });
398
- const body = JSON.stringify(args);
406
+ const transformedArgs = this.transformRequestBody(args);
407
+ const body = JSON.stringify(transformedArgs);
399
408
  const {
400
409
  responseHeaders,
401
410
  value: responseBody,
@@ -406,7 +415,7 @@ var OpenAICompatibleChatLanguageModel = class {
406
415
  modelId: this.modelId
407
416
  }),
408
417
  headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers),
409
- body: args,
418
+ body: transformedArgs,
410
419
  failedResponseHandler: this.failedResponseHandler,
411
420
  successfulResponseHandler: (0, import_provider_utils2.createJsonResponseHandler)(
412
421
  OpenAICompatibleChatResponseSchema
@@ -453,13 +462,7 @@ var OpenAICompatibleChatLanguageModel = class {
453
462
  return {
454
463
  content,
455
464
  finishReason: mapOpenAICompatibleFinishReason(choice.finish_reason),
456
- usage: {
457
- inputTokens: (_g = (_f = responseBody.usage) == null ? void 0 : _f.prompt_tokens) != null ? _g : void 0,
458
- outputTokens: (_i = (_h = responseBody.usage) == null ? void 0 : _h.completion_tokens) != null ? _i : void 0,
459
- totalTokens: (_k = (_j = responseBody.usage) == null ? void 0 : _j.total_tokens) != null ? _k : void 0,
460
- reasoningTokens: (_n = (_m = (_l = responseBody.usage) == null ? void 0 : _l.completion_tokens_details) == null ? void 0 : _m.reasoning_tokens) != null ? _n : void 0,
461
- cachedInputTokens: (_q = (_p = (_o = responseBody.usage) == null ? void 0 : _o.prompt_tokens_details) == null ? void 0 : _p.cached_tokens) != null ? _q : void 0
462
- },
465
+ usage: this.convertUsage(responseBody.usage),
463
466
  providerMetadata,
464
467
  request: { body },
465
468
  response: {
@@ -473,12 +476,12 @@ var OpenAICompatibleChatLanguageModel = class {
473
476
  async doStream(options) {
474
477
  var _a;
475
478
  const { args, warnings } = await this.getArgs({ ...options });
476
- const body = {
479
+ const body = this.transformRequestBody({
477
480
  ...args,
478
481
  stream: true,
479
482
  // only include stream_options when in strict compatibility mode:
480
483
  stream_options: this.config.includeUsage ? { include_usage: true } : void 0
481
- };
484
+ });
482
485
  const metadataExtractor = (_a = this.config.metadataExtractor) == null ? void 0 : _a.createStreamExtractor();
483
486
  const { responseHeaders, value: response } = await (0, import_provider_utils2.postJsonToApi)({
484
487
  url: this.config.url({
@@ -509,10 +512,12 @@ var OpenAICompatibleChatLanguageModel = class {
509
512
  },
510
513
  totalTokens: void 0
511
514
  };
515
+ let lastUsage = void 0;
512
516
  let isFirstChunk = true;
513
517
  const providerOptionsName = this.providerOptionsName;
514
518
  let isActiveReasoning = false;
515
519
  let isActiveText = false;
520
+ const convertUsage = (usage2) => this.convertUsage(usage2);
516
521
  return {
517
522
  stream: response.pipeThrough(
518
523
  new TransformStream({
@@ -545,6 +550,7 @@ var OpenAICompatibleChatLanguageModel = class {
545
550
  });
546
551
  }
547
552
  if (value.usage != null) {
553
+ lastUsage = value.usage;
548
554
  const {
549
555
  prompt_tokens,
550
556
  completion_tokens,
@@ -688,7 +694,7 @@ var OpenAICompatibleChatLanguageModel = class {
688
694
  }
689
695
  },
690
696
  flush(controller) {
691
- var _a2, _b, _c, _d, _e, _f;
697
+ var _a2;
692
698
  if (isActiveReasoning) {
693
699
  controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
694
700
  }
@@ -722,13 +728,7 @@ var OpenAICompatibleChatLanguageModel = class {
722
728
  controller.enqueue({
723
729
  type: "finish",
724
730
  finishReason,
725
- usage: {
726
- inputTokens: (_b = usage.promptTokens) != null ? _b : void 0,
727
- outputTokens: (_c = usage.completionTokens) != null ? _c : void 0,
728
- totalTokens: (_d = usage.totalTokens) != null ? _d : void 0,
729
- reasoningTokens: (_e = usage.completionTokensDetails.reasoningTokens) != null ? _e : void 0,
730
- cachedInputTokens: (_f = usage.promptTokensDetails.cachedTokens) != null ? _f : void 0
731
- },
731
+ usage: convertUsage(lastUsage),
732
732
  providerMetadata
733
733
  });
734
734
  }
@@ -752,6 +752,16 @@ var openaiCompatibleTokenUsageSchema = import_v43.z.object({
752
752
  rejected_prediction_tokens: import_v43.z.number().nullish()
753
753
  }).nullish()
754
754
  }).nullish();
755
+ function convertOpenAICompatibleChatUsage(usage) {
756
+ var _a, _b, _c, _d, _e, _f, _g;
757
+ return {
758
+ inputTokens: (_a = usage == null ? void 0 : usage.prompt_tokens) != null ? _a : void 0,
759
+ outputTokens: (_b = usage == null ? void 0 : usage.completion_tokens) != null ? _b : void 0,
760
+ totalTokens: (_c = usage == null ? void 0 : usage.total_tokens) != null ? _c : void 0,
761
+ reasoningTokens: (_e = (_d = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _d.reasoning_tokens) != null ? _e : void 0,
762
+ cachedInputTokens: (_g = (_f = usage == null ? void 0 : usage.prompt_tokens_details) == null ? void 0 : _f.cached_tokens) != null ? _g : void 0
763
+ };
764
+ }
755
765
  var OpenAICompatibleChatResponseSchema = import_v43.z.object({
756
766
  id: import_v43.z.string().nullish(),
757
767
  created: import_v43.z.number().nullish(),
@@ -1401,7 +1411,7 @@ var openaiCompatibleImageResponseSchema = import_v48.z.object({
1401
1411
  var import_provider_utils6 = require("@ai-sdk/provider-utils");
1402
1412
 
1403
1413
  // src/version.ts
1404
- var VERSION = true ? "1.0.37" : "0.0.0-test";
1414
+ var VERSION = true ? "1.0.39" : "0.0.0-test";
1405
1415
 
1406
1416
  // src/openai-compatible-provider.ts
1407
1417
  function createOpenAICompatible(options) {
@@ -1428,7 +1438,11 @@ function createOpenAICompatible(options) {
1428
1438
  const createChatModel = (modelId) => new OpenAICompatibleChatLanguageModel(modelId, {
1429
1439
  ...getCommonModelConfig("chat"),
1430
1440
  includeUsage: options.includeUsage,
1431
- supportsStructuredOutputs: options.supportsStructuredOutputs
1441
+ supportsStructuredOutputs: options.supportsStructuredOutputs,
1442
+ supportedUrls: options.supportedUrls,
1443
+ transformRequestBody: options.transformRequestBody,
1444
+ metadataExtractor: options.metadataExtractor,
1445
+ convertUsage: options.convertUsage
1432
1446
  });
1433
1447
  const createCompletionModel = (modelId) => new OpenAICompatibleCompletionLanguageModel(modelId, {
1434
1448
  ...getCommonModelConfig("completion"),