@tanstack/ai-grok 0.14.3 → 0.14.4

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 (54) hide show
  1. package/dist/esm/adapters/image.d.ts +89 -0
  2. package/dist/esm/adapters/image.js +205 -0
  3. package/dist/esm/adapters/image.js.map +1 -0
  4. package/dist/esm/adapters/summarize.d.ts +51 -0
  5. package/dist/esm/adapters/summarize.js +20 -0
  6. package/dist/esm/adapters/summarize.js.map +1 -0
  7. package/dist/esm/adapters/text.d.ts +76 -0
  8. package/dist/esm/adapters/text.js +44 -0
  9. package/dist/esm/adapters/text.js.map +1 -0
  10. package/dist/esm/adapters/transcription.d.ts +84 -0
  11. package/dist/esm/adapters/transcription.js +122 -0
  12. package/dist/esm/adapters/transcription.js.map +1 -0
  13. package/dist/esm/adapters/tts.d.ts +70 -0
  14. package/dist/esm/adapters/tts.js +142 -0
  15. package/dist/esm/adapters/tts.js.map +1 -0
  16. package/dist/esm/adapters/video.d.ts +128 -0
  17. package/dist/esm/adapters/video.js +237 -0
  18. package/dist/esm/adapters/video.js.map +1 -0
  19. package/dist/esm/audio/transcription-provider-options.d.ts +41 -0
  20. package/dist/esm/audio/tts-provider-options.d.ts +42 -0
  21. package/dist/esm/image/image-provider-options.d.ts +133 -0
  22. package/dist/esm/image/image-provider-options.js +76 -0
  23. package/dist/esm/image/image-provider-options.js.map +1 -0
  24. package/dist/esm/index.d.ts +16 -0
  25. package/dist/esm/index.js +40 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/message-types.d.ts +64 -0
  28. package/dist/esm/model-meta.d.ts +99 -0
  29. package/dist/esm/model-meta.js +58 -0
  30. package/dist/esm/model-meta.js.map +1 -0
  31. package/dist/esm/realtime/adapter.d.ts +21 -0
  32. package/dist/esm/realtime/adapter.js +823 -0
  33. package/dist/esm/realtime/adapter.js.map +1 -0
  34. package/dist/esm/realtime/index.d.ts +4 -0
  35. package/dist/esm/realtime/token.d.ts +22 -0
  36. package/dist/esm/realtime/token.js +75 -0
  37. package/dist/esm/realtime/token.js.map +1 -0
  38. package/dist/esm/realtime/types.d.ts +95 -0
  39. package/dist/esm/text/text-provider-options.d.ts +54 -0
  40. package/dist/esm/tools/index.d.ts +45 -0
  41. package/dist/esm/tools/index.js +113 -0
  42. package/dist/esm/tools/index.js.map +1 -0
  43. package/dist/esm/utils/audio.d.ts +23 -0
  44. package/dist/esm/utils/audio.js +172 -0
  45. package/dist/esm/utils/audio.js.map +1 -0
  46. package/dist/esm/utils/client.d.ts +14 -0
  47. package/dist/esm/utils/client.js +21 -0
  48. package/dist/esm/utils/client.js.map +1 -0
  49. package/dist/esm/utils/index.d.ts +4 -0
  50. package/dist/esm/utils/schema-converter.d.ts +2 -0
  51. package/dist/esm/video/video-provider-options.d.ts +135 -0
  52. package/dist/esm/video/video-provider-options.js +67 -0
  53. package/dist/esm/video/video-provider-options.js.map +1 -0
  54. package/package.json +5 -5
