@vibeframe/cli 0.115.4 → 0.115.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTEXT.md +1 -1
- package/dist/commands/_shared/init-templates.d.ts +1 -1
- package/dist/commands/generate/video.d.ts +9 -0
- package/dist/commands/generate.d.ts +1 -1
- package/dist/commands/output.d.ts +9 -1
- package/dist/index.js +165 -32
- package/dist/tools/manifest/index.js +137 -21
- package/dist/tools/manifest/storyboard.d.ts +2 -2
- package/dist/utils/model-lifecycle.d.ts +25 -0
- package/dist/utils/model-lifecycle.test.d.ts +1 -0
- package/package.json +3 -3
package/CONTEXT.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
5
|
VibeFrame CLI (`vibe`) generates AI video on the user's own provider keys
|
|
6
|
-
(Seedance, Runway,
|
|
6
|
+
(Seedance, Runway, Kling, Gemini Omni), behind dry runs and a hard `--max-cost`
|
|
7
7
|
ceiling, and edits the results. Every operation is
|
|
8
8
|
a shell command. The same surface is exposed as MCP tools through
|
|
9
9
|
[`@vibeframe/mcp-server`](https://www.npmjs.com/package/@vibeframe/mcp-server).
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* file. Keep this as the canonical source of truth for agent guidance -
|
|
19
19
|
* \`CLAUDE.md\` and \`GEMINI.md\` just import it.
|
|
20
20
|
*/
|
|
21
|
-
export declare const AGENTS_MD = "# AGENTS.md\n\nThis project uses [VibeFrame](https://github.com/vericontext/vibeframe) -\na CLI for AI video generation on the user's own provider keys (Seedance,\nRunway, Veo, Kling), behind dry runs and a hard `--max-cost` ceiling.\nThe `vibe` command provides 80+ subcommands for video generation,\nediting, and analysis. Cost tiers below - **always confirm with the user\nbefore running High / Very High tier commands**.\n\n## Agent host coverage\n\nVibeFrame's CLI works with any bash-capable AI coding agent. Six host\nfamilies have first-class auto-detection and scaffolds today:\n\n- **Claude Code** - `CLAUDE.md` (this file's import wrapper) +\n `AGENTS.md` + `/vibe-*` slash commands.\n- **OpenAI Codex** - reads `AGENTS.md` natively (agents.md spec).\n- **Cursor** - reads `AGENTS.md` plus `.cursor/rules/` for project\n rules; supports MCP via `.cursor/mcp.json`.\n- **Aider** - reads `AGENTS.md` (binary-only detection by VibeFrame).\n- **Gemini CLI** - primary context file is `GEMINI.md`; also reads\n `AGENTS.md` if present.\n- **OpenCode** - reads `AGENTS.md` (officially supported per\n `opencode.ai/docs/rules`); supports MCP via `.opencode/mcp.json`.\n\nRun `vibe doctor` to see which host(s) the CLI detects in your\nenvironment. Anyone running another bash-capable agent (Continue,\nSourcegraph Cody, etc.) still gets this `AGENTS.md` as the universal\nfallback.\n\n## Self-discovery\n\nDon't memorise the command surface - read it from the CLI:\n\n```bash\nvibe --help # command groups overview\nvibe schema --list # full machine-readable catalog (80+)\nvibe schema --list --surface public # small first-run/product command surface\nvibe schema generate.video # JSON Schema for any single command\nvibe doctor # available providers + system health\nvibe host setup all # print Codex/Claude/Cursor app integration snippets\nvibe host doctor all --json # verify project guidance + MCP config\nvibe guide motion # choose text-overlay vs motion-overlay vs generate motion\nvibe guide scene # step-by-step authoring guide (scene)\nvibe guide pipeline # step-by-step authoring guide (pipeline)\n```\n\n## Route by the user's actual request\n\nRouting the user's request correctly is the most important judgement call\nyou'll make. Do not force everything into a scene project.\n\n**ASSET - default for any single-asset request OR ambiguous prompt.**\nIf the user asks for a single image, single video clip, sound effect, music\nbed, or narration file - **OR pastes a visual/audio brief without explicit\nstoryboard / scene / multi-scene language** - treat it as ASSET. Use\n`vibe generate ...` directly. Do **not** edit `DESIGN.md`,\n`STORYBOARD.md`, run `vibe scene ...`, or auto-load the hyperframes\nskill until BUILD intent is explicit. The visual-identity hard-gate\napplies to BUILD only.\n\nExamples:\n- \"make this image\" \u2192 `vibe generate image \"...\" -o assets/name.png`\n- \"use this image to make a video\" \u2192 `vibe generate video \"...\" -i image.png -o renders/name.mp4`\n- \"add a lower-third/title/animated overlay/grain/vignette to this clip\" \u2192 prefer `vibe edit motion-overlay clip.mp4 \"...\" --understand auto -o out.mp4` when the request asks for designed or animated motion graphics.\n- \"please add visuals using OpenAI image gen\" \u2192 `vibe generate image \"...\" -p openai ...`\n- *(verb-less paste)* \"aerial view of a misty mountain peak at sunrise...\" \u2192 `vibe generate image \"<paste>\" -o assets/mountain-peak.png`. **Don't** read it as a brief for DESIGN.md.\n\nIf genuinely uncertain, ask one short question: *\"single asset or\nmulti-scene project?\"* before authoring DESIGN.md or loading the\nhyperframes skill.\n\n**BUILD - create new video from text intent.**\nUse `vibe build` with a STORYBOARD.md + DESIGN.md. The\nskills-driven pipeline (v0.60+) dispatches narration TTS + backdrop\nimage-gen per beat, composes scene HTML via the bundled composition rules\nbundle, then renders to MP4. Idempotent re-runs reuse cached assets.\n\n**REMIX - transform existing video / audio.**\nUse `vibe remix`, `vibe edit`, or `vibe audio`. One-shot,\nbatch-oriented operations on a file the user already has on disk.\n`vibe edit text-overlay` is the free deterministic path for simple static\ntext burn-in. If the user asks for motion design, animated lower-thirds,\ndesigned titles, grain/vignette as part of a graphic treatment, or says\n\"motion graphics\", use `vibe edit motion-overlay ... --understand auto` instead.\n\nDecision rule: if the user asks for one asset, it's ASSET. If the user asks\nfor a multi-scene/storyboard/composed video, it's BUILD. If the user is\nstarting from a media file and wants it transformed, it's REMIX.\n\n## Common workflows\n\n### BUILD (new video from text)\n\n| Task | Command |\n|---|---|\n| One-shot storyboard \u2192 video | `vibe build [project-dir]` |\n| Render an existing scene project | `vibe render [project-dir] -o out.mp4` |\n| Lint scene HTML | `vibe scene lint --json` |\n| Generate a single image | `vibe generate image \"prompt\" -o img.png --quality hd` |\n| Generate a single video | `vibe generate video \"prompt\" -i image.png -o clip.mp4` |\n| Generate narration | `vibe generate narration \"text\" -o voice.mp3` |\n\n### REMIX (transform existing media)\n\n| Task | Command |\n|---|---|\n| Extract highlights from a long video | `vibe remix highlights file.mp4 -d 60` |\n| Long video \u2192 vertical shorts | `vibe remix auto-shorts file.mp4 -n 3 --add-captions` |\n| Add animated word-by-word captions | `vibe remix animated-caption file.mp4 -s karaoke-sweep` |\n| Add designed motion graphics overlay | `vibe edit motion-overlay file.mp4 \"lower-third...\" --understand auto -o out.mp4` |\n| Remove silence | `vibe edit silence-cut in.mp4 -o out.mp4` |\n| Add static captions | `vibe edit caption in.mp4 -o out.mp4` |\n| Translate audio (transcribe \u2192 TTS) | `vibe audio dub file.mp4 -t ko` |\n| Transcribe (Whisper, word-level) | `vibe audio transcribe file.mp4 --granularity word` |\n| Inspect media with Gemini | `vibe inspect media file.mp4 \"summarise\" --json` |\n\n### Compose pipelines (Video as Code)\n\n| Task | Command |\n|---|---|\n| Run a YAML pipeline | `vibe run pipeline.yaml --dry-run` |\n| Resume from last checkpoint | `vibe run pipeline.yaml --resume` |\n\n## Cost tiers\n\n| Tier | Examples | Approx. per call |\n|---|---|---|\n| **Free** | `schema/context/doctor`, `detect *`, `status *`, `plan`, `storyboard validate`, `inspect project/render --cheap`, deterministic edits | $0 |\n| **Low** | `generate narration/sound-effect/music`, `audio transcribe`, `inspect media`, optional AI review | $0.01\u2013$0.10 |\n| **High** | `generate image/motion`, `edit image/reframe/grade/speed-ramp` | $1\u2013$5 |\n| **Very High** | `generate video`, `edit fill-gaps`, `remix highlights/auto-shorts`, `build` with generated assets | $5\u2013$50+ |\n\n## Agent invariants\n\nWhen you run vibe commands programmatically:\n\n1. **Always `--json`** for structured output you can parse without regex\n2. **Always `--dry-run` first** for any High/Very-High tier command - it returns\n the cost estimate without spending API budget\n3. **Use `vibe schema <command>`** to discover parameters; do not guess flags\n4. **Pass complex options via `--stdin`**:\n ```bash\n echo '{\"video\":\"long.mp4\",\"count\":3,\"aspect\":\"9:16\"}' | vibe remix auto-shorts --stdin --json\n ```\n\n## Provider keys and project scope\n\nPrefer `vibe setup --scope project` for project-local keys. It writes\n`.vibeframe/config.yaml` in the setup directory; when you work from a\nnested scene directory, the `vibe` CLI automatically searches parent\ndirectories and uses the nearest project config. Do not assume the config\nfile must exist in the current subdirectory.\n\nRun `vibe doctor --json` from the directory where you will run commands\nand check `data.scope.project.configPath` / `data.scope.activeScope` before\ndeciding keys are missing. Never print or copy config file contents.\n\nFor generated project assets, use VibeFrame commands such as\n`vibe generate image|video|speech ...` so these project-scope keys are\nused. Do not switch to a host agent's built-in image/audio generation tool\nunless the user explicitly asks for a non-VibeFrame asset.\n\n`.env` is still supported as a gitignored fallback. Copy `.env.example`\nto start if you prefer environment variables.\n\n## App host setup\n\nVibeFrame is CLI-first, not terminal-only. Codex, Claude Code, and Cursor can\ndrive the same project through shell commands, and app hosts can also use\nVibeFrame's MCP server as a typed tool surface.\n\n```bash\nvibe host setup all # print snippets only\nvibe host setup all --write # write project/app config\nvibe host doctor all --json # verify readiness\n```\n\nDefault setup is snippet-only; use `--write` when you want VibeFrame to merge\nthe generated config. Keep provider keys in `.vibeframe/config.yaml`, user\nconfig, or env files - not in app host config.\n\n## Host agent loop\n\nFor long-running work, use your host's agent loop (Claude Code, Codex, Cursor,\nor another coding-agent host) as the outer loop. VibeFrame should not own a\ncompeting project-level agent loop. It provides `--json` commands, dry runs,\nbudget caps, `build-report.json`, `review-report.json`, `nextActions`,\n`safeToAutoRun`, `requiresConfirmation`, `fixOwner`, deterministic repair,\nand render inspection for the host agent to decide what to do next.\n\nCopy-paste agent prompt (Codex) - a plain prompt, not a built-in command:\n\n```text\nBuild this VibeFrame project into renders/final.mp4. Use --json for every\nvibe command, run --dry-run before paid operations, use --max-cost 5 for builds\nunless the user gives another budget, read build-report.json and\nreview-report.json before deciding the next action, prefer nextActions before\nguessing, run only safeToAutoRun:true actions automatically, and ask before\nrequiresConfirmation:true actions. Treat retryWith as the compatibility\nfallback, fixOwner:\"vibe\" as CLI repair work, and fixOwner:\"host-agent\" as\nSTORYBOARD.md, DESIGN.md, or composition edits.\nStop only when renders/final.mp4 exists, target duration and aspect ratio are\nmet, inspect render --cheap has no errors, any AI review score is >= 90 when AI review is requested, and every\nremaining host-agent issue is fixed, accepted with rationale, or reported as\nblocked.\n```\n\nCopy-paste agent prompt (Claude Code) - a plain prompt, not a built-in command:\n\n```text\nFinish this VibeFrame render using your host's agent loop as the outer\nloop. Use vibe context/schema when unsure, --json everywhere, dry-run before\npaid operations, budget cap via --max-cost 5, nextActions before guessing,\nbuild-report.json/review-report.json as loop state, and safeToAutoRun,\nrequiresConfirmation, and fixOwner to decide between vibe scene repair and\nhost-agent edits. Stop only after final MP4,\ntarget duration/aspect ratio, clean render inspection, any AI review score >= 90 when AI review is requested, and\nno unresolved unacknowledged host-agent issues.\n```\n\n### Composition rules (scene HTML)\n\nComposition rules live in the **Hyperframes skill** - framework rules, motion\nprinciples, type system, and visual-identity hard-gate. **Load that skill\nbefore authoring any scene composition HTML under `compositions/`.** The same\nrules govern `vibe scene lint`, so your authored HTML and the linter stay in\nagreement.\n\nWhere the skill comes from depends on your setup:\n\n- If the `hyperframes` skill is installed globally (e.g. Claude Code), your\n agent already has it and nothing else is needed.\n- Otherwise install it into this project with `vibe scene install-skill`,\n which runs upstream's own installer and writes\n `.agents/skills/hyperframes/`.\n\n`vibe init` never copies the rules in. They come from upstream so they stay\ncurrent, and fetching them is a network call the scaffold does not make on\nyour behalf. `vibe doctor` reports whether your agent can read them.\n\nFor render-stable text, do not apply continuous `scale`, `x`, `y`,\n`filter`, or other transform tweens to `.scene-content` or any ancestor\ncontaining live text/cards. Put ambient zoom/parallax on background or media\nlayers only; text should enter briefly and then hold still at its final CSS\nposition.\n\n### Scene composer (non-agent fallback)\n\nScene HTML is authored by you, the host agent - the CLI makes no LLM call\nduring `vibe build`. When no agent is available to author scenes, pass\n`--composer template` for the deterministic no-model composer\n(concat background + lower-thirds).\n\n## Project conventions\n\n<!-- Edit this section with YOUR project's specifics. Examples below. -->\n\n- Default aspect ratio: `16:9`\n- Default scene duration: `3 seconds` (per beat)\n- Brand voice: <describe>\n- Output naming: `renders/<name>-<timestamp>.mp4`\n";
|
|
21
|
+
export declare const AGENTS_MD = "# AGENTS.md\n\nThis project uses [VibeFrame](https://github.com/vericontext/vibeframe) -\na CLI for AI video generation on the user's own provider keys (Seedance,\nRunway, Kling, Gemini Omni), behind dry runs and a hard `--max-cost` ceiling.\nThe `vibe` command provides 80+ subcommands for video generation,\nediting, and analysis. Cost tiers below - **always confirm with the user\nbefore running High / Very High tier commands**.\n\n## Agent host coverage\n\nVibeFrame's CLI works with any bash-capable AI coding agent. Six host\nfamilies have first-class auto-detection and scaffolds today:\n\n- **Claude Code** - `CLAUDE.md` (this file's import wrapper) +\n `AGENTS.md` + `/vibe-*` slash commands.\n- **OpenAI Codex** - reads `AGENTS.md` natively (agents.md spec).\n- **Cursor** - reads `AGENTS.md` plus `.cursor/rules/` for project\n rules; supports MCP via `.cursor/mcp.json`.\n- **Aider** - reads `AGENTS.md` (binary-only detection by VibeFrame).\n- **Gemini CLI** - primary context file is `GEMINI.md`; also reads\n `AGENTS.md` if present.\n- **OpenCode** - reads `AGENTS.md` (officially supported per\n `opencode.ai/docs/rules`); supports MCP via `.opencode/mcp.json`.\n\nRun `vibe doctor` to see which host(s) the CLI detects in your\nenvironment. Anyone running another bash-capable agent (Continue,\nSourcegraph Cody, etc.) still gets this `AGENTS.md` as the universal\nfallback.\n\n## Self-discovery\n\nDon't memorise the command surface - read it from the CLI:\n\n```bash\nvibe --help # command groups overview\nvibe schema --list # full machine-readable catalog (80+)\nvibe schema --list --surface public # small first-run/product command surface\nvibe schema generate.video # JSON Schema for any single command\nvibe doctor # available providers + system health\nvibe host setup all # print Codex/Claude/Cursor app integration snippets\nvibe host doctor all --json # verify project guidance + MCP config\nvibe guide motion # choose text-overlay vs motion-overlay vs generate motion\nvibe guide scene # step-by-step authoring guide (scene)\nvibe guide pipeline # step-by-step authoring guide (pipeline)\n```\n\n## Route by the user's actual request\n\nRouting the user's request correctly is the most important judgement call\nyou'll make. Do not force everything into a scene project.\n\n**ASSET - default for any single-asset request OR ambiguous prompt.**\nIf the user asks for a single image, single video clip, sound effect, music\nbed, or narration file - **OR pastes a visual/audio brief without explicit\nstoryboard / scene / multi-scene language** - treat it as ASSET. Use\n`vibe generate ...` directly. Do **not** edit `DESIGN.md`,\n`STORYBOARD.md`, run `vibe scene ...`, or auto-load the hyperframes\nskill until BUILD intent is explicit. The visual-identity hard-gate\napplies to BUILD only.\n\nExamples:\n- \"make this image\" \u2192 `vibe generate image \"...\" -o assets/name.png`\n- \"use this image to make a video\" \u2192 `vibe generate video \"...\" -i image.png -o renders/name.mp4`\n- \"add a lower-third/title/animated overlay/grain/vignette to this clip\" \u2192 prefer `vibe edit motion-overlay clip.mp4 \"...\" --understand auto -o out.mp4` when the request asks for designed or animated motion graphics.\n- \"please add visuals using OpenAI image gen\" \u2192 `vibe generate image \"...\" -p openai ...`\n- *(verb-less paste)* \"aerial view of a misty mountain peak at sunrise...\" \u2192 `vibe generate image \"<paste>\" -o assets/mountain-peak.png`. **Don't** read it as a brief for DESIGN.md.\n\nIf genuinely uncertain, ask one short question: *\"single asset or\nmulti-scene project?\"* before authoring DESIGN.md or loading the\nhyperframes skill.\n\n**BUILD - create new video from text intent.**\nUse `vibe build` with a STORYBOARD.md + DESIGN.md. The\nskills-driven pipeline (v0.60+) dispatches narration TTS + backdrop\nimage-gen per beat, composes scene HTML via the bundled composition rules\nbundle, then renders to MP4. Idempotent re-runs reuse cached assets.\n\n**REMIX - transform existing video / audio.**\nUse `vibe remix`, `vibe edit`, or `vibe audio`. One-shot,\nbatch-oriented operations on a file the user already has on disk.\n`vibe edit text-overlay` is the free deterministic path for simple static\ntext burn-in. If the user asks for motion design, animated lower-thirds,\ndesigned titles, grain/vignette as part of a graphic treatment, or says\n\"motion graphics\", use `vibe edit motion-overlay ... --understand auto` instead.\n\nDecision rule: if the user asks for one asset, it's ASSET. If the user asks\nfor a multi-scene/storyboard/composed video, it's BUILD. If the user is\nstarting from a media file and wants it transformed, it's REMIX.\n\n## Common workflows\n\n### BUILD (new video from text)\n\n| Task | Command |\n|---|---|\n| One-shot storyboard \u2192 video | `vibe build [project-dir]` |\n| Render an existing scene project | `vibe render [project-dir] -o out.mp4` |\n| Lint scene HTML | `vibe scene lint --json` |\n| Generate a single image | `vibe generate image \"prompt\" -o img.png --quality hd` |\n| Generate a single video | `vibe generate video \"prompt\" -i image.png -o clip.mp4` |\n| Generate narration | `vibe generate narration \"text\" -o voice.mp3` |\n\n### REMIX (transform existing media)\n\n| Task | Command |\n|---|---|\n| Extract highlights from a long video | `vibe remix highlights file.mp4 -d 60` |\n| Long video \u2192 vertical shorts | `vibe remix auto-shorts file.mp4 -n 3 --add-captions` |\n| Add animated word-by-word captions | `vibe remix animated-caption file.mp4 -s karaoke-sweep` |\n| Add designed motion graphics overlay | `vibe edit motion-overlay file.mp4 \"lower-third...\" --understand auto -o out.mp4` |\n| Remove silence | `vibe edit silence-cut in.mp4 -o out.mp4` |\n| Add static captions | `vibe edit caption in.mp4 -o out.mp4` |\n| Translate audio (transcribe \u2192 TTS) | `vibe audio dub file.mp4 -t ko` |\n| Transcribe (Whisper, word-level) | `vibe audio transcribe file.mp4 --granularity word` |\n| Inspect media with Gemini | `vibe inspect media file.mp4 \"summarise\" --json` |\n\n### Compose pipelines (Video as Code)\n\n| Task | Command |\n|---|---|\n| Run a YAML pipeline | `vibe run pipeline.yaml --dry-run` |\n| Resume from last checkpoint | `vibe run pipeline.yaml --resume` |\n\n## Cost tiers\n\n| Tier | Examples | Approx. per call |\n|---|---|---|\n| **Free** | `schema/context/doctor`, `detect *`, `status *`, `plan`, `storyboard validate`, `inspect project/render --cheap`, deterministic edits | $0 |\n| **Low** | `generate narration/sound-effect/music`, `audio transcribe`, `inspect media`, optional AI review | $0.01\u2013$0.10 |\n| **High** | `generate image/motion`, `edit image/reframe/grade/speed-ramp` | $1\u2013$5 |\n| **Very High** | `generate video`, `edit fill-gaps`, `remix highlights/auto-shorts`, `build` with generated assets | $5\u2013$50+ |\n\n## Agent invariants\n\nWhen you run vibe commands programmatically:\n\n1. **Always `--json`** for structured output you can parse without regex\n2. **Always `--dry-run` first** for any High/Very-High tier command - it returns\n the cost estimate without spending API budget\n3. **Use `vibe schema <command>`** to discover parameters; do not guess flags\n4. **Pass complex options via `--stdin`**:\n ```bash\n echo '{\"video\":\"long.mp4\",\"count\":3,\"aspect\":\"9:16\"}' | vibe remix auto-shorts --stdin --json\n ```\n\n## Provider keys and project scope\n\nPrefer `vibe setup --scope project` for project-local keys. It writes\n`.vibeframe/config.yaml` in the setup directory; when you work from a\nnested scene directory, the `vibe` CLI automatically searches parent\ndirectories and uses the nearest project config. Do not assume the config\nfile must exist in the current subdirectory.\n\nRun `vibe doctor --json` from the directory where you will run commands\nand check `data.scope.project.configPath` / `data.scope.activeScope` before\ndeciding keys are missing. Never print or copy config file contents.\n\nFor generated project assets, use VibeFrame commands such as\n`vibe generate image|video|speech ...` so these project-scope keys are\nused. Do not switch to a host agent's built-in image/audio generation tool\nunless the user explicitly asks for a non-VibeFrame asset.\n\n`.env` is still supported as a gitignored fallback. Copy `.env.example`\nto start if you prefer environment variables.\n\n## App host setup\n\nVibeFrame is CLI-first, not terminal-only. Codex, Claude Code, and Cursor can\ndrive the same project through shell commands, and app hosts can also use\nVibeFrame's MCP server as a typed tool surface.\n\n```bash\nvibe host setup all # print snippets only\nvibe host setup all --write # write project/app config\nvibe host doctor all --json # verify readiness\n```\n\nDefault setup is snippet-only; use `--write` when you want VibeFrame to merge\nthe generated config. Keep provider keys in `.vibeframe/config.yaml`, user\nconfig, or env files - not in app host config.\n\n## Host agent loop\n\nFor long-running work, use your host's agent loop (Claude Code, Codex, Cursor,\nor another coding-agent host) as the outer loop. VibeFrame should not own a\ncompeting project-level agent loop. It provides `--json` commands, dry runs,\nbudget caps, `build-report.json`, `review-report.json`, `nextActions`,\n`safeToAutoRun`, `requiresConfirmation`, `fixOwner`, deterministic repair,\nand render inspection for the host agent to decide what to do next.\n\nCopy-paste agent prompt (Codex) - a plain prompt, not a built-in command:\n\n```text\nBuild this VibeFrame project into renders/final.mp4. Use --json for every\nvibe command, run --dry-run before paid operations, use --max-cost 5 for builds\nunless the user gives another budget, read build-report.json and\nreview-report.json before deciding the next action, prefer nextActions before\nguessing, run only safeToAutoRun:true actions automatically, and ask before\nrequiresConfirmation:true actions. Treat retryWith as the compatibility\nfallback, fixOwner:\"vibe\" as CLI repair work, and fixOwner:\"host-agent\" as\nSTORYBOARD.md, DESIGN.md, or composition edits.\nStop only when renders/final.mp4 exists, target duration and aspect ratio are\nmet, inspect render --cheap has no errors, any AI review score is >= 90 when AI review is requested, and every\nremaining host-agent issue is fixed, accepted with rationale, or reported as\nblocked.\n```\n\nCopy-paste agent prompt (Claude Code) - a plain prompt, not a built-in command:\n\n```text\nFinish this VibeFrame render using your host's agent loop as the outer\nloop. Use vibe context/schema when unsure, --json everywhere, dry-run before\npaid operations, budget cap via --max-cost 5, nextActions before guessing,\nbuild-report.json/review-report.json as loop state, and safeToAutoRun,\nrequiresConfirmation, and fixOwner to decide between vibe scene repair and\nhost-agent edits. Stop only after final MP4,\ntarget duration/aspect ratio, clean render inspection, any AI review score >= 90 when AI review is requested, and\nno unresolved unacknowledged host-agent issues.\n```\n\n### Composition rules (scene HTML)\n\nComposition rules live in the **Hyperframes skill** - framework rules, motion\nprinciples, type system, and visual-identity hard-gate. **Load that skill\nbefore authoring any scene composition HTML under `compositions/`.** The same\nrules govern `vibe scene lint`, so your authored HTML and the linter stay in\nagreement.\n\nWhere the skill comes from depends on your setup:\n\n- If the `hyperframes` skill is installed globally (e.g. Claude Code), your\n agent already has it and nothing else is needed.\n- Otherwise install it into this project with `vibe scene install-skill`,\n which runs upstream's own installer and writes\n `.agents/skills/hyperframes/`.\n\n`vibe init` never copies the rules in. They come from upstream so they stay\ncurrent, and fetching them is a network call the scaffold does not make on\nyour behalf. `vibe doctor` reports whether your agent can read them.\n\nFor render-stable text, do not apply continuous `scale`, `x`, `y`,\n`filter`, or other transform tweens to `.scene-content` or any ancestor\ncontaining live text/cards. Put ambient zoom/parallax on background or media\nlayers only; text should enter briefly and then hold still at its final CSS\nposition.\n\n### Scene composer (non-agent fallback)\n\nScene HTML is authored by you, the host agent - the CLI makes no LLM call\nduring `vibe build`. When no agent is available to author scenes, pass\n`--composer template` for the deterministic no-model composer\n(concat background + lower-thirds).\n\n## Project conventions\n\n<!-- Edit this section with YOUR project's specifics. Examples below. -->\n\n- Default aspect ratio: `16:9`\n- Default scene duration: `3 seconds` (per beat)\n- Brand voice: <describe>\n- Output naming: `renders/<name>-<timestamp>.mp4`\n";
|
|
22
22
|
/**
|
|
23
23
|
* Claude Code project file. Imports AGENTS.md so guidance stays
|
|
24
24
|
* single-sourced; adds Claude-specific overrides (slash commands, etc.).
|
|
@@ -7,6 +7,15 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { Command } from "commander";
|
|
9
9
|
export declare function registerVideoCommand(parent: Command): void;
|
|
10
|
+
/**
|
|
11
|
+
* Cost figure for a REAL (non-dry-run) generation envelope.
|
|
12
|
+
*
|
|
13
|
+
* Seedance has a token-accurate estimator; every other provider reports the
|
|
14
|
+
* command's tier upper bound with a warning naming it an estimate. Without
|
|
15
|
+
* this the success envelope defaulted to costUsd 0, which an agent budget
|
|
16
|
+
* loop reads as "free" - the hybrid-brew dogfood run billed Runway twice
|
|
17
|
+
* while reporting $0.
|
|
18
|
+
*/
|
|
10
19
|
export declare function realRunCost(provider: string, options: {
|
|
11
20
|
duration?: string;
|
|
12
21
|
resolution?: string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Commands:
|
|
7
7
|
* generate image - Generate image (Gemini, OpenAI, Grok, Runway)
|
|
8
|
-
* generate video - Generate video (Seedance, Grok, Kling, Runway, Veo)
|
|
8
|
+
* generate video - Generate video (Seedance, Grok, Kling, Runway, Omni, Veo)
|
|
9
9
|
* generate sound-effect - Sound effects (ElevenLabs)
|
|
10
10
|
* generate music - Music generation (ElevenLabs default, Replicate MusicGen)
|
|
11
11
|
* generate motion - Standalone motion assets (Claude/Gemini + Remotion)
|
|
@@ -75,6 +75,11 @@ export interface SuccessEnvelopeOptions {
|
|
|
75
75
|
warnings?: string[];
|
|
76
76
|
/** Pass-through of `--dry-run` flag — surfaces as a top-level `dryRun: true` in the envelope. */
|
|
77
77
|
dryRun?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* The caller already printed its own human-readable output (a build plan,
|
|
80
|
+
* a render summary), so human mode adds nothing for this dry run.
|
|
81
|
+
*/
|
|
82
|
+
humanRendered?: boolean;
|
|
78
83
|
}
|
|
79
84
|
/** Look up the upper-bound cost estimate for a command (used by dry-run). */
|
|
80
85
|
/**
|
|
@@ -87,12 +92,15 @@ export declare function lookupCostEstimateUpperBound(command: string): number;
|
|
|
87
92
|
* Emit a canonical success envelope (#33 — 2c). JSON mode prints the
|
|
88
93
|
* envelope; quiet mode prints a single primary value extracted from
|
|
89
94
|
* `data.outputPath ?? data.output ?? data.path ?? data.url ?? data.id`;
|
|
90
|
-
* human mode prints
|
|
95
|
+
* human mode prints a summary for dry runs (unless the caller rendered its
|
|
96
|
+
* own) and otherwise nothing — the caller renders human output itself.
|
|
91
97
|
*
|
|
92
98
|
* Canary scope: `generate image` only in 2c-canary. 2c-sweep migrates
|
|
93
99
|
* the rest. Old `outputResult()` remains for the sweep transition.
|
|
94
100
|
*/
|
|
95
101
|
export declare function outputSuccess(opts: SuccessEnvelopeOptions): void;
|
|
102
|
+
/** Print warnings to stderr in human mode; JSON envelopes carry them instead. */
|
|
103
|
+
export declare function printWarnings(warnings: readonly string[]): void;
|
|
96
104
|
/** Output result - JSON mode outputs JSON, quiet mode outputs primary value only */
|
|
97
105
|
export declare function outputResult(result: Record<string, unknown>): void;
|
|
98
106
|
/** Wrap console output - suppressed in JSON/quiet mode */
|
package/dist/index.js
CHANGED
|
@@ -6629,7 +6629,42 @@ function outputSuccess(opts) {
|
|
|
6629
6629
|
const data = opts.data;
|
|
6630
6630
|
const primary = data.outputPath ?? data.output ?? data.path ?? data.url ?? data.id;
|
|
6631
6631
|
if (primary !== void 0) console.log(String(primary));
|
|
6632
|
+
return;
|
|
6633
|
+
}
|
|
6634
|
+
if (opts.dryRun && !opts.humanRendered) {
|
|
6635
|
+
printDryRunSummary(opts.command, costUsd, opts.data, opts.warnings ?? []);
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
function printWarnings(warnings) {
|
|
6639
|
+
if (isJsonMode()) return;
|
|
6640
|
+
for (const warning of warnings) {
|
|
6641
|
+
process.stderr.write(`${source_default.yellow(`Warning: ${warning}`)}
|
|
6642
|
+
`);
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
function formatDryRunValue(value) {
|
|
6646
|
+
const text = Array.isArray(value) ? value.map((v) => formatDryRunValue(v)).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
6647
|
+
return text.length > 80 ? `${text.slice(0, 77)}...` : text;
|
|
6648
|
+
}
|
|
6649
|
+
function printDryRunSummary(command, costUsd, data, warnings) {
|
|
6650
|
+
const params = data.params && typeof data.params === "object" ? data.params : data;
|
|
6651
|
+
const rows = [
|
|
6652
|
+
["cost", costUsd > 0 ? `up to $${costUsd.toFixed(2)} (estimate)` : "free"]
|
|
6653
|
+
];
|
|
6654
|
+
for (const [key, value] of Object.entries(params)) {
|
|
6655
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
6656
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
6657
|
+
rows.push([key, formatDryRunValue(value)]);
|
|
6632
6658
|
}
|
|
6659
|
+
const width = Math.max(...rows.map(([key]) => key.length));
|
|
6660
|
+
console.log();
|
|
6661
|
+
console.log(`${source_default.bold.cyan(`Dry run: vibe ${command}`)} ${source_default.dim("(nothing was sent)")}`);
|
|
6662
|
+
for (const [key, value] of rows) {
|
|
6663
|
+
console.log(` ${source_default.dim(key.padEnd(width))} ${value}`);
|
|
6664
|
+
}
|
|
6665
|
+
printWarnings(warnings);
|
|
6666
|
+
console.log(source_default.dim(" Run again without --dry-run to execute."));
|
|
6667
|
+
console.log();
|
|
6633
6668
|
}
|
|
6634
6669
|
function log(...args) {
|
|
6635
6670
|
if (!isJsonMode() && !isQuietMode()) {
|
|
@@ -6984,8 +7019,8 @@ var init_api_keys = __esm({
|
|
|
6984
7019
|
envVar: "GOOGLE_API_KEY",
|
|
6985
7020
|
label: "Google",
|
|
6986
7021
|
showInSetup: true,
|
|
6987
|
-
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($),
|
|
6988
|
-
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen,
|
|
7022
|
+
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($), Omni video ($$)",
|
|
7023
|
+
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen, Omni video)",
|
|
6989
7024
|
envExampleUrl: "https://aistudio.google.com/apikey",
|
|
6990
7025
|
keyFormat: { prefix: /^AIza/, example: "AIza..." }
|
|
6991
7026
|
});
|
|
@@ -7239,10 +7274,35 @@ function findModel(provider, kind, aliasOrId) {
|
|
|
7239
7274
|
const lower = key.toLowerCase();
|
|
7240
7275
|
return listModels({ provider, kind }).find((m) => m.id === key || m.aliases?.includes(lower));
|
|
7241
7276
|
}
|
|
7277
|
+
function modelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
7278
|
+
if (!spec.shutdown)
|
|
7279
|
+
return { state: "served" };
|
|
7280
|
+
const remainingMs = Date.parse(`${spec.shutdown}T00:00:00Z`) - now.getTime();
|
|
7281
|
+
const instead = spec.replacement ? ` Use ${spec.replacement} instead.` : "";
|
|
7282
|
+
if (remainingMs <= 0) {
|
|
7283
|
+
return {
|
|
7284
|
+
state: "retired",
|
|
7285
|
+
shutdown: spec.shutdown,
|
|
7286
|
+
message: `${spec.label} (${spec.id}) was shut down by the provider on ${spec.shutdown}.${instead}`
|
|
7287
|
+
};
|
|
7288
|
+
}
|
|
7289
|
+
const daysLeft = Math.ceil(remainingMs / 864e5);
|
|
7290
|
+
return {
|
|
7291
|
+
state: "retiring",
|
|
7292
|
+
shutdown: spec.shutdown,
|
|
7293
|
+
daysLeft,
|
|
7294
|
+
message: `${spec.label} (${spec.id}) shuts down on ${spec.shutdown} (${daysLeft} day${daysLeft === 1 ? "" : "s"} left).${instead}`
|
|
7295
|
+
};
|
|
7296
|
+
}
|
|
7297
|
+
function assertModelServed(spec, now = /* @__PURE__ */ new Date()) {
|
|
7298
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
7299
|
+
if (lifecycle.state === "retired")
|
|
7300
|
+
throw new ModelRetiredError(lifecycle.message, spec);
|
|
7301
|
+
}
|
|
7242
7302
|
function modelAliases(provider, kind) {
|
|
7243
7303
|
return listModels({ provider, kind }).flatMap((m) => m.aliases ?? []);
|
|
7244
7304
|
}
|
|
7245
|
-
var MODEL_CATALOG;
|
|
7305
|
+
var MODEL_CATALOG, ModelRetiredError;
|
|
7246
7306
|
var init_catalog = __esm({
|
|
7247
7307
|
"../ai-providers/dist/catalog/catalog.js"() {
|
|
7248
7308
|
"use strict";
|
|
@@ -7278,8 +7338,8 @@ var init_catalog = __esm({
|
|
|
7278
7338
|
{ id: "seedance-2.0-fast", provider: "seedance", kind: "video", label: "Seedance 2.0 Fast", aliases: ["fast"], status: "ga", price: { usd: 0.2419, per: "second", basis: "720p 16:9" }, note: "4-15 s, up to 720p, native audio" },
|
|
7279
7339
|
{ id: "seedance-2.5", provider: "seedance", kind: "video", label: "Seedance 2.5", aliases: ["2.5"], status: "ga", price: { usd: 0.473, per: "second", basis: "720p 16:9" }, note: "Opt-in; 4-30 s, native audio" },
|
|
7280
7340
|
{ id: "gemini-omni-1.1-flash", provider: "omni", kind: "video", label: "Gemini Omni 1.1 Flash", default: true, status: "ga", price: { usd: 0.1, per: "second", basis: "720p" }, note: "Google video default; the model picks 3-10 s; native audio" },
|
|
7281
|
-
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
7282
|
-
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
7341
|
+
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
7342
|
+
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
7283
7343
|
{ id: "grok-imagine-video-1.5", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5", aliases: ["1.5"], default: true, status: "ga", price: { usd: 0.14, per: "second", basis: "720p" }, note: "1-15 s, native audio; 720p unless `--resolution` says otherwise" },
|
|
7284
7344
|
{ id: "grok-imagine-video-1.5-lite", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5 Lite", aliases: ["lite", "1.5-lite"], status: "ga", price: { usd: 0.03, per: "second", basis: "720p" }, note: "1-15 s, native audio" },
|
|
7285
7345
|
{ id: "grok-imagine-video", provider: "grok", kind: "video", label: "Grok Imagine Video", aliases: ["classic"], status: "legacy", price: { usd: 0.05, per: "second", basis: "480p" }, note: "Previous generation" },
|
|
@@ -7295,6 +7355,13 @@ var init_catalog = __esm({
|
|
|
7295
7355
|
{ id: "eleven_text_to_sound_v2", provider: "elevenlabs", kind: "sound-effect", label: "ElevenLabs Sound Effects v2", default: true, status: "ga", price: { usd: 0.12, per: "minute" }, note: "0.5-30 s" },
|
|
7296
7356
|
{ id: "whisper-1", provider: "openai", kind: "transcription", label: "Whisper", default: true, status: "deprecated", shutdown: "2027-02-26", note: "Only OpenAI model with word timestamps" }
|
|
7297
7357
|
];
|
|
7358
|
+
ModelRetiredError = class extends Error {
|
|
7359
|
+
constructor(message, model) {
|
|
7360
|
+
super(message);
|
|
7361
|
+
this.model = model;
|
|
7362
|
+
this.name = "ModelRetiredError";
|
|
7363
|
+
}
|
|
7364
|
+
};
|
|
7298
7365
|
}
|
|
7299
7366
|
});
|
|
7300
7367
|
|
|
@@ -7842,12 +7909,18 @@ var init_http = __esm({
|
|
|
7842
7909
|
// ../ai-providers/dist/gemini/GeminiProvider.js
|
|
7843
7910
|
function resolveVeoModel(alias) {
|
|
7844
7911
|
if (Object.hasOwn(VEO_MODEL_ALIASES, alias)) {
|
|
7845
|
-
return VEO_MODEL_ALIASES[alias];
|
|
7912
|
+
return servedVeoModel(VEO_MODEL_ALIASES[alias]);
|
|
7846
7913
|
}
|
|
7847
7914
|
const valid = Object.keys(VEO_MODEL_ALIASES).join(", ");
|
|
7848
7915
|
const hint = alias === "3.0" ? " Veo 3.0 was shut down by Google on 2025-11-12." : "";
|
|
7849
7916
|
throw new Error(`Unknown Veo model "${alias}". Valid: ${valid}.${hint}`);
|
|
7850
7917
|
}
|
|
7918
|
+
function servedVeoModel(id) {
|
|
7919
|
+
const spec = id ? findModel("veo", "video", id) : defaultModel("veo", "video");
|
|
7920
|
+
if (spec)
|
|
7921
|
+
assertModelServed(spec);
|
|
7922
|
+
return spec?.id ?? id;
|
|
7923
|
+
}
|
|
7851
7924
|
var VEO_MODEL_ALIASES, GeminiProvider, geminiProvider;
|
|
7852
7925
|
var init_GeminiProvider = __esm({
|
|
7853
7926
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
@@ -7891,7 +7964,7 @@ var init_GeminiProvider = __esm({
|
|
|
7891
7964
|
}
|
|
7892
7965
|
try {
|
|
7893
7966
|
const veoOpts = options ?? {};
|
|
7894
|
-
const model = veoOpts.model
|
|
7967
|
+
const model = servedVeoModel(veoOpts.model);
|
|
7895
7968
|
const aspectRatioMap = {
|
|
7896
7969
|
"16:9": "16:9",
|
|
7897
7970
|
"9:16": "9:16",
|
|
@@ -8068,7 +8141,7 @@ var init_GeminiProvider = __esm({
|
|
|
8068
8141
|
};
|
|
8069
8142
|
}
|
|
8070
8143
|
try {
|
|
8071
|
-
const model = options?.model
|
|
8144
|
+
const model = servedVeoModel(options?.model ?? findModel("veo", "video", "3.1")?.id);
|
|
8072
8145
|
const instance = {
|
|
8073
8146
|
video: { previousOperationName }
|
|
8074
8147
|
};
|
|
@@ -18510,6 +18583,7 @@ __export(dist_exports2, {
|
|
|
18510
18583
|
KlingProvider: () => KlingProvider,
|
|
18511
18584
|
KokoroProvider: () => KokoroProvider,
|
|
18512
18585
|
MODEL_CATALOG: () => MODEL_CATALOG,
|
|
18586
|
+
ModelRetiredError: () => ModelRetiredError,
|
|
18513
18587
|
OPENAI_IMAGE_DEFAULT_MODEL: () => OPENAI_IMAGE_DEFAULT_MODEL,
|
|
18514
18588
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
18515
18589
|
OllamaProvider: () => OllamaProvider,
|
|
@@ -18521,6 +18595,7 @@ __export(dist_exports2, {
|
|
|
18521
18595
|
RunwayProvider: () => RunwayProvider,
|
|
18522
18596
|
VEO_MODEL_ALIASES: () => VEO_MODEL_ALIASES,
|
|
18523
18597
|
WhisperProvider: () => WhisperProvider,
|
|
18598
|
+
assertModelServed: () => assertModelServed,
|
|
18524
18599
|
claudeProvider: () => claudeProvider,
|
|
18525
18600
|
defaultModel: () => defaultModel,
|
|
18526
18601
|
defineApiKey: () => defineApiKey,
|
|
@@ -18549,6 +18624,7 @@ __export(dist_exports2, {
|
|
|
18549
18624
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
18550
18625
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
18551
18626
|
modelAliases: () => modelAliases,
|
|
18627
|
+
modelLifecycle: () => modelLifecycle,
|
|
18552
18628
|
ollamaProvider: () => ollamaProvider,
|
|
18553
18629
|
omniProvider: () => omniProvider,
|
|
18554
18630
|
openaiImageProvider: () => openaiImageProvider,
|
|
@@ -36602,6 +36678,34 @@ var init_thumbnail = __esm({
|
|
|
36602
36678
|
}
|
|
36603
36679
|
});
|
|
36604
36680
|
|
|
36681
|
+
// src/utils/model-lifecycle.ts
|
|
36682
|
+
function videoModelSpec(provider, flags) {
|
|
36683
|
+
const catalogProvider = provider === "fal" ? "seedance" : provider;
|
|
36684
|
+
const flag = VIDEO_MODEL_FLAG[catalogProvider];
|
|
36685
|
+
return findModel(catalogProvider, "video", flag ? flags[flag] : void 0);
|
|
36686
|
+
}
|
|
36687
|
+
function checkModelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
36688
|
+
if (!spec) return [];
|
|
36689
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
36690
|
+
if (lifecycle.state === "retired") exitWithError(usageError(lifecycle.message));
|
|
36691
|
+
return lifecycle.state === "retiring" ? [lifecycle.message] : [];
|
|
36692
|
+
}
|
|
36693
|
+
var VIDEO_MODEL_FLAG;
|
|
36694
|
+
var init_model_lifecycle = __esm({
|
|
36695
|
+
"src/utils/model-lifecycle.ts"() {
|
|
36696
|
+
"use strict";
|
|
36697
|
+
init_dist2();
|
|
36698
|
+
init_output();
|
|
36699
|
+
VIDEO_MODEL_FLAG = {
|
|
36700
|
+
seedance: "seedanceModel",
|
|
36701
|
+
grok: "grokModel",
|
|
36702
|
+
kling: "klingModel",
|
|
36703
|
+
veo: "veoModel",
|
|
36704
|
+
runway: "runwayModel"
|
|
36705
|
+
};
|
|
36706
|
+
}
|
|
36707
|
+
});
|
|
36708
|
+
|
|
36605
36709
|
// src/commands/generate/video-extend.ts
|
|
36606
36710
|
import { resolve as resolve26 } from "node:path";
|
|
36607
36711
|
import { writeFile as writeFile23 } from "node:fs/promises";
|
|
@@ -36613,11 +36717,22 @@ function registerVideoExtendCommand(parent) {
|
|
|
36613
36717
|
if (options.output) {
|
|
36614
36718
|
validateOutputPath(options.output);
|
|
36615
36719
|
}
|
|
36720
|
+
let lifecycleWarnings = [];
|
|
36721
|
+
if (provider === "veo") {
|
|
36722
|
+
try {
|
|
36723
|
+
resolveVeoModel(options.veoModel);
|
|
36724
|
+
} catch (err) {
|
|
36725
|
+
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
36726
|
+
}
|
|
36727
|
+
lifecycleWarnings = checkModelLifecycle(findModel("veo", "video", options.veoModel));
|
|
36728
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
36729
|
+
}
|
|
36616
36730
|
if (options.dryRun) {
|
|
36617
36731
|
outputSuccess({
|
|
36618
36732
|
command: "generate video-extend",
|
|
36619
36733
|
startedAt,
|
|
36620
36734
|
dryRun: true,
|
|
36735
|
+
warnings: lifecycleWarnings,
|
|
36621
36736
|
data: {
|
|
36622
36737
|
params: {
|
|
36623
36738
|
id,
|
|
@@ -36770,6 +36885,7 @@ function registerVideoExtendCommand(parent) {
|
|
|
36770
36885
|
outputSuccess({
|
|
36771
36886
|
command: "generate video-extend",
|
|
36772
36887
|
startedAt,
|
|
36888
|
+
warnings: lifecycleWarnings,
|
|
36773
36889
|
data: {
|
|
36774
36890
|
provider: "veo",
|
|
36775
36891
|
taskId: result.id,
|
|
@@ -36818,6 +36934,7 @@ var init_video_extend = __esm({
|
|
|
36818
36934
|
init_ora();
|
|
36819
36935
|
init_dist2();
|
|
36820
36936
|
init_api_key();
|
|
36937
|
+
init_model_lifecycle();
|
|
36821
36938
|
init_output();
|
|
36822
36939
|
init_validate();
|
|
36823
36940
|
init_ai_helpers();
|
|
@@ -38528,6 +38645,8 @@ Examples:
|
|
|
38528
38645
|
} catch (err) {
|
|
38529
38646
|
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
38530
38647
|
}
|
|
38648
|
+
const lifecycleWarnings = checkModelLifecycle(videoModelSpec(provider, options));
|
|
38649
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
38531
38650
|
if (options.dryRun) {
|
|
38532
38651
|
const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
|
|
38533
38652
|
outputSuccess({
|
|
@@ -38535,6 +38654,7 @@ Examples:
|
|
|
38535
38654
|
startedAt,
|
|
38536
38655
|
dryRun: true,
|
|
38537
38656
|
costUsd,
|
|
38657
|
+
warnings: lifecycleWarnings,
|
|
38538
38658
|
data: {
|
|
38539
38659
|
params: {
|
|
38540
38660
|
prompt: prompt3,
|
|
@@ -38542,13 +38662,10 @@ Examples:
|
|
|
38542
38662
|
duration: options.duration,
|
|
38543
38663
|
ratio: options.ratio,
|
|
38544
38664
|
image: options.image,
|
|
38545
|
-
mode: options.mode,
|
|
38665
|
+
mode: provider === "kling" ? options.mode : void 0,
|
|
38546
38666
|
negative: options.negative,
|
|
38547
38667
|
resolution: options.resolution,
|
|
38548
|
-
|
|
38549
|
-
seedanceModel: options.seedanceModel,
|
|
38550
|
-
grokModel: options.grokModel,
|
|
38551
|
-
klingModel: options.klingModel,
|
|
38668
|
+
model: videoModelSpec(provider, options)?.id,
|
|
38552
38669
|
refImages: options.refImages,
|
|
38553
38670
|
refVideos: options.refVideos,
|
|
38554
38671
|
refAudio: options.refAudio,
|
|
@@ -38940,7 +39057,7 @@ Examples:
|
|
|
38940
39057
|
command: "generate video",
|
|
38941
39058
|
startedAt,
|
|
38942
39059
|
costUsd: cost.costUsd,
|
|
38943
|
-
warnings:
|
|
39060
|
+
warnings: [...lifecycleWarnings, ...cost.warnings],
|
|
38944
39061
|
data: {
|
|
38945
39062
|
provider,
|
|
38946
39063
|
taskId: result?.id,
|
|
@@ -38952,9 +39069,6 @@ Examples:
|
|
|
38952
39069
|
return;
|
|
38953
39070
|
}
|
|
38954
39071
|
console.log();
|
|
38955
|
-
if (provider === "veo") {
|
|
38956
|
-
console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
|
|
38957
|
-
}
|
|
38958
39072
|
if (finalResult.videoUrl) {
|
|
38959
39073
|
console.log(`Video URL: ${finalResult.videoUrl}`);
|
|
38960
39074
|
}
|
|
@@ -39079,7 +39193,6 @@ function printVideoStarted(providerLabel, taskId, taskType) {
|
|
|
39079
39193
|
console.log(`Task ID: ${source_default.bold(taskId)}`);
|
|
39080
39194
|
if (taskType) console.log(`Type: ${taskType}`);
|
|
39081
39195
|
}
|
|
39082
|
-
var VEO_SHUTDOWN_WARNING;
|
|
39083
39196
|
var init_video = __esm({
|
|
39084
39197
|
"src/commands/generate/video.ts"() {
|
|
39085
39198
|
"use strict";
|
|
@@ -39088,6 +39201,7 @@ var init_video = __esm({
|
|
|
39088
39201
|
init_dist3();
|
|
39089
39202
|
init_dist2();
|
|
39090
39203
|
init_api_key();
|
|
39204
|
+
init_model_lifecycle();
|
|
39091
39205
|
init_tty();
|
|
39092
39206
|
init_output();
|
|
39093
39207
|
init_validate();
|
|
@@ -39095,7 +39209,6 @@ var init_video = __esm({
|
|
|
39095
39209
|
init_upload_host();
|
|
39096
39210
|
init_ai_helpers();
|
|
39097
39211
|
init_status_jobs();
|
|
39098
|
-
VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
|
|
39099
39212
|
}
|
|
39100
39213
|
});
|
|
39101
39214
|
|
|
@@ -39205,7 +39318,7 @@ Advanced:
|
|
|
39205
39318
|
generate video-cancel Provider lifecycle control; poll with 'vibe status job <job-id> --json'
|
|
39206
39319
|
|
|
39207
39320
|
API Keys (per provider):
|
|
39208
|
-
GOOGLE_API_KEY Image (default),
|
|
39321
|
+
GOOGLE_API_KEY Image (default), Omni video
|
|
39209
39322
|
OPENAI_API_KEY Image (-p openai)
|
|
39210
39323
|
FAL_API_KEY Seedance video (-p seedance, default video)
|
|
39211
39324
|
XAI_API_KEY Grok image/video
|
|
@@ -56227,6 +56340,7 @@ var init_detect = __esm({
|
|
|
56227
56340
|
validateOutputPath(options.output);
|
|
56228
56341
|
}
|
|
56229
56342
|
if (options.dryRun) {
|
|
56343
|
+
spinner2.stop();
|
|
56230
56344
|
outputSuccess({
|
|
56231
56345
|
command: "detect scenes",
|
|
56232
56346
|
startedAt,
|
|
@@ -56346,6 +56460,7 @@ var init_detect = __esm({
|
|
|
56346
56460
|
validateOutputPath(options.output);
|
|
56347
56461
|
}
|
|
56348
56462
|
if (options.dryRun) {
|
|
56463
|
+
spinner2.stop();
|
|
56349
56464
|
outputSuccess({
|
|
56350
56465
|
command: "detect silence",
|
|
56351
56466
|
startedAt,
|
|
@@ -56432,6 +56547,7 @@ var init_detect = __esm({
|
|
|
56432
56547
|
validateOutputPath(options.output);
|
|
56433
56548
|
}
|
|
56434
56549
|
if (options.dryRun) {
|
|
56550
|
+
spinner2.stop();
|
|
56435
56551
|
outputSuccess({
|
|
56436
56552
|
command: "detect beats",
|
|
56437
56553
|
startedAt,
|
|
@@ -70389,7 +70505,7 @@ var init_generate2 = __esm({
|
|
|
70389
70505
|
cost: "high",
|
|
70390
70506
|
title: "Generate Video",
|
|
70391
70507
|
annotations: { readOnly: false, openWorld: true },
|
|
70392
|
-
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.",
|
|
70508
|
+
description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, Gemini Omni, and Veo (shuts down 2026-10-22). Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
|
|
70393
70509
|
schema: external_exports.object({
|
|
70394
70510
|
prompt: external_exports.string().describe("Text prompt describing the video"),
|
|
70395
70511
|
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
|
|
@@ -73672,7 +73788,7 @@ init_source();
|
|
|
73672
73788
|
// package.json
|
|
73673
73789
|
var package_default = {
|
|
73674
73790
|
name: "@vibeframe/cli",
|
|
73675
|
-
version: "0.115.
|
|
73791
|
+
version: "0.115.5",
|
|
73676
73792
|
description: "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
|
|
73677
73793
|
private: false,
|
|
73678
73794
|
license: "MIT",
|
|
@@ -74058,6 +74174,7 @@ timelineCommand.command("add-source").description("Add a media source to the tim
|
|
|
74058
74174
|
const spinner2 = ora("Adding source...").start();
|
|
74059
74175
|
try {
|
|
74060
74176
|
if (options.dryRun) {
|
|
74177
|
+
spinner2.stop();
|
|
74061
74178
|
outputSuccess({
|
|
74062
74179
|
command: "timeline add-source",
|
|
74063
74180
|
startedAt,
|
|
@@ -74122,6 +74239,7 @@ timelineCommand.command("add-clip").description("Add a clip to the timeline").ar
|
|
|
74122
74239
|
validateResourceId(sourceId);
|
|
74123
74240
|
if (options.track) validateResourceId(options.track);
|
|
74124
74241
|
if (options.dryRun) {
|
|
74242
|
+
spinner2.stop();
|
|
74125
74243
|
outputSuccess({
|
|
74126
74244
|
command: "timeline add-clip",
|
|
74127
74245
|
startedAt,
|
|
@@ -74202,6 +74320,7 @@ timelineCommand.command("add-track").description("Add a new track").argument("<p
|
|
|
74202
74320
|
const spinner2 = ora("Adding track...").start();
|
|
74203
74321
|
try {
|
|
74204
74322
|
if (options.dryRun) {
|
|
74323
|
+
spinner2.stop();
|
|
74205
74324
|
outputSuccess({
|
|
74206
74325
|
command: "timeline add-track",
|
|
74207
74326
|
startedAt,
|
|
@@ -74263,6 +74382,7 @@ timelineCommand.command("add-effect").description("Add an effect to a clip").arg
|
|
|
74263
74382
|
try {
|
|
74264
74383
|
validateResourceId(clipId);
|
|
74265
74384
|
if (options.dryRun) {
|
|
74385
|
+
spinner2.stop();
|
|
74266
74386
|
outputSuccess({
|
|
74267
74387
|
command: "timeline add-effect",
|
|
74268
74388
|
startedAt,
|
|
@@ -74335,6 +74455,7 @@ timelineCommand.command("trim-clip").description("Trim a clip").argument("<proje
|
|
|
74335
74455
|
try {
|
|
74336
74456
|
validateResourceId(clipId);
|
|
74337
74457
|
if (options.dryRun) {
|
|
74458
|
+
spinner2.stop();
|
|
74338
74459
|
outputSuccess({
|
|
74339
74460
|
command: "timeline trim-clip",
|
|
74340
74461
|
startedAt,
|
|
@@ -74502,6 +74623,7 @@ timelineCommand.command("split-clip").description("Split a clip at a specific ti
|
|
|
74502
74623
|
try {
|
|
74503
74624
|
validateResourceId(clipId);
|
|
74504
74625
|
if (options.dryRun) {
|
|
74626
|
+
spinner2.stop();
|
|
74505
74627
|
outputSuccess({
|
|
74506
74628
|
command: "timeline split-clip",
|
|
74507
74629
|
startedAt,
|
|
@@ -74564,6 +74686,7 @@ timelineCommand.command("duplicate-clip").description("Duplicate a clip").argume
|
|
|
74564
74686
|
try {
|
|
74565
74687
|
validateResourceId(clipId);
|
|
74566
74688
|
if (options.dryRun) {
|
|
74689
|
+
spinner2.stop();
|
|
74567
74690
|
outputSuccess({
|
|
74568
74691
|
command: "timeline duplicate-clip",
|
|
74569
74692
|
startedAt,
|
|
@@ -74623,6 +74746,7 @@ timelineCommand.command("delete-clip").description("Delete a clip from the timel
|
|
|
74623
74746
|
try {
|
|
74624
74747
|
validateResourceId(clipId);
|
|
74625
74748
|
if (options.dryRun) {
|
|
74749
|
+
spinner2.stop();
|
|
74626
74750
|
outputSuccess({
|
|
74627
74751
|
command: "timeline delete-clip",
|
|
74628
74752
|
startedAt,
|
|
@@ -74676,6 +74800,7 @@ timelineCommand.command("move-clip").description("Move a clip to a new position"
|
|
|
74676
74800
|
validateResourceId(clipId);
|
|
74677
74801
|
if (options.track) validateResourceId(options.track);
|
|
74678
74802
|
if (options.dryRun) {
|
|
74803
|
+
spinner2.stop();
|
|
74679
74804
|
outputSuccess({
|
|
74680
74805
|
command: "timeline move-clip",
|
|
74681
74806
|
startedAt,
|
|
@@ -80171,6 +80296,7 @@ batchCommand.command("import").description("Import multiple media files from a d
|
|
|
80171
80296
|
const spinner2 = ora("Scanning directory...").start();
|
|
80172
80297
|
try {
|
|
80173
80298
|
if (options.dryRun) {
|
|
80299
|
+
spinner2.stop();
|
|
80174
80300
|
outputSuccess({
|
|
80175
80301
|
command: "batch import",
|
|
80176
80302
|
startedAt,
|
|
@@ -80248,6 +80374,7 @@ batchCommand.command("concat").description("Concatenate multiple sources into se
|
|
|
80248
80374
|
const spinner2 = ora("Creating clips...").start();
|
|
80249
80375
|
try {
|
|
80250
80376
|
if (options.dryRun) {
|
|
80377
|
+
spinner2.stop();
|
|
80251
80378
|
outputSuccess({
|
|
80252
80379
|
command: "batch concat",
|
|
80253
80380
|
startedAt,
|
|
@@ -80326,6 +80453,7 @@ batchCommand.command("apply-effect").description("Apply an effect to multiple cl
|
|
|
80326
80453
|
const spinner2 = ora("Applying effects...").start();
|
|
80327
80454
|
try {
|
|
80328
80455
|
if (options.dryRun) {
|
|
80456
|
+
spinner2.stop();
|
|
80329
80457
|
outputSuccess({
|
|
80330
80458
|
command: "batch apply-effect",
|
|
80331
80459
|
startedAt,
|
|
@@ -80397,6 +80525,7 @@ batchCommand.command("remove-clips").description("Remove multiple clips from the
|
|
|
80397
80525
|
const spinner2 = ora("Removing clips...").start();
|
|
80398
80526
|
try {
|
|
80399
80527
|
if (options.dryRun) {
|
|
80528
|
+
spinner2.stop();
|
|
80400
80529
|
outputSuccess({
|
|
80401
80530
|
command: "batch remove-clips",
|
|
80402
80531
|
startedAt,
|
|
@@ -80459,7 +80588,9 @@ batchCommand.command("info").description("Show batch processing statistics").arg
|
|
|
80459
80588
|
const tracks = project.getTracks();
|
|
80460
80589
|
const summary = project.getSummary();
|
|
80461
80590
|
spinner2.stop();
|
|
80462
|
-
console.log(
|
|
80591
|
+
console.log(`
|
|
80592
|
+
${source_default.bold("Project Statistics")}
|
|
80593
|
+
`);
|
|
80463
80594
|
const videoSources = sources.filter((s) => s.type === "video").length;
|
|
80464
80595
|
const audioSources = sources.filter((s) => s.type === "audio").length;
|
|
80465
80596
|
const imageSources = sources.filter((s) => s.type === "image").length;
|
|
@@ -80853,7 +80984,7 @@ var AI_FEATURES = [
|
|
|
80853
80984
|
label: "Videos",
|
|
80854
80985
|
desc: "generate + extend",
|
|
80855
80986
|
defaultProvider: "Seedance 2.0 via fal.ai (Artificial Analysis #2 t2v + i2v, since v0.57)",
|
|
80856
|
-
alsoAvailable: "Grok Imagine, Kling, Runway Gen-4.5,
|
|
80987
|
+
alsoAvailable: "Grok Imagine, Kling, Runway Gen-4.5, Gemini Omni",
|
|
80857
80988
|
keyHint: "1-2 keys",
|
|
80858
80989
|
keys: [
|
|
80859
80990
|
{
|
|
@@ -80932,16 +81063,16 @@ var AI_FEATURES = [
|
|
|
80932
81063
|
defaultFor: { kind: "video", value: "runway" }
|
|
80933
81064
|
},
|
|
80934
81065
|
{
|
|
80935
|
-
label: "
|
|
80936
|
-
desc: "Google
|
|
81066
|
+
label: "Gemini Omni",
|
|
81067
|
+
desc: "Google Gemini Omni video generation",
|
|
80937
81068
|
key: {
|
|
80938
81069
|
configKey: "google",
|
|
80939
81070
|
envVar: "GOOGLE_API_KEY",
|
|
80940
81071
|
name: "Google",
|
|
80941
81072
|
url: "https://aistudio.google.com/apikey",
|
|
80942
|
-
what: "Google
|
|
81073
|
+
what: "Google Gemini Omni video generation"
|
|
80943
81074
|
},
|
|
80944
|
-
defaultFor: { kind: "video", value: "
|
|
81075
|
+
defaultFor: { kind: "video", value: "omni" }
|
|
80945
81076
|
}
|
|
80946
81077
|
],
|
|
80947
81078
|
tryCommand: 'vibe generate video "ocean waves" -o waves.mp4'
|
|
@@ -82475,7 +82606,7 @@ var AGENTS_MD = `# AGENTS.md
|
|
|
82475
82606
|
|
|
82476
82607
|
This project uses [VibeFrame](https://github.com/vericontext/vibeframe) -
|
|
82477
82608
|
a CLI for AI video generation on the user's own provider keys (Seedance,
|
|
82478
|
-
Runway,
|
|
82609
|
+
Runway, Kling, Gemini Omni), behind dry runs and a hard \`--max-cost\` ceiling.
|
|
82479
82610
|
The \`vibe\` command provides 80+ subcommands for video generation,
|
|
82480
82611
|
editing, and analysis. Cost tiers below - **always confirm with the user
|
|
82481
82612
|
before running High / Very High tier commands**.
|
|
@@ -82800,7 +82931,7 @@ function renderEnvExample(opts = {}) {
|
|
|
82800
82931
|
${fallback2}# \u2500\u2500 LLM provider / optional \`vibe agent\` fallback (pick one) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
82801
82932
|
ANTHROPIC_API_KEY= # Claude - recommended default
|
|
82802
82933
|
OPENAI_API_KEY= # GPT-5.4 mini \xB7 Whisper \xB7 gpt-image-2.5
|
|
82803
|
-
GOOGLE_API_KEY= # Gemini \xB7
|
|
82934
|
+
GOOGLE_API_KEY= # Gemini \xB7 Omni video
|
|
82804
82935
|
XAI_API_KEY= # Grok image+video
|
|
82805
82936
|
OPENROUTER_API_KEY= # multiplexes any provider above
|
|
82806
82937
|
# OLLAMA_HOST=http://localhost:11434 # offline, no key needed
|
|
@@ -87654,7 +87785,8 @@ program2.name("vibe").showSuggestionAfterError(true).description("VibeFrame CLI
|
|
|
87654
87785
|
process.stderr.write(JSON.stringify(err, null, 2) + "\n");
|
|
87655
87786
|
} else {
|
|
87656
87787
|
write2(source_default.red(str.trim()) + "\n");
|
|
87657
|
-
write2(source_default.dim("Run with --help for full options
|
|
87788
|
+
write2(`${source_default.dim("Run with --help for full options.")}
|
|
87789
|
+
`);
|
|
87658
87790
|
}
|
|
87659
87791
|
}
|
|
87660
87792
|
}).configureHelp({
|
|
@@ -87807,7 +87939,8 @@ function propagateErrorHandling(cmd) {
|
|
|
87807
87939
|
process.stderr.write(JSON.stringify(err, null, 2) + "\n");
|
|
87808
87940
|
} else {
|
|
87809
87941
|
write2(source_default.red(str.trim()) + "\n");
|
|
87810
|
-
write2(source_default.dim("Run with --help for full options
|
|
87942
|
+
write2(`${source_default.dim("Run with --help for full options.")}
|
|
87943
|
+
`);
|
|
87811
87944
|
}
|
|
87812
87945
|
}
|
|
87813
87946
|
});
|
|
@@ -201,8 +201,8 @@ var init_api_keys = __esm({
|
|
|
201
201
|
envVar: "GOOGLE_API_KEY",
|
|
202
202
|
label: "Google",
|
|
203
203
|
showInSetup: true,
|
|
204
|
-
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($),
|
|
205
|
-
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen,
|
|
204
|
+
setupDescription: "Gemini \u2014 image gen (free tier), video analysis ($), Omni video ($$)",
|
|
205
|
+
envExampleComment: "Google API Key (Gemini auto-edit suggestions, image gen, Omni video)",
|
|
206
206
|
envExampleUrl: "https://aistudio.google.com/apikey",
|
|
207
207
|
keyFormat: { prefix: /^AIza/, example: "AIza..." }
|
|
208
208
|
});
|
|
@@ -456,10 +456,35 @@ function findModel(provider, kind, aliasOrId) {
|
|
|
456
456
|
const lower = key.toLowerCase();
|
|
457
457
|
return listModels({ provider, kind }).find((m) => m.id === key || m.aliases?.includes(lower));
|
|
458
458
|
}
|
|
459
|
+
function modelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
460
|
+
if (!spec.shutdown)
|
|
461
|
+
return { state: "served" };
|
|
462
|
+
const remainingMs = Date.parse(`${spec.shutdown}T00:00:00Z`) - now.getTime();
|
|
463
|
+
const instead = spec.replacement ? ` Use ${spec.replacement} instead.` : "";
|
|
464
|
+
if (remainingMs <= 0) {
|
|
465
|
+
return {
|
|
466
|
+
state: "retired",
|
|
467
|
+
shutdown: spec.shutdown,
|
|
468
|
+
message: `${spec.label} (${spec.id}) was shut down by the provider on ${spec.shutdown}.${instead}`
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const daysLeft = Math.ceil(remainingMs / 864e5);
|
|
472
|
+
return {
|
|
473
|
+
state: "retiring",
|
|
474
|
+
shutdown: spec.shutdown,
|
|
475
|
+
daysLeft,
|
|
476
|
+
message: `${spec.label} (${spec.id}) shuts down on ${spec.shutdown} (${daysLeft} day${daysLeft === 1 ? "" : "s"} left).${instead}`
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function assertModelServed(spec, now = /* @__PURE__ */ new Date()) {
|
|
480
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
481
|
+
if (lifecycle.state === "retired")
|
|
482
|
+
throw new ModelRetiredError(lifecycle.message, spec);
|
|
483
|
+
}
|
|
459
484
|
function modelAliases(provider, kind) {
|
|
460
485
|
return listModels({ provider, kind }).flatMap((m) => m.aliases ?? []);
|
|
461
486
|
}
|
|
462
|
-
var MODEL_CATALOG;
|
|
487
|
+
var MODEL_CATALOG, ModelRetiredError;
|
|
463
488
|
var init_catalog = __esm({
|
|
464
489
|
"../ai-providers/dist/catalog/catalog.js"() {
|
|
465
490
|
"use strict";
|
|
@@ -495,8 +520,8 @@ var init_catalog = __esm({
|
|
|
495
520
|
{ id: "seedance-2.0-fast", provider: "seedance", kind: "video", label: "Seedance 2.0 Fast", aliases: ["fast"], status: "ga", price: { usd: 0.2419, per: "second", basis: "720p 16:9" }, note: "4-15 s, up to 720p, native audio" },
|
|
496
521
|
{ id: "seedance-2.5", provider: "seedance", kind: "video", label: "Seedance 2.5", aliases: ["2.5"], status: "ga", price: { usd: 0.473, per: "second", basis: "720p 16:9" }, note: "Opt-in; 4-30 s, native audio" },
|
|
497
522
|
{ id: "gemini-omni-1.1-flash", provider: "omni", kind: "video", label: "Gemini Omni 1.1 Flash", default: true, status: "ga", price: { usd: 0.1, per: "second", basis: "720p" }, note: "Google video default; the model picks 3-10 s; native audio" },
|
|
498
|
-
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
499
|
-
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
523
|
+
{ id: "veo-3.1-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1", aliases: ["3.1"], status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.4, per: "second", basis: "720p/1080p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
524
|
+
{ id: "veo-3.1-fast-generate-preview", provider: "veo", kind: "video", label: "Veo 3.1 Fast", aliases: ["3.1-fast"], default: true, status: "deprecated", shutdown: "2026-10-22", replacement: "`-p omni` (Gemini Omni 1.1 Flash)", price: { usd: 0.1, per: "second", basis: "720p" }, note: "4-8 s, native audio; explicit `-p veo` only" },
|
|
500
525
|
{ id: "grok-imagine-video-1.5", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5", aliases: ["1.5"], default: true, status: "ga", price: { usd: 0.14, per: "second", basis: "720p" }, note: "1-15 s, native audio; 720p unless `--resolution` says otherwise" },
|
|
501
526
|
{ id: "grok-imagine-video-1.5-lite", provider: "grok", kind: "video", label: "Grok Imagine Video 1.5 Lite", aliases: ["lite", "1.5-lite"], status: "ga", price: { usd: 0.03, per: "second", basis: "720p" }, note: "1-15 s, native audio" },
|
|
502
527
|
{ id: "grok-imagine-video", provider: "grok", kind: "video", label: "Grok Imagine Video", aliases: ["classic"], status: "legacy", price: { usd: 0.05, per: "second", basis: "480p" }, note: "Previous generation" },
|
|
@@ -512,6 +537,13 @@ var init_catalog = __esm({
|
|
|
512
537
|
{ id: "eleven_text_to_sound_v2", provider: "elevenlabs", kind: "sound-effect", label: "ElevenLabs Sound Effects v2", default: true, status: "ga", price: { usd: 0.12, per: "minute" }, note: "0.5-30 s" },
|
|
513
538
|
{ id: "whisper-1", provider: "openai", kind: "transcription", label: "Whisper", default: true, status: "deprecated", shutdown: "2027-02-26", note: "Only OpenAI model with word timestamps" }
|
|
514
539
|
];
|
|
540
|
+
ModelRetiredError = class extends Error {
|
|
541
|
+
constructor(message, model) {
|
|
542
|
+
super(message);
|
|
543
|
+
this.model = model;
|
|
544
|
+
this.name = "ModelRetiredError";
|
|
545
|
+
}
|
|
546
|
+
};
|
|
515
547
|
}
|
|
516
548
|
});
|
|
517
549
|
|
|
@@ -1059,12 +1091,18 @@ var init_http = __esm({
|
|
|
1059
1091
|
// ../ai-providers/dist/gemini/GeminiProvider.js
|
|
1060
1092
|
function resolveVeoModel(alias) {
|
|
1061
1093
|
if (Object.hasOwn(VEO_MODEL_ALIASES, alias)) {
|
|
1062
|
-
return VEO_MODEL_ALIASES[alias];
|
|
1094
|
+
return servedVeoModel(VEO_MODEL_ALIASES[alias]);
|
|
1063
1095
|
}
|
|
1064
1096
|
const valid = Object.keys(VEO_MODEL_ALIASES).join(", ");
|
|
1065
1097
|
const hint = alias === "3.0" ? " Veo 3.0 was shut down by Google on 2025-11-12." : "";
|
|
1066
1098
|
throw new Error(`Unknown Veo model "${alias}". Valid: ${valid}.${hint}`);
|
|
1067
1099
|
}
|
|
1100
|
+
function servedVeoModel(id) {
|
|
1101
|
+
const spec = id ? findModel("veo", "video", id) : defaultModel("veo", "video");
|
|
1102
|
+
if (spec)
|
|
1103
|
+
assertModelServed(spec);
|
|
1104
|
+
return spec?.id ?? id;
|
|
1105
|
+
}
|
|
1068
1106
|
var VEO_MODEL_ALIASES, GeminiProvider, geminiProvider;
|
|
1069
1107
|
var init_GeminiProvider = __esm({
|
|
1070
1108
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
@@ -1108,7 +1146,7 @@ var init_GeminiProvider = __esm({
|
|
|
1108
1146
|
}
|
|
1109
1147
|
try {
|
|
1110
1148
|
const veoOpts = options ?? {};
|
|
1111
|
-
const model = veoOpts.model
|
|
1149
|
+
const model = servedVeoModel(veoOpts.model);
|
|
1112
1150
|
const aspectRatioMap = {
|
|
1113
1151
|
"16:9": "16:9",
|
|
1114
1152
|
"9:16": "9:16",
|
|
@@ -1285,7 +1323,7 @@ var init_GeminiProvider = __esm({
|
|
|
1285
1323
|
};
|
|
1286
1324
|
}
|
|
1287
1325
|
try {
|
|
1288
|
-
const model = options?.model
|
|
1326
|
+
const model = servedVeoModel(options?.model ?? findModel("veo", "video", "3.1")?.id);
|
|
1289
1327
|
const instance = {
|
|
1290
1328
|
video: { previousOperationName }
|
|
1291
1329
|
};
|
|
@@ -11727,6 +11765,7 @@ __export(dist_exports2, {
|
|
|
11727
11765
|
KlingProvider: () => KlingProvider,
|
|
11728
11766
|
KokoroProvider: () => KokoroProvider,
|
|
11729
11767
|
MODEL_CATALOG: () => MODEL_CATALOG,
|
|
11768
|
+
ModelRetiredError: () => ModelRetiredError,
|
|
11730
11769
|
OPENAI_IMAGE_DEFAULT_MODEL: () => OPENAI_IMAGE_DEFAULT_MODEL,
|
|
11731
11770
|
OPENAI_TTS_VOICES: () => OPENAI_TTS_VOICES,
|
|
11732
11771
|
OllamaProvider: () => OllamaProvider,
|
|
@@ -11738,6 +11777,7 @@ __export(dist_exports2, {
|
|
|
11738
11777
|
RunwayProvider: () => RunwayProvider,
|
|
11739
11778
|
VEO_MODEL_ALIASES: () => VEO_MODEL_ALIASES,
|
|
11740
11779
|
WhisperProvider: () => WhisperProvider,
|
|
11780
|
+
assertModelServed: () => assertModelServed,
|
|
11741
11781
|
claudeProvider: () => claudeProvider,
|
|
11742
11782
|
defaultModel: () => defaultModel,
|
|
11743
11783
|
defineApiKey: () => defineApiKey,
|
|
@@ -11766,6 +11806,7 @@ __export(dist_exports2, {
|
|
|
11766
11806
|
loadBundledKokoroRuntime: () => loadBundledKokoroRuntime,
|
|
11767
11807
|
loadKokoroFromWorkspace: () => loadKokoroFromWorkspace,
|
|
11768
11808
|
modelAliases: () => modelAliases,
|
|
11809
|
+
modelLifecycle: () => modelLifecycle,
|
|
11769
11810
|
ollamaProvider: () => ollamaProvider,
|
|
11770
11811
|
omniProvider: () => omniProvider,
|
|
11771
11812
|
openaiImageProvider: () => openaiImageProvider,
|
|
@@ -30473,8 +30514,43 @@ function outputSuccess(opts) {
|
|
|
30473
30514
|
const data = opts.data;
|
|
30474
30515
|
const primary = data.outputPath ?? data.output ?? data.path ?? data.url ?? data.id;
|
|
30475
30516
|
if (primary !== void 0) console.log(String(primary));
|
|
30517
|
+
return;
|
|
30518
|
+
}
|
|
30519
|
+
if (opts.dryRun && !opts.humanRendered) {
|
|
30520
|
+
printDryRunSummary(opts.command, costUsd, opts.data, opts.warnings ?? []);
|
|
30521
|
+
}
|
|
30522
|
+
}
|
|
30523
|
+
function printWarnings(warnings) {
|
|
30524
|
+
if (isJsonMode()) return;
|
|
30525
|
+
for (const warning of warnings) {
|
|
30526
|
+
process.stderr.write(`${source_default.yellow(`Warning: ${warning}`)}
|
|
30527
|
+
`);
|
|
30476
30528
|
}
|
|
30477
30529
|
}
|
|
30530
|
+
function formatDryRunValue(value) {
|
|
30531
|
+
const text = Array.isArray(value) ? value.map((v) => formatDryRunValue(v)).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
30532
|
+
return text.length > 80 ? `${text.slice(0, 77)}...` : text;
|
|
30533
|
+
}
|
|
30534
|
+
function printDryRunSummary(command, costUsd, data, warnings) {
|
|
30535
|
+
const params = data.params && typeof data.params === "object" ? data.params : data;
|
|
30536
|
+
const rows = [
|
|
30537
|
+
["cost", costUsd > 0 ? `up to $${costUsd.toFixed(2)} (estimate)` : "free"]
|
|
30538
|
+
];
|
|
30539
|
+
for (const [key, value] of Object.entries(params)) {
|
|
30540
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
30541
|
+
if (Array.isArray(value) && value.length === 0) continue;
|
|
30542
|
+
rows.push([key, formatDryRunValue(value)]);
|
|
30543
|
+
}
|
|
30544
|
+
const width = Math.max(...rows.map(([key]) => key.length));
|
|
30545
|
+
console.log();
|
|
30546
|
+
console.log(`${source_default.bold.cyan(`Dry run: vibe ${command}`)} ${source_default.dim("(nothing was sent)")}`);
|
|
30547
|
+
for (const [key, value] of rows) {
|
|
30548
|
+
console.log(` ${source_default.dim(key.padEnd(width))} ${value}`);
|
|
30549
|
+
}
|
|
30550
|
+
printWarnings(warnings);
|
|
30551
|
+
console.log(source_default.dim(" Run again without --dry-run to execute."));
|
|
30552
|
+
console.log();
|
|
30553
|
+
}
|
|
30478
30554
|
function log(...args) {
|
|
30479
30555
|
if (!isJsonMode() && !isQuietMode()) {
|
|
30480
30556
|
console.log(...args);
|
|
@@ -44079,6 +44155,34 @@ var init_thumbnail = __esm({
|
|
|
44079
44155
|
}
|
|
44080
44156
|
});
|
|
44081
44157
|
|
|
44158
|
+
// src/utils/model-lifecycle.ts
|
|
44159
|
+
function videoModelSpec(provider, flags) {
|
|
44160
|
+
const catalogProvider = provider === "fal" ? "seedance" : provider;
|
|
44161
|
+
const flag = VIDEO_MODEL_FLAG[catalogProvider];
|
|
44162
|
+
return findModel(catalogProvider, "video", flag ? flags[flag] : void 0);
|
|
44163
|
+
}
|
|
44164
|
+
function checkModelLifecycle(spec, now = /* @__PURE__ */ new Date()) {
|
|
44165
|
+
if (!spec) return [];
|
|
44166
|
+
const lifecycle = modelLifecycle(spec, now);
|
|
44167
|
+
if (lifecycle.state === "retired") exitWithError(usageError(lifecycle.message));
|
|
44168
|
+
return lifecycle.state === "retiring" ? [lifecycle.message] : [];
|
|
44169
|
+
}
|
|
44170
|
+
var VIDEO_MODEL_FLAG;
|
|
44171
|
+
var init_model_lifecycle = __esm({
|
|
44172
|
+
"src/utils/model-lifecycle.ts"() {
|
|
44173
|
+
"use strict";
|
|
44174
|
+
init_dist2();
|
|
44175
|
+
init_output();
|
|
44176
|
+
VIDEO_MODEL_FLAG = {
|
|
44177
|
+
seedance: "seedanceModel",
|
|
44178
|
+
grok: "grokModel",
|
|
44179
|
+
kling: "klingModel",
|
|
44180
|
+
veo: "veoModel",
|
|
44181
|
+
runway: "runwayModel"
|
|
44182
|
+
};
|
|
44183
|
+
}
|
|
44184
|
+
});
|
|
44185
|
+
|
|
44082
44186
|
// src/commands/generate/video-extend.ts
|
|
44083
44187
|
import { resolve as resolve48 } from "node:path";
|
|
44084
44188
|
import { writeFile as writeFile34 } from "node:fs/promises";
|
|
@@ -44090,11 +44194,22 @@ function registerVideoExtendCommand(parent) {
|
|
|
44090
44194
|
if (options.output) {
|
|
44091
44195
|
validateOutputPath(options.output);
|
|
44092
44196
|
}
|
|
44197
|
+
let lifecycleWarnings = [];
|
|
44198
|
+
if (provider === "veo") {
|
|
44199
|
+
try {
|
|
44200
|
+
resolveVeoModel(options.veoModel);
|
|
44201
|
+
} catch (err) {
|
|
44202
|
+
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
44203
|
+
}
|
|
44204
|
+
lifecycleWarnings = checkModelLifecycle(findModel("veo", "video", options.veoModel));
|
|
44205
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
44206
|
+
}
|
|
44093
44207
|
if (options.dryRun) {
|
|
44094
44208
|
outputSuccess({
|
|
44095
44209
|
command: "generate video-extend",
|
|
44096
44210
|
startedAt,
|
|
44097
44211
|
dryRun: true,
|
|
44212
|
+
warnings: lifecycleWarnings,
|
|
44098
44213
|
data: {
|
|
44099
44214
|
params: {
|
|
44100
44215
|
id,
|
|
@@ -44247,6 +44362,7 @@ function registerVideoExtendCommand(parent) {
|
|
|
44247
44362
|
outputSuccess({
|
|
44248
44363
|
command: "generate video-extend",
|
|
44249
44364
|
startedAt,
|
|
44365
|
+
warnings: lifecycleWarnings,
|
|
44250
44366
|
data: {
|
|
44251
44367
|
provider: "veo",
|
|
44252
44368
|
taskId: result.id,
|
|
@@ -44295,6 +44411,7 @@ var init_video_extend = __esm({
|
|
|
44295
44411
|
init_ora();
|
|
44296
44412
|
init_dist2();
|
|
44297
44413
|
init_api_key();
|
|
44414
|
+
init_model_lifecycle();
|
|
44298
44415
|
init_output();
|
|
44299
44416
|
init_validate();
|
|
44300
44417
|
init_ai_helpers();
|
|
@@ -46005,6 +46122,8 @@ Examples:
|
|
|
46005
46122
|
} catch (err) {
|
|
46006
46123
|
exitWithError(usageError(err instanceof Error ? err.message : String(err)));
|
|
46007
46124
|
}
|
|
46125
|
+
const lifecycleWarnings = checkModelLifecycle(videoModelSpec(provider, options));
|
|
46126
|
+
if (!options.dryRun) printWarnings(lifecycleWarnings);
|
|
46008
46127
|
if (options.dryRun) {
|
|
46009
46128
|
const costUsd = provider === "seedance" || provider === "fal" ? realRunCost(provider, options).costUsd : void 0;
|
|
46010
46129
|
outputSuccess({
|
|
@@ -46012,6 +46131,7 @@ Examples:
|
|
|
46012
46131
|
startedAt,
|
|
46013
46132
|
dryRun: true,
|
|
46014
46133
|
costUsd,
|
|
46134
|
+
warnings: lifecycleWarnings,
|
|
46015
46135
|
data: {
|
|
46016
46136
|
params: {
|
|
46017
46137
|
prompt: prompt3,
|
|
@@ -46019,13 +46139,10 @@ Examples:
|
|
|
46019
46139
|
duration: options.duration,
|
|
46020
46140
|
ratio: options.ratio,
|
|
46021
46141
|
image: options.image,
|
|
46022
|
-
mode: options.mode,
|
|
46142
|
+
mode: provider === "kling" ? options.mode : void 0,
|
|
46023
46143
|
negative: options.negative,
|
|
46024
46144
|
resolution: options.resolution,
|
|
46025
|
-
|
|
46026
|
-
seedanceModel: options.seedanceModel,
|
|
46027
|
-
grokModel: options.grokModel,
|
|
46028
|
-
klingModel: options.klingModel,
|
|
46145
|
+
model: videoModelSpec(provider, options)?.id,
|
|
46029
46146
|
refImages: options.refImages,
|
|
46030
46147
|
refVideos: options.refVideos,
|
|
46031
46148
|
refAudio: options.refAudio,
|
|
@@ -46417,7 +46534,7 @@ Examples:
|
|
|
46417
46534
|
command: "generate video",
|
|
46418
46535
|
startedAt,
|
|
46419
46536
|
costUsd: cost.costUsd,
|
|
46420
|
-
warnings:
|
|
46537
|
+
warnings: [...lifecycleWarnings, ...cost.warnings],
|
|
46421
46538
|
data: {
|
|
46422
46539
|
provider,
|
|
46423
46540
|
taskId: result?.id,
|
|
@@ -46429,9 +46546,6 @@ Examples:
|
|
|
46429
46546
|
return;
|
|
46430
46547
|
}
|
|
46431
46548
|
console.log();
|
|
46432
|
-
if (provider === "veo") {
|
|
46433
|
-
console.log(source_default.yellow(VEO_SHUTDOWN_WARNING));
|
|
46434
|
-
}
|
|
46435
46549
|
if (finalResult.videoUrl) {
|
|
46436
46550
|
console.log(`Video URL: ${finalResult.videoUrl}`);
|
|
46437
46551
|
}
|
|
@@ -46556,7 +46670,6 @@ function printVideoStarted(providerLabel, taskId, taskType) {
|
|
|
46556
46670
|
console.log(`Task ID: ${source_default.bold(taskId)}`);
|
|
46557
46671
|
if (taskType) console.log(`Type: ${taskType}`);
|
|
46558
46672
|
}
|
|
46559
|
-
var VEO_SHUTDOWN_WARNING;
|
|
46560
46673
|
var init_video = __esm({
|
|
46561
46674
|
"src/commands/generate/video.ts"() {
|
|
46562
46675
|
"use strict";
|
|
@@ -46565,6 +46678,7 @@ var init_video = __esm({
|
|
|
46565
46678
|
init_dist3();
|
|
46566
46679
|
init_dist2();
|
|
46567
46680
|
init_api_key();
|
|
46681
|
+
init_model_lifecycle();
|
|
46568
46682
|
init_tty();
|
|
46569
46683
|
init_output();
|
|
46570
46684
|
init_validate();
|
|
@@ -46572,7 +46686,6 @@ var init_video = __esm({
|
|
|
46572
46686
|
init_upload_host();
|
|
46573
46687
|
init_ai_helpers();
|
|
46574
46688
|
init_status_jobs();
|
|
46575
|
-
VEO_SHUTDOWN_WARNING = "Veo 3.1 preview models shut down on 2026-10-22. Use `-p omni` (Gemini Omni 1.1 Flash) instead.";
|
|
46576
46689
|
}
|
|
46577
46690
|
});
|
|
46578
46691
|
|
|
@@ -46682,7 +46795,7 @@ Advanced:
|
|
|
46682
46795
|
generate video-cancel Provider lifecycle control; poll with 'vibe status job <job-id> --json'
|
|
46683
46796
|
|
|
46684
46797
|
API Keys (per provider):
|
|
46685
|
-
GOOGLE_API_KEY Image (default),
|
|
46798
|
+
GOOGLE_API_KEY Image (default), Omni video
|
|
46686
46799
|
OPENAI_API_KEY Image (-p openai)
|
|
46687
46800
|
FAL_API_KEY Seedance video (-p seedance, default video)
|
|
46688
46801
|
XAI_API_KEY Grok image/video
|
|
@@ -47780,6 +47893,7 @@ var init_detect = __esm({
|
|
|
47780
47893
|
validateOutputPath(options.output);
|
|
47781
47894
|
}
|
|
47782
47895
|
if (options.dryRun) {
|
|
47896
|
+
spinner2.stop();
|
|
47783
47897
|
outputSuccess({
|
|
47784
47898
|
command: "detect scenes",
|
|
47785
47899
|
startedAt,
|
|
@@ -47899,6 +48013,7 @@ var init_detect = __esm({
|
|
|
47899
48013
|
validateOutputPath(options.output);
|
|
47900
48014
|
}
|
|
47901
48015
|
if (options.dryRun) {
|
|
48016
|
+
spinner2.stop();
|
|
47902
48017
|
outputSuccess({
|
|
47903
48018
|
command: "detect silence",
|
|
47904
48019
|
startedAt,
|
|
@@ -47985,6 +48100,7 @@ var init_detect = __esm({
|
|
|
47985
48100
|
validateOutputPath(options.output);
|
|
47986
48101
|
}
|
|
47987
48102
|
if (options.dryRun) {
|
|
48103
|
+
spinner2.stop();
|
|
47988
48104
|
outputSuccess({
|
|
47989
48105
|
command: "detect beats",
|
|
47990
48106
|
startedAt,
|
|
@@ -57720,7 +57836,7 @@ var generateVideoTool = defineTool({
|
|
|
57720
57836
|
cost: "high",
|
|
57721
57837
|
title: "Generate Video",
|
|
57722
57838
|
annotations: { readOnly: false, openWorld: true },
|
|
57723
|
-
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.",
|
|
57839
|
+
description: "Generate video using AI. Supports Seedance 2.0 via fal.ai, Grok, Kling, Runway, Gemini Omni, and Veo (shuts down 2026-10-22). Requires FAL_API_KEY, XAI_API_KEY, KLING_API_KEY, RUNWAY_API_SECRET, or GOOGLE_API_KEY.",
|
|
57724
57840
|
schema: external_exports.object({
|
|
57725
57841
|
prompt: external_exports.string().describe("Text prompt describing the video"),
|
|
57726
57842
|
provider: external_exports.enum(["seedance", "grok", "kling", "runway", "veo", "omni"]).optional().describe(
|
|
@@ -32,15 +32,15 @@ export declare const storyboardSetTool: import("../define-tool.js").ToolDefiniti
|
|
|
32
32
|
jsonValue: z.ZodOptional<z.ZodBoolean>;
|
|
33
33
|
unset: z.ZodOptional<z.ZodBoolean>;
|
|
34
34
|
}, "strip", z.ZodTypeAny, {
|
|
35
|
-
beat: string;
|
|
36
35
|
key: string;
|
|
36
|
+
beat: string;
|
|
37
37
|
value?: string | undefined;
|
|
38
38
|
projectDir?: string | undefined;
|
|
39
39
|
unset?: boolean | undefined;
|
|
40
40
|
jsonValue?: boolean | undefined;
|
|
41
41
|
}, {
|
|
42
|
-
beat: string;
|
|
43
42
|
key: string;
|
|
43
|
+
beat: string;
|
|
44
44
|
value?: string | undefined;
|
|
45
45
|
projectDir?: string | undefined;
|
|
46
46
|
unset?: boolean | undefined;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model shutdown checks for commands that call a dated model.
|
|
3
|
+
*
|
|
4
|
+
* The catalog records each model's announced shutdown date. Commands check
|
|
5
|
+
* it before any dry run or paid request: a retiring model adds a warning to
|
|
6
|
+
* the dry run, the result, and stderr; a retired model is a usage error that
|
|
7
|
+
* names the replacement. Providers enforce the same rule on their own, so
|
|
8
|
+
* executors that skip this check still never call a retired model.
|
|
9
|
+
*/
|
|
10
|
+
import { type ModelSpec } from "@vibeframe/ai-providers";
|
|
11
|
+
/** Model flags `generate video` reads, keyed by provider. */
|
|
12
|
+
export interface VideoModelFlags {
|
|
13
|
+
seedanceModel?: string;
|
|
14
|
+
grokModel?: string;
|
|
15
|
+
klingModel?: string;
|
|
16
|
+
veoModel?: string;
|
|
17
|
+
runwayModel?: string;
|
|
18
|
+
}
|
|
19
|
+
/** The catalog model a video provider will call, given the command's model flags. */
|
|
20
|
+
export declare function videoModelSpec(provider: string, flags: VideoModelFlags): ModelSpec | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Exit with a usage error for a retired model; return the shutdown warning
|
|
23
|
+
* for a retiring one, for the caller's envelope and `printWarnings()`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function checkModelLifecycle(spec: ModelSpec | undefined, now?: Date): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.115.
|
|
3
|
+
"version": "0.115.5",
|
|
4
4
|
"description": "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -91,8 +91,8 @@
|
|
|
91
91
|
"tsx": "^4.21.0",
|
|
92
92
|
"typescript": "^5.3.3",
|
|
93
93
|
"vitest": "^1.2.2",
|
|
94
|
-
"@vibeframe/ai-providers": "0.115.
|
|
95
|
-
"@vibeframe/core": "0.115.
|
|
94
|
+
"@vibeframe/ai-providers": "0.115.5",
|
|
95
|
+
"@vibeframe/core": "0.115.5"
|
|
96
96
|
},
|
|
97
97
|
"engines": {
|
|
98
98
|
"node": ">=20"
|