@broberg/ai-sdk 0.7.0 → 0.8.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 +202 -4
- package/dist/index.js +134 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ interface TierSpec {
|
|
|
13
13
|
transport: Transport;
|
|
14
14
|
}
|
|
15
15
|
/** High-level capability a call exercises. Mirrors the capability layer (F5). */
|
|
16
|
-
type Capability = "chat" | "vision" | "video" | "translate" | "image" | "embedding" | "transcribe" | "ocr" | "moderation" | "mockup" | "design" | "extract" | "classify" | "rerank";
|
|
16
|
+
type Capability = "chat" | "vision" | "video" | "translate" | "image" | "embedding" | "transcribe" | "ocr" | "moderation" | "podcast" | "tts" | "mockup" | "design" | "extract" | "classify" | "rerank";
|
|
17
17
|
type Role = "system" | "user" | "assistant" | "tool";
|
|
18
18
|
/** A piece of message content. Text everywhere; image parts feed vision. */
|
|
19
19
|
type ContentPart = {
|
|
@@ -208,6 +208,27 @@ interface ModerationResult {
|
|
|
208
208
|
results: ModerationItem[];
|
|
209
209
|
usage: Usage;
|
|
210
210
|
}
|
|
211
|
+
interface DialogueTurn {
|
|
212
|
+
text: string;
|
|
213
|
+
voiceId: string;
|
|
214
|
+
}
|
|
215
|
+
interface DialogueRequest {
|
|
216
|
+
inputs: DialogueTurn[];
|
|
217
|
+
/** Output container, e.g. "mp3" (default). */
|
|
218
|
+
format?: string;
|
|
219
|
+
spec: TierSpec;
|
|
220
|
+
}
|
|
221
|
+
interface PodcastResult {
|
|
222
|
+
/** Episode audio bytes. */
|
|
223
|
+
audio: Uint8Array;
|
|
224
|
+
mimeType: string;
|
|
225
|
+
usage: Usage;
|
|
226
|
+
}
|
|
227
|
+
interface TtsRequest {
|
|
228
|
+
text: string;
|
|
229
|
+
voiceId: string;
|
|
230
|
+
spec: TierSpec;
|
|
231
|
+
}
|
|
211
232
|
/** The thin contract every provider implements (F4). A provider need only
|
|
212
233
|
* support the capabilities it offers — `chat` is the baseline; vision/image/
|
|
213
234
|
* embedding are optional and absence is a typed capability gap. */
|
|
@@ -226,6 +247,10 @@ interface ProviderAdapter {
|
|
|
226
247
|
transcribe?(req: TranscribeRequest): Promise<TranscribeResult>;
|
|
227
248
|
ocr?(req: OcrRequest): Promise<OcrResult>;
|
|
228
249
|
moderate?(req: ModerationRequest): Promise<ModerationResult>;
|
|
250
|
+
/** Multi-voice dialogue → one audio episode (F020). ElevenLabs. */
|
|
251
|
+
dialogue?(req: DialogueRequest): Promise<PodcastResult>;
|
|
252
|
+
/** Single-voice TTS (F020.4) → audio. ElevenLabs. */
|
|
253
|
+
tts?(req: TtsRequest): Promise<PodcastResult>;
|
|
229
254
|
}
|
|
230
255
|
interface TranslateResult {
|
|
231
256
|
text: string;
|
|
@@ -1130,6 +1155,154 @@ declare const moderationInputSchema: z.ZodObject<{
|
|
|
1130
1155
|
purpose?: string | undefined;
|
|
1131
1156
|
labels?: Record<string, string> | undefined;
|
|
1132
1157
|
}>;
|
|
1158
|
+
declare const podcastInputSchema: z.ZodObject<{
|
|
1159
|
+
tier: z.ZodOptional<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>>;
|
|
1160
|
+
override: z.ZodOptional<z.ZodObject<{
|
|
1161
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
1162
|
+
model: z.ZodOptional<z.ZodString>;
|
|
1163
|
+
transport: z.ZodOptional<z.ZodEnum<["http", "subprocess"]>>;
|
|
1164
|
+
}, "strip", z.ZodTypeAny, {
|
|
1165
|
+
provider?: string | undefined;
|
|
1166
|
+
model?: string | undefined;
|
|
1167
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1168
|
+
}, {
|
|
1169
|
+
provider?: string | undefined;
|
|
1170
|
+
model?: string | undefined;
|
|
1171
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1172
|
+
}>>;
|
|
1173
|
+
fallback: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>, z.ZodObject<{
|
|
1174
|
+
provider: z.ZodString;
|
|
1175
|
+
model: z.ZodString;
|
|
1176
|
+
transport: z.ZodEnum<["http", "subprocess"]>;
|
|
1177
|
+
}, "strip", z.ZodTypeAny, {
|
|
1178
|
+
provider: string;
|
|
1179
|
+
model: string;
|
|
1180
|
+
transport: "http" | "subprocess";
|
|
1181
|
+
}, {
|
|
1182
|
+
provider: string;
|
|
1183
|
+
model: string;
|
|
1184
|
+
transport: "http" | "subprocess";
|
|
1185
|
+
}>]>, "many">>;
|
|
1186
|
+
purpose: z.ZodOptional<z.ZodString>;
|
|
1187
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1188
|
+
script: z.ZodArray<z.ZodObject<{
|
|
1189
|
+
speaker: z.ZodString;
|
|
1190
|
+
text: z.ZodString;
|
|
1191
|
+
}, "strip", z.ZodTypeAny, {
|
|
1192
|
+
text: string;
|
|
1193
|
+
speaker: string;
|
|
1194
|
+
}, {
|
|
1195
|
+
text: string;
|
|
1196
|
+
speaker: string;
|
|
1197
|
+
}>, "many">;
|
|
1198
|
+
voices: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
1199
|
+
format: z.ZodOptional<z.ZodString>;
|
|
1200
|
+
}, "strip", z.ZodTypeAny, {
|
|
1201
|
+
script: {
|
|
1202
|
+
text: string;
|
|
1203
|
+
speaker: string;
|
|
1204
|
+
}[];
|
|
1205
|
+
voices: Record<string, string>;
|
|
1206
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1207
|
+
override?: {
|
|
1208
|
+
provider?: string | undefined;
|
|
1209
|
+
model?: string | undefined;
|
|
1210
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1211
|
+
} | undefined;
|
|
1212
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1213
|
+
provider: string;
|
|
1214
|
+
model: string;
|
|
1215
|
+
transport: "http" | "subprocess";
|
|
1216
|
+
})[] | undefined;
|
|
1217
|
+
purpose?: string | undefined;
|
|
1218
|
+
labels?: Record<string, string> | undefined;
|
|
1219
|
+
format?: string | undefined;
|
|
1220
|
+
}, {
|
|
1221
|
+
script: {
|
|
1222
|
+
text: string;
|
|
1223
|
+
speaker: string;
|
|
1224
|
+
}[];
|
|
1225
|
+
voices: Record<string, string>;
|
|
1226
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1227
|
+
override?: {
|
|
1228
|
+
provider?: string | undefined;
|
|
1229
|
+
model?: string | undefined;
|
|
1230
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1231
|
+
} | undefined;
|
|
1232
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1233
|
+
provider: string;
|
|
1234
|
+
model: string;
|
|
1235
|
+
transport: "http" | "subprocess";
|
|
1236
|
+
})[] | undefined;
|
|
1237
|
+
purpose?: string | undefined;
|
|
1238
|
+
labels?: Record<string, string> | undefined;
|
|
1239
|
+
format?: string | undefined;
|
|
1240
|
+
}>;
|
|
1241
|
+
declare const ttsInputSchema: z.ZodObject<{
|
|
1242
|
+
tier: z.ZodOptional<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>>;
|
|
1243
|
+
override: z.ZodOptional<z.ZodObject<{
|
|
1244
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
1245
|
+
model: z.ZodOptional<z.ZodString>;
|
|
1246
|
+
transport: z.ZodOptional<z.ZodEnum<["http", "subprocess"]>>;
|
|
1247
|
+
}, "strip", z.ZodTypeAny, {
|
|
1248
|
+
provider?: string | undefined;
|
|
1249
|
+
model?: string | undefined;
|
|
1250
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1251
|
+
}, {
|
|
1252
|
+
provider?: string | undefined;
|
|
1253
|
+
model?: string | undefined;
|
|
1254
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1255
|
+
}>>;
|
|
1256
|
+
fallback: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>, z.ZodObject<{
|
|
1257
|
+
provider: z.ZodString;
|
|
1258
|
+
model: z.ZodString;
|
|
1259
|
+
transport: z.ZodEnum<["http", "subprocess"]>;
|
|
1260
|
+
}, "strip", z.ZodTypeAny, {
|
|
1261
|
+
provider: string;
|
|
1262
|
+
model: string;
|
|
1263
|
+
transport: "http" | "subprocess";
|
|
1264
|
+
}, {
|
|
1265
|
+
provider: string;
|
|
1266
|
+
model: string;
|
|
1267
|
+
transport: "http" | "subprocess";
|
|
1268
|
+
}>]>, "many">>;
|
|
1269
|
+
purpose: z.ZodOptional<z.ZodString>;
|
|
1270
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1271
|
+
text: z.ZodString;
|
|
1272
|
+
voice: z.ZodString;
|
|
1273
|
+
}, "strip", z.ZodTypeAny, {
|
|
1274
|
+
text: string;
|
|
1275
|
+
voice: string;
|
|
1276
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1277
|
+
override?: {
|
|
1278
|
+
provider?: string | undefined;
|
|
1279
|
+
model?: string | undefined;
|
|
1280
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1281
|
+
} | undefined;
|
|
1282
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1283
|
+
provider: string;
|
|
1284
|
+
model: string;
|
|
1285
|
+
transport: "http" | "subprocess";
|
|
1286
|
+
})[] | undefined;
|
|
1287
|
+
purpose?: string | undefined;
|
|
1288
|
+
labels?: Record<string, string> | undefined;
|
|
1289
|
+
}, {
|
|
1290
|
+
text: string;
|
|
1291
|
+
voice: string;
|
|
1292
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1293
|
+
override?: {
|
|
1294
|
+
provider?: string | undefined;
|
|
1295
|
+
model?: string | undefined;
|
|
1296
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1297
|
+
} | undefined;
|
|
1298
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1299
|
+
provider: string;
|
|
1300
|
+
model: string;
|
|
1301
|
+
transport: "http" | "subprocess";
|
|
1302
|
+
})[] | undefined;
|
|
1303
|
+
purpose?: string | undefined;
|
|
1304
|
+
labels?: Record<string, string> | undefined;
|
|
1305
|
+
}>;
|
|
1133
1306
|
declare const aiConfigSchema: z.ZodObject<{
|
|
1134
1307
|
defaults: z.ZodOptional<z.ZodRecord<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>, z.ZodObject<{
|
|
1135
1308
|
provider: z.ZodString;
|
|
@@ -1190,6 +1363,8 @@ type EmbeddingInput = z.infer<typeof embeddingInputSchema>;
|
|
|
1190
1363
|
type TranscribeInput = z.infer<typeof transcribeInputSchema>;
|
|
1191
1364
|
type OcrInput = z.infer<typeof ocrInputSchema>;
|
|
1192
1365
|
type ModerationInput = z.infer<typeof moderationInputSchema>;
|
|
1366
|
+
type PodcastInput = z.infer<typeof podcastInputSchema>;
|
|
1367
|
+
type TtsInput = z.infer<typeof ttsInputSchema>;
|
|
1193
1368
|
type AiConfig = z.infer<typeof aiConfigSchema>;
|
|
1194
1369
|
/** The public facade. Defined here because it depends on the derived inputs. */
|
|
1195
1370
|
interface AiClient {
|
|
@@ -1208,6 +1383,10 @@ interface AiClient {
|
|
|
1208
1383
|
ocr(input: OcrInput): Promise<OcrResult>;
|
|
1209
1384
|
/** Moderation (F016.4) — classify text against safety categories. Mistral. */
|
|
1210
1385
|
moderate(input: ModerationInput): Promise<ModerationResult>;
|
|
1386
|
+
/** Podcast (F020) — a finished manuscript → one multi-voice audio episode. ElevenLabs. */
|
|
1387
|
+
podcast(input: PodcastInput): Promise<PodcastResult>;
|
|
1388
|
+
/** Single-voice TTS (F020.4) — text → audio. `voice` = curated name or voiceId. ElevenLabs. */
|
|
1389
|
+
tts(input: TtsInput): Promise<PodcastResult>;
|
|
1211
1390
|
/** Prompt-contract capabilities (F5.5) layered on chat/vision. */
|
|
1212
1391
|
contracts: Contracts;
|
|
1213
1392
|
}
|
|
@@ -1263,6 +1442,25 @@ declare function mistralAdapter(config?: {
|
|
|
1263
1442
|
pricePerPage?: number;
|
|
1264
1443
|
}): ProviderAdapter;
|
|
1265
1444
|
|
|
1445
|
+
/** Curated Danish voices (F020.3) — friendly name → ElevenLabs voiceId. Apps can
|
|
1446
|
+
* pass these names to `ai.podcast`/`ai.tts` instead of raw IDs. */
|
|
1447
|
+
declare const ELEVENLABS_DANISH_VOICES: Record<string, string>;
|
|
1448
|
+
/** Resolve a curated voice name to its voiceId; pass a raw voiceId through unchanged. */
|
|
1449
|
+
declare function resolveVoice(nameOrId: string): string;
|
|
1450
|
+
interface ElevenLabsVoice {
|
|
1451
|
+
voiceId: string;
|
|
1452
|
+
name: string;
|
|
1453
|
+
language?: string;
|
|
1454
|
+
}
|
|
1455
|
+
declare function elevenlabsAdapter(config?: {
|
|
1456
|
+
apiKey?: string;
|
|
1457
|
+
baseUrl?: string;
|
|
1458
|
+
fetch?: typeof fetch;
|
|
1459
|
+
pricePer1kChars?: number;
|
|
1460
|
+
}): ProviderAdapter & {
|
|
1461
|
+
listVoices(): Promise<ElevenLabsVoice[]>;
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1266
1464
|
interface FalAdapterConfig {
|
|
1267
1465
|
apiKey?: string;
|
|
1268
1466
|
/** "sync" (default — fal.run, fast models) or "queue" (queue.fal.run, polled). */
|
|
@@ -1310,8 +1508,8 @@ declare const falStubAdapter: ProviderAdapter;
|
|
|
1310
1508
|
* wires the live adapters. */
|
|
1311
1509
|
declare const stubProviders: Record<string, ProviderAdapter>;
|
|
1312
1510
|
|
|
1313
|
-
declare const VERSION: "0.
|
|
1314
|
-
declare const SDK_TAG: "@broberg/ai-sdk@0.
|
|
1511
|
+
declare const VERSION: "0.8.0";
|
|
1512
|
+
declare const SDK_TAG: "@broberg/ai-sdk@0.8.0";
|
|
1315
1513
|
|
|
1316
1514
|
/** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
|
|
1317
1515
|
* per-call override. Model IDs are current at scaffold time; callers pin their
|
|
@@ -1504,4 +1702,4 @@ interface StreamTransportRequest extends TransportRequest {
|
|
|
1504
1702
|
*/
|
|
1505
1703
|
declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
|
|
1506
1704
|
|
|
1507
|
-
export { type AiClient, type AiConfig, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostSink, type CostSummary, DEFAULT_TIER_MAP, type DesignInput, type DesignResult, type DiscordSinkConfig, type EmbeddingInput, type EmbeddingRequest, type EmbeddingResult, type ExtractInput, type ExtractResult, type FalAdapterConfig, type HttpResponse, type ImageInput, type ImageRequest, type ImageResult, 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 PricingEntry, type ProviderAdapter, type RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, chatInputSchema, computeCost, createAI, deepinfraAdapter, defaultProviders, discordSink, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, resolveTier, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
|
1705
|
+
export { type AiClient, type AiConfig, type BudgetConfig, BudgetExceededError, BudgetGuard, type BudgetStore, type CallOptions, type Capability, type ChatInput, type ChatRequest, type ChatResult, type ChatStreamEvent, type ClassifyInput, type ClassifyResult, type ContentPart, type Contracts, type CostSink, type CostSummary, 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 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 RerankInput, type RerankResult, type Role, SDK_TAG, type SqliteBudgetStoreConfig, type SqliteSinkConfig, StreamHttpError, type SubprocessResponse, type Tier, type TierSpec, type Tool, type ToolCall, type TranscribeInput, type TranscribeRequest, type TranscribeResult, type TranslateInput, type TranslateResult, type Transport, type TransportRequest, type TransportResponse, type TtsInput, type TtsRequest, type UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, chatInputSchema, computeCost, createAI, deepinfraAdapter, defaultProviders, discordSink, elevenlabsAdapter, embeddingInputSchema, falAdapter, falStubAdapter, freshUsage, fromProviderToolCall, geminiAdapter, getCostSummary, getPrice, httpTransport, imageInputSchema, makeContracts, makeOpenAICompatibleAdapter, messageSchema, mistralAdapter, multiSink, noopSink, openaiAdapter, openaiStubAdapter, openrouterAdapter, parseClaudeCliJson, parseJsonLoose, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
package/dist/index.js
CHANGED
|
@@ -1100,6 +1100,79 @@ function mistralAdapter(config = {}) {
|
|
|
1100
1100
|
return { ...base, ocr, moderate };
|
|
1101
1101
|
}
|
|
1102
1102
|
|
|
1103
|
+
// src/providers/elevenlabs.ts
|
|
1104
|
+
var ELEVENLABS_PRICE_PER_1K_CHARS = 0.15;
|
|
1105
|
+
var ELEVENLABS_DANISH_VOICES = {
|
|
1106
|
+
soren: "xj6X4BCUsv9oxohm1E8o",
|
|
1107
|
+
jesper: "Bl1YwS3uJac5zEOSNESn",
|
|
1108
|
+
mads: "BIWC0507fYMfhPcAEIRP",
|
|
1109
|
+
noam: "V34B5u5UbLdNJVEkcgXp",
|
|
1110
|
+
camilla: "4RklGmuxoAskAbGXplXN"
|
|
1111
|
+
};
|
|
1112
|
+
function resolveVoice(nameOrId) {
|
|
1113
|
+
return ELEVENLABS_DANISH_VOICES[nameOrId] ?? nameOrId;
|
|
1114
|
+
}
|
|
1115
|
+
function elevenlabsAdapter(config = {}) {
|
|
1116
|
+
const baseUrl = config.baseUrl ?? "https://api.elevenlabs.io/v1";
|
|
1117
|
+
const fetchImpl = config.fetch ?? fetch;
|
|
1118
|
+
function key() {
|
|
1119
|
+
const k = config.apiKey ?? process.env.ELEVENLABS_API_KEY;
|
|
1120
|
+
if (!k) throw new Error("elevenlabs adapter: API key not set (env ELEVENLABS_API_KEY)");
|
|
1121
|
+
return k;
|
|
1122
|
+
}
|
|
1123
|
+
function priceFor(chars, model) {
|
|
1124
|
+
const usage = freshUsage({
|
|
1125
|
+
provider: "elevenlabs",
|
|
1126
|
+
model,
|
|
1127
|
+
transport: "http",
|
|
1128
|
+
capability: "podcast",
|
|
1129
|
+
inputTokens: 0,
|
|
1130
|
+
outputTokens: 0
|
|
1131
|
+
});
|
|
1132
|
+
usage.costUsd = chars / 1e3 * (config.pricePer1kChars ?? ELEVENLABS_PRICE_PER_1K_CHARS);
|
|
1133
|
+
return usage;
|
|
1134
|
+
}
|
|
1135
|
+
async function dialogue(req) {
|
|
1136
|
+
const res = await fetchImpl(`${baseUrl}/text-to-dialogue`, {
|
|
1137
|
+
method: "POST",
|
|
1138
|
+
headers: { "xi-api-key": key(), "content-type": "application/json", accept: "audio/mpeg" },
|
|
1139
|
+
body: JSON.stringify({
|
|
1140
|
+
model_id: req.spec.model,
|
|
1141
|
+
inputs: req.inputs.map((t) => ({ text: t.text, voice_id: t.voiceId })),
|
|
1142
|
+
...req.format ? { output_format: req.format } : {}
|
|
1143
|
+
})
|
|
1144
|
+
});
|
|
1145
|
+
if (!res.ok) {
|
|
1146
|
+
const body = await res.text().catch(() => "");
|
|
1147
|
+
throw new Error(`elevenlabs dialogue ${res.status}: ${body.slice(0, 300)}`);
|
|
1148
|
+
}
|
|
1149
|
+
const audio = new Uint8Array(await res.arrayBuffer());
|
|
1150
|
+
const chars = req.inputs.reduce((n, t) => n + t.text.length, 0);
|
|
1151
|
+
return { audio, mimeType: "audio/mpeg", usage: priceFor(chars, req.spec.model) };
|
|
1152
|
+
}
|
|
1153
|
+
async function tts(req) {
|
|
1154
|
+
const model = req.spec.model;
|
|
1155
|
+
const res = await fetchImpl(`${baseUrl}/text-to-speech/${req.voiceId}`, {
|
|
1156
|
+
method: "POST",
|
|
1157
|
+
headers: { "xi-api-key": key(), "content-type": "application/json", accept: "audio/mpeg" },
|
|
1158
|
+
body: JSON.stringify({ text: req.text, model_id: model })
|
|
1159
|
+
});
|
|
1160
|
+
if (!res.ok) {
|
|
1161
|
+
const body = await res.text().catch(() => "");
|
|
1162
|
+
throw new Error(`elevenlabs tts ${res.status}: ${body.slice(0, 300)}`);
|
|
1163
|
+
}
|
|
1164
|
+
const audio = new Uint8Array(await res.arrayBuffer());
|
|
1165
|
+
return { audio, mimeType: "audio/mpeg", usage: priceFor(req.text.length, model) };
|
|
1166
|
+
}
|
|
1167
|
+
async function listVoices() {
|
|
1168
|
+
const res = await fetchImpl(`${baseUrl}/voices`, { headers: { "xi-api-key": key() } });
|
|
1169
|
+
if (!res.ok) throw new Error(`elevenlabs voices ${res.status}`);
|
|
1170
|
+
const data = await res.json();
|
|
1171
|
+
return (data.voices ?? []).map((v) => ({ voiceId: v.voice_id, name: v.name, language: v.labels?.language }));
|
|
1172
|
+
}
|
|
1173
|
+
return { name: "elevenlabs", dialogue, tts, listVoices };
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1103
1176
|
// src/providers/fal.ts
|
|
1104
1177
|
var FAL_IMAGE_PRICE_ESTIMATE = {
|
|
1105
1178
|
"fal-ai/flux/schnell": 3e-3,
|
|
@@ -1188,6 +1261,7 @@ var defaultProviders = {
|
|
|
1188
1261
|
deepinfra: deepinfraAdapter(),
|
|
1189
1262
|
openrouter: openrouterAdapter(),
|
|
1190
1263
|
mistral: mistralAdapter(),
|
|
1264
|
+
elevenlabs: elevenlabsAdapter(),
|
|
1191
1265
|
fal: falAdapter()
|
|
1192
1266
|
};
|
|
1193
1267
|
|
|
@@ -1510,6 +1584,17 @@ var moderationInputSchema = z.object({
|
|
|
1510
1584
|
input: z.union([z.string(), z.array(z.string())]),
|
|
1511
1585
|
...callOptions
|
|
1512
1586
|
});
|
|
1587
|
+
var podcastInputSchema = z.object({
|
|
1588
|
+
script: z.array(z.object({ speaker: z.string(), text: z.string() })).min(1),
|
|
1589
|
+
voices: z.record(z.string(), z.string()),
|
|
1590
|
+
format: z.string().optional(),
|
|
1591
|
+
...callOptions
|
|
1592
|
+
});
|
|
1593
|
+
var ttsInputSchema = z.object({
|
|
1594
|
+
text: z.string(),
|
|
1595
|
+
voice: z.string(),
|
|
1596
|
+
...callOptions
|
|
1597
|
+
});
|
|
1513
1598
|
var budgetSchema = z.object({
|
|
1514
1599
|
perCallUsd: z.number().positive().optional(),
|
|
1515
1600
|
rollingUsd: z.number().positive().optional()
|
|
@@ -1531,6 +1616,8 @@ var DEFAULT_IMAGE_SPEC = {
|
|
|
1531
1616
|
};
|
|
1532
1617
|
var DEFAULT_OCR_SPEC = { provider: "mistral", model: "mistral-ocr-latest", transport: "http" };
|
|
1533
1618
|
var DEFAULT_MODERATION_SPEC = { provider: "mistral", model: "mistral-moderation-latest", transport: "http" };
|
|
1619
|
+
var DEFAULT_PODCAST_SPEC = { provider: "elevenlabs", model: "eleven_v3", transport: "http" };
|
|
1620
|
+
var DEFAULT_TTS_SPEC = { provider: "elevenlabs", model: "eleven_multilingual_v2", transport: "http" };
|
|
1534
1621
|
function createAI(config = {}) {
|
|
1535
1622
|
const cfg = aiConfigSchema.parse(config);
|
|
1536
1623
|
const providers = cfg.providers ?? defaultProviders;
|
|
@@ -1810,6 +1897,48 @@ function createAI(config = {}) {
|
|
|
1810
1897
|
}
|
|
1811
1898
|
});
|
|
1812
1899
|
},
|
|
1900
|
+
async podcast(input) {
|
|
1901
|
+
input = podcastInputSchema.parse(input);
|
|
1902
|
+
const inputs = input.script.map((turn) => {
|
|
1903
|
+
const mapped = input.voices[turn.speaker];
|
|
1904
|
+
if (!mapped) throw new Error(`ai.podcast: no voice mapped for speaker "${turn.speaker}"`);
|
|
1905
|
+
return { text: turn.text, voiceId: resolveVoice(mapped) };
|
|
1906
|
+
});
|
|
1907
|
+
const chars = input.script.reduce((n, t) => n + t.text.length, 0);
|
|
1908
|
+
return runCapability({
|
|
1909
|
+
primary: { ...DEFAULT_PODCAST_SPEC, ...input.override },
|
|
1910
|
+
fallback: input.fallback,
|
|
1911
|
+
capability: "podcast",
|
|
1912
|
+
purpose: input.purpose,
|
|
1913
|
+
labels: input.labels,
|
|
1914
|
+
estIn: chars,
|
|
1915
|
+
// per-character cost (not token-based)
|
|
1916
|
+
estOut: 0,
|
|
1917
|
+
invoke: async (spec) => {
|
|
1918
|
+
const adapter = pickProvider(spec.provider);
|
|
1919
|
+
if (!adapter.dialogue) throw new Error(`createAI: provider "${spec.provider}" does not support podcast/dialogue`);
|
|
1920
|
+
return adapter.dialogue({ inputs, format: input.format, spec });
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
},
|
|
1924
|
+
async tts(input) {
|
|
1925
|
+
input = ttsInputSchema.parse(input);
|
|
1926
|
+
return runCapability({
|
|
1927
|
+
primary: { ...DEFAULT_TTS_SPEC, ...input.override },
|
|
1928
|
+
fallback: input.fallback,
|
|
1929
|
+
capability: "tts",
|
|
1930
|
+
purpose: input.purpose,
|
|
1931
|
+
labels: input.labels,
|
|
1932
|
+
estIn: input.text.length,
|
|
1933
|
+
// per-character cost
|
|
1934
|
+
estOut: 0,
|
|
1935
|
+
invoke: async (spec) => {
|
|
1936
|
+
const adapter = pickProvider(spec.provider);
|
|
1937
|
+
if (!adapter.tts) throw new Error(`createAI: provider "${spec.provider}" does not support tts`);
|
|
1938
|
+
return adapter.tts({ text: input.text, voiceId: resolveVoice(input.voice), spec });
|
|
1939
|
+
}
|
|
1940
|
+
});
|
|
1941
|
+
},
|
|
1813
1942
|
async embedding(input) {
|
|
1814
1943
|
input = embeddingInputSchema.parse(input);
|
|
1815
1944
|
const tier = input.tier ?? EMBEDDING_DEFAULT_TIER;
|
|
@@ -1936,8 +2065,8 @@ var stubProviders = {
|
|
|
1936
2065
|
};
|
|
1937
2066
|
|
|
1938
2067
|
// src/version.ts
|
|
1939
|
-
var VERSION = "0.
|
|
1940
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
2068
|
+
var VERSION = "0.8.0";
|
|
2069
|
+
var SDK_TAG = "@broberg/ai-sdk@0.8.0";
|
|
1941
2070
|
|
|
1942
2071
|
// src/cost/budget-store.ts
|
|
1943
2072
|
function sqliteBudgetStore(config) {
|
|
@@ -2169,6 +2298,7 @@ export {
|
|
|
2169
2298
|
BudgetExceededError,
|
|
2170
2299
|
BudgetGuard,
|
|
2171
2300
|
DEFAULT_TIER_MAP,
|
|
2301
|
+
ELEVENLABS_DANISH_VOICES,
|
|
2172
2302
|
SDK_TAG,
|
|
2173
2303
|
StreamHttpError,
|
|
2174
2304
|
VERSION,
|
|
@@ -2182,6 +2312,7 @@ export {
|
|
|
2182
2312
|
deepinfraAdapter,
|
|
2183
2313
|
defaultProviders,
|
|
2184
2314
|
discordSink,
|
|
2315
|
+
elevenlabsAdapter,
|
|
2185
2316
|
embeddingInputSchema,
|
|
2186
2317
|
falAdapter,
|
|
2187
2318
|
falStubAdapter,
|
|
@@ -2204,6 +2335,7 @@ export {
|
|
|
2204
2335
|
parseClaudeCliJson,
|
|
2205
2336
|
parseJsonLoose,
|
|
2206
2337
|
resolveTier,
|
|
2338
|
+
resolveVoice,
|
|
2207
2339
|
sqliteBudgetStore,
|
|
2208
2340
|
sqliteSink,
|
|
2209
2341
|
streamTransport,
|