@vibeframe/mcp-server 0.113.24 → 0.113.26

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 +218 -59
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1843,6 +1843,113 @@ Respond with ONLY the JSON array, no other text.`;
1843
1843
  }
1844
1844
  });
1845
1845
 
1846
+ // ../ai-providers/dist/gemini/gemini-omni.js
1847
+ function firstReferenceImage(options) {
1848
+ const refs3 = options.referenceImages;
1849
+ if (refs3 && refs3.length > 0 && refs3[0].base64)
1850
+ return refs3[0];
1851
+ const ref = options.referenceImage;
1852
+ if (typeof ref === "string" && ref) {
1853
+ const m2 = ref.match(/^data:(.+?);base64,(.*)$/);
1854
+ if (m2)
1855
+ return { mimeType: m2[1], base64: m2[2] };
1856
+ return { mimeType: "image/png", base64: ref };
1857
+ }
1858
+ return void 0;
1859
+ }
1860
+ function findVideoUrl(obj) {
1861
+ if (!obj || typeof obj !== "object")
1862
+ return void 0;
1863
+ for (const [k2, v2] of Object.entries(obj)) {
1864
+ if (typeof v2 === "string" && /^https?:\/\//.test(v2) && /(uri|url|video)/i.test(k2))
1865
+ return v2;
1866
+ if (typeof v2 === "object") {
1867
+ const nested = findVideoUrl(v2);
1868
+ if (nested)
1869
+ return nested;
1870
+ }
1871
+ }
1872
+ return void 0;
1873
+ }
1874
+ var OMNI_MODEL, INTERACTIONS_URL, OmniProvider, omniProvider;
1875
+ var init_gemini_omni = __esm({
1876
+ "../ai-providers/dist/gemini/gemini-omni.js"() {
1877
+ "use strict";
1878
+ OMNI_MODEL = "gemini-omni-flash-preview";
1879
+ INTERACTIONS_URL = "https://generativelanguage.googleapis.com/v1beta/interactions";
1880
+ OmniProvider = class {
1881
+ constructor() {
1882
+ this.id = "omni";
1883
+ this.label = "Gemini Omni (experimental)";
1884
+ }
1885
+ async initialize(config4) {
1886
+ this.apiKey = config4.apiKey;
1887
+ }
1888
+ isConfigured() {
1889
+ return !!this.apiKey;
1890
+ }
1891
+ async generateVideo(prompt3, options) {
1892
+ if (!this.apiKey) {
1893
+ return { id: "", status: "failed", error: "GOOGLE_API_KEY not configured for Gemini Omni" };
1894
+ }
1895
+ const opts = options ?? { prompt: prompt3 };
1896
+ const image = firstReferenceImage(opts);
1897
+ const task = image ? "image_to_video" : "text_to_video";
1898
+ const aspectRatio2 = opts.aspectRatio === "9:16" ? "9:16" : "16:9";
1899
+ const inputs = [{ text: prompt3 }];
1900
+ if (image) {
1901
+ inputs.push({ inline_data: { mime_type: image.mimeType, data: image.base64 } });
1902
+ }
1903
+ const body = {
1904
+ model: OMNI_MODEL,
1905
+ inputs,
1906
+ generation_config: {
1907
+ video_config: { task, aspect_ratio: aspectRatio2 }
1908
+ }
1909
+ };
1910
+ try {
1911
+ const res = await fetch(INTERACTIONS_URL, {
1912
+ method: "POST",
1913
+ headers: { "Content-Type": "application/json", "x-goog-api-key": this.apiKey },
1914
+ body: JSON.stringify(body)
1915
+ });
1916
+ const text = await res.text();
1917
+ if (!res.ok) {
1918
+ return {
1919
+ id: "",
1920
+ status: "failed",
1921
+ error: `Gemini Omni (experimental) request failed: HTTP ${res.status} \u2014 ${text.slice(0, 300)}`
1922
+ };
1923
+ }
1924
+ let parsed;
1925
+ try {
1926
+ parsed = JSON.parse(text);
1927
+ } catch {
1928
+ return { id: "", status: "failed", error: "Gemini Omni returned a non-JSON response" };
1929
+ }
1930
+ const videoUrl = findVideoUrl(parsed);
1931
+ const id = parsed?.interaction_id ?? parsed?.name ?? "";
1932
+ if (!videoUrl) {
1933
+ return {
1934
+ id,
1935
+ status: "failed",
1936
+ error: "Gemini Omni response contained no video URL (the preview interactions schema may have changed)."
1937
+ };
1938
+ }
1939
+ return { id, status: "completed", videoUrl };
1940
+ } catch (err) {
1941
+ return {
1942
+ id: "",
1943
+ status: "failed",
1944
+ error: `Gemini Omni (experimental) error: ${err instanceof Error ? err.message : String(err)}`
1945
+ };
1946
+ }
1947
+ }
1948
+ };
1949
+ omniProvider = new OmniProvider();
1950
+ }
1951
+ });
1952
+
1846
1953
  // ../ai-providers/dist/gemini/index.js
1847
1954
  var init_gemini = __esm({
1848
1955
  "../ai-providers/dist/gemini/index.js"() {
@@ -1850,6 +1957,7 @@ var init_gemini = __esm({
1850
1957
  init_GeminiProvider();
1851
1958
  init_gemini_motion();
1852
1959
  init_gemini_models();
1960
+ init_gemini_omni();
1853
1961
  init_define_provider();
1854
1962
  defineProvider({
1855
1963
  id: "gemini",
@@ -1873,6 +1981,13 @@ var init_gemini = __esm({
1873
1981
  resolverPriority: { video: 3 },
1874
1982
  commandsUnlocked: ["generate video -p veo"]
1875
1983
  });
1984
+ defineProvider({
1985
+ id: "omni",
1986
+ label: "Gemini Omni (experimental)",
1987
+ apiKey: "google",
1988
+ kinds: ["video"],
1989
+ commandsUnlocked: ["generate video -p omni"]
1990
+ });
1876
1991
  }
1877
1992
  });
1878
1993
 
@@ -11436,6 +11551,7 @@ __export(dist_exports, {
11436
11551
  KokoroProvider: () => KokoroProvider,
11437
11552
  OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
11438
11553
  OllamaProvider: () => OllamaProvider,
11554
+ OmniProvider: () => OmniProvider,
11439
11555
  OpenAIImageProvider: () => OpenAIImageProvider,
11440
11556
  OpenAIProvider: () => OpenAIProvider,
11441
11557
  OpenAiTtsProvider: () => OpenAiTtsProvider,
@@ -11466,6 +11582,7 @@ __export(dist_exports, {
11466
11582
  loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
11467
11583
  loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
11468
11584
  ollamaProvider: () => ollamaProvider,
11585
+ omniProvider: () => omniProvider,
11469
11586
  openaiImageProvider: () => openaiImageProvider,
11470
11587
  openaiProvider: () => openaiProvider,
11471
11588
  openaiTtsProvider: () => openaiTtsProvider,
@@ -20713,6 +20830,7 @@ async function executeVideoGenerate(options) {
20713
20830
  runway: "RUNWAY_API_SECRET",
20714
20831
  kling: "KLING_API_KEY",
20715
20832
  veo: "GOOGLE_API_KEY",
20833
+ omni: "GOOGLE_API_KEY",
20716
20834
  seedance: "FAL_API_KEY",
20717
20835
  fal: "FAL_API_KEY"
20718
20836
  };
@@ -20933,6 +21051,31 @@ async function executeVideoGenerate(options) {
20933
21051
  outputPath,
20934
21052
  provider: "grok"
20935
21053
  };
21054
+ } else if (provider === "omni") {
21055
+ const omni = new OmniProvider();
21056
+ await omni.initialize({ apiKey: key2 });
21057
+ const result = await omni.generateVideo(prompt3, {
21058
+ prompt: prompt3,
21059
+ referenceImage,
21060
+ aspectRatio: ratio
21061
+ });
21062
+ if (result.status !== "completed" || !result.videoUrl) {
21063
+ return { success: false, error: result.error || "Gemini Omni generation failed" };
21064
+ }
21065
+ let outputPath;
21066
+ if (output3) {
21067
+ const buffer = await downloadVideo(result.videoUrl, key2);
21068
+ outputPath = resolve4(process.cwd(), output3);
21069
+ await writeFile4(outputPath, buffer);
21070
+ }
21071
+ return {
21072
+ success: true,
21073
+ taskId: result.id,
21074
+ status: "completed",
21075
+ videoUrl: result.videoUrl,
21076
+ outputPath,
21077
+ provider: "omni"
21078
+ };
20936
21079
  }
20937
21080
  return { success: false, error: `Unsupported provider: ${provider}` };
20938
21081
  } catch (error) {
@@ -24636,6 +24779,30 @@ var init_review_report = __esm({
24636
24779
  }
24637
24780
  });
24638
24781
 
24782
+ // ../cli/src/commands/_shared/frontmatter.ts
24783
+ function extractFrontmatter(md) {
24784
+ const raw2 = md.replace(/\r\n/g, "\n");
24785
+ const match2 = raw2.match(FRONTMATTER_RE);
24786
+ if (match2) {
24787
+ try {
24788
+ const parsed = (0, import_yaml2.parse)(match2[1]);
24789
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
24790
+ return { data: parsed, body: raw2.slice(match2[0].length), raw: raw2 };
24791
+ }
24792
+ } catch {
24793
+ }
24794
+ }
24795
+ return { data: null, body: raw2, raw: raw2 };
24796
+ }
24797
+ var import_yaml2, FRONTMATTER_RE;
24798
+ var init_frontmatter = __esm({
24799
+ "../cli/src/commands/_shared/frontmatter.ts"() {
24800
+ "use strict";
24801
+ import_yaml2 = __toESM(require_dist3(), 1);
24802
+ FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
24803
+ }
24804
+ });
24805
+
24639
24806
  // ../cli/src/commands/_shared/storyboard-parse.ts
24640
24807
  function resolveCharacters(frontmatter) {
24641
24808
  const pool = frontmatter?.characters;
@@ -24714,28 +24881,16 @@ function parseStoryboard(md) {
24714
24881
  };
24715
24882
  }
24716
24883
  function extractProjectFrontmatter(md) {
24717
- const match2 = md.match(FRONTMATTER_RE);
24718
- if (!match2) return { frontmatter: void 0, remaining: md };
24719
- let parsed;
24720
- try {
24721
- parsed = (0, import_yaml2.parse)(match2[1]);
24722
- } catch {
24723
- return { frontmatter: void 0, remaining: md };
24724
- }
24725
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
24726
- return { frontmatter: void 0, remaining: md };
24727
- }
24728
- return {
24729
- frontmatter: parsed,
24730
- remaining: md.slice(match2[0].length)
24731
- };
24884
+ const { data, body } = extractFrontmatter(md);
24885
+ if (!data) return { frontmatter: void 0, remaining: md };
24886
+ return { frontmatter: data, remaining: body };
24732
24887
  }
24733
24888
  function extractBeatCues(body) {
24734
24889
  const match2 = body.match(BEAT_CUES_RE);
24735
24890
  if (!match2) return { cues: void 0, body };
24736
24891
  let parsed;
24737
24892
  try {
24738
- parsed = (0, import_yaml2.parse)(match2[1]);
24893
+ parsed = (0, import_yaml3.parse)(match2[1]);
24739
24894
  } catch {
24740
24895
  return { cues: void 0, body };
24741
24896
  }
@@ -24765,16 +24920,16 @@ function parseBeatDuration(body) {
24765
24920
  const n2 = parseFloat(valueMatch[1]);
24766
24921
  return Number.isFinite(n2) && n2 > 0 ? n2 : void 0;
24767
24922
  }
24768
- var import_yaml2, HEADING_RE, BEAT_PREFIX_RE, DURATION_SUBSECTION_RE, DURATION_VALUE_RE, FRONTMATTER_RE, BEAT_CUES_RE;
24923
+ var import_yaml3, HEADING_RE, BEAT_PREFIX_RE, DURATION_SUBSECTION_RE, DURATION_VALUE_RE, BEAT_CUES_RE;
24769
24924
  var init_storyboard_parse = __esm({
24770
24925
  "../cli/src/commands/_shared/storyboard-parse.ts"() {
24771
24926
  "use strict";
24772
- import_yaml2 = __toESM(require_dist3(), 1);
24927
+ import_yaml3 = __toESM(require_dist3(), 1);
24928
+ init_frontmatter();
24773
24929
  HEADING_RE = /^##\s+(.+?)\s*$/gm;
24774
24930
  BEAT_PREFIX_RE = /^Beat\s+(.+?)\s+(?:—|:|-)\s+(.+)$/i;
24775
24931
  DURATION_SUBSECTION_RE = /###\s+Beat\s+duration\s*\n([\s\S]*?)(?=\n###\s|\n##\s|$)/i;
24776
24932
  DURATION_VALUE_RE = /(-?\d+(?:\.\d+)?)\s*(?:s|sec|seconds?)?/i;
24777
- FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
24778
24933
  BEAT_CUES_RE = /^\s*```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
