@broberg/ai-sdk 0.15.0 → 0.17.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 +137 -10
- package/dist/index.js +191 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ interface TierSpec {
|
|
|
14
14
|
transport: Transport;
|
|
15
15
|
}
|
|
16
16
|
/** High-level capability a call exercises. Mirrors the capability layer (F5). */
|
|
17
|
-
type Capability = "chat" | "vision" | "video" | "translate" | "image" | "embedding" | "transcribe" | "ocr" | "moderation" | "podcast" | "tts" | "trainStyle" | "mockup" | "design" | "extract" | "classify" | "rerank";
|
|
17
|
+
type Capability = "chat" | "vision" | "video" | "translate" | "image" | "animate" | "embedding" | "transcribe" | "ocr" | "moderation" | "podcast" | "tts" | "trainStyle" | "mockup" | "design" | "extract" | "classify" | "rerank";
|
|
18
18
|
type Role = "system" | "user" | "assistant" | "tool";
|
|
19
19
|
/** A piece of message content. Text everywhere; image parts feed vision. */
|
|
20
20
|
type ContentPart = {
|
|
@@ -188,6 +188,30 @@ interface ImageResult {
|
|
|
188
188
|
url: string;
|
|
189
189
|
usage: Usage;
|
|
190
190
|
}
|
|
191
|
+
/** Image-to-video generation (F024) — animate a still into a short clip. */
|
|
192
|
+
interface AnimateRequest {
|
|
193
|
+
/** Input image: a URL (passed through) or raw bytes (uploaded to fal storage). */
|
|
194
|
+
image: string | Uint8Array;
|
|
195
|
+
/** Motion/scene prompt, e.g. "the subject turns and smiles". */
|
|
196
|
+
prompt?: string;
|
|
197
|
+
/** Clip length in seconds (provider-dependent; Veo ≤ 8s). */
|
|
198
|
+
durationSec?: number;
|
|
199
|
+
/** e.g. "720p" / "1080p" (provider-dependent). */
|
|
200
|
+
resolution?: string;
|
|
201
|
+
spec: TierSpec;
|
|
202
|
+
}
|
|
203
|
+
interface AnimateResult {
|
|
204
|
+
/** URL to the generated video. For fal this is a public hosted URL; for the
|
|
205
|
+
* Gemini/Veo route it is Google's file URI (needs the API key to fetch — the
|
|
206
|
+
* bytes are also returned below, already downloaded). */
|
|
207
|
+
url: string;
|
|
208
|
+
/** The downloaded video bytes — set by providers whose result URL is auth-gated
|
|
209
|
+
* or short-lived (Gemini/Veo). Absent for providers that return a public URL (fal). */
|
|
210
|
+
bytes?: Uint8Array;
|
|
211
|
+
/** MIME type of `bytes` (e.g. "video/mp4"). */
|
|
212
|
+
mimeType?: string;
|
|
213
|
+
usage: Usage;
|
|
214
|
+
}
|
|
191
215
|
/** Style/brand LoRA training (F021) — fal fal-ai/flux-lora-fast-training. */
|
|
192
216
|
interface TrainStyleRequest {
|
|
193
217
|
/** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */
|
|
@@ -304,6 +328,8 @@ interface ProviderAdapter {
|
|
|
304
328
|
chatStream?(req: ChatRequest): AsyncIterable<ChatStreamEvent>;
|
|
305
329
|
vision?(req: ChatRequest): Promise<ChatResult>;
|
|
306
330
|
image?(req: ImageRequest): Promise<ImageResult>;
|
|
331
|
+
/** Image-to-video generation (F024) — animate a still into a short clip. fal. */
|
|
332
|
+
animate?(req: AnimateRequest): Promise<AnimateResult>;
|
|
307
333
|
/** Train a style/brand LoRA from images (F021). fal. */
|
|
308
334
|
trainStyle?(req: TrainStyleRequest): Promise<TrainStyleResult>;
|
|
309
335
|
embedding?(req: EmbeddingRequest): Promise<EmbeddingResult>;
|
|
@@ -417,12 +443,12 @@ declare const toolSchema: z.ZodObject<{
|
|
|
417
443
|
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
418
444
|
}, "strip", z.ZodTypeAny, {
|
|
419
445
|
name: string;
|
|
420
|
-
description: string;
|
|
421
446
|
parameters: Record<string, unknown>;
|
|
447
|
+
description: string;
|
|
422
448
|
}, {
|
|
423
449
|
name: string;
|
|
424
|
-
description: string;
|
|
425
450
|
parameters: Record<string, unknown>;
|
|
451
|
+
description: string;
|
|
426
452
|
}>;
|
|
427
453
|
declare const messageSchema: z.ZodObject<{
|
|
428
454
|
role: z.ZodEnum<["system", "user", "assistant", "tool"]>;
|
|
@@ -604,12 +630,12 @@ declare const chatInputSchema: z.ZodObject<{
|
|
|
604
630
|
parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
605
631
|
}, "strip", z.ZodTypeAny, {
|
|
606
632
|
name: string;
|
|
607
|
-
description: string;
|
|
608
633
|
parameters: Record<string, unknown>;
|
|
634
|
+
description: string;
|
|
609
635
|
}, {
|
|
610
636
|
name: string;
|
|
611
|
-
description: string;
|
|
612
637
|
parameters: Record<string, unknown>;
|
|
638
|
+
description: string;
|
|
613
639
|
}>, "many">>;
|
|
614
640
|
maxTokens: z.ZodOptional<z.ZodNumber>;
|
|
615
641
|
temperature: z.ZodOptional<z.ZodNumber>;
|
|
@@ -637,8 +663,8 @@ declare const chatInputSchema: z.ZodObject<{
|
|
|
637
663
|
}[] | undefined;
|
|
638
664
|
tools?: {
|
|
639
665
|
name: string;
|
|
640
|
-
description: string;
|
|
641
666
|
parameters: Record<string, unknown>;
|
|
667
|
+
description: string;
|
|
642
668
|
}[] | undefined;
|
|
643
669
|
temperature?: number | undefined;
|
|
644
670
|
purpose?: string | undefined;
|
|
@@ -678,8 +704,8 @@ declare const chatInputSchema: z.ZodObject<{
|
|
|
678
704
|
}[] | undefined;
|
|
679
705
|
tools?: {
|
|
680
706
|
name: string;
|
|
681
|
-
description: string;
|
|
682
707
|
parameters: Record<string, unknown>;
|
|
708
|
+
description: string;
|
|
683
709
|
}[] | undefined;
|
|
684
710
|
temperature?: number | undefined;
|
|
685
711
|
purpose?: string | undefined;
|
|
@@ -1032,6 +1058,81 @@ declare const imageInputSchema: z.ZodObject<{
|
|
|
1032
1058
|
safetyTolerance?: number | undefined;
|
|
1033
1059
|
retryOnBlack?: boolean | undefined;
|
|
1034
1060
|
}>;
|
|
1061
|
+
declare const animateInputSchema: z.ZodObject<{
|
|
1062
|
+
tier: z.ZodOptional<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>>;
|
|
1063
|
+
override: z.ZodOptional<z.ZodObject<{
|
|
1064
|
+
provider: z.ZodOptional<z.ZodString>;
|
|
1065
|
+
model: z.ZodOptional<z.ZodString>;
|
|
1066
|
+
transport: z.ZodOptional<z.ZodEnum<["http", "subprocess"]>>;
|
|
1067
|
+
}, "strip", z.ZodTypeAny, {
|
|
1068
|
+
provider?: string | undefined;
|
|
1069
|
+
model?: string | undefined;
|
|
1070
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1071
|
+
}, {
|
|
1072
|
+
provider?: string | undefined;
|
|
1073
|
+
model?: string | undefined;
|
|
1074
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1075
|
+
}>>;
|
|
1076
|
+
fallback: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>, z.ZodObject<{
|
|
1077
|
+
provider: z.ZodString;
|
|
1078
|
+
model: z.ZodString;
|
|
1079
|
+
transport: z.ZodEnum<["http", "subprocess"]>;
|
|
1080
|
+
}, "strip", z.ZodTypeAny, {
|
|
1081
|
+
provider: string;
|
|
1082
|
+
model: string;
|
|
1083
|
+
transport: "http" | "subprocess";
|
|
1084
|
+
}, {
|
|
1085
|
+
provider: string;
|
|
1086
|
+
model: string;
|
|
1087
|
+
transport: "http" | "subprocess";
|
|
1088
|
+
}>]>, "many">>;
|
|
1089
|
+
purpose: z.ZodOptional<z.ZodString>;
|
|
1090
|
+
labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1091
|
+
/** Input image: a URL or raw bytes (uploaded to fal storage). */
|
|
1092
|
+
image: z.ZodUnion<[z.ZodString, z.ZodType<Uint8Array<ArrayBuffer>, z.ZodTypeDef, Uint8Array<ArrayBuffer>>]>;
|
|
1093
|
+
/** Motion/scene prompt. */
|
|
1094
|
+
prompt: z.ZodOptional<z.ZodString>;
|
|
1095
|
+
/** Clip length in seconds (provider-dependent; Veo ≤ 8s). */
|
|
1096
|
+
durationSec: z.ZodOptional<z.ZodNumber>;
|
|
1097
|
+
/** e.g. "720p" / "1080p" (provider-dependent). */
|
|
1098
|
+
resolution: z.ZodOptional<z.ZodString>;
|
|
1099
|
+
}, "strip", z.ZodTypeAny, {
|
|
1100
|
+
image: string | Uint8Array<ArrayBuffer>;
|
|
1101
|
+
prompt?: string | undefined;
|
|
1102
|
+
resolution?: string | undefined;
|
|
1103
|
+
purpose?: string | undefined;
|
|
1104
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1105
|
+
override?: {
|
|
1106
|
+
provider?: string | undefined;
|
|
1107
|
+
model?: string | undefined;
|
|
1108
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1109
|
+
} | undefined;
|
|
1110
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1111
|
+
provider: string;
|
|
1112
|
+
model: string;
|
|
1113
|
+
transport: "http" | "subprocess";
|
|
1114
|
+
})[] | undefined;
|
|
1115
|
+
labels?: Record<string, string> | undefined;
|
|
1116
|
+
durationSec?: number | undefined;
|
|
1117
|
+
}, {
|
|
1118
|
+
image: string | Uint8Array<ArrayBuffer>;
|
|
1119
|
+
prompt?: string | undefined;
|
|
1120
|
+
resolution?: string | undefined;
|
|
1121
|
+
purpose?: string | undefined;
|
|
1122
|
+
tier?: "fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | undefined;
|
|
1123
|
+
override?: {
|
|
1124
|
+
provider?: string | undefined;
|
|
1125
|
+
model?: string | undefined;
|
|
1126
|
+
transport?: "http" | "subprocess" | undefined;
|
|
1127
|
+
} | undefined;
|
|
1128
|
+
fallback?: ("fast" | "smart" | "powerful" | "cheap" | "vision" | "video" | "embedding" | {
|
|
1129
|
+
provider: string;
|
|
1130
|
+
model: string;
|
|
1131
|
+
transport: "http" | "subprocess";
|
|
1132
|
+
})[] | undefined;
|
|
1133
|
+
labels?: Record<string, string> | undefined;
|
|
1134
|
+
durationSec?: number | undefined;
|
|
1135
|
+
}>;
|
|
1035
1136
|
declare const trainStyleInputSchema: z.ZodObject<{
|
|
1036
1137
|
tier: z.ZodOptional<z.ZodEnum<["fast", "smart", "powerful", "cheap", "vision", "video", "embedding"]>>;
|
|
1037
1138
|
override: z.ZodOptional<z.ZodObject<{
|
|
@@ -1591,6 +1692,7 @@ type VisionInput = z.infer<typeof visionInputSchema>;
|
|
|
1591
1692
|
type VideoInput = z.infer<typeof videoInputSchema>;
|
|
1592
1693
|
type TranslateInput = z.infer<typeof translateInputSchema>;
|
|
1593
1694
|
type ImageInput = z.infer<typeof imageInputSchema>;
|
|
1695
|
+
type AnimateInput = z.infer<typeof animateInputSchema>;
|
|
1594
1696
|
type TrainStyleInput = z.infer<typeof trainStyleInputSchema>;
|
|
1595
1697
|
type EmbeddingInput = z.infer<typeof embeddingInputSchema>;
|
|
1596
1698
|
type TranscribeInput = z.infer<typeof transcribeInputSchema>;
|
|
@@ -1610,6 +1712,8 @@ interface AiClient {
|
|
|
1610
1712
|
video(input: VideoInput): Promise<ChatResult>;
|
|
1611
1713
|
translate(input: TranslateInput): Promise<TranslateResult>;
|
|
1612
1714
|
image(input: ImageInput): Promise<ImageResult>;
|
|
1715
|
+
/** Image-to-video (F024) — animate a still into a short clip → { url, usage }. fal. */
|
|
1716
|
+
animate(input: AnimateInput): Promise<AnimateResult>;
|
|
1613
1717
|
/** Train a style/brand LoRA from images (F021) → { loraUrl, configUrl }. fal. */
|
|
1614
1718
|
trainStyle(input: TrainStyleInput): Promise<TrainStyleResult>;
|
|
1615
1719
|
embedding(input: EmbeddingInput): Promise<EmbeddingResult>;
|
|
@@ -1665,6 +1769,12 @@ declare function geminiAdapter(config?: {
|
|
|
1665
1769
|
baseUrl?: string;
|
|
1666
1770
|
fetch?: typeof fetch;
|
|
1667
1771
|
pricePerImage?: number;
|
|
1772
|
+
/** Override the per-SECOND Veo video price (else estimate per model, 0 if unknown). */
|
|
1773
|
+
pricePerSecond?: number;
|
|
1774
|
+
/** Poll interval for Veo long-running operations (default 5s). */
|
|
1775
|
+
pollIntervalMs?: number;
|
|
1776
|
+
/** Deadline for a Veo job (default 300000 = 5 min). */
|
|
1777
|
+
videoTimeoutMs?: number;
|
|
1668
1778
|
}): ProviderAdapter;
|
|
1669
1779
|
|
|
1670
1780
|
declare function deepinfraAdapter(config?: {
|
|
@@ -1715,11 +1825,15 @@ interface FalAdapterConfig {
|
|
|
1715
1825
|
timeoutMs?: number;
|
|
1716
1826
|
/** Deadline for training jobs — they take minutes (default 600000 = 10 min). */
|
|
1717
1827
|
trainTimeoutMs?: number;
|
|
1828
|
+
/** Deadline for video jobs — they take minutes (default 600000 = 10 min). */
|
|
1829
|
+
videoTimeoutMs?: number;
|
|
1718
1830
|
fetch?: typeof fetch;
|
|
1719
1831
|
/** Override the per-image USD price (else a built-in estimate per model, 0 if unknown). */
|
|
1720
1832
|
pricePerImage?: number;
|
|
1721
1833
|
/** Override the flat per-training USD price (else ~$2 estimate). */
|
|
1722
1834
|
pricePerTraining?: number;
|
|
1835
|
+
/** Override the per-SECOND video USD price (else a built-in estimate per model, 0 if unknown). */
|
|
1836
|
+
pricePerSecond?: number;
|
|
1723
1837
|
}
|
|
1724
1838
|
declare function falAdapter(config?: FalAdapterConfig): ProviderAdapter;
|
|
1725
1839
|
|
|
@@ -1733,6 +1847,19 @@ interface BflAdapterConfig {
|
|
|
1733
1847
|
/** Override the per-image USD price (else the built-in finetuned-inference estimate). */
|
|
1734
1848
|
pricePerImage?: number;
|
|
1735
1849
|
}
|
|
1850
|
+
/** Remaining BFL account credits + their USD value (1 credit = $0.01). */
|
|
1851
|
+
interface BflCredits {
|
|
1852
|
+
credits: number;
|
|
1853
|
+
usd: number;
|
|
1854
|
+
}
|
|
1855
|
+
/** F023.6 — check the BFL account's remaining credit balance (`GET /v1/credits`).
|
|
1856
|
+
* Account-level (region-independent); EU-pinned by default for consistency. Use it
|
|
1857
|
+
* for budget-gating before a generate call: `if ((await bflCredits()).usd < 1) …`. */
|
|
1858
|
+
declare function bflCredits(opts?: {
|
|
1859
|
+
apiKey?: string;
|
|
1860
|
+
baseUrl?: string;
|
|
1861
|
+
fetch?: typeof fetch;
|
|
1862
|
+
}): Promise<BflCredits>;
|
|
1736
1863
|
declare function bflAdapter(config?: BflAdapterConfig): ProviderAdapter;
|
|
1737
1864
|
|
|
1738
1865
|
interface OpenAICompatibleConfig {
|
|
@@ -1768,8 +1895,8 @@ declare const falStubAdapter: ProviderAdapter;
|
|
|
1768
1895
|
* wires the live adapters. */
|
|
1769
1896
|
declare const stubProviders: Record<string, ProviderAdapter>;
|
|
1770
1897
|
|
|
1771
|
-
declare const VERSION: "0.
|
|
1772
|
-
declare const SDK_TAG: "@broberg/ai-sdk@0.
|
|
1898
|
+
declare const VERSION: "0.17.0";
|
|
1899
|
+
declare const SDK_TAG: "@broberg/ai-sdk@0.17.0";
|
|
1773
1900
|
|
|
1774
1901
|
/** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
|
|
1775
1902
|
* per-call override. Model IDs are current at scaffold time; callers pin their
|
|
@@ -1995,4 +2122,4 @@ interface StreamTransportRequest extends TransportRequest {
|
|
|
1995
2122
|
*/
|
|
1996
2123
|
declare function streamTransport(req: StreamTransportRequest): AsyncIterable<string>;
|
|
1997
2124
|
|
|
1998
|
-
export { type AiClient, type AiConfig, type BatchJob, type BatchRequestItem, type BatchResultItem, type BflAdapterConfig, 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 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 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 UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, bflAdapter, 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, refreshAvailability, resetRefreshState, resetRegistry, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
|
2125
|
+
export { type AiClient, type AiConfig, 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 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 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 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 UpmetricsSinkConfig, type Usage, VERSION, type VideoInput, type VisionInput, aiConfigSchema, anthropicAdapter, anthropicApiAdapter, anthropicSubprocessAdapter, bflAdapter, bflCredits, 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, refreshAvailability, resetRefreshState, resetRegistry, resolveTier, resolveVoice, sqliteBudgetStore, sqliteSink, streamTransport, stubProviders, subprocessTransport, tierSpecSchema, toProviderTools, toolSchema, translateInputSchema, upmetricsSink, visionInputSchema };
|
package/dist/index.js
CHANGED
|
@@ -870,6 +870,16 @@ function partsFrom(content) {
|
|
|
870
870
|
return { inlineData: { mimeType: p.mimeType ?? "image/png", data } };
|
|
871
871
|
});
|
|
872
872
|
}
|
|
873
|
+
var VEO_PRICE_PER_SEC = {
|
|
874
|
+
"veo-3.1-generate-preview": 0.4,
|
|
875
|
+
// standard; 4K = 0.60
|
|
876
|
+
"veo-3.1-fast-generate-preview": 0.1,
|
|
877
|
+
// 720p; 1080p = 0.12, 4K = 0.30
|
|
878
|
+
"veo-3.1-lite-generate-preview": 0.05,
|
|
879
|
+
// 720p; 1080p = 0.08
|
|
880
|
+
"veo-3.0-generate-001": 0.4,
|
|
881
|
+
"veo-3.0-fast-generate-001": 0.1
|
|
882
|
+
};
|
|
873
883
|
function geminiAdapter(config = {}) {
|
|
874
884
|
const baseUrl = config.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
|
|
875
885
|
function resolveKey() {
|
|
@@ -1025,7 +1035,82 @@ function geminiAdapter(config = {}) {
|
|
|
1025
1035
|
usage.costUsd = config.pricePerImage ?? GEMINI_IMAGE_PRICE_PER_IMAGE[req.spec.model] ?? 0;
|
|
1026
1036
|
return { url, usage };
|
|
1027
1037
|
}
|
|
1028
|
-
|
|
1038
|
+
async function animate(req) {
|
|
1039
|
+
const apiKey = resolveKey();
|
|
1040
|
+
const fetchImpl = config.fetch ?? fetch;
|
|
1041
|
+
const pollIntervalMs = config.pollIntervalMs ?? 5e3;
|
|
1042
|
+
const deadline = Date.now() + (config.videoTimeoutMs ?? 3e5);
|
|
1043
|
+
const { data, mimeType } = await toInlineImage(req.image, fetchImpl);
|
|
1044
|
+
const parameters = {};
|
|
1045
|
+
if (req.durationSec !== void 0) parameters.durationSeconds = req.durationSec;
|
|
1046
|
+
if (req.resolution !== void 0) parameters.resolution = req.resolution;
|
|
1047
|
+
const body = {
|
|
1048
|
+
instances: [{ prompt: req.prompt ?? "", image: { bytesBase64Encoded: data, mimeType } }],
|
|
1049
|
+
...Object.keys(parameters).length ? { parameters } : {}
|
|
1050
|
+
};
|
|
1051
|
+
const submit = await fetchImpl(
|
|
1052
|
+
`${baseUrl}/models/${req.spec.model}:predictLongRunning?key=${encodeURIComponent(apiKey)}`,
|
|
1053
|
+
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) }
|
|
1054
|
+
);
|
|
1055
|
+
if (!submit.ok) {
|
|
1056
|
+
throw new Error(`gemini animate ${submit.status}: ${(await submit.text().catch(() => "")).slice(0, 300)}`);
|
|
1057
|
+
}
|
|
1058
|
+
const op = await submit.json();
|
|
1059
|
+
if (!op.name) throw new Error("gemini animate: no operation name in submit response");
|
|
1060
|
+
let videoUri;
|
|
1061
|
+
for (; ; ) {
|
|
1062
|
+
const poll = await fetchImpl(`${baseUrl}/${op.name}?key=${encodeURIComponent(apiKey)}`, {
|
|
1063
|
+
headers: { "content-type": "application/json" }
|
|
1064
|
+
});
|
|
1065
|
+
if (!poll.ok) throw new Error(`gemini animate poll ${poll.status}`);
|
|
1066
|
+
const opData = await poll.json();
|
|
1067
|
+
if (opData.error) throw new Error(`gemini animate: ${opData.error.message ?? "operation error"}`);
|
|
1068
|
+
if (opData.done) {
|
|
1069
|
+
videoUri = opData.response?.generateVideoResponse?.generatedSamples?.[0]?.video?.uri;
|
|
1070
|
+
if (!videoUri) throw new Error(`gemini animate: done but no video uri: ${JSON.stringify(opData.response).slice(0, 300)}`);
|
|
1071
|
+
break;
|
|
1072
|
+
}
|
|
1073
|
+
if (Date.now() >= deadline) throw new Error("gemini animate: timed out");
|
|
1074
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
1075
|
+
}
|
|
1076
|
+
const dl = await fetchImpl(videoUri.includes("key=") ? videoUri : `${videoUri}${videoUri.includes("?") ? "&" : "?"}key=${encodeURIComponent(apiKey)}`);
|
|
1077
|
+
if (!dl.ok) throw new Error(`gemini animate download ${dl.status}`);
|
|
1078
|
+
const bytes = new Uint8Array(await dl.arrayBuffer());
|
|
1079
|
+
const usage = freshUsage({
|
|
1080
|
+
provider: "gemini",
|
|
1081
|
+
model: req.spec.model,
|
|
1082
|
+
transport: "http",
|
|
1083
|
+
capability: "animate",
|
|
1084
|
+
inputTokens: 0,
|
|
1085
|
+
outputTokens: 0
|
|
1086
|
+
});
|
|
1087
|
+
const perSec = config.pricePerSecond ?? VEO_PRICE_PER_SEC[req.spec.model] ?? 0;
|
|
1088
|
+
usage.costUsd = perSec * (req.durationSec ?? 8);
|
|
1089
|
+
return { url: videoUri, bytes, mimeType: "video/mp4", usage };
|
|
1090
|
+
}
|
|
1091
|
+
return { name: "gemini", chat, chatStream, image, animate, vision: chat };
|
|
1092
|
+
}
|
|
1093
|
+
async function toInlineImage(image, fetchImpl) {
|
|
1094
|
+
if (typeof image !== "string") {
|
|
1095
|
+
return { data: Buffer.from(image).toString("base64"), mimeType: sniffMime(image) };
|
|
1096
|
+
}
|
|
1097
|
+
if (/^https?:\/\//i.test(image)) {
|
|
1098
|
+
const res = await fetchImpl(image);
|
|
1099
|
+
if (!res.ok) throw new Error(`gemini animate: failed to fetch image (${res.status})`);
|
|
1100
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
1101
|
+
const mimeType2 = res.headers.get("content-type") ?? sniffMime(bytes);
|
|
1102
|
+
return { data: Buffer.from(bytes).toString("base64"), mimeType: mimeType2 };
|
|
1103
|
+
}
|
|
1104
|
+
const comma = image.startsWith("data:") ? image.indexOf(",") : -1;
|
|
1105
|
+
const b64 = comma >= 0 ? image.slice(comma + 1) : image;
|
|
1106
|
+
const mimeType = image.startsWith("data:") ? image.slice(5, image.indexOf(";")) : "image/png";
|
|
1107
|
+
return { data: b64, mimeType };
|
|
1108
|
+
}
|
|
1109
|
+
function sniffMime(b) {
|
|
1110
|
+
if (b[0] === 137 && b[1] === 80) return "image/png";
|
|
1111
|
+
if (b[0] === 71 && b[1] === 73) return "image/gif";
|
|
1112
|
+
if (b[0] === 82 && b[1] === 73 && b[8] === 87) return "image/webp";
|
|
1113
|
+
return "image/jpeg";
|
|
1029
1114
|
}
|
|
1030
1115
|
function mapGeminiFinish(reason) {
|
|
1031
1116
|
switch (reason) {
|
|
@@ -1320,6 +1405,8 @@ var FAL_IMAGE_PRICE_ESTIMATE = {
|
|
|
1320
1405
|
"fal-ai/flux-pro/v1.1": 0.04
|
|
1321
1406
|
};
|
|
1322
1407
|
var FAL_TRAIN_PRICE_ESTIMATE = 2;
|
|
1408
|
+
var FAL_VIDEO_PRICE_PER_SEC = {};
|
|
1409
|
+
var FAL_VIDEO_DEFAULT_SEC = 8;
|
|
1323
1410
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1324
1411
|
function falAdapter(config = {}) {
|
|
1325
1412
|
const doFetch = config.fetch ?? fetch;
|
|
@@ -1362,6 +1449,36 @@ function falAdapter(config = {}) {
|
|
|
1362
1449
|
usage.costUsd = (config.pricePerImage ?? FAL_IMAGE_PRICE_ESTIMATE[req.spec.model] ?? 0) * calls;
|
|
1363
1450
|
return { url, usage };
|
|
1364
1451
|
}
|
|
1452
|
+
async function animate(req) {
|
|
1453
|
+
const apiKey = resolveKey();
|
|
1454
|
+
if (!apiKey) throw new Error("fal adapter: FAL_KEY not set");
|
|
1455
|
+
const headers = authHeaders(apiKey);
|
|
1456
|
+
const imageUrl = typeof req.image === "string" && /^https?:\/\//i.test(req.image) ? req.image : await uploadToFalStorage(toBytes(req.image), sniffImageType(req.image), "input", apiKey);
|
|
1457
|
+
const body = { image_url: imageUrl };
|
|
1458
|
+
if (req.prompt !== void 0) body.prompt = req.prompt;
|
|
1459
|
+
if (req.durationSec !== void 0) body.duration = req.durationSec;
|
|
1460
|
+
if (req.resolution !== void 0) body.resolution = req.resolution;
|
|
1461
|
+
const result = await queueResult(req.spec.model, headers, body, config.videoTimeoutMs ?? 6e5);
|
|
1462
|
+
const url = extractVideoUrl(result);
|
|
1463
|
+
if (!url) {
|
|
1464
|
+
throw new Error(
|
|
1465
|
+
`fal animate: no video url in result \u2014 keys [${Object.keys(
|
|
1466
|
+
result ?? {}
|
|
1467
|
+
).join(", ")}]: ${JSON.stringify(result).slice(0, 500)}`
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
const usage = freshUsage({
|
|
1471
|
+
provider: "fal",
|
|
1472
|
+
model: req.spec.model,
|
|
1473
|
+
transport: "http",
|
|
1474
|
+
capability: "animate",
|
|
1475
|
+
inputTokens: 0,
|
|
1476
|
+
outputTokens: 0
|
|
1477
|
+
});
|
|
1478
|
+
const perSec = config.pricePerSecond ?? FAL_VIDEO_PRICE_PER_SEC[req.spec.model] ?? 0;
|
|
1479
|
+
usage.costUsd = perSec * (req.durationSec ?? FAL_VIDEO_DEFAULT_SEC);
|
|
1480
|
+
return { url, usage };
|
|
1481
|
+
}
|
|
1365
1482
|
async function trainStyle(req) {
|
|
1366
1483
|
const apiKey = resolveKey();
|
|
1367
1484
|
if (!apiKey) throw new Error("fal adapter: FAL_KEY not set");
|
|
@@ -1481,7 +1598,24 @@ function falAdapter(config = {}) {
|
|
|
1481
1598
|
}
|
|
1482
1599
|
return resultRes.json();
|
|
1483
1600
|
}
|
|
1484
|
-
return { name: "fal", image, trainStyle };
|
|
1601
|
+
return { name: "fal", image, animate, trainStyle };
|
|
1602
|
+
}
|
|
1603
|
+
function toBytes(img) {
|
|
1604
|
+
if (typeof img !== "string") return img;
|
|
1605
|
+
const b64 = img.startsWith("data:") ? img.slice(img.indexOf(",") + 1) : img;
|
|
1606
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
1607
|
+
}
|
|
1608
|
+
function sniffImageType(img) {
|
|
1609
|
+
const b = toBytes(img);
|
|
1610
|
+
if (b[0] === 137 && b[1] === 80) return "image/png";
|
|
1611
|
+
if (b[0] === 71 && b[1] === 73) return "image/gif";
|
|
1612
|
+
if (b[0] === 82 && b[1] === 73 && b[8] === 87) return "image/webp";
|
|
1613
|
+
return "image/jpeg";
|
|
1614
|
+
}
|
|
1615
|
+
function extractVideoUrl(result) {
|
|
1616
|
+
const r = result;
|
|
1617
|
+
const root = r?.data ?? r?.response ?? r?.output ?? r;
|
|
1618
|
+
return urlOf(root?.video) ?? urlOf(root?.videos?.[0]) ?? deepFindUrl(root, (u) => /\.(mp4|webm|mov)(\?|$)/i.test(u));
|
|
1485
1619
|
}
|
|
1486
1620
|
function urlOf(v) {
|
|
1487
1621
|
if (typeof v === "string") return v;
|
|
@@ -1581,6 +1715,18 @@ var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
1581
1715
|
function gcd(a, b) {
|
|
1582
1716
|
return b === 0 ? a : gcd(b, a % b);
|
|
1583
1717
|
}
|
|
1718
|
+
async function bflCredits(opts = {}) {
|
|
1719
|
+
const apiKey = opts.apiKey ?? process.env.BFL_API_KEY;
|
|
1720
|
+
if (!apiKey) throw new Error("bflCredits: BFL_API_KEY not set");
|
|
1721
|
+
const doFetch = opts.fetch ?? fetch;
|
|
1722
|
+
const res = await doFetch(`${opts.baseUrl ?? EU_BASE}/v1/credits`, { headers: { "x-key": apiKey } });
|
|
1723
|
+
if (!res.ok) {
|
|
1724
|
+
throw new Error(`bflCredits ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
|
|
1725
|
+
}
|
|
1726
|
+
const data = await res.json();
|
|
1727
|
+
const credits = typeof data.credits === "number" ? data.credits : 0;
|
|
1728
|
+
return { credits, usd: credits * BFL_CREDIT_USD };
|
|
1729
|
+
}
|
|
1584
1730
|
function bflAdapter(config = {}) {
|
|
1585
1731
|
const doFetch = config.fetch ?? fetch;
|
|
1586
1732
|
const base = config.baseUrl ?? EU_BASE;
|
|
@@ -2007,6 +2153,17 @@ var imageInputSchema = z.object({
|
|
|
2007
2153
|
retryOnBlack: z.boolean().optional(),
|
|
2008
2154
|
...callOptions
|
|
2009
2155
|
});
|
|
2156
|
+
var animateInputSchema = z.object({
|
|
2157
|
+
/** Input image: a URL or raw bytes (uploaded to fal storage). */
|
|
2158
|
+
image: z.union([z.string(), z.instanceof(Uint8Array)]),
|
|
2159
|
+
/** Motion/scene prompt. */
|
|
2160
|
+
prompt: z.string().optional(),
|
|
2161
|
+
/** Clip length in seconds (provider-dependent; Veo ≤ 8s). */
|
|
2162
|
+
durationSec: z.number().positive().optional(),
|
|
2163
|
+
/** e.g. "720p" / "1080p" (provider-dependent). */
|
|
2164
|
+
resolution: z.string().optional(),
|
|
2165
|
+
...callOptions
|
|
2166
|
+
});
|
|
2010
2167
|
var trainStyleInputSchema = z.object({
|
|
2011
2168
|
/** A hosted archive URL, or an array of image URLs the SDK zips in-memory. */
|
|
2012
2169
|
images: z.union([z.string(), z.array(z.string())]),
|
|
@@ -2085,6 +2242,11 @@ var DEFAULT_TRAINSTYLE_SPEC = {
|
|
|
2085
2242
|
model: "fal-ai/flux-lora-fast-training",
|
|
2086
2243
|
transport: "http"
|
|
2087
2244
|
};
|
|
2245
|
+
var DEFAULT_ANIMATE_SPEC = {
|
|
2246
|
+
provider: "gemini",
|
|
2247
|
+
model: "veo-3.1-generate-preview",
|
|
2248
|
+
transport: "http"
|
|
2249
|
+
};
|
|
2088
2250
|
var DEFAULT_BFL_FINETUNE_SPEC = {
|
|
2089
2251
|
provider: "bfl",
|
|
2090
2252
|
model: "flux-pro-1.1-ultra-finetuned",
|
|
@@ -2371,6 +2533,30 @@ function createAI(config = {}) {
|
|
|
2371
2533
|
}
|
|
2372
2534
|
});
|
|
2373
2535
|
},
|
|
2536
|
+
async animate(input) {
|
|
2537
|
+
input = animateInputSchema.parse(input);
|
|
2538
|
+
return runCapability({
|
|
2539
|
+
primary: { ...DEFAULT_ANIMATE_SPEC, ...input.override },
|
|
2540
|
+
fallback: input.fallback,
|
|
2541
|
+
capability: "animate",
|
|
2542
|
+
purpose: input.purpose,
|
|
2543
|
+
labels: input.labels,
|
|
2544
|
+
estIn: 0,
|
|
2545
|
+
// video cost is per-second, not token-based
|
|
2546
|
+
estOut: 0,
|
|
2547
|
+
invoke: async (spec) => {
|
|
2548
|
+
const adapter = pickProvider(spec.provider);
|
|
2549
|
+
if (!adapter.animate) throw new Error(`createAI: provider "${spec.provider}" does not support animate`);
|
|
2550
|
+
return adapter.animate({
|
|
2551
|
+
image: input.image,
|
|
2552
|
+
prompt: input.prompt,
|
|
2553
|
+
durationSec: input.durationSec,
|
|
2554
|
+
resolution: input.resolution,
|
|
2555
|
+
spec
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
});
|
|
2559
|
+
},
|
|
2374
2560
|
async trainStyle(input) {
|
|
2375
2561
|
input = trainStyleInputSchema.parse(input);
|
|
2376
2562
|
return runCapability({
|
|
@@ -2621,8 +2807,8 @@ var stubProviders = {
|
|
|
2621
2807
|
};
|
|
2622
2808
|
|
|
2623
2809
|
// src/version.ts
|
|
2624
|
-
var VERSION = "0.
|
|
2625
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
2810
|
+
var VERSION = "0.17.0";
|
|
2811
|
+
var SDK_TAG = "@broberg/ai-sdk@0.17.0";
|
|
2626
2812
|
|
|
2627
2813
|
// src/availability/refresh.ts
|
|
2628
2814
|
var NOT_REFRESHED = { refreshed: false, checked: 0, markedUnavailable: [] };
|
|
@@ -2909,6 +3095,7 @@ export {
|
|
|
2909
3095
|
anthropicApiAdapter,
|
|
2910
3096
|
anthropicSubprocessAdapter,
|
|
2911
3097
|
bflAdapter,
|
|
3098
|
+
bflCredits,
|
|
2912
3099
|
chatInputSchema,
|
|
2913
3100
|
computeCost,
|
|
2914
3101
|
createAI,
|