@vibeframe/mcp-server 0.102.0 → 0.103.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 +190 -56
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7643,9 +7643,14 @@ End on the product name, offer, or command. Avoid adding a new idea in the
|
|
|
7643
7643
|
final beat.
|
|
7644
7644
|
`;
|
|
7645
7645
|
}
|
|
7646
|
-
function
|
|
7646
|
+
function buildProjectAgentsMd(name) {
|
|
7647
7647
|
return `# ${name} \u2014 Scene Authoring Project
|
|
7648
7648
|
|
|
7649
|
+
This is the canonical cross-agent guidance file for this scene project.
|
|
7650
|
+
Claude Code imports it through \`CLAUDE.md\`; Codex, Cursor, Aider,
|
|
7651
|
+
Gemini CLI, OpenCode, and other bash-capable agents should read it
|
|
7652
|
+
directly.
|
|
7653
|
+
|
|
7649
7654
|
This project is **bilingual**: it works with both VibeFrame (\`vibe\`) and
|
|
7650
7655
|
HeyGen Hyperframes (\`hyperframes\`). You can run either CLI inside this
|
|
7651
7656
|
directory.
|
|
@@ -7685,6 +7690,8 @@ Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
|
|
|
7685
7690
|
|
|
7686
7691
|
## Skills \u2014 USE THESE FIRST
|
|
7687
7692
|
|
|
7693
|
+
@SKILL.md
|
|
7694
|
+
|
|
7688
7695
|
**Always invoke the relevant skill before authoring scenes.** Skills encode
|
|
7689
7696
|
framework-specific patterns (GSAP timeline registration, data-attribute
|
|
7690
7697
|
semantics, VibeFrame pipeline conventions) that are NOT in generic web docs.
|
|
@@ -7753,6 +7760,17 @@ vibe scene lint --json # structured output for agent loops
|
|
|
7753
7760
|
\`\`\`
|
|
7754
7761
|
`;
|
|
7755
7762
|
}
|
|
7763
|
+
function buildProjectClaudeMd(name) {
|
|
7764
|
+
return `@AGENTS.md
|
|
7765
|
+
|
|
7766
|
+
# ${name} \u2014 Claude Code Overrides
|
|
7767
|
+
|
|
7768
|
+
This file imports \`AGENTS.md\`; keep cross-agent VibeFrame and
|
|
7769
|
+
Hyperframes instructions there so Codex, Cursor, Aider, Gemini CLI, and
|
|
7770
|
+
OpenCode see the same project rules. Add Claude-Code-specific notes below
|
|
7771
|
+
only when this project needs them.
|
|
7772
|
+
`;
|
|
7773
|
+
}
|
|
7756
7774
|
function buildSceneGitignore() {
|
|
7757
7775
|
return `# VibeFrame \u2014 caches, checkpoints, and project-scope config.yaml (may contain API keys)
|
|
7758
7776
|
.vibeframe/
|
|
@@ -7792,6 +7810,7 @@ function describeSceneScaffold(opts) {
|
|
|
7792
7810
|
}
|
|
7793
7811
|
if (profile === "agent" || profile === "full") {
|
|
7794
7812
|
groups.agent = [
|
|
7813
|
+
resolve2(dir, "AGENTS.md"),
|
|
7795
7814
|
resolve2(dir, "SKILL.md"),
|
|
7796
7815
|
resolve2(dir, "references"),
|
|
7797
7816
|
resolve2(dir, "CLAUDE.md")
|
|
@@ -7871,9 +7890,24 @@ async function scaffoldSceneProject(opts) {
|
|
|
7871
7890
|
created.push(vibePath);
|
|
7872
7891
|
}
|
|
7873
7892
|
if (profile === "agent" || profile === "full") {
|
|
7893
|
+
const agentsPath = resolve2(dir, "AGENTS.md");
|
|
7894
|
+
if (await pathExists(agentsPath)) {
|
|
7895
|
+
skipped2.push(agentsPath);
|
|
7896
|
+
} else {
|
|
7897
|
+
await writeFile(agentsPath, buildProjectAgentsMd(name), "utf-8");
|
|
7898
|
+
created.push(agentsPath);
|
|
7899
|
+
}
|
|
7874
7900
|
const claudePath = resolve2(dir, "CLAUDE.md");
|
|
7875
7901
|
if (await pathExists(claudePath)) {
|
|
7876
|
-
|
|
7902
|
+
const existing = await readFile2(claudePath, "utf-8");
|
|
7903
|
+
if (existing.includes("@AGENTS.md")) {
|
|
7904
|
+
skipped2.push(claudePath);
|
|
7905
|
+
} else {
|
|
7906
|
+
await writeFile(claudePath, `@AGENTS.md
|
|
7907
|
+
|
|
7908
|
+
${existing}`, "utf-8");
|
|
7909
|
+
merged.push(claudePath);
|
|
7910
|
+
}
|
|
7877
7911
|
} else {
|
|
7878
7912
|
await writeFile(claudePath, buildProjectClaudeMd(name), "utf-8");
|
|
7879
7913
|
created.push(claudePath);
|
|
@@ -25606,6 +25640,7 @@ __export(config_exports, {
|
|
|
25606
25640
|
USER_CONFIG_DIR: () => USER_CONFIG_DIR,
|
|
25607
25641
|
USER_CONFIG_PATH: () => USER_CONFIG_PATH,
|
|
25608
25642
|
createDefaultConfig: () => createDefaultConfig,
|
|
25643
|
+
findProjectConfigPath: () => findProjectConfigPath,
|
|
25609
25644
|
getActiveScope: () => getActiveScope,
|
|
25610
25645
|
getApiKeyFromConfig: () => getApiKeyFromConfig,
|
|
25611
25646
|
getConfigDir: () => getConfigDir,
|
|
@@ -450988,9 +451023,22 @@ function backdropCacheDescriptor(opts) {
|
|
|
450988
451023
|
provider: opts.provider,
|
|
450989
451024
|
quality: opts.quality,
|
|
450990
451025
|
size: opts.size,
|
|
451026
|
+
ratio: opts.ratio,
|
|
450991
451027
|
ext: "png"
|
|
450992
451028
|
});
|
|
450993
451029
|
}
|
|
451030
|
+
function imageRatioForSize(size) {
|
|
451031
|
+
switch (size) {
|
|
451032
|
+
case "1024x1024":
|
|
451033
|
+
return "1:1";
|
|
451034
|
+
case "1024x1536":
|
|
451035
|
+
return "2:3";
|
|
451036
|
+
case "1536x1024":
|
|
451037
|
+
return "3:2";
|
|
451038
|
+
default:
|
|
451039
|
+
return "16:9";
|
|
451040
|
+
}
|
|
451041
|
+
}
|
|
450994
451042
|
function videoCacheDescriptor(opts) {
|
|
450995
451043
|
return cacheAssetDescriptor("video", {
|
|
450996
451044
|
beatId: opts.beatId,
|
|
@@ -451319,6 +451367,7 @@ async function createBuildPlan(opts) {
|
|
|
451319
451367
|
}
|
|
451320
451368
|
const storyboardMd = await readFile13(storyboardPath, "utf-8");
|
|
451321
451369
|
const validation3 = validateStoryboardMarkdown(storyboardMd);
|
|
451370
|
+
const validationIssues = [...validation3.issues];
|
|
451322
451371
|
const parsed = parseStoryboard(storyboardMd);
|
|
451323
451372
|
let sourceBeats = parsed.beats;
|
|
451324
451373
|
if (opts.beat) {
|
|
@@ -451341,6 +451390,7 @@ async function createBuildPlan(opts) {
|
|
|
451341
451390
|
const mode = opts.mode ?? config4.config.build.mode;
|
|
451342
451391
|
const imageQuality = opts.imageQuality ?? config4.config.build.imageQuality ?? "hd";
|
|
451343
451392
|
const imageSize2 = opts.imageSize ?? config4.config.build.imageSize ?? "1536x1024";
|
|
451393
|
+
const imageRatio = imageRatioForSize(imageSize2);
|
|
451344
451394
|
const needsComposer = includeCompose && mode !== "agent" && sourceBeats.some((beat) => !existsSync31(join30(projectDir, `compositions/scene-${beat.id}.html`)));
|
|
451345
451395
|
const resolved = await resolvePlanProviders({
|
|
451346
451396
|
projectDir,
|
|
@@ -451390,7 +451440,8 @@ async function createBuildPlan(opts) {
|
|
|
451390
451440
|
cue: backdropPrompt,
|
|
451391
451441
|
provider: resolved.image.resolved,
|
|
451392
451442
|
quality: imageQuality,
|
|
451393
|
-
size: imageSize2
|
|
451443
|
+
size: imageSize2,
|
|
451444
|
+
ratio: imageRatio
|
|
451394
451445
|
}) : null;
|
|
451395
451446
|
const videoCache = videoPrompt && !videoReference ? videoCacheDescriptor({
|
|
451396
451447
|
beatId: beat.id,
|
|
@@ -451484,7 +451535,8 @@ async function createBuildPlan(opts) {
|
|
|
451484
451535
|
}
|
|
451485
451536
|
}
|
|
451486
451537
|
if (narration?.willGenerate) noteProviderNeed(resolved.narration, "Narration");
|
|
451487
|
-
if (backdrop?.willGenerate
|
|
451538
|
+
if (backdrop?.willGenerate && isSupportedBuildImageProvider(resolved.image.resolved))
|
|
451539
|
+
noteProviderNeed(resolved.image, "Backdrop generation");
|
|
451488
451540
|
if (video?.willGenerate) noteProviderNeed(resolved.video, "Video generation");
|
|
451489
451541
|
if (music?.willGenerate) noteProviderNeed(resolved.music, "Music generation");
|
|
451490
451542
|
if (!compositionExists) missing.add("compositions");
|
|
@@ -451506,23 +451558,35 @@ async function createBuildPlan(opts) {
|
|
|
451506
451558
|
};
|
|
451507
451559
|
});
|
|
451508
451560
|
providerResolution.push(...providerResolutionsForPlan(resolved, beats, opts, includeAssets));
|
|
451561
|
+
if (includeAssets && !opts.skipBackdrop && !isSupportedBuildImageProvider(resolved.image.resolved)) {
|
|
451562
|
+
const unsupportedBackdropBeats = beats.filter(
|
|
451563
|
+
(beat) => isBuildGeneratedBackdropPlan(beat.assets.backdrop)
|
|
451564
|
+
);
|
|
451565
|
+
for (const beat of unsupportedBackdropBeats) {
|
|
451566
|
+
validationIssues.push({
|
|
451567
|
+
severity: "error",
|
|
451568
|
+
code: "UNSUPPORTED_BUILD_IMAGE_PROVIDER",
|
|
451569
|
+
beatId: beat.id,
|
|
451570
|
+
message: `Build backdrop generation supports openai, gemini, and grok. Beat "${beat.id}" resolves image provider "${resolved.image.resolved}"; rerun with one of those or replace the backdrop cue with a project asset path.`
|
|
451571
|
+
});
|
|
451572
|
+
}
|
|
451573
|
+
if (unsupportedBackdropBeats.length > 0) {
|
|
451574
|
+
const beatFlag = opts.beat ? ` --beat ${opts.beat}` : "";
|
|
451575
|
+
retryWith.push(
|
|
451576
|
+
`vibe build ${projectDir}${beatFlag} --stage assets --image-provider openai --json`
|
|
451577
|
+
);
|
|
451578
|
+
}
|
|
451579
|
+
}
|
|
451580
|
+
const validationOk = !validationIssues.some((issue) => issue.severity === "error");
|
|
451509
451581
|
if (!existsSync31(join30(projectDir, config4.config.composition.entry))) {
|
|
451510
451582
|
missing.add("root-composition");
|
|
451511
|
-
if (
|
|
451583
|
+
if (validationOk) retryWith.push(`vibe build ${projectDir} --stage sync --json`);
|
|
451512
451584
|
}
|
|
451513
451585
|
if (config4.legacy) {
|
|
451514
451586
|
warnings.push(
|
|
451515
451587
|
`Using legacy ${config4.source}; write ${projectDir}/vibe.config.json to use the TO-BE project contract.`
|
|
451516
451588
|
);
|
|
451517
451589
|
}
|
|
451518
|
-
if (resolved.image.resolved !== "openai" && beats.some((beat) => {
|
|
451519
|
-
const backdrop = beat.assets.backdrop;
|
|
451520
|
-
return backdrop && !["referenced-asset", "invalid-reference", "stage-skipped"].includes(backdrop.reason);
|
|
451521
|
-
}) && !opts.skipBackdrop) {
|
|
451522
|
-
warnings.push(
|
|
451523
|
-
`Image provider "${resolved.image.resolved}" is not supported by build assets yet; use --image-provider openai.`
|
|
451524
|
-
);
|
|
451525
|
-
}
|
|
451526
451590
|
if (!validation3.ok) {
|
|
451527
451591
|
retryWith.push(
|
|
451528
451592
|
`vibe storyboard validate ${projectDir} --json`,
|
|
@@ -451533,7 +451597,7 @@ async function createBuildPlan(opts) {
|
|
|
451533
451597
|
projectDir,
|
|
451534
451598
|
config: config4,
|
|
451535
451599
|
stage,
|
|
451536
|
-
status:
|
|
451600
|
+
status: validationOk ? "ready" : "invalid",
|
|
451537
451601
|
currentStage: stage,
|
|
451538
451602
|
mode,
|
|
451539
451603
|
beat: opts.beat ?? null,
|
|
@@ -451545,8 +451609,8 @@ async function createBuildPlan(opts) {
|
|
|
451545
451609
|
warnings,
|
|
451546
451610
|
retryWith,
|
|
451547
451611
|
validation: {
|
|
451548
|
-
ok:
|
|
451549
|
-
issues:
|
|
451612
|
+
ok: validationOk,
|
|
451613
|
+
issues: validationIssues
|
|
451550
451614
|
}
|
|
451551
451615
|
});
|
|
451552
451616
|
}
|
|
@@ -451573,6 +451637,15 @@ function finalizeBuildPlan(plan) {
|
|
|
451573
451637
|
retryWith: unique2(plan.retryWith)
|
|
451574
451638
|
};
|
|
451575
451639
|
}
|
|
451640
|
+
function isBuildGeneratedBackdropPlan(asset) {
|
|
451641
|
+
if (!asset || asset.kind !== "backdrop") return false;
|
|
451642
|
+
return !["referenced-asset", "invalid-reference", "stage-skipped"].includes(asset.reason);
|
|
451643
|
+
}
|
|
451644
|
+
function isSupportedBuildImageProvider(provider) {
|
|
451645
|
+
return SUPPORTED_BUILD_IMAGE_PROVIDERS.includes(
|
|
451646
|
+
provider
|
|
451647
|
+
);
|
|
451648
|
+
}
|
|
451576
451649
|
function nextCommandsForPlan(plan) {
|
|
451577
451650
|
if (plan.status === "invalid") return unique2(plan.retryWith);
|
|
451578
451651
|
const commands = [];
|
|
@@ -451872,7 +451945,7 @@ function loadPlanEnv(projectDir) {
|
|
|
451872
451945
|
dir = dirname18(dir);
|
|
451873
451946
|
}
|
|
451874
451947
|
}
|
|
451875
|
-
var import_dotenv2, BACKDROP_COST_USD, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, COMPOSE_COST_USD;
|
|
451948
|
+
var import_dotenv2, BACKDROP_COST_USD, VIDEO_COST_USD, MUSIC_COST_USD, ELEVENLABS_NARRATION_COST_USD, COMPOSE_COST_USD, SUPPORTED_BUILD_IMAGE_PROVIDERS;
|
|
451876
451949
|
var init_build_plan = __esm({
|
|
451877
451950
|
"../cli/src/commands/_shared/build-plan.ts"() {
|
|
451878
451951
|
"use strict";
|
|
@@ -451891,6 +451964,7 @@ var init_build_plan = __esm({
|
|
|
451891
451964
|
MUSIC_COST_USD = 0.5;
|
|
451892
451965
|
ELEVENLABS_NARRATION_COST_USD = 0.05;
|
|
451893
451966
|
COMPOSE_COST_USD = 0.06;
|
|
451967
|
+
SUPPORTED_BUILD_IMAGE_PROVIDERS = ["openai", "gemini", "grok"];
|
|
451894
451968
|
}
|
|
451895
451969
|
});
|
|
451896
451970
|
|
|
@@ -451916,22 +451990,35 @@ function applySuggestion(project, suggestion) {
|
|
|
451916
451990
|
if (clipIds.length === 0) return false;
|
|
451917
451991
|
const clipId = clipIds[0];
|
|
451918
451992
|
switch (type) {
|
|
451919
|
-
case "trim":
|
|
451920
|
-
|
|
451921
|
-
|
|
451993
|
+
case "trim": {
|
|
451994
|
+
const newDuration = params.newDuration;
|
|
451995
|
+
if (typeof newDuration === "number") {
|
|
451996
|
+
return project.trimClipEnd(clipId, newDuration);
|
|
451922
451997
|
}
|
|
451923
451998
|
break;
|
|
451924
|
-
|
|
451925
|
-
|
|
451999
|
+
}
|
|
452000
|
+
case "add-effect": {
|
|
452001
|
+
const effectType = params.effectType;
|
|
452002
|
+
if (typeof effectType === "string") {
|
|
452003
|
+
const startTime = typeof params.startTime === "number" ? params.startTime : 0;
|
|
452004
|
+
const duration = typeof params.duration === "number" ? params.duration : 1;
|
|
452005
|
+
const rawEffectParams = params.effectParams && typeof params.effectParams === "object" ? params.effectParams : {};
|
|
452006
|
+
const effectParams = {};
|
|
452007
|
+
for (const [k, v] of Object.entries(rawEffectParams)) {
|
|
452008
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
452009
|
+
effectParams[k] = v;
|
|
452010
|
+
}
|
|
452011
|
+
}
|
|
451926
452012
|
const effect = project.addEffect(clipId, {
|
|
451927
|
-
type:
|
|
451928
|
-
startTime
|
|
451929
|
-
duration
|
|
451930
|
-
params:
|
|
452013
|
+
type: effectType,
|
|
452014
|
+
startTime,
|
|
452015
|
+
duration,
|
|
452016
|
+
params: effectParams
|
|
451931
452017
|
});
|
|
451932
452018
|
return effect !== null;
|
|
451933
452019
|
}
|
|
451934
452020
|
break;
|
|
452021
|
+
}
|
|
451935
452022
|
case "delete":
|
|
451936
452023
|
return project.removeClip(clipId);
|
|
451937
452024
|
}
|
|
@@ -453526,6 +453613,7 @@ function isActiveStatus(status) {
|
|
|
453526
453613
|
}
|
|
453527
453614
|
function providerStatusCommand(record) {
|
|
453528
453615
|
if (record.jobType === "generate-video") {
|
|
453616
|
+
if (record.provider !== "runway" && record.provider !== "kling") return void 0;
|
|
453529
453617
|
const type = record.provider === "kling" && record.providerTaskType ? ` --type ${record.providerTaskType}` : "";
|
|
453530
453618
|
return `vibe generate video-status ${record.providerTaskId} -p ${record.provider}${type} --json`;
|
|
453531
453619
|
}
|
|
@@ -454625,19 +454713,18 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454625
454713
|
if (reference) return referencePrimitiveOutcome("backdrop", beat, ctx, reference);
|
|
454626
454714
|
const prompt3 = stringOrUndefined4(beat.cues?.backdrop);
|
|
454627
454715
|
if (!prompt3) return { status: "no-cue" };
|
|
454628
|
-
if (ctx.imageProvider !== "openai") {
|
|
454629
|
-
const error = `image provider "${ctx.imageProvider}" not yet supported (use openai)`;
|
|
454630
|
-
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
454631
|
-
return { status: "failed", error };
|
|
454632
|
-
}
|
|
454633
454716
|
const rel = `assets/backdrop-${beat.id}.png`;
|
|
454634
454717
|
const abs = join33(ctx.projectDir, rel);
|
|
454718
|
+
const size = ctx.imageSize ?? "1536x1024";
|
|
454719
|
+
const ratio = imageRatioForSize(size);
|
|
454720
|
+
const metadataOptions = { quality: ctx.imageQuality, size, ratio };
|
|
454635
454721
|
const cache = backdropCacheDescriptor({
|
|
454636
454722
|
beatId: beat.id,
|
|
454637
454723
|
cue: prompt3,
|
|
454638
454724
|
provider: ctx.imageProvider,
|
|
454639
454725
|
quality: ctx.imageQuality,
|
|
454640
|
-
size
|
|
454726
|
+
size,
|
|
454727
|
+
ratio
|
|
454641
454728
|
});
|
|
454642
454729
|
const metadataPath = assetMetadataPath("backdrop", beat.id);
|
|
454643
454730
|
if (existsSync35(abs) && !ctx.force) {
|
|
@@ -454648,7 +454735,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454648
454735
|
beatId: beat.id,
|
|
454649
454736
|
cue: prompt3,
|
|
454650
454737
|
provider: ctx.imageProvider,
|
|
454651
|
-
options:
|
|
454738
|
+
options: metadataOptions,
|
|
454652
454739
|
cacheKey: cache.key
|
|
454653
454740
|
})) {
|
|
454654
454741
|
ctx.onProgress({ type: "backdrop-cached", beatId: beat.id, path: rel });
|
|
@@ -454673,7 +454760,7 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454673
454760
|
beatId: beat.id,
|
|
454674
454761
|
cue: prompt3,
|
|
454675
454762
|
provider: ctx.imageProvider,
|
|
454676
|
-
options:
|
|
454763
|
+
options: metadataOptions,
|
|
454677
454764
|
cacheKey: cache.key,
|
|
454678
454765
|
canonicalPath: rel,
|
|
454679
454766
|
cachePath: cache.path
|
|
@@ -454689,27 +454776,14 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454689
454776
|
freshness: "fresh"
|
|
454690
454777
|
};
|
|
454691
454778
|
}
|
|
454692
|
-
|
|
454693
|
-
|
|
454694
|
-
|
|
454695
|
-
const error = "OPENAI_API_KEY not set \u2014 cannot dispatch backdrop";
|
|
454696
|
-
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
454697
|
-
return { status: "failed", error };
|
|
454698
|
-
}
|
|
454699
|
-
const provider = new OpenAIImageProvider();
|
|
454700
|
-
await provider.initialize({ apiKey });
|
|
454701
|
-
const result = await provider.generateImage(prompt3, {
|
|
454702
|
-
model: "gpt-image-2",
|
|
454703
|
-
size: ctx.imageSize,
|
|
454704
|
-
quality: ctx.imageQuality
|
|
454705
|
-
});
|
|
454706
|
-
if (!result.success || !result.images?.[0]?.base64) {
|
|
454707
|
-
const error = result.error ?? "no image data returned";
|
|
454779
|
+
const generated = await generateBackdropImage(prompt3, ctx, ratio);
|
|
454780
|
+
if (!generated.success) {
|
|
454781
|
+
const error = generated.error;
|
|
454708
454782
|
ctx.onProgress({ type: "backdrop-failed", beatId: beat.id, error });
|
|
454709
454783
|
return { status: "failed", error };
|
|
454710
454784
|
}
|
|
454711
454785
|
await mkdir12(dirname20(abs), { recursive: true });
|
|
454712
|
-
const buffer =
|
|
454786
|
+
const buffer = generated.buffer;
|
|
454713
454787
|
await writeFile19(abs, buffer);
|
|
454714
454788
|
await mkdir12(dirname20(cacheAbs), { recursive: true });
|
|
454715
454789
|
await writeFile19(cacheAbs, buffer);
|
|
@@ -454718,8 +454792,8 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454718
454792
|
kind: "backdrop",
|
|
454719
454793
|
beatId: beat.id,
|
|
454720
454794
|
cue: prompt3,
|
|
454721
|
-
provider:
|
|
454722
|
-
options:
|
|
454795
|
+
provider: ctx.imageProvider,
|
|
454796
|
+
options: metadataOptions,
|
|
454723
454797
|
cacheKey: cache.key,
|
|
454724
454798
|
canonicalPath: rel,
|
|
454725
454799
|
cachePath: cache.path
|
|
@@ -454728,18 +454802,75 @@ async function dispatchBackdrop(beat, ctx) {
|
|
|
454728
454802
|
type: "backdrop-generated",
|
|
454729
454803
|
beatId: beat.id,
|
|
454730
454804
|
path: rel,
|
|
454731
|
-
provider:
|
|
454805
|
+
provider: ctx.imageProvider
|
|
454732
454806
|
});
|
|
454733
454807
|
return {
|
|
454734
454808
|
status: "generated",
|
|
454735
454809
|
path: rel,
|
|
454736
|
-
provider:
|
|
454810
|
+
provider: ctx.imageProvider,
|
|
454737
454811
|
cachePath: cache.path,
|
|
454738
454812
|
cacheKey: cache.key,
|
|
454739
454813
|
metadataPath,
|
|
454740
454814
|
freshness: "fresh"
|
|
454741
454815
|
};
|
|
454742
454816
|
}
|
|
454817
|
+
async function generateBackdropImage(prompt3, ctx, ratio) {
|
|
454818
|
+
loadSceneBuildEnv(ctx.projectDir);
|
|
454819
|
+
const keyInfo = imageProviderKeyInfo(ctx.imageProvider);
|
|
454820
|
+
const apiKey = await getApiKeyFromConfig(keyInfo.configKey, { cwd: ctx.projectDir }) ?? process.env[keyInfo.envVar] ?? "";
|
|
454821
|
+
if (!apiKey) {
|
|
454822
|
+
return {
|
|
454823
|
+
success: false,
|
|
454824
|
+
error: `${keyInfo.envVar} not set \u2014 cannot dispatch backdrop with ${ctx.imageProvider}`
|
|
454825
|
+
};
|
|
454826
|
+
}
|
|
454827
|
+
if (ctx.imageProvider === "openai") {
|
|
454828
|
+
const provider2 = new OpenAIImageProvider();
|
|
454829
|
+
await provider2.initialize({ apiKey });
|
|
454830
|
+
const result2 = await provider2.generateImage(prompt3, {
|
|
454831
|
+
model: "gpt-image-2",
|
|
454832
|
+
size: ctx.imageSize,
|
|
454833
|
+
quality: ctx.imageQuality
|
|
454834
|
+
});
|
|
454835
|
+
return imageBufferFromResult(result2);
|
|
454836
|
+
}
|
|
454837
|
+
if (ctx.imageProvider === "gemini") {
|
|
454838
|
+
const provider2 = new GeminiProvider();
|
|
454839
|
+
await provider2.initialize({ apiKey });
|
|
454840
|
+
const result2 = await provider2.generateImage(prompt3, {
|
|
454841
|
+
model: "flash",
|
|
454842
|
+
aspectRatio: ratio
|
|
454843
|
+
});
|
|
454844
|
+
return imageBufferFromResult(result2);
|
|
454845
|
+
}
|
|
454846
|
+
const provider = new GrokProvider();
|
|
454847
|
+
await provider.initialize({ apiKey });
|
|
454848
|
+
const result = await provider.generateImage(prompt3, {
|
|
454849
|
+
aspectRatio: ratio,
|
|
454850
|
+
n: 1
|
|
454851
|
+
});
|
|
454852
|
+
return imageBufferFromResult(result);
|
|
454853
|
+
}
|
|
454854
|
+
async function imageBufferFromResult(result) {
|
|
454855
|
+
const image = result.images?.[0];
|
|
454856
|
+
if (!result.success || !image) {
|
|
454857
|
+
return { success: false, error: result.error ?? "no image data returned" };
|
|
454858
|
+
}
|
|
454859
|
+
if (image.base64) return { success: true, buffer: Buffer.from(image.base64, "base64") };
|
|
454860
|
+
if (image.url) {
|
|
454861
|
+
const response = await fetch(image.url);
|
|
454862
|
+
if (!response.ok) {
|
|
454863
|
+
return { success: false, error: `failed to download image: HTTP ${response.status}` };
|
|
454864
|
+
}
|
|
454865
|
+
return { success: true, buffer: Buffer.from(await response.arrayBuffer()) };
|
|
454866
|
+
}
|
|
454867
|
+
return { success: false, error: "no image data returned" };
|
|
454868
|
+
}
|
|
454869
|
+
function imageProviderKeyInfo(provider) {
|
|
454870
|
+
if (provider === "gemini") return { configKey: "google", envVar: "GOOGLE_API_KEY" };
|
|
454871
|
+
if (provider === "grok") return { configKey: "xai", envVar: "XAI_API_KEY" };
|
|
454872
|
+
return { configKey: "openai", envVar: "OPENAI_API_KEY" };
|
|
454873
|
+
}
|
|
454743
454874
|
async function dispatchVideo(beat, ctx) {
|
|
454744
454875
|
const reference = assetReferenceForBeat(ctx.projectDir, "video", beat);
|
|
454745
454876
|
if (reference) return referencePrimitiveOutcome("video", beat, ctx, reference);
|
|
@@ -470125,7 +470256,10 @@ async function executeSuggestEdit(options) {
|
|
|
470125
470256
|
}
|
|
470126
470257
|
return { success: true, suggestions };
|
|
470127
470258
|
} catch (error) {
|
|
470128
|
-
return {
|
|
470259
|
+
return {
|
|
470260
|
+
success: false,
|
|
470261
|
+
error: `Suggest failed: ${error instanceof Error ? error.message : String(error)}`
|
|
470262
|
+
};
|
|
470129
470263
|
}
|
|
470130
470264
|
}
|
|
470131
470265
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.103.0",
|
|
4
4
|
"description": "VibeFrame MCP Server - AI-native video editing via Model Context Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"tsx": "^4.21.0",
|
|
58
58
|
"typescript": "^5.3.3",
|
|
59
59
|
"vitest": "^1.2.2",
|
|
60
|
-
"@vibeframe/
|
|
61
|
-
"@vibeframe/
|
|
60
|
+
"@vibeframe/cli": "0.103.0",
|
|
61
|
+
"@vibeframe/core": "0.103.0"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
64
|
"node": ">=20"
|