@vibeframe/cli 0.113.29 → 0.113.30
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 +11 -7
- package/dist/commands/_shared/scene-project.d.ts +1 -1
- package/dist/commands/output.d.ts +21 -0
- package/dist/index.js +68 -73
- package/dist/tools/manifest/index.js +32 -12
- package/package.json +3 -3
package/CONTEXT.md
CHANGED
|
@@ -125,13 +125,17 @@ vibe guide <topic> --json # Step-by-step guides (motion | scene | p
|
|
|
125
125
|
}
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
| Code
|
|
129
|
-
|
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
128
|
+
| Code | Exit | Meaning | Recovery |
|
|
129
|
+
| -------------------- | ---- | --------------------------- | --------------------------------- |
|
|
130
|
+
| `COST_CAP_EXCEEDED` | 1 | estimate over `--max-cost` | follow `retryWith`; do not re-run as-is |
|
|
131
|
+
| `USAGE_ERROR` | 2 | bad arg | check `vibe schema <cmd>` |
|
|
132
|
+
| `NOT_FOUND` | 3 | file missing | verify path |
|
|
133
|
+
| `AUTH_ERROR` | 4 | key missing/invalid | `vibe doctor` |
|
|
134
|
+
| `API_ERROR` | 5 | provider failed | retry if `retryable: true` |
|
|
135
|
+
| `NETWORK_ERROR` | 6 | connection | retry with backoff |
|
|
136
|
+
|
|
137
|
+
`COST_CAP_EXCEEDED` also carries `data.plan` - the priced plan the refusal was
|
|
138
|
+
based on - so a refused call still tells you what the build would have cost.
|
|
135
139
|
|
|
136
140
|
## Authentication
|
|
137
141
|
|
|
@@ -98,7 +98,7 @@ export declare function buildHyperframesConfig(): HyperframesConfig;
|
|
|
98
98
|
export declare function buildHyperframesMeta(name: string, now?: Date): HyperframesMeta;
|
|
99
99
|
/**
|
|
100
100
|
* Merge an existing Hyperframes config with our defaults, preserving any
|
|
101
|
-
* user-authored keys and nested values. `vibe
|
|
101
|
+
* user-authored keys and nested values. `vibe init` is idempotent:
|
|
102
102
|
* running it on a directory that already has `hyperframes.json` must never
|
|
103
103
|
* lose user config.
|
|
104
104
|
*/
|
|
@@ -22,6 +22,12 @@ export interface StructuredError {
|
|
|
22
22
|
retryWith?: string[];
|
|
23
23
|
recoverable?: boolean;
|
|
24
24
|
retryable: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Structured context carried alongside the failure, so a refusal can hand
|
|
27
|
+
* back the evidence it refused on instead of forcing a second call. Used by
|
|
28
|
+
* the `--max-cost` gate to return the priced build plan with the refusal.
|
|
29
|
+
*/
|
|
30
|
+
data?: Record<string, unknown>;
|
|
25
31
|
}
|
|
26
32
|
export declare function usageError(msg: string, suggestion?: string): StructuredError;
|
|
27
33
|
export declare function authError(envVar: string, provider: string): StructuredError;
|
|
@@ -29,6 +35,21 @@ export declare function apiError(msg: string, retryable?: boolean): StructuredEr
|
|
|
29
35
|
export declare function notFoundError(path: string): StructuredError;
|
|
30
36
|
export declare function networkError(msg: string): StructuredError;
|
|
31
37
|
export declare function generalError(msg: string, suggestion?: string): StructuredError;
|
|
38
|
+
/**
|
|
39
|
+
* The `--max-cost` refusal. A command that declines to spend is a failure, so
|
|
40
|
+
* it takes the structured error path like every other refusal: `success:false`
|
|
41
|
+
* on stderr, exit 1. `data` carries the priced plan the refusal was based on,
|
|
42
|
+
* so an agent gets the estimate and the reason from one call.
|
|
43
|
+
*
|
|
44
|
+
* `recoverable: true` because the caller has two real ways forward (raise the
|
|
45
|
+
* ceiling, or narrow the scope), both spelled out in `retryWith`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function costCapError(opts: {
|
|
48
|
+
estimatedCostUsd: number;
|
|
49
|
+
maxCostUsd: number;
|
|
50
|
+
retryWith: string[];
|
|
51
|
+
data?: Record<string, unknown>;
|
|
52
|
+
}): StructuredError;
|
|
32
53
|
/** Output structured error then exit */
|
|
33
54
|
export declare function exitWithError(err: StructuredError): never;
|
|
34
55
|
/** Check if --json flag is active */
|
package/dist/index.js
CHANGED
|
@@ -6557,6 +6557,19 @@ function notFoundError(path2) {
|
|
|
6557
6557
|
function generalError(msg, suggestion) {
|
|
6558
6558
|
return { success: false, error: msg, code: "ERROR", exitCode: 1 /* GENERAL */, suggestion, retryable: false };
|
|
6559
6559
|
}
|
|
6560
|
+
function costCapError(opts) {
|
|
6561
|
+
return {
|
|
6562
|
+
success: false,
|
|
6563
|
+
error: `Estimated cost $${opts.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${opts.maxCostUsd.toFixed(2)}.`,
|
|
6564
|
+
code: "COST_CAP_EXCEEDED",
|
|
6565
|
+
exitCode: 1 /* GENERAL */,
|
|
6566
|
+
suggestion: "Raise --max-cost or reduce the stage/provider scope.",
|
|
6567
|
+
retryWith: opts.retryWith,
|
|
6568
|
+
recoverable: true,
|
|
6569
|
+
retryable: false,
|
|
6570
|
+
data: opts.data
|
|
6571
|
+
};
|
|
6572
|
+
}
|
|
6560
6573
|
function exitWithError(err) {
|
|
6561
6574
|
if (isJsonMode()) {
|
|
6562
6575
|
console.error(JSON.stringify({
|
|
@@ -6571,6 +6584,9 @@ function exitWithError(err) {
|
|
|
6571
6584
|
if (err.suggestion) {
|
|
6572
6585
|
console.error(source_default.dim(` ${err.suggestion}`));
|
|
6573
6586
|
}
|
|
6587
|
+
if (err.retryWith && err.retryWith.length > 0) {
|
|
6588
|
+
console.error(source_default.dim(` Retry: ${err.retryWith[0]}`));
|
|
6589
|
+
}
|
|
6574
6590
|
console.error();
|
|
6575
6591
|
}
|
|
6576
6592
|
process.exit(err.exitCode);
|
|
@@ -26945,7 +26961,7 @@ ${avoid}
|
|
|
26945
26961
|
---
|
|
26946
26962
|
|
|
26947
26963
|
_Browse other named styles: \`vibe scene list-styles\`_
|
|
26948
|
-
${style ? `_This file was seeded by \`vibe
|
|
26964
|
+
${style ? `_This file was seeded by \`vibe init --visual-style "${style.name}"\`._` : `_Seed this file from a named style: \`vibe init <dir> --visual-style "<name>"\`._`}
|
|
26949
26965
|
`;
|
|
26950
26966
|
}
|
|
26951
26967
|
function buildScriptMd(name, kind = DEFAULT_SCENE_KIND) {
|
|
@@ -27090,7 +27106,7 @@ Single-asset requests (\`vibe generate image|video|speech|...\`) do NOT
|
|
|
27090
27106
|
consult this file - run the generate command directly.
|
|
27091
27107
|
|
|
27092
27108
|
Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
|
|
27093
|
-
\`vibe
|
|
27109
|
+
\`vibe init . --visual-style "Swiss Pulse"\` (idempotent).
|
|
27094
27110
|
|
|
27095
27111
|
## Brief and local media
|
|
27096
27112
|
|
|
@@ -27245,9 +27261,21 @@ npx hyperframes render
|
|
|
27245
27261
|
|
|
27246
27262
|
## Key Rules (for hand-authored scene HTML)
|
|
27247
27263
|
|
|
27264
|
+
0. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE
|
|
27265
|
+
composition div - not a standalone \`<!doctype html>\` document:
|
|
27266
|
+
\`\`\`html
|
|
27267
|
+
<template id="scene-hook-template">
|
|
27268
|
+
<div data-composition-id="scene-hook" data-start="0" data-duration="3.3"
|
|
27269
|
+
data-width="1920" data-height="1080">\u2026</div>
|
|
27270
|
+
</template>
|
|
27271
|
+
\`\`\`
|
|
27272
|
+
The composition div **MUST** carry \`data-width\` and \`data-height\`.
|
|
27248
27273
|
1. Every timed element needs \`data-start\`, \`data-duration\`, and \`data-track-index\`.
|
|
27249
27274
|
2. Elements with timing **MUST** have \`class="clip"\` - the framework uses this for visibility control.
|
|
27250
|
-
3. Timelines must be paused and registered on \`window.__timelines
|
|
27275
|
+
3. Timelines must be paused and registered on \`window.__timelines\`, which is an
|
|
27276
|
+
OBJECT keyed by composition id - not an array, and \`.push()\` leaves the
|
|
27277
|
+
timeline undiscovered, which renders a black frame because \`gsap.from\` holds
|
|
27278
|
+
elements at their start state:
|
|
27251
27279
|
\`\`\`js
|
|
27252
27280
|
window.__timelines = window.__timelines || {};
|
|
27253
27281
|
window.__timelines["composition-id"] = gsap.timeline({ paused: true });
|
|
@@ -28111,7 +28139,7 @@ function insertClipIntoRoot(rootHtml, clip) {
|
|
|
28111
28139
|
const closeMatch = rootHtml.match(/\n(\s*)<\/div>(\s*\n\s*<script>)/);
|
|
28112
28140
|
if (!closeMatch) {
|
|
28113
28141
|
throw new Error(
|
|
28114
|
-
"Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe
|
|
28142
|
+
"Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe init`."
|
|
28115
28143
|
);
|
|
28116
28144
|
}
|
|
28117
28145
|
const closeIdx = closeMatch.index;
|
|
@@ -29393,10 +29421,10 @@ async function getComposePrompts(opts) {
|
|
|
29393
29421
|
error: msg
|
|
29394
29422
|
});
|
|
29395
29423
|
if (!existsSync6(designPath)) {
|
|
29396
|
-
return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe
|
|
29424
|
+
return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe init <dir>\` first.`);
|
|
29397
29425
|
}
|
|
29398
29426
|
if (!existsSync6(storyboardPath2)) {
|
|
29399
|
-
return baseError(`STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe
|
|
29427
|
+
return baseError(`STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`);
|
|
29400
29428
|
}
|
|
29401
29429
|
if (!hyperframesSkillAvailable(projectDir)) {
|
|
29402
29430
|
warnings.push(
|
|
@@ -29476,7 +29504,9 @@ function buildInstructions(args) {
|
|
|
29476
29504
|
if (args.skillRef) {
|
|
29477
29505
|
lines.push(`1. Read \`${args.skillRef}\` for the Hyperframes framework rules + house style. This is the visual-identity hard-gate.`);
|
|
29478
29506
|
} else {
|
|
29479
|
-
lines.push(
|
|
29507
|
+
lines.push(
|
|
29508
|
+
`1. Read this project's \`AGENTS.md\` section "Key Rules (for hand-authored scene HTML)" - written by \`vibe init\`, and the authoritative local contract. \`vibe scene install-skill\` adds Hyperframes' house style on top, but note it installs a ROUTER whose full contract sits behind \`/hyperframes-core\`, which resolves only in a host that has upstream's Hyperframes skills.`
|
|
29509
|
+
);
|
|
29480
29510
|
}
|
|
29481
29511
|
lines.push(`2. Read \`DESIGN.md\` for project-specific palette, typography, motion signature.`);
|
|
29482
29512
|
if (args.compositionRef) {
|
|
@@ -29486,6 +29516,7 @@ function buildInstructions(args) {
|
|
|
29486
29516
|
lines.push(`3b. Use each beat's \`finalDurationSec\` (narration-synced) for \`data-duration\` and timeline anchors when present \u2014 NOT the storyboard \`duration\`, which is only the minimum. Scenes composed at the storyboard duration end early and render black tails.`);
|
|
29487
29517
|
lines.push(`3c. Never give inner \`.clip\` elements a non-zero \`data-start\` \u2014 the renderer does not toggle internal clip visibility inside sub-compositions, so phased clips render all phases at once (overlapping text). Use full-window clips and GSAP autoAlpha phase transitions instead. Also keep beats 6-15s; split anything longer in the storyboard first.`);
|
|
29488
29518
|
lines.push(`3d. If your environment cannot write files (e.g. Claude Desktop / MCP-only hosts), author each beat's HTML and submit it with the \`scene_submit\` tool (beat id + html). It validates with the same Hyperframes lint and writes the file for you; on lint errors it returns the findings without writing \u2014 fix and resubmit.`);
|
|
29519
|
+
lines.push(`3e. Hard requirements the linter fails on, so satisfy them even without the full contract. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE \`<div data-composition-id="scene-<id>" data-start="0" data-duration="<sec>" data-width="1920" data-height="1080">\` \u2014 not a standalone \`<!doctype html>\` document. Register the paused GSAP timeline on the registry OBJECT keyed by composition id: \`window.__timelines = window.__timelines || {}; window.__timelines["scene-<id>"] = tl;\` \u2014 it is not an array, and \`.push()\` leaves the timeline undiscovered, which renders a black frame because \`gsap.from\` holds elements at their start state. Also put \`class="clip"\` on every timed element and give timeline-visible elements a stable \`id\`. Generate a reference scene with \`vibe scene add <id> --style <preset> --no-audio --no-image\` and match its shape.`);
|
|
29489
29520
|
if (args.beatCount > 1) {
|
|
29490
29521
|
lines.push(`4. After authoring all ${args.beatCount} beat(s), run \`vibe build <project> --stage sync --json\` to assemble the root composition (index.html) from the fragments. Lint needs that root, so sync comes first.`);
|
|
29491
29522
|
} else if (args.filtered) {
|
|
@@ -30771,7 +30802,9 @@ async function executeSceneAdd(opts) {
|
|
|
30771
30802
|
error
|
|
30772
30803
|
});
|
|
30773
30804
|
if (!await pathExists2(rootPath)) {
|
|
30774
|
-
return errResult(
|
|
30805
|
+
return errResult(
|
|
30806
|
+
`Root composition not found: ${rootPath}. Run \`vibe build\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
|
|
30807
|
+
);
|
|
30775
30808
|
}
|
|
30776
30809
|
if (!opts.force && await pathExists2(scenePath)) {
|
|
30777
30810
|
return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
|
|
@@ -31313,7 +31346,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
31313
31346
|
console.log(source_default.dim("Show details: "), source_default.cyan('vibe scene list-styles "<name>"'));
|
|
31314
31347
|
console.log(
|
|
31315
31348
|
source_default.dim("Seed DESIGN.md:"),
|
|
31316
|
-
source_default.cyan('vibe
|
|
31349
|
+
source_default.cyan('vibe init <dir> --visual-style "<name>"')
|
|
31317
31350
|
);
|
|
31318
31351
|
return;
|
|
31319
31352
|
}
|
|
@@ -31348,7 +31381,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
31348
31381
|
console.log();
|
|
31349
31382
|
console.log(
|
|
31350
31383
|
source_default.dim("Seed DESIGN.md:"),
|
|
31351
|
-
source_default.cyan(`vibe
|
|
31384
|
+
source_default.cyan(`vibe init <dir> --visual-style "${style.name}"`)
|
|
31352
31385
|
);
|
|
31353
31386
|
});
|
|
31354
31387
|
sceneCommand.command("add").description("Add a new scene to a project: AI narration + image + per-scene HTML").argument("<name>", "Scene name (slugified into the composition id)").option("--style <preset>", `Style preset: ${SCENE_PRESETS.join(", ")}`, "simple").option(
|
|
@@ -61218,7 +61251,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
61218
61251
|
kind: "render",
|
|
61219
61252
|
beat: opts.beatId ?? null,
|
|
61220
61253
|
root,
|
|
61221
|
-
error: `Root composition not found: ${resolve66(projectDir, root)}. Run \`vibe
|
|
61254
|
+
error: `Root composition not found: ${resolve66(projectDir, root)}. Run \`vibe build ${projectDir}\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
|
|
61222
61255
|
};
|
|
61223
61256
|
}
|
|
61224
61257
|
const chrome = await preflightChrome();
|
|
@@ -61709,7 +61742,7 @@ async function executeSceneBuild(opts) {
|
|
|
61709
61742
|
phase: "failed",
|
|
61710
61743
|
mode,
|
|
61711
61744
|
selectedStage,
|
|
61712
|
-
error: `STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe
|
|
61745
|
+
error: `STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`,
|
|
61713
61746
|
beats: [],
|
|
61714
61747
|
stageReports,
|
|
61715
61748
|
warnings,
|
|
@@ -74249,7 +74282,7 @@ init_source();
|
|
|
74249
74282
|
// package.json
|
|
74250
74283
|
var package_default = {
|
|
74251
74284
|
name: "@vibeframe/cli",
|
|
74252
|
-
version: "0.113.
|
|
74285
|
+
version: "0.113.30",
|
|
74253
74286
|
description: "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
|
|
74254
74287
|
private: false,
|
|
74255
74288
|
license: "MIT",
|
|
@@ -84605,35 +84638,17 @@ var planCommand = new Command("plan").description("Read STORYBOARD.md and show b
|
|
|
84605
84638
|
return;
|
|
84606
84639
|
}
|
|
84607
84640
|
if (maxCost !== void 0 && plan.estimatedCostUsd > maxCost) {
|
|
84608
|
-
const warning = `Estimated cost $${plan.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${maxCost.toFixed(2)}.`;
|
|
84609
|
-
const data = {
|
|
84610
|
-
...plan,
|
|
84611
|
-
costCapUsd: maxCost,
|
|
84612
|
-
code: "COST_CAP_EXCEEDED",
|
|
84613
|
-
message: warning,
|
|
84614
|
-
suggestion: "Raise --max-cost or reduce the stage/provider scope.",
|
|
84615
|
-
recoverable: true,
|
|
84616
|
-
retryWith: [
|
|
84617
|
-
...plan.retryWith,
|
|
84618
|
-
`vibe plan ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
|
|
84619
|
-
`vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
|
|
84620
|
-
].filter((value, index, all) => value.length > 0 && all.indexOf(value) === index)
|
|
84621
|
-
};
|
|
84622
|
-
if (isJsonMode()) {
|
|
84623
|
-
outputSuccess({
|
|
84624
|
-
command: "plan",
|
|
84625
|
-
startedAt,
|
|
84626
|
-
data,
|
|
84627
|
-
warnings: [warning]
|
|
84628
|
-
});
|
|
84629
|
-
process.exitCode = 1;
|
|
84630
|
-
return;
|
|
84631
|
-
}
|
|
84632
84641
|
exitWithError(
|
|
84633
|
-
|
|
84634
|
-
|
|
84635
|
-
|
|
84636
|
-
|
|
84642
|
+
costCapError({
|
|
84643
|
+
estimatedCostUsd: plan.estimatedCostUsd,
|
|
84644
|
+
maxCostUsd: maxCost,
|
|
84645
|
+
retryWith: [
|
|
84646
|
+
...plan.retryWith,
|
|
84647
|
+
`vibe plan ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
|
|
84648
|
+
`vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
|
|
84649
|
+
].filter((value, index, all) => value.length > 0 && all.indexOf(value) === index),
|
|
84650
|
+
data: { ...plan, costCapUsd: maxCost }
|
|
84651
|
+
})
|
|
84637
84652
|
);
|
|
84638
84653
|
}
|
|
84639
84654
|
if (isJsonMode()) {
|
|
@@ -84844,38 +84859,18 @@ Advanced equivalent: \`vibe scene build\`.`
|
|
|
84844
84859
|
return;
|
|
84845
84860
|
}
|
|
84846
84861
|
if (maxCostUsd !== void 0 && plan.estimatedCostUsd > maxCostUsd) {
|
|
84847
|
-
|
|
84848
|
-
|
|
84849
|
-
|
|
84850
|
-
|
|
84851
|
-
|
|
84852
|
-
|
|
84853
|
-
|
|
84854
|
-
|
|
84855
|
-
|
|
84856
|
-
|
|
84857
|
-
|
|
84858
|
-
|
|
84859
|
-
data: {
|
|
84860
|
-
params,
|
|
84861
|
-
plan,
|
|
84862
|
-
costCapUsd: maxCostUsd,
|
|
84863
|
-
code: "COST_CAP_EXCEEDED",
|
|
84864
|
-
message: warning,
|
|
84865
|
-
suggestion: "Raise --max-cost or reduce the stage/provider scope.",
|
|
84866
|
-
retryWith,
|
|
84867
|
-
recoverable: true
|
|
84868
|
-
}
|
|
84869
|
-
});
|
|
84870
|
-
process.exitCode = 1;
|
|
84871
|
-
return;
|
|
84872
|
-
}
|
|
84873
|
-
console.log(source_default.red(warning));
|
|
84874
|
-
if (retryWith.length > 0) {
|
|
84875
|
-
console.log(source_default.dim(`Retry: ${retryWith[0]}`));
|
|
84876
|
-
}
|
|
84877
|
-
process.exitCode = 1;
|
|
84878
|
-
return;
|
|
84862
|
+
exitWithError(
|
|
84863
|
+
costCapError({
|
|
84864
|
+
estimatedCostUsd: plan.estimatedCostUsd,
|
|
84865
|
+
maxCostUsd,
|
|
84866
|
+
retryWith: unique6([
|
|
84867
|
+
...plan.retryWith,
|
|
84868
|
+
`vibe build ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
|
|
84869
|
+
`vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
|
|
84870
|
+
]),
|
|
84871
|
+
data: { params, plan, costCapUsd: maxCostUsd }
|
|
84872
|
+
})
|
|
84873
|
+
);
|
|
84879
84874
|
}
|
|
84880
84875
|
if (!isJsonMode() && !isQuietMode()) {
|
|
84881
84876
|
printBuildDryRun(projectDirArg, params, plan);
|
|
@@ -24010,6 +24010,9 @@ function exitWithError(err) {
|
|
|
24010
24010
|
if (err.suggestion) {
|
|
24011
24011
|
console.error(source_default.dim(` ${err.suggestion}`));
|
|
24012
24012
|
}
|
|
24013
|
+
if (err.retryWith && err.retryWith.length > 0) {
|
|
24014
|
+
console.error(source_default.dim(` Retry: ${err.retryWith[0]}`));
|
|
24015
|
+
}
|
|
24013
24016
|
console.error();
|
|
24014
24017
|
}
|
|
24015
24018
|
process.exit(err.exitCode);
|
|
@@ -26127,7 +26130,7 @@ ${avoid}
|
|
|
26127
26130
|
---
|
|
26128
26131
|
|
|
26129
26132
|
_Browse other named styles: \`vibe scene list-styles\`_
|
|
26130
|
-
${style ? `_This file was seeded by \`vibe
|
|
26133
|
+
${style ? `_This file was seeded by \`vibe init --visual-style "${style.name}"\`._` : `_Seed this file from a named style: \`vibe init <dir> --visual-style "<name>"\`._`}
|
|
26131
26134
|
`;
|
|
26132
26135
|
}
|
|
26133
26136
|
function buildScriptMd(name, kind = DEFAULT_SCENE_KIND) {
|
|
@@ -26272,7 +26275,7 @@ Single-asset requests (\`vibe generate image|video|speech|...\`) do NOT
|
|
|
26272
26275
|
consult this file - run the generate command directly.
|
|
26273
26276
|
|
|
26274
26277
|
Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
|
|
26275
|
-
\`vibe
|
|
26278
|
+
\`vibe init . --visual-style "Swiss Pulse"\` (idempotent).
|
|
26276
26279
|
|
|
26277
26280
|
## Brief and local media
|
|
26278
26281
|
|
|
@@ -26427,9 +26430,21 @@ npx hyperframes render
|
|
|
26427
26430
|
|
|
26428
26431
|
## Key Rules (for hand-authored scene HTML)
|
|
26429
26432
|
|
|
26433
|
+
0. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE
|
|
26434
|
+
composition div - not a standalone \`<!doctype html>\` document:
|
|
26435
|
+
\`\`\`html
|
|
26436
|
+
<template id="scene-hook-template">
|
|
26437
|
+
<div data-composition-id="scene-hook" data-start="0" data-duration="3.3"
|
|
26438
|
+
data-width="1920" data-height="1080">\u2026</div>
|
|
26439
|
+
</template>
|
|
26440
|
+
\`\`\`
|
|
26441
|
+
The composition div **MUST** carry \`data-width\` and \`data-height\`.
|
|
26430
26442
|
1. Every timed element needs \`data-start\`, \`data-duration\`, and \`data-track-index\`.
|
|
26431
26443
|
2. Elements with timing **MUST** have \`class="clip"\` - the framework uses this for visibility control.
|
|
26432
|
-
3. Timelines must be paused and registered on \`window.__timelines
|
|
26444
|
+
3. Timelines must be paused and registered on \`window.__timelines\`, which is an
|
|
26445
|
+
OBJECT keyed by composition id - not an array, and \`.push()\` leaves the
|
|
26446
|
+
timeline undiscovered, which renders a black frame because \`gsap.from\` holds
|
|
26447
|
+
elements at their start state:
|
|
26433
26448
|
\`\`\`js
|
|
26434
26449
|
window.__timelines = window.__timelines || {};
|
|
26435
26450
|
window.__timelines["composition-id"] = gsap.timeline({ paused: true });
|
|
@@ -30750,10 +30765,10 @@ async function getComposePrompts(opts) {
|
|
|
30750
30765
|
error: msg
|
|
30751
30766
|
});
|
|
30752
30767
|
if (!existsSync8(designPath)) {
|
|
30753
|
-
return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe
|
|
30768
|
+
return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe init <dir>\` first.`);
|
|
30754
30769
|
}
|
|
30755
30770
|
if (!existsSync8(storyboardPath)) {
|
|
30756
|
-
return baseError(`STORYBOARD.md not found at ${storyboardPath}. Run \`vibe
|
|
30771
|
+
return baseError(`STORYBOARD.md not found at ${storyboardPath}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`);
|
|
30757
30772
|
}
|
|
30758
30773
|
if (!hyperframesSkillAvailable(projectDir)) {
|
|
30759
30774
|
warnings.push(
|
|
@@ -30833,7 +30848,9 @@ function buildInstructions(args) {
|
|
|
30833
30848
|
if (args.skillRef) {
|
|
30834
30849
|
lines.push(`1. Read \`${args.skillRef}\` for the Hyperframes framework rules + house style. This is the visual-identity hard-gate.`);
|
|
30835
30850
|
} else {
|
|
30836
|
-
lines.push(
|
|
30851
|
+
lines.push(
|
|
30852
|
+
`1. Read this project's \`AGENTS.md\` section "Key Rules (for hand-authored scene HTML)" - written by \`vibe init\`, and the authoritative local contract. \`vibe scene install-skill\` adds Hyperframes' house style on top, but note it installs a ROUTER whose full contract sits behind \`/hyperframes-core\`, which resolves only in a host that has upstream's Hyperframes skills.`
|
|
30853
|
+
);
|
|
30837
30854
|
}
|
|
30838
30855
|
lines.push(`2. Read \`DESIGN.md\` for project-specific palette, typography, motion signature.`);
|
|
30839
30856
|
if (args.compositionRef) {
|
|
@@ -30843,6 +30860,7 @@ function buildInstructions(args) {
|
|
|
30843
30860
|
lines.push(`3b. Use each beat's \`finalDurationSec\` (narration-synced) for \`data-duration\` and timeline anchors when present \u2014 NOT the storyboard \`duration\`, which is only the minimum. Scenes composed at the storyboard duration end early and render black tails.`);
|
|
30844
30861
|
lines.push(`3c. Never give inner \`.clip\` elements a non-zero \`data-start\` \u2014 the renderer does not toggle internal clip visibility inside sub-compositions, so phased clips render all phases at once (overlapping text). Use full-window clips and GSAP autoAlpha phase transitions instead. Also keep beats 6-15s; split anything longer in the storyboard first.`);
|
|
30845
30862
|
lines.push(`3d. If your environment cannot write files (e.g. Claude Desktop / MCP-only hosts), author each beat's HTML and submit it with the \`scene_submit\` tool (beat id + html). It validates with the same Hyperframes lint and writes the file for you; on lint errors it returns the findings without writing \u2014 fix and resubmit.`);
|
|
30863
|
+
lines.push(`3e. Hard requirements the linter fails on, so satisfy them even without the full contract. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE \`<div data-composition-id="scene-<id>" data-start="0" data-duration="<sec>" data-width="1920" data-height="1080">\` \u2014 not a standalone \`<!doctype html>\` document. Register the paused GSAP timeline on the registry OBJECT keyed by composition id: \`window.__timelines = window.__timelines || {}; window.__timelines["scene-<id>"] = tl;\` \u2014 it is not an array, and \`.push()\` leaves the timeline undiscovered, which renders a black frame because \`gsap.from\` holds elements at their start state. Also put \`class="clip"\` on every timed element and give timeline-visible elements a stable \`id\`. Generate a reference scene with \`vibe scene add <id> --style <preset> --no-audio --no-image\` and match its shape.`);
|
|
30846
30864
|
if (args.beatCount > 1) {
|
|
30847
30865
|
lines.push(`4. After authoring all ${args.beatCount} beat(s), run \`vibe build <project> --stage sync --json\` to assemble the root composition (index.html) from the fragments. Lint needs that root, so sync comes first.`);
|
|
30848
30866
|
} else if (args.filtered) {
|
|
@@ -31941,7 +31959,7 @@ async function executeSceneRender(opts = {}) {
|
|
|
31941
31959
|
kind: "render",
|
|
31942
31960
|
beat: opts.beatId ?? null,
|
|
31943
31961
|
root,
|
|
31944
|
-
error: `Root composition not found: ${resolve20(projectDir, root)}. Run \`vibe
|
|
31962
|
+
error: `Root composition not found: ${resolve20(projectDir, root)}. Run \`vibe build ${projectDir}\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
|
|
31945
31963
|
};
|
|
31946
31964
|
}
|
|
31947
31965
|
const chrome = await preflightChrome();
|
|
@@ -34189,7 +34207,7 @@ async function executeSceneBuild(opts) {
|
|
|
34189
34207
|
phase: "failed",
|
|
34190
34208
|
mode,
|
|
34191
34209
|
selectedStage,
|
|
34192
|
-
error: `STORYBOARD.md not found at ${storyboardPath}. Run \`vibe
|
|
34210
|
+
error: `STORYBOARD.md not found at ${storyboardPath}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`,
|
|
34193
34211
|
beats: [],
|
|
34194
34212
|
stageReports,
|
|
34195
34213
|
warnings,
|
|
@@ -52976,7 +52994,7 @@ function insertClipIntoRoot(rootHtml, clip) {
|
|
|
52976
52994
|
const closeMatch = rootHtml.match(/\n(\s*)<\/div>(\s*\n\s*<script>)/);
|
|
52977
52995
|
if (!closeMatch) {
|
|
52978
52996
|
throw new Error(
|
|
52979
|
-
"Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe
|
|
52997
|
+
"Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe init`."
|
|
52980
52998
|
);
|
|
52981
52999
|
}
|
|
52982
53000
|
const closeIdx = closeMatch.index;
|
|
@@ -53377,7 +53395,7 @@ sceneCommand.command("list-styles").description("List vendored visual styles (or
|
|
|
53377
53395
|
console.log(source_default.dim("Show details: "), source_default.cyan('vibe scene list-styles "<name>"'));
|
|
53378
53396
|
console.log(
|
|
53379
53397
|
source_default.dim("Seed DESIGN.md:"),
|
|
53380
|
-
source_default.cyan('vibe
|
|
53398
|
+
source_default.cyan('vibe init <dir> --visual-style "<name>"')
|
|
53381
53399
|
);
|
|
53382
53400
|
return;
|
|
53383
53401
|
}
|
|
@@ -53412,7 +53430,7 @@ sceneCommand.command("list-styles").description("List vendored visual styles (or
|
|
|
53412
53430
|
console.log();
|
|
53413
53431
|
console.log(
|
|
53414
53432
|
source_default.dim("Seed DESIGN.md:"),
|
|
53415
|
-
source_default.cyan(`vibe
|
|
53433
|
+
source_default.cyan(`vibe init <dir> --visual-style "${style.name}"`)
|
|
53416
53434
|
);
|
|
53417
53435
|
});
|
|
53418
53436
|
sceneCommand.command("add").description("Add a new scene to a project: AI narration + image + per-scene HTML").argument("<name>", "Scene name (slugified into the composition id)").option("--style <preset>", `Style preset: ${SCENE_PRESETS.join(", ")}`, "simple").option(
|
|
@@ -53670,7 +53688,9 @@ async function executeSceneAdd(opts) {
|
|
|
53670
53688
|
error
|
|
53671
53689
|
});
|
|
53672
53690
|
if (!await pathExists2(rootPath)) {
|
|
53673
|
-
return errResult(
|
|
53691
|
+
return errResult(
|
|
53692
|
+
`Root composition not found: ${rootPath}. Run \`vibe build\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
|
|
53693
|
+
);
|
|
53674
53694
|
}
|
|
53675
53695
|
if (!opts.force && await pathExists2(scenePath)) {
|
|
53676
53696
|
return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.113.
|
|
3
|
+
"version": "0.113.30",
|
|
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/
|
|
95
|
-
"@vibeframe/
|
|
94
|
+
"@vibeframe/core": "0.113.30",
|
|
95
|
+
"@vibeframe/ai-providers": "0.113.30"
|
|
96
96
|
},
|
|
97
97
|
"engines": {
|
|
98
98
|
"node": ">=20"
|