@ai-sdk/xai 3.0.55 → 3.0.57

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,17 @@
1
1
  # @ai-sdk/xai
2
2
 
3
+ ## 3.0.57
4
+
5
+ ### Patch Changes
6
+
7
+ - 56dfdf6: feat (provider/xai): add video support
8
+
9
+ ## 3.0.56
10
+
11
+ ### Patch Changes
12
+
13
+ - 7ccb902: fix(provider/xai): handle inconsistent cached token reporting
14
+
3
15
  ## 3.0.55
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod/v4';
2
- import { ProviderV3, LanguageModelV3, ImageModelV3 } from '@ai-sdk/provider';
2
+ import { ProviderV3, LanguageModelV3, ImageModelV3, Experimental_VideoModelV3 } from '@ai-sdk/provider';
3
3
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
4
4
  import { FetchFunction } from '@ai-sdk/provider-utils';
5
5
 
@@ -81,6 +81,16 @@ declare const xaiImageModelOptions: z.ZodObject<{
81
81
  }, z.core.$strip>;
82
82
  type XaiImageModelOptions = z.infer<typeof xaiImageModelOptions>;
83
83
 
84
+ type XaiVideoModelId = 'grok-imagine-video' | (string & {});
85
+
86
+ type XaiVideoModelOptions = {
87
+ pollIntervalMs?: number | null;
88
+ pollTimeoutMs?: number | null;
89
+ resolution?: '480p' | '720p' | null;
90
+ videoUrl?: string | null;
91
+ [key: string]: unknown;
92
+ };
93
+
84
94
  type XaiImageModelId = 'grok-2-image' | 'grok-imagine-image' | (string & {});
85
95
 
