@broberg/ai-sdk 0.43.0 → 0.45.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/dist/index.d.ts +145 -21
- package/dist/index.js +225 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -87,6 +87,61 @@ interface Pronunciation {
|
|
|
87
87
|
lang?: string;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/** One entry of Azure's `[nnnn].word.json`, verbatim field names. */
|
|
91
|
+
interface AzureWordBoundary {
|
|
92
|
+
Text: string;
|
|
93
|
+
/** Milliseconds into the audio. */
|
|
94
|
+
AudioOffset: number;
|
|
95
|
+
/** Milliseconds. */
|
|
96
|
+
Duration: number;
|
|
97
|
+
}
|
|
98
|
+
interface WordTiming {
|
|
99
|
+
/** The spoken word, as Azure reported it. */
|
|
100
|
+
text: string;
|
|
101
|
+
startMs: number;
|
|
102
|
+
endMs: number;
|
|
103
|
+
/** Character span in the SOURCE text. Several spoken words share one span when they
|
|
104
|
+
* came from one substituted manuscript word. */
|
|
105
|
+
sourceStart: number;
|
|
106
|
+
sourceEnd: number;
|
|
107
|
+
}
|
|
108
|
+
interface AlignedWordTimings {
|
|
109
|
+
/** Every word we could place in the source, in audio order. */
|
|
110
|
+
words: WordTiming[];
|
|
111
|
+
/** Spoken words we could NOT place, in order, verbatim.
|
|
112
|
+
*
|
|
113
|
+
* Named rather than dropped, and never given a guessed offset. "I could not place
|
|
114
|
+
* this" and "it was here" must not be the same answer — the same discipline as
|
|
115
|
+
* `rerank.unscored` (F052). A highlighter that treats `words` as complete must look
|
|
116
|
+
* here. */
|
|
117
|
+
unaligned: string[];
|
|
118
|
+
}
|
|
119
|
+
/** A pronunciation entry, narrowed to what alignment needs. */
|
|
120
|
+
interface AliasEntry {
|
|
121
|
+
word: string;
|
|
122
|
+
alias?: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Map Azure's spoken word list onto positions in the SOURCE text.
|
|
126
|
+
*
|
|
127
|
+
* Two rules carry the whole function:
|
|
128
|
+
*
|
|
129
|
+
* **The walk only moves FORWARD.** That is what puts a repeated word on its own
|
|
130
|
+
* occurrence — "AI er AI" must not place the second on the first. Searching from 0 each
|
|
131
|
+
* time passes every test with distinct words and fails silently on real prose.
|
|
132
|
+
*
|
|
133
|
+
* **A substitution is matched as a RUN, not word by word.** Azure speaks SSML, so
|
|
134
|
+
* `<sub alias='broberg punktum a i'>broberg.ai</sub>` puts four words in the list where
|
|
135
|
+
* the manuscript has one. Matching them individually is not merely imprecise, it is
|
|
136
|
+
* wrong in a way that bites every Danish text: MEASURED on cms's own dictionary entry,
|
|
137
|
+
* a per-word map made the alias's "i" swallow the next real Danish word "i" in
|
|
138
|
+
* "broberg.ai i dag". An alias's parts are often ordinary words ("a", "i", "punktum"),
|
|
139
|
+
* so a lookup table cannot be the mechanism — the run has to be consumed positionally.
|
|
140
|
+
*/
|
|
141
|
+
declare function alignWordTimings(text: string, words: AzureWordBoundary[], opts?: {
|
|
142
|
+
pronunciations?: AliasEntry[];
|
|
143
|
+
}): AlignedWordTimings;
|
|
144
|
+
|
|
90
145
|
/** How a call reaches the model. `http` = provider REST API; `subprocess` = local
|
|
91
146
|
* `claude -p` CLI (Max plan, costUsd 0). */
|
|
92
147
|
type Transport = "http" | "subprocess";
|
|
@@ -479,6 +534,11 @@ interface DialogueTurn {
|
|
|
479
534
|
}
|
|
480
535
|
interface DialogueRequest {
|
|
481
536
|
inputs: DialogueTurn[];
|
|
537
|
+
/** F051.4 — the pronunciation dictionary, applied to EACH line. cms measured the
|
|
538
|
+
* gap: a two-host podcast could not get a dictionary at all, so "broberg.ai" was
|
|
539
|
+
* said wrong in every episode — they could fix the sponsor read and the host's
|
|
540
|
+
* hand-off (both `ai.tts`) and not the conversation, which is 95% of the audio. */
|
|
541
|
+
pronunciations?: Pronunciation[];
|
|
482
542
|
/** Output container, e.g. "mp3" (default). */
|
|
483
543
|
format?: string;
|
|
484
544
|
spec: TierSpec;
|
|
@@ -487,6 +547,14 @@ interface PodcastResult {
|
|
|
487
547
|
/** Episode audio bytes. */
|
|
488
548
|
audio: Uint8Array;
|
|
489
549
|
mimeType: string;
|
|
550
|
+
/** F055 — per-word timings, present only when `wordTimings` was asked for AND the
|
|
551
|
+
* route produces them. Its ABSENCE says "not available here"; an empty `words` array
|
|
552
|
+
* would say "the text had no words", which is a different claim.
|
|
553
|
+
*
|
|
554
|
+
* `sourceStart`/`sourceEnd` index the ORIGINAL text you passed, not the SSML we sent
|
|
555
|
+
* — Azure reports only audio time, so the link back to the manuscript is derived
|
|
556
|
+
* here. `unaligned` names any spoken word that could not be placed. */
|
|
557
|
+
wordTimings?: AlignedWordTimings;
|
|
490
558
|
usage: Usage;
|
|
491
559
|
}
|
|
492
560
|
|
|
@@ -507,6 +575,16 @@ interface TtsRequest {
|
|
|
507
575
|
* into SSML** — the substitution happens adapter-side AFTER the text is escaped, so
|
|
508
576
|
* `text` can never inject markup, and `alias`/`ipa` are escaped too. */
|
|
509
577
|
pronunciations?: Pronunciation[];
|
|
578
|
+
/** F055 — ask for per-word timings so a reader can highlight each word as it is
|
|
579
|
+
* spoken. Azure only. Absent from the result means "this route does not produce
|
|
580
|
+
* them", which is a different answer from an empty list.
|
|
581
|
+
*
|
|
582
|
+
* **This changes the ROUTE, not just the payload.** The real-time endpoint returns
|
|
583
|
+
* audio only; word boundaries exist solely on Azure's asynchronous batch synthesis
|
|
584
|
+
* API, so the call becomes submit → poll → fetch. Microsoft quotes 10–20s for half
|
|
585
|
+
* of all jobs and up to 120s for 95%. Worth it for a pre-generated, cached reading;
|
|
586
|
+
* wrong for anything a user is waiting on. */
|
|
587
|
+
wordTimings?: boolean;
|
|
510
588
|
spec: TierSpec;
|
|
511
589
|
}
|
|
512
590
|
interface BatchRequestItem {
|
|
@@ -1317,6 +1395,7 @@ declare const imageInputSchema: z.ZodObject<{
|
|
|
1317
1395
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1318
1396
|
seed?: number | undefined;
|
|
1319
1397
|
purpose?: string | undefined;
|
|
1398
|
+
outputFormat?: "jpeg" | "png" | "webp" | undefined;
|
|
1320
1399
|
loras?: {
|
|
1321
1400
|
path: string;
|
|
1322
1401
|
scale?: number | undefined;
|
|
@@ -1338,7 +1417,6 @@ declare const imageInputSchema: z.ZodObject<{
|
|
|
1338
1417
|
finetune?: string | undefined;
|
|
1339
1418
|
finetuneStrength?: number | undefined;
|
|
1340
1419
|
referenceImages?: (string | Uint8Array<ArrayBuffer>)[] | undefined;
|
|
1341
|
-
outputFormat?: "jpeg" | "png" | "webp" | undefined;
|
|
1342
1420
|
safetyTolerance?: number | undefined;
|
|
1343
1421
|
retryOnBlack?: boolean | undefined;
|
|
1344
1422
|
}, {
|
|
@@ -1346,6 +1424,7 @@ declare const imageInputSchema: z.ZodObject<{
|
|
|
1346
1424
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1347
1425
|
seed?: number | undefined;
|
|
1348
1426
|
purpose?: string | undefined;
|
|
1427
|
+
outputFormat?: "jpeg" | "png" | "webp" | undefined;
|
|
1349
1428
|
loras?: {
|
|
1350
1429
|
path: string;
|
|
1351
1430
|
scale?: number | undefined;
|
|
@@ -1367,7 +1446,6 @@ declare const imageInputSchema: z.ZodObject<{
|
|
|
1367
1446
|
finetune?: string | undefined;
|
|
1368
1447
|
finetuneStrength?: number | undefined;
|
|
1369
1448
|
referenceImages?: (string | Uint8Array<ArrayBuffer>)[] | undefined;
|
|
1370
|
-
outputFormat?: "jpeg" | "png" | "webp" | undefined;
|
|
1371
1449
|
safetyTolerance?: number | undefined;
|
|
1372
1450
|
retryOnBlack?: boolean | undefined;
|
|
1373
1451
|
}>;
|
|
@@ -1837,6 +1915,29 @@ declare const podcastInputSchema: z.ZodObject<{
|
|
|
1837
1915
|
}>, "many">;
|
|
1838
1916
|
voices: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1839
1917
|
format: z.ZodOptional<z.ZodString>;
|
|
1918
|
+
/** F051.4 — same field, same semantics as tts. Applied PER LINE: ElevenLabs'
|
|
1919
|
+
* /text-to-dialogue takes inputs[].text separately, so there is no composed string
|
|
1920
|
+
* a replacement could run across a speaker boundary in. */
|
|
1921
|
+
pronunciations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1922
|
+
word: z.ZodString;
|
|
1923
|
+
alias: z.ZodOptional<z.ZodString>;
|
|
1924
|
+
ipa: z.ZodOptional<z.ZodString>;
|
|
1925
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
1926
|
+
/** F051.3 — also match inside a hyphenated compound ("AI" in "AI-agenter"). */
|
|
1927
|
+
matchInCompounds: z.ZodOptional<z.ZodBoolean>;
|
|
1928
|
+
}, "strip", z.ZodTypeAny, {
|
|
1929
|
+
word: string;
|
|
1930
|
+
matchInCompounds?: boolean | undefined;
|
|
1931
|
+
alias?: string | undefined;
|
|
1932
|
+
ipa?: string | undefined;
|
|
1933
|
+
lang?: string | undefined;
|
|
1934
|
+
}, {
|
|
1935
|
+
word: string;
|
|
1936
|
+
matchInCompounds?: boolean | undefined;
|
|
1937
|
+
alias?: string | undefined;
|
|
1938
|
+
ipa?: string | undefined;
|
|
1939
|
+
lang?: string | undefined;
|
|
1940
|
+
}>, "many">>;
|
|
1840
1941
|
}, "strip", z.ZodTypeAny, {
|
|
1841
1942
|
script: {
|
|
1842
1943
|
text: string;
|
|
@@ -1845,6 +1946,13 @@ declare const podcastInputSchema: z.ZodObject<{
|
|
|
1845
1946
|
voices: Record<string, string>;
|
|
1846
1947
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1847
1948
|
purpose?: string | undefined;
|
|
1949
|
+
pronunciations?: {
|
|
1950
|
+
word: string;
|
|
1951
|
+
matchInCompounds?: boolean | undefined;
|
|
1952
|
+
alias?: string | undefined;
|
|
1953
|
+
ipa?: string | undefined;
|
|
1954
|
+
lang?: string | undefined;
|
|
1955
|
+
}[] | undefined;
|
|
1848
1956
|
override?: {
|
|
1849
1957
|
provider?: string | undefined;
|
|
1850
1958
|
model?: string | undefined;
|
|
@@ -1865,6 +1973,13 @@ declare const podcastInputSchema: z.ZodObject<{
|
|
|
1865
1973
|
voices: Record<string, string>;
|
|
1866
1974
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1867
1975
|
purpose?: string | undefined;
|
|
1976
|
+
pronunciations?: {
|
|
1977
|
+
word: string;
|
|
1978
|
+
matchInCompounds?: boolean | undefined;
|
|
1979
|
+
alias?: string | undefined;
|
|
1980
|
+
ipa?: string | undefined;
|
|
1981
|
+
lang?: string | undefined;
|
|
1982
|
+
}[] | undefined;
|
|
1868
1983
|
override?: {
|
|
1869
1984
|
provider?: string | undefined;
|
|
1870
1985
|
model?: string | undefined;
|
|
@@ -1932,6 +2047,8 @@ declare const ttsInputSchema: z.ZodObject<{
|
|
|
1932
2047
|
ipa?: string | undefined;
|
|
1933
2048
|
lang?: string | undefined;
|
|
1934
2049
|
}>, "many">>;
|
|
2050
|
+
/** F055 — per-word timings (Azure only). Changes the route to batch synthesis. */
|
|
2051
|
+
wordTimings: z.ZodOptional<z.ZodBoolean>;
|
|
1935
2052
|
/** F037: voice to use if `voice` is one we know the provider has retired. Without
|
|
1936
2053
|
* it a retired voice throws VoiceUnavailableError rather than reaching the API.
|
|
1937
2054
|
*
|
|
@@ -1951,6 +2068,14 @@ declare const ttsInputSchema: z.ZodObject<{
|
|
|
1951
2068
|
voice: string;
|
|
1952
2069
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1953
2070
|
purpose?: string | undefined;
|
|
2071
|
+
wordTimings?: boolean | undefined;
|
|
2072
|
+
pronunciations?: {
|
|
2073
|
+
word: string;
|
|
2074
|
+
matchInCompounds?: boolean | undefined;
|
|
2075
|
+
alias?: string | undefined;
|
|
2076
|
+
ipa?: string | undefined;
|
|
2077
|
+
lang?: string | undefined;
|
|
2078
|
+
}[] | undefined;
|
|
1954
2079
|
override?: {
|
|
1955
2080
|
provider?: string | undefined;
|
|
1956
2081
|
model?: string | undefined;
|
|
@@ -1962,15 +2087,8 @@ declare const ttsInputSchema: z.ZodObject<{
|
|
|
1962
2087
|
transport: "http" | "subprocess";
|
|
1963
2088
|
})[] | undefined;
|
|
1964
2089
|
labels?: Record<string, string> | undefined;
|
|
1965
|
-
format?: string | undefined;
|
|
1966
2090
|
lang?: string | undefined;
|
|
1967
|
-
|
|
1968
|
-
word: string;
|
|
1969
|
-
matchInCompounds?: boolean | undefined;
|
|
1970
|
-
alias?: string | undefined;
|
|
1971
|
-
ipa?: string | undefined;
|
|
1972
|
-
lang?: string | undefined;
|
|
1973
|
-
}[] | undefined;
|
|
2091
|
+
format?: string | undefined;
|
|
1974
2092
|
voiceFallback?: string | undefined;
|
|
1975
2093
|
rate?: number | undefined;
|
|
1976
2094
|
}, {
|
|
@@ -1978,6 +2096,14 @@ declare const ttsInputSchema: z.ZodObject<{
|
|
|
1978
2096
|
voice: string;
|
|
1979
2097
|
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1980
2098
|
purpose?: string | undefined;
|
|
2099
|
+
wordTimings?: boolean | undefined;
|
|
2100
|
+
pronunciations?: {
|
|
2101
|
+
word: string;
|
|
2102
|
+
matchInCompounds?: boolean | undefined;
|
|
2103
|
+
alias?: string | undefined;
|
|
2104
|
+
ipa?: string | undefined;
|
|
2105
|
+
lang?: string | undefined;
|
|
2106
|
+
}[] | undefined;
|
|
1981
2107
|
override?: {
|
|
1982
2108
|
provider?: string | undefined;
|
|
1983
2109
|
model?: string | undefined;
|
|
@@ -1989,15 +2115,8 @@ declare const ttsInputSchema: z.ZodObject<{
|
|
|
1989
2115
|
transport: "http" | "subprocess";
|
|
1990
2116
|
})[] | undefined;
|
|
1991
2117
|
labels?: Record<string, string> | undefined;
|
|
1992
|
-
format?: string | undefined;
|
|
1993
2118
|
lang?: string | undefined;
|
|
1994
|
-
|
|
1995
|
-
word: string;
|
|
1996
|
-
matchInCompounds?: boolean | undefined;
|
|
1997
|
-
alias?: string | undefined;
|
|
1998
|
-
ipa?: string | undefined;
|
|
1999
|
-
lang?: string | undefined;
|
|
2000
|
-
}[] | undefined;
|
|
2119
|
+
format?: string | undefined;
|
|
2001
2120
|
voiceFallback?: string | undefined;
|
|
2002
2121
|
rate?: number | undefined;
|
|
2003
2122
|
}>;
|
|
@@ -2271,6 +2390,11 @@ declare function azureAdapter(config?: {
|
|
|
2271
2390
|
resource?: string;
|
|
2272
2391
|
/** Fast-transcription api-version (overrides the GA default). */
|
|
2273
2392
|
sttApiVersion?: string;
|
|
2393
|
+
/** F055 — how long to wait for a batch synthesis job. Default 180s (Microsoft's own
|
|
2394
|
+
* 95th percentile is 120s). */
|
|
2395
|
+
batchTimeoutMs?: number;
|
|
2396
|
+
/** F055 — poll interval for batch synthesis. Default 3s. */
|
|
2397
|
+
batchPollMs?: number;
|
|
2274
2398
|
/** phraseList biasing weight (0–2) applied when a call passes `phrases`. Default 1.5. */
|
|
2275
2399
|
sttBiasingWeight?: number;
|
|
2276
2400
|
}): ProviderAdapter;
|
|
@@ -2390,8 +2514,8 @@ declare const falStubAdapter: ProviderAdapter;
|
|
|
2390
2514
|
* wires the live adapters. */
|
|
2391
2515
|
declare const stubProviders: Record<string, ProviderAdapter>;
|
|
2392
2516
|
|
|
2393
|
-
declare const VERSION: "0.
|
|
2394
|
-
declare const SDK_TAG: "@broberg/ai-sdk@0.
|
|
2517
|
+
declare const VERSION: "0.45.0";
|
|
2518
|
+
declare const SDK_TAG: "@broberg/ai-sdk@0.45.0";
|
|
2395
2519
|
|
|
2396
2520
|
/** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
|
|
2397
2521
|
* per-call override.
|
|
@@ -2802,4 +2926,4 @@ interface StreamTransportRequest extends TransportRequest {
|
|
|
2802
2926
|
*/
|
|
2803
2927
|
declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
|
|
2804
2928
|
|
|
2805
|
-
export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AzureVoiceInfo, type BatchJob, type BatchRequestItem, type BatchResultItem, type BflAdapterConfig, type BflCredits, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostQuery, type CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DialogueRequest, type DialogueTurn, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, type LoraWeight, type Message, type MockupInput, type MockupResult, type ModerationInput, type ModerationItem, type ModerationRequest, type ModerationResult, type OcrInput, type OcrPage, type OcrRequest, type OcrResult, type OpenAICompatibleConfig, type PodcastInput, type PodcastResult, type PricingEntry, type ProviderAdapter, type RefreshOptions, type RefreshResult, type Region, type RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TrainStyleInput, type TrainStyleRequest, type TrainStyleResult, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, chatInputSchema, checkVoice, classifyRegionName, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, regionOfHost, regionOfProvider, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema };
|
|
2929
|
+
export { AZURE_DANISH_VOICES, AZURE_DANISH_VOICE_LIST, type AiClient, type AiConfig, type AlignedWordTimings, type AzureVoiceInfo, type AzureWordBoundary, type BatchJob, type BatchRequestItem, type BatchResultItem, type BflAdapterConfig, type BflCredits, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type CheckVoiceOptions, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostQuery, type CostSink, type CostSummary, type CostSummaryQuery, type CostTimeseriesQuery, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DialogueRequest, type DialogueTurn, type DiscordSinkConfig, ELEVENLABS_DANISH_VOICES, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, type LoraWeight, type Message, type MockupInput, type MockupResult, type ModerationInput, type ModerationItem, type ModerationRequest, type ModerationResult, type OcrInput, type OcrPage, type OcrRequest, type OcrResult, type OpenAICompatibleConfig, type PodcastInput, type PodcastResult, type PricingEntry, type ProviderAdapter, type RefreshOptions, type RefreshResult, type Region, type RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TrainStyleInput, type TrainStyleRequest, type TrainStyleResult, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsCostClientConfig, UpmetricsCostError, type UpmetricsCostRow, type UpmetricsCostSummary, type UpmetricsCostTimeseries, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, type VoiceInfo, type VoiceProvider, type VoiceResolveResult, type VoiceStatus, VoiceUnavailableError, type WordTiming, aiConfigSchema, alignWordTimings, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, azureAdapter, bflAdapter, bflCredits, chatInputSchema, checkVoice, classifyRegionName, computeCost, createAI, deepinfraAdapter, deeplAdapter, deepseekAdapter, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, listAzureDanishVoices, listVoices, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, mistralStubAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, refreshAvailability, regionOfHost, regionOfProvider, requestyAdapter, resetRefreshState, resetRegistry, resolveAzureVoice, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsCostClient, upmetricsSink, usdFromMicro, vertexAdapter, visionInputSchema };
|
package/dist/index.js
CHANGED
|
@@ -1617,7 +1617,13 @@ function elevenlabsAdapter(config = {}) {
|
|
|
1617
1617
|
headers: { "xi-api-key": key(), "content-type": "application/json", accept: "audio/mpeg" },
|
|
1618
1618
|
body: JSON.stringify({
|
|
1619
1619
|
model_id: req.spec.model,
|
|
1620
|
-
|
|
1620
|
+
// F051.4 — PER LINE. The endpoint takes each turn's text separately, so the
|
|
1621
|
+
// dictionary applies exactly as it does in tts; composing the script into one
|
|
1622
|
+
// string first would let a replacement run across a speaker boundary.
|
|
1623
|
+
inputs: req.inputs.map((t) => ({
|
|
1624
|
+
text: ttsText({ text: t.text, pronunciations: req.pronunciations }),
|
|
1625
|
+
voice_id: t.voiceId
|
|
1626
|
+
})),
|
|
1621
1627
|
...req.format ? { output_format: req.format } : {}
|
|
1622
1628
|
})
|
|
1623
1629
|
});
|
|
@@ -1652,6 +1658,124 @@ function elevenlabsAdapter(config = {}) {
|
|
|
1652
1658
|
return { name: "elevenlabs", dialogue, tts, listVoices: listVoices2 };
|
|
1653
1659
|
}
|
|
1654
1660
|
|
|
1661
|
+
// src/providers/word-timings.ts
|
|
1662
|
+
var PUNCTUATION = /* @__PURE__ */ new Set([".", ",", "!", "?", ":", ";", "\u2026", "\u2014", "\u2013", '"', "'", "(", ")"]);
|
|
1663
|
+
var fold = (s) => s.toLowerCase();
|
|
1664
|
+
function alignWordTimings(text, words, opts = {}) {
|
|
1665
|
+
const out = [];
|
|
1666
|
+
const unaligned = [];
|
|
1667
|
+
const haystack = fold(text);
|
|
1668
|
+
const aliases = (opts.pronunciations ?? []).filter((p) => typeof p.alias === "string" && p.alias.trim() !== "").map((p) => ({ word: p.word, parts: p.alias.trim().split(/\s+/).map(fold) })).sort((a, b) => b.parts.length - a.parts.length);
|
|
1669
|
+
const spoken = words.filter((w) => !PUNCTUATION.has(w.Text.trim()));
|
|
1670
|
+
let cursor = 0;
|
|
1671
|
+
let i = 0;
|
|
1672
|
+
while (i < spoken.length) {
|
|
1673
|
+
let consumed = false;
|
|
1674
|
+
for (const a of aliases) {
|
|
1675
|
+
if (i + a.parts.length > spoken.length) continue;
|
|
1676
|
+
const matches = a.parts.every((part, k) => fold(spoken[i + k].Text) === part);
|
|
1677
|
+
if (!matches) continue;
|
|
1678
|
+
const at2 = haystack.indexOf(fold(a.word), cursor);
|
|
1679
|
+
if (at2 === -1) continue;
|
|
1680
|
+
const span = { start: at2, end: at2 + a.word.length };
|
|
1681
|
+
for (let k = 0; k < a.parts.length; k++) {
|
|
1682
|
+
const w2 = spoken[i + k];
|
|
1683
|
+
out.push({
|
|
1684
|
+
text: w2.Text,
|
|
1685
|
+
startMs: w2.AudioOffset,
|
|
1686
|
+
endMs: w2.AudioOffset + w2.Duration,
|
|
1687
|
+
sourceStart: span.start,
|
|
1688
|
+
sourceEnd: span.end
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
cursor = span.end;
|
|
1692
|
+
i += a.parts.length;
|
|
1693
|
+
consumed = true;
|
|
1694
|
+
break;
|
|
1695
|
+
}
|
|
1696
|
+
if (consumed) continue;
|
|
1697
|
+
const w = spoken[i];
|
|
1698
|
+
const at = haystack.indexOf(fold(w.Text), cursor);
|
|
1699
|
+
if (at === -1) {
|
|
1700
|
+
unaligned.push(w.Text);
|
|
1701
|
+
} else {
|
|
1702
|
+
out.push({
|
|
1703
|
+
text: w.Text,
|
|
1704
|
+
startMs: w.AudioOffset,
|
|
1705
|
+
endMs: w.AudioOffset + w.Duration,
|
|
1706
|
+
sourceStart: at,
|
|
1707
|
+
sourceEnd: at + w.Text.length
|
|
1708
|
+
});
|
|
1709
|
+
cursor = at + w.Text.length;
|
|
1710
|
+
}
|
|
1711
|
+
i++;
|
|
1712
|
+
}
|
|
1713
|
+
return { words: out, unaligned };
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/providers/zip.ts
|
|
1717
|
+
import { inflateRawSync } from "zlib";
|
|
1718
|
+
var EOCD_SIG = 101010256;
|
|
1719
|
+
var CEN_SIG = 33639248;
|
|
1720
|
+
function readZipEntry(zip, name) {
|
|
1721
|
+
const view = new DataView(zip.buffer, zip.byteOffset, zip.byteLength);
|
|
1722
|
+
let eocd = -1;
|
|
1723
|
+
for (let i = zip.length - 22; i >= 0; i--) {
|
|
1724
|
+
if (view.getUint32(i, true) === EOCD_SIG) {
|
|
1725
|
+
eocd = i;
|
|
1726
|
+
break;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if (eocd === -1) throw new Error("readZipEntry: not a ZIP archive (no end-of-central-directory record)");
|
|
1730
|
+
const entryCount = view.getUint16(eocd + 10, true);
|
|
1731
|
+
let p = view.getUint32(eocd + 16, true);
|
|
1732
|
+
for (let n = 0; n < entryCount; n++) {
|
|
1733
|
+
if (view.getUint32(p, true) !== CEN_SIG) {
|
|
1734
|
+
throw new Error(`readZipEntry: corrupt central directory at entry ${n}`);
|
|
1735
|
+
}
|
|
1736
|
+
const method = view.getUint16(p + 10, true);
|
|
1737
|
+
const compressedSize = view.getUint32(p + 20, true);
|
|
1738
|
+
const nameLen = view.getUint16(p + 28, true);
|
|
1739
|
+
const extraLen = view.getUint16(p + 30, true);
|
|
1740
|
+
const commentLen = view.getUint16(p + 32, true);
|
|
1741
|
+
const localOffset = view.getUint32(p + 42, true);
|
|
1742
|
+
const entryName = new TextDecoder().decode(zip.subarray(p + 46, p + 46 + nameLen));
|
|
1743
|
+
if (entryName === name) {
|
|
1744
|
+
const lNameLen = view.getUint16(localOffset + 26, true);
|
|
1745
|
+
const lExtraLen = view.getUint16(localOffset + 28, true);
|
|
1746
|
+
const start = localOffset + 30 + lNameLen + lExtraLen;
|
|
1747
|
+
const raw = zip.subarray(start, start + compressedSize);
|
|
1748
|
+
if (method === 0) return new Uint8Array(raw);
|
|
1749
|
+
if (method === 8) return new Uint8Array(inflateRawSync(raw));
|
|
1750
|
+
throw new Error(`readZipEntry: "${name}" uses unsupported compression method ${method}`);
|
|
1751
|
+
}
|
|
1752
|
+
p += 46 + nameLen + extraLen + commentLen;
|
|
1753
|
+
}
|
|
1754
|
+
return void 0;
|
|
1755
|
+
}
|
|
1756
|
+
function listZipEntries(zip) {
|
|
1757
|
+
const view = new DataView(zip.buffer, zip.byteOffset, zip.byteLength);
|
|
1758
|
+
let eocd = -1;
|
|
1759
|
+
for (let i = zip.length - 22; i >= 0; i--) {
|
|
1760
|
+
if (view.getUint32(i, true) === EOCD_SIG) {
|
|
1761
|
+
eocd = i;
|
|
1762
|
+
break;
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
if (eocd === -1) throw new Error("listZipEntries: not a ZIP archive (no end-of-central-directory record)");
|
|
1766
|
+
const entryCount = view.getUint16(eocd + 10, true);
|
|
1767
|
+
let p = view.getUint32(eocd + 16, true);
|
|
1768
|
+
const names = [];
|
|
1769
|
+
for (let n = 0; n < entryCount; n++) {
|
|
1770
|
+
const nameLen = view.getUint16(p + 28, true);
|
|
1771
|
+
const extraLen = view.getUint16(p + 30, true);
|
|
1772
|
+
const commentLen = view.getUint16(p + 32, true);
|
|
1773
|
+
names.push(new TextDecoder().decode(zip.subarray(p + 46, p + 46 + nameLen)));
|
|
1774
|
+
p += 46 + nameLen + extraLen + commentLen;
|
|
1775
|
+
}
|
|
1776
|
+
return names;
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1655
1779
|
// src/providers/azure.ts
|
|
1656
1780
|
var DEFAULT_STT_API_VERSION = "2025-10-15";
|
|
1657
1781
|
var DEFAULT_REGION = "westeurope";
|
|
@@ -1733,10 +1857,9 @@ function azureAdapter(config = {}) {
|
|
|
1733
1857
|
usage.costUsd = chars / 1e3 * (config.pricePer1kChars ?? getMediaPrice("azure", "tts")?.usd ?? 0);
|
|
1734
1858
|
return usage;
|
|
1735
1859
|
}
|
|
1736
|
-
|
|
1860
|
+
function buildSsml(req) {
|
|
1737
1861
|
const voice = resolveAzureVoice(req.voiceId);
|
|
1738
1862
|
const lang = req.lang ?? localeOf(voice);
|
|
1739
|
-
const format = req.format ?? DEFAULT_FORMAT;
|
|
1740
1863
|
assertPronunciations(req.pronunciations, "azure");
|
|
1741
1864
|
const escaped = applyPronunciations(
|
|
1742
1865
|
xmlEscape(req.text),
|
|
@@ -1746,7 +1869,11 @@ function azureAdapter(config = {}) {
|
|
|
1746
1869
|
);
|
|
1747
1870
|
const effRate = req.rate ?? AZURE_DANISH_VOICE_LIST.find((v) => v.voiceId === voice)?.defaultRate;
|
|
1748
1871
|
const inner = effRate != null && effRate !== 1 ? `<prosody rate='${effRate}'>${escaped}</prosody>` : escaped;
|
|
1749
|
-
|
|
1872
|
+
return `<speak version='1.0' xml:lang='${lang}'><voice name='${voice}'>${inner}</voice></speak>`;
|
|
1873
|
+
}
|
|
1874
|
+
async function tts(req) {
|
|
1875
|
+
if (req.wordTimings) return ttsBatch(req);
|
|
1876
|
+
const format = req.format ?? DEFAULT_FORMAT;
|
|
1750
1877
|
const res = await fetchImpl(
|
|
1751
1878
|
`https://${region()}.tts.speech.microsoft.com/cognitiveservices/v1`,
|
|
1752
1879
|
{
|
|
@@ -1756,7 +1883,7 @@ function azureAdapter(config = {}) {
|
|
|
1756
1883
|
"Content-Type": "application/ssml+xml",
|
|
1757
1884
|
"X-Microsoft-OutputFormat": format
|
|
1758
1885
|
},
|
|
1759
|
-
body:
|
|
1886
|
+
body: buildSsml(req)
|
|
1760
1887
|
}
|
|
1761
1888
|
);
|
|
1762
1889
|
if (!res.ok) {
|
|
@@ -1766,6 +1893,82 @@ function azureAdapter(config = {}) {
|
|
|
1766
1893
|
const audio = new Uint8Array(await res.arrayBuffer());
|
|
1767
1894
|
return { audio, mimeType: "audio/mpeg", usage: priceFor(req.text.length, req.spec.model) };
|
|
1768
1895
|
}
|
|
1896
|
+
async function ttsBatch(req) {
|
|
1897
|
+
const host = sttBaseUrl();
|
|
1898
|
+
const api = "api-version=2024-04-01";
|
|
1899
|
+
const id = `wt-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
1900
|
+
const headers = { "Ocp-Apim-Subscription-Key": key(), "Content-Type": "application/json" };
|
|
1901
|
+
const put = await fetchImpl(`${host}/texttospeech/batchsyntheses/${id}?${api}`, {
|
|
1902
|
+
method: "PUT",
|
|
1903
|
+
headers,
|
|
1904
|
+
body: JSON.stringify({
|
|
1905
|
+
inputKind: "SSML",
|
|
1906
|
+
inputs: [{ content: buildSsml(req) }],
|
|
1907
|
+
properties: {
|
|
1908
|
+
wordBoundaryEnabled: true,
|
|
1909
|
+
// ONE audio file and ONE word list for the whole text. Without it a chunked
|
|
1910
|
+
// input yields per-chunk offsets that somebody has to re-base — the kind of
|
|
1911
|
+
// arithmetic that looks right and is 40 ms wrong by the end.
|
|
1912
|
+
concatenateResult: true,
|
|
1913
|
+
...req.format ? { outputFormat: req.format } : {}
|
|
1914
|
+
}
|
|
1915
|
+
})
|
|
1916
|
+
});
|
|
1917
|
+
if (!put.ok) {
|
|
1918
|
+
const body = await put.text().catch(() => "");
|
|
1919
|
+
throw new Error(`azure batch synthesis submit ${put.status}: ${body.slice(0, 300)}`);
|
|
1920
|
+
}
|
|
1921
|
+
const deadline = Date.now() + (config.batchTimeoutMs ?? 18e4);
|
|
1922
|
+
let resultUrl = "";
|
|
1923
|
+
for (; ; ) {
|
|
1924
|
+
const get = await fetchImpl(`${host}/texttospeech/batchsyntheses/${id}?${api}`, {
|
|
1925
|
+
headers: { "Ocp-Apim-Subscription-Key": key() }
|
|
1926
|
+
});
|
|
1927
|
+
if (!get.ok) {
|
|
1928
|
+
const body = await get.text().catch(() => "");
|
|
1929
|
+
throw new Error(`azure batch synthesis poll ${get.status}: ${body.slice(0, 300)}`);
|
|
1930
|
+
}
|
|
1931
|
+
const job = await get.json();
|
|
1932
|
+
if (job.status === "Succeeded") {
|
|
1933
|
+
resultUrl = job.outputs?.result ?? "";
|
|
1934
|
+
break;
|
|
1935
|
+
}
|
|
1936
|
+
if (job.status === "Failed") throw new Error(`azure batch synthesis ${id} failed`);
|
|
1937
|
+
if (Date.now() > deadline) {
|
|
1938
|
+
throw new Error(
|
|
1939
|
+
`azure batch synthesis ${id} still "${job.status}" after ${Math.round((config.batchTimeoutMs ?? 18e4) / 1e3)}s`
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
await new Promise((r) => setTimeout(r, config.batchPollMs ?? 3e3));
|
|
1943
|
+
}
|
|
1944
|
+
if (!resultUrl) throw new Error(`azure batch synthesis ${id} succeeded without a result URL`);
|
|
1945
|
+
const zipRes = await fetchImpl(resultUrl, { headers: { "Ocp-Apim-Subscription-Key": key() } });
|
|
1946
|
+
if (!zipRes.ok) {
|
|
1947
|
+
throw new Error(`azure batch synthesis results ${zipRes.status}`);
|
|
1948
|
+
}
|
|
1949
|
+
const zip = new Uint8Array(await zipRes.arrayBuffer());
|
|
1950
|
+
const audio = readZipEntry(zip, "0001.wav");
|
|
1951
|
+
if (!audio) {
|
|
1952
|
+
throw new Error(`azure batch synthesis: no 0001.wav in results; archive holds ${listZipEntries(zip).join(", ")}`);
|
|
1953
|
+
}
|
|
1954
|
+
const wordsRaw = readZipEntry(zip, "0001.word.json");
|
|
1955
|
+
if (!wordsRaw) {
|
|
1956
|
+
throw new Error(
|
|
1957
|
+
`azure batch synthesis: wordTimings was requested but the archive has no 0001.word.json; it holds ${listZipEntries(zip).join(", ")}`
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
const boundaries = JSON.parse(new TextDecoder().decode(wordsRaw));
|
|
1961
|
+
return {
|
|
1962
|
+
audio,
|
|
1963
|
+
// Batch defaults to riff PCM, not mp3 — saying audio/mpeg here would be a lie the
|
|
1964
|
+
// browser would act on.
|
|
1965
|
+
mimeType: req.format?.includes("mp3") ? "audio/mpeg" : "audio/wav",
|
|
1966
|
+
// Aligned against the ORIGINAL text, with the dictionary, so the offsets index the
|
|
1967
|
+
// manuscript rather than the SSML we sent.
|
|
1968
|
+
wordTimings: alignWordTimings(req.text, boundaries, { pronunciations: req.pronunciations }),
|
|
1969
|
+
usage: priceFor(req.text.length, req.spec.model)
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1769
1972
|
async function transcribe(req) {
|
|
1770
1973
|
const locale = toAzureLocale(req.language);
|
|
1771
1974
|
const definition = { locales: [locale] };
|
|
@@ -3055,12 +3258,6 @@ var moderationInputSchema = z.object({
|
|
|
3055
3258
|
input: z.union([z.string(), z.array(z.string())]),
|
|
3056
3259
|
...callOptions
|
|
3057
3260
|
});
|
|
3058
|
-
var podcastInputSchema = z.object({
|
|
3059
|
-
script: z.array(z.object({ speaker: z.string(), text: z.string() })).min(1),
|
|
3060
|
-
voices: z.record(z.string(), z.string()),
|
|
3061
|
-
format: z.string().optional(),
|
|
3062
|
-
...callOptions
|
|
3063
|
-
});
|
|
3064
3261
|
var pronunciationSchema = z.object({
|
|
3065
3262
|
word: z.string(),
|
|
3066
3263
|
alias: z.string().optional(),
|
|
@@ -3069,12 +3266,24 @@ var pronunciationSchema = z.object({
|
|
|
3069
3266
|
/** F051.3 — also match inside a hyphenated compound ("AI" in "AI-agenter"). */
|
|
3070
3267
|
matchInCompounds: z.boolean().optional()
|
|
3071
3268
|
});
|
|
3269
|
+
var podcastInputSchema = z.object({
|
|
3270
|
+
script: z.array(z.object({ speaker: z.string(), text: z.string() })).min(1),
|
|
3271
|
+
voices: z.record(z.string(), z.string()),
|
|
3272
|
+
format: z.string().optional(),
|
|
3273
|
+
/** F051.4 — same field, same semantics as tts. Applied PER LINE: ElevenLabs'
|
|
3274
|
+
* /text-to-dialogue takes inputs[].text separately, so there is no composed string
|
|
3275
|
+
* a replacement could run across a speaker boundary in. */
|
|
3276
|
+
pronunciations: z.array(pronunciationSchema).optional(),
|
|
3277
|
+
...callOptions
|
|
3278
|
+
});
|
|
3072
3279
|
var ttsInputSchema = z.object({
|
|
3073
3280
|
text: z.string(),
|
|
3074
3281
|
voice: z.string(),
|
|
3075
3282
|
/** F051 — see TtsRequest.pronunciations. The alias/ipa exclusivity is enforced in
|
|
3076
3283
|
* the adapter, not here: the message must name the provider that cannot do it. */
|
|
3077
3284
|
pronunciations: z.array(pronunciationSchema).optional(),
|
|
3285
|
+
/** F055 — per-word timings (Azure only). Changes the route to batch synthesis. */
|
|
3286
|
+
wordTimings: z.boolean().optional(),
|
|
3078
3287
|
/** F037: voice to use if `voice` is one we know the provider has retired. Without
|
|
3079
3288
|
* it a retired voice throws VoiceUnavailableError rather than reaching the API.
|
|
3080
3289
|
*
|
|
@@ -3116,8 +3325,8 @@ var aiConfigSchema = z.object({
|
|
|
3116
3325
|
});
|
|
3117
3326
|
|
|
3118
3327
|
// src/version.ts
|
|
3119
|
-
var VERSION = "0.
|
|
3120
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
3328
|
+
var VERSION = "0.45.0";
|
|
3329
|
+
var SDK_TAG = "@broberg/ai-sdk@0.45.0";
|
|
3121
3330
|
|
|
3122
3331
|
// src/cost/sinks/upmetrics.ts
|
|
3123
3332
|
function upmetricsSink(config) {
|
|
@@ -3646,7 +3855,7 @@ function createAI(config = {}) {
|
|
|
3646
3855
|
invoke: async (spec) => {
|
|
3647
3856
|
const adapter = pickProvider(spec.provider);
|
|
3648
3857
|
if (!adapter.dialogue) throw new Error(`createAI: provider "${spec.provider}" does not support podcast/dialogue`);
|
|
3649
|
-
return adapter.dialogue({ inputs, format: input.format, spec });
|
|
3858
|
+
return adapter.dialogue({ inputs, format: input.format, pronunciations: input.pronunciations, spec });
|
|
3650
3859
|
}
|
|
3651
3860
|
});
|
|
3652
3861
|
},
|
|
@@ -3672,6 +3881,7 @@ function createAI(config = {}) {
|
|
|
3672
3881
|
format: input.format,
|
|
3673
3882
|
rate: input.rate,
|
|
3674
3883
|
pronunciations: input.pronunciations,
|
|
3884
|
+
wordTimings: input.wordTimings,
|
|
3675
3885
|
spec
|
|
3676
3886
|
});
|
|
3677
3887
|
}
|
|
@@ -4140,6 +4350,7 @@ export {
|
|
|
4140
4350
|
VERSION,
|
|
4141
4351
|
VoiceUnavailableError,
|
|
4142
4352
|
aiConfigSchema,
|
|
4353
|
+
alignWordTimings,
|
|
4143
4354
|
anthropicAdapter,
|
|
4144
4355
|
anthropicApiAdapter,
|
|
4145
4356
|
anthropicSubprocessAdapter,
|