hyperframes 0.7.3 → 0.7.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.
- package/dist/cli.js +305 -76
- package/dist/skills/hyperframes/SKILL.md +28 -11
- package/dist/studio/assets/{index-C5AdP06R.js → index-CUhSVvnV.js} +1 -1
- package/dist/studio/assets/{index-hqkzfAEp.js → index-Dp0h2I9v.js} +96 -96
- package/dist/studio/assets/{index-C4cVeLOS.js → index-DvpQwnaB.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +9 -4
- package/dist/studio/index.js.map +1 -1
- package/dist/templates/_shared/AGENTS.md +2 -2
- package/dist/templates/_shared/CLAUDE.md +2 -2
- package/dist/templates/warm-grain/compositions/graphics.html +6 -9
- package/dist/templates/warm-grain/compositions/intro.html +7 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ var VERSION;
|
|
|
50
50
|
var init_version = __esm({
|
|
51
51
|
"src/version.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
VERSION = true ? "0.7.
|
|
53
|
+
VERSION = true ? "0.7.4" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -26253,13 +26253,49 @@ function cssTransformToGsapProps(cssTransform) {
|
|
|
26253
26253
|
}
|
|
26254
26254
|
return parts.length > 0 ? parts.join(", ") : null;
|
|
26255
26255
|
}
|
|
26256
|
-
|
|
26256
|
+
function targetedSelectorTokens(selector) {
|
|
26257
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
26258
|
+
for (const group of selector.split(",")) {
|
|
26259
|
+
const compounds = group.trim().split(/[\s>+~]+/).filter(Boolean);
|
|
26260
|
+
const last = compounds[compounds.length - 1];
|
|
26261
|
+
if (!last) continue;
|
|
26262
|
+
const simple2 = last.match(/[#.][A-Za-z0-9_-]+/g);
|
|
26263
|
+
if (simple2) for (const token of simple2) tokens.add(token);
|
|
26264
|
+
}
|
|
26265
|
+
return tokens;
|
|
26266
|
+
}
|
|
26267
|
+
function matchCssTransform(gsapSelector, cssMap) {
|
|
26268
|
+
if (cssMap.size === 0) return void 0;
|
|
26269
|
+
const direct = cssMap.get(gsapSelector);
|
|
26270
|
+
if (direct) return direct;
|
|
26271
|
+
const tokens = targetedSelectorTokens(gsapSelector);
|
|
26272
|
+
for (const [cssSelector, value] of cssMap) {
|
|
26273
|
+
if (tokens.has(cssSelector)) return value;
|
|
26274
|
+
}
|
|
26275
|
+
return void 0;
|
|
26276
|
+
}
|
|
26277
|
+
function extractStandaloneGsapTransformCalls(script) {
|
|
26278
|
+
const calls = [];
|
|
26279
|
+
const pattern = /gsap\.(set|to|from|fromTo)\s*\(\s*(["'])([^"']+)\2\s*,\s*\{([^{}]*)\}/g;
|
|
26280
|
+
let match;
|
|
26281
|
+
while ((match = pattern.exec(script)) !== null) {
|
|
26282
|
+
const method = match[1] ?? "set";
|
|
26283
|
+
const selector = match[3] ?? "";
|
|
26284
|
+
const propsBody = match[4] ?? "";
|
|
26285
|
+
const properties = [...propsBody.matchAll(/([A-Za-z_$][\w$]*)\s*:/g)].map((m2) => m2[1] ?? "");
|
|
26286
|
+
calls.push({ method, selector, properties, raw: truncateSnippet(match[0]) ?? match[0] });
|
|
26287
|
+
}
|
|
26288
|
+
return calls;
|
|
26289
|
+
}
|
|
26290
|
+
var SCENE_BOUNDARY_EPSILON_SECONDS, gsapWindowsCache, CONFLICTING_TRANSLATE_PROPS, CONFLICTING_SCALE_PROPS, gsapRules;
|
|
26257
26291
|
var init_gsap = __esm({
|
|
26258
26292
|
"../core/src/lint/rules/gsap.ts"() {
|
|
26259
26293
|
"use strict";
|
|
26260
26294
|
init_utils2();
|
|
26261
26295
|
SCENE_BOUNDARY_EPSILON_SECONDS = 0.05;
|
|
26262
26296
|
gsapWindowsCache = /* @__PURE__ */ new Map();
|
|
26297
|
+
CONFLICTING_TRANSLATE_PROPS = ["x", "y", "xPercent", "yPercent"];
|
|
26298
|
+
CONFLICTING_SCALE_PROPS = ["scale", "scaleX", "scaleY"];
|
|
26263
26299
|
gsapRules = [
|
|
26264
26300
|
// overlapping_gsap_tweens + gsap_animates_clip_element + unscoped_gsap_selector
|
|
26265
26301
|
// fallow-ignore-next-line complexity
|
|
@@ -26413,22 +26449,30 @@ ${right.raw}`)
|
|
|
26413
26449
|
for (const script of scripts) {
|
|
26414
26450
|
if (!/gsap\.timeline/.test(script.content)) continue;
|
|
26415
26451
|
const windows = await cachedExtractGsapWindows(script.content);
|
|
26452
|
+
const calls = [
|
|
26453
|
+
...windows.map((win) => ({
|
|
26454
|
+
method: win.method,
|
|
26455
|
+
selector: win.targetSelector,
|
|
26456
|
+
properties: win.properties,
|
|
26457
|
+
raw: win.raw
|
|
26458
|
+
})),
|
|
26459
|
+
...extractStandaloneGsapTransformCalls(stripJsComments(script.content))
|
|
26460
|
+
];
|
|
26416
26461
|
const conflicts = /* @__PURE__ */ new Map();
|
|
26417
|
-
for (const
|
|
26418
|
-
if (
|
|
26419
|
-
const sel =
|
|
26420
|
-
const
|
|
26421
|
-
|
|
26422
|
-
(p2) => ["x", "y", "xPercent", "yPercent"].includes(p2)
|
|
26462
|
+
for (const call of calls) {
|
|
26463
|
+
if (call.method === "fromTo" || call.method === "from") continue;
|
|
26464
|
+
const sel = call.selector;
|
|
26465
|
+
const translateProps = call.properties.filter(
|
|
26466
|
+
(p2) => CONFLICTING_TRANSLATE_PROPS.includes(p2)
|
|
26423
26467
|
);
|
|
26424
|
-
const scaleProps =
|
|
26425
|
-
const cssFromTranslate = translateProps.length > 0 ? cssTranslateSelectors
|
|
26426
|
-
const cssFromScale = scaleProps.length > 0 ? cssScaleSelectors
|
|
26468
|
+
const scaleProps = call.properties.filter((p2) => CONFLICTING_SCALE_PROPS.includes(p2));
|
|
26469
|
+
const cssFromTranslate = translateProps.length > 0 ? matchCssTransform(sel, cssTranslateSelectors) : void 0;
|
|
26470
|
+
const cssFromScale = scaleProps.length > 0 ? matchCssTransform(sel, cssScaleSelectors) : void 0;
|
|
26427
26471
|
if (!cssFromTranslate && !cssFromScale) continue;
|
|
26428
26472
|
const existing = conflicts.get(sel) ?? {
|
|
26429
26473
|
cssTransform: [cssFromTranslate, cssFromScale].filter(Boolean).join(" "),
|
|
26430
26474
|
props: /* @__PURE__ */ new Set(),
|
|
26431
|
-
raw:
|
|
26475
|
+
raw: call.raw
|
|
26432
26476
|
};
|
|
26433
26477
|
for (const p2 of [...translateProps, ...scaleProps]) existing.props.add(p2);
|
|
26434
26478
|
conflicts.set(sel, existing);
|
|
@@ -26925,6 +26969,35 @@ function isCompositionRootOrMount(rawTag) {
|
|
|
26925
26969
|
readAttr(rawTag, "data-composition-id") || readAttr(rawTag, "data-composition-src")
|
|
26926
26970
|
);
|
|
26927
26971
|
}
|
|
26972
|
+
function extractCssSelectors(css) {
|
|
26973
|
+
const out = [];
|
|
26974
|
+
const noComments = css.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
26975
|
+
const ruleHeader = /([^{}]+)\{/g;
|
|
26976
|
+
let m2;
|
|
26977
|
+
while ((m2 = ruleHeader.exec(noComments)) !== null) {
|
|
26978
|
+
const header = (m2[1] ?? "").trim();
|
|
26979
|
+
if (!header || header.startsWith("@")) continue;
|
|
26980
|
+
for (const sel of header.split(",")) {
|
|
26981
|
+
const s2 = sel.trim();
|
|
26982
|
+
if (s2) out.push(s2);
|
|
26983
|
+
}
|
|
26984
|
+
}
|
|
26985
|
+
return out;
|
|
26986
|
+
}
|
|
26987
|
+
function leftmostCompoundClasses(selector) {
|
|
26988
|
+
const leftmost = selector.trim().split(/[\s>+~]+/)[0] ?? "";
|
|
26989
|
+
return (leftmost.match(/\.([\w-]+)/g) ?? []).map((c3) => c3.slice(1));
|
|
26990
|
+
}
|
|
26991
|
+
function rootClassStyledSelectors(styles, rootClasses) {
|
|
26992
|
+
const offenders = [];
|
|
26993
|
+
for (const style of styles) {
|
|
26994
|
+
for (const selector of extractCssSelectors(style.content)) {
|
|
26995
|
+
const hitsRoot = leftmostCompoundClasses(selector).some((c3) => rootClasses.includes(c3));
|
|
26996
|
+
if (hitsRoot && !offenders.includes(selector)) offenders.push(selector);
|
|
26997
|
+
}
|
|
26998
|
+
}
|
|
26999
|
+
return offenders;
|
|
27000
|
+
}
|
|
26928
27001
|
var MAX_COMPOSITION_LINES, MAX_TIMED_ELEMENTS_PER_TRACK, TRACK_DENSITY_EXEMPT_TAGS, compositionRules;
|
|
26929
27002
|
var init_composition = __esm({
|
|
26930
27003
|
"../core/src/lint/rules/composition.ts"() {
|
|
@@ -27377,6 +27450,39 @@ var init_composition = __esm({
|
|
|
27377
27450
|
});
|
|
27378
27451
|
}
|
|
27379
27452
|
return findings;
|
|
27453
|
+
},
|
|
27454
|
+
// subcomposition_root_styled_by_class
|
|
27455
|
+
// A sub-composition's <style> is scoped at render time to
|
|
27456
|
+
// `[data-composition-id="<id>"] <selector>` so scenes inlined into one document
|
|
27457
|
+
// can't leak styles into each other. A rule whose LEFTMOST selector is the ROOT
|
|
27458
|
+
// element's own class (e.g. `.frame { ... }` on the same element that carries
|
|
27459
|
+
// data-composition-id) therefore becomes a DESCENDANT selector that can never
|
|
27460
|
+
// match the root — the whole scene renders unstyled (tiny text top-left, images
|
|
27461
|
+
// at natural size). lint/validate/inspect evaluate the file in isolation (no
|
|
27462
|
+
// scoping) and Studio previews each scene in its own iframe (no scoping), so the
|
|
27463
|
+
// break is invisible until the composited MP4 render. Style the root via `#root`
|
|
27464
|
+
// (the scoper special-cases the root id) and descendants via plain selectors,
|
|
27465
|
+
// like the registry blocks — the runtime already scopes each scene by id, so a
|
|
27466
|
+
// class namespace on the root is redundant.
|
|
27467
|
+
({ rootTag, rootCompositionId, styles, options }) => {
|
|
27468
|
+
if (!options.isSubComposition) return [];
|
|
27469
|
+
if (isRegistrySourceFile(options.filePath)) return [];
|
|
27470
|
+
if (!rootTag || !rootCompositionId) return [];
|
|
27471
|
+
const rootClasses = (readAttr(rootTag.raw, "class") || "").split(/\s+/).filter(Boolean);
|
|
27472
|
+
if (rootClasses.length === 0) return [];
|
|
27473
|
+
const offenders = rootClassStyledSelectors(styles, rootClasses);
|
|
27474
|
+
if (offenders.length === 0) return [];
|
|
27475
|
+
const example = offenders.slice(0, 3).join(", ");
|
|
27476
|
+
return [
|
|
27477
|
+
{
|
|
27478
|
+
code: "subcomposition_root_styled_by_class",
|
|
27479
|
+
severity: "error",
|
|
27480
|
+
message: `Root element has class="${rootClasses.join(" ")}" and is styled by ${offenders.length} rule(s) keyed off that class (e.g. ${example}). At render, every sub-composition rule is scoped to [data-composition-id="${rootCompositionId}"] <selector>, so a selector whose leftmost part is the ROOT's own class becomes a descendant selector that cannot match the root \u2014 the scene renders unstyled (tiny text top-left, full-size images). lint/validate/inspect and Studio's per-frame iframe preview do not scope, so this passes every static check and looks correct in preview.`,
|
|
27481
|
+
selector: example,
|
|
27482
|
+
fixHint: `Give the root id="root" and style it with \`#root { ... }\` plus plain descendant selectors (\`.kicker\`, \`#hero\`) \u2014 the runtime already scopes each sub-composition by data-composition-id, so a class namespace on the root is redundant and breaks under scoping.`,
|
|
27483
|
+
snippet: truncateSnippet(rootTag.raw)
|
|
27484
|
+
}
|
|
27485
|
+
];
|
|
27380
27486
|
}
|
|
27381
27487
|
];
|
|
27382
27488
|
}
|
|
@@ -33175,11 +33281,10 @@ async function pageScreenshotCapture(page, options) {
|
|
|
33175
33281
|
format: isPng ? "png" : "jpeg",
|
|
33176
33282
|
quality: isPng ? void 0 : options.quality ?? 80,
|
|
33177
33283
|
fromSurface: true,
|
|
33178
|
-
//
|
|
33179
|
-
//
|
|
33180
|
-
//
|
|
33181
|
-
|
|
33182
|
-
captureBeyondViewport: true,
|
|
33284
|
+
// Use Chrome's faster viewport-bound screenshot path by default. Callers
|
|
33285
|
+
// opt into the beyond-viewport path only for known compositor edge cases,
|
|
33286
|
+
// such as native video surfaces in tall portrait renders.
|
|
33287
|
+
captureBeyondViewport: options.captureBeyondViewport ?? false,
|
|
33183
33288
|
optimizeForSpeed: !isPng,
|
|
33184
33289
|
clip
|
|
33185
33290
|
});
|
|
@@ -33194,8 +33299,8 @@ async function captureScreenshotWithAlpha(page, width, height) {
|
|
|
33194
33299
|
const result = await client.send("Page.captureScreenshot", {
|
|
33195
33300
|
format: "png",
|
|
33196
33301
|
fromSurface: true,
|
|
33302
|
+
// Preserve the #1094 tall-portrait edge-clipping guard on HDR alpha captures.
|
|
33197
33303
|
captureBeyondViewport: true,
|
|
33198
|
-
// see pageScreenshotCapture for rationale
|
|
33199
33304
|
optimizeForSpeed: false,
|
|
33200
33305
|
// `true` uses a zero-alpha-aware fast path that crushes real alpha values — observed empirically, CDP docs don't spell it out
|
|
33201
33306
|
clip: { x: 0, y: 0, width, height, scale: 1 }
|
|
@@ -33224,8 +33329,8 @@ async function captureAlphaPng(page, width, height) {
|
|
|
33224
33329
|
const result = await client.send("Page.captureScreenshot", {
|
|
33225
33330
|
format: "png",
|
|
33226
33331
|
fromSurface: true,
|
|
33332
|
+
// Preserve the #1094 tall-portrait edge-clipping guard on HDR alpha captures.
|
|
33227
33333
|
captureBeyondViewport: true,
|
|
33228
|
-
// see pageScreenshotCapture for rationale
|
|
33229
33334
|
optimizeForSpeed: false,
|
|
33230
33335
|
// must be false to preserve alpha
|
|
33231
33336
|
clip: { x: 0, y: 0, width, height, scale: 1 }
|
|
@@ -37049,21 +37154,6 @@ function defaultBuildScopeSelector(compId) {
|
|
|
37049
37154
|
const escaped = compId.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
37050
37155
|
return `[data-composition-id="${escaped}"]`;
|
|
37051
37156
|
}
|
|
37052
|
-
function emptyCompositionHtmlError(src) {
|
|
37053
|
-
return new Error(
|
|
37054
|
-
`Composition HTML is empty or could not be parsed: ${src}. Check that the file referenced by data-composition-src contains valid HTML.`
|
|
37055
|
-
);
|
|
37056
|
-
}
|
|
37057
|
-
function assertNonEmptyCompositionHtml(html, src) {
|
|
37058
|
-
if (!html.trim()) {
|
|
37059
|
-
throw emptyCompositionHtmlError(src);
|
|
37060
|
-
}
|
|
37061
|
-
}
|
|
37062
|
-
function assertParsedCompositionDocument(doc, src) {
|
|
37063
|
-
if (!doc.documentElement) {
|
|
37064
|
-
throw emptyCompositionHtmlError(src);
|
|
37065
|
-
}
|
|
37066
|
-
}
|
|
37067
37157
|
function inlineSubCompositions(document2, hosts, options) {
|
|
37068
37158
|
const {
|
|
37069
37159
|
resolveHtml,
|
|
@@ -37089,15 +37179,15 @@ function inlineSubCompositions(document2, hosts, options) {
|
|
|
37089
37179
|
const src = hostEl.getAttribute("data-composition-src");
|
|
37090
37180
|
if (!src) continue;
|
|
37091
37181
|
const compHtml = resolveHtml(src);
|
|
37092
|
-
if (compHtml == null) {
|
|
37093
|
-
|
|
37094
|
-
onMissingComposition(src);
|
|
37095
|
-
}
|
|
37182
|
+
if (compHtml == null || !compHtml.trim()) {
|
|
37183
|
+
onMissingComposition?.(src);
|
|
37096
37184
|
continue;
|
|
37097
37185
|
}
|
|
37098
|
-
assertNonEmptyCompositionHtml(compHtml, src);
|
|
37099
37186
|
const compDoc = parseHtml2(compHtml);
|
|
37100
|
-
|
|
37187
|
+
if (!compDoc.documentElement) {
|
|
37188
|
+
onMissingComposition?.(src);
|
|
37189
|
+
continue;
|
|
37190
|
+
}
|
|
37101
37191
|
let compId;
|
|
37102
37192
|
let runtimeCompId;
|
|
37103
37193
|
if (hostIdentityMap) {
|
|
@@ -37110,9 +37200,15 @@ function inlineSubCompositions(document2, hosts, options) {
|
|
|
37110
37200
|
}
|
|
37111
37201
|
const contentRoot = compDoc.querySelector("template");
|
|
37112
37202
|
const contentHtml = contentRoot ? contentRoot.innerHTML || "" : compDoc.body?.innerHTML || "";
|
|
37113
|
-
|
|
37203
|
+
if (!contentHtml.trim()) {
|
|
37204
|
+
onMissingComposition?.(src);
|
|
37205
|
+
continue;
|
|
37206
|
+
}
|
|
37114
37207
|
const contentDoc = parseHtml2(contentHtml);
|
|
37115
|
-
|
|
37208
|
+
if (!contentDoc.documentElement) {
|
|
37209
|
+
onMissingComposition?.(src);
|
|
37210
|
+
continue;
|
|
37211
|
+
}
|
|
37116
37212
|
const innerRoot = compId ? queryByAttr(contentDoc, "data-composition-id", compId) : contentDoc.querySelector("[data-composition-id]");
|
|
37117
37213
|
const inferredCompId = innerRoot?.getAttribute("data-composition-id")?.trim() || "";
|
|
37118
37214
|
const authoredRootId = innerRoot?.getAttribute("id")?.trim() || null;
|
|
@@ -45203,6 +45299,7 @@ __export(manager_exports, {
|
|
|
45203
45299
|
ensureModel: () => ensureModel,
|
|
45204
45300
|
ensureWhisper: () => ensureWhisper,
|
|
45205
45301
|
findWhisper: () => findWhisper,
|
|
45302
|
+
getInstallInstructions: () => getInstallInstructions,
|
|
45206
45303
|
hasFFmpeg: () => hasFFmpeg,
|
|
45207
45304
|
isWhisperUnavailable: () => isWhisperUnavailable
|
|
45208
45305
|
});
|
|
@@ -45309,6 +45406,12 @@ function getInstallInstructions() {
|
|
|
45309
45406
|
if (platform4() === "darwin") {
|
|
45310
45407
|
return "brew install whisper-cpp";
|
|
45311
45408
|
}
|
|
45409
|
+
if (platform4() === "linux") {
|
|
45410
|
+
return "Build from source: https://github.com/ggml-org/whisper.cpp#building (requires cmake and a C compiler)";
|
|
45411
|
+
}
|
|
45412
|
+
if (platform4() === "win32") {
|
|
45413
|
+
return "Build with cmake: https://github.com/ggml-org/whisper.cpp#building";
|
|
45414
|
+
}
|
|
45312
45415
|
return "See https://github.com/ggml-org/whisper.cpp#building";
|
|
45313
45416
|
}
|
|
45314
45417
|
function hasBrew() {
|
|
@@ -45910,7 +46013,8 @@ var init_npxCommand = __esm({
|
|
|
45910
46013
|
// src/commands/skills.ts
|
|
45911
46014
|
var skills_exports = {};
|
|
45912
46015
|
__export(skills_exports, {
|
|
45913
|
-
default: () => skills_default
|
|
46016
|
+
default: () => skills_default,
|
|
46017
|
+
installAllSkills: () => installAllSkills
|
|
45914
46018
|
});
|
|
45915
46019
|
import { execFileSync as execFileSync4, spawn as spawn7 } from "child_process";
|
|
45916
46020
|
function hasNpx() {
|
|
@@ -45922,12 +46026,13 @@ function hasNpx() {
|
|
|
45922
46026
|
return false;
|
|
45923
46027
|
}
|
|
45924
46028
|
}
|
|
45925
|
-
function runSkillsAdd(repo) {
|
|
45926
|
-
const npx = buildNpxCommand(["skills", "add", repo, "--all"]);
|
|
46029
|
+
function runSkillsAdd(repo, opts = {}) {
|
|
46030
|
+
const npx = buildNpxCommand(["skills", "add", repo, ...opts.extraArgs ?? ["--all"]]);
|
|
45927
46031
|
return new Promise((resolve58, reject) => {
|
|
45928
46032
|
const child = spawn7(npx.command, npx.args, {
|
|
45929
46033
|
stdio: "inherit",
|
|
45930
46034
|
timeout: 12e4,
|
|
46035
|
+
cwd: opts.cwd,
|
|
45931
46036
|
// GH #316 — the upstream `skills` CLI shells out to `git clone`.
|
|
45932
46037
|
// When Git's clone-hook protection is active (shipped on by
|
|
45933
46038
|
// default in 2.45.1, reverted in 2.45.2, still present on many
|
|
@@ -45945,6 +46050,22 @@ function runSkillsAdd(repo) {
|
|
|
45945
46050
|
child.on("error", reject);
|
|
45946
46051
|
});
|
|
45947
46052
|
}
|
|
46053
|
+
async function installAllSkills(opts = {}) {
|
|
46054
|
+
if (!hasNpx()) {
|
|
46055
|
+
R2.error(c.error("npx not found. Install Node.js and retry."));
|
|
46056
|
+
return;
|
|
46057
|
+
}
|
|
46058
|
+
for (const source of SOURCES) {
|
|
46059
|
+
console.log();
|
|
46060
|
+
console.log(c.bold(`Installing ${source.name} skills...`));
|
|
46061
|
+
console.log();
|
|
46062
|
+
try {
|
|
46063
|
+
await runSkillsAdd(source.repo, opts);
|
|
46064
|
+
} catch {
|
|
46065
|
+
console.log(c.dim(`${source.name} skills skipped`));
|
|
46066
|
+
}
|
|
46067
|
+
}
|
|
46068
|
+
}
|
|
45948
46069
|
var SOURCES, skills_default;
|
|
45949
46070
|
var init_skills = __esm({
|
|
45950
46071
|
"src/commands/skills.ts"() {
|
|
@@ -45961,20 +46082,7 @@ var init_skills = __esm({
|
|
|
45961
46082
|
},
|
|
45962
46083
|
args: {},
|
|
45963
46084
|
async run() {
|
|
45964
|
-
|
|
45965
|
-
R2.error(c.error("npx not found. Install Node.js and retry."));
|
|
45966
|
-
return;
|
|
45967
|
-
}
|
|
45968
|
-
for (const source of SOURCES) {
|
|
45969
|
-
console.log();
|
|
45970
|
-
console.log(c.bold(`Installing ${source.name} skills...`));
|
|
45971
|
-
console.log();
|
|
45972
|
-
try {
|
|
45973
|
-
await runSkillsAdd(source.repo);
|
|
45974
|
-
} catch {
|
|
45975
|
-
console.log(c.dim(`${source.name} skills skipped`));
|
|
45976
|
-
}
|
|
45977
|
-
}
|
|
46085
|
+
await installAllSkills();
|
|
45978
46086
|
}
|
|
45979
46087
|
});
|
|
45980
46088
|
}
|
|
@@ -46171,7 +46279,16 @@ async function lintProject(project) {
|
|
|
46171
46279
|
const allHtmlSources = [{ html: rootHtml }];
|
|
46172
46280
|
const compositionsDir = resolve12(project.dir, "compositions");
|
|
46173
46281
|
if (existsSync22(compositionsDir)) {
|
|
46174
|
-
const
|
|
46282
|
+
const collectHtmlFiles = (dir, rel) => {
|
|
46283
|
+
const out = [];
|
|
46284
|
+
for (const entry of readdirSync8(dir, { withFileTypes: true })) {
|
|
46285
|
+
const relPath = rel ? `${rel}/${entry.name}` : entry.name;
|
|
46286
|
+
if (entry.isDirectory()) out.push(...collectHtmlFiles(join21(dir, entry.name), relPath));
|
|
46287
|
+
else if (entry.isFile() && entry.name.endsWith(".html")) out.push(relPath);
|
|
46288
|
+
}
|
|
46289
|
+
return out;
|
|
46290
|
+
};
|
|
46291
|
+
const files = collectHtmlFiles(compositionsDir, "").sort();
|
|
46175
46292
|
for (const file of files) {
|
|
46176
46293
|
const filePath = join21(compositionsDir, file);
|
|
46177
46294
|
const html = readFileSync15(filePath, "utf-8");
|
|
@@ -93728,7 +93845,16 @@ var init_fileServer2 = __esm({
|
|
|
93728
93845
|
var root = document.querySelector('[data-composition-id]');
|
|
93729
93846
|
if (!root) return 0;
|
|
93730
93847
|
var d = Number(root.getAttribute('data-duration'));
|
|
93731
|
-
|
|
93848
|
+
if (Number.isFinite(d) && d > 0) return d;
|
|
93849
|
+
var comps = document.querySelectorAll('[data-composition-src]');
|
|
93850
|
+
var maxEnd = 0;
|
|
93851
|
+
for (var i = 0; i < comps.length; i++) {
|
|
93852
|
+
var start = Number(comps[i].getAttribute('data-start')) || 0;
|
|
93853
|
+
var dur = Number(comps[i].getAttribute('data-duration')) || 0;
|
|
93854
|
+
if (dur > 0) maxEnd = Math.max(maxEnd, start + dur);
|
|
93855
|
+
}
|
|
93856
|
+
if (maxEnd > 0) console.warn('[HF Bridge] No root data-duration; derived ' + maxEnd + 's from sub-compositions');
|
|
93857
|
+
return maxEnd;
|
|
93732
93858
|
}
|
|
93733
93859
|
function seekSameOriginChildFrames(frameWindow, nextTimeMs) {
|
|
93734
93860
|
var frames;
|
|
@@ -95272,7 +95398,10 @@ function inlineSubCompositions2(html, subCompositions, projectDir) {
|
|
|
95272
95398
|
},
|
|
95273
95399
|
parseHtml: (htmlStr) => parseHTML(htmlStr).document,
|
|
95274
95400
|
scriptErrorLabel: "[Compiler] Composition script failed",
|
|
95275
|
-
compoundAuthoredRoot: true
|
|
95401
|
+
compoundAuthoredRoot: true,
|
|
95402
|
+
onMissingComposition: (srcPath) => {
|
|
95403
|
+
console.warn(`[Compiler] Composition file missing or empty: ${srcPath}`);
|
|
95404
|
+
}
|
|
95276
95405
|
}
|
|
95277
95406
|
);
|
|
95278
95407
|
for (const hostEl of hosts) {
|
|
@@ -99550,6 +99679,12 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
99550
99679
|
job.startedAt = /* @__PURE__ */ new Date();
|
|
99551
99680
|
assertNotAborted();
|
|
99552
99681
|
assertConfiguredFfmpegBinariesExist();
|
|
99682
|
+
if (!existsSync45(workDir)) mkdirSync26(workDir, { recursive: true });
|
|
99683
|
+
if (job.config.debug) {
|
|
99684
|
+
const logPath = join55(workDir, "render.log");
|
|
99685
|
+
restoreLogger = installDebugLogger(logPath, log2);
|
|
99686
|
+
log2.info("[Render] Debug artifacts enabled", { workDir, logPath });
|
|
99687
|
+
}
|
|
99553
99688
|
log2.info("[Render] Pipeline started", {
|
|
99554
99689
|
platform: process.platform,
|
|
99555
99690
|
arch: process.arch,
|
|
@@ -99574,11 +99709,6 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
99574
99709
|
playerReadyTimeoutMs: cfg.playerReadyTimeout,
|
|
99575
99710
|
requestedWorkers: job.config.workers ?? "auto"
|
|
99576
99711
|
});
|
|
99577
|
-
if (!existsSync45(workDir)) mkdirSync26(workDir, { recursive: true });
|
|
99578
|
-
if (job.config.debug) {
|
|
99579
|
-
const logPath = join55(workDir, "render.log");
|
|
99580
|
-
restoreLogger = installDebugLogger(logPath, log2);
|
|
99581
|
-
}
|
|
99582
99712
|
const entryFile = job.config.entryFile || "index.html";
|
|
99583
99713
|
let htmlPath = join55(projectDir, entryFile);
|
|
99584
99714
|
if (!existsSync45(htmlPath)) {
|
|
@@ -99796,8 +99926,12 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
99796
99926
|
format: needsAlpha ? "png" : "jpeg",
|
|
99797
99927
|
quality: needsAlpha ? void 0 : job.config.quality === "draft" ? 80 : 95,
|
|
99798
99928
|
variables: job.config.variables,
|
|
99799
|
-
deviceScaleFactor
|
|
99929
|
+
deviceScaleFactor,
|
|
99930
|
+
captureBeyondViewport: composition.videos.length > 0
|
|
99800
99931
|
};
|
|
99932
|
+
updateCaptureObservability({
|
|
99933
|
+
captureBeyondViewport: captureOptions.captureBeyondViewport ?? false
|
|
99934
|
+
});
|
|
99801
99935
|
const buildCaptureOptions = () => ({
|
|
99802
99936
|
...captureOptions,
|
|
99803
99937
|
videoMetadataHints,
|
|
@@ -99926,6 +100060,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
99926
100060
|
observability.checkpoint("capture_strategy", "resolved", {
|
|
99927
100061
|
workerCount,
|
|
99928
100062
|
forceScreenshot: captureForceScreenshot,
|
|
100063
|
+
captureBeyondViewport: captureOptions.captureBeyondViewport ?? false,
|
|
99929
100064
|
useStreamingEncode,
|
|
99930
100065
|
useLayeredComposite,
|
|
99931
100066
|
usePageSideCompositing: usePageSideCompositingForTransitions,
|
|
@@ -102036,6 +102171,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
102036
102171
|
// declare `data-composition-variables` leave this undefined and the
|
|
102037
102172
|
// engine skips the `evaluateOnNewDocument` injection.
|
|
102038
102173
|
variables: encoder.variables,
|
|
102174
|
+
captureBeyondViewport: (planVideos?.videos.length ?? 0) > 0,
|
|
102039
102175
|
// lock the BeginFrame warmup loop to a fixed iteration count so
|
|
102040
102176
|
// `beginFrameTimeTicks` is host-independent. Only chunks ever set this.
|
|
102041
102177
|
lockWarmupTicks: true
|
|
@@ -104527,11 +104663,22 @@ var init_init = __esm({
|
|
|
104527
104663
|
for (const f3 of readdirSync23(destDir2).filter((f4) => !f4.startsWith("."))) {
|
|
104528
104664
|
console.log(` ${c.accent(f3)}`);
|
|
104529
104665
|
}
|
|
104666
|
+
if (!skipSkills) {
|
|
104667
|
+
const { installAllSkills: installAllSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
|
|
104668
|
+
const args2 = process.env["CLAUDECODE"] ? ["--agent", "claude-code", "--yes"] : ["--yes"];
|
|
104669
|
+
await installAllSkills2({ cwd: destDir2, extraArgs: args2 });
|
|
104670
|
+
}
|
|
104530
104671
|
console.log();
|
|
104531
104672
|
console.log("Get started:");
|
|
104532
104673
|
console.log();
|
|
104533
|
-
|
|
104534
|
-
|
|
104674
|
+
if (skipSkills) {
|
|
104675
|
+
console.log(` ${c.accent("1.")} Install AI coding skills (one-time):`);
|
|
104676
|
+
console.log(` ${c.accent("npx skills add heygen-com/hyperframes --yes")}`);
|
|
104677
|
+
} else {
|
|
104678
|
+
console.log(
|
|
104679
|
+
` ${c.accent("1.")} Restart your AI agent (new session) so it loads the skills.`
|
|
104680
|
+
);
|
|
104681
|
+
}
|
|
104535
104682
|
console.log();
|
|
104536
104683
|
console.log(` ${c.accent("2.")} Open this project with your AI coding agent:`);
|
|
104537
104684
|
console.log(
|
|
@@ -104718,8 +104865,8 @@ ${c.dim("Use --example blank for offline use.")}`
|
|
|
104718
104865
|
process.exit(0);
|
|
104719
104866
|
}
|
|
104720
104867
|
if (installSkills) {
|
|
104721
|
-
const
|
|
104722
|
-
await
|
|
104868
|
+
const { installAllSkills: installAllSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
|
|
104869
|
+
await installAllSkills2({ cwd: destDir });
|
|
104723
104870
|
}
|
|
104724
104871
|
}
|
|
104725
104872
|
R2.info("Opening studio preview...");
|
|
@@ -106649,6 +106796,10 @@ function buildDockerRunArgs(input2) {
|
|
|
106649
106796
|
`${projectDir}:/project:ro`,
|
|
106650
106797
|
"-v",
|
|
106651
106798
|
`${outputDir}:/output`,
|
|
106799
|
+
// Keep debug artifacts on the mounted host output path. The producer roots
|
|
106800
|
+
// `.debug` at dirname(PRODUCER_RENDERS_DIR), so `/output/renders` maps to
|
|
106801
|
+
// `/output/.debug/<job id>` instead of a disposable container path.
|
|
106802
|
+
...options.debug ? ["-e", "PRODUCER_RENDERS_DIR=/output/renders"] : [],
|
|
106652
106803
|
imageTag,
|
|
106653
106804
|
"/project",
|
|
106654
106805
|
"--output",
|
|
@@ -106666,6 +106817,7 @@ function buildDockerRunArgs(input2) {
|
|
|
106666
106817
|
...options.videoBitrate ? ["--video-bitrate", options.videoBitrate] : [],
|
|
106667
106818
|
...options.videoFrameFormat && options.videoFrameFormat !== "auto" ? ["--video-frame-format", options.videoFrameFormat] : [],
|
|
106668
106819
|
...options.quiet ? ["--quiet"] : [],
|
|
106820
|
+
...options.debug ? ["--debug"] : [],
|
|
106669
106821
|
...options.gpu ? ["--gpu"] : [],
|
|
106670
106822
|
...options.browserGpu ? [] : ["--no-browser-gpu"],
|
|
106671
106823
|
...options.hdrMode === "force-hdr" ? ["--hdr"] : [],
|
|
@@ -107413,6 +107565,7 @@ async function renderDocker(projectDir, outputPath, options) {
|
|
|
107413
107565
|
entryFile: options.entryFile,
|
|
107414
107566
|
outputResolution: options.outputResolution,
|
|
107415
107567
|
pageSideCompositing: options.pageSideCompositing,
|
|
107568
|
+
debug: options.debug,
|
|
107416
107569
|
pageNavigationTimeoutMs: options.pageNavigationTimeoutMs
|
|
107417
107570
|
}
|
|
107418
107571
|
});
|
|
@@ -107480,7 +107633,7 @@ async function renderLocal(projectDir, outputPath, options) {
|
|
|
107480
107633
|
const producer = await loadProducer();
|
|
107481
107634
|
const startTime = Date.now();
|
|
107482
107635
|
const logger = createRenderTelemetryLogger(
|
|
107483
|
-
producer.createConsoleLogger?.("info") ?? createNoopProducerLogger()
|
|
107636
|
+
producer.createConsoleLogger?.(options.debug ? "debug" : "info") ?? createNoopProducerLogger()
|
|
107484
107637
|
);
|
|
107485
107638
|
const job = producer.createRenderJob({
|
|
107486
107639
|
fps: options.fps,
|
|
@@ -107503,7 +107656,8 @@ async function renderLocal(projectDir, outputPath, options) {
|
|
|
107503
107656
|
videoFrameFormat: options.videoFrameFormat,
|
|
107504
107657
|
variables: options.variables,
|
|
107505
107658
|
entryFile: options.entryFile,
|
|
107506
|
-
outputResolution: options.outputResolution
|
|
107659
|
+
outputResolution: options.outputResolution,
|
|
107660
|
+
debug: options.debug
|
|
107507
107661
|
});
|
|
107508
107662
|
const onProgress = options.quiet ? void 0 : (progressJob, message) => {
|
|
107509
107663
|
renderProgress(progressJob.progress, message);
|
|
@@ -107882,6 +108036,11 @@ var init_render2 = __esm({
|
|
|
107882
108036
|
description: "Suppress verbose output",
|
|
107883
108037
|
default: false
|
|
107884
108038
|
},
|
|
108039
|
+
debug: {
|
|
108040
|
+
type: "boolean",
|
|
108041
|
+
description: "Write full render diagnostics and keep intermediate artifacts under the producer .debug directory.",
|
|
108042
|
+
default: false
|
|
108043
|
+
},
|
|
107885
108044
|
strict: {
|
|
107886
108045
|
type: "boolean",
|
|
107887
108046
|
description: "Fail render on lint errors",
|
|
@@ -108109,6 +108268,7 @@ var init_render2 = __esm({
|
|
|
108109
108268
|
const browserGpuArg = args["browser-gpu"];
|
|
108110
108269
|
const browserGpuMode = resolveBrowserGpuForCli(useDocker, browserGpuArg);
|
|
108111
108270
|
const quiet = args.quiet ?? false;
|
|
108271
|
+
const debug = args.debug ?? false;
|
|
108112
108272
|
const batchJson = args.json ?? false;
|
|
108113
108273
|
const effectiveQuiet = quiet || batchPath != null && batchJson;
|
|
108114
108274
|
const strictAll = args["strict-all"] ?? false;
|
|
@@ -108280,6 +108440,7 @@ var init_render2 = __esm({
|
|
|
108280
108440
|
pageNavigationTimeoutMs,
|
|
108281
108441
|
protocolTimeout,
|
|
108282
108442
|
playerReadyTimeout,
|
|
108443
|
+
debug,
|
|
108283
108444
|
exitAfterComplete: false,
|
|
108284
108445
|
throwOnError: true,
|
|
108285
108446
|
skipFeedback: true
|
|
@@ -108323,6 +108484,7 @@ var init_render2 = __esm({
|
|
|
108323
108484
|
videoBitrate,
|
|
108324
108485
|
videoFrameFormat,
|
|
108325
108486
|
quiet,
|
|
108487
|
+
debug,
|
|
108326
108488
|
variables,
|
|
108327
108489
|
entryFile,
|
|
108328
108490
|
outputResolution,
|
|
@@ -108348,6 +108510,7 @@ var init_render2 = __esm({
|
|
|
108348
108510
|
videoFrameFormat,
|
|
108349
108511
|
quiet,
|
|
108350
108512
|
browserPath,
|
|
108513
|
+
debug,
|
|
108351
108514
|
variables,
|
|
108352
108515
|
entryFile,
|
|
108353
108516
|
outputResolution,
|
|
@@ -112167,6 +112330,18 @@ function checkEnvironment() {
|
|
|
112167
112330
|
}
|
|
112168
112331
|
return { ok: true, detail: parts.join(" \xB7 ") };
|
|
112169
112332
|
}
|
|
112333
|
+
async function checkWhisper() {
|
|
112334
|
+
const { findWhisper: findWhisper2, getInstallInstructions: getInstallInstructions2 } = await Promise.resolve().then(() => (init_manager(), manager_exports));
|
|
112335
|
+
const result = findWhisper2();
|
|
112336
|
+
if (result) {
|
|
112337
|
+
return { ok: true, detail: result.executablePath };
|
|
112338
|
+
}
|
|
112339
|
+
return {
|
|
112340
|
+
ok: false,
|
|
112341
|
+
detail: "Not found (optional \u2014 needed for transcription)",
|
|
112342
|
+
hint: getInstallInstructions2()
|
|
112343
|
+
};
|
|
112344
|
+
}
|
|
112170
112345
|
function redactHome(s2) {
|
|
112171
112346
|
const home = process.env["HOME"] || process.env["USERPROFILE"];
|
|
112172
112347
|
if (!home) return s2;
|
|
@@ -112221,6 +112396,7 @@ var init_doctor = __esm({
|
|
|
112221
112396
|
checks.push({ name: "/dev/shm", run: checkShm });
|
|
112222
112397
|
}
|
|
112223
112398
|
checks.push({ name: "Environment", run: checkEnvironment });
|
|
112399
|
+
checks.push({ name: "whisper-cpp", run: checkWhisper });
|
|
112224
112400
|
const outcomes = [];
|
|
112225
112401
|
for (const check of checks) {
|
|
112226
112402
|
const result = await check.run();
|
|
@@ -112541,6 +112717,58 @@ Run ${c.accent("hyperframes telemetry --help")} for usage.`
|
|
|
112541
112717
|
}
|
|
112542
112718
|
});
|
|
112543
112719
|
|
|
112720
|
+
// src/commands/events.ts
|
|
112721
|
+
var events_exports2 = {};
|
|
112722
|
+
__export(events_exports2, {
|
|
112723
|
+
default: () => events_default
|
|
112724
|
+
});
|
|
112725
|
+
var ALLOWED_EVENTS, ALLOWED_OUTCOMES, SKILL_SLUG, events_default;
|
|
112726
|
+
var init_events2 = __esm({
|
|
112727
|
+
"src/commands/events.ts"() {
|
|
112728
|
+
"use strict";
|
|
112729
|
+
init_dist();
|
|
112730
|
+
init_client();
|
|
112731
|
+
ALLOWED_EVENTS = ["skill_invoked", "skill_completed"];
|
|
112732
|
+
ALLOWED_OUTCOMES = ["success", "error", "abort"];
|
|
112733
|
+
SKILL_SLUG = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
112734
|
+
events_default = defineCommand({
|
|
112735
|
+
meta: {
|
|
112736
|
+
name: "events",
|
|
112737
|
+
description: "Emit an anonymous skill-usage telemetry event (skills report their own invocation/outcome). Honors DO_NOT_TRACK / telemetry opt-out."
|
|
112738
|
+
},
|
|
112739
|
+
args: {
|
|
112740
|
+
skill: {
|
|
112741
|
+
type: "string",
|
|
112742
|
+
description: "Authoring skill slug, e.g. product-launch-video"
|
|
112743
|
+
},
|
|
112744
|
+
event: {
|
|
112745
|
+
type: "string",
|
|
112746
|
+
description: "Event name: skill_invoked | skill_completed (default: skill_invoked)",
|
|
112747
|
+
default: "skill_invoked"
|
|
112748
|
+
},
|
|
112749
|
+
outcome: {
|
|
112750
|
+
type: "string",
|
|
112751
|
+
description: "Optional outcome for completion events: success | error | abort"
|
|
112752
|
+
}
|
|
112753
|
+
},
|
|
112754
|
+
async run({ args }) {
|
|
112755
|
+
try {
|
|
112756
|
+
const skill = typeof args.skill === "string" ? args.skill.trim() : "";
|
|
112757
|
+
if (!SKILL_SLUG.test(skill)) return;
|
|
112758
|
+
const event = ALLOWED_EVENTS.includes(args.event) ? args.event : "skill_invoked";
|
|
112759
|
+
const props = { authoring_skill: skill };
|
|
112760
|
+
if (args.outcome && ALLOWED_OUTCOMES.includes(args.outcome)) {
|
|
112761
|
+
props["outcome"] = args.outcome;
|
|
112762
|
+
}
|
|
112763
|
+
trackEvent(event, props);
|
|
112764
|
+
await flush();
|
|
112765
|
+
} catch {
|
|
112766
|
+
}
|
|
112767
|
+
}
|
|
112768
|
+
});
|
|
112769
|
+
}
|
|
112770
|
+
});
|
|
112771
|
+
|
|
112544
112772
|
// src/utils/compositionViewport.ts
|
|
112545
112773
|
function parseViewportDimension(value) {
|
|
112546
112774
|
if (!value) return null;
|
|
@@ -162861,6 +163089,7 @@ var commandLoaders = {
|
|
|
162861
163089
|
skills: () => Promise.resolve().then(() => (init_skills(), skills_exports)).then((m2) => m2.default),
|
|
162862
163090
|
feedback: () => Promise.resolve().then(() => (init_feedback2(), feedback_exports)).then((m2) => m2.default),
|
|
162863
163091
|
telemetry: () => Promise.resolve().then(() => (init_telemetry(), telemetry_exports)).then((m2) => m2.default),
|
|
163092
|
+
events: () => Promise.resolve().then(() => (init_events2(), events_exports2)).then((m2) => m2.default),
|
|
162864
163093
|
validate: () => Promise.resolve().then(() => (init_validate(), validate_exports)).then((m2) => m2.default),
|
|
162865
163094
|
snapshot: () => Promise.resolve().then(() => (init_snapshot(), snapshot_exports)).then((m2) => m2.default),
|
|
162866
163095
|
capture: () => Promise.resolve().then(() => (init_capture2(), capture_exports2)).then((m2) => m2.default),
|
|
@@ -162891,7 +163120,7 @@ var _flushSync;
|
|
|
162891
163120
|
var _trackCliError;
|
|
162892
163121
|
var _trackCommandResult;
|
|
162893
163122
|
var _printUpdateNotice;
|
|
162894
|
-
if (!isHelp && command !== "telemetry" && command !== "unknown") {
|
|
163123
|
+
if (!isHelp && command !== "telemetry" && command !== "events" && command !== "unknown") {
|
|
162895
163124
|
Promise.resolve().then(() => (init_telemetry2(), telemetry_exports2)).then((mod) => {
|
|
162896
163125
|
_flush = mod.flush;
|
|
162897
163126
|
_flushSync = mod.flushSync;
|
|
@@ -162902,7 +163131,7 @@ if (!isHelp && command !== "telemetry" && command !== "unknown") {
|
|
|
162902
163131
|
if (mod.shouldTrack()) mod.incrementCommandCount();
|
|
162903
163132
|
});
|
|
162904
163133
|
}
|
|
162905
|
-
if (!isHelp && !hasJsonFlag && command !== "upgrade") {
|
|
163134
|
+
if (!isHelp && !hasJsonFlag && command !== "upgrade" && command !== "events") {
|
|
162906
163135
|
Promise.resolve().then(() => (init_autoUpdate(), autoUpdate_exports)).then((mod) => mod.reportCompletedUpdate()).catch(() => {
|
|
162907
163136
|
});
|
|
162908
163137
|
Promise.resolve().then(() => (init_updateCheck(), updateCheck_exports)).then(async (mod) => {
|