@@ -0,0 +1,237 @@
1
+ import { resolveMediaPrompt } from "@tanstack/ai";
2
+ import { BaseVideoAdapter, snapToDurationOption } from "@tanstack/ai/adapters";
3
+ import { toRunErrorPayload } from "@tanstack/ai/adapter-internals";
4
+ import { withGrokDefaults, getGrokApiKeyFromEnv } from "../utils/client.js";
5
+ import { validateVideoSize, isImageToVideoOnlyModel, parseGrokVideoSize, getGrokVideoDurationOptions } from "../video/video-provider-options.js";
6
+ const USD_TICKS_PER_DOLLAR = 1e10;
7
+ function imagePartToUrl(part) {
8
+ if (part.source.type === "url") return part.source.value;
9
+ return `data:${part.source.mimeType};base64,${part.source.value}`;
10
+ }
11
+ function buildGrokVideoUsage(response) {
12
+ const seconds = response.video?.duration;
13
+ const ticks = response.usage?.cost_in_usd_ticks;
14
+ if (seconds === void 0 && ticks === void 0) return void 0;
15
+ return {
16
+ promptTokens: 0,
17
+ completionTokens: 0,
18
+ totalTokens: 0,
19
+ ...seconds !== void 0 && { unitsBilled: seconds },
20
+ ...ticks !== void 0 && { cost: ticks / USD_TICKS_PER_DOLLAR }
21
+ };
22
+ }
23
+ class GrokVideoAdapter extends BaseVideoAdapter {
24
+ name = "grok";
25
+ clientConfig;
26
+ constructor(config, model) {
27
+ super({}, model);
28
+ this.clientConfig = withGrokDefaults(config);
29
+ }
30
+ get fetch() {
31
+ return this.clientConfig.fetch ?? fetch;
32
+ }
33
+ async request(path, init) {
34
+ return await this.fetch(`${this.clientConfig.baseURL}${path}`, {
35
+ ...init,
36
+ headers: {
37
+ "Content-Type": "application/json",
38
+ Authorization: `Bearer ${this.clientConfig.apiKey}`
39
+ }
40
+ });
41
+ }
42
+ /**
43
+ * Reads the error message out of an Imagine API error body
44
+ * (`{"code": "...", "error": "..."}`), falling back to the raw text.
45
+ */
46
+ async errorMessage(response) {
47
+ const body = await response.text();
48
+ try {
49
+ const parsed = JSON.parse(body);
50
+ if (typeof parsed === "object" && parsed !== null && "error" in parsed && typeof parsed.error === "string") {
51
+ return parsed.error;
52
+ }
53
+ } catch {
54
+ }
55
+ return body;
56
+ }
57
+ async createVideoJob(options) {
58
+ const { model, size, modelOptions, logger } = options;
59
+ validateVideoSize(model, size);
60
+ const rawDuration = modelOptions?.duration ?? options.duration;
61
+ const duration = rawDuration !== void 0 ? this.snapDuration(rawDuration) : void 0;
62
+ const resolved = resolveMediaPrompt(options.prompt);
63
+ if (resolved.videos.length > 0) {
64
+ throw new Error(
65
+ `${this.name}.createVideoJob does not support video prompt parts (model: ${model}).`
66
+ );
67
+ }
68
+ if (resolved.audios.length > 0) {
69
+ throw new Error(
70
+ `${this.name}.createVideoJob does not support audio prompt parts (model: ${model}).`
71
+ );
72
+ }
73
+ if (resolved.images.length === 0 && isImageToVideoOnlyModel(model)) {
74
+ throw new Error(
75
+ `${this.name}: ${model} does not support text-to-video — it is image-to-video only. Include an image prompt part as the starting frame, or use 'grok-imagine-video' for text-to-video.`
76
+ );
77
+ }
78
+ if (resolved.images.length > 1) {
79
+ throw new Error(
80
+ `${this.name}: ${model} accepts at most one starting-frame image; received ${resolved.images.length}.`
81
+ );
82
+ }
83
+ const [startFrame] = resolved.images;
84
+ const parsedSize = size !== void 0 ? parseGrokVideoSize(size) : void 0;
85
+ const request = {
86
+ model,
87
+ prompt: resolved.text,
88
+ ...startFrame && { image: { url: imagePartToUrl(startFrame) } },
89
+ ...parsedSize && {
90
+ aspect_ratio: parsedSize.aspectRatio,
91
+ ...parsedSize.resolution !== void 0 && {
92
+ resolution: parsedSize.resolution
93
+ }
94
+ },
95
+ ...modelOptions,
96
+ // Spread after modelOptions so the snapped duration is authoritative
97
+ // (modelOptions.duration is folded into `duration` via snapDuration above).
98
+ ...duration !== void 0 && { duration }
99
+ };
100
+ try {
101
+ logger.request(
102
+ `activity=video.create provider=${this.name} model=${model} size=${size ?? "default"} duration=${duration ?? "default"}`,
103
+ { provider: this.name, model }
104
+ );
105
+ const response = await this.request("/videos/generations", {
106
+ method: "POST",
107
+ body: JSON.stringify(request)
108
+ });
109
+ if (!response.ok) {
110
+ throw new Error(
111
+ `grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`
112
+ );
113
+ }
114
+ const result = await response.json();
115
+ if (!result.request_id) {
116
+ throw new Error(
117
+ "grok: video generation response contained no request_id"
118
+ );
119
+ }
120
+ return { jobId: result.request_id, model };
121
+ } catch (error) {
122
+ logger.errors(`${this.name}.createVideoJob fatal`, {
123
+ error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
124
+ source: `${this.name}.createVideoJob`
125
+ });
126
+ throw error;
127
+ }
128
+ }
129
+ async retrieveJob(jobId) {
130
+ const response = await this.request(`/videos/${jobId}`);
131
+ if (!response.ok) {
132
+ const error = new Error(
133
+ `grok: video status request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`
134
+ );
135
+ error.status = response.status;
136
+ throw error;
137
+ }
138
+ return await response.json();
139
+ }
140
+ async getVideoStatus(jobId) {
141
+ let response;
142
+ try {
143
+ response = await this.retrieveJob(jobId);
144
+ } catch (error) {
145
+ if (error.status === 404) {
146
+ return { jobId, status: "failed", error: "Job not found" };
147
+ }
148
+ throw error;
149
+ }
150
+ return {
151
+ jobId,
152
+ status: this.mapStatus(response.status),
153
+ ...response.progress !== void 0 && { progress: response.progress },
154
+ ...response.error !== void 0 && { error: response.error }
155
+ };
156
+ }
157
+ async getVideoUrl(jobId) {
158
+ let response;
159
+ try {
160
+ response = await this.retrieveJob(jobId);
161
+ } catch (error) {
162
+ if (error.status === 404) {
163
+ throw new Error(`Video job not found: ${jobId}`);
164
+ }
165
+ throw error;
166
+ }
167
+ const status = this.mapStatus(response.status);
168
+ if (status === "failed") {
169
+ throw new Error(
170
+ `Video generation failed${response.error ? `: ${response.error}` : ""}. Job ID: ${jobId}`
171
+ );
172
+ }
173
+ const url = response.video?.url;
174
+ if (!url) {
175
+ throw new Error(
176
+ `Video is not ready for download. Check status first. Job ID: ${jobId}`
177
+ );
178
+ }
179
+ const usage = buildGrokVideoUsage(response);
180
+ return {
181
+ jobId,
182
+ url,
183
+ ...usage && { usage }
184
+ };
185
+ }
186
+ /**
187
+ * Maps Imagine API job statuses onto the generic video status set. The
188
+ * API reports 'pending' while queued/generating (with a numeric
189
+ * `progress`), then a terminal 'done' / 'failed' / 'expired'.
190
+ */
191
+ mapStatus(apiStatus) {
192
+ switch (apiStatus) {
193
+ case "pending":
194
+ case "queued":
195
+ return "pending";
196
+ case "done":
197
+ case "completed":
198
+ case "succeeded":
199
+ return "completed";
200
+ case "failed":
201
+ case "expired":
202
+ case "error":
203
+ case "cancelled":
204
+ return "failed";
205
+ case void 0:
206
+ default:
207
+ return "processing";
208
+ }
209
+ }
210
+ /**
211
+ * Both grok-imagine video models accept a continuous 1–15 integer-second
212
+ * range. Consumers can use this to render UI without provider knowledge.
213
+ */
214
+ availableDurations() {
215
+ return getGrokVideoDurationOptions(this.model);
216
+ }
217
+ /**
218
+ * Coerce a raw seconds value to the closest valid duration (clamped to
219
+ * [1, 15] and rounded to whole seconds).
220
+ */
221
+ snapDuration(seconds) {
222
+ return snapToDurationOption(seconds, this.availableDurations());
223
+ }
224
+ }
225
+ function createGrokVideo(model, apiKey, config) {
226
+ return new GrokVideoAdapter({ apiKey, ...config }, model);
227
+ }
228
+ function grokVideo(model, config) {
229
+ const apiKey = getGrokApiKeyFromEnv();
230
+ return createGrokVideo(model, apiKey, config);
231
+ }
232
+ export {
233
+ GrokVideoAdapter,
234
+ createGrokVideo,
235
+ grokVideo
236
+ };
237
+ //# sourceMappingURL=video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.js","sources":["../../../src/adapters/video.ts"],"sourcesContent":["import { resolveMediaPrompt } from '@tanstack/ai'\nimport { BaseVideoAdapter, snapToDurationOption } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { getGrokApiKeyFromEnv, withGrokDefaults } from '../utils/client'\nimport {\n getGrokVideoDurationOptions,\n isImageToVideoOnlyModel,\n parseGrokVideoSize,\n validateVideoSize,\n} from '../video/video-provider-options'\nimport type { DurationOptions } from '@tanstack/ai/adapters'\nimport type {\n ImagePart,\n MediaInputMetadata,\n TokenUsage,\n VideoGenerationOptions,\n VideoJobResult,\n VideoStatusResult,\n VideoUrlResult,\n} from '@tanstack/ai'\nimport type { GrokVideoModel } from '../model-meta'\nimport type {\n GrokVideoModelDurationByName,\n GrokVideoModelInputModalitiesByName,\n GrokVideoModelProviderOptionsByName,\n GrokVideoModelSizeByName,\n GrokVideoProviderOptions,\n} from '../video/video-provider-options'\nimport type { GrokClientConfig } from '../utils'\n\n/**\n * Configuration for Grok video adapter.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface GrokVideoConfig extends GrokClientConfig {}\n\n/**\n * xAI bills video generation in \"USD ticks\": 10^10 ticks per US dollar\n * (e.g. one grok-imagine-video-1.5 second costs $0.08 = 800_000_000 ticks).\n */\nconst USD_TICKS_PER_DOLLAR = 10_000_000_000\n\n/** Response of POST /v1/videos/generations. */\ninterface GrokVideoCreateResponse {\n request_id?: string\n}\n\n/** Response of GET /v1/videos/{request_id}. */\ninterface GrokVideoStatusResponse {\n status?: string\n progress?: number\n model?: string\n video?: {\n url?: string\n duration?: number\n }\n usage?: {\n cost_in_usd_ticks?: number\n }\n error?: string\n}\n\n/**\n * Convert a TanStack ImagePart to the URL string accepted by xAI's Imagine\n * video endpoint: public URLs pass through (fetched by xAI's servers), data\n * sources become base64 data URIs.\n */\nfunction imagePartToUrl(part: ImagePart<MediaInputMetadata>): string {\n if (part.source.type === 'url') return part.source.value\n return `data:${part.source.mimeType};base64,${part.source.value}`\n}\n\nfunction buildGrokVideoUsage(\n response: GrokVideoStatusResponse,\n): TokenUsage | undefined {\n const seconds = response.video?.duration\n const ticks = response.usage?.cost_in_usd_ticks\n if (seconds === undefined && ticks === undefined) return undefined\n return {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n ...(seconds !== undefined && { unitsBilled: seconds }),\n ...(ticks !== undefined && { cost: ticks / USD_TICKS_PER_DOLLAR }),\n }\n}\n\n/**\n * Grok Video Generation Adapter (xAI Imagine API)\n *\n * Tree-shakeable adapter for the grok-imagine video models using the\n * async jobs/polling architecture: create a generation request, poll it,\n * then read the completed video URL.\n *\n * `grok-imagine-video` (v1.0) supports text-to-video and image-to-video.\n * `grok-imagine-video-1.5` is image-to-video only — every request needs an\n * image prompt part as the starting frame, and the adapter rejects a\n * text-only prompt with a clear error rather than a raw API 400.\n *\n * The Imagine video endpoints are not part of the OpenAI SDK surface (and\n * xAI rejects the SDK's multipart paths), so requests are plain JSON calls\n * issued with the configured `fetch` (or the global one).\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * Features:\n * - Async job-based video generation (1–15 second clips with audio)\n * - Aspect-ratio sizing via the \"aspectRatio_resolution\" size template\n * (e.g. '16:9_720p'), consistent with the grok-imagine image models\n * - Image-to-video via an `image` prompt part (starting frame URL or data URI)\n * - Usage reporting: billed seconds (`unitsBilled`) and exact cost\n */\nexport class GrokVideoAdapter<\n TModel extends GrokVideoModel,\n> extends BaseVideoAdapter<\n TModel,\n GrokVideoProviderOptions,\n GrokVideoModelProviderOptionsByName,\n GrokVideoModelSizeByName,\n GrokVideoModelInputModalitiesByName,\n GrokVideoModelDurationByName\n> {\n readonly name = 'grok' as const\n\n private readonly clientConfig: GrokVideoConfig\n\n constructor(config: GrokVideoConfig, model: TModel) {\n super({}, model)\n this.clientConfig = withGrokDefaults(config)\n }\n\n private get fetch(): (\n input: string,\n init?: RequestInit,\n ) => Promise<Response> {\n return this.clientConfig.fetch ?? fetch\n }\n\n private async request(\n path: string,\n init?: Omit<RequestInit, 'headers'>,\n ): Promise<Response> {\n return await this.fetch(`${this.clientConfig.baseURL}${path}`, {\n ...init,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.clientConfig.apiKey}`,\n },\n })\n }\n\n /**\n * Reads the error message out of an Imagine API error body\n * (`{\"code\": \"...\", \"error\": \"...\"}`), falling back to the raw text.\n */\n private async errorMessage(response: Response): Promise<string> {\n const body = await response.text()\n try {\n const parsed: unknown = JSON.parse(body)\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n 'error' in parsed &&\n typeof parsed.error === 'string'\n ) {\n return parsed.error\n }\n } catch {\n // not JSON — fall through to the raw body\n }\n return body\n }\n\n async createVideoJob(\n options: VideoGenerationOptions<\n GrokVideoProviderOptions,\n GrokVideoModelSizeByName[TModel],\n GrokVideoModelDurationByName[TModel]\n >,\n ): Promise<VideoJobResult> {\n const { model, size, modelOptions, logger } = options\n\n validateVideoSize(model, size)\n\n // Coerce the requested duration into the model's valid range (1–15s,\n // integer) instead of rejecting it — `snapDuration` clamps and rounds.\n // modelOptions wins over the generic `duration`, mirroring the size\n // precedence below.\n const rawDuration = modelOptions?.duration ?? options.duration\n const duration =\n rawDuration !== undefined ? this.snapDuration(rawDuration) : undefined\n\n // The interleaved prompt decomposes into verbatim text plus typed media\n // buckets. The Imagine video endpoint takes a text prompt and an optional\n // starting frame; reject the modalities it can't consume.\n const resolved = resolveMediaPrompt(options.prompt)\n if (resolved.videos.length > 0) {\n throw new Error(\n `${this.name}.createVideoJob does not support video prompt parts (model: ${model}).`,\n )\n }\n if (resolved.audios.length > 0) {\n throw new Error(\n `${this.name}.createVideoJob does not support audio prompt parts (model: ${model}).`,\n )\n }\n // grok-imagine-video-1.5 is image-to-video only — text-to-video is\n // rejected by the API, so fail fast with a clear, actionable message\n // pointing at the model that does support text-to-video.\n if (resolved.images.length === 0 && isImageToVideoOnlyModel(model)) {\n throw new Error(\n `${this.name}: ${model} does not support text-to-video — it is image-to-video only. ` +\n `Include an image prompt part as the starting frame, or use 'grok-imagine-video' for text-to-video.`,\n )\n }\n if (resolved.images.length > 1) {\n throw new Error(\n `${this.name}: ${model} accepts at most one starting-frame image; received ${resolved.images.length}.`,\n )\n }\n\n // Image-to-video: the single image prompt part becomes the starting frame\n // and the prompt text describes the desired motion. URL sources are\n // fetched by xAI's servers; data sources are sent as base64 data URIs.\n const [startFrame] = resolved.images\n\n // The generic `size` option carries an \"aspectRatio_resolution\" template\n // (e.g. '16:9_720p') and maps to the Imagine API's `aspect_ratio` /\n // `resolution` parameters; explicit modelOptions win over the template.\n const parsedSize = size !== undefined ? parseGrokVideoSize(size) : undefined\n const request = {\n model,\n prompt: resolved.text,\n ...(startFrame && { image: { url: imagePartToUrl(startFrame) } }),\n ...(parsedSize && {\n aspect_ratio: parsedSize.aspectRatio,\n ...(parsedSize.resolution !== undefined && {\n resolution: parsedSize.resolution,\n }),\n }),\n ...modelOptions,\n // Spread after modelOptions so the snapped duration is authoritative\n // (modelOptions.duration is folded into `duration` via snapDuration above).\n ...(duration !== undefined && { duration }),\n }\n\n try {\n logger.request(\n `activity=video.create provider=${this.name} model=${model} size=${size ?? 'default'} duration=${duration ?? 'default'}`,\n { provider: this.name, model },\n )\n\n const response = await this.request('/videos/generations', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n if (!response.ok) {\n throw new Error(\n `grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,\n )\n }\n\n const result = (await response.json()) as GrokVideoCreateResponse\n if (!result.request_id) {\n throw new Error(\n 'grok: video generation response contained no request_id',\n )\n }\n return { jobId: result.request_id, model }\n } catch (error: unknown) {\n logger.errors(`${this.name}.createVideoJob fatal`, {\n error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),\n source: `${this.name}.createVideoJob`,\n })\n throw error\n }\n }\n\n private async retrieveJob(jobId: string): Promise<GrokVideoStatusResponse> {\n const response = await this.request(`/videos/${jobId}`)\n if (!response.ok) {\n const error = new Error(\n `grok: video status request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,\n )\n ;(error as { status?: number }).status = response.status\n throw error\n }\n return (await response.json()) as GrokVideoStatusResponse\n }\n\n async getVideoStatus(jobId: string): Promise<VideoStatusResult> {\n let response: GrokVideoStatusResponse\n try {\n response = await this.retrieveJob(jobId)\n } catch (error) {\n if ((error as { status?: number }).status === 404) {\n return { jobId, status: 'failed', error: 'Job not found' }\n }\n throw error\n }\n\n return {\n jobId,\n status: this.mapStatus(response.status),\n ...(response.progress !== undefined && { progress: response.progress }),\n ...(response.error !== undefined && { error: response.error }),\n }\n }\n\n async getVideoUrl(jobId: string): Promise<VideoUrlResult> {\n let response: GrokVideoStatusResponse\n try {\n response = await this.retrieveJob(jobId)\n } catch (error) {\n if ((error as { status?: number }).status === 404) {\n throw new Error(`Video job not found: ${jobId}`)\n }\n throw error\n }\n\n const status = this.mapStatus(response.status)\n if (status === 'failed') {\n throw new Error(\n `Video generation failed${response.error ? `: ${response.error}` : ''}. Job ID: ${jobId}`,\n )\n }\n const url = response.video?.url\n if (!url) {\n throw new Error(\n `Video is not ready for download. Check status first. Job ID: ${jobId}`,\n )\n }\n\n const usage = buildGrokVideoUsage(response)\n return {\n jobId,\n url,\n ...(usage && { usage }),\n }\n }\n\n /**\n * Maps Imagine API job statuses onto the generic video status set. The\n * API reports 'pending' while queued/generating (with a numeric\n * `progress`), then a terminal 'done' / 'failed' / 'expired'.\n */\n protected mapStatus(\n apiStatus: string | undefined,\n ): 'pending' | 'processing' | 'completed' | 'failed' {\n switch (apiStatus) {\n case 'pending':\n case 'queued':\n return 'pending'\n case 'done':\n case 'completed':\n case 'succeeded':\n return 'completed'\n case 'failed':\n case 'expired':\n case 'error':\n case 'cancelled':\n return 'failed'\n case undefined:\n default:\n return 'processing'\n }\n }\n\n /**\n * Both grok-imagine video models accept a continuous 1–15 integer-second\n * range. Consumers can use this to render UI without provider knowledge.\n */\n override availableDurations(): DurationOptions<\n GrokVideoModelDurationByName[TModel]\n > {\n return getGrokVideoDurationOptions(this.model)\n }\n\n /**\n * Coerce a raw seconds value to the closest valid duration (clamped to\n * [1, 15] and rounded to whole seconds).\n */\n override snapDuration(\n seconds: number,\n ): GrokVideoModelDurationByName[TModel] | undefined {\n return snapToDurationOption(seconds, this.availableDurations())\n }\n}\n\n/**\n * Creates a Grok video adapter with an explicit API key.\n * Type resolution happens here at the call site.\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * @param model - The model name (e.g., 'grok-imagine-video')\n * @param apiKey - Your xAI API key\n * @param config - Optional additional configuration\n * @returns Configured Grok video adapter instance with resolved types\n *\n * @example\n * ```typescript\n * // grok-imagine-video (v1.0) supports text-to-video.\n * const adapter = createGrokVideo('grok-imagine-video', 'xai-...');\n *\n * const { jobId } = await generateVideo({\n * adapter,\n * prompt: 'A beautiful sunset over the ocean',\n * size: '16:9_720p',\n * duration: 5\n * });\n * ```\n */\nexport function createGrokVideo<TModel extends GrokVideoModel>(\n model: TModel,\n apiKey: string,\n config?: Omit<GrokVideoConfig, 'apiKey'>,\n): GrokVideoAdapter<TModel> {\n return new GrokVideoAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates a Grok video adapter with automatic API key detection from environment variables.\n * Type resolution happens here at the call site.\n *\n * Looks for `XAI_API_KEY` in:\n * - `process.env` (Node.js)\n * - `window.env` (Browser with injected env)\n *\n * @experimental Video generation is an experimental feature and may change.\n *\n * @param model - The model name (e.g., 'grok-imagine-video-1.5')\n * @param config - Optional configuration (excluding apiKey which is auto-detected)\n * @returns Configured Grok video adapter instance with resolved types\n * @throws Error if XAI_API_KEY is not found in environment\n *\n * @example\n * ```typescript\n * // Automatically uses XAI_API_KEY from environment\n * const adapter = grokVideo('grok-imagine-video-1.5');\n *\n * // Image-to-video only: the prompt must carry a starting-frame image part.\n * const { jobId } = await generateVideo({\n * adapter,\n * prompt: [\n * { type: 'text', content: 'Make the cat start playing the piano' },\n * { type: 'image', source: { type: 'url', value: 'https://example.com/cat.png' } },\n * ],\n * });\n *\n * // Poll for status\n * const status = await getVideoJobStatus({ adapter, jobId });\n * ```\n */\nexport function grokVideo<TModel extends GrokVideoModel>(\n model: TModel,\n config?: Omit<GrokVideoConfig, 'apiKey'>,\n): GrokVideoAdapter<TModel> {\n const apiKey = getGrokApiKeyFromEnv()\n return createGrokVideo(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Grok STT supported audio formats.
3
+ * See https://docs.x.ai/developers/rest-api-reference/inference/voice
4
+ */
5
+ export type GrokSTTAudioFormat = 'pcm' | 'mulaw' | 'alaw' | 'wav' | 'mp3' | 'ogg' | 'opus' | 'flac' | 'aac' | 'mp4' | 'm4a' | 'mkv';
6
+ /**
7
+ * Provider-specific options for Grok transcription (`POST /v1/stt`).
8
+ */
9
+ export interface GrokTranscriptionProviderOptions {
10
+ /**
11
+ * The format of the provided audio. Required for raw codecs (pcm, mulaw, alaw).
12
+ */
13
+ audio_format?: GrokSTTAudioFormat;
14
+ /**
15
+ * Sample rate of the audio (Hz). Required for raw codecs.
16
+ */
17
+ sample_rate?: number;
18
+ /**
19
+ * Apply inverse text normalization (e.g. "one hundred" → "100"). Requires
20
+ * `language` to be set on the core `TranscriptionOptions`.
21
+ *
22
+ * NOTE: xAI's STT API exposes this on the wire as `format` (a boolean
23
+ * toggle). We surface it under the clearer name
24
+ * `inverse_text_normalization` on the SDK, and translate to the wire name
25
+ * inside the adapter.
26
+ */
27
+ inverse_text_normalization?: boolean;
28
+ /**
29
+ * Treat the audio as multichannel. When enabled, `channels` must also be set.
30
+ */
31
+ multichannel?: boolean;
32
+ /**
33
+ * Channel count for multichannel raw audio (2–8).
34
+ */
35
+ channels?: number;
36
+ /**
37
+ * Enable speaker diarization. When true, response words include a `speaker`
38
+ * field.
39
+ */
40
+ diarize?: boolean;
41
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Grok TTS voice options.
3
+ * See https://docs.x.ai/developers/model-capabilities/audio/text-to-speech
4
+ */
5
+ export type GrokTTSVoice = 'eve' | 'ara' | 'rex' | 'sal' | 'leo';
6
+ /**
7
+ * Grok TTS output audio codecs.
8
+ * Grok does NOT support opus or aac; those formats are mapped to mp3.
9
+ */
10
+ export type GrokTTSCodec = 'mp3' | 'wav' | 'pcm' | 'mulaw' | 'alaw';
11
+ /**
12
+ * Provider-specific options for Grok TTS (`POST /v1/tts`).
13
+ */
14
+ export interface GrokTTSProviderOptions {
15
+ /**
16
+ * BCP-47 language code (e.g., `en`, `zh`, `pt-BR`) or `'auto'` for detection.
17
+ * Defaults to `'en'` when not provided.
18
+ */
19
+ language?: string;
20
+ /**
21
+ * Audio codec. Overrides the `format` field on `TTSOptions` when set.
22
+ */
23
+ codec?: GrokTTSCodec;
24
+ /**
25
+ * Sample rate in Hz. Valid values: 8000, 16000, 22050, 24000, 44100, 48000.
26
+ * Defaults to 24000.
27
+ */
28
+ sample_rate?: 8000 | 16000 | 22050 | 24000 | 44100 | 48000;
29
+ /**
30
+ * Bit rate for MP3 output. Ignored for other codecs.
31
+ * Valid values: 32000, 64000, 96000, 128000, 192000. Defaults to 128000.
32
+ */
33
+ bit_rate?: 32000 | 64000 | 96000 | 128000 | 192000;
34
+ /**
35
+ * Set to 1 for lower latency streaming; 0 (default) for normal quality.
36
+ */
37
+ optimize_streaming_latency?: 0 | 1;
38
+ /**
39
+ * Enable text normalization. Defaults to false.
40
+ */
41
+ text_normalization?: boolean;
42
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Grok Image Generation Provider Options
3
+ *
4
+ * These are provider-specific options for Grok image generation.
5
+ * Grok uses the grok-2-image-1212 model for image generation.
6
+ */
7
+ /**
8
+ * Supported sizes for grok-2-image-1212 model
9
+ */
10
+ export type GrokImageSize = '1024x1024' | '1536x1024' | '1024x1536';
11
+ /**
12
+ * Aspect ratios accepted by the grok-imagine image models.
13
+ */
14
+ export type GrokImagineAspectRatio = '1:1' | '3:4' | '4:3' | '9:16' | '16:9' | '2:3' | '3:2' | '9:19.5' | '19.5:9' | '9:20' | '20:9' | '1:2' | '2:1' | 'auto';
15
+ /**
16
+ * Resolution tiers for the grok-imagine image models.
17
+ */
18
+ export type GrokImagineResolution = '1k' | '2k';
19
+ /**
20
+ * Size strings for grok-imagine image models. The Imagine API is
21
+ * aspect-ratio based rather than pixel-size based; like Gemini's native
22
+ * image models, the generic `size` option uses an
23
+ * `aspectRatio_resolution` template ("16:9_2k") — the resolution suffix is
24
+ * optional ("16:9" uses the API default of 1k).
25
+ */
26
+ export type GrokImagineImageSize = GrokImagineAspectRatio | `${GrokImagineAspectRatio}_${GrokImagineResolution}`;
27
+ /**
28
+ * Models served by xAI's Imagine API. They are aspect-ratio sized and
29
+ * support image-conditioned generation via `/v1/images/edits`; the legacy
30
+ * grok-2-image-1212 model is pixel-sized and text-to-image only.
31
+ */
32
+ export declare function isGrokImagineImageModel(model: string): boolean;
33
+ /**
34
+ * Parses a grok-imagine size string into its components.
35
+ * Format: "aspectRatio" or "aspectRatio_resolution",
36
+ * e.g. "16:9_2k" → { aspectRatio: "16:9", resolution: "2k" }.
37
+ * Returns undefined when the string doesn't match the template.
38
+ */
39
+ export declare function parseGrokImagineSize(size: string): {
40
+ aspectRatio: string;
41
+ resolution?: string;
42
+ } | undefined;
43
+ /**
44
+ * Base provider options for Grok image models
45
+ */
46
+ export interface GrokImageBaseProviderOptions {
47
+ /**
48
+ * A unique identifier representing your end-user.
49
+ * Can help xAI to monitor and detect abuse.
50
+ */
51
+ user?: string;
52
+ }
53
+ /**
54
+ * Provider options for grok-2-image-1212 model
55
+ */
56
+ export interface GrokImageProviderOptions extends GrokImageBaseProviderOptions {
57
+ /**
58
+ * The quality of the image.
59
+ * @default 'standard'
60
+ */
61
+ quality?: 'standard' | 'hd';
62
+ /**
63
+ * The format in which generated images are returned.
64
+ * URLs are only valid for 60 minutes after generation.
65
+ * @default 'url'
66
+ */
67
+ response_format?: 'url' | 'b64_json';
68
+ }
69
+ /**
70
+ * Provider options for the grok-imagine image models (generation and
71
+ * image-conditioned editing via xAI's Imagine API).
72
+ */
73
+ export interface GrokImagineImageProviderOptions extends GrokImageBaseProviderOptions {
74
+ /**
75
+ * The format in which generated images are returned.
76
+ * @default 'url'
77
+ */
78
+ response_format?: 'url' | 'b64_json';
79
+ /**
80
+ * Output resolution.
81
+ * @default '1k'
82
+ */
83
+ resolution?: '1k' | '2k';
84
+ /**
85
+ * Processing tier for the request.
86
+ * @default 'default'
87
+ */
88
+ service_tier?: 'default' | 'priority';
89
+ }
90
+ /**
91
+ * Type-only map from model name to its specific provider options.
92
+ */
93
+ export type GrokImageModelProviderOptionsByName = {
94
+ 'grok-2-image-1212': GrokImageProviderOptions;
95
+ 'grok-imagine-image': GrokImagineImageProviderOptions;
96
+ 'grok-imagine-image-quality': GrokImagineImageProviderOptions;
97
+ };
98
+ /**
99
+ * Type-only map from model name to its supported sizes.
100
+ */
101
+ export type GrokImageModelSizeByName = {
102
+ 'grok-2-image-1212': GrokImageSize;
103
+ 'grok-imagine-image': GrokImagineImageSize;
104
+ 'grok-imagine-image-quality': GrokImagineImageSize;
105
+ };
106
+ /**
107
+ * Per-model prompt input modalities. Imagine API models accept image parts
108
+ * in the prompt (routed to `/v1/images/edits`, up to 3 images, addressed by
109
+ * xAI in request order); grok-2-image is text-to-image only.
110
+ */
111
+ export type GrokImageModelInputModalitiesByName = {
112
+ 'grok-2-image-1212': readonly [];
113
+ 'grok-imagine-image': readonly ['image'];
114
+ 'grok-imagine-image-quality': readonly ['image'];
115
+ };
116
+ /**
117
+ * Internal options interface for validation
118
+ */
119
+ interface ImageValidationOptions {
120
+ prompt: string;
121
+ model: string;
122
+ }
123
+ /**
124
+ * Validates that the provided size is supported by the model.
125
+ * Throws a descriptive error if the size is not supported.
126
+ */
127
+ export declare function validateImageSize(model: string, size: string | undefined): void;
128
+ /**
129
+ * Validates that the number of images is within bounds for the model.
130
+ */
131
+ export declare function validateNumberOfImages(_model: string, numberOfImages: number | undefined): void;
132
+ export declare const validatePrompt: (options: ImageValidationOptions) => void;
133
+ export {};
@@ -0,0 +1,76 @@
1
+ const GROK_IMAGINE_ASPECT_RATIOS = [
2
+ "1:1",
3
+ "3:4",
4
+ "4:3",
5
+ "9:16",
6
+ "16:9",
7
+ "2:3",
8
+ "3:2",
9
+ "9:19.5",
10
+ "19.5:9",
11
+ "9:20",
12
+ "20:9",
13
+ "1:2",
14
+ "2:1",
15
+ "auto"
16
+ ];
17
+ const GROK_IMAGINE_RESOLUTIONS = ["1k", "2k"];
18
+ function isGrokImagineImageModel(model) {
19
+ return model.startsWith("grok-imagine-image");
20
+ }
21
+ function parseGrokImagineSize(size) {
22
+ const match = size.match(/^([\d.]+:[\d.]+|auto)(?:_(.+))?$/);
23
+ const [, aspectRatio, resolution] = match ?? [];
24
+ if (aspectRatio === void 0) return void 0;
25
+ return { aspectRatio, ...resolution !== void 0 && { resolution } };
26
+ }
27
+ function validateImageSize(model, size) {
28
+ if (!size) return;
29
+ if (isGrokImagineImageModel(model)) {
30
+ const parsed = parseGrokImagineSize(size);
31
+ if (!parsed || !GROK_IMAGINE_ASPECT_RATIOS.includes(parsed.aspectRatio) || parsed.resolution !== void 0 && !GROK_IMAGINE_RESOLUTIONS.includes(parsed.resolution)) {
32
+ throw new Error(
33
+ `Size "${size}" is not supported by model "${model}". Expected an aspect ratio (${GROK_IMAGINE_ASPECT_RATIOS.join(", ")}) optionally suffixed with a resolution ("16:9_2k"; resolutions: ${GROK_IMAGINE_RESOLUTIONS.join(", ")}).`
34
+ );
35
+ }
36
+ return;
37
+ }
38
+ const validSizes = {
39
+ "grok-2-image-1212": ["1024x1024", "1536x1024", "1024x1536"]
40
+ };
41
+ const modelSizes = validSizes[model];
42
+ if (!modelSizes) {
43
+ throw new Error(`Unknown image model: ${model}`);
44
+ }
45
+ if (!modelSizes.includes(size)) {
46
+ throw new Error(
47
+ `Size "${size}" is not supported by model "${model}". Supported sizes: ${modelSizes.join(", ")}`
48
+ );
49
+ }
50
+ }
51
+ function validateNumberOfImages(_model, numberOfImages) {
52
+ if (numberOfImages === void 0) return;
53
+ if (numberOfImages < 1 || numberOfImages > 10) {
54
+ throw new Error(
55
+ `Number of images must be between 1 and 10. Requested: ${numberOfImages}`
56
+ );
57
+ }
58
+ }
59
+ const validatePrompt = (options) => {
60
+ if (options.prompt.length === 0) {
61
+ throw new Error("Prompt cannot be empty.");
62
+ }
63
+ if (options.prompt.length > 4e3) {
64
+ throw new Error(
65
+ "For grok-2-image-1212, prompt length must be less than or equal to 4000 characters."
66
+ );
67
+ }
68
+ };
69
+ export {
70
+ isGrokImagineImageModel,
71
+ parseGrokImagineSize,
72
+ validateImageSize,
73
+ validateNumberOfImages,
74
+ validatePrompt
75
+ };
76
+ //# sourceMappingURL=image-provider-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-provider-options.js","sources":["../../../src/image/image-provider-options.ts"],"sourcesContent":["/**\n * Grok Image Generation Provider Options\n *\n * These are provider-specific options for Grok image generation.\n * Grok uses the grok-2-image-1212 model for image generation.\n */\n\n/**\n * Supported sizes for grok-2-image-1212 model\n */\nexport type GrokImageSize = '1024x1024' | '1536x1024' | '1024x1536'\n\n/**\n * Aspect ratios accepted by the grok-imagine image models.\n */\nexport type GrokImagineAspectRatio =\n | '1:1'\n | '3:4'\n | '4:3'\n | '9:16'\n | '16:9'\n | '2:3'\n | '3:2'\n | '9:19.5'\n | '19.5:9'\n | '9:20'\n | '20:9'\n | '1:2'\n | '2:1'\n | 'auto'\n\n/**\n * Resolution tiers for the grok-imagine image models.\n */\nexport type GrokImagineResolution = '1k' | '2k'\n\n/**\n * Size strings for grok-imagine image models. The Imagine API is\n * aspect-ratio based rather than pixel-size based; like Gemini's native\n * image models, the generic `size` option uses an\n * `aspectRatio_resolution` template (\"16:9_2k\") — the resolution suffix is\n * optional (\"16:9\" uses the API default of 1k).\n */\nexport type GrokImagineImageSize =\n | GrokImagineAspectRatio\n | `${GrokImagineAspectRatio}_${GrokImagineResolution}`\n\nconst GROK_IMAGINE_ASPECT_RATIOS: ReadonlyArray<string> = [\n '1:1',\n '3:4',\n '4:3',\n '9:16',\n '16:9',\n '2:3',\n '3:2',\n '9:19.5',\n '19.5:9',\n '9:20',\n '20:9',\n '1:2',\n '2:1',\n 'auto',\n]\n\nconst GROK_IMAGINE_RESOLUTIONS: ReadonlyArray<string> = ['1k', '2k']\n\n/**\n * Models served by xAI's Imagine API. They are aspect-ratio sized and\n * support image-conditioned generation via `/v1/images/edits`; the legacy\n * grok-2-image-1212 model is pixel-sized and text-to-image only.\n */\nexport function isGrokImagineImageModel(model: string): boolean {\n return model.startsWith('grok-imagine-image')\n}\n\n/**\n * Parses a grok-imagine size string into its components.\n * Format: \"aspectRatio\" or \"aspectRatio_resolution\",\n * e.g. \"16:9_2k\" → { aspectRatio: \"16:9\", resolution: \"2k\" }.\n * Returns undefined when the string doesn't match the template.\n */\nexport function parseGrokImagineSize(\n size: string,\n): { aspectRatio: string; resolution?: string } | undefined {\n const match = size.match(/^([\\d.]+:[\\d.]+|auto)(?:_(.+))?$/)\n const [, aspectRatio, resolution] = match ?? []\n if (aspectRatio === undefined) return undefined\n return { aspectRatio, ...(resolution !== undefined && { resolution }) }\n}\n\n/**\n * Base provider options for Grok image models\n */\nexport interface GrokImageBaseProviderOptions {\n /**\n * A unique identifier representing your end-user.\n * Can help xAI to monitor and detect abuse.\n */\n user?: string\n}\n\n/**\n * Provider options for grok-2-image-1212 model\n */\nexport interface GrokImageProviderOptions extends GrokImageBaseProviderOptions {\n /**\n * The quality of the image.\n * @default 'standard'\n */\n quality?: 'standard' | 'hd'\n\n /**\n * The format in which generated images are returned.\n * URLs are only valid for 60 minutes after generation.\n * @default 'url'\n */\n response_format?: 'url' | 'b64_json'\n}\n\n/**\n * Provider options for the grok-imagine image models (generation and\n * image-conditioned editing via xAI's Imagine API).\n */\nexport interface GrokImagineImageProviderOptions extends GrokImageBaseProviderOptions {\n /**\n * The format in which generated images are returned.\n * @default 'url'\n */\n response_format?: 'url' | 'b64_json'\n\n /**\n * Output resolution.\n * @default '1k'\n */\n resolution?: '1k' | '2k'\n\n /**\n * Processing tier for the request.\n * @default 'default'\n */\n service_tier?: 'default' | 'priority'\n}\n\n/**\n * Type-only map from model name to its specific provider options.\n */\nexport type GrokImageModelProviderOptionsByName = {\n 'grok-2-image-1212': GrokImageProviderOptions\n 'grok-imagine-image': GrokImagineImageProviderOptions\n 'grok-imagine-image-quality': GrokImagineImageProviderOptions\n}\n\n/**\n * Type-only map from model name to its supported sizes.\n */\nexport type GrokImageModelSizeByName = {\n 'grok-2-image-1212': GrokImageSize\n 'grok-imagine-image': GrokImagineImageSize\n 'grok-imagine-image-quality': GrokImagineImageSize\n}\n\n/**\n * Per-model prompt input modalities. Imagine API models accept image parts\n * in the prompt (routed to `/v1/images/edits`, up to 3 images, addressed by\n * xAI in request order); grok-2-image is text-to-image only.\n */\nexport type GrokImageModelInputModalitiesByName = {\n 'grok-2-image-1212': readonly []\n 'grok-imagine-image': readonly ['image']\n 'grok-imagine-image-quality': readonly ['image']\n}\n\n/**\n * Internal options interface for validation\n */\ninterface ImageValidationOptions {\n prompt: string\n model: string\n}\n\n/**\n * Validates that the provided size is supported by the model.\n * Throws a descriptive error if the size is not supported.\n */\nexport function validateImageSize(\n model: string,\n size: string | undefined,\n): void {\n if (!size) return\n\n if (isGrokImagineImageModel(model)) {\n const parsed = parseGrokImagineSize(size)\n if (\n !parsed ||\n !GROK_IMAGINE_ASPECT_RATIOS.includes(parsed.aspectRatio) ||\n (parsed.resolution !== undefined &&\n !GROK_IMAGINE_RESOLUTIONS.includes(parsed.resolution))\n ) {\n throw new Error(\n `Size \"${size}\" is not supported by model \"${model}\". ` +\n `Expected an aspect ratio (${GROK_IMAGINE_ASPECT_RATIOS.join(', ')}) ` +\n `optionally suffixed with a resolution (\"16:9_2k\"; resolutions: ${GROK_IMAGINE_RESOLUTIONS.join(', ')}).`,\n )\n }\n return\n }\n\n const validSizes: Record<string, Array<string>> = {\n 'grok-2-image-1212': ['1024x1024', '1536x1024', '1024x1536'],\n }\n\n const modelSizes = validSizes[model]\n if (!modelSizes) {\n throw new Error(`Unknown image model: ${model}`)\n }\n\n if (!modelSizes.includes(size)) {\n throw new Error(\n `Size \"${size}\" is not supported by model \"${model}\". ` +\n `Supported sizes: ${modelSizes.join(', ')}`,\n )\n }\n}\n\n/**\n * Validates that the number of images is within bounds for the model.\n */\nexport function validateNumberOfImages(\n _model: string,\n numberOfImages: number | undefined,\n): void {\n if (numberOfImages === undefined) return\n\n // grok-2-image-1212 supports 1-10 images per request\n if (numberOfImages < 1 || numberOfImages > 10) {\n throw new Error(\n `Number of images must be between 1 and 10. Requested: ${numberOfImages}`,\n )\n }\n}\n\nexport const validatePrompt = (options: ImageValidationOptions) => {\n if (options.prompt.length === 0) {\n throw new Error('Prompt cannot be empty.')\n }\n // Grok image model supports up to 4000 characters\n if (options.prompt.length > 4000) {\n throw new Error(\n 'For grok-2-image-1212, prompt length must be less than or equal to 4000 characters.',\n )\n }\n}\n"],"names":[],"mappings":"AA+CA,MAAM,6BAAoD;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,2BAAkD,CAAC,MAAM,IAAI;AAO5D,SAAS,wBAAwB,OAAwB;AAC9D,SAAO,MAAM,WAAW,oBAAoB;AAC9C;AAQO,SAAS,qBACd,MAC0D;AAC1D,QAAM,QAAQ,KAAK,MAAM,kCAAkC;AAC3D,QAAM,GAAG,aAAa,UAAU,IAAI,SAAS,CAAA;AAC7C,MAAI,gBAAgB,OAAW,QAAO;AACtC,SAAO,EAAE,aAAa,GAAI,eAAe,UAAa,EAAE,aAAW;AACrE;AAgGO,SAAS,kBACd,OACA,MACM;AACN,MAAI,CAAC,KAAM;AAEX,MAAI,wBAAwB,KAAK,GAAG;AAClC,UAAM,SAAS,qBAAqB,IAAI;AACxC,QACE,CAAC,UACD,CAAC,2BAA2B,SAAS,OAAO,WAAW,KACtD,OAAO,eAAe,UACrB,CAAC,yBAAyB,SAAS,OAAO,UAAU,GACtD;AACA,YAAM,IAAI;AAAA,QACR,SAAS,IAAI,gCAAgC,KAAK,gCACnB,2BAA2B,KAAK,IAAI,CAAC,oEACA,yBAAyB,KAAK,IAAI,CAAC;AAAA,MAAA;AAAA,IAE3G;AACA;AAAA,EACF;AAEA,QAAM,aAA4C;AAAA,IAChD,qBAAqB,CAAC,aAAa,aAAa,WAAW;AAAA,EAAA;AAG7D,QAAM,aAAa,WAAW,KAAK;AACnC,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,wBAAwB,KAAK,EAAE;AAAA,EACjD;AAEA,MAAI,CAAC,WAAW,SAAS,IAAI,GAAG;AAC9B,UAAM,IAAI;AAAA,MACR,SAAS,IAAI,gCAAgC,KAAK,uBAC5B,WAAW,KAAK,IAAI,CAAC;AAAA,IAAA;AAAA,EAE/C;AACF;AAKO,SAAS,uBACd,QACA,gBACM;AACN,MAAI,mBAAmB,OAAW;AAGlC,MAAI,iBAAiB,KAAK,iBAAiB,IAAI;AAC7C,UAAM,IAAI;AAAA,MACR,yDAAyD,cAAc;AAAA,IAAA;AAAA,EAE3E;AACF;AAEO,MAAM,iBAAiB,CAAC,YAAoC;AACjE,MAAI,QAAQ,OAAO,WAAW,GAAG;AAC/B,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,MAAI,QAAQ,OAAO,SAAS,KAAM;AAChC,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;"}
@@ -0,0 +1,16 @@
1
+ export { GrokTextAdapter, createGrokText, grokText, type GrokTextConfig, type GrokTextProviderOptions, } from './adapters/text.js';
2
+ export { createGrokSummarize, grokSummarize, type GrokSummarizeConfig, type GrokSummarizeModel, } from './adapters/summarize.js';
3
+ export { GrokImageAdapter, createGrokImage, grokImage, type GrokImageConfig, } from './adapters/image.js';
4
+ export type { GrokImageProviderOptions, GrokImageModelProviderOptionsByName, } from './image/image-provider-options.js';
5
+ export { GrokVideoAdapter, createGrokVideo, grokVideo, type GrokVideoConfig, } from './adapters/video.js';
6
+ export { GROK_VIDEO_DURATIONS, getGrokVideoDurationOptions, } from './video/video-provider-options.js';
7
+ export type { GrokVideoProviderOptions, GrokVideoModelProviderOptionsByName, GrokVideoModelSizeByName, GrokVideoModelDurationByName, GrokVideoAspectRatio, GrokVideoResolution, GrokVideoSize, } from './video/video-provider-options.js';
8
+ export { GrokSpeechAdapter, createGrokSpeech, grokSpeech, type GrokSpeechConfig, } from './adapters/tts.js';
9
+ export type { GrokTTSProviderOptions, GrokTTSVoice, GrokTTSCodec, } from './audio/tts-provider-options.js';
10
+ export { GrokTranscriptionAdapter, createGrokTranscription, grokTranscription, type GrokTranscriptionConfig, } from './adapters/transcription.js';
11
+ export type { GrokTranscriptionProviderOptions, GrokSTTAudioFormat, } from './audio/transcription-provider-options.js';
12
+ export type { GrokChatModelProviderOptionsByName, GrokChatModelToolCapabilitiesByName, GrokModelInputModalitiesByName, ResolveProviderOptions, ResolveInputModalities, GrokChatModel, GrokImageModel, GrokVideoModel, GrokTTSModel, GrokTranscriptionModel, GrokRealtimeModel, } from './model-meta.js';
13
+ export { GROK_CHAT_MODELS, GROK_IMAGE_MODELS, GROK_VIDEO_MODELS, GROK_TTS_MODELS, GROK_TRANSCRIPTION_MODELS, GROK_REALTIME_MODELS, } from './model-meta.js';
14
+ export type { GrokTextMetadata, GrokImageMetadata, GrokAudioMetadata, GrokVideoMetadata, GrokDocumentMetadata, GrokMessageMetadataByModality, } from './message-types.js';
15
+ export { grokRealtimeToken, grokRealtime } from './realtime/index.js';
16
+ export type { GrokRealtimeVoice, GrokRealtimeTokenOptions, GrokRealtimeOptions, GrokTurnDetection, GrokSemanticVADConfig, GrokServerVADConfig, } from './realtime/index.js';
@@ -0,0 +1,40 @@
1
+ import { GrokTextAdapter, createGrokText, grokText } from "./adapters/text.js";
2
+ import { createGrokSummarize, grokSummarize } from "./adapters/summarize.js";
3
+ import { GrokImageAdapter, createGrokImage, grokImage } from "./adapters/image.js";
4
+ import { GrokVideoAdapter, createGrokVideo, grokVideo } from "./adapters/video.js";
5
+ import { GROK_VIDEO_DURATIONS, getGrokVideoDurationOptions } from "./video/video-provider-options.js";
6
+ import { GrokSpeechAdapter, createGrokSpeech, grokSpeech } from "./adapters/tts.js";
7
+ import { GrokTranscriptionAdapter, createGrokTranscription, grokTranscription } from "./adapters/transcription.js";
8
+ import { GROK_CHAT_MODELS, GROK_IMAGE_MODELS, GROK_REALTIME_MODELS, GROK_TRANSCRIPTION_MODELS, GROK_TTS_MODELS, GROK_VIDEO_MODELS } from "./model-meta.js";
9
+ import { grokRealtimeToken } from "./realtime/token.js";
10
+ import { grokRealtime } from "./realtime/adapter.js";
11
+ export {
12
+ GROK_CHAT_MODELS,
13
+ GROK_IMAGE_MODELS,
14
+ GROK_REALTIME_MODELS,
15
+ GROK_TRANSCRIPTION_MODELS,
16
+ GROK_TTS_MODELS,
17
+ GROK_VIDEO_DURATIONS,
18
+ GROK_VIDEO_MODELS,
19
+ GrokImageAdapter,
20
+ GrokSpeechAdapter,
21
+ GrokTextAdapter,
22
+ GrokTranscriptionAdapter,
23
+ GrokVideoAdapter,
24
+ createGrokImage,
25
+ createGrokSpeech,
26
+ createGrokSummarize,
27
+ createGrokText,
28
+ createGrokTranscription,
29
+ createGrokVideo,
30
+ getGrokVideoDurationOptions,
31
+ grokImage,
32
+ grokRealtime,
33
+ grokRealtimeToken,
34
+ grokSpeech,
35
+ grokSummarize,
36
+ grokText,
37
+ grokTranscription,
38
+ grokVideo
39
+ };
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}