@apicity/xai 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +862 -0
- package/dist/src/example.d.ts +8 -0
- package/dist/src/example.d.ts.map +1 -0
- package/dist/src/example.js +230 -0
- package/dist/src/example.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/middleware.d.ts +56 -0
- package/dist/src/middleware.d.ts.map +1 -0
- package/dist/src/middleware.js +226 -0
- package/dist/src/middleware.js.map +1 -0
- package/dist/src/types.d.ts +812 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +14 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/xai.d.ts +3 -0
- package/dist/src/xai.d.ts.map +1 -0
- package/dist/src/xai.js +759 -0
- package/dist/src/xai.js.map +1 -0
- package/dist/src/zod.d.ts +2458 -0
- package/dist/src/zod.d.ts.map +1 -0
- package/dist/src/zod.js +434 -0
- package/dist/src/zod.js.map +1 -0
- package/package.json +60 -0
package/dist/src/xai.js
ADDED
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
import { XaiError, } from "./types.js";
|
|
2
|
+
import { XaiChatRequestSchema, XaiImageGenerateRequestSchema, XaiImageEditRequestSchema, XaiVideoGenerateRequestSchema, XaiVideoEditRequestSchema, XaiVideoExtendRequestSchema, XaiBatchCreateRequestSchema, XaiCollectionCreateRequestSchema, XaiCollectionUpdateRequestSchema, XaiDocumentSearchRequestSchema, XaiResponseRequestSchema, XaiTokenizeTextRequestSchema, XaiRealtimeClientSecretRequestSchema, XaiTtsRequestSchema, XaiSttRequestSchema, XaiCustomVoiceCreateRequestSchema, } from "./zod.js";
|
|
3
|
+
import { attachExamples } from "./example.js";
|
|
4
|
+
// Helper function to safely handle AbortSignal across different environments
|
|
5
|
+
function attachAbortHandler(signal, controller) {
|
|
6
|
+
if (!signal)
|
|
7
|
+
return;
|
|
8
|
+
// Handle both standard AbortSignal and node-fetch's AbortSignal
|
|
9
|
+
if (typeof signal.addEventListener === "function") {
|
|
10
|
+
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
11
|
+
}
|
|
12
|
+
else if (signal.aborted) {
|
|
13
|
+
// Already aborted, abort our controller too
|
|
14
|
+
controller.abort();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function xai(opts) {
|
|
18
|
+
const baseURL = opts.baseURL ?? "https://api.x.ai/v1";
|
|
19
|
+
const managementBaseURL = opts.managementBaseURL ?? "https://management-api.x.ai/v1";
|
|
20
|
+
const managementApiKey = opts.managementApiKey ?? opts.apiKey;
|
|
21
|
+
const doFetch = opts.fetch ?? fetch;
|
|
22
|
+
const timeout = opts.timeout ?? 30000;
|
|
23
|
+
async function makeRequest(method, path, body, signal) {
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
26
|
+
if (signal) {
|
|
27
|
+
attachAbortHandler(signal, controller);
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const headers = {
|
|
31
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
32
|
+
};
|
|
33
|
+
const init = {
|
|
34
|
+
method,
|
|
35
|
+
headers,
|
|
36
|
+
signal: controller.signal,
|
|
37
|
+
};
|
|
38
|
+
if (body !== undefined) {
|
|
39
|
+
headers["Content-Type"] = "application/json";
|
|
40
|
+
init.body = JSON.stringify(body);
|
|
41
|
+
}
|
|
42
|
+
const res = await doFetch(`${baseURL}${path}`, init);
|
|
43
|
+
clearTimeout(timeoutId);
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
let message = `XAI API error: ${res.status}`;
|
|
46
|
+
let body = null;
|
|
47
|
+
try {
|
|
48
|
+
body = await res.json();
|
|
49
|
+
if (typeof body === "object" && body !== null && "error" in body) {
|
|
50
|
+
const err = body.error;
|
|
51
|
+
if (err?.message) {
|
|
52
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// ignore parse errors
|
|
58
|
+
}
|
|
59
|
+
throw new XaiError(message, res.status, body);
|
|
60
|
+
}
|
|
61
|
+
return (await res.json());
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
clearTimeout(timeoutId);
|
|
65
|
+
if (error instanceof XaiError)
|
|
66
|
+
throw error;
|
|
67
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function buildQuery(params) {
|
|
71
|
+
const parts = [];
|
|
72
|
+
for (const [key, value] of Object.entries(params)) {
|
|
73
|
+
if (value !== undefined && value !== null) {
|
|
74
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
78
|
+
}
|
|
79
|
+
async function makeManagementRequest(method, path, body, signal) {
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
82
|
+
if (signal) {
|
|
83
|
+
attachAbortHandler(signal, controller);
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const headers = {
|
|
87
|
+
Authorization: `Bearer ${managementApiKey}`,
|
|
88
|
+
};
|
|
89
|
+
const init = {
|
|
90
|
+
method,
|
|
91
|
+
headers,
|
|
92
|
+
signal: controller.signal,
|
|
93
|
+
};
|
|
94
|
+
if (body !== undefined) {
|
|
95
|
+
headers["Content-Type"] = "application/json";
|
|
96
|
+
init.body = JSON.stringify(body);
|
|
97
|
+
}
|
|
98
|
+
const res = await doFetch(`${managementBaseURL}${path}`, init);
|
|
99
|
+
clearTimeout(timeoutId);
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
let message = `XAI API error: ${res.status}`;
|
|
102
|
+
let errBody = null;
|
|
103
|
+
try {
|
|
104
|
+
errBody = await res.json();
|
|
105
|
+
if (typeof errBody === "object" &&
|
|
106
|
+
errBody !== null &&
|
|
107
|
+
"error" in errBody) {
|
|
108
|
+
const err = errBody.error;
|
|
109
|
+
if (err?.message) {
|
|
110
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// ignore parse errors
|
|
116
|
+
}
|
|
117
|
+
throw new XaiError(message, res.status, errBody);
|
|
118
|
+
}
|
|
119
|
+
return (await res.json());
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
clearTimeout(timeoutId);
|
|
123
|
+
if (error instanceof XaiError)
|
|
124
|
+
throw error;
|
|
125
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function buildManagementQuery(params) {
|
|
129
|
+
const parts = [];
|
|
130
|
+
for (const [key, value] of Object.entries(params)) {
|
|
131
|
+
if (value !== undefined && value !== null) {
|
|
132
|
+
if (Array.isArray(value)) {
|
|
133
|
+
for (const item of value) {
|
|
134
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return parts.length > 0 ? `?${parts.join("&")}` : "";
|
|
143
|
+
}
|
|
144
|
+
async function makeBinaryRequest(path, body, signal) {
|
|
145
|
+
const controller = new AbortController();
|
|
146
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
147
|
+
if (signal) {
|
|
148
|
+
attachAbortHandler(signal, controller);
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const res = await doFetch(`${baseURL}${path}`, {
|
|
152
|
+
method: "POST",
|
|
153
|
+
headers: {
|
|
154
|
+
Authorization: `Bearer ${opts.apiKey}`,
|
|
155
|
+
"Content-Type": "application/json",
|
|
156
|
+
},
|
|
157
|
+
body: JSON.stringify(body),
|
|
158
|
+
signal: controller.signal,
|
|
159
|
+
});
|
|
160
|
+
clearTimeout(timeoutId);
|
|
161
|
+
if (!res.ok) {
|
|
162
|
+
let message = `XAI API error: ${res.status}`;
|
|
163
|
+
let errBody = null;
|
|
164
|
+
try {
|
|
165
|
+
errBody = await res.json();
|
|
166
|
+
if (typeof errBody === "object" &&
|
|
167
|
+
errBody !== null &&
|
|
168
|
+
"error" in errBody) {
|
|
169
|
+
const err = errBody.error;
|
|
170
|
+
if (err?.message) {
|
|
171
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// ignore parse errors
|
|
177
|
+
}
|
|
178
|
+
throw new XaiError(message, res.status, errBody);
|
|
179
|
+
}
|
|
180
|
+
return await res.arrayBuffer();
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
clearTimeout(timeoutId);
|
|
184
|
+
if (error instanceof XaiError)
|
|
185
|
+
throw error;
|
|
186
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function makeMultipartRequest(path, form, signal) {
|
|
190
|
+
const controller = new AbortController();
|
|
191
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
192
|
+
if (signal) {
|
|
193
|
+
attachAbortHandler(signal, controller);
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const res = await doFetch(`${baseURL}${path}`, {
|
|
197
|
+
method: "POST",
|
|
198
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
199
|
+
body: form,
|
|
200
|
+
signal: controller.signal,
|
|
201
|
+
});
|
|
202
|
+
clearTimeout(timeoutId);
|
|
203
|
+
if (!res.ok) {
|
|
204
|
+
let message = `XAI API error: ${res.status}`;
|
|
205
|
+
let errBody = null;
|
|
206
|
+
try {
|
|
207
|
+
errBody = await res.json();
|
|
208
|
+
if (typeof errBody === "object" &&
|
|
209
|
+
errBody !== null &&
|
|
210
|
+
"error" in errBody) {
|
|
211
|
+
const err = errBody.error;
|
|
212
|
+
if (err?.message) {
|
|
213
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// ignore parse errors
|
|
219
|
+
}
|
|
220
|
+
throw new XaiError(message, res.status, errBody);
|
|
221
|
+
}
|
|
222
|
+
return (await res.json());
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
clearTimeout(timeoutId);
|
|
226
|
+
if (error instanceof XaiError)
|
|
227
|
+
throw error;
|
|
228
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// POST https://api.x.ai/v1/batches
|
|
232
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
233
|
+
const postBatches = Object.assign(async function createBatch(req, signal) {
|
|
234
|
+
return await makeRequest("POST", "/batches", req, signal);
|
|
235
|
+
}, {
|
|
236
|
+
schema: XaiBatchCreateRequestSchema,
|
|
237
|
+
// POST https://api.x.ai/v1/batches/{batchId}:cancel
|
|
238
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
239
|
+
cancel: async function cancelBatch(batchId, signal) {
|
|
240
|
+
return await makeRequest("POST", `/batches/${batchId}:cancel`, {}, signal);
|
|
241
|
+
},
|
|
242
|
+
// POST https://api.x.ai/v1/batches/{batchId}/requests
|
|
243
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
244
|
+
requests: async function addRequests(batchId, req, signal) {
|
|
245
|
+
await makeRequest("POST", `/batches/${batchId}/requests`, req, signal);
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
// POST https://api.x.ai/v1/collections
|
|
249
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
250
|
+
const postCollections = Object.assign(async function createCollection(req, signal) {
|
|
251
|
+
return await makeManagementRequest("POST", "/collections", req, signal);
|
|
252
|
+
}, {
|
|
253
|
+
schema: XaiCollectionCreateRequestSchema,
|
|
254
|
+
// POST https://api.x.ai/v1/collections/{collectionId}/documents/{fileId}
|
|
255
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
256
|
+
documents: async function addDocument(collectionId, fileId, req, signal) {
|
|
257
|
+
await makeManagementRequest("POST", `/collections/${collectionId}/documents/${fileId}`, req ?? {}, signal);
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
// GET https://api.x.ai/v1/files/{fileIdOrSignal}
|
|
261
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
262
|
+
async function getFiles(fileIdOrSignal, signal) {
|
|
263
|
+
if (typeof fileIdOrSignal === "string") {
|
|
264
|
+
return makeRequest("GET", `/files/${fileIdOrSignal}`, undefined, signal);
|
|
265
|
+
}
|
|
266
|
+
return makeRequest("GET", "/files", undefined, fileIdOrSignal);
|
|
267
|
+
}
|
|
268
|
+
// GET https://api.x.ai/v1/models/{modelIdOrSignal}
|
|
269
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
270
|
+
async function getModels(modelIdOrSignal, signal) {
|
|
271
|
+
if (typeof modelIdOrSignal === "string") {
|
|
272
|
+
return makeRequest("GET", `/models/${modelIdOrSignal}`, undefined, signal);
|
|
273
|
+
}
|
|
274
|
+
return makeRequest("GET", "/models", undefined, modelIdOrSignal);
|
|
275
|
+
}
|
|
276
|
+
// GET https://api.x.ai/v1/language-models/{modelIdOrSignal}
|
|
277
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
278
|
+
async function getLanguageModels(modelIdOrSignal, signal) {
|
|
279
|
+
if (typeof modelIdOrSignal === "string") {
|
|
280
|
+
return makeRequest("GET", `/language-models/${modelIdOrSignal}`, undefined, signal);
|
|
281
|
+
}
|
|
282
|
+
return makeRequest("GET", "/language-models", undefined, modelIdOrSignal);
|
|
283
|
+
}
|
|
284
|
+
// GET https://api.x.ai/v1/image-generation-models/{modelIdOrSignal}
|
|
285
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
286
|
+
async function getImageGenerationModels(modelIdOrSignal, signal) {
|
|
287
|
+
if (typeof modelIdOrSignal === "string") {
|
|
288
|
+
return makeRequest("GET", `/image-generation-models/${modelIdOrSignal}`, undefined, signal);
|
|
289
|
+
}
|
|
290
|
+
return makeRequest("GET", "/image-generation-models", undefined, modelIdOrSignal);
|
|
291
|
+
}
|
|
292
|
+
// GET https://api.x.ai/v1/video-generation-models/{modelIdOrSignal}
|
|
293
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
294
|
+
async function getVideoGenerationModels(modelIdOrSignal, signal) {
|
|
295
|
+
if (typeof modelIdOrSignal === "string") {
|
|
296
|
+
return makeRequest("GET", `/video-generation-models/${modelIdOrSignal}`, undefined, signal);
|
|
297
|
+
}
|
|
298
|
+
return makeRequest("GET", "/video-generation-models", undefined, modelIdOrSignal);
|
|
299
|
+
}
|
|
300
|
+
// GET https://api.x.ai/v1/batches/{paramsOrIdOrSignal}
|
|
301
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
302
|
+
async function getBatches(paramsOrIdOrSignal, signal) {
|
|
303
|
+
if (typeof paramsOrIdOrSignal === "string") {
|
|
304
|
+
return makeRequest("GET", `/batches/${paramsOrIdOrSignal}`, undefined, signal);
|
|
305
|
+
}
|
|
306
|
+
const query = buildQuery(paramsOrIdOrSignal ?? {});
|
|
307
|
+
return makeRequest("GET", `/batches${query}`, undefined, signal);
|
|
308
|
+
}
|
|
309
|
+
const getBatchesNamespace = Object.assign(getBatches, {
|
|
310
|
+
// GET https://api.x.ai/v1/batches/{batchId}/requests{query}
|
|
311
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
312
|
+
requests: async function listRequests(batchId, params, signal) {
|
|
313
|
+
const query = buildQuery(params ?? {});
|
|
314
|
+
return await makeRequest("GET", `/batches/${batchId}/requests${query}`, undefined, signal);
|
|
315
|
+
},
|
|
316
|
+
// GET https://api.x.ai/v1/batches/{batchId}/results{query}
|
|
317
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
318
|
+
results: async function listResults(batchId, params, signal) {
|
|
319
|
+
const query = buildQuery(params ?? {});
|
|
320
|
+
return await makeRequest("GET", `/batches/${batchId}/results${query}`, undefined, signal);
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
// GET https://api.x.ai/v1/collections/{paramsOrIdOrSignal}
|
|
324
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
325
|
+
async function getCollections(paramsOrIdOrSignal, signal) {
|
|
326
|
+
if (typeof paramsOrIdOrSignal === "string") {
|
|
327
|
+
return makeManagementRequest("GET", `/collections/${paramsOrIdOrSignal}`, undefined, signal);
|
|
328
|
+
}
|
|
329
|
+
const query = buildManagementQuery(paramsOrIdOrSignal ?? {});
|
|
330
|
+
return makeManagementRequest("GET", `/collections${query}`, undefined, signal);
|
|
331
|
+
}
|
|
332
|
+
// GET https://api.x.ai/v1/collections/{collectionId}/documents/{paramsOrFileId}
|
|
333
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
334
|
+
const getCollectionsDocuments = Object.assign(async function listDocuments(collectionId, paramsOrFileId, signal) {
|
|
335
|
+
if (typeof paramsOrFileId === "string") {
|
|
336
|
+
return makeManagementRequest("GET", `/collections/${collectionId}/documents/${paramsOrFileId}`, undefined, signal);
|
|
337
|
+
}
|
|
338
|
+
const query = buildManagementQuery(paramsOrFileId ?? {});
|
|
339
|
+
return makeManagementRequest("GET", `/collections/${collectionId}/documents${query}`, undefined, signal);
|
|
340
|
+
}, {
|
|
341
|
+
// GET https://api.x.ai/v1/collections/{collectionId}/documents:batchGet{query}
|
|
342
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
343
|
+
batchGet: async function batchGetDocuments(collectionId, fileIds, signal) {
|
|
344
|
+
const params = fileIds
|
|
345
|
+
.map((id) => `file_ids=${encodeURIComponent(id)}`)
|
|
346
|
+
.join("&");
|
|
347
|
+
const query = params ? `?${params}` : "";
|
|
348
|
+
return await makeManagementRequest("GET", `/collections/${collectionId}/documents:batchGet${query}`, undefined, signal);
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
const getCollectionsNamespace = Object.assign(getCollections, {
|
|
352
|
+
documents: getCollectionsDocuments,
|
|
353
|
+
});
|
|
354
|
+
// DELETE https://api.x.ai/v1/collections/{collectionId}
|
|
355
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
356
|
+
const deleteCollections = Object.assign(async function deleteCollection(collectionId, signal) {
|
|
357
|
+
await makeManagementRequest("DELETE", `/collections/${collectionId}`, undefined, signal);
|
|
358
|
+
}, {
|
|
359
|
+
// DELETE https://api.x.ai/v1/collections/{collectionId}/documents/{fileId}
|
|
360
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
361
|
+
documents: async function deleteDocument(collectionId, fileId, signal) {
|
|
362
|
+
await makeManagementRequest("DELETE", `/collections/${collectionId}/documents/${fileId}`, undefined, signal);
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
// PUT https://api.x.ai/v1/collections/{collectionId}
|
|
366
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
367
|
+
const putCollections = Object.assign(async function updateCollection(collectionId, req, signal) {
|
|
368
|
+
return await makeManagementRequest("PUT", `/collections/${collectionId}`, req, signal);
|
|
369
|
+
}, {
|
|
370
|
+
schema: XaiCollectionUpdateRequestSchema,
|
|
371
|
+
});
|
|
372
|
+
return attachExamples({
|
|
373
|
+
post: {
|
|
374
|
+
v1: {
|
|
375
|
+
// POST https://api.x.ai/v1/responses
|
|
376
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
377
|
+
responses: Object.assign(async function postResponses(req, signal) {
|
|
378
|
+
return await makeRequest("POST", "/responses", req, signal);
|
|
379
|
+
}, {
|
|
380
|
+
schema: XaiResponseRequestSchema,
|
|
381
|
+
}),
|
|
382
|
+
chat: {
|
|
383
|
+
// POST https://api.x.ai/v1/chat/completions
|
|
384
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
385
|
+
completions: Object.assign(async function completions(req, signal) {
|
|
386
|
+
return await makeRequest("POST", "/chat/completions", req, signal);
|
|
387
|
+
}, {
|
|
388
|
+
schema: XaiChatRequestSchema,
|
|
389
|
+
}),
|
|
390
|
+
},
|
|
391
|
+
images: {
|
|
392
|
+
// POST https://api.x.ai/v1/images/generations
|
|
393
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
394
|
+
generations: Object.assign(async function generations(req, signal) {
|
|
395
|
+
return await makeRequest("POST", "/images/generations", req, signal);
|
|
396
|
+
}, {
|
|
397
|
+
schema: XaiImageGenerateRequestSchema,
|
|
398
|
+
}),
|
|
399
|
+
// POST https://api.x.ai/v1/images/edits
|
|
400
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
401
|
+
edits: Object.assign(async function edits(req, signal) {
|
|
402
|
+
return await makeRequest("POST", "/images/edits", req, signal);
|
|
403
|
+
}, {
|
|
404
|
+
schema: XaiImageEditRequestSchema,
|
|
405
|
+
}),
|
|
406
|
+
},
|
|
407
|
+
videos: {
|
|
408
|
+
// POST https://api.x.ai/v1/videos/generations
|
|
409
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
410
|
+
generations: Object.assign(async function generations(req, signal) {
|
|
411
|
+
return await makeRequest("POST", "/videos/generations", req, signal);
|
|
412
|
+
}, {
|
|
413
|
+
schema: XaiVideoGenerateRequestSchema,
|
|
414
|
+
}),
|
|
415
|
+
// POST https://api.x.ai/v1/videos/edits
|
|
416
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
417
|
+
edits: Object.assign(async function edits(req, signal) {
|
|
418
|
+
return await makeRequest("POST", "/videos/edits", req, signal);
|
|
419
|
+
}, {
|
|
420
|
+
schema: XaiVideoEditRequestSchema,
|
|
421
|
+
}),
|
|
422
|
+
// POST https://api.x.ai/v1/videos/extensions
|
|
423
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
424
|
+
extensions: Object.assign(async function extensions(req, signal) {
|
|
425
|
+
return await makeRequest("POST", "/videos/extensions", req, signal);
|
|
426
|
+
}, {
|
|
427
|
+
schema: XaiVideoExtendRequestSchema,
|
|
428
|
+
}),
|
|
429
|
+
},
|
|
430
|
+
// POST https://api.x.ai/v1/files
|
|
431
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
432
|
+
files: Object.assign(async function postFiles(file, filename, purpose, signal) {
|
|
433
|
+
const controller = new AbortController();
|
|
434
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
435
|
+
if (signal) {
|
|
436
|
+
attachAbortHandler(signal, controller);
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
const formData = new FormData();
|
|
440
|
+
formData.append("file", file, filename);
|
|
441
|
+
if (purpose !== undefined)
|
|
442
|
+
formData.append("purpose", purpose);
|
|
443
|
+
const res = await doFetch(`${baseURL}/files`, {
|
|
444
|
+
method: "POST",
|
|
445
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
446
|
+
body: formData,
|
|
447
|
+
signal: controller.signal,
|
|
448
|
+
});
|
|
449
|
+
clearTimeout(timeoutId);
|
|
450
|
+
if (!res.ok) {
|
|
451
|
+
let message = `XAI API error: ${res.status}`;
|
|
452
|
+
let body = null;
|
|
453
|
+
try {
|
|
454
|
+
body = await res.json();
|
|
455
|
+
if (typeof body === "object" &&
|
|
456
|
+
body !== null &&
|
|
457
|
+
"error" in body) {
|
|
458
|
+
const err = body.error;
|
|
459
|
+
if (err?.message) {
|
|
460
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
// ignore parse errors
|
|
466
|
+
}
|
|
467
|
+
throw new XaiError(message, res.status, body);
|
|
468
|
+
}
|
|
469
|
+
return (await res.json());
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
clearTimeout(timeoutId);
|
|
473
|
+
if (error instanceof XaiError)
|
|
474
|
+
throw error;
|
|
475
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
476
|
+
}
|
|
477
|
+
}, {}),
|
|
478
|
+
batches: postBatches,
|
|
479
|
+
collections: postCollections,
|
|
480
|
+
documents: {
|
|
481
|
+
// POST https://api.x.ai/v1/documents/search
|
|
482
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
483
|
+
search: Object.assign(async function search(req, signal) {
|
|
484
|
+
return await makeRequest("POST", "/documents/search", req, signal);
|
|
485
|
+
}, {
|
|
486
|
+
schema: XaiDocumentSearchRequestSchema,
|
|
487
|
+
}),
|
|
488
|
+
},
|
|
489
|
+
// POST https://api.x.ai/v1/tokenize-text
|
|
490
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
491
|
+
tokenizeText: Object.assign(async function tokenizeText(req, signal) {
|
|
492
|
+
return await makeRequest("POST", "/tokenize-text", req, signal);
|
|
493
|
+
}, {
|
|
494
|
+
schema: XaiTokenizeTextRequestSchema,
|
|
495
|
+
}),
|
|
496
|
+
realtime: {
|
|
497
|
+
// POST https://api.x.ai/v1/realtime/client_secrets
|
|
498
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
499
|
+
clientSecrets: Object.assign(async function clientSecrets(req, signal) {
|
|
500
|
+
return await makeRequest("POST", "/realtime/client_secrets", req, signal);
|
|
501
|
+
}, {
|
|
502
|
+
schema: XaiRealtimeClientSecretRequestSchema,
|
|
503
|
+
}),
|
|
504
|
+
},
|
|
505
|
+
// POST https://api.x.ai/v1/tts
|
|
506
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
507
|
+
tts: Object.assign(async function tts(req, signal) {
|
|
508
|
+
return await makeBinaryRequest("/tts", req, signal);
|
|
509
|
+
}, {
|
|
510
|
+
schema: XaiTtsRequestSchema,
|
|
511
|
+
}),
|
|
512
|
+
// POST https://api.x.ai/v1/stt
|
|
513
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
514
|
+
stt: Object.assign(async function stt(req, signal) {
|
|
515
|
+
const form = new FormData();
|
|
516
|
+
form.append("file", req.file, req.filename ?? "audio");
|
|
517
|
+
if (req.language !== undefined) {
|
|
518
|
+
form.append("language", req.language);
|
|
519
|
+
}
|
|
520
|
+
return await makeMultipartRequest("/stt", form, signal);
|
|
521
|
+
}, {
|
|
522
|
+
schema: XaiSttRequestSchema,
|
|
523
|
+
}),
|
|
524
|
+
// POST https://api.x.ai/v1/custom-voices
|
|
525
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
526
|
+
customVoices: Object.assign(async function customVoices(req, signal) {
|
|
527
|
+
const form = new FormData();
|
|
528
|
+
form.append("file", req.file, req.filename ?? "reference");
|
|
529
|
+
form.append("name", req.name);
|
|
530
|
+
form.append("language", req.language);
|
|
531
|
+
return await makeMultipartRequest("/custom-voices", form, signal);
|
|
532
|
+
}, {
|
|
533
|
+
schema: XaiCustomVoiceCreateRequestSchema,
|
|
534
|
+
}),
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
get: {
|
|
538
|
+
v1: {
|
|
539
|
+
// GET https://api.x.ai/v1/responses/{id}
|
|
540
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
541
|
+
responses: async function getResponses(id, signal) {
|
|
542
|
+
return await makeRequest("GET", `/responses/${encodeURIComponent(id)}`, undefined, signal);
|
|
543
|
+
},
|
|
544
|
+
chat: {
|
|
545
|
+
// GET https://api.x.ai/v1/chat/deferred-completion/{requestId}
|
|
546
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
547
|
+
deferredCompletion: async function deferredCompletion(requestId, signal) {
|
|
548
|
+
const controller = new AbortController();
|
|
549
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
550
|
+
if (signal) {
|
|
551
|
+
attachAbortHandler(signal, controller);
|
|
552
|
+
}
|
|
553
|
+
try {
|
|
554
|
+
const res = await doFetch(`${baseURL}/chat/deferred-completion/${encodeURIComponent(requestId)}`, {
|
|
555
|
+
method: "GET",
|
|
556
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
557
|
+
signal: controller.signal,
|
|
558
|
+
});
|
|
559
|
+
clearTimeout(timeoutId);
|
|
560
|
+
if (res.status === 202) {
|
|
561
|
+
return { ready: false, data: null };
|
|
562
|
+
}
|
|
563
|
+
if (!res.ok) {
|
|
564
|
+
let message = `XAI API error: ${res.status}`;
|
|
565
|
+
let body = null;
|
|
566
|
+
try {
|
|
567
|
+
body = await res.json();
|
|
568
|
+
if (typeof body === "object" &&
|
|
569
|
+
body !== null &&
|
|
570
|
+
"error" in body) {
|
|
571
|
+
const err = body.error;
|
|
572
|
+
if (err?.message) {
|
|
573
|
+
message = `XAI API error ${res.status}: ${err.message}`;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
catch {
|
|
578
|
+
// ignore parse errors
|
|
579
|
+
}
|
|
580
|
+
throw new XaiError(message, res.status, body);
|
|
581
|
+
}
|
|
582
|
+
const data = (await res.json());
|
|
583
|
+
return { ready: true, data };
|
|
584
|
+
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
clearTimeout(timeoutId);
|
|
587
|
+
if (error instanceof XaiError)
|
|
588
|
+
throw error;
|
|
589
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
// GET https://api.x.ai/v1/videos/{requestId}
|
|
594
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
595
|
+
videos: async function getVideos(requestId, signal) {
|
|
596
|
+
return await makeRequest("GET", `/videos/${requestId}`, undefined, signal);
|
|
597
|
+
},
|
|
598
|
+
files: getFiles,
|
|
599
|
+
models: getModels,
|
|
600
|
+
languageModels: getLanguageModels,
|
|
601
|
+
imageGenerationModels: getImageGenerationModels,
|
|
602
|
+
videoGenerationModels: getVideoGenerationModels,
|
|
603
|
+
batches: getBatchesNamespace,
|
|
604
|
+
collections: getCollectionsNamespace,
|
|
605
|
+
},
|
|
606
|
+
},
|
|
607
|
+
delete: {
|
|
608
|
+
v1: {
|
|
609
|
+
// DELETE https://api.x.ai/v1/responses/{id}
|
|
610
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
611
|
+
responses: async function deleteResponses(id, signal) {
|
|
612
|
+
return await makeRequest("DELETE", `/responses/${encodeURIComponent(id)}`, undefined, signal);
|
|
613
|
+
},
|
|
614
|
+
// DELETE https://api.x.ai/v1/files/{fileId}
|
|
615
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
616
|
+
files: async function deleteFiles(fileId, signal) {
|
|
617
|
+
const controller = new AbortController();
|
|
618
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
619
|
+
if (signal) {
|
|
620
|
+
attachAbortHandler(signal, controller);
|
|
621
|
+
}
|
|
622
|
+
try {
|
|
623
|
+
const res = await doFetch(`${baseURL}/files/${fileId}`, {
|
|
624
|
+
method: "DELETE",
|
|
625
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
626
|
+
signal: controller.signal,
|
|
627
|
+
});
|
|
628
|
+
clearTimeout(timeoutId);
|
|
629
|
+
if (!res.ok) {
|
|
630
|
+
let deleteBody = null;
|
|
631
|
+
try {
|
|
632
|
+
deleteBody = await res.json();
|
|
633
|
+
}
|
|
634
|
+
catch {
|
|
635
|
+
// ignore parse errors
|
|
636
|
+
}
|
|
637
|
+
throw new XaiError(`XAI API error: ${res.status}`, res.status, deleteBody);
|
|
638
|
+
}
|
|
639
|
+
return (await res.json());
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
clearTimeout(timeoutId);
|
|
643
|
+
if (error instanceof XaiError)
|
|
644
|
+
throw error;
|
|
645
|
+
throw new XaiError(`XAI request failed: ${error}`, 500);
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
collections: deleteCollections,
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
put: {
|
|
652
|
+
v1: {
|
|
653
|
+
collections: putCollections,
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
patch: {
|
|
657
|
+
v1: {
|
|
658
|
+
collections: {
|
|
659
|
+
// PATCH https://api.x.ai/v1/collections/{collectionId}/documents/{fileId}
|
|
660
|
+
// Docs: https://docs.x.ai/docs/api-reference
|
|
661
|
+
documents: async function regenerateDocument(collectionId, fileId, signal) {
|
|
662
|
+
await makeManagementRequest("PATCH", `/collections/${collectionId}/documents/${fileId}`, undefined, signal);
|
|
663
|
+
},
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
ws: {
|
|
668
|
+
v1: {
|
|
669
|
+
realtime: function connectRealtime(connectOpts) {
|
|
670
|
+
const wsBaseURL = baseURL.replace(/^http/, "ws");
|
|
671
|
+
const token = connectOpts?.token ?? opts.apiKey;
|
|
672
|
+
const model = connectOpts?.model;
|
|
673
|
+
// Voice-agent connection: ?model= query string + Authorization
|
|
674
|
+
// header (no subprotocols). Otherwise, OpenAI-compat subprotocol auth.
|
|
675
|
+
let ws;
|
|
676
|
+
if (model) {
|
|
677
|
+
const url = `${wsBaseURL}/realtime?model=${encodeURIComponent(model)}`;
|
|
678
|
+
// Node `ws` accepts a third-arg options object with `headers`;
|
|
679
|
+
// browsers ignore it. Cast keeps TS happy across DOM/Node lib defs.
|
|
680
|
+
ws = new WebSocket(url, undefined, {
|
|
681
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
ws = new WebSocket(`${wsBaseURL}/realtime`, [
|
|
686
|
+
"realtime",
|
|
687
|
+
`openai-insecure-api-key.${token}`,
|
|
688
|
+
"openai-beta.realtime-v1",
|
|
689
|
+
]);
|
|
690
|
+
}
|
|
691
|
+
let resolveNext = null;
|
|
692
|
+
const eventQueue = [];
|
|
693
|
+
let closed = false;
|
|
694
|
+
ws.onmessage = (ev) => {
|
|
695
|
+
const event = JSON.parse(typeof ev.data === "string" ? ev.data : String(ev.data));
|
|
696
|
+
if (resolveNext) {
|
|
697
|
+
const resolve = resolveNext;
|
|
698
|
+
resolveNext = null;
|
|
699
|
+
resolve({ value: event, done: false });
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
eventQueue.push(event);
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
ws.onclose = () => {
|
|
706
|
+
closed = true;
|
|
707
|
+
if (resolveNext) {
|
|
708
|
+
const resolve = resolveNext;
|
|
709
|
+
resolveNext = null;
|
|
710
|
+
resolve({ value: undefined, done: true });
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
ws.onerror = () => {
|
|
714
|
+
closed = true;
|
|
715
|
+
if (resolveNext) {
|
|
716
|
+
const resolve = resolveNext;
|
|
717
|
+
resolveNext = null;
|
|
718
|
+
resolve({ value: undefined, done: true });
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
return {
|
|
722
|
+
send(event) {
|
|
723
|
+
ws.send(JSON.stringify(event));
|
|
724
|
+
},
|
|
725
|
+
close() {
|
|
726
|
+
closed = true;
|
|
727
|
+
ws.close();
|
|
728
|
+
},
|
|
729
|
+
[Symbol.asyncIterator]() {
|
|
730
|
+
return {
|
|
731
|
+
next() {
|
|
732
|
+
if (eventQueue.length > 0) {
|
|
733
|
+
return Promise.resolve({
|
|
734
|
+
value: eventQueue.shift(),
|
|
735
|
+
done: false,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
if (closed) {
|
|
739
|
+
return Promise.resolve({
|
|
740
|
+
value: undefined,
|
|
741
|
+
done: true,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
return new Promise((resolve) => {
|
|
745
|
+
resolveNext = resolve;
|
|
746
|
+
});
|
|
747
|
+
},
|
|
748
|
+
[Symbol.asyncIterator]() {
|
|
749
|
+
return this;
|
|
750
|
+
},
|
|
751
|
+
};
|
|
752
|
+
},
|
|
753
|
+
};
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
//# sourceMappingURL=xai.js.map
|