@vibeframe/cli 0.109.1 → 0.110.0

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/dist/index.js CHANGED
@@ -29613,6 +29613,7 @@ function isComposerProvider(value) {
29613
29613
  return value === "claude" || value === "openai" || value === "gemini";
29614
29614
  }
29615
29615
  function resolveComposer(explicit) {
29616
+ loadEnv();
29616
29617
  if (explicit) {
29617
29618
  const key = readKey(explicit);
29618
29619
  if (!key) {
@@ -29637,6 +29638,7 @@ var ENV_VAR, PROVIDER_LABEL, ComposerResolveError;
29637
29638
  var init_composer_resolve = __esm({
29638
29639
  "src/commands/_shared/composer-resolve.ts"() {
29639
29640
  "use strict";
29641
+ init_api_key();
29640
29642
  ENV_VAR = {
29641
29643
  claude: "ANTHROPIC_API_KEY",
29642
29644
  openai: "OPENAI_API_KEY",
@@ -67836,6 +67838,82 @@ var init_long_poll = __esm({
67836
67838
  }
67837
67839
  });
67838
67840
 
67841
+ // src/tools/_shared/elicit.ts
67842
+ function planBuildElicitation(args) {
67843
+ const assetsWillRun = args.stage === void 0 || args.stage === "all" || args.stage === "assets";
67844
+ if (!assetsWillRun) return null;
67845
+ const properties = {};
67846
+ const required = [];
67847
+ const narrationUndecided = !args.skipNarration && (args.ttsProvider === void 0 || args.ttsProvider === "auto");
67848
+ if (narrationUndecided) {
67849
+ properties.narration = {
67850
+ type: "string",
67851
+ title: "Narration voice-over",
67852
+ description: "Which TTS engine narrates the video?",
67853
+ enum: [...NARRATION_CHOICES],
67854
+ enumNames: [
67855
+ "Kokoro \u2014 free, runs locally on this machine",
67856
+ "ElevenLabs \u2014 cloud TTS, uses your ElevenLabs credits"
67857
+ ]
67858
+ };
67859
+ required.push("narration");
67860
+ }
67861
+ if (args.skipBackdrop === void 0 && args.imageProvider === void 0) {
67862
+ properties.backdrop_images = {
67863
+ type: "string",
67864
+ title: "Backdrop images",
67865
+ description: "Generate AI background images for each scene?",
67866
+ enum: [...BACKDROP_CHOICES],
67867
+ enumNames: [
67868
+ "Skip \u2014 free, pure typographic scenes",
67869
+ "OpenAI \u2014 paid image generation (roughly $1-3 per video)"
67870
+ ]
67871
+ };
67872
+ required.push("backdrop_images");
67873
+ }
67874
+ if (args.maxCostUsd === void 0) {
67875
+ properties.max_cost_usd = {
67876
+ type: "number",
67877
+ title: "Max provider spend (USD)",
67878
+ description: "Abort before any paid provider call when the estimate exceeds this cap. Leave empty for no cap.",
67879
+ minimum: 0
67880
+ };
67881
+ }
67882
+ if (Object.keys(properties).length === 0) return null;
67883
+ return {
67884
+ message: "VibeFrame is about to build this video. Choose how the assets are generated:",
67885
+ requestedSchema: { type: "object", properties, required }
67886
+ };
67887
+ }
67888
+ function applyElicitationAnswers(args, content) {
67889
+ if (!content) return args;
67890
+ const next = { ...args };
67891
+ const narration = content.narration;
67892
+ if (typeof narration === "string" && NARRATION_CHOICES.includes(narration)) {
67893
+ next.ttsProvider = narration;
67894
+ }
67895
+ const backdrop = content.backdrop_images;
67896
+ if (backdrop === "skip") {
67897
+ next.skipBackdrop = true;
67898
+ } else if (backdrop === "openai") {
67899
+ next.skipBackdrop = false;
67900
+ next.imageProvider = "openai";
67901
+ }
67902
+ const cap = content.max_cost_usd;
67903
+ if (typeof cap === "number" && Number.isFinite(cap) && cap >= 0) {
67904
+ next.maxCostUsd = cap;
67905
+ }
67906
+ return next;
67907
+ }
67908
+ var NARRATION_CHOICES, BACKDROP_CHOICES;
67909
+ var init_elicit = __esm({
67910
+ "src/tools/_shared/elicit.ts"() {
67911
+ "use strict";
67912
+ NARRATION_CHOICES = ["kokoro", "elevenlabs"];
67913
+ BACKDROP_CHOICES = ["skip", "openai"];
67914
+ }
67915
+ });
67916
+
67839
67917
  // src/tools/manifest/scene.ts
67840
67918
  import { resolve as resolve75, relative as relative12 } from "node:path";
67841
67919
  function summariseLint(result) {
@@ -67974,6 +68052,7 @@ var init_scene2 = __esm({
67974
68052
  init_zod();
67975
68053
  init_define_tool();
67976
68054
  init_long_poll();
68055
+ init_elicit();
67977
68056
  init_visual_styles();
67978
68057
  init_scene_project();
67979
68058
  init_scene();
@@ -68307,9 +68386,32 @@ var init_scene2 = __esm({
68307
68386
  name: "build",
68308
68387
  category: "scene",
68309
68388
  cost: "high",
68310
- description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken.",
68389
+ description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken. When the MCP host supports elicitation, unspecified asset choices (narration provider, backdrop images, cost cap) are confirmed with the user via a form before the build starts.",
68311
68390
  schema: sceneBuildSchema,
68312
68391
  async execute(args, ctx) {
68392
+ let warnings;
68393
+ if (ctx.surface === "mcp" && ctx.elicit) {
68394
+ const form = planBuildElicitation(args);
68395
+ if (form) {
68396
+ const outcome = await ctx.elicit(form).catch(() => null);
68397
+ if (outcome === null) {
68398
+ warnings = ["Asset-choice elicitation failed or timed out; proceeding with defaults."];
68399
+ } else if (outcome.action === "accept") {
68400
+ args = applyElicitationAnswers(args, outcome.content);
68401
+ } else {
68402
+ return {
68403
+ success: false,
68404
+ error: "Build cancelled \u2014 the user declined the asset choices.",
68405
+ data: {
68406
+ cancelled: true,
68407
+ retryWith: [
68408
+ `build { projectDir: "${args.projectDir ?? "."}", ttsProvider: "kokoro", skipBackdrop: true }`
68409
+ ]
68410
+ }
68411
+ };
68412
+ }
68413
+ }
68414
+ }
68313
68415
  const projectDir = args.projectDir ? resolve75(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
68314
68416
  const runBuild = (report) => executeSceneBuild({
68315
68417
  projectDir,
@@ -68337,7 +68439,9 @@ var init_scene2 = __esm({
68337
68439
  ctx.onProgress?.({ message: update.message ?? update.stage });
68338
68440
  report(update);
68339
68441
  }
68340
- }).then(mapBuildResultToToolResult);
68442
+ }).then(mapBuildResultToToolResult).then(
68443
+ (result) => warnings === void 0 ? result : { ...result, data: { ...result.data, elicitationWarnings: warnings } }
68444
+ );
68341
68445
  if (ctx.surface !== "mcp") {
68342
68446
  return runBuild(() => void 0);
68343
68447
  }
@@ -72909,7 +73013,7 @@ init_source();
72909
73013
  // package.json
72910
73014
  var package_default = {
72911
73015
  name: "@vibeframe/cli",
72912
- version: "0.109.1",
73016
+ version: "0.110.0",
72913
73017
  description: "VibeFrame CLI - agentic video workflow runtime",
72914
73018
  private: false,
72915
73019
  license: "MIT",
@@ -0,0 +1,31 @@
1
+ import type { ElicitForm } from "../adapters/mcp.js";
2
+ /**
3
+ * @module tools/_shared/elicit
4
+ *
5
+ * Pre-flight elicitation for the `build` tool: when an MCP client supports
6
+ * elicitation, ask the user the choices the host agent would otherwise pick
7
+ * silently (narration provider, paid backdrop generation, cost ceiling).
8
+ * Pure functions — the MCP wiring lives in the tool's execute and the
9
+ * server's makeElicitFn; CLI/Agent surfaces never reach this code path.
10
+ */
11
+ /** The subset of build args that drive the question set. */
12
+ export interface BuildChoiceArgs {
13
+ stage?: "assets" | "compose" | "sync" | "render" | "all";
14
+ ttsProvider?: "auto" | "elevenlabs" | "kokoro";
15
+ skipNarration?: boolean;
16
+ skipBackdrop?: boolean;
17
+ imageProvider?: string;
18
+ maxCostUsd?: number;
19
+ }
20
+ /**
21
+ * Builds the elicitation form for a build call, asking ONLY about choices the
22
+ * caller left unspecified. Returns null when there is nothing to ask — every
23
+ * choice explicit, or the requested stage doesn't generate assets.
24
+ */
25
+ export declare function planBuildElicitation(args: BuildChoiceArgs): ElicitForm | null;
26
+ /**
27
+ * Maps accepted form answers back onto build args. Unknown or invalid values
28
+ * are ignored so a misbehaving client can never produce a worse state than
29
+ * the defaults the user would have gotten without elicitation.
30
+ */
31
+ export declare function applyElicitationAnswers<T extends BuildChoiceArgs>(args: T, content: Record<string, string | number | boolean | string[]> | undefined): T;
@@ -0,0 +1 @@
1
+ export {};
@@ -22,6 +22,25 @@ export interface McpTool {
22
22
  description: string;
23
23
  inputSchema: McpInputSchema;
24
24
  }
25
+ /**
26
+ * Structural mirror of the MCP elicitation form request/result (the CLI
27
+ * package deliberately has no dependency on @modelcontextprotocol/sdk).
28
+ * `requestedSchema.properties` values follow the spec's flat primitive
29
+ * schema: string (optionally with enum/enumNames), number, boolean.
30
+ */
31
+ export interface ElicitForm {
32
+ message: string;
33
+ requestedSchema: {
34
+ type: "object";
35
+ properties: Record<string, unknown>;
36
+ required?: string[];
37
+ };
38
+ }
39
+ export interface ElicitOutcome {
40
+ action: "accept" | "decline" | "cancel";
41
+ content?: Record<string, string | number | boolean | string[]>;
42
+ }
43
+ export type ElicitFn = (form: ElicitForm) => Promise<ElicitOutcome>;
25
44
  /** Per-call extras forwarded by the MCP server request handler. */
26
45
  export interface McpCallExtra {
27
46
  /**
@@ -34,6 +53,12 @@ export interface McpCallExtra {
34
53
  total?: number;
35
54
  message?: string;
36
55
  }) => void;
56
+ /**
57
+ * Sends an `elicitation/create` form to the client and resolves with the
58
+ * user's answer. Only present when the connected client advertises the
59
+ * elicitation capability.
60
+ */
61
+ elicit?: ElicitFn;
37
62
  }
38
63
  export type McpDispatcher = (name: string, args: Record<string, unknown>, extra?: McpCallExtra) => Promise<{
39
64
  content: Array<{
@@ -245,7 +245,8 @@ function buildMcpDispatcher(manifest) {
245
245
  () => tool.execute(parsed.data, {
246
246
  workingDirectory: process.cwd(),
247
247
  surface: "mcp",
248
- ...extra?.onProgress ? { onProgress: sink.send } : {}
248
+ ...extra?.onProgress ? { onProgress: sink.send } : {},
249
+ ...extra?.elicit ? { elicit: extra.elicit } : {}
249
250
  })
250
251
  );
251
252
  const text = result.success ? JSON.stringify({ success: true, ...result.data }) : result.data ? JSON.stringify({
@@ -49,6 +49,23 @@ export interface ExecuteContext {
49
49
  total?: number;
50
50
  message?: string;
51
51
  }) => void;
52
+ /**
53
+ * Optional MCP elicitation channel. Present only when the connected MCP
54
+ * client advertises the elicitation capability; CLI/Agent surfaces leave
55
+ * it undefined, so CLI behavior never changes. See adapters/mcp.ts for
56
+ * the structural types.
57
+ */
58
+ elicit?: (form: {
59
+ message: string;
60
+ requestedSchema: {
61
+ type: "object";
62
+ properties: Record<string, unknown>;
63
+ required?: string[];
64
+ };
65
+ }) => Promise<{
66
+ action: "accept" | "decline" | "cancel";
67
+ content?: Record<string, string | number | boolean | string[]>;
68
+ }>;
52
69
  }
53
70
  export interface ToolExecuteResult {
54
71
  success: boolean;
@@ -30319,6 +30319,7 @@ function isComposerProvider(value) {
30319
30319
  return value === "claude" || value === "openai" || value === "gemini";
30320
30320
  }
30321
30321
  function resolveComposer(explicit) {
30322
+ loadEnv();
30322
30323
  if (explicit) {
30323
30324
  const key = readKey(explicit);
30324
30325
  if (!key) {
@@ -30343,6 +30344,7 @@ var ENV_VAR, PROVIDER_LABEL, ComposerResolveError;
30343
30344
  var init_composer_resolve = __esm({
30344
30345
  "src/commands/_shared/composer-resolve.ts"() {
30345
30346
  "use strict";
30347
+ init_api_key();
30346
30348
  ENV_VAR = {
30347
30349
  claude: "ANTHROPIC_API_KEY",
30348
30350
  openai: "OPENAI_API_KEY",
@@ -51298,6 +51300,76 @@ function pickOutputPath(data) {
51298
51300
  return typeof candidate === "string" ? candidate : void 0;
51299
51301
  }
51300
51302
 
51303
+ // src/tools/_shared/elicit.ts
51304
+ var NARRATION_CHOICES = ["kokoro", "elevenlabs"];
51305
+ var BACKDROP_CHOICES = ["skip", "openai"];
51306
+ function planBuildElicitation(args) {
51307
+ const assetsWillRun = args.stage === void 0 || args.stage === "all" || args.stage === "assets";
51308
+ if (!assetsWillRun) return null;
51309
+ const properties = {};
51310
+ const required = [];
51311
+ const narrationUndecided = !args.skipNarration && (args.ttsProvider === void 0 || args.ttsProvider === "auto");
51312
+ if (narrationUndecided) {
51313
+ properties.narration = {
51314
+ type: "string",
51315
+ title: "Narration voice-over",
51316
+ description: "Which TTS engine narrates the video?",
51317
+ enum: [...NARRATION_CHOICES],
51318
+ enumNames: [
51319
+ "Kokoro \u2014 free, runs locally on this machine",
51320
+ "ElevenLabs \u2014 cloud TTS, uses your ElevenLabs credits"
51321
+ ]
51322
+ };
51323
+ required.push("narration");
51324
+ }
51325
+ if (args.skipBackdrop === void 0 && args.imageProvider === void 0) {
51326
+ properties.backdrop_images = {
51327
+ type: "string",
51328
+ title: "Backdrop images",
51329
+ description: "Generate AI background images for each scene?",
51330
+ enum: [...BACKDROP_CHOICES],
51331
+ enumNames: [
51332
+ "Skip \u2014 free, pure typographic scenes",
51333
+ "OpenAI \u2014 paid image generation (roughly $1-3 per video)"
51334
+ ]
51335
+ };
51336
+ required.push("backdrop_images");
51337
+ }
51338
+ if (args.maxCostUsd === void 0) {
51339
+ properties.max_cost_usd = {
51340
+ type: "number",
51341
+ title: "Max provider spend (USD)",
51342
+ description: "Abort before any paid provider call when the estimate exceeds this cap. Leave empty for no cap.",
51343
+ minimum: 0
51344
+ };
51345
+ }
51346
+ if (Object.keys(properties).length === 0) return null;
51347
+ return {
51348
+ message: "VibeFrame is about to build this video. Choose how the assets are generated:",
51349
+ requestedSchema: { type: "object", properties, required }
51350
+ };
51351
+ }
51352
+ function applyElicitationAnswers(args, content) {
51353
+ if (!content) return args;
51354
+ const next = { ...args };
51355
+ const narration = content.narration;
51356
+ if (typeof narration === "string" && NARRATION_CHOICES.includes(narration)) {
51357
+ next.ttsProvider = narration;
51358
+ }
51359
+ const backdrop = content.backdrop_images;
51360
+ if (backdrop === "skip") {
51361
+ next.skipBackdrop = true;
51362
+ } else if (backdrop === "openai") {
51363
+ next.skipBackdrop = false;
51364
+ next.imageProvider = "openai";
51365
+ }
51366
+ const cap = content.max_cost_usd;
51367
+ if (typeof cap === "number" && Number.isFinite(cap) && cap >= 0) {
51368
+ next.maxCostUsd = cap;
51369
+ }
51370
+ return next;
51371
+ }
51372
+
51301
51373
  // src/commands/_shared/visual-styles.ts
51302
51374
  var STYLES = [
51303
51375
  {
@@ -53536,9 +53608,32 @@ var sceneBuildTool = defineTool({
53536
53608
  name: "build",
53537
53609
  category: "scene",
53538
53610
  cost: "high",
53539
- description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken.",
53611
+ description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap. Long runs: over MCP, calls exceeding ~45s return immediately with { promoted: true, jobId, status: 'running' } \u2014 poll status_job every 15-30s until completed/failed instead of re-invoking build. Emits MCP progress notifications when the client supplies a progressToken. When the MCP host supports elicitation, unspecified asset choices (narration provider, backdrop images, cost cap) are confirmed with the user via a form before the build starts.",
53540
53612
  schema: sceneBuildSchema,
53541
53613
  async execute(args, ctx) {
53614
+ let warnings;
53615
+ if (ctx.surface === "mcp" && ctx.elicit) {
53616
+ const form = planBuildElicitation(args);
53617
+ if (form) {
53618
+ const outcome = await ctx.elicit(form).catch(() => null);
53619
+ if (outcome === null) {
53620
+ warnings = ["Asset-choice elicitation failed or timed out; proceeding with defaults."];
53621
+ } else if (outcome.action === "accept") {
53622
+ args = applyElicitationAnswers(args, outcome.content);
53623
+ } else {
53624
+ return {
53625
+ success: false,
53626
+ error: "Build cancelled \u2014 the user declined the asset choices.",
53627
+ data: {
53628
+ cancelled: true,
53629
+ retryWith: [
53630
+ `build { projectDir: "${args.projectDir ?? "."}", ttsProvider: "kokoro", skipBackdrop: true }`
53631
+ ]
53632
+ }
53633
+ };
53634
+ }
53635
+ }
53636
+ }
53542
53637
  const projectDir = args.projectDir ? resolve26(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
53543
53638
  const runBuild = (report) => executeSceneBuild({
53544
53639
  projectDir,
@@ -53566,7 +53661,9 @@ var sceneBuildTool = defineTool({
53566
53661
  ctx.onProgress?.({ message: update.message ?? update.stage });
53567
53662
  report(update);
53568
53663
  }
53569
- }).then(mapBuildResultToToolResult);
53664
+ }).then(mapBuildResultToToolResult).then(
53665
+ (result) => warnings === void 0 ? result : { ...result, data: { ...result.data, elicitationWarnings: warnings } }
53666
+ );
53570
53667
  if (ctx.surface !== "mcp") {
53571
53668
  return runBuild(() => void 0);
53572
53669
  }
@@ -167,9 +167,9 @@ export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<
167
167
  skipBackdrop?: boolean | undefined;
168
168
  skipRender?: boolean | undefined;
169
169
  imageProvider?: "openai" | undefined;
170
+ ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
170
171
  skipVideo?: boolean | undefined;
171
172
  skipMusic?: boolean | undefined;
172
- ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
173
173
  videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
174
174
  musicProvider?: "elevenlabs" | "replicate" | undefined;
175
175
  imageQuality?: "standard" | "hd" | undefined;
@@ -188,9 +188,9 @@ export declare const sceneBuildTool: import("../define-tool.js").ToolDefinition<
188
188
  skipBackdrop?: boolean | undefined;
189
189
  skipRender?: boolean | undefined;
190
190
  imageProvider?: "openai" | undefined;
191
+ ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
191
192
  skipVideo?: boolean | undefined;
192
193
  skipMusic?: boolean | undefined;
193
- ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
194
194
  videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
195
195
  musicProvider?: "elevenlabs" | "replicate" | undefined;
196
196
  imageQuality?: "standard" | "hd" | undefined;
@@ -107,9 +107,9 @@ export declare const planTool: import("../define-tool.js").ToolDefinition<z.ZodO
107
107
  skipNarration?: boolean | undefined;
108
108
  skipBackdrop?: boolean | undefined;
109
109
  imageProvider?: string | undefined;
110
+ ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
110
111
  skipVideo?: boolean | undefined;
111
112
  skipMusic?: boolean | undefined;
112
- ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
113
113
  videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
114
114
  musicProvider?: "elevenlabs" | "replicate" | undefined;
115
115
  imageQuality?: "standard" | "hd" | undefined;
@@ -125,9 +125,9 @@ export declare const planTool: import("../define-tool.js").ToolDefinition<z.ZodO
125
125
  skipNarration?: boolean | undefined;
126
126
  skipBackdrop?: boolean | undefined;
127
127
  imageProvider?: string | undefined;
128
+ ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
128
129
  skipVideo?: boolean | undefined;
129
130
  skipMusic?: boolean | undefined;
130
- ttsProvider?: "elevenlabs" | "auto" | "kokoro" | undefined;
131
131
  videoProvider?: "grok" | "seedance" | "kling" | "runway" | "veo" | undefined;
132
132
  musicProvider?: "elevenlabs" | "replicate" | undefined;
133
133
  imageQuality?: "standard" | "hd" | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/cli",
3
- "version": "0.109.1",
3
+ "version": "0.110.0",
4
4
  "description": "VibeFrame CLI - agentic video workflow runtime",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -83,8 +83,8 @@
83
83
  "tsx": "^4.21.0",
84
84
  "typescript": "^5.3.3",
85
85
  "vitest": "^1.2.2",
86
- "@vibeframe/ai-providers": "0.109.1",
87
- "@vibeframe/core": "0.109.1"
86
+ "@vibeframe/ai-providers": "0.110.0",
87
+ "@vibeframe/core": "0.110.0"
88
88
  },
89
89
  "engines": {
90
90
  "node": ">=20"