24779
24934
  }
24780
24935
  });
@@ -25743,7 +25898,7 @@ async function readProjectConfig(projectDir) {
25743
25898
  if (existsSync3(legacyPath)) {
25744
25899
  try {
25745
25900
  const raw2 = await readFile5(legacyPath, "utf-8");
25746
- const legacy = (0, import_yaml3.parse)(raw2);
25901
+ const legacy = (0, import_yaml4.parse)(raw2);
25747
25902
  const name = legacy?.name ?? dir.split(/[\\/]/).filter(Boolean).pop() ?? "video";
25748
25903
  const config4 = defaultProjectConfig({
25749
25904
  name,
@@ -25775,11 +25930,11 @@ async function readProjectConfig(projectDir) {
25775
25930
  legacy: false
25776
25931
  };
25777
25932
  }
25778
- var import_yaml3, VIBE_CONFIG_FILENAME, LEGACY_VIBE_PROJECT_FILENAME;
25933
+ var import_yaml4, VIBE_CONFIG_FILENAME, LEGACY_VIBE_PROJECT_FILENAME;
25779
25934
  var init_project_config = __esm({
25780
25935
  "../cli/src/commands/_shared/project-config.ts"() {
25781
25936
  "use strict";
25782
- import_yaml3 = __toESM(require_dist3(), 1);
25937
+ import_yaml4 = __toESM(require_dist3(), 1);
25783
25938
  VIBE_CONFIG_FILENAME = "vibe.config.json";
25784
25939
  LEGACY_VIBE_PROJECT_FILENAME = "vibe.project.yaml";
25785
25940
  }
@@ -25901,6 +26056,7 @@ function buildDesignMd(opts) {
25901
26056
  const { name, style } = opts;
25902
26057
  const roles = designColorRoles(style);
25903
26058
  const frontmatter = `---
26059
+ type: Design
25904
26060
  name: ${name}
25905
26061
  colors:
25906
26062
  primary: "${roles.primary}"
@@ -26025,6 +26181,7 @@ function buildCharactersMd(name) {
26025
26181
  }
26026
26182
  function buildStoryboardMd(name, duration = 12) {
26027
26183
  return `---
26184
+ type: Storyboard
26028
26185
  title: ${name}
26029
26186
  duration: ${duration}
26030
26187
  aspect: 16:9
@@ -471807,7 +471964,7 @@ function setStoryboardCue(markdown, opts) {
471807
471964
  cues[opts.key] = normalizeCueValue(opts.key, opts.value);
471808
471965
  }
471809
471966
  const remainingBody = cue ? section.body.slice(cue.full.length).replace(/^\s*\n/, "") : section.body.replace(/^\s*\n/, "");
471810
- const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml4.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
471967
+ const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
471811
471968
  const nextBody = cueBlock + remainingBody.trimStart();
471812
471969
  const nextSection = section.raw.slice(0, section.headingEnd - section.start) + "\n\n" + nextBody.trimEnd() + "\n";
471813
471970
  return markdown.slice(0, section.start) + nextSection + markdown.slice(section.end);
@@ -471841,7 +471998,7 @@ function storyboardCuesFromInput(opts) {
471841
471998
  }
471842
471999
  function buildStoryboardBeatSection(opts) {
471843
472000
  const title = normalizeTitle(opts.title ?? humanizeBeatId(opts.beatId));
471844
- const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0, import_yaml4.stringify)(opts.cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
472001
+ const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(opts.cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
471845
472002
  const body = opts.body?.trim() || "Scene created with `vibe scene add`. Edit this body if the build flow should recompose it.";
471846
472003
  return `## Beat ${opts.beatId} - ${title}
471847
472004
 
@@ -471900,7 +472057,7 @@ function readLeadingCueBlock(body) {
471900
472057
  const match2 = body.match(LEADING_CUE_RE);
471901
472058
  if (!match2) return null;
471902
472059
  try {
471903
- const parsed = (0, import_yaml4.parse)(match2[2]);
472060
+ const parsed = (0, import_yaml5.parse)(match2[2]);
471904
472061
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
471905
472062
  return { full: match2[0], error: "cue block must parse to a YAML object" };
471906
472063
  }
@@ -471909,11 +472066,11 @@ function readLeadingCueBlock(body) {
471909
472066
  return { full: match2[0], error: error instanceof Error ? error.message : String(error) };
471910
472067
  }
471911
472068
  }
471912
- var import_yaml4, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
472069
+ var import_yaml5, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
471913
472070
  var init_storyboard_edit = __esm({
471914
472071
  "../cli/src/commands/_shared/storyboard-edit.ts"() {
471915
472072
  "use strict";
471916
- import_yaml4 = __toESM(require_dist3(), 1);
472073
+ import_yaml5 = __toESM(require_dist3(), 1);
471917
472074
  init_storyboard_parse();
471918
472075
  STORYBOARD_CUE_KEYS = [
471919
472076
  "duration",
@@ -472815,20 +472972,8 @@ function colorTokens(value) {
472815
472972
  return out;
472816
472973
  }
472817
472974
  function parseDesign(md) {
472818
- const raw2 = md.replace(/\r\n/g, "\n");
472819
- let frontmatter = {};
472820
- let body = raw2;
472821
- const fm = raw2.match(DESIGN_FRONTMATTER_RE);
472822
- if (fm) {
472823
- try {
472824
- const parsed = (0, import_yaml5.parse)(fm[1]);
472825
- if (isPlainObject5(parsed)) {
472826
- frontmatter = parsed;
472827
- body = raw2.slice(fm[0].length);
472828
- }
472829
- } catch {
472830
- }
472831
- }
472975
+ const { data, body, raw: raw2 } = extractFrontmatter(md);
472976
+ const frontmatter = data ?? {};
472832
472977
  const sections = {};
472833
472978
  const headings = [];
472834
472979
  SECTION_RE.lastIndex = 0;
@@ -472864,7 +473009,7 @@ function validateDesignMarkdown(md) {
472864
473009
  const fm = raw2.match(DESIGN_FRONTMATTER_RE);
472865
473010
  if (fm) {
472866
473011
  try {
472867
- const parsed = (0, import_yaml5.parse)(fm[1]);
473012
+ const parsed = (0, import_yaml6.parse)(fm[1]);
472868
473013
  if (!isPlainObject5(parsed)) {
472869
473014
  issues.push({
472870
473015
  severity: "warning",
@@ -472905,11 +473050,12 @@ function validateDesignMarkdown(md) {
472905
473050
  }
472906
473051
  return issues;
472907
473052
  }
472908
- var import_yaml5, DESIGN_FRONTMATTER_RE, SECTION_RE, HEX_RE;
473053
+ var import_yaml6, DESIGN_FRONTMATTER_RE, SECTION_RE, HEX_RE;
472909
473054
  var init_design_parse = __esm({
472910
473055
  "../cli/src/commands/_shared/design-parse.ts"() {
472911
473056
  "use strict";
472912
- import_yaml5 = __toESM(require_dist3(), 1);
473057
+ import_yaml6 = __toESM(require_dist3(), 1);
473058
+ init_frontmatter();
472913
473059
  DESIGN_FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
472914
473060
  SECTION_RE = /^##\s+(.+?)\s*$/gm;
472915
473061
  HEX_RE = /#[0-9a-fA-F]{6}\b/g;
@@ -486295,9 +486441,9 @@ var init_dist4 = __esm({
486295
486441
  import { resolve as resolve65 } from "node:path";
486296
486442
  import { readFile as readFile37, writeFile as writeFile42 } from "node:fs/promises";
486297
486443
  function registerVideoCommand(parent) {
486298
- parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, or Veo)").argument("[prompt]", "Text prompt describing the video (interactive if omitted)").option(
486444
+ parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, Veo, or Gemini Omni)").argument("[prompt]", "Text prompt describing the video (interactive if omitted)").option(
486299
486445
  "-p, --provider <provider>",
486300
- "Provider: seedance (ByteDance Seedance 2.0 via fal.ai), grok, kling, runway, veo. `fal` is a deprecated v0.x alias for seedance and will be removed in 1.0."
486446
+ "Provider: seedance (ByteDance Seedance 2.0 via fal.ai), grok, kling, runway, veo, omni (Gemini Omni, experimental). `fal` is a deprecated v0.x alias for seedance and will be removed in 1.0."
486301
486447
  ).option(
486302
486448
  "-k, --api-key <key>",
486303
486449
  "API key (or set FAL_API_KEY / XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
@@ -486360,10 +486506,11 @@ Examples:
486360
486506
  );
486361
486507
  }
486362
486508
  }
486363
- const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal"];
486509
+ const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal", "omni"];
486364
486510
  const videoEnvMap = {
486365
486511
  grok: "XAI_API_KEY",
486366
486512
  veo: "GOOGLE_API_KEY",
486513
+ omni: "GOOGLE_API_KEY",
486367
486514
  kling: "KLING_API_KEY",
486368
486515
  runway: "RUNWAY_API_SECRET",
486369
486516
  seedance: "FAL_API_KEY"
@@ -486375,7 +486522,7 @@ Examples:
486375
486522
  exitWithError(
486376
486523
  usageError(
486377
486524
  `Invalid provider: ${provider}`,
486378
- "Available providers: seedance, grok, kling, runway, veo. `fal` is a deprecated alias for seedance."
486525
+ "Available providers: seedance, grok, kling, runway, veo, omni (experimental). `fal` is a deprecated alias for seedance."
486379
486526
  )
486380
486527
  );
486381
486528
  }
@@ -486480,6 +486627,7 @@ Examples:
486480
486627
  runway: "RUNWAY_API_SECRET",
486481
486628
  kling: "KLING_API_KEY",
486482
486629
  veo: "GOOGLE_API_KEY",
486630
+ omni: "GOOGLE_API_KEY",
486483
486631
  grok: "XAI_API_KEY",
486484
486632
  seedance: "FAL_API_KEY"
486485
486633
  };
@@ -486487,6 +486635,7 @@ Examples:
486487
486635
  runway: "Runway",
486488
486636
  kling: "Kling",
486489
486637
  veo: "Veo",
486638
+ omni: "Gemini Omni (experimental)",
486490
486639
  grok: "Grok",
486491
486640
  seedance: "Seedance 2.0 via fal.ai"
486492
486641
  };
@@ -486821,6 +486970,16 @@ Examples:
486821
486970
  lastFrame: seedanceEndImage
486822
486971
  });
486823
486972
  finalResult = result;
486973
+ } else if (provider === "omni") {
486974
+ const omni = new OmniProvider();
486975
+ await omni.initialize({ apiKey });
486976
+ spinner2.text = "Generating video with Gemini Omni (experimental)...";
486977
+ result = await omni.generateVideo(prompt3, {
486978
+ prompt: prompt3,
486979
+ referenceImage,
486980
+ aspectRatio: options.ratio
486981
+ });
486982
+ finalResult = result;
486824
486983
  }
486825
486984
  if (!finalResult || finalResult.status !== "completed") {
486826
486985
  spinner2.fail(finalResult?.error || "Generation failed");
@@ -494317,8 +494476,8 @@ var generateVideoTool = defineTool({
494317
494476
  description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, and Veo. Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
494318
494477
  schema: z6.object({
494319
494478
  prompt: z6.string().describe("Text prompt describing the video"),
494320
- provider: z6.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe(
494321
- "Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
494479
+ provider: z6.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
494480
+ "Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider). `omni` = Gemini Omni, experimental/opt-in, uses GOOGLE_API_KEY."
494322
494481
  ),
494323
494482
  image: z6.string().optional().describe("Reference image path for image-to-video"),
494324
494483
  endImage: z6.string().optional().describe("Ending frame image path for Seedance image-to-video"),
@@ -495135,7 +495294,7 @@ import { join as join44 } from "node:path";
495135
495294
  import { z as z9 } from "zod";
495136
495295
 
495137
495296
  // ../cli/src/commands/ai-script-pipeline.ts
495138
- var import_yaml6 = __toESM(require_dist3(), 1);
495297
+ var import_yaml7 = __toESM(require_dist3(), 1);
495139
495298
  init_dist();
495140
495299
  init_api_key();
495141
495300
  init_config();
@@ -495313,7 +495472,7 @@ async function executeRegenerateScene(options) {
495313
495472
  return { ...result, error: `Storyboard not found in: ${outputDir} (expected storyboard.yaml or storyboard.json)` };
495314
495473
  }
495315
495474
  const storyboardContent = await readFile41(storyboardPath, "utf-8");
495316
- const segments = storyboardPath.endsWith(".yaml") ? (0, import_yaml6.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
495475
+ const segments = storyboardPath.endsWith(".yaml") ? (0, import_yaml7.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
495317
495476
  for (const sceneNum of options.scenes) {
495318
495477
  if (sceneNum < 1 || sceneNum > segments.length) {
495319
495478
  return { ...result, error: `Scene ${sceneNum} does not exist. Storyboard has ${segments.length} scenes.` };
@@ -495695,7 +495854,7 @@ Generate the single-person scene image now.`;
495695
495854
  segment.startTime = currentTime;
495696
495855
  currentTime += segment.duration;
495697
495856
  }
495698
- const serialized = storyboardPath.endsWith(".yaml") ? (0, import_yaml6.stringify)({ scenes: segments }, { indent: 2 }) : JSON.stringify(segments, null, 2);
495857
+ const serialized = storyboardPath.endsWith(".yaml") ? (0, import_yaml7.stringify)({ scenes: segments }, { indent: 2 }) : JSON.stringify(segments, null, 2);
495699
495858
  await writeFile45(storyboardPath, serialized, "utf-8");
495700
495859
  }
495701
495860
  result.success = result.failedScenes.length === 0;
@@ -496150,7 +496309,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
496150
496309
  }
496151
496310
 
496152
496311
  // ../cli/src/pipeline/executor.ts
496153
- var import_yaml7 = __toESM(require_dist3(), 1);
496312
+ var import_yaml8 = __toESM(require_dist3(), 1);
496154
496313
  import { resolve as resolve73 } from "node:path";
496155
496314
  import { readFile as readFile44, writeFile as writeFile48, mkdir as mkdir29 } from "node:fs/promises";
496156
496315
  import { existsSync as existsSync68 } from "node:fs";
@@ -496570,7 +496729,7 @@ async function loadPipeline(filePath) {
496570
496729
  throw new Error(`Pipeline file not found: ${absPath}`);
496571
496730
  }
496572
496731
  const content = await readFile44(absPath, "utf-8");
496573
- const manifest2 = (0, import_yaml7.parse)(content);
496732
+ const manifest2 = (0, import_yaml8.parse)(content);
496574
496733
  if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
496575
496734
  if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
496576
496735
  const ids = /* @__PURE__ */ new Set();
@@ -496594,7 +496753,7 @@ async function executePipeline(manifest2, options = {}) {
496594
496753
  const checkpointPath = resolve73(outputDir, CHECKPOINT_FILE);
496595
496754
  if (existsSync68(checkpointPath)) {
496596
496755
  const checkpointContent = await readFile44(checkpointPath, "utf-8");
496597
- const checkpoint = (0, import_yaml7.parse)(checkpointContent);
496756
+ const checkpoint = (0, import_yaml8.parse)(checkpointContent);
496598
496757
  for (const cs of checkpoint.completedSteps) {
496599
496758
  completedSteps.set(cs.id, {
496600
496759
  id: cs.id,
@@ -496713,7 +496872,7 @@ async function executePipeline(manifest2, options = {}) {
496713
496872
  };
496714
496873
  await writeFile48(
496715
496874
  resolve73(outputDir, CHECKPOINT_FILE),
496716
- (0, import_yaml7.stringify)(checkpoint, { indent: 2 }),
496875
+ (0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
496717
496876
  "utf-8"
496718
496877
  );
496719
496878
  } else {
@@ -500561,7 +500720,7 @@ function handleCliFlags(argv, version) {
500561
500720
  }
500562
500721
 
500563
500722
  // src/index.ts
500564
- if (handleCliFlags(process.argv.slice(2), "0.113.24")) {
500723
+ if (handleCliFlags(process.argv.slice(2), "0.113.26")) {
500565
500724
  process.exit(0);
500566
500725
  }
500567
500726
  console.log = (...args) => console.error(...args);
@@ -500574,7 +500733,7 @@ var server2 = new Server(
500574
500733
  {
500575
500734
  name: "vibeframe",
500576
500735
  // Stamped with the package version by build.js at bundle time.
500577
- version: "0.113.24"
500736
+ version: "0.113.26"
500578
500737
  },
500579
500738
  {
500580
500739
  capabilities: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/mcp-server",
3
- "version": "0.113.24",
3
+ "version": "0.113.26",
4
4
  "description": "VibeFrame MCP Server - AI-native video editing via Model Context Protocol",
5
5
  "type": "module",
6
6
  "bin": {
@@ -60,8 +60,8 @@
60
60
  "tsx": "^4.21.0",
61
61
  "typescript": "^5.3.3",
62
62
  "vitest": "^1.2.2",
63
- "@vibeframe/cli": "0.113.24",
64
- "@vibeframe/core": "0.113.24"
63
+ "@vibeframe/cli": "0.113.26",
64
+ "@vibeframe/core": "0.113.26"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">=20"