@tanstack/ai-grok 0.14.2 → 0.14.3
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/package.json +4 -4
- package/dist/esm/adapters/image.d.ts +0 -89
- package/dist/esm/adapters/image.js +0 -205
- package/dist/esm/adapters/image.js.map +0 -1
- package/dist/esm/adapters/summarize.d.ts +0 -51
- package/dist/esm/adapters/summarize.js +0 -20
- package/dist/esm/adapters/summarize.js.map +0 -1
- package/dist/esm/adapters/text.d.ts +0 -76
- package/dist/esm/adapters/text.js +0 -44
- package/dist/esm/adapters/text.js.map +0 -1
- package/dist/esm/adapters/transcription.d.ts +0 -84
- package/dist/esm/adapters/transcription.js +0 -122
- package/dist/esm/adapters/transcription.js.map +0 -1
- package/dist/esm/adapters/tts.d.ts +0 -70
- package/dist/esm/adapters/tts.js +0 -142
- package/dist/esm/adapters/tts.js.map +0 -1
- package/dist/esm/adapters/video.d.ts +0 -128
- package/dist/esm/adapters/video.js +0 -237
- package/dist/esm/adapters/video.js.map +0 -1
- package/dist/esm/audio/transcription-provider-options.d.ts +0 -41
- package/dist/esm/audio/tts-provider-options.d.ts +0 -42
- package/dist/esm/image/image-provider-options.d.ts +0 -133
- package/dist/esm/image/image-provider-options.js +0 -76
- package/dist/esm/image/image-provider-options.js.map +0 -1
- package/dist/esm/index.d.ts +0 -16
- package/dist/esm/index.js +0 -40
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/message-types.d.ts +0 -64
- package/dist/esm/model-meta.d.ts +0 -99
- package/dist/esm/model-meta.js +0 -58
- package/dist/esm/model-meta.js.map +0 -1
- package/dist/esm/realtime/adapter.d.ts +0 -21
- package/dist/esm/realtime/adapter.js +0 -823
- package/dist/esm/realtime/adapter.js.map +0 -1
- package/dist/esm/realtime/index.d.ts +0 -4
- package/dist/esm/realtime/token.d.ts +0 -22
- package/dist/esm/realtime/token.js +0 -75
- package/dist/esm/realtime/token.js.map +0 -1
- package/dist/esm/realtime/types.d.ts +0 -95
- package/dist/esm/text/text-provider-options.d.ts +0 -54
- package/dist/esm/tools/index.d.ts +0 -45
- package/dist/esm/tools/index.js +0 -113
- package/dist/esm/tools/index.js.map +0 -1
- package/dist/esm/utils/audio.d.ts +0 -23
- package/dist/esm/utils/audio.js +0 -172
- package/dist/esm/utils/audio.js.map +0 -1
- package/dist/esm/utils/client.d.ts +0 -14
- package/dist/esm/utils/client.js +0 -21
- package/dist/esm/utils/client.js.map +0 -1
- package/dist/esm/utils/index.d.ts +0 -4
- package/dist/esm/utils/schema-converter.d.ts +0 -2
- package/dist/esm/video/video-provider-options.d.ts +0 -135
- package/dist/esm/video/video-provider-options.js +0 -67
- package/dist/esm/video/video-provider-options.js.map +0 -1
package/dist/esm/utils/audio.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
function toAudioFile(audio, audioFormat) {
|
|
2
|
-
if (typeof File !== "undefined" && audio instanceof File) {
|
|
3
|
-
if (audioFormat) {
|
|
4
|
-
const mimeType = toMimeType(audioFormat);
|
|
5
|
-
return new File([audio], `audio.${extensionFor(mimeType)}`, {
|
|
6
|
-
type: mimeType
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
if (audio.type) {
|
|
10
|
-
return audio;
|
|
11
|
-
}
|
|
12
|
-
throw new Error(
|
|
13
|
-
'toAudioFile cannot infer type for File input with empty .type — pass an explicit audioFormat (e.g. "mp3", "wav", "audio/mpeg")'
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
if (typeof Blob !== "undefined" && audio instanceof Blob) {
|
|
17
|
-
const mimeType = audioFormat ? toMimeType(audioFormat) : audio.type || void 0;
|
|
18
|
-
if (!mimeType) {
|
|
19
|
-
throw new Error(
|
|
20
|
-
'toAudioFile cannot infer type for Blob input with empty .type — pass an explicit audioFormat (e.g. "mp3", "wav", "audio/mpeg")'
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
return new File([audio], `audio.${extensionFor(mimeType)}`, {
|
|
24
|
-
type: mimeType
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
if (audio instanceof ArrayBuffer) {
|
|
28
|
-
if (!audioFormat) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
'toAudioFile cannot infer type for ArrayBuffer input — pass an explicit audioFormat (e.g. "mp3", "wav", "audio/mpeg")'
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
const mimeType = toMimeType(audioFormat);
|
|
34
|
-
return new File([audio], `audio.${extensionFor(mimeType)}`, {
|
|
35
|
-
type: mimeType
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
if (typeof audio === "string") {
|
|
39
|
-
if (audio.startsWith("data:")) {
|
|
40
|
-
const [header, base64Data] = audio.split(",");
|
|
41
|
-
const headerMatch = header?.match(/data:([^;]+)/);
|
|
42
|
-
const uriMimeType = headerMatch?.[1];
|
|
43
|
-
if (!uriMimeType) {
|
|
44
|
-
throw new Error(
|
|
45
|
-
"Malformed data: URI in toAudioFile: cannot parse MIME type — expected data:<mime>[;charset=…][;base64],<payload>"
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
if (base64Data === void 0 || base64Data.trim() === "") {
|
|
49
|
-
throw new Error(
|
|
50
|
-
"Malformed data: URI in toAudioFile: missing base64 payload after comma"
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
const mimeType2 = audioFormat ? toMimeType(audioFormat) : uriMimeType;
|
|
54
|
-
const buffer2 = base64ToArrayBuffer(base64Data);
|
|
55
|
-
return new File([buffer2], `audio.${extensionFor(mimeType2)}`, {
|
|
56
|
-
type: mimeType2
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
if (!audioFormat) {
|
|
60
|
-
throw new Error(
|
|
61
|
-
"toAudioFile requires a data: URI (e.g. data:audio/wav;base64,...) or an explicit audioFormat argument — bare base64 strings have no MIME type to infer"
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
const buffer = base64ToArrayBuffer(audio);
|
|
65
|
-
const mimeType = toMimeType(audioFormat);
|
|
66
|
-
return new File([buffer], `audio.${extensionFor(mimeType)}`, {
|
|
67
|
-
type: mimeType
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
throw new Error("Invalid audio input type");
|
|
71
|
-
}
|
|
72
|
-
function toMimeType(audioFormat) {
|
|
73
|
-
if (audioFormat.includes("/")) return audioFormat;
|
|
74
|
-
const ext = audioFormat.toLowerCase();
|
|
75
|
-
switch (ext) {
|
|
76
|
-
case "mp3":
|
|
77
|
-
return "audio/mpeg";
|
|
78
|
-
case "wav":
|
|
79
|
-
return "audio/wav";
|
|
80
|
-
case "ogg":
|
|
81
|
-
return "audio/ogg";
|
|
82
|
-
case "opus":
|
|
83
|
-
return "audio/opus";
|
|
84
|
-
case "flac":
|
|
85
|
-
return "audio/flac";
|
|
86
|
-
case "aac":
|
|
87
|
-
return "audio/aac";
|
|
88
|
-
case "mp4":
|
|
89
|
-
return "audio/mp4";
|
|
90
|
-
case "m4a":
|
|
91
|
-
return "audio/mp4";
|
|
92
|
-
case "webm":
|
|
93
|
-
return "audio/webm";
|
|
94
|
-
case "pcm":
|
|
95
|
-
return "audio/L16";
|
|
96
|
-
case "mulaw":
|
|
97
|
-
return "audio/basic";
|
|
98
|
-
case "alaw":
|
|
99
|
-
return "audio/x-alaw-basic";
|
|
100
|
-
default:
|
|
101
|
-
return `audio/${ext}`;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function extensionFor(mimeType) {
|
|
105
|
-
switch (mimeType) {
|
|
106
|
-
case "audio/mpeg":
|
|
107
|
-
return "mp3";
|
|
108
|
-
case "audio/wav":
|
|
109
|
-
case "audio/x-wav":
|
|
110
|
-
return "wav";
|
|
111
|
-
case "audio/ogg":
|
|
112
|
-
return "ogg";
|
|
113
|
-
case "audio/opus":
|
|
114
|
-
return "opus";
|
|
115
|
-
case "audio/flac":
|
|
116
|
-
return "flac";
|
|
117
|
-
case "audio/aac":
|
|
118
|
-
return "aac";
|
|
119
|
-
case "audio/mp4":
|
|
120
|
-
return "m4a";
|
|
121
|
-
case "audio/webm":
|
|
122
|
-
return "webm";
|
|
123
|
-
case "audio/L16":
|
|
124
|
-
return "pcm";
|
|
125
|
-
case "audio/basic":
|
|
126
|
-
return "mulaw";
|
|
127
|
-
case "audio/x-alaw-basic":
|
|
128
|
-
return "alaw";
|
|
129
|
-
default: {
|
|
130
|
-
const slash = mimeType.indexOf("/");
|
|
131
|
-
if (slash === -1) return "bin";
|
|
132
|
-
return mimeType.slice(slash + 1) || "bin";
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
function arrayBufferToBase64(buffer) {
|
|
137
|
-
if (typeof Buffer !== "undefined") {
|
|
138
|
-
return Buffer.from(buffer).toString("base64");
|
|
139
|
-
}
|
|
140
|
-
const bytes = new Uint8Array(buffer);
|
|
141
|
-
const chunkSize = 32768;
|
|
142
|
-
let binary = "";
|
|
143
|
-
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
144
|
-
const end = Math.min(i + chunkSize, bytes.length);
|
|
145
|
-
binary += String.fromCharCode.apply(
|
|
146
|
-
null,
|
|
147
|
-
// eslint-disable-next-line no-restricted-syntax -- TS lib types String.fromCharCode.apply as Array<number> but runtime accepts any ArrayLike
|
|
148
|
-
bytes.subarray(i, end)
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
return btoa(binary);
|
|
152
|
-
}
|
|
153
|
-
function base64ToArrayBuffer(base64) {
|
|
154
|
-
let binary;
|
|
155
|
-
try {
|
|
156
|
-
binary = atob(base64);
|
|
157
|
-
} catch (err) {
|
|
158
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
159
|
-
throw new Error(`Invalid base64 input to toAudioFile: ${msg}`);
|
|
160
|
-
}
|
|
161
|
-
const buffer = new ArrayBuffer(binary.length);
|
|
162
|
-
const bytes = new Uint8Array(buffer);
|
|
163
|
-
for (let i = 0; i < binary.length; i++) {
|
|
164
|
-
bytes[i] = binary.charCodeAt(i);
|
|
165
|
-
}
|
|
166
|
-
return buffer;
|
|
167
|
-
}
|
|
168
|
-
export {
|
|
169
|
-
arrayBufferToBase64,
|
|
170
|
-
toAudioFile
|
|
171
|
-
};
|
|
172
|
-
//# sourceMappingURL=audio.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audio.js","sources":["../../../src/utils/audio.ts"],"sourcesContent":["/**\n * Coerce the various audio input shapes accepted by `TranscriptionOptions.audio`\n * into a `File` suitable for `multipart/form-data` uploads.\n *\n * For base64 string inputs we require an explicit MIME type — either via a\n * `data:<mime>;base64,<payload>` URI prefix, or via the caller-provided\n * `audioFormat` parameter. Bare base64 without either is rejected, because\n * silently defaulting to `audio/mpeg` misreports non-mp3 audio to the server.\n *\n * The same rule applies to raw `ArrayBuffer` inputs: the caller must supply\n * an `audioFormat` so we know what MIME type and extension to use.\n */\nexport function toAudioFile(\n audio: string | File | Blob | ArrayBuffer,\n audioFormat?: string,\n): File {\n if (typeof File !== 'undefined' && audio instanceof File) {\n // Prefer the caller-supplied `audioFormat` over a potentially empty or\n // incorrect `File.type` — callers pass `audioFormat` precisely because\n // they have more context than the browser does about the payload. If\n // neither is set, fall through to the Blob-style error path below.\n if (audioFormat) {\n const mimeType = toMimeType(audioFormat)\n return new File([audio], `audio.${extensionFor(mimeType)}`, {\n type: mimeType,\n })\n }\n if (audio.type) {\n return audio\n }\n throw new Error(\n 'toAudioFile cannot infer type for File input with empty .type — pass an explicit audioFormat (e.g. \"mp3\", \"wav\", \"audio/mpeg\")',\n )\n }\n\n if (typeof Blob !== 'undefined' && audio instanceof Blob) {\n // Mirror the ArrayBuffer / bare-base64 paths: prefer the explicit\n // audioFormat argument over the Blob's (often empty) .type. We refuse to\n // fall back to `application/octet-stream` because that mislabels audio\n // for the server.\n const mimeType = audioFormat\n ? toMimeType(audioFormat)\n : audio.type || undefined\n if (!mimeType) {\n throw new Error(\n 'toAudioFile cannot infer type for Blob input with empty .type — pass an explicit audioFormat (e.g. \"mp3\", \"wav\", \"audio/mpeg\")',\n )\n }\n return new File([audio], `audio.${extensionFor(mimeType)}`, {\n type: mimeType,\n })\n }\n\n if (audio instanceof ArrayBuffer) {\n if (!audioFormat) {\n throw new Error(\n 'toAudioFile cannot infer type for ArrayBuffer input — pass an explicit audioFormat (e.g. \"mp3\", \"wav\", \"audio/mpeg\")',\n )\n }\n const mimeType = toMimeType(audioFormat)\n return new File([audio], `audio.${extensionFor(mimeType)}`, {\n type: mimeType,\n })\n }\n\n if (typeof audio === 'string') {\n if (audio.startsWith('data:')) {\n const [header, base64Data] = audio.split(',')\n // Fail loudly on malformed data: URIs instead of silently defaulting\n // to `audio/mpeg` — the file's contract is that we never mislabel\n // audio for the server.\n const headerMatch = header?.match(/data:([^;]+)/)\n const uriMimeType = headerMatch?.[1]\n if (!uriMimeType) {\n throw new Error(\n 'Malformed data: URI in toAudioFile: cannot parse MIME type — expected data:<mime>[;charset=…][;base64],<payload>',\n )\n }\n if (base64Data === undefined || base64Data.trim() === '') {\n throw new Error(\n 'Malformed data: URI in toAudioFile: missing base64 payload after comma',\n )\n }\n // Caller-supplied `audioFormat` wins over the URI-embedded MIME: the\n // caller has more context (the URI MIME may be wrong, or a generic\n // `application/octet-stream`).\n const mimeType = audioFormat ? toMimeType(audioFormat) : uriMimeType\n const buffer = base64ToArrayBuffer(base64Data)\n return new File([buffer], `audio.${extensionFor(mimeType)}`, {\n type: mimeType,\n })\n }\n\n if (!audioFormat) {\n throw new Error(\n 'toAudioFile requires a data: URI (e.g. data:audio/wav;base64,...) or an explicit audioFormat argument — bare base64 strings have no MIME type to infer',\n )\n }\n\n const buffer = base64ToArrayBuffer(audio)\n const mimeType = toMimeType(audioFormat)\n return new File([buffer], `audio.${extensionFor(mimeType)}`, {\n type: mimeType,\n })\n }\n\n throw new Error('Invalid audio input type')\n}\n\nfunction toMimeType(audioFormat: string): string {\n // Accept either \"audio/…\" strings or bare extensions like \"mp3\".\n if (audioFormat.includes('/')) return audioFormat\n const ext = audioFormat.toLowerCase()\n switch (ext) {\n case 'mp3':\n return 'audio/mpeg'\n case 'wav':\n return 'audio/wav'\n case 'ogg':\n return 'audio/ogg'\n case 'opus':\n return 'audio/opus'\n case 'flac':\n return 'audio/flac'\n case 'aac':\n return 'audio/aac'\n case 'mp4':\n return 'audio/mp4'\n case 'm4a':\n return 'audio/mp4'\n case 'webm':\n return 'audio/webm'\n case 'pcm':\n return 'audio/L16'\n case 'mulaw':\n return 'audio/basic'\n case 'alaw':\n return 'audio/x-alaw-basic'\n default:\n return `audio/${ext}`\n }\n}\n\nfunction extensionFor(mimeType: string): string {\n switch (mimeType) {\n case 'audio/mpeg':\n return 'mp3'\n case 'audio/wav':\n case 'audio/x-wav':\n return 'wav'\n case 'audio/ogg':\n return 'ogg'\n case 'audio/opus':\n return 'opus'\n case 'audio/flac':\n return 'flac'\n case 'audio/aac':\n return 'aac'\n case 'audio/mp4':\n return 'm4a'\n case 'audio/webm':\n return 'webm'\n case 'audio/L16':\n return 'pcm'\n case 'audio/basic':\n return 'mulaw'\n case 'audio/x-alaw-basic':\n return 'alaw'\n default: {\n const slash = mimeType.indexOf('/')\n if (slash === -1) return 'bin'\n return mimeType.slice(slash + 1) || 'bin'\n }\n }\n}\n\n/**\n * Cross-runtime ArrayBuffer → base64 conversion.\n *\n * Uses Node's `Buffer` when available (fastest path on server) and falls\n * back to `btoa` + chunked `String.fromCharCode` everywhere else (browser,\n * Cloudflare Workers, Bun, Deno). Chunking is required because a very\n * large audio buffer spread into `String.fromCharCode(...bytes)` in one\n * call can hit `Maximum call stack size exceeded`.\n */\nexport function arrayBufferToBase64(buffer: ArrayBuffer): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(buffer).toString('base64')\n }\n const bytes = new Uint8Array(buffer)\n const chunkSize = 0x8000\n let binary = ''\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const end = Math.min(i + chunkSize, bytes.length)\n binary += String.fromCharCode.apply(\n null,\n // eslint-disable-next-line no-restricted-syntax -- TS lib types String.fromCharCode.apply as Array<number> but runtime accepts any ArrayLike\n bytes.subarray(i, end) as unknown as Array<number>,\n )\n }\n return btoa(binary)\n}\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n let binary: string\n try {\n binary = atob(base64)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(`Invalid base64 input to toAudioFile: ${msg}`)\n }\n const buffer = new ArrayBuffer(binary.length)\n const bytes = new Uint8Array(buffer)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return buffer\n}\n"],"names":["mimeType","buffer"],"mappings":"AAYO,SAAS,YACd,OACA,aACM;AACN,MAAI,OAAO,SAAS,eAAe,iBAAiB,MAAM;AAKxD,QAAI,aAAa;AACf,YAAM,WAAW,WAAW,WAAW;AACvC,aAAO,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,aAAa,QAAQ,CAAC,IAAI;AAAA,QAC1D,MAAM;AAAA,MAAA,CACP;AAAA,IACH;AACA,QAAI,MAAM,MAAM;AACd,aAAO;AAAA,IACT;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AAEA,MAAI,OAAO,SAAS,eAAe,iBAAiB,MAAM;AAKxD,UAAM,WAAW,cACb,WAAW,WAAW,IACtB,MAAM,QAAQ;AAClB,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,WAAO,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,aAAa,QAAQ,CAAC,IAAI;AAAA,MAC1D,MAAM;AAAA,IAAA,CACP;AAAA,EACH;AAEA,MAAI,iBAAiB,aAAa;AAChC,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,WAAW,WAAW,WAAW;AACvC,WAAO,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,aAAa,QAAQ,CAAC,IAAI;AAAA,MAC1D,MAAM;AAAA,IAAA,CACP;AAAA,EACH;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,MAAM,WAAW,OAAO,GAAG;AAC7B,YAAM,CAAC,QAAQ,UAAU,IAAI,MAAM,MAAM,GAAG;AAI5C,YAAM,cAAc,QAAQ,MAAM,cAAc;AAChD,YAAM,cAAc,cAAc,CAAC;AACnC,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAEJ;AACA,UAAI,eAAe,UAAa,WAAW,KAAA,MAAW,IAAI;AACxD,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAEJ;AAIA,YAAMA,YAAW,cAAc,WAAW,WAAW,IAAI;AACzD,YAAMC,UAAS,oBAAoB,UAAU;AAC7C,aAAO,IAAI,KAAK,CAACA,OAAM,GAAG,SAAS,aAAaD,SAAQ,CAAC,IAAI;AAAA,QAC3D,MAAMA;AAAAA,MAAA,CACP;AAAA,IACH;AAEA,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,SAAS,oBAAoB,KAAK;AACxC,UAAM,WAAW,WAAW,WAAW;AACvC,WAAO,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,aAAa,QAAQ,CAAC,IAAI;AAAA,MAC3D,MAAM;AAAA,IAAA,CACP;AAAA,EACH;AAEA,QAAM,IAAI,MAAM,0BAA0B;AAC5C;AAEA,SAAS,WAAW,aAA6B;AAE/C,MAAI,YAAY,SAAS,GAAG,EAAG,QAAO;AACtC,QAAM,MAAM,YAAY,YAAA;AACxB,UAAQ,KAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,SAAS,GAAG;AAAA,EAAA;AAEzB;AAEA,SAAS,aAAa,UAA0B;AAC9C,UAAQ,UAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,SAAS;AACP,YAAM,QAAQ,SAAS,QAAQ,GAAG;AAClC,UAAI,UAAU,GAAI,QAAO;AACzB,aAAO,SAAS,MAAM,QAAQ,CAAC,KAAK;AAAA,IACtC;AAAA,EAAA;AAEJ;AAWO,SAAS,oBAAoB,QAA6B;AAC/D,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,MAAM,EAAE,SAAS,QAAQ;AAAA,EAC9C;AACA,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,QAAM,YAAY;AAClB,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AAChD,UAAM,MAAM,KAAK,IAAI,IAAI,WAAW,MAAM,MAAM;AAChD,cAAU,OAAO,aAAa;AAAA,MAC5B;AAAA;AAAA,MAEA,MAAM,SAAS,GAAG,GAAG;AAAA,IAAA;AAAA,EAEzB;AACA,SAAO,KAAK,MAAM;AACpB;AAEA,SAAS,oBAAoB,QAA6B;AACxD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM;AAAA,EACtB,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAM,IAAI,MAAM,wCAAwC,GAAG,EAAE;AAAA,EAC/D;AACA,QAAM,SAAS,IAAI,YAAY,OAAO,MAAM;AAC5C,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ClientOptions } from 'openai';
|
|
2
|
-
export interface GrokClientConfig extends Omit<ClientOptions, 'apiKey'> {
|
|
3
|
-
apiKey: string;
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* Gets Grok API key from environment variables
|
|
7
|
-
* @throws Error if XAI_API_KEY is not found
|
|
8
|
-
*/
|
|
9
|
-
export declare function getGrokApiKeyFromEnv(): string;
|
|
10
|
-
/**
|
|
11
|
-
* Returns a Grok client config with the default xAI base URL applied
|
|
12
|
-
* when not already set.
|
|
13
|
-
*/
|
|
14
|
-
export declare function withGrokDefaults(config: GrokClientConfig): GrokClientConfig;
|
package/dist/esm/utils/client.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { getApiKeyFromEnv } from "@tanstack/ai-utils";
|
|
2
|
-
function getGrokApiKeyFromEnv() {
|
|
3
|
-
try {
|
|
4
|
-
return getApiKeyFromEnv("XAI_API_KEY");
|
|
5
|
-
} catch {
|
|
6
|
-
throw new Error(
|
|
7
|
-
"XAI_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key."
|
|
8
|
-
);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
function withGrokDefaults(config) {
|
|
12
|
-
return {
|
|
13
|
-
...config,
|
|
14
|
-
baseURL: config.baseURL || "https://api.x.ai/v1"
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export {
|
|
18
|
-
getGrokApiKeyFromEnv,
|
|
19
|
-
withGrokDefaults
|
|
20
|
-
};
|
|
21
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../../src/utils/client.ts"],"sourcesContent":["import { getApiKeyFromEnv } from '@tanstack/ai-utils'\nimport type { ClientOptions } from 'openai'\n\nexport interface GrokClientConfig extends Omit<ClientOptions, 'apiKey'> {\n apiKey: string\n}\n\n/**\n * Gets Grok API key from environment variables\n * @throws Error if XAI_API_KEY is not found\n */\nexport function getGrokApiKeyFromEnv(): string {\n try {\n return getApiKeyFromEnv('XAI_API_KEY')\n } catch {\n throw new Error(\n 'XAI_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key.',\n )\n }\n}\n\n/**\n * Returns a Grok client config with the default xAI base URL applied\n * when not already set.\n */\nexport function withGrokDefaults(config: GrokClientConfig): GrokClientConfig {\n return {\n ...config,\n baseURL: config.baseURL || 'https://api.x.ai/v1',\n }\n}\n"],"names":[],"mappings":";AAWO,SAAS,uBAA+B;AAC7C,MAAI;AACF,WAAO,iBAAiB,aAAa;AAAA,EACvC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AAMO,SAAS,iBAAiB,QAA4C;AAC3E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,OAAO,WAAW;AAAA,EAAA;AAE/B;"}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { generateId } from '@tanstack/ai-utils';
|
|
2
|
-
export { getGrokApiKeyFromEnv, withGrokDefaults, type GrokClientConfig, } from './client.js';
|
|
3
|
-
export { makeGrokStructuredOutputCompatible, transformNullsToUndefined, } from './schema-converter.js';
|
|
4
|
-
export { toAudioFile, arrayBufferToBase64 } from './audio.js';
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { DurationOptions } from '@tanstack/ai/adapters';
|
|
2
|
-
import { GrokVideoModel } from '../model-meta.js';
|
|
3
|
-
/**
|
|
4
|
-
* Aspect ratios accepted by the grok-imagine video models.
|
|
5
|
-
*
|
|
6
|
-
* Note: this is a narrower set than the grok-imagine image models — the
|
|
7
|
-
* video endpoint rejects the phone-screen ratios ('9:19.5', '9:20', …) and
|
|
8
|
-
* 'auto'.
|
|
9
|
-
*
|
|
10
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
11
|
-
*/
|
|
12
|
-
export type GrokVideoAspectRatio = '1:1' | '16:9' | '9:16' | '4:3' | '3:4' | '3:2' | '2:3';
|
|
13
|
-
/**
|
|
14
|
-
* Resolution tiers for the grok-imagine video models.
|
|
15
|
-
*
|
|
16
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
17
|
-
*/
|
|
18
|
-
export type GrokVideoResolution = '480p' | '720p' | '1080p';
|
|
19
|
-
/**
|
|
20
|
-
* Size strings for grok-imagine video models. The Imagine API is
|
|
21
|
-
* aspect-ratio based rather than pixel-size based; like the grok-imagine
|
|
22
|
-
* image models, the generic `size` option uses an
|
|
23
|
-
* `aspectRatio_resolution` template ("16:9_720p") — the resolution suffix
|
|
24
|
-
* is optional ("16:9" uses the API default).
|
|
25
|
-
*
|
|
26
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
27
|
-
*/
|
|
28
|
-
export type GrokVideoSize = GrokVideoAspectRatio | `${GrokVideoAspectRatio}_${GrokVideoResolution}`;
|
|
29
|
-
/**
|
|
30
|
-
* Video duration limits enforced by the Imagine API (seconds).
|
|
31
|
-
*/
|
|
32
|
-
export declare const GROK_VIDEO_MIN_DURATION = 1;
|
|
33
|
-
export declare const GROK_VIDEO_MAX_DURATION = 15;
|
|
34
|
-
/**
|
|
35
|
-
* Parses a grok video size string into its components.
|
|
36
|
-
* Format: "aspectRatio" or "aspectRatio_resolution",
|
|
37
|
-
* e.g. "16:9_720p" → { aspectRatio: "16:9", resolution: "720p" }.
|
|
38
|
-
* Returns undefined when the string doesn't match the template.
|
|
39
|
-
*/
|
|
40
|
-
export declare function parseGrokVideoSize(size: string): {
|
|
41
|
-
aspectRatio: string;
|
|
42
|
-
resolution?: string;
|
|
43
|
-
} | undefined;
|
|
44
|
-
/**
|
|
45
|
-
* Validate the `size` template for a given grok video model.
|
|
46
|
-
*
|
|
47
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
48
|
-
*/
|
|
49
|
-
export declare function validateVideoSize(model: string, size?: string): asserts size is GrokVideoSize | undefined;
|
|
50
|
-
/**
|
|
51
|
-
* Per-model duration type. The Imagine API accepts any integer second in the
|
|
52
|
-
* 1–15 range, so this is a continuous range expressed as `number` (a literal
|
|
53
|
-
* union can't represent it). `snapDuration()` coerces a raw seconds value into
|
|
54
|
-
* the valid range at runtime.
|
|
55
|
-
*
|
|
56
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
57
|
-
*/
|
|
58
|
-
export type GrokVideoModelDurationByName = {
|
|
59
|
-
'grok-imagine-video': number;
|
|
60
|
-
'grok-imagine-video-1.5': number;
|
|
61
|
-
};
|
|
62
|
-
/**
|
|
63
|
-
* Runtime duration table backing `availableDurations()` / `snapDuration()`.
|
|
64
|
-
* Both grok-imagine video models accept the same continuous 1–15 integer-second
|
|
65
|
-
* range.
|
|
66
|
-
*
|
|
67
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
68
|
-
*/
|
|
69
|
-
export declare const GROK_VIDEO_DURATIONS: {
|
|
70
|
-
readonly [TModel in GrokVideoModel]: DurationOptions<GrokVideoModelDurationByName[TModel]>;
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Look up the duration options for a grok video model.
|
|
74
|
-
*
|
|
75
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
76
|
-
*/
|
|
77
|
-
export declare function getGrokVideoDurationOptions<TModel extends GrokVideoModel>(model: TModel): DurationOptions<GrokVideoModelDurationByName[TModel]>;
|
|
78
|
-
/**
|
|
79
|
-
* Provider-specific options for grok video generation. These map directly
|
|
80
|
-
* onto the Imagine API request body and take precedence over the generic
|
|
81
|
-
* `size` / `duration` options when both are provided.
|
|
82
|
-
*
|
|
83
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
84
|
-
*/
|
|
85
|
-
export interface GrokVideoProviderOptions {
|
|
86
|
-
/**
|
|
87
|
-
* Output aspect ratio.
|
|
88
|
-
*/
|
|
89
|
-
aspect_ratio?: GrokVideoAspectRatio;
|
|
90
|
-
/**
|
|
91
|
-
* Output resolution tier.
|
|
92
|
-
*/
|
|
93
|
-
resolution?: GrokVideoResolution;
|
|
94
|
-
/**
|
|
95
|
-
* Video duration in integer seconds (1–15).
|
|
96
|
-
*/
|
|
97
|
-
duration?: number;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Type-only map from model name to its specific provider options.
|
|
101
|
-
*
|
|
102
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
103
|
-
*/
|
|
104
|
-
export type GrokVideoModelProviderOptionsByName = {
|
|
105
|
-
'grok-imagine-video': GrokVideoProviderOptions;
|
|
106
|
-
'grok-imagine-video-1.5': GrokVideoProviderOptions;
|
|
107
|
-
};
|
|
108
|
-
/**
|
|
109
|
-
* Type-only map from model name to its supported `size` strings.
|
|
110
|
-
*
|
|
111
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
112
|
-
*/
|
|
113
|
-
export type GrokVideoModelSizeByName = {
|
|
114
|
-
'grok-imagine-video': GrokVideoSize;
|
|
115
|
-
'grok-imagine-video-1.5': GrokVideoSize;
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* Type-only map from model name to the non-text prompt modalities it accepts.
|
|
119
|
-
* Both models accept an `image` prompt part as the starting frame:
|
|
120
|
-
* `grok-imagine-video` (v1.0) does text-to-video and image-to-video, while
|
|
121
|
-
* `grok-imagine-video-1.5` is image-to-video only (the image is required).
|
|
122
|
-
*
|
|
123
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
124
|
-
*/
|
|
125
|
-
export type GrokVideoModelInputModalitiesByName = {
|
|
126
|
-
'grok-imagine-video': readonly ['image'];
|
|
127
|
-
'grok-imagine-video-1.5': readonly ['image'];
|
|
128
|
-
};
|
|
129
|
-
/**
|
|
130
|
-
* True when the model only supports image-to-video (a starting frame is
|
|
131
|
-
* required).
|
|
132
|
-
*
|
|
133
|
-
* @experimental Video generation is an experimental feature and may change.
|
|
134
|
-
*/
|
|
135
|
-
export declare function isImageToVideoOnlyModel(model: string): boolean;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
const GROK_VIDEO_ASPECT_RATIOS = [
|
|
2
|
-
"1:1",
|
|
3
|
-
"16:9",
|
|
4
|
-
"9:16",
|
|
5
|
-
"4:3",
|
|
6
|
-
"3:4",
|
|
7
|
-
"3:2",
|
|
8
|
-
"2:3"
|
|
9
|
-
];
|
|
10
|
-
const GROK_VIDEO_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
11
|
-
const GROK_VIDEO_MIN_DURATION = 1;
|
|
12
|
-
const GROK_VIDEO_MAX_DURATION = 15;
|
|
13
|
-
function parseGrokVideoSize(size) {
|
|
14
|
-
const match = size.match(/^([\d.]+:[\d.]+)(?:_(.+))?$/);
|
|
15
|
-
const [, aspectRatio, resolution] = match ?? [];
|
|
16
|
-
if (aspectRatio === void 0) return void 0;
|
|
17
|
-
return { aspectRatio, ...resolution !== void 0 && { resolution } };
|
|
18
|
-
}
|
|
19
|
-
function validateVideoSize(model, size) {
|
|
20
|
-
if (size === void 0) return;
|
|
21
|
-
const parsed = parseGrokVideoSize(size);
|
|
22
|
-
if (!parsed || !GROK_VIDEO_ASPECT_RATIOS.includes(parsed.aspectRatio)) {
|
|
23
|
-
throw new Error(
|
|
24
|
-
`Size "${size}" is not supported by model "${model}". Expected "aspectRatio" or "aspectRatio_resolution" (e.g. "16:9_720p") with aspect ratio one of: ${GROK_VIDEO_ASPECT_RATIOS.join(", ")}`
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
if (parsed.resolution !== void 0 && !GROK_VIDEO_RESOLUTIONS.includes(parsed.resolution)) {
|
|
28
|
-
throw new Error(
|
|
29
|
-
`Resolution "${parsed.resolution}" is not supported by model "${model}". Supported resolutions: ${GROK_VIDEO_RESOLUTIONS.join(", ")}`
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const GROK_VIDEO_DURATIONS = {
|
|
34
|
-
"grok-imagine-video": {
|
|
35
|
-
kind: "range",
|
|
36
|
-
min: GROK_VIDEO_MIN_DURATION,
|
|
37
|
-
max: GROK_VIDEO_MAX_DURATION,
|
|
38
|
-
step: 1,
|
|
39
|
-
unit: "seconds"
|
|
40
|
-
},
|
|
41
|
-
"grok-imagine-video-1.5": {
|
|
42
|
-
kind: "range",
|
|
43
|
-
min: GROK_VIDEO_MIN_DURATION,
|
|
44
|
-
max: GROK_VIDEO_MAX_DURATION,
|
|
45
|
-
step: 1,
|
|
46
|
-
unit: "seconds"
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
function getGrokVideoDurationOptions(model) {
|
|
50
|
-
return GROK_VIDEO_DURATIONS[model];
|
|
51
|
-
}
|
|
52
|
-
const GROK_VIDEO_IMAGE_TO_VIDEO_ONLY = /* @__PURE__ */ new Set([
|
|
53
|
-
"grok-imagine-video-1.5"
|
|
54
|
-
]);
|
|
55
|
-
function isImageToVideoOnlyModel(model) {
|
|
56
|
-
return GROK_VIDEO_IMAGE_TO_VIDEO_ONLY.has(model);
|
|
57
|
-
}
|
|
58
|
-
export {
|
|
59
|
-
GROK_VIDEO_DURATIONS,
|
|
60
|
-
GROK_VIDEO_MAX_DURATION,
|
|
61
|
-
GROK_VIDEO_MIN_DURATION,
|
|
62
|
-
getGrokVideoDurationOptions,
|
|
63
|
-
isImageToVideoOnlyModel,
|
|
64
|
-
parseGrokVideoSize,
|
|
65
|
-
validateVideoSize
|
|
66
|
-
};
|
|
67
|
-
//# sourceMappingURL=video-provider-options.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"video-provider-options.js","sources":["../../../src/video/video-provider-options.ts"],"sourcesContent":["/**\n * Grok Video Generation Provider Options (xAI Imagine API)\n *\n * Based on https://docs.x.ai/docs/guides/video-generations\n *\n * @experimental Video generation is an experimental feature and may change.\n */\n\nimport type { DurationOptions } from '@tanstack/ai/adapters'\nimport type { GrokVideoModel } from '../model-meta'\n\n/**\n * Aspect ratios accepted by the grok-imagine video models.\n *\n * Note: this is a narrower set than the grok-imagine image models — the\n * video endpoint rejects the phone-screen ratios ('9:19.5', '9:20', …) and\n * 'auto'.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoAspectRatio =\n | '1:1'\n | '16:9'\n | '9:16'\n | '4:3'\n | '3:4'\n | '3:2'\n | '2:3'\n\n/**\n * Resolution tiers for the grok-imagine video models.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoResolution = '480p' | '720p' | '1080p'\n\n/**\n * Size strings for grok-imagine video models. The Imagine API is\n * aspect-ratio based rather than pixel-size based; like the grok-imagine\n * image models, the generic `size` option uses an\n * `aspectRatio_resolution` template (\"16:9_720p\") — the resolution suffix\n * is optional (\"16:9\" uses the API default).\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoSize =\n | GrokVideoAspectRatio\n | `${GrokVideoAspectRatio}_${GrokVideoResolution}`\n\nconst GROK_VIDEO_ASPECT_RATIOS: ReadonlyArray<string> = [\n '1:1',\n '16:9',\n '9:16',\n '4:3',\n '3:4',\n '3:2',\n '2:3',\n]\n\nconst GROK_VIDEO_RESOLUTIONS: ReadonlyArray<string> = ['480p', '720p', '1080p']\n\n/**\n * Video duration limits enforced by the Imagine API (seconds).\n */\nexport const GROK_VIDEO_MIN_DURATION = 1\nexport const GROK_VIDEO_MAX_DURATION = 15\n\n/**\n * Parses a grok video size string into its components.\n * Format: \"aspectRatio\" or \"aspectRatio_resolution\",\n * e.g. \"16:9_720p\" → { aspectRatio: \"16:9\", resolution: \"720p\" }.\n * Returns undefined when the string doesn't match the template.\n */\nexport function parseGrokVideoSize(\n size: string,\n): { aspectRatio: string; resolution?: string } | undefined {\n const match = size.match(/^([\\d.]+:[\\d.]+)(?:_(.+))?$/)\n const [, aspectRatio, resolution] = match ?? []\n if (aspectRatio === undefined) return undefined\n return { aspectRatio, ...(resolution !== undefined && { resolution }) }\n}\n\n/**\n * Validate the `size` template for a given grok video model.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport function validateVideoSize(\n model: string,\n size?: string,\n): asserts size is GrokVideoSize | undefined {\n if (size === undefined) return\n const parsed = parseGrokVideoSize(size)\n if (!parsed || !GROK_VIDEO_ASPECT_RATIOS.includes(parsed.aspectRatio)) {\n throw new Error(\n `Size \"${size}\" is not supported by model \"${model}\". Expected ` +\n `\"aspectRatio\" or \"aspectRatio_resolution\" (e.g. \"16:9_720p\") with ` +\n `aspect ratio one of: ${GROK_VIDEO_ASPECT_RATIOS.join(', ')}`,\n )\n }\n if (\n parsed.resolution !== undefined &&\n !GROK_VIDEO_RESOLUTIONS.includes(parsed.resolution)\n ) {\n throw new Error(\n `Resolution \"${parsed.resolution}\" is not supported by model \"${model}\". ` +\n `Supported resolutions: ${GROK_VIDEO_RESOLUTIONS.join(', ')}`,\n )\n }\n}\n\n/**\n * Per-model duration type. The Imagine API accepts any integer second in the\n * 1–15 range, so this is a continuous range expressed as `number` (a literal\n * union can't represent it). `snapDuration()` coerces a raw seconds value into\n * the valid range at runtime.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoModelDurationByName = {\n 'grok-imagine-video': number\n 'grok-imagine-video-1.5': number\n}\n\n/**\n * Runtime duration table backing `availableDurations()` / `snapDuration()`.\n * Both grok-imagine video models accept the same continuous 1–15 integer-second\n * range.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport const GROK_VIDEO_DURATIONS: {\n readonly [TModel in GrokVideoModel]: DurationOptions<\n GrokVideoModelDurationByName[TModel]\n >\n} = {\n 'grok-imagine-video': {\n kind: 'range',\n min: GROK_VIDEO_MIN_DURATION,\n max: GROK_VIDEO_MAX_DURATION,\n step: 1,\n unit: 'seconds',\n },\n 'grok-imagine-video-1.5': {\n kind: 'range',\n min: GROK_VIDEO_MIN_DURATION,\n max: GROK_VIDEO_MAX_DURATION,\n step: 1,\n unit: 'seconds',\n },\n}\n\n/**\n * Look up the duration options for a grok video model.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport function getGrokVideoDurationOptions<TModel extends GrokVideoModel>(\n model: TModel,\n): DurationOptions<GrokVideoModelDurationByName[TModel]> {\n return GROK_VIDEO_DURATIONS[model]\n}\n\n/**\n * Provider-specific options for grok video generation. These map directly\n * onto the Imagine API request body and take precedence over the generic\n * `size` / `duration` options when both are provided.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport interface GrokVideoProviderOptions {\n /**\n * Output aspect ratio.\n */\n aspect_ratio?: GrokVideoAspectRatio\n\n /**\n * Output resolution tier.\n */\n resolution?: GrokVideoResolution\n\n /**\n * Video duration in integer seconds (1–15).\n */\n duration?: number\n}\n\n/**\n * Type-only map from model name to its specific provider options.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoModelProviderOptionsByName = {\n 'grok-imagine-video': GrokVideoProviderOptions\n 'grok-imagine-video-1.5': GrokVideoProviderOptions\n}\n\n/**\n * Type-only map from model name to its supported `size` strings.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoModelSizeByName = {\n 'grok-imagine-video': GrokVideoSize\n 'grok-imagine-video-1.5': GrokVideoSize\n}\n\n/**\n * Type-only map from model name to the non-text prompt modalities it accepts.\n * Both models accept an `image` prompt part as the starting frame:\n * `grok-imagine-video` (v1.0) does text-to-video and image-to-video, while\n * `grok-imagine-video-1.5` is image-to-video only (the image is required).\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport type GrokVideoModelInputModalitiesByName = {\n 'grok-imagine-video': readonly ['image']\n 'grok-imagine-video-1.5': readonly ['image']\n}\n\n/**\n * Models that only support image-to-video — a starting-frame image is\n * required and text-to-video is rejected by the Imagine API. Used by the\n * adapter to fail fast with a clear message instead of surfacing the raw\n * \"Text-to-video is not supported for this model\" 400.\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nconst GROK_VIDEO_IMAGE_TO_VIDEO_ONLY: ReadonlySet<string> = new Set([\n 'grok-imagine-video-1.5',\n])\n\n/**\n * True when the model only supports image-to-video (a starting frame is\n * required).\n *\n * @experimental Video generation is an experimental feature and may change.\n */\nexport function isImageToVideoOnlyModel(model: string): boolean {\n return GROK_VIDEO_IMAGE_TO_VIDEO_ONLY.has(model)\n}\n"],"names":[],"mappings":"AAiDA,MAAM,2BAAkD;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,yBAAgD,CAAC,QAAQ,QAAQ,OAAO;AAKvE,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAQhC,SAAS,mBACd,MAC0D;AAC1D,QAAM,QAAQ,KAAK,MAAM,6BAA6B;AACtD,QAAM,GAAG,aAAa,UAAU,IAAI,SAAS,CAAA;AAC7C,MAAI,gBAAgB,OAAW,QAAO;AACtC,SAAO,EAAE,aAAa,GAAI,eAAe,UAAa,EAAE,aAAW;AACrE;AAOO,SAAS,kBACd,OACA,MAC2C;AAC3C,MAAI,SAAS,OAAW;AACxB,QAAM,SAAS,mBAAmB,IAAI;AACtC,MAAI,CAAC,UAAU,CAAC,yBAAyB,SAAS,OAAO,WAAW,GAAG;AACrE,UAAM,IAAI;AAAA,MACR,SAAS,IAAI,gCAAgC,KAAK,sGAExB,yBAAyB,KAAK,IAAI,CAAC;AAAA,IAAA;AAAA,EAEjE;AACA,MACE,OAAO,eAAe,UACtB,CAAC,uBAAuB,SAAS,OAAO,UAAU,GAClD;AACA,UAAM,IAAI;AAAA,MACR,eAAe,OAAO,UAAU,gCAAgC,KAAK,6BACzC,uBAAuB,KAAK,IAAI,CAAC;AAAA,IAAA;AAAA,EAEjE;AACF;AAsBO,MAAM,uBAIT;AAAA,EACF,sBAAsB;AAAA,IACpB,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAAA,EAER,0BAA0B;AAAA,IACxB,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,EAAA;AAEV;AAOO,SAAS,4BACd,OACuD;AACvD,SAAO,qBAAqB,KAAK;AACnC;AAmEA,MAAM,qDAA0D,IAAI;AAAA,EAClE;AACF,CAAC;AAQM,SAAS,wBAAwB,OAAwB;AAC9D,SAAO,+BAA+B,IAAI,KAAK;AACjD;"}
|