@broberg/ai-sdk 0.36.6 → 0.36.7

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 CHANGED
@@ -273,7 +273,9 @@ interface ImageResult {
273
273
  }
274
274
  /** Image-to-video generation (F024) — animate a still into a short clip. */
275
275
  interface AnimateRequest {
276
- /** Input image: a URL (passed through) or raw bytes (uploaded to fal storage). */
276
+ /** Input image: a URL (passed through) or raw bytes. Where bytes are uploaded is
277
+ * the ADAPTER's business — fal uses fal storage, the Gemini/Veo default inlines
278
+ * them — so do not read a storage provider out of this field. */
277
279
  image: string | Uint8Array;
278
280
  /** Motion/scene prompt, e.g. "the subject turns and smiles". */
279
281
  prompt?: string;
@@ -446,7 +448,11 @@ interface ProviderAdapter {
446
448
  translate?(req: TranslateRequest): Promise<TranslateResult>;
447
449
  vision?(req: ChatRequest): Promise<ChatResult>;
448
450
  image?(req: ImageRequest): Promise<ImageResult>;
449
- /** Image-to-video generation (F024) — animate a still into a short clip. fal. */
451
+ /** Image-to-video generation (F024) — animate a still into a short clip. gemini
452
+ * (Veo 3.1) by default; override to fal for Kling/Seedance. Name only the DEFAULT
453
+ * route here — provider-doc-drift.test.ts fails if this and DEFAULT_ANIMATE_SPEC
454
+ * disagree, because this sentence is the editor tooltip a consumer reads when
455
+ * deciding which API key to buy. */
450
456
  animate?(req: AnimateRequest): Promise<AnimateResult>;
451
457
  /** Train a style/brand LoRA from images (F021). fal. */
452
458
  trainStyle?(req: TrainStyleRequest): Promise<TrainStyleResult>;
@@ -2200,8 +2206,8 @@ declare const falStubAdapter: ProviderAdapter;
2200
2206
  * wires the live adapters. */
2201
2207
  declare const stubProviders: Record<string, ProviderAdapter>;
2202
2208
 
2203
- declare const VERSION: "0.36.6";
2204
- declare const SDK_TAG: "@broberg/ai-sdk@0.36.6";
2209
+ declare const VERSION: "0.36.7";
2210
+ declare const SDK_TAG: "@broberg/ai-sdk@0.36.7";
2205
2211
 
2206
2212
  /** Built-in defaults. Every entry is overridable via AiConfig.defaults or a
2207
2213
  * per-call override.
package/dist/index.js CHANGED
@@ -959,7 +959,7 @@ function geminiAdapter(config = {}) {
959
959
  const baseUrl = config.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
960
960
  function resolveKey() {
961
961
  const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
962
- if (!apiKey) throw new Error("gemini adapter: API key not set (env GOOGLE_API_KEY)");
962
+ if (!apiKey) throw new Error("gemini adapter: API key not set (env GOOGLE_API_KEY or GEMINI_API_KEY)");
963
963
  return apiKey;
964
964
  }
965
965
  function buildBody(req) {
@@ -1998,7 +1998,7 @@ function falAdapter(config = {}) {
1998
1998
  });
1999
1999
  async function image(req) {
2000
2000
  const apiKey = resolveKey();
2001
- if (!apiKey) throw new Error("fal adapter: FAL_KEY not set");
2001
+ if (!apiKey) throw new Error("fal adapter: API key not set (env FAL_KEY or FAL_API_KEY)");
2002
2002
  const headers = authHeaders(apiKey);
2003
2003
  const body = { prompt: req.prompt };
2004
2004
  if (req.width !== void 0 && req.height !== void 0) {
@@ -2028,7 +2028,7 @@ function falAdapter(config = {}) {
2028
2028
  }
2029
2029
  async function animate(req) {
2030
2030
  const apiKey = resolveKey();
2031
- if (!apiKey) throw new Error("fal adapter: FAL_KEY not set");
2031
+ if (!apiKey) throw new Error("fal adapter: API key not set (env FAL_KEY or FAL_API_KEY)");
2032
2032
  const headers = authHeaders(apiKey);
2033
2033
  const imageUrl = typeof req.image === "string" && /^https?:\/\//i.test(req.image) ? req.image : await uploadToFalStorage(toBytes(req.image), sniffImageType(req.image), "input", apiKey);
2034
2034
  const body = { image_url: imageUrl };
@@ -2058,7 +2058,7 @@ function falAdapter(config = {}) {
2058
2058
  }
2059
2059
  async function trainStyle(req) {
2060
2060
  const apiKey = resolveKey();
2061
- if (!apiKey) throw new Error("fal adapter: FAL_KEY not set");
2061
+ if (!apiKey) throw new Error("fal adapter: API key not set (env FAL_KEY or FAL_API_KEY)");
2062
2062
  const headers = authHeaders(apiKey);
2063
2063
  const body = {
2064
2064
  images_data_url: await resolveImagesUrl(req.images, apiKey),
@@ -2993,8 +2993,8 @@ var aiConfigSchema = z.object({
2993
2993
  });
2994
2994
 
2995
2995
  // src/version.ts
2996
- var VERSION = "0.36.6";
2997
- var SDK_TAG = "@broberg/ai-sdk@0.36.6";
2996
+ var VERSION = "0.36.7";
2997
+ var SDK_TAG = "@broberg/ai-sdk@0.36.7";
2998
2998
 
2999
2999
  // src/cost/sinks/upmetrics.ts
3000
3000
  function upmetricsSink(config) {
@@ -3090,6 +3090,11 @@ var DEFAULT_ANIMATE_SPEC = {
3090
3090
  transport: "http"
3091
3091
  };
3092
3092
  var ANIMATE_AUDIO_DIRECTIVE = "No spoken dialogue, no talking, no voiceover. Include natural ambient background sounds that match the environment.";
3093
+ function routeHasAudio(spec) {
3094
+ const m = spec.model.toLowerCase();
3095
+ if (m.includes("kling") || m.includes("seedance") || m.includes("wan-")) return false;
3096
+ return true;
3097
+ }
3093
3098
  var DEFAULT_BFL_FINETUNE_SPEC = {
3094
3099
  provider: "bfl",
3095
3100
  model: "flux-pro-1.1-ultra-finetuned",
@@ -3405,7 +3410,7 @@ function createAI(config = {}) {
3405
3410
  },
3406
3411
  async animate(input) {
3407
3412
  input = animateInputSchema.parse(input);
3408
- const prompt = input.prompt?.trim() ? `${input.prompt.trim()} ${ANIMATE_AUDIO_DIRECTIVE}` : ANIMATE_AUDIO_DIRECTIVE;
3413
+ const basePrompt = input.prompt?.trim() ?? "";
3409
3414
  return runCapability({
3410
3415
  primary: withOverride(DEFAULT_ANIMATE_SPEC, input.override, "animate"),
3411
3416
  fallback: input.fallback,
@@ -3418,9 +3423,10 @@ function createAI(config = {}) {
3418
3423
  invoke: async (spec) => {
3419
3424
  const adapter = pickProvider(spec.provider);
3420
3425
  if (!adapter.animate) throw new Error(`createAI: provider "${spec.provider}" does not support animate`);
3426
+ const prompt = routeHasAudio(spec) ? `${basePrompt} ${ANIMATE_AUDIO_DIRECTIVE}`.trim() : basePrompt;
3421
3427
  return adapter.animate({
3422
3428
  image: input.image,
3423
- prompt,
3429
+ prompt: prompt || void 0,
3424
3430
  durationSec: input.durationSec,
3425
3431
  resolution: input.resolution,
3426
3432
  spec