@vibeframe/mcp-server 0.104.3 → 0.105.1

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.
Files changed (2) hide show
  1. package/dist/index.js +251 -35
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -7688,6 +7688,33 @@ consult this file \u2014 run the generate command directly.
7688
7688
  Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
7689
7689
  \`vibe scene init . --visual-style "Swiss Pulse"\` (idempotent).
7690
7690
 
7691
+ ## Brief and local media
7692
+
7693
+ \`brief.md\` is raw intent, not a strict schema. It may contain messy notes,
7694
+ pasted research, links, product requirements, or a one-line idea. \`vibe init
7695
+ --from brief.md\` uses it only to seed \`STORYBOARD.md\` and \`DESIGN.md\`;
7696
+ after init, those two files are the working source of truth.
7697
+
7698
+ Use \`media/\` for user-provided source files: product photos, screenshots,
7699
+ logos, B-roll, recorded narration, or reference clips. Keep those inputs
7700
+ inside this project so build references stay project-relative. Do not put user
7701
+ media in \`references/\`; that directory is reserved for local composition
7702
+ rules installed by VibeFrame.
7703
+
7704
+ When a beat should reuse a local file, reference it from \`STORYBOARD.md\`
7705
+ with a project-relative path:
7706
+
7707
+ \`\`\`yaml
7708
+ backdrop: "media/product-shot.png" # existing still image
7709
+ video: "media/broll.mp4" # existing video/B-roll
7710
+ narration: "media/voice.wav" # existing recorded narration
7711
+ asset: "media/logo.png" # generic local asset reference
7712
+ \`\`\`
7713
+
7714
+ Use text cues when you want VibeFrame to generate an asset. Use path cues
7715
+ when you want VibeFrame to reuse a local file. Avoid absolute paths or parent
7716
+ directory references; copy files into \`media/\` first.
7717
+
7691
7718
  ## Provider keys and project scope
7692
7719
 
7693
7720
  Use VibeFrame CLI generation for project assets:
@@ -7735,9 +7762,11 @@ the framework-level minimum, not the cinematic craft layer.
7735
7762
 
7736
7763
  - \`DESIGN.md\` \u2014 visual identity contract (palette, type, motion, transitions)
7737
7764
  - \`STORYBOARD.md\` \u2014 per-beat narration/backdrop/duration cues for \`vibe build\`
7765
+ - \`media/\` \u2014 user-provided source files (photos, logos, clips, voice recordings)
7738
7766
  - \`index.html\` \u2014 root composition (timeline)
7739
7767
  - \`compositions/scene-*.html\` \u2014 per-scene HTML authored by you or the agent
7740
- - \`assets/\` \u2014 shared media (narration audio, images, video)
7768
+ - \`assets/\` \u2014 generated/canonical build media (narration audio, images, video)
7769
+ - \`references/\` \u2014 composition rule docs installed by VibeFrame, not user media
7741
7770
  - \`transcript.json\` \u2014 Whisper word-level transcript (if narration exists)
7742
7771
  - \`hyperframes.json\` \u2014 HF registry config (speak to both toolchains)
7743
7772
  - \`vibe.config.json\` \u2014 canonical VibeFrame config (providers, budget)
@@ -7882,7 +7911,11 @@ async function scaffoldSceneProject(opts) {
7882
7911
  if (await pathExists(metaPath)) {
7883
7912
  skipped2.push(metaPath);
7884
7913
  } else {
7885
- await writeFile(metaPath, JSON.stringify(buildHyperframesMeta(name, now), null, 2) + "\n", "utf-8");
7914
+ await writeFile(
7915
+ metaPath,
7916
+ JSON.stringify(buildHyperframesMeta(name, now), null, 2) + "\n",
7917
+ "utf-8"
7918
+ );
7886
7919
  created.push(metaPath);
7887
7920
  }
7888
7921
  const rootPath = resolve2(dir, "index.html");
@@ -7897,11 +7930,7 @@ async function scaffoldSceneProject(opts) {
7897
7930
  if (await pathExists(vibeConfigJsonPath)) {
7898
7931
  skipped2.push(vibeConfigJsonPath);
7899
7932
  } else {
7900
- await writeFile(
7901
- vibeConfigJsonPath,
7902
- projectConfigJson({ name, aspect }),
7903
- "utf-8"
7904
- );
7933
+ await writeFile(vibeConfigJsonPath, projectConfigJson({ name, aspect }), "utf-8");
7905
7934
  created.push(vibeConfigJsonPath);
7906
7935
  }
7907
7936
  const vibePath = resolve2(dir, "vibe.project.yaml");
@@ -7940,11 +7969,7 @@ ${existing}`, "utf-8");
7940
7969
  if (await pathExists(designPath)) {
7941
7970
  skipped2.push(designPath);
7942
7971
  } else {
7943
- await writeFile(
7944
- designPath,
7945
- buildDesignMd({ name, style: opts.visualStyle }),
7946
- "utf-8"
7947
- );
7972
+ await writeFile(designPath, buildDesignMd({ name, style: opts.visualStyle }), "utf-8");
7948
7973
  created.push(designPath);
7949
7974
  }
