@vibeframe/cli 0.115.1 → 0.115.3

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.
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import type { LLMAdapter } from "./index.js";
5
5
  import type { ToolDefinition, LLMResponse, AgentMessage, LLMProvider } from "../types.js";
6
+ /** Drop schema keys Gemini rejects, recursing into properties and items. */
7
+ export declare function toGeminiSchema(schema: unknown): unknown;
6
8
  export declare class GeminiAdapter implements LLMAdapter {
7
9
  readonly provider: LLMProvider;
8
10
  private client;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Claude and Gemini adapters replay the provider's own assistant content
3
+ * (thinking blocks, thought signatures) and group tool results per turn.
4
+ * Mock-based, no API calls.
5
+ */
6
+ export {};
@@ -21,7 +21,7 @@ export declare class ConversationMemory {
21
21
  /**
22
22
  * Add an assistant message
23
23
  */
24
- addAssistant(content: string, toolCalls?: ToolCall[]): void;
24
+ addAssistant(content: string, toolCalls?: ToolCall[], providerContent?: unknown): void;
25
25
  /**
26
26
  * Add a tool result message
27
27
  */
@@ -48,6 +48,12 @@ export interface AgentMessage {
48
48
  content: string;
49
49
  toolCalls?: ToolCall[];
50
50
  toolCallId?: string;
51
+ /**
52
+ * The provider's own assistant content (Claude content blocks, Gemini
53
+ * parts), replayed verbatim on the next turn. Newer models require their
54
+ * thinking blocks and thought signatures back unmodified during tool use.
55
+ */
56
+ providerContent?: unknown;
51
57
  }
52
58
  export interface AgentConfig {
53
59
  provider: LLMProvider;
@@ -60,6 +66,8 @@ export interface LLMResponse {
60
66
  content: string;
61
67
  toolCalls?: ToolCall[];
62
68
  finishReason: "stop" | "tool_calls" | "length" | "error";
69
+ /** See {@link AgentMessage.providerContent}. */
70
+ providerContent?: unknown;
63
71
  }
64
72
  export interface AgentContext {
65
73
  projectPath: string | null;
@@ -0,0 +1 @@
1
+ export {};
@@ -19,6 +19,8 @@ export declare function backdropCacheDescriptor(opts: {
19
19
  quality: "standard" | "hd";
20
20
  size: string;
21
21
  ratio?: string;
22
+ /** Provider-specific image model override — switching models re-keys the asset. */
23
+ model?: string;
22
24
  }): CacheAssetDescriptor;
23
25
  export declare function characterCacheDescriptor(opts: {
24
26
  name: string;
@@ -26,6 +28,8 @@ export declare function characterCacheDescriptor(opts: {
26
28
  provider: string;
27
29
  quality: "standard" | "hd";
28
30
  size: string;
31
+ /** Provider-specific image model override — switching models re-keys the asset. */
32
+ model?: string;
29
33
  }): CacheAssetDescriptor;
30
34
  export declare function keyframeCacheDescriptor(opts: {
31
35
  beatId: string;
@@ -36,6 +40,8 @@ export declare function keyframeCacheDescriptor(opts: {
36
40
  ratio?: string;
37
41
  /** Character sheet paths used as edit references — changing them re-keys the keyframe. */
38
42
  characters?: string[];
43
+ /** Provider-specific image model override — switching models re-keys the asset. */
44
+ model?: string;
39
45
  }): CacheAssetDescriptor;
40
46
  export declare function imageRatioForSize(size: string | undefined): string;
41
47
  export declare function videoCacheDescriptor(opts: {
@@ -109,6 +109,8 @@ export interface CreateBuildPlanOptions {
109
109
  imageProvider?: string;
110
110
  imageQuality?: "standard" | "hd";
111
111
  imageSize?: string;
112
+ /** Provider-specific image model override — must match executeSceneBuild for cache parity. */
113
+ imageModel?: string;
112
114
  videoProvider?: string;
113
115
  musicProvider?: string;
114
116
  composer?: string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Video providers a project build (`vibe plan`, `vibe build`, storyboard
3
+ * `provider:` cues, project config) can target. One list, so adding a
4
+ * provider is a one-line change instead of a hunt through every command.
5
+ */
6
+ export declare const BUILD_VIDEO_PROVIDERS: readonly ["seedance", "grok", "kling", "runway", "omni", "veo"];
7
+ export type BuildVideoProvider = (typeof BUILD_VIDEO_PROVIDERS)[number];
8
+ export declare function isBuildVideoProvider(value: string): value is BuildVideoProvider;
9
+ /** Normalize user input; `fal` is the deprecated alias for seedance. Unknown values fall back to seedance. */
10
+ export declare function resolveBuildVideoProvider(value: unknown): BuildVideoProvider;
11
+ /** Config/API-key id that unlocks a video provider. */
12
+ export declare function videoProviderConfigKey(provider: string): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,166 @@
1
+ import type { ReviewAction } from "./review-report.js";
2
+ export interface FootageClipInput {
3
+ id: string;
4
+ clipDurationSec: number;
5
+ narrationDurationSec?: number;
6
+ }
7
+ export interface FootagePlanOptions {
8
+ /** Crossfade length between segments (seconds). */
9
+ transitionSec?: number;
10
+ /** Fade-from/to-black length at the head and tail of the cut (seconds). */
11
+ fadeSec?: number;
12
+ /** Gap between a segment becoming dominant and its narration starting. */
13
+ narrationLeadSec?: number;
14
+ /** Silence required after narration ends before the segment may end. */
15
+ narrationTailSec?: number;
16
+ }
17
+ export interface FootageBeatPlan {
18
+ id: string;
19
+ clipDurationSec: number;
20
+ narrationDurationSec?: number;
21
+ /** Segment length on the timeline (clip, possibly tpad-extended). */
22
+ segmentDurationSec: number;
23
+ /** Seconds of last-frame clone added so narration + tail fit. 0 = untouched. */
24
+ extendedSec: number;
25
+ /** Timeline position where this segment (and its incoming crossfade) starts. */
26
+ startSec: number;
27
+ /** Timeline position where this segment's narration starts (when present). */
28
+ narrationStartSec?: number;
29
+ }
30
+ export interface FootageTimelinePlan {
31
+ beats: FootageBeatPlan[];
32
+ transitionSec: number;
33
+ fadeSec: number;
34
+ totalDurationSec: number;
35
+ warnings: string[];
36
+ }
37
+ export declare const FOOTAGE_DEFAULTS: {
38
+ readonly transitionSec: 0.5;
39
+ readonly fadeSec: 0.6;
40
+ readonly narrationLeadSec: 0.35;
41
+ readonly narrationTailSec: 0.4;
42
+ readonly width: 1920;
43
+ readonly height: 1080;
44
+ readonly fps: 30;
45
+ readonly crf: 18;
46
+ readonly finishCrf: 23;
47
+ readonly musicVolume: 0.35;
48
+ readonly duck: {
49
+ readonly thresholdDb: -30;
50
+ readonly ratio: 3;
51
+ readonly attackMs: 20;
52
+ readonly releaseMs: 200;
53
+ };
54
+ /**
55
+ * The cinematic finish pass: subtle vignette + temporal film grain, applied
56
+ * before the head/tail fades. These are the field-tested values that pull
57
+ * provider clips away from the too-clean "AI look"; the fades multiply over
58
+ * them so blacks stay black.
59
+ */
60
+ readonly finish: readonly ["vignette=angle=PI/5", "noise=alls=7:allf=t"];
61
+ /** Base segment length for a ken-burns keyframe fallback (no clip to probe). */
62
+ readonly kenburnsSec: 4;
63
+ /** Slow-push ceiling for the ken-burns zoom. */
64
+ readonly kenburnsMaxZoom: 1.1;
65
+ };
66
+ /**
67
+ * Compute segment lengths and timeline offsets from real clip/narration
68
+ * durations. Deterministic and side-effect free so agents can reason about the
69
+ * cut from the report alone.
70
+ *
71
+ * Timeline model: segment i starts at `start_i = start_{i-1} + seg_{i-1} - T`
72
+ * (each crossfade overlaps T seconds), so the xfade filter offset for join i
73
+ * is exactly `start_i`. When clips are too short to host the requested
74
+ * transition, T is clamped (with a warning) instead of failing the run.
75
+ */
76
+ export declare function planFootageTimeline(inputs: FootageClipInput[], opts?: FootagePlanOptions): FootageTimelinePlan;
77
+ /** One visual source per beat: a generated clip, or a keyframe still to ken-burns. */
78
+ export interface FootageSource {
79
+ /** Absolute path to the clip (video) or keyframe still (image). */
80
+ path: string;
81
+ kind: "video" | "image";
82
+ }
83
+ export interface FootageAssembleArgsOptions {
84
+ /** Visual sources in beat order (parallel to `plan.beats`). */
85
+ sources: FootageSource[];
86
+ plan: FootageTimelinePlan;
87
+ /** Absolute narration paths keyed by beat index (sparse — not every beat narrates). */
88
+ narrationPaths: ReadonlyMap<number, string>;
89
+ /** Absolute music-bed path; looped and ducked under narration when present. */
90
+ musicPath?: string;
91
+ outputPath: string;
92
+ width?: number;
93
+ height?: number;
94
+ fps?: number;
95
+ crf?: number;
96
+ musicVolume?: number;
97
+ /** Apply the cinematic finish pass (vignette + film grain) before the fades. */
98
+ finish?: boolean;
99
+ }
100
+ /**
101
+ * Build the single-pass FFmpeg invocation: normalize every clip to one
102
+ * geometry/fps, xfade-chain them at the planned offsets, fade the head and
103
+ * tail, and mix narration (adelay per beat) over an optional looped,
104
+ * sidechain-ducked music bed.
105
+ */
106
+ export declare function buildFootageAssembleArgs(opts: FootageAssembleArgsOptions): string[];
107
+ export interface FootageAssembleOptions {
108
+ projectDir: string;
109
+ /** Output path (relative paths resolve against projectDir). Default: renders/footage.mp4. */
110
+ output?: string;
111
+ transitionSec?: number;
112
+ fadeSec?: number;
113
+ /**
114
+ * Music bed: an explicit path, `"none"` to disable, or undefined to
115
+ * auto-detect `assets/music.mp3|wav` then `assets/music-<firstBeat>.mp3|wav`.
116
+ */
117
+ music?: string;
118
+ musicVolume?: number;
119
+ /** Apply the cinematic finish pass (vignette + film grain). */
120
+ finish?: boolean;
121
+ dryRun?: boolean;
122
+ }
123
+ export interface FootageAssembleReport {
124
+ schemaVersion: "1";
125
+ kind: "footage-assemble";
126
+ project: string;
127
+ output: string;
128
+ totalDurationSec: number;
129
+ transitionSec: number;
130
+ fadeSec: number;
131
+ beats: Array<FootageBeatPlan & {
132
+ /** The visual source file (generated clip, or keyframe still on fallback). */
133
+ clip: string;
134
+ /** How the segment was produced. */
135
+ source: "clip" | "keyframe-kenburns";
136
+ narration?: string;
137
+ }>;
138
+ music: {
139
+ path: string;
140
+ source: "flag" | "auto";
141
+ volume: number;
142
+ ducked: boolean;
143
+ } | null;
144
+ /** The finish filters applied before the fades, or null when skipped. */
145
+ finish: {
146
+ filters: string[];
147
+ } | null;
148
+ warnings: string[];
149
+ nextActions: ReviewAction[];
150
+ }
151
+ export interface FootageAssembleResult {
152
+ success: boolean;
153
+ dryRun: boolean;
154
+ outputPath: string;
155
+ reportPath?: string;
156
+ report?: FootageAssembleReport;
157
+ error?: string;
158
+ suggestion?: string;
159
+ }
160
+ /**
161
+ * Assemble a scene project's generated clips into the footage cut. Probes real
162
+ * durations, plans the timeline, runs one FFmpeg pass, and writes
163
+ * `assemble-report.json` so the driving agent can read the cut's anatomy
164
+ * (offsets, extensions, clamps) without watching the video.
165
+ */
166
+ export declare function executeFootageAssemble(opts: FootageAssembleOptions): Promise<FootageAssembleResult>;
@@ -0,0 +1 @@
1
+ export {};
@@ -14,7 +14,7 @@
14
14
  *
15
15
  * See issue #58.
16
16
  */
17
- import type { ImageResult } from "@vibeframe/ai-providers";
17
+ import type { GPTImageModel, ImageResult } from "@vibeframe/ai-providers";
18
18
  /** Subset of CLI options consumed by the helper. */
19
19
  export interface OpenAIImageHelperOptions {
20
20
  model?: string;
@@ -27,18 +27,18 @@ export interface OpenAIImageHelperOptions {
27
27
  export interface OpenAIImageHelperResult {
28
28
  result: ImageResult;
29
29
  /** Resolved model id passed to the API. */
30
- openaiModel: "gpt-image-2" | "gpt-image-1.5";
30
+ openaiModel: GPTImageModel;
31
31
  /** Human-friendly label for spinner / success output. */
32
- modelLabel: "GPT Image 2" | "GPT Image 1.5";
32
+ modelLabel: string;
33
33
  }
34
34
  /**
35
35
  * Resolve the user-supplied model alias to the API id + display label.
36
- * Exported so unit tests can assert label↔model parity (regression cover
37
- * for v0.52.0 bug).
36
+ * Unknown or empty aliases resolve to the default model. Exported so unit
37
+ * tests can assert label↔model parity (regression cover for v0.52.0 bug).
38
38
  */
39
39
  export declare function resolveOpenAIImageModel(modelAlias?: string): {
40
- openaiModel: "gpt-image-2" | "gpt-image-1.5";
41
- modelLabel: "GPT Image 2" | "GPT Image 1.5";
40
+ openaiModel: GPTImageModel;
41
+ modelLabel: string;
42
42
  };
43
43
  /**
44
44
  * Run an OpenAI image generation. Caller owns: api-key acquisition,
@@ -1,9 +1,10 @@
1
1
  import type { SceneAspect, SceneKind } from "./scene-project.js";
2
+ import type { BuildVideoProvider } from "./build-video-providers.js";
2
3
  export declare const VIBE_CONFIG_FILENAME = "vibe.config.json";
3
4
  export declare const LEGACY_VIBE_PROJECT_FILENAME = "vibe.project.yaml";
4
5
  export type CompositionEngine = "hyperframes";
5
6
  export type ProjectImageProvider = "openai" | "gemini" | "grok" | null;
6
- export type ProjectVideoProvider = "seedance" | "grok" | "kling" | "runway" | "veo" | null;
7
+ export type ProjectVideoProvider = BuildVideoProvider | null;
7
8
  export type ProjectNarrationProvider = "elevenlabs" | "openai" | "kokoro" | null;
8
9
  export type ProjectComposerProvider = "claude" | "openai" | "gemini" | null;
9
10
  export type ProjectQuality = "draft" | "standard" | "high";
@@ -19,6 +19,7 @@
19
19
  * already have one with sub-composition references.
20
20
  */
21
21
  import { type ImageOptions } from "@vibeframe/ai-providers";
22
+ import { type FootageAssembleReport } from "./footage-assemble.js";
22
23
  import type { ComposerProvider } from "./composer-resolve.js";
23
24
  import { type ComposePromptsBeat } from "./compose-prompts.js";
24
25
  import { type SceneRenderResult } from "./scene-render.js";
@@ -28,6 +29,7 @@ import { type JobRecord } from "./status-jobs.js";
28
29
  import { type SceneRepairResult } from "./scene-repair.js";
29
30
  import { type TtsProviderName } from "./tts-resolve.js";
30
31
  import { type SceneBuildMode } from "./scene-build-mode.js";
32
+ import { type BuildVideoProvider } from "./build-video-providers.js";
31
33
  export { resolveSceneBuildMode, type SceneBuildMode } from "./scene-build-mode.js";
32
34
  export type BuildImageProvider = "openai" | "gemini" | "grok";
33
35
  export type SceneBuildProgressEvent = {
@@ -128,6 +130,12 @@ export type SceneBuildProgressEvent = {
128
130
  type: "video-failed";
129
131
  beatId: string;
130
132
  error: string;
133
+ } | {
134
+ type: "video-fallback";
135
+ beatId: string;
136
+ from: string;
137
+ to: string;
138
+ reason: string;
131
139
  } | {
132
140
  type: "video-skipped";
133
141
  beatId: string;
@@ -213,7 +221,7 @@ export interface BeatBuildOutcome {
213
221
  musicSourcePath?: string;
214
222
  musicDurationSec?: number;
215
223
  }
216
- export type BuildVideoProvider = "seedance" | "grok" | "kling" | "runway" | "veo";
224
+ export type { BuildVideoProvider } from "./build-video-providers.js";
217
225
  export type BuildMusicProvider = "elevenlabs" | "replicate";
218
226
  /**
219
227
  * Build mode dispatch (Phase H3 / Plan H).
@@ -244,7 +252,7 @@ export interface SceneBuildOptions {
244
252
  * based on env keys (claude > gemini > openai). Pass an explicit value
245
253
  * to require that provider's key.
246
254
  */
247
- composer?: ComposerProvider | "template";
255
+ composer?: ComposerProvider | "template" | "footage";
248
256
  skipNarration?: boolean;
249
257
  skipBackdrop?: boolean;
250
258
  skipRender?: boolean;
@@ -271,6 +279,12 @@ export interface SceneBuildOptions {
271
279
  * kinetic-type reveals to speech. Pass true to opt out (no transcribe cost).
272
280
  */
273
281
  skipTranscript?: boolean;
282
+ /**
283
+ * Provider-specific image model for backdrops/keyframes/character sheets
284
+ * (e.g. gemini `flash` | `pro`, openai `gpt-image-2.5-sunburst`). Provider default when
285
+ * omitted; grok has a single model and ignores it.
286
+ */
287
+ imageModel?: string;
274
288
  /** OpenAI image quality — see `vibe generate image --quality`. */
275
289
  imageQuality?: "standard" | "hd";
276
290
  /** OpenAI image size. Default 1536x1024 for cinematic 16:9-ish framing. */
@@ -341,6 +355,12 @@ export interface SceneBuildResult {
341
355
  /** MP4 path when `skipRender` is false and render succeeded. */
342
356
  outputPath?: string;
343
357
  renderResult?: SceneRenderResult;
358
+ /**
359
+ * The footage composer's cut anatomy (offsets, extensions, clamps) — also
360
+ * persisted as `assemble-report.json`. Present only when
361
+ * `composer === "footage"` reached the render phase.
362
+ */
363
+ footageReport?: FootageAssembleReport;
344
364
  /**
345
365
  * Populated only in agent mode when {@link phase} === `"needs-author"`.
346
366
  * The host agent should consume this to write each beat's HTML, then
@@ -372,6 +392,12 @@ export interface SceneBuildResult {
372
392
  totalLatencyMs: number;
373
393
  }
374
394
  export declare function executeSceneBuild(opts: SceneBuildOptions): Promise<SceneBuildResult>;
395
+ /**
396
+ * ByteDance's platform-wide moderation rejects i2v inputs showing a
397
+ * recognizable face with a deterministic 422 ("likenesses of real people") —
398
+ * it applies to AI-generated photoreal faces too, and retrying never helps.
399
+ */
400
+ export declare function isLikenessRejection(error: string | undefined): boolean;
375
401
  export type BuildReport = ReturnType<typeof toBuildReport>;
376
402
  declare function toBuildReport(projectDir: string, result: SceneBuildResult): {
377
403
  schemaVersion: string;
@@ -104,7 +104,7 @@ export declare function resolveCharacters(frontmatter: ProjectFrontmatter | unde
104
104
  * rather than restating it - four surfaces had drifted to four different
105
105
  * sub-lists before this became the one list.
106
106
  */
107
- export declare const STORYBOARD_CUE_KEYS: readonly ["duration", "narration", "backdrop", "video", "keyframe", "motion", "voice", "music", "asset", "characters", "eyebrow", "title", "caption", "kicker", "sub"];
107
+ export declare const STORYBOARD_CUE_KEYS: readonly ["duration", "narration", "backdrop", "video", "keyframe", "provider", "motion", "voice", "music", "asset", "characters", "eyebrow", "title", "caption", "kicker", "sub"];
108
108
  export type StoryboardCueKey = (typeof STORYBOARD_CUE_KEYS)[number];
109
109
  /**
110
110
  * Per-beat cues extracted from the first ```yaml fenced block inside a beat
@@ -138,6 +138,12 @@ export interface BeatCues {
138
138
  * and shapes the HTML that agent writes.
139
139
  */
140
140
  motion?: string;
141
+ /**
142
+ * Video-provider override for this beat (seedance|runway|kling|veo|grok).
143
+ * Use to pin a face-visible keyframe to a provider that accepts it (e.g.
144
+ * `provider: runway` — Seedance's likeness filter rejects face i2v inputs).
145
+ */
146
+ provider?: string;
141
147
  /** Voice override for this beat (overrides project frontmatter `voice`). */
142
148
  voice?: string;
143
149
  /** Music prompt or a project-relative path to an existing track. */
@@ -28,6 +28,8 @@ export interface VideoGenerateOptions {
28
28
  veoModel?: string;
29
29
  runwayModel?: string;
30
30
  seedanceModel?: string;
31
+ grokModel?: string;
32
+ klingModel?: string;
31
33
  generateAudio?: boolean;
32
34
  output?: string;
33
35
  wait?: boolean;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @module generate/image
3
3
  * @description `vibe generate image` (alias `img`) — multi-provider image
4
- * generation. OpenAI gpt-image-2, Gemini Nano Banana, Grok, Runway. Split
4
+ * generation. OpenAI gpt-image-2.5, Gemini Nano Banana, Grok, Runway. Split
5
5
  * out of `generate.ts` in v0.69 (Plan G Phase 2).
6
6
  */
7
7
  import type { Command } from "commander";
@@ -2,20 +2,11 @@
2
2
  * @module generate/video
3
3
  * @description `vibe generate video` (alias `vid`) — multi-provider video
4
4
  * generation. fal.ai (Seedance 2.0), Grok, Veo (Gemini), Kling, Runway,
5
- * plus experimental Gemini Omni (`-p omni`).
5
+ * plus Gemini Omni 1.1 Flash (`-p omni`).
6
6
  * Split out of `generate.ts` in v0.69 (Plan G Phase 2).
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
- */
19
10
  export declare function realRunCost(provider: string, options: {
20
11
  duration?: string;
21
12
  resolution?: string;
@@ -33,7 +33,7 @@ export interface VibeConfig {
33
33
  /** Default provider for image generation */
34
34
  imageProvider?: "gemini" | "openai" | "grok";
35
35
  /** Default provider for video generation. `fal` is a deprecated v0.x alias for `seedance` and will be removed at 1.0. */
36
- videoProvider?: "seedance" | "fal" | "grok" | "kling" | "runway" | "veo";
36
+ videoProvider?: "seedance" | "fal" | "grok" | "kling" | "runway" | "omni" | "veo";
37
37
  /** Default provider for storyboard analysis */
38
38
  storyboardProvider?: "claude" | "openai" | "gemini";
39
39
  /** Default voice for TTS */