@ai-sdk/xai 4.0.39 → 4.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +108 -51
- package/dist/index.js.map +1 -1
- package/docs/01-xai.mdx +39 -0
- package/package.json +1 -1
- package/src/xai-error.ts +12 -2
- package/src/xai-speech-model-options.ts +14 -0
- package/src/xai-speech-model.ts +78 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @ai-sdk/xai
|
|
2
2
|
|
|
3
|
+
## 4.0.40
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1ffa1d2: feat(xai): speech timestamps, pronunciation replacements, provider metadata, and error parsing
|
|
8
|
+
|
|
9
|
+
- Add `withTimestamps` and `replace` provider options for text to speech. With
|
|
10
|
+
`withTimestamps`, the JSON envelope is decoded and the audio returned as
|
|
11
|
+
usual, while duration, content type, and character-level alignment are
|
|
12
|
+
exposed via `providerMetadata.xai`.
|
|
13
|
+
- Return `providerMetadata.xai.traceId` (from the `x-trace-id` response
|
|
14
|
+
header) on every speech response.
|
|
15
|
+
- Parse the text to speech error shape (`{"error":"..."}`) so `APICallError`
|
|
16
|
+
messages carry xAI's real error detail instead of the HTTP reason phrase.
|
|
17
|
+
|
|
3
18
|
## 4.0.39
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -65,6 +65,8 @@ declare const xaiErrorDataSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
65
65
|
}, z.core.$strip>, z.ZodObject<{
|
|
66
66
|
code: z.ZodString;
|
|
67
67
|
error: z.ZodString;
|
|
68
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
69
|
+
error: z.ZodString;
|
|
68
70
|
}, z.core.$strip>]>;
|
|
69
71
|
type XaiErrorData = z.infer<typeof xaiErrorDataSchema>;
|
|
70
72
|
|
|
@@ -218,6 +220,8 @@ declare const xaiSpeechModelOptionsSchema: _ai_sdk_provider_utils.LazySchema<{
|
|
|
218
220
|
bitRate?: 32000 | 64000 | 96000 | 128000 | 192000 | null | undefined;
|
|
219
221
|
optimizeStreamingLatency?: 0 | 1 | 2 | null | undefined;
|
|
220
222
|
textNormalization?: boolean | null | undefined;
|
|
223
|
+
withTimestamps?: boolean | null | undefined;
|
|
224
|
+
replace?: Record<string, string> | null | undefined;
|
|
221
225
|
}>;
|
|
222
226
|
type XaiSpeechModelOptions = InferSchema<typeof xaiSpeechModelOptionsSchema>;
|
|
223
227
|
|
package/dist/index.js
CHANGED
|
@@ -384,13 +384,22 @@ var responsesErrorSchema = z3.object({
|
|
|
384
384
|
code: z3.string(),
|
|
385
385
|
error: z3.string()
|
|
386
386
|
});
|
|
387
|
+
var speechErrorSchema = z3.object({
|
|
388
|
+
error: z3.string()
|
|
389
|
+
});
|
|
387
390
|
var xaiErrorDataSchema = z3.union([
|
|
388
391
|
chatCompletionsErrorSchema,
|
|
389
|
-
responsesErrorSchema
|
|
392
|
+
responsesErrorSchema,
|
|
393
|
+
speechErrorSchema
|
|
390
394
|
]);
|
|
391
395
|
var xaiFailedResponseHandler = createJsonErrorResponseHandler({
|
|
392
396
|
errorSchema: xaiErrorDataSchema,
|
|
393
|
-
errorToMessage: (data) =>
|
|
397
|
+
errorToMessage: (data) => {
|
|
398
|
+
if (typeof data.error === "string") {
|
|
399
|
+
return "code" in data ? `${data.code}: ${data.error}` : data.error;
|
|
400
|
+
}
|
|
401
|
+
return data.error.message;
|
|
402
|
+
}
|
|
394
403
|
});
|
|
395
404
|
|
|
396
405
|
// src/xai-prepare-tools.ts
|
|
@@ -3720,7 +3729,7 @@ var xaiTools = {
|
|
|
3720
3729
|
};
|
|
3721
3730
|
|
|
3722
3731
|
// src/version.ts
|
|
3723
|
-
var VERSION = true ? "4.0.
|
|
3732
|
+
var VERSION = true ? "4.0.40" : "0.0.0-test";
|
|
3724
3733
|
|
|
3725
3734
|
// src/files/xai-files.ts
|
|
3726
3735
|
import {
|
|
@@ -4360,7 +4369,9 @@ var xaiVideoStatusResponseHandler = async (options) => {
|
|
|
4360
4369
|
// src/xai-speech-model.ts
|
|
4361
4370
|
import {
|
|
4362
4371
|
combineHeaders as combineHeaders6,
|
|
4372
|
+
convertBase64ToUint8Array,
|
|
4363
4373
|
createBinaryResponseHandler as createBinaryResponseHandler2,
|
|
4374
|
+
createJsonResponseHandler as createJsonResponseHandler6,
|
|
4364
4375
|
parseProviderOptions as parseProviderOptions8,
|
|
4365
4376
|
postJsonToApi as postJsonToApi5,
|
|
4366
4377
|
resolve,
|
|
@@ -4368,6 +4379,7 @@ import {
|
|
|
4368
4379
|
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE4,
|
|
4369
4380
|
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE4
|
|
4370
4381
|
} from "@ai-sdk/provider-utils";
|
|
4382
|
+
import { z as z22 } from "zod/v4";
|
|
4371
4383
|
|
|
4372
4384
|
// src/xai-speech-model-options.ts
|
|
4373
4385
|
import {
|
|
@@ -4406,7 +4418,19 @@ var xaiSpeechModelOptionsSchema = lazySchema9(
|
|
|
4406
4418
|
/**
|
|
4407
4419
|
* Normalize written-form text into spoken-form text before synthesis.
|
|
4408
4420
|
*/
|
|
4409
|
-
textNormalization: z21.boolean().nullish()
|
|
4421
|
+
textNormalization: z21.boolean().nullish(),
|
|
4422
|
+
/**
|
|
4423
|
+
* Return character-level timing metadata alongside the audio. When
|
|
4424
|
+
* enabled, the response carries per-character start/end times and the
|
|
4425
|
+
* total duration, exposed via `providerMetadata.xai`.
|
|
4426
|
+
*/
|
|
4427
|
+
withTimestamps: z21.boolean().nullish(),
|
|
4428
|
+
/**
|
|
4429
|
+
* Map of phrases to spoken substitutions applied before synthesis.
|
|
4430
|
+
* Values may be respellings (`{ 'Acme Mobile': 'Acme Mobull' }`) or IPA
|
|
4431
|
+
* phonetics (`{ nginx: '/ˈɛndʒɪn ˈɛks/' }`).
|
|
4432
|
+
*/
|
|
4433
|
+
replace: z21.record(z21.string(), z21.string()).nullish()
|
|
4410
4434
|
})
|
|
4411
4435
|
)
|
|
4412
4436
|
);
|
|
@@ -4486,19 +4510,21 @@ var XaiSpeechModel = class _XaiSpeechModel {
|
|
|
4486
4510
|
output_format,
|
|
4487
4511
|
speed,
|
|
4488
4512
|
optimize_streaming_latency: xaiOptions == null ? void 0 : xaiOptions.optimizeStreamingLatency,
|
|
4489
|
-
text_normalization: xaiOptions == null ? void 0 : xaiOptions.textNormalization
|
|
4513
|
+
text_normalization: xaiOptions == null ? void 0 : xaiOptions.textNormalization,
|
|
4514
|
+
with_timestamps: xaiOptions == null ? void 0 : xaiOptions.withTimestamps,
|
|
4515
|
+
replace: xaiOptions == null ? void 0 : xaiOptions.replace
|
|
4516
|
+
};
|
|
4517
|
+
return {
|
|
4518
|
+
requestBody,
|
|
4519
|
+
warnings,
|
|
4520
|
+
withTimestamps: (xaiOptions == null ? void 0 : xaiOptions.withTimestamps) === true
|
|
4490
4521
|
};
|
|
4491
|
-
return { requestBody, warnings };
|
|
4492
4522
|
}
|
|
4493
4523
|
async doGenerate(options) {
|
|
4494
4524
|
var _a, _b, _c;
|
|
4495
4525
|
const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
|
|
4496
|
-
const { requestBody, warnings } = await this.getArgs(options);
|
|
4497
|
-
const {
|
|
4498
|
-
value: audio,
|
|
4499
|
-
responseHeaders,
|
|
4500
|
-
rawValue: rawResponse
|
|
4501
|
-
} = await postJsonToApi5({
|
|
4526
|
+
const { requestBody, warnings, withTimestamps } = await this.getArgs(options);
|
|
4527
|
+
const { value, responseHeaders, rawValue } = await postJsonToApi5({
|
|
4502
4528
|
url: `${this.config.baseURL}/tts`,
|
|
4503
4529
|
headers: combineHeaders6(
|
|
4504
4530
|
this.config.headers ? await resolve(this.config.headers) : void 0,
|
|
@@ -4506,10 +4532,19 @@ var XaiSpeechModel = class _XaiSpeechModel {
|
|
|
4506
4532
|
),
|
|
4507
4533
|
body: requestBody,
|
|
4508
4534
|
failedResponseHandler: xaiFailedResponseHandler,
|
|
4509
|
-
successfulResponseHandler: createBinaryResponseHandler2(),
|
|
4535
|
+
successfulResponseHandler: withTimestamps ? createJsonResponseHandler6(xaiSpeechTimestampsResponseSchema) : createBinaryResponseHandler2(),
|
|
4510
4536
|
abortSignal: options.abortSignal,
|
|
4511
4537
|
fetch: this.config.fetch
|
|
4512
4538
|
});
|
|
4539
|
+
let audio;
|
|
4540
|
+
let envelope;
|
|
4541
|
+
if (value instanceof Uint8Array) {
|
|
4542
|
+
audio = value;
|
|
4543
|
+
} else {
|
|
4544
|
+
envelope = value;
|
|
4545
|
+
audio = envelope.audio != null ? convertBase64ToUint8Array(envelope.audio) : new Uint8Array(0);
|
|
4546
|
+
}
|
|
4547
|
+
const traceId = responseHeaders == null ? void 0 : responseHeaders["x-trace-id"];
|
|
4513
4548
|
return {
|
|
4514
4549
|
audio,
|
|
4515
4550
|
warnings,
|
|
@@ -4520,11 +4555,33 @@ var XaiSpeechModel = class _XaiSpeechModel {
|
|
|
4520
4555
|
timestamp: currentDate,
|
|
4521
4556
|
modelId: this.modelId,
|
|
4522
4557
|
headers: responseHeaders,
|
|
4523
|
-
body:
|
|
4558
|
+
body: rawValue
|
|
4559
|
+
},
|
|
4560
|
+
providerMetadata: {
|
|
4561
|
+
xai: {
|
|
4562
|
+
...traceId != null ? { traceId } : {},
|
|
4563
|
+
...(envelope == null ? void 0 : envelope.duration) != null ? { duration: envelope.duration } : {},
|
|
4564
|
+
...(envelope == null ? void 0 : envelope.content_type) != null ? { contentType: envelope.content_type } : {},
|
|
4565
|
+
...(envelope == null ? void 0 : envelope.audio_timestamps) != null ? {
|
|
4566
|
+
audioTimestamps: {
|
|
4567
|
+
graphChars: envelope.audio_timestamps.graph_chars,
|
|
4568
|
+
graphTimes: envelope.audio_timestamps.graph_times
|
|
4569
|
+
}
|
|
4570
|
+
} : {}
|
|
4571
|
+
}
|
|
4524
4572
|
}
|
|
4525
4573
|
};
|
|
4526
4574
|
}
|
|
4527
4575
|
};
|
|
4576
|
+
var xaiSpeechTimestampsResponseSchema = z22.object({
|
|
4577
|
+
audio: z22.string().nullish(),
|
|
4578
|
+
content_type: z22.string().nullish(),
|
|
4579
|
+
duration: z22.number().nullish(),
|
|
4580
|
+
audio_timestamps: z22.object({
|
|
4581
|
+
graph_chars: z22.array(z22.string()),
|
|
4582
|
+
graph_times: z22.array(z22.tuple([z22.number(), z22.number()]))
|
|
4583
|
+
}).nullish()
|
|
4584
|
+
});
|
|
4528
4585
|
|
|
4529
4586
|
// src/xai-transcription-model.ts
|
|
4530
4587
|
import {
|
|
@@ -4532,8 +4589,8 @@ import {
|
|
|
4532
4589
|
} from "@ai-sdk/provider";
|
|
4533
4590
|
import {
|
|
4534
4591
|
combineHeaders as combineHeaders7,
|
|
4535
|
-
convertBase64ToUint8Array,
|
|
4536
|
-
createJsonResponseHandler as
|
|
4592
|
+
convertBase64ToUint8Array as convertBase64ToUint8Array2,
|
|
4593
|
+
createJsonResponseHandler as createJsonResponseHandler7,
|
|
4537
4594
|
connectToWebSocket,
|
|
4538
4595
|
mediaTypeToExtension,
|
|
4539
4596
|
parseProviderOptions as parseProviderOptions9,
|
|
@@ -4545,80 +4602,80 @@ import {
|
|
|
4545
4602
|
WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE5,
|
|
4546
4603
|
WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE5
|
|
4547
4604
|
} from "@ai-sdk/provider-utils";
|
|
4548
|
-
import { z as
|
|
4605
|
+
import { z as z24 } from "zod/v4";
|
|
4549
4606
|
|
|
4550
4607
|
// src/xai-transcription-model-options.ts
|
|
4551
4608
|
import {
|
|
4552
4609
|
lazySchema as lazySchema10,
|
|
4553
4610
|
zodSchema as zodSchema10
|
|
4554
4611
|
} from "@ai-sdk/provider-utils";
|
|
4555
|
-
import { z as
|
|
4612
|
+
import { z as z23 } from "zod/v4";
|
|
4556
4613
|
var xaiTranscriptionModelOptionsSchema = lazySchema10(
|
|
4557
4614
|
() => zodSchema10(
|
|
4558
|
-
|
|
4615
|
+
z23.object({
|
|
4559
4616
|
/**
|
|
4560
4617
|
* Audio encoding for raw, headerless input audio.
|
|
4561
4618
|
*/
|
|
4562
|
-
audioFormat:
|
|
4619
|
+
audioFormat: z23.enum(["pcm", "mulaw", "alaw"]).nullish(),
|
|
4563
4620
|
/**
|
|
4564
4621
|
* Sample rate of the input audio in Hz.
|
|
4565
4622
|
*/
|
|
4566
|
-
sampleRate:
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4623
|
+
sampleRate: z23.union([
|
|
4624
|
+
z23.literal(8e3),
|
|
4625
|
+
z23.literal(16e3),
|
|
4626
|
+
z23.literal(22050),
|
|
4627
|
+
z23.literal(24e3),
|
|
4628
|
+
z23.literal(44100),
|
|
4629
|
+
z23.literal(48e3)
|
|
4573
4630
|
]).nullish(),
|
|
4574
4631
|
/**
|
|
4575
4632
|
* Language code used for inverse text normalization.
|
|
4576
4633
|
*/
|
|
4577
|
-
language:
|
|
4634
|
+
language: z23.string().nullish(),
|
|
4578
4635
|
/**
|
|
4579
4636
|
* Enable inverse text normalization. Requires `language`.
|
|
4580
4637
|
*/
|
|
4581
|
-
format:
|
|
4638
|
+
format: z23.boolean().nullish(),
|
|
4582
4639
|
/**
|
|
4583
4640
|
* Enable per-channel transcription for multichannel audio.
|
|
4584
4641
|
*/
|
|
4585
|
-
multichannel:
|
|
4642
|
+
multichannel: z23.boolean().nullish(),
|
|
4586
4643
|
/**
|
|
4587
4644
|
* Number of interleaved audio channels.
|
|
4588
4645
|
*/
|
|
4589
|
-
channels:
|
|
4646
|
+
channels: z23.number().int().min(2).max(8).nullish(),
|
|
4590
4647
|
/**
|
|
4591
4648
|
* Enable speaker diarization.
|
|
4592
4649
|
*/
|
|
4593
|
-
diarize:
|
|
4650
|
+
diarize: z23.boolean().nullish(),
|
|
4594
4651
|
/**
|
|
4595
4652
|
* Terms to bias transcription toward.
|
|
4596
4653
|
*/
|
|
4597
|
-
keyterm:
|
|
4654
|
+
keyterm: z23.union([z23.string(), z23.array(z23.string())]).nullish(),
|
|
4598
4655
|
/**
|
|
4599
4656
|
* Include filler words such as "uh" and "um" in the transcript.
|
|
4600
4657
|
*/
|
|
4601
|
-
fillerWords:
|
|
4658
|
+
fillerWords: z23.boolean().nullish(),
|
|
4602
4659
|
/**
|
|
4603
4660
|
* Options for streaming speech-to-text over WebSocket.
|
|
4604
4661
|
*/
|
|
4605
|
-
streaming:
|
|
4662
|
+
streaming: z23.object({
|
|
4606
4663
|
/**
|
|
4607
4664
|
* Emit interim transcript results while speech is being processed.
|
|
4608
4665
|
*/
|
|
4609
|
-
interimResults:
|
|
4666
|
+
interimResults: z23.boolean().optional(),
|
|
4610
4667
|
/**
|
|
4611
4668
|
* Silence duration in milliseconds before an utterance-final event.
|
|
4612
4669
|
*/
|
|
4613
|
-
endpointing:
|
|
4670
|
+
endpointing: z23.number().int().min(0).max(5e3).optional(),
|
|
4614
4671
|
/**
|
|
4615
4672
|
* End-of-turn detection threshold. When set, enables Smart Turn.
|
|
4616
4673
|
*/
|
|
4617
|
-
smartTurn:
|
|
4674
|
+
smartTurn: z23.number().min(0).max(1).optional(),
|
|
4618
4675
|
/**
|
|
4619
4676
|
* Maximum silence duration in milliseconds before forcing speech_final.
|
|
4620
4677
|
*/
|
|
4621
|
-
smartTurnTimeout:
|
|
4678
|
+
smartTurnTimeout: z23.number().int().min(1).max(5e3).optional()
|
|
4622
4679
|
}).optional()
|
|
4623
4680
|
})
|
|
4624
4681
|
)
|
|
@@ -4676,7 +4733,7 @@ var XaiTranscriptionModel = class _XaiTranscriptionModel {
|
|
|
4676
4733
|
formData.append("keyterm", keyterm);
|
|
4677
4734
|
}
|
|
4678
4735
|
}
|
|
4679
|
-
const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([
|
|
4736
|
+
const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array2(audio)]);
|
|
4680
4737
|
const fileExtension = mediaTypeToExtension(mediaType);
|
|
4681
4738
|
formData.append(
|
|
4682
4739
|
"file",
|
|
@@ -4698,7 +4755,7 @@ var XaiTranscriptionModel = class _XaiTranscriptionModel {
|
|
|
4698
4755
|
headers: combineHeaders7((_f = (_e = this.config).headers) == null ? void 0 : _f.call(_e), options.headers),
|
|
4699
4756
|
formData,
|
|
4700
4757
|
failedResponseHandler: xaiFailedResponseHandler,
|
|
4701
|
-
successfulResponseHandler:
|
|
4758
|
+
successfulResponseHandler: createJsonResponseHandler7(
|
|
4702
4759
|
xaiTranscriptionResponseSchema
|
|
4703
4760
|
),
|
|
4704
4761
|
abortSignal: options.abortSignal,
|
|
@@ -4835,7 +4892,7 @@ function createXaiStreamingTranscriptionStream({
|
|
|
4835
4892
|
const { done, value } = await audioReader.read();
|
|
4836
4893
|
if (done || finished) break;
|
|
4837
4894
|
socket.send(
|
|
4838
|
-
value instanceof Uint8Array ? value :
|
|
4895
|
+
value instanceof Uint8Array ? value : convertBase64ToUint8Array2(value)
|
|
4839
4896
|
);
|
|
4840
4897
|
await waitForWebSocketBufferDrain(socket);
|
|
4841
4898
|
}
|
|
@@ -5017,15 +5074,15 @@ function timingFromXaiEvent(event) {
|
|
|
5017
5074
|
...event.start != null && event.duration != null ? { endSecond: event.start + event.duration } : {}
|
|
5018
5075
|
};
|
|
5019
5076
|
}
|
|
5020
|
-
var xaiTranscriptionResponseSchema =
|
|
5021
|
-
text:
|
|
5022
|
-
language:
|
|
5023
|
-
duration:
|
|
5024
|
-
words:
|
|
5025
|
-
|
|
5026
|
-
text:
|
|
5027
|
-
start:
|
|
5028
|
-
end:
|
|
5077
|
+
var xaiTranscriptionResponseSchema = z24.object({
|
|
5078
|
+
text: z24.string(),
|
|
5079
|
+
language: z24.string().nullish(),
|
|
5080
|
+
duration: z24.number().nullish(),
|
|
5081
|
+
words: z24.array(
|
|
5082
|
+
z24.object({
|
|
5083
|
+
text: z24.string(),
|
|
5084
|
+
start: z24.number(),
|
|
5085
|
+
end: z24.number()
|
|
5029
5086
|
})
|
|
5030
5087
|
).nullish()
|
|
5031
5088
|
});
|