@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.
@@ -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