@picsart/ai-sdk 6.15.0 → 6.16.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/README.md +29 -0
- package/index.d.ts +51 -12
- package/index.js +179 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -153,6 +153,35 @@ const folders = await ai.drive.folders()
|
|
|
153
153
|
const items = await ai.drive.list()
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
Generated Drive assets carry `model` and JSON `aiSDKPayload` automatically. Both
|
|
157
|
+
`generate()` and `submit()` record the original SDK inputs; custom Drive attributes
|
|
158
|
+
cannot replace that provenance. These are requested inputs, not a claim that every
|
|
159
|
+
provider default or rewritten prompt has been recovered. The stored prompt is capped
|
|
160
|
+
at 18,000 characters without changing the prompt sent to generation.
|
|
161
|
+
|
|
162
|
+
`apis.run()` remains a direct vendor API pass-through. It does not apply the client’s
|
|
163
|
+
Drive configuration or derive SDK metadata, even when a vendor payload explicitly
|
|
164
|
+
requests Drive saving. Vendor-shaped inputs must never be stored as `aiSDKPayload`;
|
|
165
|
+
that attribute is reserved for original SDK-shaped inputs.
|
|
166
|
+
|
|
167
|
+
For a separate or delayed save, pass the original generation context:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
await ai.drive.save({
|
|
171
|
+
url: generatedUrl,
|
|
172
|
+
name: 'clip.mp4',
|
|
173
|
+
resourceType: 'VIDEO',
|
|
174
|
+
generation: { modelId, params: originalGenerationParams },
|
|
175
|
+
})
|
|
176
|
+
// The existing helper also accepts a full params object instead of just a prompt:
|
|
177
|
+
const saveParams = ai.drive.buildSaveParams(generatedUrl, modelId, modelName, 'video', originalGenerationParams)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Legacy `model`/`prompt`/`textScript` saves are normalized at write time. URL-only
|
|
181
|
+
uploads remain ordinary uploads: without generation context the SDK cannot infer
|
|
182
|
+
model, prompt or settings. Existing Drive files are not backfilled. The backend preserves SDK-supplied metadata; it cannot reconstruct SDK input
|
|
183
|
+
names or catalog model IDs from an arbitrary vendor request.
|
|
184
|
+
|
|
156
185
|
## Text Generation (LLMs)
|
|
157
186
|
|
|
158
187
|
Claude, GPT, and Gemini text models are called with `generateText()`. Single-shot:
|
package/index.d.ts
CHANGED
|
@@ -349,14 +349,30 @@ type ModelInputById = {
|
|
|
349
349
|
"gemini-2.5-flash-tts": {
|
|
350
350
|
language?: string;
|
|
351
351
|
accent?: string;
|
|
352
|
-
prompt
|
|
352
|
+
prompt?: string;
|
|
353
353
|
voiceId?: string;
|
|
354
|
+
parts?: Array<{
|
|
355
|
+
text: string;
|
|
356
|
+
speaker?: string;
|
|
357
|
+
}>;
|
|
358
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
359
|
+
speaker: string;
|
|
360
|
+
voiceName: string;
|
|
361
|
+
}>;
|
|
354
362
|
};
|
|
355
363
|
"gemini-2.5-pro-tts": {
|
|
356
364
|
language?: string;
|
|
357
365
|
accent?: string;
|
|
358
|
-
prompt
|
|
366
|
+
prompt?: string;
|
|
359
367
|
voiceId?: string;
|
|
368
|
+
parts?: Array<{
|
|
369
|
+
text: string;
|
|
370
|
+
speaker?: string;
|
|
371
|
+
}>;
|
|
372
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
373
|
+
speaker: string;
|
|
374
|
+
voiceName: string;
|
|
375
|
+
}>;
|
|
360
376
|
};
|
|
361
377
|
"gemini-3-pro": {
|
|
362
378
|
prompt: string;
|
|
@@ -412,14 +428,34 @@ type ModelInputById = {
|
|
|
412
428
|
"gemini-3.8-flash-lite-tts": {
|
|
413
429
|
language?: string;
|
|
414
430
|
accent?: string;
|
|
415
|
-
prompt
|
|
431
|
+
prompt?: string;
|
|
416
432
|
voiceId?: string;
|
|
433
|
+
style?: string;
|
|
434
|
+
parts?: Array<{
|
|
435
|
+
text: string;
|
|
436
|
+
speaker?: string;
|
|
437
|
+
style?: string;
|
|
438
|
+
}>;
|
|
439
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
440
|
+
speaker: string;
|
|
441
|
+
voiceName: string;
|
|
442
|
+
}>;
|
|
417
443
|
};
|
|
418
444
|
"gemini-3.8-flash-tts": {
|
|
419
445
|
language?: string;
|
|
420
446
|
accent?: string;
|
|
421
|
-
prompt
|
|
447
|
+
prompt?: string;
|
|
422
448
|
voiceId?: string;
|
|
449
|
+
style?: string;
|
|
450
|
+
parts?: Array<{
|
|
451
|
+
text: string;
|
|
452
|
+
speaker?: string;
|
|
453
|
+
style?: string;
|
|
454
|
+
}>;
|
|
455
|
+
multiSpeakerVoiceConfigs?: Array<{
|
|
456
|
+
speaker: string;
|
|
457
|
+
voiceName: string;
|
|
458
|
+
}>;
|
|
423
459
|
};
|
|
424
460
|
"gemini-omni-1.1-flash-preview": {
|
|
425
461
|
prompt: string;
|
|
@@ -2668,11 +2704,19 @@ interface ListOptions {
|
|
|
2668
2704
|
folder?: DriveFolder;
|
|
2669
2705
|
type?: MediaTypeFilter;
|
|
2670
2706
|
}
|
|
2707
|
+
/** Original generation inputs, portable across clients and delayed Drive saves. */
|
|
2708
|
+
interface GenerationProvenance {
|
|
2709
|
+
modelId: string;
|
|
2710
|
+
params: Record<string, unknown>;
|
|
2711
|
+
app?: AppIdentity;
|
|
2712
|
+
}
|
|
2671
2713
|
interface SaveParams {
|
|
2672
2714
|
url: string;
|
|
2673
2715
|
name: string;
|
|
2674
2716
|
resourceType: 'PHOTO' | 'VIDEO' | 'AUDIO';
|
|
2675
2717
|
attributes?: Record<string, string>;
|
|
2718
|
+
/** Required to retain full provenance when saving a generated URL separately. */
|
|
2719
|
+
generation?: GenerationProvenance;
|
|
2676
2720
|
previewUrl?: string;
|
|
2677
2721
|
}
|
|
2678
2722
|
/** Target folder for backend Drive save. */
|
|
@@ -2714,7 +2758,7 @@ interface DriveClient {
|
|
|
2714
2758
|
/** Save an asset to Drive. */
|
|
2715
2759
|
save(params: SaveParams, folder?: DriveFolder): Promise<DriveSaveResult | null>;
|
|
2716
2760
|
/** Build the save params for a generation result. */
|
|
2717
|
-
buildSaveParams(url: string, modelId: string, modelName: string, mode: string,
|
|
2761
|
+
buildSaveParams(url: string, modelId: string, modelName: string, mode: string, promptOrParams?: string | Record<string, unknown>): SaveParams;
|
|
2718
2762
|
/** Set a like/dislike reaction on a file. */
|
|
2719
2763
|
addReaction(fileUid: string, reaction: UserReaction): Promise<boolean>;
|
|
2720
2764
|
/** Clear the reaction on a file. */
|
|
@@ -2744,12 +2788,7 @@ declare function resolveExtension(mode: string, hints?: FilenameHints): string;
|
|
|
2744
2788
|
*/
|
|
2745
2789
|
declare function expectedOutputFormat(model: Pick<ModelDefinition, 'paramConfig' | 'outputExtension'>, params: Record<string, unknown>): string | undefined;
|
|
2746
2790
|
declare function buildFilename(prompt: string | undefined, mode: string, hints?: FilenameHints): string;
|
|
2747
|
-
declare function buildGenerationAttributes(input:
|
|
2748
|
-
modelId: string;
|
|
2749
|
-
params: Record<string, unknown>;
|
|
2750
|
-
/** TODO(backend-autosave): temporary — remove once the backend stamps appId/appType. */
|
|
2751
|
-
app?: AppIdentity;
|
|
2752
|
-
}): DriveAttributes;
|
|
2791
|
+
declare function buildGenerationAttributes(input: GenerationProvenance): DriveAttributes;
|
|
2753
2792
|
declare function parseGeneration(file: DriveFile | Record<string, unknown>): GenerationFile;
|
|
2754
2793
|
|
|
2755
2794
|
/** Result of `ai.apis.run()` — the API result plus optional credit usage. */
|
|
@@ -3545,4 +3584,4 @@ declare const getModel: (id: string) => ModelDefinition | undefined;
|
|
|
3545
3584
|
*/
|
|
3546
3585
|
declare const findModel: (ref: string) => ModelDefinition | undefined;
|
|
3547
3586
|
|
|
3548
|
-
export { ALL_MODELS, type AiClient, ApiError, type ApiErrorCode, type ApiErrorInit, type ApiResponse, type ApiRunOptions, type ApiSchemas, type ApisClient, type AppIdentity, type AppType, type AuthenticatedFetch, type AvatarOption, type BooleanDescriptor, type BooleanEntry, type CatalogDescriptor, type CatalogEntry, type CatalogItem, type CatalogPage, type CatalogPageOptions, type CatalogPreview, type CatalogQuery, type CatalogResult, type CatalogSource, type CatalogsClient, type CatalogsOptions, type ClientConfig, type CreditRange, type CreditRangeContext, type CreditTier, type CreditUsage, DEFAULT_VISIBLE_RELEASES, type DeepLinkResult, type DriveAttributes, type DriveClient, type DriveConfig, type DriveDraftInfo, type DriveFile, type DriveFileDetails, type DriveFolder, type DriveMediaItem, type DriveSaveResult, type EntryMeta, type EnumDescriptor, type EnumEntry, type EnumOption, type FileDescriptor, type FileEntry, type FlatParamEntry, type GenerateOptions, type GenerateResult, type GenerateResultItem, type GenerateResultItemMetadata, type GenerateTextResult, type GenerationContext, type GenerationEvent, GenerationEventType, type GenerationFile, type GenerationMode, type GenerationOptions, type GenerationProgress, type ListOptions, type MediaModelId, type MediaTypeFilter, Model, type ModelDefinition, type ModelDescriptor, type ModelFilter, type ModelInput, type ModelInputById, type ModelMeta, type ModelParams, type ModelParamsAccessor, Models, type ObjectDescriptor, type ObjectEntry, type ParamDescriptor, type ParamEntry, type ParamOption, type PayloadDriveFolderOptions, type PayloadDriveOptions, type PayloadInputsTransformationOptions, type PricingOptions, type ProviderInfo, type RangeDescriptor, type RangeEntry, type ReleaseTag, type SaveParams, type SdkPayload, type SdkTransport, type SeedanceDraftTask, type TextDescriptor, type TextEntry, type TextModelId, type TextModelInputById, type ToolUsage, type TransportPollOptions, type TransportResult, type TypedModelId, type UserReaction, type ValidationResult, type VoiceOption, type WorkflowJobHandle, type WorkflowSubmitRequest, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, expectedOutputFormat, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, resolveExtension, toAvatarOption, toVoiceOption };
|
|
3587
|
+
export { ALL_MODELS, type AiClient, ApiError, type ApiErrorCode, type ApiErrorInit, type ApiResponse, type ApiRunOptions, type ApiSchemas, type ApisClient, type AppIdentity, type AppType, type AuthenticatedFetch, type AvatarOption, type BooleanDescriptor, type BooleanEntry, type CatalogDescriptor, type CatalogEntry, type CatalogItem, type CatalogPage, type CatalogPageOptions, type CatalogPreview, type CatalogQuery, type CatalogResult, type CatalogSource, type CatalogsClient, type CatalogsOptions, type ClientConfig, type CreditRange, type CreditRangeContext, type CreditTier, type CreditUsage, DEFAULT_VISIBLE_RELEASES, type DeepLinkResult, type DriveAttributes, type DriveClient, type DriveConfig, type DriveDraftInfo, type DriveFile, type DriveFileDetails, type DriveFolder, type DriveMediaItem, type DriveSaveResult, type EntryMeta, type EnumDescriptor, type EnumEntry, type EnumOption, type FileDescriptor, type FileEntry, type FlatParamEntry, type GenerateOptions, type GenerateResult, type GenerateResultItem, type GenerateResultItemMetadata, type GenerateTextResult, type GenerationContext, type GenerationEvent, GenerationEventType, type GenerationFile, type GenerationMode, type GenerationOptions, type GenerationProgress, type GenerationProvenance, type ListOptions, type MediaModelId, type MediaTypeFilter, Model, type ModelDefinition, type ModelDescriptor, type ModelFilter, type ModelInput, type ModelInputById, type ModelMeta, type ModelParams, type ModelParamsAccessor, Models, type ObjectDescriptor, type ObjectEntry, type ParamDescriptor, type ParamEntry, type ParamOption, type PayloadDriveFolderOptions, type PayloadDriveOptions, type PayloadInputsTransformationOptions, type PricingOptions, type ProviderInfo, type RangeDescriptor, type RangeEntry, type ReleaseTag, type SaveParams, type SdkPayload, type SdkTransport, type SeedanceDraftTask, type TextDescriptor, type TextEntry, type TextModelId, type TextModelInputById, type ToolUsage, type TransportPollOptions, type TransportResult, type TypedModelId, type UserReaction, type ValidationResult, type VoiceOption, type WorkflowJobHandle, type WorkflowSubmitRequest, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, expectedOutputFormat, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, resolveExtension, toAvatarOption, toVoiceOption };
|
package/index.js
CHANGED
|
@@ -6453,11 +6453,6 @@ var buildGemini31FlashLiteImagePayload = (ctx) => ({
|
|
|
6453
6453
|
imageSize: ctx.resolution ?? "1K",
|
|
6454
6454
|
...buildThinkingConfig(ctx)
|
|
6455
6455
|
});
|
|
6456
|
-
var buildGeminiTTSPayload = (model) => (ctx) => ({
|
|
6457
|
-
text: ctx.prompt,
|
|
6458
|
-
model,
|
|
6459
|
-
voiceName: ctx.voiceId ?? "Kore"
|
|
6460
|
-
});
|
|
6461
6456
|
function inferMimeType2(url) {
|
|
6462
6457
|
return url.match(/\.png(\?|$)/i) ? "image/png" : "image/jpeg";
|
|
6463
6458
|
}
|
|
@@ -6469,6 +6464,52 @@ var buildGeminiOmniVideoPayload = (ctx) => ({
|
|
|
6469
6464
|
...ctx.imageUrls?.[0] ? { image: { url: ctx.imageUrls[0], mimeType: inferMimeType2(ctx.imageUrls[0]) } } : {},
|
|
6470
6465
|
...ctx.videoUrl ? { video: { url: ctx.videoUrl } } : {}
|
|
6471
6466
|
});
|
|
6467
|
+
var GEMINI_TTS_TEXT_MAX = 6e3;
|
|
6468
|
+
var GEMINI_TTS_STYLE_MAX = 500;
|
|
6469
|
+
var geminiTtsParams = (directable) => ({
|
|
6470
|
+
...params.language(true),
|
|
6471
|
+
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6472
|
+
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6473
|
+
...params.prompt({ required: false, maxLength: GEMINI_TTS_TEXT_MAX }),
|
|
6474
|
+
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } }),
|
|
6475
|
+
...directable ? {
|
|
6476
|
+
style: {
|
|
6477
|
+
label: "Style",
|
|
6478
|
+
descriptor: {
|
|
6479
|
+
kind: "text",
|
|
6480
|
+
maxLength: GEMINI_TTS_STYLE_MAX,
|
|
6481
|
+
placeholder: "e.g. warm, unhurried; a bedtime story"
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
6484
|
+
} : {},
|
|
6485
|
+
// Worker `SpeechPartDto[]`, same names. Used instead of `prompt`.
|
|
6486
|
+
parts: {
|
|
6487
|
+
label: "Spoken Parts",
|
|
6488
|
+
descriptor: {
|
|
6489
|
+
kind: "object",
|
|
6490
|
+
array: { min: 1, max: 200 },
|
|
6491
|
+
fields: {
|
|
6492
|
+
text: { label: "Text", kind: "text", maxLength: GEMINI_TTS_TEXT_MAX },
|
|
6493
|
+
speaker: { label: "Speaker", kind: "text", required: false },
|
|
6494
|
+
...directable ? { style: { label: "Style", kind: "text", maxLength: GEMINI_TTS_STYLE_MAX, required: false } } : {}
|
|
6495
|
+
}
|
|
6496
|
+
}
|
|
6497
|
+
},
|
|
6498
|
+
// Worker `SpeakerVoiceConfigDto[]`, max 2. Replaces `voiceId`. The voice is
|
|
6499
|
+
// a plain id, not a catalog picker: catalog loading resolves top-level params
|
|
6500
|
+
// only, so a caller lists voices with `ai.catalogs.voices(<model>)`.
|
|
6501
|
+
multiSpeakerVoiceConfigs: {
|
|
6502
|
+
label: "Speakers",
|
|
6503
|
+
descriptor: {
|
|
6504
|
+
kind: "object",
|
|
6505
|
+
array: { min: 1, max: 2 },
|
|
6506
|
+
fields: {
|
|
6507
|
+
speaker: { label: "Speaker", kind: "text", placeholder: "Speaker 1" },
|
|
6508
|
+
voiceName: { label: "Voice", kind: "text", placeholder: GEMINI_DEFAULT_VOICE_ID }
|
|
6509
|
+
}
|
|
6510
|
+
}
|
|
6511
|
+
}
|
|
6512
|
+
});
|
|
6472
6513
|
var GEMINI_AR_WIDE = ["1:1", "16:9", "9:16", "3:4", "4:3", "2:3", "21:9", "auto"];
|
|
6473
6514
|
var thinkingLevelParam = {
|
|
6474
6515
|
thinkingLevel: {
|
|
@@ -6586,32 +6627,35 @@ var { MODELS: MODELS22 } = defineModels("google", [
|
|
|
6586
6627
|
}
|
|
6587
6628
|
},
|
|
6588
6629
|
// ── Audio ─────────────────────────────────────────────────────────
|
|
6630
|
+
// Payload builders live in gemini.payloads.ts (typed against ModelInput).
|
|
6631
|
+
// The wire `model` is fixed per entry there: `modelId` is the pricing key and
|
|
6632
|
+
// never reaches the builder.
|
|
6633
|
+
//
|
|
6634
|
+
// 2.5 and 3.8 take direction and speakers differently, so the builders
|
|
6635
|
+
// resolve them per generation. 3.8 reads `style` and per-part speakers from
|
|
6636
|
+
// `speechMetadata` and speaks a natural-language prefix in the text aloud:
|
|
6637
|
+
// `parts` go through and `language` / `accent` fold into `style`. 2.5
|
|
6638
|
+
// ignores `speechMetadata`: it reads speakers from "Speaker: line" labels
|
|
6639
|
+
// and direction from a "Say …:" prefix, so the builder writes both into
|
|
6640
|
+
// one text.
|
|
6589
6641
|
{
|
|
6590
6642
|
id: "gemini-2.5-flash-tts",
|
|
6591
6643
|
name: "Gemini 2.5 Flash TTS",
|
|
6592
6644
|
addedAt: "2026-02-15",
|
|
6593
6645
|
workflow: "gemini/v1/audios",
|
|
6594
|
-
buildPayload: buildGeminiTTSPayload("gemini-2.5-flash-tts"),
|
|
6595
6646
|
estimatedTime: 15,
|
|
6596
6647
|
mode: "audio",
|
|
6597
6648
|
inputType: "tts",
|
|
6598
6649
|
modelId: "gemini-2.5-flash-tts",
|
|
6599
6650
|
description: "Google Gemini native text-to-speech with expressive multilingual voices.",
|
|
6600
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6601
|
-
paramConfig:
|
|
6602
|
-
...params.language(true),
|
|
6603
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6604
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6605
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6606
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6607
|
-
}
|
|
6651
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic")],
|
|
6652
|
+
paramConfig: geminiTtsParams(false)
|
|
6608
6653
|
},
|
|
6609
6654
|
{
|
|
6610
6655
|
id: "gemini-2.5-pro-tts",
|
|
6611
6656
|
name: "Gemini 2.5 Pro TTS",
|
|
6612
6657
|
addedAt: "2026-03-18",
|
|
6613
6658
|
workflow: "gemini/v1/audios",
|
|
6614
|
-
buildPayload: buildGeminiTTSPayload("gemini-2.5-pro-tts"),
|
|
6615
6659
|
estimatedTime: 20,
|
|
6616
6660
|
mode: "audio",
|
|
6617
6661
|
inputType: "tts",
|
|
@@ -6619,54 +6663,34 @@ var { MODELS: MODELS22 } = defineModels("google", [
|
|
|
6619
6663
|
badge: ["premium"],
|
|
6620
6664
|
description: "Premium Gemini TTS with richer expressiveness and multi-speaker support.",
|
|
6621
6665
|
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic")],
|
|
6622
|
-
paramConfig:
|
|
6623
|
-
...params.language(true),
|
|
6624
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6625
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6626
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6627
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6628
|
-
}
|
|
6666
|
+
paramConfig: geminiTtsParams(false)
|
|
6629
6667
|
},
|
|
6630
6668
|
{
|
|
6631
6669
|
id: "gemini-3.8-flash-tts",
|
|
6632
6670
|
name: "Gemini 3.8 Flash TTS",
|
|
6633
6671
|
addedAt: "2026-09-24",
|
|
6634
6672
|
workflow: "gemini/v1/audios",
|
|
6635
|
-
buildPayload: buildGeminiTTSPayload("gemini-3.8-flash-tts"),
|
|
6636
6673
|
estimatedTime: 15,
|
|
6637
6674
|
mode: "audio",
|
|
6638
6675
|
inputType: "tts",
|
|
6639
6676
|
modelId: "gemini-3.8-flash-tts",
|
|
6640
|
-
description: "Latest Gemini native text-to-speech with
|
|
6641
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6642
|
-
paramConfig:
|
|
6643
|
-
...params.language(true),
|
|
6644
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6645
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6646
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6647
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6648
|
-
}
|
|
6677
|
+
description: "Latest Gemini native text-to-speech with directable delivery and inline vocal events like <laugh> and <sigh>.",
|
|
6678
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic"), feat("Style Direction", "characteristic")],
|
|
6679
|
+
paramConfig: geminiTtsParams(true)
|
|
6649
6680
|
},
|
|
6650
6681
|
{
|
|
6651
6682
|
id: "gemini-3.8-flash-lite-tts",
|
|
6652
6683
|
name: "Gemini 3.8 Flash Lite TTS",
|
|
6653
6684
|
addedAt: "2026-09-24",
|
|
6654
6685
|
workflow: "gemini/v1/audios",
|
|
6655
|
-
buildPayload: buildGeminiTTSPayload("gemini-3.8-flash-lite-tts"),
|
|
6656
6686
|
estimatedTime: 12,
|
|
6657
6687
|
mode: "audio",
|
|
6658
6688
|
inputType: "tts",
|
|
6659
6689
|
modelId: "gemini-3.8-flash-lite-tts",
|
|
6660
6690
|
badge: ["fast"],
|
|
6661
|
-
description: "Lightweight Gemini 3.8 TTS
|
|
6662
|
-
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic")],
|
|
6663
|
-
paramConfig:
|
|
6664
|
-
...params.language(true),
|
|
6665
|
-
// 6,000 boundary-verified against the live gemini/v1/audios worker
|
|
6666
|
-
// (accepts >5,000; see scripts/api-tests/audio-charlimit-boundary-probe.mjs).
|
|
6667
|
-
...params.prompt({ maxLength: 6e3 }),
|
|
6668
|
-
...params.voiceId([], GEMINI_DEFAULT_VOICE_ID, { catalog: { workflow: "gemini/v1/catalog/voices" } })
|
|
6669
|
-
}
|
|
6691
|
+
description: "Lightweight Gemini 3.8 TTS with directable delivery for faster, high-volume speech synthesis.",
|
|
6692
|
+
features: [feat("Multilingual", "characteristic"), feat("30 Voices", "characteristic"), feat("Multi-Speaker", "characteristic"), feat("Style Direction", "characteristic")],
|
|
6693
|
+
paramConfig: geminiTtsParams(true)
|
|
6670
6694
|
},
|
|
6671
6695
|
// ── Video ─────────────────────────────────────────────────────────
|
|
6672
6696
|
{
|
|
@@ -6733,8 +6757,95 @@ var buildOmniFlash11Payload = (input) => ({
|
|
|
6733
6757
|
...input.videoUrl ? { video: { url: input.videoUrl } } : {},
|
|
6734
6758
|
...input.videoUrls?.length ? { referenceVideos: input.videoUrls.map((url) => ({ url })) } : {}
|
|
6735
6759
|
});
|
|
6760
|
+
var STYLE_MAX = 500;
|
|
6761
|
+
var TEXT_MAX = 6e3;
|
|
6762
|
+
var invalid = (message) => new ApiError(message, { status: 400, code: "validation_error" });
|
|
6763
|
+
var blank = (value) => !value?.trim();
|
|
6764
|
+
function checkInput(input) {
|
|
6765
|
+
const configs = input.multiSpeakerVoiceConfigs ?? [];
|
|
6766
|
+
for (const [i, config] of configs.entries()) {
|
|
6767
|
+
if (blank(config.speaker)) throw invalid(`Gemini TTS: speaker config ${i + 1} has no speaker.`);
|
|
6768
|
+
if (blank(config.voiceName)) throw invalid(`Gemini TTS: speaker config ${i + 1} has no voiceName.`);
|
|
6769
|
+
}
|
|
6770
|
+
const speakers = configs.map((config) => config.speaker);
|
|
6771
|
+
if (new Set(speakers).size !== speakers.length) {
|
|
6772
|
+
throw invalid("Gemini TTS: multiSpeakerVoiceConfigs names the same speaker twice.");
|
|
6773
|
+
}
|
|
6774
|
+
const parts = input.parts?.length ? input.parts : void 0;
|
|
6775
|
+
if (!parts) {
|
|
6776
|
+
if (blank(input.prompt)) throw invalid("Gemini TTS: provide a prompt or parts.");
|
|
6777
|
+
return { speakers };
|
|
6778
|
+
}
|
|
6779
|
+
for (const [i, part] of parts.entries()) {
|
|
6780
|
+
if (blank(part.text)) throw invalid(`Gemini TTS: part ${i + 1} has no text.`);
|
|
6781
|
+
if (speakers.length && (!part.speaker || !speakers.includes(part.speaker))) {
|
|
6782
|
+
throw invalid(
|
|
6783
|
+
`Gemini TTS: part ${i + 1} needs a speaker from multiSpeakerVoiceConfigs (${speakers.join(", ")}).`
|
|
6784
|
+
);
|
|
6785
|
+
}
|
|
6786
|
+
if (!speakers.length && part.speaker) {
|
|
6787
|
+
throw invalid(`Gemini TTS: part ${i + 1} names a speaker but no multiSpeakerVoiceConfigs are set.`);
|
|
6788
|
+
}
|
|
6789
|
+
}
|
|
6790
|
+
return { parts, speakers };
|
|
6791
|
+
}
|
|
6792
|
+
function assertLength(spoken) {
|
|
6793
|
+
if (spoken.length > TEXT_MAX) {
|
|
6794
|
+
throw invalid(`Gemini TTS: the text totals ${spoken.length} characters; the limit is ${TEXT_MAX}.`);
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6797
|
+
var voiceFields = (input) => input.multiSpeakerVoiceConfigs?.length ? { multiSpeakerVoiceConfigs: input.multiSpeakerVoiceConfigs } : { voiceName: input.voiceId ?? GEMINI_DEFAULT_VOICE_ID };
|
|
6798
|
+
function composeStyle(input) {
|
|
6799
|
+
const language = input.language?.trim();
|
|
6800
|
+
const accent = input.accent?.trim();
|
|
6801
|
+
const voice = language || accent ? `speak${language ? ` in ${language}` : ""}${accent ? ` with a ${accent} accent` : ""}` : void 0;
|
|
6802
|
+
const composed = [...input.styles.map((style) => style?.trim()), voice].filter(Boolean).join("; ") || void 0;
|
|
6803
|
+
if (composed && composed.length > STYLE_MAX) {
|
|
6804
|
+
throw invalid(`Gemini TTS: style with language/accent exceeds ${STYLE_MAX} characters.`);
|
|
6805
|
+
}
|
|
6806
|
+
return composed;
|
|
6807
|
+
}
|
|
6808
|
+
function directionPrefix(input) {
|
|
6809
|
+
const language = input.language?.trim();
|
|
6810
|
+
const accent = input.accent?.trim();
|
|
6811
|
+
if (!language && !accent) return "";
|
|
6812
|
+
return `Say${language ? ` in ${language}` : ""}${accent ? ` with a ${accent} accent` : ""}: `;
|
|
6813
|
+
}
|
|
6814
|
+
var buildTts25Payload = (model) => (input) => {
|
|
6815
|
+
const { parts, speakers } = checkInput(input);
|
|
6816
|
+
const body = parts ? parts.map((part) => speakers.length ? `${part.speaker}: ${part.text}` : part.text).join("\n") : input.prompt;
|
|
6817
|
+
const text = `${directionPrefix(input)}${body}`;
|
|
6818
|
+
assertLength(text);
|
|
6819
|
+
return { text, model, ...voiceFields(input) };
|
|
6820
|
+
};
|
|
6821
|
+
var buildTts38Payload = (model) => (input) => {
|
|
6822
|
+
const { parts } = checkInput(input);
|
|
6823
|
+
const direction = { language: input.language, accent: input.accent };
|
|
6824
|
+
if (!parts) {
|
|
6825
|
+
assertLength(input.prompt);
|
|
6826
|
+
const style = composeStyle({ styles: [input.style], ...direction });
|
|
6827
|
+
return { text: input.prompt, model, ...voiceFields(input), ...style ? { style } : {} };
|
|
6828
|
+
}
|
|
6829
|
+
assertLength(parts.map((part) => part.text).join("\n"));
|
|
6830
|
+
return {
|
|
6831
|
+
parts: parts.map((part) => {
|
|
6832
|
+
const style = composeStyle({ styles: [input.style, part.style], ...direction });
|
|
6833
|
+
return {
|
|
6834
|
+
text: part.text,
|
|
6835
|
+
...part.speaker ? { speaker: part.speaker } : {},
|
|
6836
|
+
...style ? { style } : {}
|
|
6837
|
+
};
|
|
6838
|
+
}),
|
|
6839
|
+
model,
|
|
6840
|
+
...voiceFields(input)
|
|
6841
|
+
};
|
|
6842
|
+
};
|
|
6736
6843
|
registerPayloads(MODELS22, {
|
|
6737
|
-
"gemini-omni-1.1-flash-preview": buildOmniFlash11Payload
|
|
6844
|
+
"gemini-omni-1.1-flash-preview": buildOmniFlash11Payload,
|
|
6845
|
+
"gemini-2.5-flash-tts": buildTts25Payload("gemini-2.5-flash-tts"),
|
|
6846
|
+
"gemini-2.5-pro-tts": buildTts25Payload("gemini-2.5-pro-tts"),
|
|
6847
|
+
"gemini-3.8-flash-tts": buildTts38Payload("gemini-3.8-flash-tts"),
|
|
6848
|
+
"gemini-3.8-flash-lite-tts": buildTts38Payload("gemini-3.8-flash-lite-tts")
|
|
6738
6849
|
});
|
|
6739
6850
|
|
|
6740
6851
|
// src/vendors/catalog/openai.ts
|
|
@@ -11997,6 +12108,23 @@ function buildGenerationAttributes(input) {
|
|
|
11997
12108
|
}
|
|
11998
12109
|
return attrs;
|
|
11999
12110
|
}
|
|
12111
|
+
function attributesForSave(params2) {
|
|
12112
|
+
const attributes = { ...params2.attributes };
|
|
12113
|
+
if (params2.generation) {
|
|
12114
|
+
return { ...attributes, ...buildGenerationAttributes(params2.generation) };
|
|
12115
|
+
}
|
|
12116
|
+
if (asString(attributes.model)) {
|
|
12117
|
+
const legacy = adaptLegacyGeneration(attributes);
|
|
12118
|
+
const canonical = parseJsonAttr(attributes.aiSDKPayload);
|
|
12119
|
+
const payload = canonical && typeof canonical.prompt === "string" ? canonical : legacy.aiSDKPayload ?? {};
|
|
12120
|
+
return {
|
|
12121
|
+
...legacy.appId ? { appId: legacy.appId, appType: legacy.appType } : {},
|
|
12122
|
+
...attributes,
|
|
12123
|
+
...buildGenerationAttributes({ modelId: attributes.model, params: payload })
|
|
12124
|
+
};
|
|
12125
|
+
}
|
|
12126
|
+
return attributes;
|
|
12127
|
+
}
|
|
12000
12128
|
function toMediaItem(file) {
|
|
12001
12129
|
const url = normalizeUrl(file.sourceUrl);
|
|
12002
12130
|
if (!url || String(file.name || "").startsWith("__")) return null;
|
|
@@ -12332,7 +12460,7 @@ function createDriveClient(f, apiUrl, rootFolderName) {
|
|
|
12332
12460
|
width: 1024,
|
|
12333
12461
|
height: 1024
|
|
12334
12462
|
},
|
|
12335
|
-
attributes: Object.entries(params2
|
|
12463
|
+
attributes: Object.entries(attributesForSave(params2)).map(([property, value]) => ({
|
|
12336
12464
|
property,
|
|
12337
12465
|
value
|
|
12338
12466
|
}))
|
|
@@ -12360,15 +12488,17 @@ function createDriveClient(f, apiUrl, rootFolderName) {
|
|
|
12360
12488
|
}
|
|
12361
12489
|
},
|
|
12362
12490
|
/** Build standard save params from a generation result. */
|
|
12363
|
-
buildSaveParams(url, modelId, modelName, mode,
|
|
12491
|
+
buildSaveParams(url, modelId, modelName, mode, promptOrParams) {
|
|
12492
|
+
const params2 = typeof promptOrParams === "string" ? { prompt: promptOrParams } : promptOrParams ?? {};
|
|
12493
|
+
const prompt = String(params2.prompt ?? "");
|
|
12364
12494
|
return {
|
|
12365
12495
|
url,
|
|
12366
12496
|
name: buildFilename(prompt, mode, { url }),
|
|
12367
12497
|
resourceType: inferResourceType(mode),
|
|
12368
12498
|
attributes: {
|
|
12369
12499
|
tool: "ai-sdk",
|
|
12370
|
-
|
|
12371
|
-
prompt
|
|
12500
|
+
...buildGenerationAttributes({ modelId, params: params2 }),
|
|
12501
|
+
prompt,
|
|
12372
12502
|
service: modelName
|
|
12373
12503
|
}
|
|
12374
12504
|
};
|
|
@@ -12676,8 +12806,8 @@ function createClient(config) {
|
|
|
12676
12806
|
return {
|
|
12677
12807
|
// Named before the job runs, so the requested/declared format is the best hint.
|
|
12678
12808
|
name: explicit?.name ?? buildFilename(params2.prompt, model.mode, { format: expectedOutputFormat(model, params2) }),
|
|
12679
|
-
//
|
|
12680
|
-
attributes: { ...
|
|
12809
|
+
// Generation provenance is authoritative; custom attributes cannot replace it.
|
|
12810
|
+
attributes: { ...explicit?.attributes ?? {}, ...attributes },
|
|
12681
12811
|
folder: explicit?.folder ?? (folderPath ? { path: folderPath } : void 0)
|
|
12682
12812
|
};
|
|
12683
12813
|
}
|