@vibeframe/cli 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.
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module _shared/frontmatter
|
|
3
|
+
*
|
|
4
|
+
* One canonical "YAML frontmatter + markdown body" splitter for all VibeFrame
|
|
5
|
+
* `.md` files. Previously each consumer (storyboard, design, install-skill)
|
|
6
|
+
* declared its own `/^---\n…\n---/` regex + `yaml.parse` — this consolidates
|
|
7
|
+
* them.
|
|
8
|
+
*
|
|
9
|
+
* The shape matches Google's Open Knowledge Format (OKF) and Mintlify: a leading
|
|
10
|
+
* `---` YAML block, then a free-form markdown body. VibeFrame project files
|
|
11
|
+
* (STORYBOARD.md, DESIGN.md, CHARACTERS.md, …) are OKF concept documents; docs/
|
|
12
|
+
* pages carry OKF/Mintlify frontmatter (`type`, `title`, `description`, `tags`).
|
|
13
|
+
*/
|
|
14
|
+
/** Leading `---\n…\n---` block. Anchored to the start of the (normalized) text. */
|
|
15
|
+
export declare const FRONTMATTER_RE: RegExp;
|
|
16
|
+
export interface ExtractedFrontmatter {
|
|
17
|
+
/** Parsed frontmatter map, or `null` when absent / invalid / not a map. */
|
|
18
|
+
data: Record<string, unknown> | null;
|
|
19
|
+
/** Markdown body after the frontmatter block (or the whole doc when absent). */
|
|
20
|
+
body: string;
|
|
21
|
+
/** The full document, CRLF-normalized to LF. */
|
|
22
|
+
raw: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Split a leading YAML frontmatter block from the markdown body. CRLF is
|
|
26
|
+
* normalized to LF. Returns `data: null` (freeform) when there is no leading
|
|
27
|
+
* block, the YAML is invalid, or it is not a plain object — callers decide
|
|
28
|
+
* whether that means `undefined` or `{}`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractFrontmatter(md: string): ExtractedFrontmatter;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
export interface VideoGenerateOptions {
|
|
16
16
|
prompt: string;
|
|
17
|
-
provider?: "grok" | "runway" | "kling" | "veo" | "seedance" | "fal";
|
|
17
|
+
provider?: "grok" | "runway" | "kling" | "veo" | "seedance" | "fal" | "omni";
|
|
18
18
|
image?: string;
|
|
19
19
|
refImages?: string[];
|
|
20
20
|
refVideos?: string[];
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module generate/video
|
|
3
3
|
* @description `vibe generate video` (alias `vid`) — multi-provider video
|
|
4
|
-
* generation. fal.ai (Seedance 2.0), Grok, Veo (Gemini), Kling, Runway
|
|
4
|
+
* generation. fal.ai (Seedance 2.0), Grok, Veo (Gemini), Kling, Runway,
|
|
5
|
+
* plus experimental Gemini Omni (`-p omni`).
|
|
5
6
|
* Split out of `generate.ts` in v0.69 (Plan G Phase 2).
|
|
6
7
|
*/
|
|
7
8
|
import type { Command } from "commander";
|
package/dist/index.js
CHANGED
|
@@ -8609,6 +8609,113 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
8609
8609
|
}
|
|
8610
8610
|
});
|
|
8611
8611
|
|
|
8612
|
+
// ../ai-providers/dist/gemini/gemini-omni.js
|
|
8613
|
+
function firstReferenceImage(options) {
|
|
8614
|
+
const refs = options.referenceImages;
|
|
8615
|
+
if (refs && refs.length > 0 && refs[0].base64)
|
|
8616
|
+
return refs[0];
|
|
8617
|
+
const ref = options.referenceImage;
|
|
8618
|
+
if (typeof ref === "string" && ref) {
|
|
8619
|
+
const m = ref.match(/^data:(.+?);base64,(.*)$/);
|
|
8620
|
+
if (m)
|
|
8621
|
+
return { mimeType: m[1], base64: m[2] };
|
|
8622
|
+
return { mimeType: "image/png", base64: ref };
|
|
8623
|
+
}
|
|
8624
|
+
return void 0;
|
|
8625
|
+
}
|
|
8626
|
+
function findVideoUrl(obj) {
|
|
8627
|
+
if (!obj || typeof obj !== "object")
|
|
8628
|
+
return void 0;
|
|
8629
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
8630
|
+
if (typeof v === "string" && /^https?:\/\//.test(v) && /(uri|url|video)/i.test(k))
|
|
8631
|
+
return v;
|
|
8632
|
+
if (typeof v === "object") {
|
|
8633
|
+
const nested = findVideoUrl(v);
|
|
8634
|
+
if (nested)
|
|
8635
|
+
return nested;
|
|
8636
|
+
}
|
|
8637
|
+
}
|
|
8638
|
+
return void 0;
|
|
8639
|
+
}
|
|
8640
|
+
var OMNI_MODEL, INTERACTIONS_URL, OmniProvider, omniProvider;
|
|
8641
|
+
var init_gemini_omni = __esm({
|
|
8642
|
+
"../ai-providers/dist/gemini/gemini-omni.js"() {
|
|
8643
|
+
"use strict";
|
|
8644
|
+
OMNI_MODEL = "gemini-omni-flash-preview";
|
|
8645
|
+
INTERACTIONS_URL = "https://generativelanguage.googleapis.com/v1beta/interactions";
|
|
8646
|
+
OmniProvider = class {
|
|
8647
|
+
constructor() {
|
|
8648
|
+
this.id = "omni";
|
|
8649
|
+
this.label = "Gemini Omni (experimental)";
|
|
8650
|
+
}
|
|
8651
|
+
async initialize(config2) {
|
|
8652
|
+
this.apiKey = config2.apiKey;
|
|
8653
|
+
}
|
|
8654
|
+
isConfigured() {
|
|
8655
|
+
return !!this.apiKey;
|
|
8656
|
+
}
|
|
8657
|
+
async generateVideo(prompt3, options) {
|
|
8658
|
+
if (!this.apiKey) {
|
|
8659
|
+
return { id: "", status: "failed", error: "GOOGLE_API_KEY not configured for Gemini Omni" };
|
|
8660
|
+
}
|
|
8661
|
+
const opts = options ?? { prompt: prompt3 };
|
|
8662
|
+
const image = firstReferenceImage(opts);
|
|
8663
|
+
const task = image ? "image_to_video" : "text_to_video";
|
|
8664
|
+
const aspectRatio2 = opts.aspectRatio === "9:16" ? "9:16" : "16:9";
|
|
8665
|
+
const inputs = [{ text: prompt3 }];
|
|
8666
|
+
if (image) {
|
|
8667
|
+
inputs.push({ inline_data: { mime_type: image.mimeType, data: image.base64 } });
|
|
8668
|
+
}
|
|
8669
|
+
const body = {
|
|
8670
|
+
model: OMNI_MODEL,
|
|
8671
|
+
inputs,
|
|
8672
|
+
generation_config: {
|
|
8673
|
+
video_config: { task, aspect_ratio: aspectRatio2 }
|
|
8674
|
+
}
|
|
8675
|
+
};
|
|
8676
|
+
try {
|
|
8677
|
+
const res = await fetch(INTERACTIONS_URL, {
|
|
8678
|
+
method: "POST",
|
|
8679
|
+
headers: { "Content-Type": "application/json", "x-goog-api-key": this.apiKey },
|
|
8680
|
+
body: JSON.stringify(body)
|
|
8681
|
+
});
|
|
8682
|
+
const text = await res.text();
|
|
8683
|
+
if (!res.ok) {
|
|
8684
|
+
return {
|
|
8685
|
+
id: "",
|
|
8686
|
+
status: "failed",
|
|
8687
|
+
error: `Gemini Omni (experimental) request failed: HTTP ${res.status} \u2014 ${text.slice(0, 300)}`
|
|
8688
|
+
};
|
|
8689
|
+
}
|
|
8690
|
+
let parsed;
|
|
8691
|
+
try {
|
|
8692
|
+
parsed = JSON.parse(text);
|
|
8693
|
+
} catch {
|
|
8694
|
+
return { id: "", status: "failed", error: "Gemini Omni returned a non-JSON response" };
|
|
8695
|
+
}
|
|
8696
|
+
const videoUrl = findVideoUrl(parsed);
|
|
8697
|
+
const id = parsed?.interaction_id ?? parsed?.name ?? "";
|
|
8698
|
+
if (!videoUrl) {
|
|
8699
|
+
return {
|
|
8700
|
+
id,
|
|
8701
|
+
status: "failed",
|
|
8702
|
+
error: "Gemini Omni response contained no video URL (the preview interactions schema may have changed)."
|
|
8703
|
+
};
|
|
8704
|
+
}
|
|
8705
|
+
return { id, status: "completed", videoUrl };
|
|
8706
|
+
} catch (err) {
|
|
8707
|
+
return {
|
|
8708
|
+
id: "",
|
|
8709
|
+
status: "failed",
|
|
8710
|
+
error: `Gemini Omni (experimental) error: ${err instanceof Error ? err.message : String(err)}`
|
|
8711
|
+
};
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
8714
|
+
};
|
|
8715
|
+
omniProvider = new OmniProvider();
|
|
8716
|
+
}
|
|
8717
|
+
});
|
|
8718
|
+
|
|
8612
8719
|
// ../ai-providers/dist/gemini/index.js
|
|
8613
8720
|
var init_gemini = __esm({
|
|
8614
8721
|
"../ai-providers/dist/gemini/index.js"() {
|
|
@@ -8616,6 +8723,7 @@ var init_gemini = __esm({
|
|
|
8616
8723
|
init_GeminiProvider();
|
|
8617
8724
|
init_gemini_motion();
|
|
8618
8725
|
init_gemini_models();
|
|
8726
|
+
init_gemini_omni();
|
|
8619
8727
|
init_define_provider();
|
|
8620
8728
|
defineProvider({
|
|
8621
8729
|
id: "gemini",
|
|
@@ -8639,6 +8747,13 @@ var init_gemini = __esm({
|
|
|
8639
8747
|
resolverPriority: { video: 3 },
|
|
8640
8748
|
commandsUnlocked: ["generate video -p veo"]
|
|
8641
8749
|
});
|
|
8750
|
+
defineProvider({
|
|
8751
|
+
id: "omni",
|
|
8752
|
+
label: "Gemini Omni (experimental)",
|
|
8753
|
+
apiKey: "google",
|
|
8754
|
+
kinds: ["video"],
|
|
8755
|
+
commandsUnlocked: ["generate video -p omni"]
|
|
8756
|
+
});
|
|
8642
8757
|
}
|
|
8643
8758
|
});
|
|
8644
8759
|
|
|
@@ -18202,6 +18317,7 @@ __export(dist_exports2, {
|
|
|
18202
18317
|
KokoroProvider: () => KokoroProvider,
|
|
18203
18318
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
18204
18319
|
OllamaProvider: () => OllamaProvider,
|
|
18320
|
+
OmniProvider: () => OmniProvider,
|
|
18205
18321
|
OpenAIImageProvider: () => OpenAIImageProvider,
|
|
18206
18322
|
OpenAIProvider: () => OpenAIProvider,
|
|
18207
18323
|
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
@@ -18232,6 +18348,7 @@ __export(dist_exports2, {
|
|
|
18232
18348
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
18233
18349
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
18234
18350
|
ollamaProvider: () => ollamaProvider,
|
|
18351
|
+
omniProvider: () => omniProvider,
|
|
18235
18352
|
openaiImageProvider: () => openaiImageProvider,
|
|
18236
18353
|
openaiProvider: () => openaiProvider,
|
|
18237
18354
|
openaiTtsProvider: () => openaiTtsProvider,
|
|
@@ -26756,6 +26873,7 @@ function buildDesignMd(opts) {
|
|
|
26756
26873
|
const { name, style } = opts;
|
|
26757
26874
|
const roles = designColorRoles(style);
|
|
26758
26875
|
const frontmatter = `---
|
|
26876
|
+
type: Design
|
|
26759
26877
|
name: ${name}
|
|
26760
26878
|
colors:
|
|
26761
26879
|
primary: "${roles.primary}"
|
|
@@ -26880,6 +26998,7 @@ function buildCharactersMd(name) {
|
|
|
26880
26998
|
}
|
|
26881
26999
|
function buildStoryboardMd(name, duration = 12) {
|
|
26882
27000
|
return `---
|
|
27001
|
+
type: Storyboard
|
|
26883
27002
|
title: ${name}
|
|
26884
27003
|
duration: ${duration}
|
|
26885
27004
|
aspect: 16:9
|
|
@@ -29493,6 +29612,30 @@ var init_install_skill = __esm({
|
|
|
29493
29612
|
}
|
|
29494
29613
|
});
|
|
29495
29614
|
|
|
29615
|
+
// src/commands/_shared/frontmatter.ts
|
|
29616
|
+
function extractFrontmatter(md) {
|
|
29617
|
+
const raw = md.replace(/\r\n/g, "\n");
|
|
29618
|
+
const match = raw.match(FRONTMATTER_RE);
|
|
29619
|
+
if (match) {
|
|
29620
|
+
try {
|
|
29621
|
+
const parsed = (0, import_yaml3.parse)(match[1]);
|
|
29622
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
29623
|
+
return { data: parsed, body: raw.slice(match[0].length), raw };
|
|
29624
|
+
}
|
|
29625
|
+
} catch {
|
|
29626
|
+
}
|
|
29627
|
+
}
|
|
29628
|
+
return { data: null, body: raw, raw };
|
|
29629
|
+
}
|
|
29630
|
+
var import_yaml3, FRONTMATTER_RE;
|
|
29631
|
+
var init_frontmatter = __esm({
|
|
29632
|
+
"src/commands/_shared/frontmatter.ts"() {
|
|
29633
|
+
"use strict";
|
|
29634
|
+
import_yaml3 = __toESM(require_dist2(), 1);
|
|
29635
|
+
FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
29636
|
+
}
|
|
29637
|
+
});
|
|
29638
|
+
|
|
29496
29639
|
// src/commands/_shared/storyboard-parse.ts
|
|
29497
29640
|
function resolveCharacters(frontmatter) {
|
|
29498
29641
|
const pool = frontmatter?.characters;
|
|
@@ -29571,28 +29714,16 @@ function parseStoryboard(md) {
|
|
|
29571
29714
|
};
|
|
29572
29715
|
}
|
|
29573
29716
|
function extractProjectFrontmatter(md) {
|
|
29574
|
-
const
|
|
29575
|
-
if (!
|
|
29576
|
-
|
|
29577
|
-
try {
|
|
29578
|
-
parsed = (0, import_yaml3.parse)(match[1]);
|
|
29579
|
-
} catch {
|
|
29580
|
-
return { frontmatter: void 0, remaining: md };
|
|
29581
|
-
}
|
|
29582
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
29583
|
-
return { frontmatter: void 0, remaining: md };
|
|
29584
|
-
}
|
|
29585
|
-
return {
|
|
29586
|
-
frontmatter: parsed,
|
|
29587
|
-
remaining: md.slice(match[0].length)
|
|
29588
|
-
};
|
|
29717
|
+
const { data, body } = extractFrontmatter(md);
|
|
29718
|
+
if (!data) return { frontmatter: void 0, remaining: md };
|
|
29719
|
+
return { frontmatter: data, remaining: body };
|
|
29589
29720
|
}
|
|
29590
29721
|
function extractBeatCues(body) {
|
|
29591
29722
|
const match = body.match(BEAT_CUES_RE);
|
|
29592
29723
|
if (!match) return { cues: void 0, body };
|
|
29593
29724
|
let parsed;
|
|
29594
29725
|
try {
|
|
29595
|
-
parsed = (0,
|
|
29726
|
+
parsed = (0, import_yaml4.parse)(match[1]);
|
|
29596
29727
|
} catch {
|
|
29597
29728
|
return { cues: void 0, body };
|
|
29598
29729
|
}
|
|
@@ -29622,16 +29753,16 @@ function parseBeatDuration(body) {
|
|
|
29622
29753
|
const n = parseFloat(valueMatch[1]);
|
|
29623
29754
|
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
29624
29755
|
}
|
|
29625
|
-
var
|
|
29756
|
+
var import_yaml4, HEADING_RE, BEAT_PREFIX_RE, DURATION_SUBSECTION_RE, DURATION_VALUE_RE, BEAT_CUES_RE;
|
|
29626
29757
|
var init_storyboard_parse = __esm({
|
|
29627
29758
|
"src/commands/_shared/storyboard-parse.ts"() {
|
|
29628
29759
|
"use strict";
|
|
29629
|
-
|
|
29760
|
+
import_yaml4 = __toESM(require_dist2(), 1);
|
|
29761
|
+
init_frontmatter();
|
|
29630
29762
|
HEADING_RE = /^##\s+(.+?)\s*$/gm;
|
|
29631
29763
|
BEAT_PREFIX_RE = /^Beat\s+(.+?)\s+(?:—|:|-)\s+(.+)$/i;
|
|
29632
29764
|
DURATION_SUBSECTION_RE = /###\s+Beat\s+duration\s*\n([\s\S]*?)(?=\n###\s|\n##\s|$)/i;
|
|
29633
29765
|
DURATION_VALUE_RE = /(-?\d+(?:\.\d+)?)\s*(?:s|sec|seconds?)?/i;
|
|
29634
|
-
FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
29635
29766
|
BEAT_CUES_RE = /^\s*```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
|
|
29636
29767
|
}
|
|
29637
29768
|
});
|
|
@@ -32004,7 +32135,7 @@ function setStoryboardCue(markdown, opts) {
|
|
|
32004
32135
|
cues[opts.key] = normalizeCueValue(opts.key, opts.value);
|
|
32005
32136
|
}
|
|
32006
32137
|
const remainingBody = cue ? section.body.slice(cue.full.length).replace(/^\s*\n/, "") : section.body.replace(/^\s*\n/, "");
|
|
32007
|
-
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0,
|
|
32138
|
+
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
32008
32139
|
const nextBody = cueBlock + remainingBody.trimStart();
|
|
32009
32140
|
const nextSection = section.raw.slice(0, section.headingEnd - section.start) + "\n\n" + nextBody.trimEnd() + "\n";
|
|
32010
32141
|
return markdown.slice(0, section.start) + nextSection + markdown.slice(section.end);
|
|
@@ -32038,7 +32169,7 @@ function storyboardCuesFromInput(opts) {
|
|
|
32038
32169
|
}
|
|
32039
32170
|
function buildStoryboardBeatSection(opts) {
|
|
32040
32171
|
const title = normalizeTitle(opts.title ?? humanizeBeatId(opts.beatId));
|
|
32041
|
-
const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0,
|
|
32172
|
+
const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(opts.cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
32042
32173
|
const body = opts.body?.trim() || "Scene created with `vibe scene add`. Edit this body if the build flow should recompose it.";
|
|
32043
32174
|
return `## Beat ${opts.beatId} - ${title}
|
|
32044
32175
|
|
|
@@ -32097,7 +32228,7 @@ function readLeadingCueBlock(body) {
|
|
|
32097
32228
|
const match = body.match(LEADING_CUE_RE);
|
|
32098
32229
|
if (!match) return null;
|
|
32099
32230
|
try {
|
|
32100
|
-
const parsed = (0,
|
|
32231
|
+
const parsed = (0, import_yaml5.parse)(match[2]);
|
|
32101
32232
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
32102
32233
|
return { full: match[0], error: "cue block must parse to a YAML object" };
|
|
32103
32234
|
}
|
|
@@ -32106,11 +32237,11 @@ function readLeadingCueBlock(body) {
|
|
|
32106
32237
|
return { full: match[0], error: error instanceof Error ? error.message : String(error) };
|
|
32107
32238
|
}
|
|
32108
32239
|
}
|
|
32109
|
-
var
|
|
32240
|
+
var import_yaml5, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
|
|
32110
32241
|
var init_storyboard_edit = __esm({
|
|
32111
32242
|
"src/commands/_shared/storyboard-edit.ts"() {
|
|
32112
32243
|
"use strict";
|
|
32113
|
-
|
|
32244
|
+
import_yaml5 = __toESM(require_dist2(), 1);
|
|
32114
32245
|
init_storyboard_parse();
|
|
32115
32246
|
STORYBOARD_CUE_KEYS = [
|
|
32116
32247
|
"duration",
|
|
@@ -35976,6 +36107,7 @@ async function executeVideoGenerate(options) {
|
|
|
35976
36107
|
runway: "RUNWAY_API_SECRET",
|
|
35977
36108
|
kling: "KLING_API_KEY",
|
|
35978
36109
|
veo: "GOOGLE_API_KEY",
|
|
36110
|
+
omni: "GOOGLE_API_KEY",
|
|
35979
36111
|
seedance: "FAL_API_KEY",
|
|
35980
36112
|
fal: "FAL_API_KEY"
|
|
35981
36113
|
};
|
|
@@ -36196,6 +36328,31 @@ async function executeVideoGenerate(options) {
|
|
|
36196
36328
|
outputPath,
|
|
36197
36329
|
provider: "grok"
|
|
36198
36330
|
};
|
|
36331
|
+
} else if (provider === "omni") {
|
|
36332
|
+
const omni = new OmniProvider();
|
|
36333
|
+
await omni.initialize({ apiKey: key });
|
|
36334
|
+
const result = await omni.generateVideo(prompt3, {
|
|
36335
|
+
prompt: prompt3,
|
|
36336
|
+
referenceImage,
|
|
36337
|
+
aspectRatio: ratio
|
|
36338
|
+
});
|
|
36339
|
+
if (result.status !== "completed" || !result.videoUrl) {
|
|
36340
|
+
return { success: false, error: result.error || "Gemini Omni generation failed" };
|
|
36341
|
+
}
|
|
36342
|
+
let outputPath;
|
|
36343
|
+
if (output) {
|
|
36344
|
+
const buffer = await downloadVideo(result.videoUrl, key);
|
|
36345
|
+
outputPath = resolve25(process.cwd(), output);
|
|
36346
|
+
await writeFile21(outputPath, buffer);
|
|
36347
|
+
}
|
|
36348
|
+
return {
|
|
36349
|
+
success: true,
|
|
36350
|
+
taskId: result.id,
|
|
36351
|
+
status: "completed",
|
|
36352
|
+
videoUrl: result.videoUrl,
|
|
36353
|
+
outputPath,
|
|
36354
|
+
provider: "omni"
|
|
36355
|
+
};
|
|
36199
36356
|
}
|
|
36200
36357
|
return { success: false, error: `Unsupported provider: ${provider}` };
|
|
36201
36358
|
} catch (error) {
|
|
@@ -40156,9 +40313,9 @@ var init_dist3 = __esm({
|
|
|
40156
40313
|
import { resolve as resolve33 } from "node:path";
|
|
40157
40314
|
import { readFile as readFile21, writeFile as writeFile30 } from "node:fs/promises";
|
|
40158
40315
|
function registerVideoCommand(parent) {
|
|
40159
|
-
parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, or
|
|
40316
|
+
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(
|
|
40160
40317
|
"-p, --provider <provider>",
|
|
40161
|
-
"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."
|
|
40318
|
+
"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."
|
|
40162
40319
|
).option(
|
|
40163
40320
|
"-k, --api-key <key>",
|
|
40164
40321
|
"API key (or set FAL_API_KEY / XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
|
|
@@ -40221,10 +40378,11 @@ Examples:
|
|
|
40221
40378
|
);
|
|
40222
40379
|
}
|
|
40223
40380
|
}
|
|
40224
|
-
const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal"];
|
|
40381
|
+
const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal", "omni"];
|
|
40225
40382
|
const videoEnvMap = {
|
|
40226
40383
|
grok: "XAI_API_KEY",
|
|
40227
40384
|
veo: "GOOGLE_API_KEY",
|
|
40385
|
+
omni: "GOOGLE_API_KEY",
|
|
40228
40386
|
kling: "KLING_API_KEY",
|
|
40229
40387
|
runway: "RUNWAY_API_SECRET",
|
|
40230
40388
|
seedance: "FAL_API_KEY"
|
|
@@ -40236,7 +40394,7 @@ Examples:
|
|
|
40236
40394
|
exitWithError(
|
|
40237
40395
|
usageError(
|
|
40238
40396
|
`Invalid provider: ${provider}`,
|
|
40239
|
-
"Available providers: seedance, grok, kling, runway, veo. `fal` is a deprecated alias for seedance."
|
|
40397
|
+
"Available providers: seedance, grok, kling, runway, veo, omni (experimental). `fal` is a deprecated alias for seedance."
|
|
40240
40398
|
)
|
|
40241
40399
|
);
|
|
40242
40400
|
}
|
|
@@ -40341,6 +40499,7 @@ Examples:
|
|
|
40341
40499
|
runway: "RUNWAY_API_SECRET",
|
|
40342
40500
|
kling: "KLING_API_KEY",
|
|
40343
40501
|
veo: "GOOGLE_API_KEY",
|
|
40502
|
+
omni: "GOOGLE_API_KEY",
|
|
40344
40503
|
grok: "XAI_API_KEY",
|
|
40345
40504
|
seedance: "FAL_API_KEY"
|
|
40346
40505
|
};
|
|
@@ -40348,6 +40507,7 @@ Examples:
|
|
|
40348
40507
|
runway: "Runway",
|
|
40349
40508
|
kling: "Kling",
|
|
40350
40509
|
veo: "Veo",
|
|
40510
|
+
omni: "Gemini Omni (experimental)",
|
|
40351
40511
|
grok: "Grok",
|
|
40352
40512
|
seedance: "Seedance 2.0 via fal.ai"
|
|
40353
40513
|
};
|
|
@@ -40682,6 +40842,16 @@ Examples:
|
|
|
40682
40842
|
lastFrame: seedanceEndImage
|
|
40683
40843
|
});
|
|
40684
40844
|
finalResult = result;
|
|
40845
|
+
} else if (provider === "omni") {
|
|
40846
|
+
const omni = new OmniProvider();
|
|
40847
|
+
await omni.initialize({ apiKey });
|
|
40848
|
+
spinner2.text = "Generating video with Gemini Omni (experimental)...";
|
|
40849
|
+
result = await omni.generateVideo(prompt3, {
|
|
40850
|
+
prompt: prompt3,
|
|
40851
|
+
referenceImage,
|
|
40852
|
+
aspectRatio: options.ratio
|
|
40853
|
+
});
|
|
40854
|
+
finalResult = result;
|
|
40685
40855
|
}
|
|
40686
40856
|
if (!finalResult || finalResult.status !== "completed") {
|
|
40687
40857
|
spinner2.fail(finalResult?.error || "Generation failed");
|
|
@@ -47153,7 +47323,7 @@ async function executeRegenerateScene(options) {
|
|
|
47153
47323
|
return { ...result, error: `Storyboard not found in: ${outputDir} (expected storyboard.yaml or storyboard.json)` };
|
|
47154
47324
|
}
|
|
47155
47325
|
const storyboardContent = await readFile34(storyboardPath2, "utf-8");
|
|
47156
|
-
const segments = storyboardPath2.endsWith(".yaml") ? (0,
|
|
47326
|
+
const segments = storyboardPath2.endsWith(".yaml") ? (0, import_yaml6.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
|
|
47157
47327
|
for (const sceneNum of options.scenes) {
|
|
47158
47328
|
if (sceneNum < 1 || sceneNum > segments.length) {
|
|
47159
47329
|
return { ...result, error: `Scene ${sceneNum} does not exist. Storyboard has ${segments.length} scenes.` };
|
|
@@ -47535,7 +47705,7 @@ Generate the single-person scene image now.`;
|
|
|
47535
47705
|
segment.startTime = currentTime;
|
|
47536
47706
|
currentTime += segment.duration;
|
|
47537
47707
|
}
|
|
47538
|
-
const serialized = storyboardPath2.endsWith(".yaml") ? (0,
|
|
47708
|
+
const serialized = storyboardPath2.endsWith(".yaml") ? (0, import_yaml6.stringify)({ scenes: segments }, { indent: 2 }) : JSON.stringify(segments, null, 2);
|
|
47539
47709
|
await writeFile39(storyboardPath2, serialized, "utf-8");
|
|
47540
47710
|
}
|
|
47541
47711
|
result.success = result.failedScenes.length === 0;
|
|
@@ -47547,11 +47717,11 @@ Generate the single-person scene image now.`;
|
|
|
47547
47717
|
};
|
|
47548
47718
|
}
|
|
47549
47719
|
}
|
|
47550
|
-
var
|
|
47720
|
+
var import_yaml6;
|
|
47551
47721
|
var init_ai_script_pipeline = __esm({
|
|
47552
47722
|
"src/commands/ai-script-pipeline.ts"() {
|
|
47553
47723
|
"use strict";
|
|
47554
|
-
|
|
47724
|
+
import_yaml6 = __toESM(require_dist2(), 1);
|
|
47555
47725
|
init_dist2();
|
|
47556
47726
|
init_api_key();
|
|
47557
47727
|
init_config();
|
|
@@ -60714,20 +60884,8 @@ function colorTokens(value) {
|
|
|
60714
60884
|
return out;
|
|
60715
60885
|
}
|
|
60716
60886
|
function parseDesign(md) {
|
|
60717
|
-
const raw = md
|
|
60718
|
-
|
|
60719
|
-
let body = raw;
|
|
60720
|
-
const fm = raw.match(DESIGN_FRONTMATTER_RE);
|
|
60721
|
-
if (fm) {
|
|
60722
|
-
try {
|
|
60723
|
-
const parsed = (0, import_yaml7.parse)(fm[1]);
|
|
60724
|
-
if (isPlainObject(parsed)) {
|
|
60725
|
-
frontmatter = parsed;
|
|
60726
|
-
body = raw.slice(fm[0].length);
|
|
60727
|
-
}
|
|
60728
|
-
} catch {
|
|
60729
|
-
}
|
|
60730
|
-
}
|
|
60887
|
+
const { data, body, raw } = extractFrontmatter(md);
|
|
60888
|
+
const frontmatter = data ?? {};
|
|
60731
60889
|
const sections = {};
|
|
60732
60890
|
const headings = [];
|
|
60733
60891
|
SECTION_RE.lastIndex = 0;
|
|
@@ -60763,7 +60921,7 @@ function validateDesignMarkdown(md) {
|
|
|
60763
60921
|
const fm = raw.match(DESIGN_FRONTMATTER_RE);
|
|
60764
60922
|
if (fm) {
|
|
60765
60923
|
try {
|
|
60766
|
-
const parsed = (0,
|
|
60924
|
+
const parsed = (0, import_yaml8.parse)(fm[1]);
|
|
60767
60925
|
if (!isPlainObject(parsed)) {
|
|
60768
60926
|
issues.push({
|
|
60769
60927
|
severity: "warning",
|
|
@@ -60804,11 +60962,12 @@ function validateDesignMarkdown(md) {
|
|
|
60804
60962
|
}
|
|
60805
60963
|
return issues;
|
|
60806
60964
|
}
|
|
60807
|
-
var
|
|
60965
|
+
var import_yaml8, DESIGN_FRONTMATTER_RE, SECTION_RE, HEX_RE;
|
|
60808
60966
|
var init_design_parse = __esm({
|
|
60809
60967
|
"src/commands/_shared/design-parse.ts"() {
|
|
60810
60968
|
"use strict";
|
|
60811
|
-
|
|
60969
|
+
import_yaml8 = __toESM(require_dist2(), 1);
|
|
60970
|
+
init_frontmatter();
|
|
60812
60971
|
DESIGN_FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
60813
60972
|
SECTION_RE = /^##\s+(.+?)\s*$/gm;
|
|
60814
60973
|
HEX_RE = /#[0-9a-fA-F]{6}\b/g;
|
|
@@ -65773,7 +65932,7 @@ async function loadPipeline(filePath) {
|
|
|
65773
65932
|
throw new Error(`Pipeline file not found: ${absPath}`);
|
|
65774
65933
|
}
|
|
65775
65934
|
const content = await readFile53(absPath, "utf-8");
|
|
65776
|
-
const manifest2 = (0,
|
|
65935
|
+
const manifest2 = (0, import_yaml9.parse)(content);
|
|
65777
65936
|
if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
|
|
65778
65937
|
if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
|
|
65779
65938
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -65796,7 +65955,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
65796
65955
|
const checkpointPath = resolve79(outputDir, CHECKPOINT_FILE);
|
|
65797
65956
|
if (existsSync59(checkpointPath)) {
|
|
65798
65957
|
const checkpointContent = await readFile53(checkpointPath, "utf-8");
|
|
65799
|
-
const checkpoint = (0,
|
|
65958
|
+
const checkpoint = (0, import_yaml9.parse)(checkpointContent);
|
|
65800
65959
|
for (const cs of checkpoint.completedSteps) {
|
|
65801
65960
|
completedSteps.set(cs.id, {
|
|
65802
65961
|
id: cs.id,
|
|
@@ -65915,7 +66074,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
65915
66074
|
};
|
|
65916
66075
|
await writeFile53(
|
|
65917
66076
|
resolve79(outputDir, CHECKPOINT_FILE),
|
|
65918
|
-
(0,
|
|
66077
|
+
(0, import_yaml9.stringify)(checkpoint, { indent: 2 }),
|
|
65919
66078
|
"utf-8"
|
|
65920
66079
|
);
|
|
65921
66080
|
} else {
|
|
@@ -65961,11 +66120,11 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
65961
66120
|
budget: effectiveBudget ? budgetUsage : void 0
|
|
65962
66121
|
};
|
|
65963
66122
|
}
|
|
65964
|
-
var
|
|
66123
|
+
var import_yaml9, ACTION_METADATA, ACTION_HANDLERS, CHECKPOINT_FILE;
|
|
65965
66124
|
var init_executor = __esm({
|
|
65966
66125
|
"src/pipeline/executor.ts"() {
|
|
65967
66126
|
"use strict";
|
|
65968
|
-
|
|
66127
|
+
import_yaml9 = __toESM(require_dist2(), 1);
|
|
65969
66128
|
init_resolver();
|
|
65970
66129
|
init_output();
|
|
65971
66130
|
init_config();
|
|
@@ -72339,8 +72498,8 @@ var init_generate2 = __esm({
|
|
|
72339
72498
|
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.",
|
|
72340
72499
|
schema: external_exports.object({
|
|
72341
72500
|
prompt: external_exports.string().describe("Text prompt describing the video"),
|
|
72342
|
-
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe(
|
|
72343
|
-
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
|
|
72501
|
+
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
|
|
72502
|
+
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider). `omni` = Gemini Omni, experimental/opt-in, uses GOOGLE_API_KEY."
|
|
72344
72503
|
),
|
|
72345
72504
|
image: external_exports.string().optional().describe("Reference image path for image-to-video"),
|
|
72346
72505
|
endImage: external_exports.string().optional().describe("Ending frame image path for Seedance image-to-video"),
|
|
@@ -75683,7 +75842,7 @@ init_source();
|
|
|
75683
75842
|
// package.json
|
|
75684
75843
|
var package_default = {
|
|
75685
75844
|
name: "@vibeframe/cli",
|
|
75686
|
-
version: "0.113.
|
|
75845
|
+
version: "0.113.26",
|
|
75687
75846
|
description: "VibeFrame CLI - agentic video workflow runtime",
|
|
75688
75847
|
private: false,
|
|
75689
75848
|
license: "MIT",
|
|
@@ -77769,7 +77928,7 @@ import { existsSync as existsSync42 } from "node:fs";
|
|
|
77769
77928
|
// src/commands/ai-script-pipeline-cli.ts
|
|
77770
77929
|
init_source();
|
|
77771
77930
|
init_ora();
|
|
77772
|
-
var
|
|
77931
|
+
var import_yaml7 = __toESM(require_dist2(), 1);
|
|
77773
77932
|
init_api_key();
|
|
77774
77933
|
init_ai_script_pipeline();
|
|
77775
77934
|
init_output();
|
|
@@ -77834,7 +77993,7 @@ function registerScriptPipelineCommands(aiCommand) {
|
|
|
77834
77993
|
return;
|
|
77835
77994
|
}
|
|
77836
77995
|
const content = await readFile35(storyboardPath2, "utf-8");
|
|
77837
|
-
const segments = storyboardIsYaml ? (0,
|
|
77996
|
+
const segments = storyboardIsYaml ? (0, import_yaml7.parse)(content).scenes : JSON.parse(content);
|
|
77838
77997
|
for (const sceneNum of sceneNums) {
|
|
77839
77998
|
if (sceneNum > segments.length) {
|
|
77840
77999
|
exitWithError(
|
|
@@ -77920,7 +78079,7 @@ function registerScriptPipelineCommands(aiCommand) {
|
|
|
77920
78079
|
const updateSpinner = ora("Updating timeline file...").start();
|
|
77921
78080
|
try {
|
|
77922
78081
|
const updatedContent = await readFile35(storyboardPath2, "utf-8");
|
|
77923
|
-
const updatedSegments = storyboardIsYaml ? (0,
|
|
78082
|
+
const updatedSegments = storyboardIsYaml ? (0, import_yaml7.parse)(updatedContent).scenes : JSON.parse(updatedContent);
|
|
77924
78083
|
const projectContent = await readFile35(projectPath, "utf-8");
|
|
77925
78084
|
const projectData = JSON.parse(projectContent);
|
|
77926
78085
|
for (const sceneNum of result.regeneratedScenes) {
|
|
@@ -84135,6 +84294,7 @@ function draftStoryboardFromBrief(opts) {
|
|
|
84135
84294
|
const theme = describeTheme(brief, product);
|
|
84136
84295
|
const beats = beatCount === 4 ? fourBeatDraft({ product, brief, theme, durations: beatDurations }) : threeBeatDraft({ product, brief, theme, durations: beatDurations });
|
|
84137
84296
|
const storyboardMd = `---
|
|
84297
|
+
type: Storyboard
|
|
84138
84298
|
title: ${JSON.stringify(product)}
|
|
84139
84299
|
duration: ${total}
|
|
84140
84300
|
aspect: ${opts.aspect ?? "16:9"}
|
|
@@ -197,7 +197,7 @@ export declare const generateThumbnailTool: import("../define-tool.js").ToolDefi
|
|
|
197
197
|
}>>;
|
|
198
198
|
export declare const generateVideoTool: import("../define-tool.js").ToolDefinition<z.ZodObject<{
|
|
199
199
|
prompt: z.ZodString;
|
|
200
|
-
provider: z.ZodOptional<z.ZodEnum<["seedance", "grok", "kling", "runway", "veo"]>>;
|
|
200
|
+
provider: z.ZodOptional<z.ZodEnum<["seedance", "grok", "kling", "runway", "veo", "omni"]>>;
|
|
201
201
|
image: z.ZodOptional<z.ZodString>;
|
|
202
202
|
endImage: z.ZodOptional<z.ZodString>;
|
|
203
203
|
refImages: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -219,7 +219,7 @@ export declare const generateVideoTool: import("../define-tool.js").ToolDefiniti
|
|
|
219
219
|
image?: string | undefined;
|
|
220
220
|
duration?: number | undefined;
|
|
221
221
|
output?: string | undefined;
|
|
222
|
-
provider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
|
222
|
+
provider?: "grok" | "seedance" | "kling" | "runway" | "veo" | "omni" | undefined;
|
|
223
223
|
refImages?: string[] | undefined;
|
|
224
224
|
refVideos?: string[] | undefined;
|
|
225
225
|
refAudio?: string[] | undefined;
|
|
@@ -238,7 +238,7 @@ export declare const generateVideoTool: import("../define-tool.js").ToolDefiniti
|
|
|
238
238
|
image?: string | undefined;
|
|
239
239
|
duration?: number | undefined;
|
|
240
240
|
output?: string | undefined;
|
|
241
|
-
provider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
|
|
241
|
+
provider?: "grok" | "seedance" | "kling" | "runway" | "veo" | "omni" | undefined;
|
|
242
242
|
refImages?: string[] | undefined;
|
|
243
243
|
refVideos?: string[] | undefined;
|
|
244
244
|
refAudio?: string[] | undefined;
|
|
@@ -1842,6 +1842,113 @@ Respond with ONLY the JSON array, no other text.`;
|
|
|
1842
1842
|
}
|
|
1843
1843
|
});
|
|
1844
1844
|
|
|
1845
|
+
// ../ai-providers/dist/gemini/gemini-omni.js
|
|
1846
|
+
function firstReferenceImage(options) {
|
|
1847
|
+
const refs = options.referenceImages;
|
|
1848
|
+
if (refs && refs.length > 0 && refs[0].base64)
|
|
1849
|
+
return refs[0];
|
|
1850
|
+
const ref = options.referenceImage;
|
|
1851
|
+
if (typeof ref === "string" && ref) {
|
|
1852
|
+
const m = ref.match(/^data:(.+?);base64,(.*)$/);
|
|
1853
|
+
if (m)
|
|
1854
|
+
return { mimeType: m[1], base64: m[2] };
|
|
1855
|
+
return { mimeType: "image/png", base64: ref };
|
|
1856
|
+
}
|
|
1857
|
+
return void 0;
|
|
1858
|
+
}
|
|
1859
|
+
function findVideoUrl(obj) {
|
|
1860
|
+
if (!obj || typeof obj !== "object")
|
|
1861
|
+
return void 0;
|
|
1862
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
1863
|
+
if (typeof v === "string" && /^https?:\/\//.test(v) && /(uri|url|video)/i.test(k))
|
|
1864
|
+
return v;
|
|
1865
|
+
if (typeof v === "object") {
|
|
1866
|
+
const nested = findVideoUrl(v);
|
|
1867
|
+
if (nested)
|
|
1868
|
+
return nested;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
return void 0;
|
|
1872
|
+
}
|
|
1873
|
+
var OMNI_MODEL, INTERACTIONS_URL, OmniProvider, omniProvider;
|
|
1874
|
+
var init_gemini_omni = __esm({
|
|
1875
|
+
"../ai-providers/dist/gemini/gemini-omni.js"() {
|
|
1876
|
+
"use strict";
|
|
1877
|
+
OMNI_MODEL = "gemini-omni-flash-preview";
|
|
1878
|
+
INTERACTIONS_URL = "https://generativelanguage.googleapis.com/v1beta/interactions";
|
|
1879
|
+
OmniProvider = class {
|
|
1880
|
+
constructor() {
|
|
1881
|
+
this.id = "omni";
|
|
1882
|
+
this.label = "Gemini Omni (experimental)";
|
|
1883
|
+
}
|
|
1884
|
+
async initialize(config2) {
|
|
1885
|
+
this.apiKey = config2.apiKey;
|
|
1886
|
+
}
|
|
1887
|
+
isConfigured() {
|
|
1888
|
+
return !!this.apiKey;
|
|
1889
|
+
}
|
|
1890
|
+
async generateVideo(prompt3, options) {
|
|
1891
|
+
if (!this.apiKey) {
|
|
1892
|
+
return { id: "", status: "failed", error: "GOOGLE_API_KEY not configured for Gemini Omni" };
|
|
1893
|
+
}
|
|
1894
|
+
const opts = options ?? { prompt: prompt3 };
|
|
1895
|
+
const image = firstReferenceImage(opts);
|
|
1896
|
+
const task = image ? "image_to_video" : "text_to_video";
|
|
1897
|
+
const aspectRatio2 = opts.aspectRatio === "9:16" ? "9:16" : "16:9";
|
|
1898
|
+
const inputs = [{ text: prompt3 }];
|
|
1899
|
+
if (image) {
|
|
1900
|
+
inputs.push({ inline_data: { mime_type: image.mimeType, data: image.base64 } });
|
|
1901
|
+
}
|
|
1902
|
+
const body = {
|
|
1903
|
+
model: OMNI_MODEL,
|
|
1904
|
+
inputs,
|
|
1905
|
+
generation_config: {
|
|
1906
|
+
video_config: { task, aspect_ratio: aspectRatio2 }
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
try {
|
|
1910
|
+
const res = await fetch(INTERACTIONS_URL, {
|
|
1911
|
+
method: "POST",
|
|
1912
|
+
headers: { "Content-Type": "application/json", "x-goog-api-key": this.apiKey },
|
|
1913
|
+
body: JSON.stringify(body)
|
|
1914
|
+
});
|
|
1915
|
+
const text = await res.text();
|
|
1916
|
+
if (!res.ok) {
|
|
1917
|
+
return {
|
|
1918
|
+
id: "",
|
|
1919
|
+
status: "failed",
|
|
1920
|
+
error: `Gemini Omni (experimental) request failed: HTTP ${res.status} \u2014 ${text.slice(0, 300)}`
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
let parsed;
|
|
1924
|
+
try {
|
|
1925
|
+
parsed = JSON.parse(text);
|
|
1926
|
+
} catch {
|
|
1927
|
+
return { id: "", status: "failed", error: "Gemini Omni returned a non-JSON response" };
|
|
1928
|
+
}
|
|
1929
|
+
const videoUrl = findVideoUrl(parsed);
|
|
1930
|
+
const id = parsed?.interaction_id ?? parsed?.name ?? "";
|
|
1931
|
+
if (!videoUrl) {
|
|
1932
|
+
return {
|
|
1933
|
+
id,
|
|
1934
|
+
status: "failed",
|
|
1935
|
+
error: "Gemini Omni response contained no video URL (the preview interactions schema may have changed)."
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1938
|
+
return { id, status: "completed", videoUrl };
|
|
1939
|
+
} catch (err) {
|
|
1940
|
+
return {
|
|
1941
|
+
id: "",
|
|
1942
|
+
status: "failed",
|
|
1943
|
+
error: `Gemini Omni (experimental) error: ${err instanceof Error ? err.message : String(err)}`
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
};
|
|
1948
|
+
omniProvider = new OmniProvider();
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
|
|
1845
1952
|
// ../ai-providers/dist/gemini/index.js
|
|
1846
1953
|
var init_gemini = __esm({
|
|
1847
1954
|
"../ai-providers/dist/gemini/index.js"() {
|
|
@@ -1849,6 +1956,7 @@ var init_gemini = __esm({
|
|
|
1849
1956
|
init_GeminiProvider();
|
|
1850
1957
|
init_gemini_motion();
|
|
1851
1958
|
init_gemini_models();
|
|
1959
|
+
init_gemini_omni();
|
|
1852
1960
|
init_define_provider();
|
|
1853
1961
|
defineProvider({
|
|
1854
1962
|
id: "gemini",
|
|
@@ -1872,6 +1980,13 @@ var init_gemini = __esm({
|
|
|
1872
1980
|
resolverPriority: { video: 3 },
|
|
1873
1981
|
commandsUnlocked: ["generate video -p veo"]
|
|
1874
1982
|
});
|
|
1983
|
+
defineProvider({
|
|
1984
|
+
id: "omni",
|
|
1985
|
+
label: "Gemini Omni (experimental)",
|
|
1986
|
+
apiKey: "google",
|
|
1987
|
+
kinds: ["video"],
|
|
1988
|
+
commandsUnlocked: ["generate video -p omni"]
|
|
1989
|
+
});
|
|
1875
1990
|
}
|
|
1876
1991
|
});
|
|
1877
1992
|
|
|
@@ -11435,6 +11550,7 @@ __export(dist_exports2, {
|
|
|
11435
11550
|
KokoroProvider: () => KokoroProvider,
|
|
11436
11551
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
11437
11552
|
OllamaProvider: () => OllamaProvider,
|
|
11553
|
+
OmniProvider: () => OmniProvider,
|
|
11438
11554
|
OpenAIImageProvider: () => OpenAIImageProvider,
|
|
11439
11555
|
OpenAIProvider: () => OpenAIProvider,
|
|
11440
11556
|
OpenAiTtsProvider: () => OpenAiTtsProvider,
|
|
@@ -11465,6 +11581,7 @@ __export(dist_exports2, {
|
|
|
11465
11581
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
11466
11582
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
11467
11583
|
ollamaProvider: () => ollamaProvider,
|
|
11584
|
+
omniProvider: () => omniProvider,
|
|
11468
11585
|
openaiImageProvider: () => openaiImageProvider,
|
|
11469
11586
|
openaiProvider: () => openaiProvider,
|
|
11470
11587
|
openaiTtsProvider: () => openaiTtsProvider,
|
|
@@ -20712,6 +20829,7 @@ async function executeVideoGenerate(options) {
|
|
|
20712
20829
|
runway: "RUNWAY_API_SECRET",
|
|
20713
20830
|
kling: "KLING_API_KEY",
|
|
20714
20831
|
veo: "GOOGLE_API_KEY",
|
|
20832
|
+
omni: "GOOGLE_API_KEY",
|
|
20715
20833
|
seedance: "FAL_API_KEY",
|
|
20716
20834
|
fal: "FAL_API_KEY"
|
|
20717
20835
|
};
|
|
@@ -20932,6 +21050,31 @@ async function executeVideoGenerate(options) {
|
|
|
20932
21050
|
outputPath,
|
|
20933
21051
|
provider: "grok"
|
|
20934
21052
|
};
|
|
21053
|
+
} else if (provider === "omni") {
|
|
21054
|
+
const omni = new OmniProvider();
|
|
21055
|
+
await omni.initialize({ apiKey: key });
|
|
21056
|
+
const result = await omni.generateVideo(prompt3, {
|
|
21057
|
+
prompt: prompt3,
|
|
21058
|
+
referenceImage,
|
|
21059
|
+
aspectRatio: ratio
|
|
21060
|
+
});
|
|
21061
|
+
if (result.status !== "completed" || !result.videoUrl) {
|
|
21062
|
+
return { success: false, error: result.error || "Gemini Omni generation failed" };
|
|
21063
|
+
}
|
|
21064
|
+
let outputPath;
|
|
21065
|
+
if (output) {
|
|
21066
|
+
const buffer = await downloadVideo(result.videoUrl, key);
|
|
21067
|
+
outputPath = resolve4(process.cwd(), output);
|
|
21068
|
+
await writeFile4(outputPath, buffer);
|
|
21069
|
+
}
|
|
21070
|
+
return {
|
|
21071
|
+
success: true,
|
|
21072
|
+
taskId: result.id,
|
|
21073
|
+
status: "completed",
|
|
21074
|
+
videoUrl: result.videoUrl,
|
|
21075
|
+
outputPath,
|
|
21076
|
+
provider: "omni"
|
|
21077
|
+
};
|
|
20935
21078
|
}
|
|
20936
21079
|
return { success: false, error: `Unsupported provider: ${provider}` };
|
|
20937
21080
|
} catch (error) {
|
|
@@ -24635,6 +24778,30 @@ var init_review_report = __esm({
|
|
|
24635
24778
|
}
|
|
24636
24779
|
});
|
|
24637
24780
|
|
|
24781
|
+
// src/commands/_shared/frontmatter.ts
|
|
24782
|
+
function extractFrontmatter(md) {
|
|
24783
|
+
const raw = md.replace(/\r\n/g, "\n");
|
|
24784
|
+
const match = raw.match(FRONTMATTER_RE);
|
|
24785
|
+
if (match) {
|
|
24786
|
+
try {
|
|
24787
|
+
const parsed = (0, import_yaml2.parse)(match[1]);
|
|
24788
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
24789
|
+
return { data: parsed, body: raw.slice(match[0].length), raw };
|
|
24790
|
+
}
|
|
24791
|
+
} catch {
|
|
24792
|
+
}
|
|
24793
|
+
}
|
|
24794
|
+
return { data: null, body: raw, raw };
|
|
24795
|
+
}
|
|
24796
|
+
var import_yaml2, FRONTMATTER_RE;
|
|
24797
|
+
var init_frontmatter = __esm({
|
|
24798
|
+
"src/commands/_shared/frontmatter.ts"() {
|
|
24799
|
+
"use strict";
|
|
24800
|
+
import_yaml2 = __toESM(require_dist2(), 1);
|
|
24801
|
+
FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
24802
|
+
}
|
|
24803
|
+
});
|
|
24804
|
+
|
|
24638
24805
|
// src/commands/_shared/storyboard-parse.ts
|
|
24639
24806
|
function resolveCharacters(frontmatter) {
|
|
24640
24807
|
const pool = frontmatter?.characters;
|
|
@@ -24713,28 +24880,16 @@ function parseStoryboard(md) {
|
|
|
24713
24880
|
};
|
|
24714
24881
|
}
|
|
24715
24882
|
function extractProjectFrontmatter(md) {
|
|
24716
|
-
const
|
|
24717
|
-
if (!
|
|
24718
|
-
|
|
24719
|
-
try {
|
|
24720
|
-
parsed = (0, import_yaml2.parse)(match[1]);
|
|
24721
|
-
} catch {
|
|
24722
|
-
return { frontmatter: void 0, remaining: md };
|
|
24723
|
-
}
|
|
24724
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
24725
|
-
return { frontmatter: void 0, remaining: md };
|
|
24726
|
-
}
|
|
24727
|
-
return {
|
|
24728
|
-
frontmatter: parsed,
|
|
24729
|
-
remaining: md.slice(match[0].length)
|
|
24730
|
-
};
|
|
24883
|
+
const { data, body } = extractFrontmatter(md);
|
|
24884
|
+
if (!data) return { frontmatter: void 0, remaining: md };
|
|
24885
|
+
return { frontmatter: data, remaining: body };
|
|
24731
24886
|
}
|
|
24732
24887
|
function extractBeatCues(body) {
|
|
24733
24888
|
const match = body.match(BEAT_CUES_RE);
|
|
24734
24889
|
if (!match) return { cues: void 0, body };
|
|
24735
24890
|
let parsed;
|
|
24736
24891
|
try {
|
|
24737
|
-
parsed = (0,
|
|
24892
|
+
parsed = (0, import_yaml3.parse)(match[1]);
|
|
24738
24893
|
} catch {
|
|
24739
24894
|
return { cues: void 0, body };
|
|
24740
24895
|
}
|
|
@@ -24764,16 +24919,16 @@ function parseBeatDuration(body) {
|
|
|
24764
24919
|
const n = parseFloat(valueMatch[1]);
|
|
24765
24920
|
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
24766
24921
|
}
|
|
24767
|
-
var
|
|
24922
|
+
var import_yaml3, HEADING_RE, BEAT_PREFIX_RE, DURATION_SUBSECTION_RE, DURATION_VALUE_RE, BEAT_CUES_RE;
|
|
24768
24923
|
var init_storyboard_parse = __esm({
|
|
24769
24924
|
"src/commands/_shared/storyboard-parse.ts"() {
|
|
24770
24925
|
"use strict";
|
|
24771
|
-
|
|
24926
|
+
import_yaml3 = __toESM(require_dist2(), 1);
|
|
24927
|
+
init_frontmatter();
|
|
24772
24928
|
HEADING_RE = /^##\s+(.+?)\s*$/gm;
|
|
24773
24929
|
BEAT_PREFIX_RE = /^Beat\s+(.+?)\s+(?:—|:|-)\s+(.+)$/i;
|
|
24774
24930
|
DURATION_SUBSECTION_RE = /###\s+Beat\s+duration\s*\n([\s\S]*?)(?=\n###\s|\n##\s|$)/i;
|
|
24775
24931
|
DURATION_VALUE_RE = /(-?\d+(?:\.\d+)?)\s*(?:s|sec|seconds?)?/i;
|
|
24776
|
-
FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
24777
24932
|
BEAT_CUES_RE = /^\s*```ya?ml\s*\n([\s\S]*?)\n```\s*(?:\n|$)/;
|
|
24778
24933
|
}
|
|
24779
24934
|
});
|
|
@@ -25742,7 +25897,7 @@ async function readProjectConfig(projectDir) {
|
|
|
25742
25897
|
if (existsSync3(legacyPath)) {
|
|
25743
25898
|
try {
|
|
25744
25899
|
const raw = await readFile5(legacyPath, "utf-8");
|
|
25745
|
-
const legacy = (0,
|
|
25900
|
+
const legacy = (0, import_yaml4.parse)(raw);
|
|
25746
25901
|
const name = legacy?.name ?? dir.split(/[\\/]/).filter(Boolean).pop() ?? "video";
|
|
25747
25902
|
const config2 = defaultProjectConfig({
|
|
25748
25903
|
name,
|
|
@@ -25774,11 +25929,11 @@ async function readProjectConfig(projectDir) {
|
|
|
25774
25929
|
legacy: false
|
|
25775
25930
|
};
|
|
25776
25931
|
}
|
|
25777
|
-
var
|
|
25932
|
+
var import_yaml4, VIBE_CONFIG_FILENAME, LEGACY_VIBE_PROJECT_FILENAME;
|
|
25778
25933
|
var init_project_config = __esm({
|
|
25779
25934
|
"src/commands/_shared/project-config.ts"() {
|
|
25780
25935
|
"use strict";
|
|
25781
|
-
|
|
25936
|
+
import_yaml4 = __toESM(require_dist2(), 1);
|
|
25782
25937
|
VIBE_CONFIG_FILENAME = "vibe.config.json";
|
|
25783
25938
|
LEGACY_VIBE_PROJECT_FILENAME = "vibe.project.yaml";
|
|
25784
25939
|
}
|
|
@@ -25900,6 +26055,7 @@ function buildDesignMd(opts) {
|
|
|
25900
26055
|
const { name, style } = opts;
|
|
25901
26056
|
const roles = designColorRoles(style);
|
|
25902
26057
|
const frontmatter = `---
|
|
26058
|
+
type: Design
|
|
25903
26059
|
name: ${name}
|
|
25904
26060
|
colors:
|
|
25905
26061
|
primary: "${roles.primary}"
|
|
@@ -26024,6 +26180,7 @@ function buildCharactersMd(name) {
|
|
|
26024
26180
|
}
|
|
26025
26181
|
function buildStoryboardMd(name, duration = 12) {
|
|
26026
26182
|
return `---
|
|
26183
|
+
type: Storyboard
|
|
26027
26184
|
title: ${name}
|
|
26028
26185
|
duration: ${duration}
|
|
26029
26186
|
aspect: 16:9
|
|
@@ -32589,7 +32746,7 @@ function setStoryboardCue(markdown, opts) {
|
|
|
32589
32746
|
cues[opts.key] = normalizeCueValue(opts.key, opts.value);
|
|
32590
32747
|
}
|
|
32591
32748
|
const remainingBody = cue ? section.body.slice(cue.full.length).replace(/^\s*\n/, "") : section.body.replace(/^\s*\n/, "");
|
|
32592
|
-
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0,
|
|
32749
|
+
const cueBlock = Object.keys(cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
32593
32750
|
const nextBody = cueBlock + remainingBody.trimStart();
|
|
32594
32751
|
const nextSection = section.raw.slice(0, section.headingEnd - section.start) + "\n\n" + nextBody.trimEnd() + "\n";
|
|
32595
32752
|
return markdown.slice(0, section.start) + nextSection + markdown.slice(section.end);
|
|
@@ -32623,7 +32780,7 @@ function storyboardCuesFromInput(opts) {
|
|
|
32623
32780
|
}
|
|
32624
32781
|
function buildStoryboardBeatSection(opts) {
|
|
32625
32782
|
const title = normalizeTitle(opts.title ?? humanizeBeatId(opts.beatId));
|
|
32626
|
-
const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0,
|
|
32783
|
+
const cueBlock = Object.keys(opts.cues).length > 0 ? "```yaml\n" + (0, import_yaml5.stringify)(opts.cues, { lineWidth: 0 }).trimEnd() + "\n```\n\n" : "";
|
|
32627
32784
|
const body = opts.body?.trim() || "Scene created with `vibe scene add`. Edit this body if the build flow should recompose it.";
|
|
32628
32785
|
return `## Beat ${opts.beatId} - ${title}
|
|
32629
32786
|
|
|
@@ -32682,7 +32839,7 @@ function readLeadingCueBlock(body) {
|
|
|
32682
32839
|
const match = body.match(LEADING_CUE_RE);
|
|
32683
32840
|
if (!match) return null;
|
|
32684
32841
|
try {
|
|
32685
|
-
const parsed = (0,
|
|
32842
|
+
const parsed = (0, import_yaml5.parse)(match[2]);
|
|
32686
32843
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
32687
32844
|
return { full: match[0], error: "cue block must parse to a YAML object" };
|
|
32688
32845
|
}
|
|
@@ -32691,11 +32848,11 @@ function readLeadingCueBlock(body) {
|
|
|
32691
32848
|
return { full: match[0], error: error instanceof Error ? error.message : String(error) };
|
|
32692
32849
|
}
|
|
32693
32850
|
}
|
|
32694
|
-
var
|
|
32851
|
+
var import_yaml5, STORYBOARD_CUE_KEYS, HEADING_RE2, LEADING_CUE_RE, ALLOWED_CUE_KEYS, STRING_CUE_KEYS, MAX_RECOMMENDED_BEAT_SEC;
|
|
32695
32852
|
var init_storyboard_edit = __esm({
|
|
32696
32853
|
"src/commands/_shared/storyboard-edit.ts"() {
|
|
32697
32854
|
"use strict";
|
|
32698
|
-
|
|
32855
|
+
import_yaml5 = __toESM(require_dist2(), 1);
|
|
32699
32856
|
init_storyboard_parse();
|
|
32700
32857
|
STORYBOARD_CUE_KEYS = [
|
|
32701
32858
|
"duration",
|
|
@@ -33600,20 +33757,8 @@ function colorTokens(value) {
|
|
|
33600
33757
|
return out;
|
|
33601
33758
|
}
|
|
33602
33759
|
function parseDesign(md) {
|
|
33603
|
-
const raw = md
|
|
33604
|
-
|
|
33605
|
-
let body = raw;
|
|
33606
|
-
const fm = raw.match(DESIGN_FRONTMATTER_RE);
|
|
33607
|
-
if (fm) {
|
|
33608
|
-
try {
|
|
33609
|
-
const parsed = (0, import_yaml5.parse)(fm[1]);
|
|
33610
|
-
if (isPlainObject(parsed)) {
|
|
33611
|
-
frontmatter = parsed;
|
|
33612
|
-
body = raw.slice(fm[0].length);
|
|
33613
|
-
}
|
|
33614
|
-
} catch {
|
|
33615
|
-
}
|
|
33616
|
-
}
|
|
33760
|
+
const { data, body, raw } = extractFrontmatter(md);
|
|
33761
|
+
const frontmatter = data ?? {};
|
|
33617
33762
|
const sections = {};
|
|
33618
33763
|
const headings = [];
|
|
33619
33764
|
SECTION_RE.lastIndex = 0;
|
|
@@ -33649,7 +33794,7 @@ function validateDesignMarkdown(md) {
|
|
|
33649
33794
|
const fm = raw.match(DESIGN_FRONTMATTER_RE);
|
|
33650
33795
|
if (fm) {
|
|
33651
33796
|
try {
|
|
33652
|
-
const parsed = (0,
|
|
33797
|
+
const parsed = (0, import_yaml6.parse)(fm[1]);
|
|
33653
33798
|
if (!isPlainObject(parsed)) {
|
|
33654
33799
|
issues.push({
|
|
33655
33800
|
severity: "warning",
|
|
@@ -33690,11 +33835,12 @@ function validateDesignMarkdown(md) {
|
|
|
33690
33835
|
}
|
|
33691
33836
|
return issues;
|
|
33692
33837
|
}
|
|
33693
|
-
var
|
|
33838
|
+
var import_yaml6, DESIGN_FRONTMATTER_RE, SECTION_RE, HEX_RE;
|
|
33694
33839
|
var init_design_parse = __esm({
|
|
33695
33840
|
"src/commands/_shared/design-parse.ts"() {
|
|
33696
33841
|
"use strict";
|
|
33697
|
-
|
|
33842
|
+
import_yaml6 = __toESM(require_dist2(), 1);
|
|
33843
|
+
init_frontmatter();
|
|
33698
33844
|
DESIGN_FRONTMATTER_RE = /^---\s*\n([\s\S]*?)\n---\s*(?:\n|$)/;
|
|
33699
33845
|
SECTION_RE = /^##\s+(.+?)\s*$/gm;
|
|
33700
33846
|
HEX_RE = /#[0-9a-fA-F]{6}\b/g;
|
|
@@ -47081,9 +47227,9 @@ var init_dist3 = __esm({
|
|
|
47081
47227
|
import { resolve as resolve54 } from "node:path";
|
|
47082
47228
|
import { readFile as readFile37, writeFile as writeFile40 } from "node:fs/promises";
|
|
47083
47229
|
function registerVideoCommand(parent) {
|
|
47084
|
-
parent.command("video").alias("vid").description("Generate video using AI (Seedance, Grok, Kling, Runway, or
|
|
47230
|
+
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(
|
|
47085
47231
|
"-p, --provider <provider>",
|
|
47086
|
-
"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."
|
|
47232
|
+
"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."
|
|
47087
47233
|
).option(
|
|
47088
47234
|
"-k, --api-key <key>",
|
|
47089
47235
|
"API key (or set FAL_API_KEY / XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
|
|
@@ -47146,10 +47292,11 @@ Examples:
|
|
|
47146
47292
|
);
|
|
47147
47293
|
}
|
|
47148
47294
|
}
|
|
47149
|
-
const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal"];
|
|
47295
|
+
const validProviders = ["runway", "kling", "veo", "grok", "seedance", "fal", "omni"];
|
|
47150
47296
|
const videoEnvMap = {
|
|
47151
47297
|
grok: "XAI_API_KEY",
|
|
47152
47298
|
veo: "GOOGLE_API_KEY",
|
|
47299
|
+
omni: "GOOGLE_API_KEY",
|
|
47153
47300
|
kling: "KLING_API_KEY",
|
|
47154
47301
|
runway: "RUNWAY_API_SECRET",
|
|
47155
47302
|
seedance: "FAL_API_KEY"
|
|
@@ -47161,7 +47308,7 @@ Examples:
|
|
|
47161
47308
|
exitWithError(
|
|
47162
47309
|
usageError(
|
|
47163
47310
|
`Invalid provider: ${provider}`,
|
|
47164
|
-
"Available providers: seedance, grok, kling, runway, veo. `fal` is a deprecated alias for seedance."
|
|
47311
|
+
"Available providers: seedance, grok, kling, runway, veo, omni (experimental). `fal` is a deprecated alias for seedance."
|
|
47165
47312
|
)
|
|
47166
47313
|
);
|
|
47167
47314
|
}
|
|
@@ -47266,6 +47413,7 @@ Examples:
|
|
|
47266
47413
|
runway: "RUNWAY_API_SECRET",
|
|
47267
47414
|
kling: "KLING_API_KEY",
|
|
47268
47415
|
veo: "GOOGLE_API_KEY",
|
|
47416
|
+
omni: "GOOGLE_API_KEY",
|
|
47269
47417
|
grok: "XAI_API_KEY",
|
|
47270
47418
|
seedance: "FAL_API_KEY"
|
|
47271
47419
|
};
|
|
@@ -47273,6 +47421,7 @@ Examples:
|
|
|
47273
47421
|
runway: "Runway",
|
|
47274
47422
|
kling: "Kling",
|
|
47275
47423
|
veo: "Veo",
|
|
47424
|
+
omni: "Gemini Omni (experimental)",
|
|
47276
47425
|
grok: "Grok",
|
|
47277
47426
|
seedance: "Seedance 2.0 via fal.ai"
|
|
47278
47427
|
};
|
|
@@ -47607,6 +47756,16 @@ Examples:
|
|
|
47607
47756
|
lastFrame: seedanceEndImage
|
|
47608
47757
|
});
|
|
47609
47758
|
finalResult = result;
|
|
47759
|
+
} else if (provider === "omni") {
|
|
47760
|
+
const omni = new OmniProvider();
|
|
47761
|
+
await omni.initialize({ apiKey });
|
|
47762
|
+
spinner2.text = "Generating video with Gemini Omni (experimental)...";
|
|
47763
|
+
result = await omni.generateVideo(prompt3, {
|
|
47764
|
+
prompt: prompt3,
|
|
47765
|
+
referenceImage,
|
|
47766
|
+
aspectRatio: options.ratio
|
|
47767
|
+
});
|
|
47768
|
+
finalResult = result;
|
|
47610
47769
|
}
|
|
47611
47770
|
if (!finalResult || finalResult.status !== "completed") {
|
|
47612
47771
|
spinner2.fail(finalResult?.error || "Generation failed");
|
|
@@ -59127,8 +59286,8 @@ var generateVideoTool = defineTool({
|
|
|
59127
59286
|
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.",
|
|
59128
59287
|
schema: external_exports.object({
|
|
59129
59288
|
prompt: external_exports.string().describe("Text prompt describing the video"),
|
|
59130
|
-
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo"]).optional().describe(
|
|
59131
|
-
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
|
|
59289
|
+
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
|
|
59290
|
+
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider). `omni` = Gemini Omni, experimental/opt-in, uses GOOGLE_API_KEY."
|
|
59132
59291
|
),
|
|
59133
59292
|
image: external_exports.string().optional().describe("Reference image path for image-to-video"),
|
|
59134
59293
|
endImage: external_exports.string().optional().describe("Ending frame image path for Seedance image-to-video"),
|
|
@@ -59942,7 +60101,7 @@ import { tmpdir as tmpdir4 } from "node:os";
|
|
|
59942
60101
|
import { join as join27 } from "node:path";
|
|
59943
60102
|
|
|
59944
60103
|
// src/commands/ai-script-pipeline.ts
|
|
59945
|
-
var
|
|
60104
|
+
var import_yaml7 = __toESM(require_dist2(), 1);
|
|
59946
60105
|
init_dist2();
|
|
59947
60106
|
init_api_key();
|
|
59948
60107
|
init_config();
|
|
@@ -60120,7 +60279,7 @@ async function executeRegenerateScene(options) {
|
|
|
60120
60279
|
return { ...result, error: `Storyboard not found in: ${outputDir} (expected storyboard.yaml or storyboard.json)` };
|
|
60121
60280
|
}
|
|
60122
60281
|
const storyboardContent = await readFile41(storyboardPath, "utf-8");
|
|
60123
|
-
const segments = storyboardPath.endsWith(".yaml") ? (0,
|
|
60282
|
+
const segments = storyboardPath.endsWith(".yaml") ? (0, import_yaml7.parse)(storyboardContent).scenes : JSON.parse(storyboardContent);
|
|
60124
60283
|
for (const sceneNum of options.scenes) {
|
|
60125
60284
|
if (sceneNum < 1 || sceneNum > segments.length) {
|
|
60126
60285
|
return { ...result, error: `Scene ${sceneNum} does not exist. Storyboard has ${segments.length} scenes.` };
|
|
@@ -60502,7 +60661,7 @@ Generate the single-person scene image now.`;
|
|
|
60502
60661
|
segment.startTime = currentTime;
|
|
60503
60662
|
currentTime += segment.duration;
|
|
60504
60663
|
}
|
|
60505
|
-
const serialized = storyboardPath.endsWith(".yaml") ? (0,
|
|
60664
|
+
const serialized = storyboardPath.endsWith(".yaml") ? (0, import_yaml7.stringify)({ scenes: segments }, { indent: 2 }) : JSON.stringify(segments, null, 2);
|
|
60506
60665
|
await writeFile43(storyboardPath, serialized, "utf-8");
|
|
60507
60666
|
}
|
|
60508
60667
|
result.success = result.failedScenes.length === 0;
|
|
@@ -60957,7 +61116,7 @@ Analyze both VISUALS (expressions, actions, scene changes) and AUDIO (speech, re
|
|
|
60957
61116
|
}
|
|
60958
61117
|
|
|
60959
61118
|
// src/pipeline/executor.ts
|
|
60960
|
-
var
|
|
61119
|
+
var import_yaml8 = __toESM(require_dist2(), 1);
|
|
60961
61120
|
import { resolve as resolve61 } from "node:path";
|
|
60962
61121
|
import { readFile as readFile44, writeFile as writeFile46, mkdir as mkdir25 } from "node:fs/promises";
|
|
60963
61122
|
import { existsSync as existsSync49 } from "node:fs";
|
|
@@ -61377,7 +61536,7 @@ async function loadPipeline(filePath) {
|
|
|
61377
61536
|
throw new Error(`Pipeline file not found: ${absPath}`);
|
|
61378
61537
|
}
|
|
61379
61538
|
const content = await readFile44(absPath, "utf-8");
|
|
61380
|
-
const manifest2 = (0,
|
|
61539
|
+
const manifest2 = (0, import_yaml8.parse)(content);
|
|
61381
61540
|
if (!manifest2.name) throw new Error("Pipeline missing 'name' field");
|
|
61382
61541
|
if (!manifest2.steps || !Array.isArray(manifest2.steps)) throw new Error("Pipeline missing 'steps' array");
|
|
61383
61542
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -61401,7 +61560,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
61401
61560
|
const checkpointPath = resolve61(outputDir, CHECKPOINT_FILE);
|
|
61402
61561
|
if (existsSync49(checkpointPath)) {
|
|
61403
61562
|
const checkpointContent = await readFile44(checkpointPath, "utf-8");
|
|
61404
|
-
const checkpoint = (0,
|
|
61563
|
+
const checkpoint = (0, import_yaml8.parse)(checkpointContent);
|
|
61405
61564
|
for (const cs of checkpoint.completedSteps) {
|
|
61406
61565
|
completedSteps.set(cs.id, {
|
|
61407
61566
|
id: cs.id,
|
|
@@ -61520,7 +61679,7 @@ async function executePipeline(manifest2, options = {}) {
|
|
|
61520
61679
|
};
|
|
61521
61680
|
await writeFile46(
|
|
61522
61681
|
resolve61(outputDir, CHECKPOINT_FILE),
|
|
61523
|
-
(0,
|
|
61682
|
+
(0, import_yaml8.stringify)(checkpoint, { indent: 2 }),
|
|
61524
61683
|
"utf-8"
|
|
61525
61684
|
);
|
|
61526
61685
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.113.
|
|
3
|
+
"version": "0.113.26",
|
|
4
4
|
"description": "VibeFrame CLI - agentic video workflow runtime",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"tsx": "^4.21.0",
|
|
84
84
|
"typescript": "^5.3.3",
|
|
85
85
|
"vitest": "^1.2.2",
|
|
86
|
-
"@vibeframe/ai-providers": "0.113.
|
|
87
|
-
"@vibeframe/core": "0.113.
|
|
86
|
+
"@vibeframe/ai-providers": "0.113.26",
|
|
87
|
+
"@vibeframe/core": "0.113.26"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
|
90
90
|
"node": ">=20"
|