7950
7975
  const storyboardPath = resolve2(dir, "STORYBOARD.md");
@@ -24326,6 +24351,53 @@ function pickReferenceImageUrl(input3) {
24326
24351
  return input3;
24327
24352
  return void 0;
24328
24353
  }
24354
+ function isFalFileInput(value) {
24355
+ return value.startsWith("http://") || value.startsWith("https://") || value.startsWith("data:");
24356
+ }
24357
+ async function normaliseReferences(input3, client) {
24358
+ if (!input3)
24359
+ return [];
24360
+ const references = [];
24361
+ for (const ref of input3) {
24362
+ if (!isFalFileInput(ref.url))
24363
+ continue;
24364
+ references.push({
24365
+ ...ref,
24366
+ url: ref.url.startsWith("data:") ? await uploadDataUri(client, ref.url) : ref.url
24367
+ });
24368
+ }
24369
+ return references;
24370
+ }
24371
+ async function uploadDataUri(client, dataUri) {
24372
+ const blob = dataUriToBlob(dataUri);
24373
+ return client.storage.upload(blob, {
24374
+ lifecycle: { expiresIn: "1h" }
24375
+ });
24376
+ }
24377
+ function dataUriToBlob(dataUri) {
24378
+ const match2 = /^data:([^;,]+)?(;base64)?,(.*)$/s.exec(dataUri);
24379
+ if (!match2)
24380
+ throw new Error("Invalid data URI reference.");
24381
+ const mimeType = match2[1] || "application/octet-stream";
24382
+ const isBase64 = Boolean(match2[2]);
24383
+ const payload = match2[3] ?? "";
24384
+ const buffer = isBase64 ? Buffer.from(payload, "base64") : Buffer.from(decodeURIComponent(payload), "utf-8");
24385
+ return new Blob([new Uint8Array(buffer)], { type: mimeType });
24386
+ }
24387
+ function groupReferences(references) {
24388
+ const image_urls = [];
24389
+ const video_urls = [];
24390
+ const audio_urls = [];
24391
+ for (const ref of references) {
24392
+ if (ref.kind === "image")
24393
+ image_urls.push(ref.url);
24394
+ if (ref.kind === "video")
24395
+ video_urls.push(ref.url);
24396
+ if (ref.kind === "audio")
24397
+ audio_urls.push(ref.url);
24398
+ }
24399
+ return { image_urls, video_urls, audio_urls };
24400
+ }
24329
24401
  function normaliseAspect(value) {
24330
24402
  if (!value)
24331
24403
  return "auto";
@@ -24348,7 +24420,7 @@ function normaliseDuration(value) {
24348
24420
  return "auto";
24349
24421
  return Math.max(4, Math.min(15, Math.round(value)));
24350
24422
  }
24351
- var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, FalProvider, falProvider;
24423
+ var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, FalProvider, falProvider;
24352
24424
  var init_FalProvider = __esm({
24353
24425
  "../ai-providers/dist/fal/FalProvider.js"() {
24354
24426
  "use strict";
@@ -24361,6 +24433,10 @@ var init_FalProvider = __esm({
24361
24433
  "seedance-2.0": "bytedance/seedance-2.0/image-to-video",
24362
24434
  "seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video"
24363
24435
  };
24436
+ ENDPOINT_REFERENCE_TO_VIDEO = {
24437
+ "seedance-2.0": "bytedance/seedance-2.0/reference-to-video",
24438
+ "seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video"
24439
+ };
24364
24440
  DEFAULT_VARIANT = "seedance-2.0";
24365
24441
  VALID_RESOLUTIONS = ["480p", "720p", "1080p"];
24366
24442
  VALID_ASPECTS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "auto"];
@@ -24369,7 +24445,7 @@ var init_FalProvider = __esm({
24369
24445
  this.id = "seedance";
24370
24446
  this.name = "fal.ai (Seedance 2.0)";
24371
24447
  this.description = "fal.ai hosting ByteDance Seedance 2.0 \u2014 Artificial Analysis #2 on both text-to-video and image-to-video leaderboards";
24372
- this.capabilities = ["text-to-video", "image-to-video"];
24448
+ this.capabilities = ["text-to-video", "image-to-video", "reference-to-video"];
24373
24449
  this.iconUrl = "/icons/fal.svg";
24374
24450
  this.isAvailable = true;
24375
24451
  }
@@ -24408,9 +24484,11 @@ var init_FalProvider = __esm({
24408
24484
  error: `Unknown Seedance variant: ${variant}. Valid: ${Object.keys(ENDPOINT_TEXT_TO_VIDEO).join(", ")}.`
24409
24485
  };
24410
24486
  }
24411
- const referenceImage = pickReferenceImageUrl(options?.referenceImage);
24487
+ const references = await normaliseReferences(options?.references, this.client);
24488
+ const hasReferences = references.length > 0;
24489
+ const referenceImage = hasReferences ? void 0 : pickReferenceImageUrl(options?.referenceImage);
24412
24490
  const isImageToVideo = !!referenceImage;
24413
- const endpointId = isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
24491
+ const endpointId = hasReferences ? ENDPOINT_REFERENCE_TO_VIDEO[variant] : isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
24414
24492
  const aspect = normaliseAspect(options?.aspectRatio);
24415
24493
  const resolution = normaliseResolution(options?.resolution);
24416
24494
  const duration = normaliseDuration(options?.duration);
@@ -24420,13 +24498,26 @@ var init_FalProvider = __esm({
24420
24498
  resolution,
24421
24499
  duration
24422
24500
  };
24423
- if (referenceImage)
24501
+ if (hasReferences) {
24502
+ const grouped = groupReferences(references);
24503
+ if (grouped.image_urls.length > 0)
24504
+ input3.image_urls = grouped.image_urls;
24505
+ if (grouped.video_urls.length > 0)
24506
+ input3.video_urls = grouped.video_urls;
24507
+ if (grouped.audio_urls.length > 0)
24508
+ input3.audio_urls = grouped.audio_urls;
24509
+ } else if (referenceImage) {
24424
24510
  input3.image_url = referenceImage;
24511
+ }
24425
24512
  if (options?.negativePrompt)
24426
24513
  input3.negative_prompt = options.negativePrompt;
24427
24514
  if (typeof options?.seed === "number")
24428
24515
  input3.seed = options.seed;
24429
- if (options?.lastFrame)
24516
+ if (typeof options?.generateAudio === "boolean")
24517
+ input3.generate_audio = options.generateAudio;
24518
+ if (options?.endUserId)
24519
+ input3.end_user_id = options.endUserId;
24520
+ if (!hasReferences && options?.lastFrame)
24430
24521
  input3.end_image_url = options.lastFrame;
24431
24522
  try {
24432
24523
  const out = await this.client.subscribe(endpointId, { input: input3, logs: false });
@@ -24473,14 +24564,15 @@ var init_fal = __esm({
24473
24564
  // Review this alias at the 1.0 cut.
24474
24565
  aliases: ["fal"],
24475
24566
  models: ["seedance-2.0", "seedance-2.0-fast"],
24476
- capabilities: ["text-to-video", "image-to-video", "native-audio"],
24567
+ capabilities: ["text-to-video", "image-to-video", "reference-to-video", "native-audio"],
24477
24568
  apiKey: "fal",
24478
24569
  kinds: ["video"],
24479
24570
  resolverPriority: { video: 1 },
24480
24571
  commandsUnlocked: [
24481
24572
  "generate video -p seedance (Seedance 2.0 via fal.ai \u2014 default since v0.57)",
24482
24573
  "generate video -p seedance --seedance-model fast (lower-latency variant)",
24483
- "generate video -p seedance -i <image> (image-to-video)"
24574
+ "generate video -p seedance -i <image> (image-to-video)",
24575
+ "generate video -p seedance --ref-images <images...> (reference-to-video)"
24484
24576
  ]
24485
24577
  });
24486
24578
  }
@@ -284704,7 +284796,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
284704
284796
  /*mapfn*/
284705
284797
  (name) => ts_FindAllReferences_exports.getReferenceEntriesForNode(-1, name, program2, program2.getSourceFiles(), cancellationToken)
284706
284798
  );
284707
- const groupedReferences = groupReferences(references);
284799
+ const groupedReferences = groupReferences2(references);
284708
284800
  if (!every(
284709
284801
  groupedReferences.declarations,
284710
284802
  /*callback*/
@@ -284713,7 +284805,7 @@ ${newComment.split("\n").map((c) => ` * ${c}`).join("\n")}
284713
284805
  groupedReferences.valid = false;
284714
284806
  }
284715
284807
  return groupedReferences;
284716
- function groupReferences(referenceEntries) {
284808
+ function groupReferences2(referenceEntries) {
284717
284809
  const classReferences = { accessExpressions: [], typeUsages: [] };
284718
284810
  const groupedReferences2 = { functionCalls: [], declarations: [], classReferences, valid: true };
284719
284811
  const functionSymbols = map3(functionNames, getSymbolTargetAtLocation);
@@ -452471,6 +452563,9 @@ async function executeVideoGenerate(options) {
452471
452563
  prompt: prompt3,
452472
452564
  provider = "kling",
452473
452565
  image,
452566
+ refImages,
452567
+ refVideos,
452568
+ refAudio,
452474
452569
  duration = 5,
452475
452570
  ratio = "16:9",
452476
452571
  seed,
@@ -452479,6 +452574,7 @@ async function executeVideoGenerate(options) {
452479
452574
  resolution,
452480
452575
  veoModel = "3.1-fast",
452481
452576
  seedanceModel = "quality",
452577
+ generateAudio,
452482
452578
  output: output3,
452483
452579
  wait = true,
452484
452580
  apiKey
@@ -452517,8 +452613,13 @@ async function executeVideoGenerate(options) {
452517
452613
  if (provider === "seedance" || provider === "fal") {
452518
452614
  const fal = new FalProvider();
452519
452615
  await fal.initialize({ apiKey: key2 });
452616
+ const references = await prepareSeedanceReferences({
452617
+ refImages,
452618
+ refVideos,
452619
+ refAudio
452620
+ });
452520
452621
  let falImage = referenceImage;
452521
- if (falImage && falImage.startsWith("data:")) {
452622
+ if (falImage && falImage.startsWith("data:") && references.length === 0) {
452522
452623
  const uploadHost = await resolveUploadHost();
452523
452624
  const upload = await uploadHost.uploadImage(referenceImageBuffer, {
452524
452625
  filename: image,
@@ -452529,11 +452630,14 @@ async function executeVideoGenerate(options) {
452529
452630
  const model = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
452530
452631
  const result = await fal.generateVideo(prompt3, {
452531
452632
  prompt: prompt3,
452532
- referenceImage: falImage,
452633
+ referenceImage: references.length > 0 ? void 0 : falImage,
452634
+ references: references.length > 0 ? references : void 0,
452533
452635
  duration,
452534
452636
  aspectRatio: ratio,
452535
452637
  negativePrompt: negative,
452536
- model
452638
+ model,
452639
+ resolution,
452640
+ generateAudio
452537
452641
  });
452538
452642
  if (result.status === "failed")
452539
452643
  return { success: false, error: result.error || "Seedance generation failed" };
@@ -452710,6 +452814,54 @@ async function executeVideoGenerate(options) {
452710
452814
  };
452711
452815
  }
452712
452816
  }
452817
+ async function prepareSeedanceReferences(opts) {
452818
+ const references = [];
452819
+ for (const sourcePath of opts.refImages ?? []) {
452820
+ references.push({
452821
+ kind: "image",
452822
+ url: await fileInputToUrlOrDataUri(sourcePath, "image/png"),
452823
+ sourcePath
452824
+ });
452825
+ }
452826
+ for (const sourcePath of opts.refVideos ?? []) {
452827
+ references.push({
452828
+ kind: "video",
452829
+ url: await fileInputToUrlOrDataUri(sourcePath, "video/mp4"),
452830
+ sourcePath
452831
+ });
452832
+ }
452833
+ for (const sourcePath of opts.refAudio ?? []) {
452834
+ references.push({
452835
+ kind: "audio",
452836
+ url: await fileInputToUrlOrDataUri(sourcePath, "audio/mpeg"),
452837
+ sourcePath
452838
+ });
452839
+ }
452840
+ return references;
452841
+ }
452842
+ async function fileInputToUrlOrDataUri(input3, fallbackMimeType) {
452843
+ if (input3.startsWith("http://") || input3.startsWith("https://") || input3.startsWith("data:")) {
452844
+ return input3;
452845
+ }
452846
+ const absPath = resolve28(process.cwd(), input3);
452847
+ const buffer = await readFile14(absPath);
452848
+ return `data:${mimeTypeForPath(input3, fallbackMimeType)};base64,${buffer.toString("base64")}`;
452849
+ }
452850
+ function mimeTypeForPath(path14, fallback2) {
452851
+ const ext = path14.toLowerCase().split(".").pop();
452852
+ const mimeTypes = {
452853
+ jpg: "image/jpeg",
452854
+ jpeg: "image/jpeg",
452855
+ png: "image/png",
452856
+ gif: "image/gif",
452857
+ webp: "image/webp",
452858
+ mp4: "video/mp4",
452859
+ mov: "video/quicktime",
452860
+ mp3: "audio/mpeg",
452861
+ wav: "audio/wav"
452862
+ };
452863
+ return mimeTypes[ext || ""] || fallback2;
452864
+ }
452713
452865
  async function executeVideoStatus(options) {
452714
452866
  const {
452715
452867
  taskId,
@@ -463925,10 +464077,10 @@ var init_provider_resolver = __esm({
463925
464077
 
463926
464078
  // ../cli/src/commands/_shared/openai-image.ts
463927
464079
  function resolveOpenAIImageModel(modelAlias) {
463928
- const isGptImage2 = modelAlias === "2" || modelAlias === "gpt-image-2";
464080
+ const isGptImage15 = modelAlias === "1.5" || modelAlias === "gpt-image-1.5";
463929
464081
  return {
463930
- openaiModel: isGptImage2 ? "gpt-image-2" : void 0,
463931
- modelLabel: isGptImage2 ? "GPT Image 2" : "GPT Image 1.5"
464082
+ openaiModel: isGptImage15 ? "gpt-image-1.5" : "gpt-image-2",
464083
+ modelLabel: isGptImage15 ? "GPT Image 1.5" : "GPT Image 2"
463932
464084
  };
463933
464085
  }
463934
464086
  async function executeOpenAIImageGenerate(prompt3, options, ctx) {
@@ -463965,7 +464117,7 @@ function registerImageCommand(parent) {
463965
464117
  "1:1"
463966
464118
  ).option("--quality <quality>", "Quality: standard, hd (openai only)", "standard").option("--style <style>", "Style: vivid, natural (openai only)", "vivid").option("--count <n>", "Number of images to generate", "1").option(
463967
464119
  "-m, --model <model>",
463968
- "Model. Gemini: flash, 3.1-flash, latest, pro. OpenAI: 1.5 (default), 2 (gpt-image-2)"
464120
+ "Model. Gemini: flash, 3.1-flash, latest, pro. OpenAI: 2 (default), 1.5"
463969
464121
  ).option("--dry-run", "Preview parameters without executing").addHelpText(
463970
464122
  "after",
463971
464123
  `
@@ -465399,8 +465551,8 @@ function registerVideoCommand(parent) {
465399
465551
  "quality"
465400
465552
  ).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 720p, 1080p, 4k (Veo only)").option("--last-frame <path>", "Last frame image for frame interpolation (Veo only)").option(
465401
465553
  "--ref-images <paths...>",
465402
- "Reference images for character consistency (Veo 3.1 only, max 3)"
465403
- ).option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.0, 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
465554
+ "Reference images for Seedance reference-to-video or Veo character consistency"
465555
+ ).option("--ref-videos <paths...>", "Reference videos for Seedance reference-to-video").option("--ref-audio <paths...>", "Reference audio for Seedance reference-to-video").option("--no-generate-audio", "Disable native audio when the provider supports it").option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.0, 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
465404
465556
  "--runway-model <model>",
465405
465557
  "Runway model: gen4.5 (default, text+image-to-video), gen4_turbo (image-to-video only)",
465406
465558
  "gen4.5"
@@ -465543,7 +465695,11 @@ Examples:
465543
465695
  negative: options.negative,
465544
465696
  resolution: options.resolution,
465545
465697
  veoModel: options.veoModel,
465546
- seedanceModel: options.seedanceModel
465698
+ seedanceModel: options.seedanceModel,
465699
+ refImages: options.refImages,
465700
+ refVideos: options.refVideos,
465701
+ refAudio: options.refAudio,
465702
+ generateAudio: options.generateAudio
465547
465703
  }
465548
465704
  }
465549
465705
  });
@@ -465830,8 +465986,13 @@ Examples:
465830
465986
  } else if (provider === "seedance") {
465831
465987
  const fal = new FalProvider();
465832
465988
  await fal.initialize({ apiKey });
465989
+ const seedanceReferences = await prepareSeedanceReferences2({
465990
+ refImages: options.refImages,
465991
+ refVideos: options.refVideos,
465992
+ refAudio: options.refAudio
465993
+ });
465833
465994
  let falImage = referenceImage;
465834
- if (falImage && falImage.startsWith("data:")) {
465995
+ if (falImage && falImage.startsWith("data:") && seedanceReferences.length === 0) {
465835
465996
  try {
465836
465997
  const uploadHost = await resolveUploadHost();
465837
465998
  spinner2.text = `Uploading image via ${uploadHost.provider} for Seedance...`;
@@ -465854,11 +466015,14 @@ Examples:
465854
466015
  const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
465855
466016
  result = await fal.generateVideo(prompt3, {
465856
466017
  prompt: prompt3,
465857
- referenceImage: falImage,
466018
+ referenceImage: seedanceReferences.length > 0 ? void 0 : falImage,
466019
+ references: seedanceReferences.length > 0 ? seedanceReferences : void 0,
465858
466020
  duration: options.duration ? parseInt(options.duration) : void 0,
465859
466021
  aspectRatio: options.ratio,
465860
466022
  negativePrompt: options.negative,
465861
- model: falModel
466023
+ model: falModel,
466024
+ resolution: options.resolution,
466025
+ generateAudio: options.generateAudio
465862
466026
  });
465863
466027
  finalResult = result;
465864
466028
  }
@@ -465913,6 +466077,54 @@ Examples:
465913
466077
  }
465914
466078
  });
465915
466079
  }
466080
+ async function prepareSeedanceReferences2(opts) {
466081
+ const references = [];
466082
+ for (const sourcePath of opts.refImages ?? []) {
466083
+ references.push({
466084
+ kind: "image",
466085
+ url: await fileInputToUrlOrDataUri2(sourcePath, "image/png"),
466086
+ sourcePath
466087
+ });
466088
+ }
466089
+ for (const sourcePath of opts.refVideos ?? []) {
466090
+ references.push({
466091
+ kind: "video",
466092
+ url: await fileInputToUrlOrDataUri2(sourcePath, "video/mp4"),
466093
+ sourcePath
466094
+ });
466095
+ }
466096
+ for (const sourcePath of opts.refAudio ?? []) {
466097
+ references.push({
466098
+ kind: "audio",
466099
+ url: await fileInputToUrlOrDataUri2(sourcePath, "audio/mpeg"),
466100
+ sourcePath
466101
+ });
466102
+ }
466103
+ return references;
466104
+ }
466105
+ async function fileInputToUrlOrDataUri2(input3, fallbackMimeType) {
466106
+ if (input3.startsWith("http://") || input3.startsWith("https://") || input3.startsWith("data:")) {
466107
+ return input3;
466108
+ }
466109
+ const absPath = resolve63(process.cwd(), input3);
466110
+ const buffer = await readFile32(absPath);
466111
+ return `data:${mimeTypeForPath2(input3, fallbackMimeType)};base64,${buffer.toString("base64")}`;
466112
+ }
466113
+ function mimeTypeForPath2(path14, fallback2) {
466114
+ const ext = path14.toLowerCase().split(".").pop();
466115
+ const mimeTypes = {
466116
+ jpg: "image/jpeg",
466117
+ jpeg: "image/jpeg",
466118
+ png: "image/png",
466119
+ gif: "image/gif",
466120
+ webp: "image/webp",
466121
+ mp4: "video/mp4",
466122
+ mov: "video/quicktime",
466123
+ mp3: "audio/mpeg",
466124
+ wav: "audio/wav"
466125
+ };
466126
+ return mimeTypes[ext || ""] || fallback2;
466127
+ }
465916
466128
  async function recordVideoNoWaitJob(opts) {
465917
466129
  return createAndWriteJobRecord({
465918
466130
  jobType: "generate-video",
@@ -472252,6 +472464,9 @@ var generateVideoTool = defineTool({
472252
472464
  "Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
472253
472465
  ),
472254
472466
  image: z5.string().optional().describe("Reference image path for image-to-video"),
472467
+ refImages: z5.array(z5.string()).optional().describe("Reference images for Seedance reference-to-video"),
472468
+ refVideos: z5.array(z5.string()).optional().describe("Reference videos for Seedance reference-to-video"),
472469
+ refAudio: z5.array(z5.string()).optional().describe("Reference audio files for Seedance reference-to-video"),
472255
472470
  duration: z5.number().optional().describe("Duration in seconds (default: 5; Seedance accepts 4-15)"),
472256
472471
  ratio: z5.string().optional().describe("Aspect ratio: 16:9, 9:16, 1:1 (default: 16:9)"),
472257
472472
  mode: z5.string().optional().describe("Kling mode: std or pro"),
@@ -472260,6 +472475,7 @@ var generateVideoTool = defineTool({
472260
472475
  veoModel: z5.string().optional().describe("Veo model: 3.0, 3.1, 3.1-fast"),
472261
472476
  runwayModel: z5.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
472262
472477
  seedanceModel: z5.string().optional().describe("Seedance variant: quality or fast (fal.ai only)"),
472478
+ generateAudio: z5.boolean().optional().describe("Generate native synchronized audio when supported"),
472263
472479
  output: z5.string().optional().describe("Output file path (downloads video)"),
472264
472480
  wait: z5.boolean().optional().describe("Wait for completion (default: true)")
472265
472481
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/mcp-server",
3
- "version": "0.104.3",
3
+ "version": "0.105.1",
4
4
  "description": "VibeFrame MCP Server - AI-native video editing via Model Context Protocol",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,8 +57,8 @@
57
57
  "tsx": "^4.21.0",
58
58
  "typescript": "^5.3.3",
59
59
  "vitest": "^1.2.2",
60
- "@vibeframe/cli": "0.104.3",
61
- "@vibeframe/core": "0.104.3"
60
+ "@vibeframe/core": "0.105.1",
61
+ "@vibeframe/cli": "0.105.1"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=20"