@vibeframe/mcp-server 0.113.3 → 0.113.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +57 -32
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -472894,6 +472894,14 @@ async function createBuildPlan(opts) {
472894
472894
  duration: beat.duration,
472895
472895
  keyframe: keyframePrompt
472896
472896
  }) : null;
472897
+ const keyframeCache2 = keyframePrompt ? keyframeCacheDescriptor({
472898
+ beatId: beat.id,
472899
+ cue: keyframePrompt,
472900
+ provider: resolved.image.resolved,
472901
+ quality: imageQuality,
472902
+ size: imageSize2,
472903
+ ratio: imageRatio
472904
+ }) : null;
472897
472905
  const musicCache = musicPrompt && !musicReference ? musicCacheDescriptor({
472898
472906
  beatId: beat.id,
472899
472907
  cue: musicPrompt,
@@ -472929,6 +472937,19 @@ async function createBuildPlan(opts) {
472929
472937
  cost: backdropCostUsd(imageQuality),
472930
472938
  active: includeAssets
472931
472939
  }) : null;
472940
+ const keyframe = keyframePrompt && !opts.skipKeyframe ? assetPlan({
472941
+ kind: "keyframe",
472942
+ beatId: beat.id,
472943
+ cue: keyframePrompt,
472944
+ provider: resolved.image.resolved,
472945
+ path: `assets/keyframe-${beat.id}.png`,
472946
+ cache: keyframeCache2,
472947
+ reference: null,
472948
+ projectDir,
472949
+ force: opts.force,
472950
+ cost: backdropCostUsd(imageQuality),
472951
+ active: includeAssets
472952
+ }) : null;
472932
472953
  const video = videoCue && !opts.skipVideo ? assetPlan({
472933
472954
  kind: "video",
472934
472955
  beatId: beat.id,
@@ -472961,7 +472982,7 @@ async function createBuildPlan(opts) {
472961
472982
  }) : null;
472962
472983
  const compositionPath = `compositions/scene-${beat.id}.html`;
472963
472984
  const compositionExists = existsSync33(join30(projectDir, compositionPath));
472964
- for (const asset of [narration, backdrop, video, music]) {
472985
+ for (const asset of [narration, backdrop, keyframe, video, music]) {
472965
472986
  if (!asset) continue;
472966
472987
  if (asset.referenceError) {
472967
472988
  missing.add("assets");
@@ -472986,13 +473007,9 @@ async function createBuildPlan(opts) {
472986
473007
  if (narration?.willGenerate) noteProviderNeed(resolved.narration, "Narration");
472987
473008
  if (backdrop?.willGenerate && isSupportedBuildImageProvider(resolved.image.resolved))
472988
473009
  noteProviderNeed(resolved.image, "Backdrop generation");
473010
+ if (keyframe?.willGenerate && isSupportedBuildImageProvider(resolved.image.resolved))
473011
+ noteProviderNeed(resolved.image, "Keyframe generation");
472989
473012
  if (video?.willGenerate) noteProviderNeed(resolved.video, "Video generation");
472990
- if (keyframePrompt && video?.willGenerate) {
472991
- estimatedCostUsd += backdropCostUsd(imageQuality);
472992
- providers.add(resolved.image.resolved);
472993
- if (isSupportedBuildImageProvider(resolved.image.resolved))
472994
- noteProviderNeed(resolved.image, "Keyframe generation");
472995
- }
472996
473013
  if (music?.willGenerate) noteProviderNeed(resolved.music, "Music generation");
472997
473014
  if (!compositionExists) missing.add("compositions");
472998
473015
  if (includeCompose && !compositionExists && mode !== "agent") {
@@ -473005,7 +473022,7 @@ async function createBuildPlan(opts) {
473005
473022
  heading: beat.heading,
473006
473023
  durationSec: beat.duration ?? null,
473007
473024
  cues: cue,
473008
- assets: { narration, backdrop, video, music },
473025
+ assets: { narration, backdrop, keyframe, video, music },
473009
473026
  composition: {
473010
473027
  path: compositionPath,
473011
473028
  exists: compositionExists
@@ -473221,6 +473238,7 @@ function providerResolutionsForPlan(resolved, beats, opts, includeAssets) {
473221
473238
  return [
473222
473239
  includeAssets && !opts.skipNarration && needsProvider("narration") ? resolved.narration : null,
473223
473240
  includeAssets && !opts.skipBackdrop && needsProvider("backdrop") ? resolved.image : null,
473241
+ includeAssets && !opts.skipKeyframe && needsProvider("keyframe") ? resolved.image : null,
473224
473242
  includeAssets && !opts.skipVideo && needsProvider("video") ? resolved.video : null,
473225
473243
  includeAssets && !opts.skipMusic && needsProvider("music") ? resolved.music : null,
473226
473244
  resolved.composer ?? null
@@ -473795,6 +473813,7 @@ async function executeSceneBuild(opts) {
473795
473813
  skipNarration: opts.skipNarration,
473796
473814
  skipBackdrop: opts.skipBackdrop,
473797
473815
  skipVideo: opts.skipVideo,
473816
+ skipKeyframe: opts.skipKeyframe,
473798
473817
  skipMusic: opts.skipMusic,
473799
473818
  ttsProvider: opts.ttsProvider,
473800
473819
  voice: opts.voice,
@@ -473980,6 +473999,7 @@ async function executeSceneBuild(opts) {
473980
473999
  skipNarration: opts.skipNarration ?? false,
473981
474000
  skipBackdrop: opts.skipBackdrop ?? false,
473982
474001
  skipVideo: opts.skipVideo ?? false,
474002
+ skipKeyframe: opts.skipKeyframe ?? false,
473983
474003
  skipMusic: opts.skipMusic ?? false,
473984
474004
  force: opts.force ?? false,
473985
474005
  onProgress,
@@ -474356,10 +474376,11 @@ async function executeSceneBuild(opts) {
474356
474376
  });
474357
474377
  }
474358
474378
  async function buildBeatPrimitives(beat, ctx) {
474379
+ const keyframe = ctx.skipKeyframe ? await skipped("keyframe", beat.id, "--skip-keyframe", ctx) : await dispatchKeyframe(beat, ctx);
474359
474380
  const [narration, backdrop, video, music] = await Promise.all([
474360
474381
  ctx.skipNarration ? skipped("narration", beat.id, "--skip-narration", ctx) : dispatchNarration(beat, ctx),
474361
474382
  ctx.skipBackdrop ? skipped("backdrop", beat.id, "--skip-backdrop", ctx) : dispatchBackdrop(beat, ctx),
474362
- ctx.skipVideo ? skipped("video", beat.id, "--skip-video", ctx) : dispatchVideo(beat, ctx),
474383
+ ctx.skipVideo ? skipped("video", beat.id, "--skip-video", ctx) : dispatchVideo(beat, ctx, keyframe),
474363
474384
  ctx.skipMusic ? skipped("music", beat.id, "--skip-music", ctx) : dispatchMusic(beat, ctx)
474364
474385
  ]);
474365
474386
  return {
@@ -474403,8 +474424,8 @@ async function buildBeatPrimitives(beat, ctx) {
474403
474424
  videoMetadataPath: video.metadataPath,
474404
474425
  videoFreshness: video.freshness,
474405
474426
  videoSourcePath: video.sourcePath,
474406
- keyframeStatus: video.keyframeStatus,
474407
- keyframePath: video.keyframePath,
474427
+ keyframeStatus: keyframe.status,
474428
+ keyframePath: keyframe.path,
474408
474429
  musicStatus: music.status,
474409
474430
  musicPath: music.path,
474410
474431
  musicJobId: music.job?.id,
@@ -474975,7 +474996,21 @@ function imageProviderKeyInfo(provider) {
474975
474996
  if (provider === "grok") return { configKey: "xai", envVar: "XAI_API_KEY" };
474976
474997
  return { configKey: "openai", envVar: "OPENAI_API_KEY" };
474977
474998
  }
474978
- async function dispatchVideo(beat, ctx) {
474999
+ async function dispatchKeyframe(beat, ctx) {
475000
+ const keyframeCue = stringOrUndefined4(beat.cues?.keyframe);
475001
+ if (!keyframeCue) return { status: "no-cue" };
475002
+ const characterRefsRel = beatCharacterNames(beat.cues).map((name) => ctx.characterPaths?.get(name)).filter((p2) => typeof p2 === "string");
475003
+ const kf = await ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel);
475004
+ if (kf.status === "failed") {
475005
+ ctx.onProgress({ type: "keyframe-failed", beatId: beat.id, error: kf.error });
475006
+ return { status: "failed", error: kf.error };
475007
+ }
475008
+ ctx.onProgress(
475009
+ kf.status === "cached" ? { type: "keyframe-cached", beatId: beat.id, path: kf.rel } : { type: "keyframe-generated", beatId: beat.id, path: kf.rel, provider: ctx.imageProvider }
475010
+ );
475011
+ return { status: kf.status, path: kf.rel, provider: ctx.imageProvider };
475012
+ }
475013
+ async function dispatchVideo(beat, ctx, keyframe) {
474979
475014
  const reference = assetReferenceForBeat(ctx.projectDir, "video", beat);
474980
475015
  if (reference) return referencePrimitiveOutcome("video", beat, ctx, reference);
474981
475016
  const keyframeCue = stringOrUndefined4(beat.cues?.keyframe);
@@ -475045,20 +475080,14 @@ async function dispatchVideo(beat, ctx) {
475045
475080
  freshness: "fresh"
475046
475081
  };
475047
475082
  }
475048
- loadSceneBuildEnv(ctx.projectDir);
475049
- let keyframeStatus;
475050
- let keyframeRel;
475051
- let keyframeImageAbs;
475052
- if (keyframeCue) {
475053
- const kf = await ensureKeyframe(beat, ctx, keyframeCue, characterRefsRel);
475054
- if (kf.status === "failed") {
475055
- ctx.onProgress({ type: "video-failed", beatId: beat.id, error: kf.error });
475056
- return { status: "failed", error: kf.error };
475057
- }
475058
- keyframeStatus = kf.status;
475059
- keyframeRel = kf.rel;
475060
- keyframeImageAbs = join31(ctx.projectDir, kf.rel);
475083
+ const keyframeImageRel = keyframeCue && (keyframe.status === "generated" || keyframe.status === "cached") ? keyframe.path : void 0;
475084
+ if (keyframeCue && !keyframeImageRel) {
475085
+ const reason = keyframe.status === "failed" ? `keyframe unavailable: ${keyframe.error ?? "generation failed"}` : "keyframe not generated (build without --skip-keyframe first)";
475086
+ ctx.onProgress({ type: "video-skipped", beatId: beat.id, reason });
475087
+ return { status: "skipped" };
475061
475088
  }
475089
+ const keyframeImageAbs = keyframeImageRel ? join31(ctx.projectDir, keyframeImageRel) : void 0;
475090
+ loadSceneBuildEnv(ctx.projectDir);
475062
475091
  const result = await executeVideoGenerate({
475063
475092
  prompt: prompt3,
475064
475093
  provider: ctx.videoProvider,
@@ -475104,9 +475133,7 @@ async function dispatchVideo(beat, ctx) {
475104
475133
  cachePath: cache.path,
475105
475134
  cacheKey: cache.key,
475106
475135
  metadataPath,
475107
- freshness: "fresh",
475108
- keyframeStatus,
475109
- keyframePath: keyframeRel
475136
+ freshness: "fresh"
475110
475137
  };
475111
475138
  }
475112
475139
  const job = await createAndWriteJobRecord({
@@ -475138,9 +475165,7 @@ async function dispatchVideo(beat, ctx) {
475138
475165
  provider: job.provider,
475139
475166
  cachePath: cache.path,
475140
475167
  cacheKey: cache.key,
475141
- metadataPath,
475142
- keyframeStatus,
475143
- keyframePath: keyframeRel
475168
+ metadataPath
475144
475169
  };
475145
475170
  }
475146
475171
  async function dispatchMusic(beat, ctx) {
@@ -499699,7 +499724,7 @@ var server2 = new Server(
499699
499724
  {
499700
499725
  name: "vibeframe",
499701
499726
  // Stamped with the package version by build.js at bundle time.
499702
- version: "0.113.3"
499727
+ version: "0.113.4"
499703
499728
  },
499704
499729
  {
499705
499730
  capabilities: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/mcp-server",
3
- "version": "0.113.3",
3
+ "version": "0.113.4",
4
4
  "description": "VibeFrame MCP Server - AI-native video editing via Model Context Protocol",
5
5
  "type": "module",
6
6
  "bin": {
@@ -60,8 +60,8 @@
60
60
  "tsx": "^4.21.0",
61
61
  "typescript": "^5.3.3",
62
62
  "vitest": "^1.2.2",
63
- "@vibeframe/cli": "0.113.3",
64
- "@vibeframe/core": "0.113.3"
63
+ "@vibeframe/cli": "0.113.4",
64
+ "@vibeframe/core": "0.113.4"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">=20"