86
96
  declare const codeExecutionToolFactory: _ai_sdk_provider_utils.ProviderToolFactoryWithOutputSchema<Record<string, never>, {
@@ -307,6 +317,14 @@ interface XaiProvider extends ProviderV3 {
307
317
  * Creates an Xai image model for image generation.
308
318
  */
309
319
  imageModel(modelId: XaiImageModelId): ImageModelV3;
320
+ /**
321
+ * Creates an Xai video model for video generation.
322
+ */
323
+ video(modelId: XaiVideoModelId): Experimental_VideoModelV3;
324
+ /**
325
+ * Creates an Xai video model for video generation.
326
+ */
327
+ videoModel(modelId: XaiVideoModelId): Experimental_VideoModelV3;
310
328
  /**
311
329
  * Server-side agentic tools for use with the responses API.
312
330
  */
@@ -340,4 +358,4 @@ declare const xai: XaiProvider;
340
358
 
341
359
  declare const VERSION: string;
342
360
 
343
- export { VERSION, type XaiErrorData, type XaiImageModelOptions, type XaiImageModelOptions as XaiImageProviderOptions, type XaiLanguageModelChatOptions, type XaiLanguageModelResponsesOptions, type XaiProvider, type XaiLanguageModelChatOptions as XaiProviderOptions, type XaiProviderSettings, type XaiLanguageModelResponsesOptions as XaiResponsesProviderOptions, codeExecution, createXai, mcpServer, viewImage, viewXVideo, webSearch, xSearch, xai, xaiTools };
361
+ export { VERSION, type XaiErrorData, type XaiImageModelOptions, type XaiImageModelOptions as XaiImageProviderOptions, type XaiLanguageModelChatOptions, type XaiLanguageModelResponsesOptions, type XaiProvider, type XaiLanguageModelChatOptions as XaiProviderOptions, type XaiProviderSettings, type XaiLanguageModelResponsesOptions as XaiResponsesProviderOptions, type XaiVideoModelId, type XaiVideoModelOptions, type XaiVideoModelOptions as XaiVideoProviderOptions, codeExecution, createXai, mcpServer, viewImage, viewXVideo, webSearch, xSearch, xai, xaiTools };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod/v4';
2
- import { ProviderV3, LanguageModelV3, ImageModelV3 } from '@ai-sdk/provider';
2
+ import { ProviderV3, LanguageModelV3, ImageModelV3, Experimental_VideoModelV3 } from '@ai-sdk/provider';
3
3
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
4
4
  import { FetchFunction } from '@ai-sdk/provider-utils';
5
5
 
@@ -81,6 +81,16 @@ declare const xaiImageModelOptions: z.ZodObject<{
81
81
  }, z.core.$strip>;
82
82
  type XaiImageModelOptions = z.infer<typeof xaiImageModelOptions>;
83
83
 
84
+ type XaiVideoModelId = 'grok-imagine-video' | (string & {});
85
+
86
+ type XaiVideoModelOptions = {
87
+ pollIntervalMs?: number | null;
88
+ pollTimeoutMs?: number | null;
89
+ resolution?: '480p' | '720p' | null;
90
+ videoUrl?: string | null;
91
+ [key: string]: unknown;
92
+ };
93
+
84
94
  type XaiImageModelId = 'grok-2-image' | 'grok-imagine-image' | (string & {});
85
95
 
86
96
  declare const codeExecutionToolFactory: _ai_sdk_provider_utils.ProviderToolFactoryWithOutputSchema<Record<string, never>, {
@@ -307,6 +317,14 @@ interface XaiProvider extends ProviderV3 {
307
317
  * Creates an Xai image model for image generation.
308
318
  */
309
319
  imageModel(modelId: XaiImageModelId): ImageModelV3;
320
+ /**
321
+ * Creates an Xai video model for video generation.
322
+ */
323
+ video(modelId: XaiVideoModelId): Experimental_VideoModelV3;
324
+ /**
325
+ * Creates an Xai video model for video generation.
326
+ */
327
+ videoModel(modelId: XaiVideoModelId): Experimental_VideoModelV3;
310
328
  /**
311
329
  * Server-side agentic tools for use with the responses API.
312
330
  */
@@ -340,4 +358,4 @@ declare const xai: XaiProvider;
340
358
 
341
359
  declare const VERSION: string;
342
360
 
343
- export { VERSION, type XaiErrorData, type XaiImageModelOptions, type XaiImageModelOptions as XaiImageProviderOptions, type XaiLanguageModelChatOptions, type XaiLanguageModelResponsesOptions, type XaiProvider, type XaiLanguageModelChatOptions as XaiProviderOptions, type XaiProviderSettings, type XaiLanguageModelResponsesOptions as XaiResponsesProviderOptions, codeExecution, createXai, mcpServer, viewImage, viewXVideo, webSearch, xSearch, xai, xaiTools };
361
+ export { VERSION, type XaiErrorData, type XaiImageModelOptions, type XaiImageModelOptions as XaiImageProviderOptions, type XaiLanguageModelChatOptions, type XaiLanguageModelResponsesOptions, type XaiProvider, type XaiLanguageModelChatOptions as XaiProviderOptions, type XaiProviderSettings, type XaiLanguageModelResponsesOptions as XaiResponsesProviderOptions, type XaiVideoModelId, type XaiVideoModelOptions, type XaiVideoModelOptions as XaiVideoProviderOptions, codeExecution, createXai, mcpServer, viewImage, viewXVideo, webSearch, xSearch, xai, xaiTools };
package/dist/index.js CHANGED
@@ -34,8 +34,8 @@ __export(src_exports, {
34
34
  module.exports = __toCommonJS(src_exports);
35
35
 
36
36
  // src/xai-provider.ts
37
- var import_provider6 = require("@ai-sdk/provider");
38
- var import_provider_utils15 = require("@ai-sdk/provider-utils");
37
+ var import_provider7 = require("@ai-sdk/provider");
38
+ var import_provider_utils17 = require("@ai-sdk/provider-utils");
39
39
 
40
40
  // src/xai-chat-language-model.ts
41
41
  var import_provider3 = require("@ai-sdk/provider");
@@ -159,10 +159,11 @@ function convertXaiChatUsage(usage) {
159
159
  var _a, _b, _c, _d;
160
160
  const cacheReadTokens = (_b = (_a = usage.prompt_tokens_details) == null ? void 0 : _a.cached_tokens) != null ? _b : 0;
161
161
  const reasoningTokens = (_d = (_c = usage.completion_tokens_details) == null ? void 0 : _c.reasoning_tokens) != null ? _d : 0;
162
+ const promptTokensIncludesCached = cacheReadTokens <= usage.prompt_tokens;
162
163
  return {
163
164
  inputTokens: {
164
- total: usage.prompt_tokens,
165
- noCache: usage.prompt_tokens - cacheReadTokens,
165
+ total: promptTokensIncludesCached ? usage.prompt_tokens : usage.prompt_tokens + cacheReadTokens,
166
+ noCache: promptTokensIncludesCached ? usage.prompt_tokens - cacheReadTokens : usage.prompt_tokens,
166
167
  cacheRead: cacheReadTokens,
167
168
  cacheWrite: void 0
168
169
  },
@@ -1186,10 +1187,11 @@ function convertXaiResponsesUsage(usage) {
1186
1187
  var _a, _b, _c, _d;
1187
1188
  const cacheReadTokens = (_b = (_a = usage.input_tokens_details) == null ? void 0 : _a.cached_tokens) != null ? _b : 0;
1188
1189
  const reasoningTokens = (_d = (_c = usage.output_tokens_details) == null ? void 0 : _c.reasoning_tokens) != null ? _d : 0;
1190
+ const inputTokensIncludesCached = cacheReadTokens <= usage.input_tokens;
1189
1191
  return {
1190
1192
  inputTokens: {
1191
- total: usage.input_tokens,
1192
- noCache: usage.input_tokens - cacheReadTokens,
1193
+ total: inputTokensIncludesCached ? usage.input_tokens : usage.input_tokens + cacheReadTokens,
1194
+ noCache: inputTokensIncludesCached ? usage.input_tokens - cacheReadTokens : usage.input_tokens,
1193
1195
  cacheRead: cacheReadTokens,
1194
1196
  cacheWrite: void 0
1195
1197
  },
@@ -2690,17 +2692,247 @@ var xaiTools = {
2690
2692
  };
2691
2693
 
2692
2694
  // src/version.ts
2693
- var VERSION = true ? "3.0.55" : "0.0.0-test";
2695
+ var VERSION = true ? "3.0.57" : "0.0.0-test";
2696
+
2697
+ // src/xai-video-model.ts
2698
+ var import_provider6 = require("@ai-sdk/provider");
2699
+ var import_provider_utils16 = require("@ai-sdk/provider-utils");
2700
+ var import_v416 = require("zod/v4");
2701
+
2702
+ // src/xai-video-options.ts
2703
+ var import_provider_utils15 = require("@ai-sdk/provider-utils");
2704
+ var import_v415 = require("zod/v4");
2705
+ var xaiVideoModelOptionsSchema = (0, import_provider_utils15.lazySchema)(
2706
+ () => (0, import_provider_utils15.zodSchema)(
2707
+ import_v415.z.object({
2708
+ pollIntervalMs: import_v415.z.number().positive().nullish(),
2709
+ pollTimeoutMs: import_v415.z.number().positive().nullish(),
2710
+ resolution: import_v415.z.enum(["480p", "720p"]).nullish(),
2711
+ videoUrl: import_v415.z.string().nullish()
2712
+ }).passthrough()
2713
+ )
2714
+ );
2715
+
2716
+ // src/xai-video-model.ts
2717
+ var RESOLUTION_MAP = {
2718
+ "1280x720": "720p",
2719
+ "854x480": "480p",
2720
+ "640x480": "480p"
2721
+ };
2722
+ var XaiVideoModel = class {
2723
+ constructor(modelId, config) {
2724
+ this.modelId = modelId;
2725
+ this.config = config;
2726
+ this.specificationVersion = "v3";
2727
+ this.maxVideosPerCall = 1;
2728
+ }
2729
+ get provider() {
2730
+ return this.config.provider;
2731
+ }
2732
+ async doGenerate(options) {
2733
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2734
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
2735
+ const warnings = [];
2736
+ const xaiOptions = await (0, import_provider_utils16.parseProviderOptions)({
2737
+ provider: "xai",
2738
+ providerOptions: options.providerOptions,
2739
+ schema: xaiVideoModelOptionsSchema
2740
+ });
2741
+ const isEdit = (xaiOptions == null ? void 0 : xaiOptions.videoUrl) != null;
2742
+ if (options.fps != null) {
2743
+ warnings.push({
2744
+ type: "unsupported",
2745
+ feature: "fps",
2746
+ details: "xAI video models do not support custom FPS."
2747
+ });
2748
+ }
2749
+ if (options.seed != null) {
2750
+ warnings.push({
2751
+ type: "unsupported",
2752
+ feature: "seed",
2753
+ details: "xAI video models do not support seed."
2754
+ });
2755
+ }
2756
+ if (options.n != null && options.n > 1) {
2757
+ warnings.push({
2758
+ type: "unsupported",
2759
+ feature: "n",
2760
+ details: "xAI video models do not support generating multiple videos per call. Only 1 video will be generated."
2761
+ });
2762
+ }
2763
+ if (isEdit && options.duration != null) {
2764
+ warnings.push({
2765
+ type: "unsupported",
2766
+ feature: "duration",
2767
+ details: "xAI video editing does not support custom duration."
2768
+ });
2769
+ }
2770
+ if (isEdit && options.aspectRatio != null) {
2771
+ warnings.push({
2772
+ type: "unsupported",
2773
+ feature: "aspectRatio",
2774
+ details: "xAI video editing does not support custom aspect ratio."
2775
+ });
2776
+ }
2777
+ if (isEdit && ((xaiOptions == null ? void 0 : xaiOptions.resolution) != null || options.resolution != null)) {
2778
+ warnings.push({
2779
+ type: "unsupported",
2780
+ feature: "resolution",
2781
+ details: "xAI video editing does not support custom resolution."
2782
+ });
2783
+ }
2784
+ const body = {
2785
+ model: this.modelId,
2786
+ prompt: options.prompt
2787
+ };
2788
+ if (!isEdit && options.duration != null) {
2789
+ body.duration = options.duration;
2790
+ }
2791
+ if (!isEdit && options.aspectRatio != null) {
2792
+ body.aspect_ratio = options.aspectRatio;
2793
+ }
2794
+ if (!isEdit && (xaiOptions == null ? void 0 : xaiOptions.resolution) != null) {
2795
+ body.resolution = xaiOptions.resolution;
2796
+ } else if (!isEdit && options.resolution != null) {
2797
+ const mapped = RESOLUTION_MAP[options.resolution];
2798
+ if (mapped != null) {
2799
+ body.resolution = mapped;
2800
+ } else {
2801
+ warnings.push({
2802
+ type: "unsupported",
2803
+ feature: "resolution",
2804
+ details: `Unrecognized resolution "${options.resolution}". Use providerOptions.xai.resolution with "480p" or "720p" instead.`
2805
+ });
2806
+ }
2807
+ }
2808
+ if ((xaiOptions == null ? void 0 : xaiOptions.videoUrl) != null) {
2809
+ body.video = { url: xaiOptions.videoUrl };
2810
+ }
2811
+ if (options.image != null) {
2812
+ if (options.image.type === "url") {
2813
+ body.image = { url: options.image.url };
2814
+ } else {
2815
+ const base64Data = typeof options.image.data === "string" ? options.image.data : (0, import_provider_utils16.convertUint8ArrayToBase64)(options.image.data);
2816
+ body.image = {
2817
+ url: `data:${options.image.mediaType};base64,${base64Data}`
2818
+ };
2819
+ }
2820
+ }
2821
+ if (xaiOptions != null) {
2822
+ for (const [key, value] of Object.entries(xaiOptions)) {
2823
+ if (![
2824
+ "pollIntervalMs",
2825
+ "pollTimeoutMs",
2826
+ "resolution",
2827
+ "videoUrl"
2828
+ ].includes(key)) {
2829
+ body[key] = value;
2830
+ }
2831
+ }
2832
+ }
2833
+ const baseURL = (_d = this.config.baseURL) != null ? _d : "https://api.x.ai/v1";
2834
+ const { value: createResponse } = await (0, import_provider_utils16.postJsonToApi)({
2835
+ url: `${baseURL}/videos/${isEdit ? "edits" : "generations"}`,
2836
+ headers: (0, import_provider_utils16.combineHeaders)(this.config.headers(), options.headers),
2837
+ body,
2838
+ failedResponseHandler: xaiFailedResponseHandler,
2839
+ successfulResponseHandler: (0, import_provider_utils16.createJsonResponseHandler)(
2840
+ xaiCreateVideoResponseSchema
2841
+ ),
2842
+ abortSignal: options.abortSignal,
2843
+ fetch: this.config.fetch
2844
+ });
2845
+ const requestId = createResponse.request_id;
2846
+ if (!requestId) {
2847
+ throw new import_provider6.AISDKError({
2848
+ name: "XAI_VIDEO_GENERATION_ERROR",
2849
+ message: `No request_id returned from xAI API. Response: ${JSON.stringify(createResponse)}`
2850
+ });
2851
+ }
2852
+ const pollIntervalMs = (_e = xaiOptions == null ? void 0 : xaiOptions.pollIntervalMs) != null ? _e : 5e3;
2853
+ const pollTimeoutMs = (_f = xaiOptions == null ? void 0 : xaiOptions.pollTimeoutMs) != null ? _f : 6e5;
2854
+ const startTime = Date.now();
2855
+ let responseHeaders;
2856
+ while (true) {
2857
+ await (0, import_provider_utils16.delay)(pollIntervalMs, { abortSignal: options.abortSignal });
2858
+ if (Date.now() - startTime > pollTimeoutMs) {
2859
+ throw new import_provider6.AISDKError({
2860
+ name: "XAI_VIDEO_GENERATION_TIMEOUT",
2861
+ message: `Video generation timed out after ${pollTimeoutMs}ms`
2862
+ });
2863
+ }
2864
+ const { value: statusResponse, responseHeaders: pollHeaders } = await (0, import_provider_utils16.getFromApi)({
2865
+ url: `${baseURL}/videos/${requestId}`,
2866
+ headers: (0, import_provider_utils16.combineHeaders)(this.config.headers(), options.headers),
2867
+ successfulResponseHandler: (0, import_provider_utils16.createJsonResponseHandler)(
2868
+ xaiVideoStatusResponseSchema
2869
+ ),
2870
+ failedResponseHandler: xaiFailedResponseHandler,
2871
+ abortSignal: options.abortSignal,
2872
+ fetch: this.config.fetch
2873
+ });
2874
+ responseHeaders = pollHeaders;
2875
+ if (statusResponse.status === "done" || statusResponse.status == null && ((_g = statusResponse.video) == null ? void 0 : _g.url)) {
2876
+ if (!((_h = statusResponse.video) == null ? void 0 : _h.url)) {
2877
+ throw new import_provider6.AISDKError({
2878
+ name: "XAI_VIDEO_GENERATION_ERROR",
2879
+ message: "Video generation completed but no video URL was returned."
2880
+ });
2881
+ }
2882
+ return {
2883
+ videos: [
2884
+ {
2885
+ type: "url",
2886
+ url: statusResponse.video.url,
2887
+ mediaType: "video/mp4"
2888
+ }
2889
+ ],
2890
+ warnings,
2891
+ response: {
2892
+ timestamp: currentDate,
2893
+ modelId: this.modelId,
2894
+ headers: responseHeaders
2895
+ },
2896
+ providerMetadata: {
2897
+ xai: {
2898
+ requestId,
2899
+ videoUrl: statusResponse.video.url,
2900
+ ...statusResponse.video.duration != null ? { duration: statusResponse.video.duration } : {}
2901
+ }
2902
+ }
2903
+ };
2904
+ }
2905
+ if (statusResponse.status === "expired") {
2906
+ throw new import_provider6.AISDKError({
2907
+ name: "XAI_VIDEO_GENERATION_EXPIRED",
2908
+ message: "Video generation request expired."
2909
+ });
2910
+ }
2911
+ }
2912
+ }
2913
+ };
2914
+ var xaiCreateVideoResponseSchema = import_v416.z.object({
2915
+ request_id: import_v416.z.string().nullish()
2916
+ });
2917
+ var xaiVideoStatusResponseSchema = import_v416.z.object({
2918
+ status: import_v416.z.string().nullish(),
2919
+ video: import_v416.z.object({
2920
+ url: import_v416.z.string(),
2921
+ duration: import_v416.z.number().nullish(),
2922
+ respect_moderation: import_v416.z.boolean().nullish()
2923
+ }).nullish(),
2924
+ model: import_v416.z.string().nullish()
2925
+ });
2694
2926
 
2695
2927
  // src/xai-provider.ts
2696
2928
  function createXai(options = {}) {
2697
2929
  var _a;
2698
- const baseURL = (0, import_provider_utils15.withoutTrailingSlash)(
2930
+ const baseURL = (0, import_provider_utils17.withoutTrailingSlash)(
2699
2931
  (_a = options.baseURL) != null ? _a : "https://api.x.ai/v1"
2700
2932
  );
2701
- const getHeaders = () => (0, import_provider_utils15.withUserAgentSuffix)(
2933
+ const getHeaders = () => (0, import_provider_utils17.withUserAgentSuffix)(
2702
2934
  {
2703
- Authorization: `Bearer ${(0, import_provider_utils15.loadApiKey)({
2935
+ Authorization: `Bearer ${(0, import_provider_utils17.loadApiKey)({
2704
2936
  apiKey: options.apiKey,
2705
2937
  environmentVariableName: "XAI_API_KEY",
2706
2938
  description: "xAI API key"
@@ -2714,7 +2946,7 @@ function createXai(options = {}) {
2714
2946
  provider: "xai.chat",
2715
2947
  baseURL,
2716
2948
  headers: getHeaders,
2717
- generateId: import_provider_utils15.generateId,
2949
+ generateId: import_provider_utils17.generateId,
2718
2950
  fetch: options.fetch
2719
2951
  });
2720
2952
  };
@@ -2723,7 +2955,7 @@ function createXai(options = {}) {
2723
2955
  provider: "xai.responses",
2724
2956
  baseURL,
2725
2957
  headers: getHeaders,
2726
- generateId: import_provider_utils15.generateId,
2958
+ generateId: import_provider_utils17.generateId,
2727
2959
  fetch: options.fetch
2728
2960
  });
2729
2961
  };
@@ -2735,17 +2967,27 @@ function createXai(options = {}) {
2735
2967
  fetch: options.fetch
2736
2968
  });
2737
2969
  };
2970
+ const createVideoModel = (modelId) => {
2971
+ return new XaiVideoModel(modelId, {
2972
+ provider: "xai.video",
2973
+ baseURL,
2974
+ headers: getHeaders,
2975
+ fetch: options.fetch
2976
+ });
2977
+ };
2738
2978
  const provider = (modelId) => createChatLanguageModel(modelId);
2739
2979
  provider.specificationVersion = "v3";
2740
2980
  provider.languageModel = createChatLanguageModel;
2741
2981
  provider.chat = createChatLanguageModel;
2742
2982
  provider.responses = createResponsesLanguageModel;
2743
2983
  provider.embeddingModel = (modelId) => {
2744
- throw new import_provider6.NoSuchModelError({ modelId, modelType: "embeddingModel" });
2984
+ throw new import_provider7.NoSuchModelError({ modelId, modelType: "embeddingModel" });
2745
2985
  };
2746
2986
  provider.textEmbeddingModel = provider.embeddingModel;
2747
2987
  provider.imageModel = createImageModel;
2748
2988
  provider.image = createImageModel;
2989
+ provider.videoModel = createVideoModel;
2990
+ provider.video = createVideoModel;
2749
2991
  provider.tools = xaiTools;
2750
2992
  return provider;
2751
2993
  }