Setting the file. One moment.
Recipe · Media Use · heygen-com/hyperframes · Skills Docs
ContentsBack to the top of the page ⋯
scripts/11 files
(opens in a new tab)
scripts/ recipe.mjs
JavaScript · 103 lines · 4 KB
15 * Two-tier merged listing (project wins), newest approval first.
16 *
17 * node recipe.mjs use --hyperframes . --name <n> [--json]
18 * Adopt a recipe: import it from the user tier if needed, copy its
19 * frame.md over the project's, and print the brief values + skeleton path.
20 *
21 * When recipes are offered/consumed is the review loop's and the intent
22 * layer's business — see hyperframes/references/review-loop.md § 4 and
23 * the intent layer's recipe check (hyperframes SKILL.md § 4).
24 */
25 import { parseArgs } from "node:util" ;
26 import { freezeRecipe, listRecipes, useRecipe } from "./lib/recipe-store.mjs" ;
27
28 const { values : args , positionals } = parseArgs ({
29 options: {
30 hyperframes: { type: "string" , default: "." },
31 name: { type: "string" },
32 workflow: { type: "string" },
33 blocks: { type: "string" },
34 json: { type: "boolean" , default: false },
35 },
36 allowPositionals: true ,
37 });
38
39 const verb = positionals[ 0 ];
40
41 function fail ( message ) {
42 console. error (message);
43 process. exit ( 1 );
44 }
45
46 try {
47 if (verb === "freeze" ) {
48 if ( ! args.name) fail ( "freeze needs --name" );
49 const frozen = freezeRecipe ({
50 projectDir: args.hyperframes,
51 name: args.name,
52 workflow: args.workflow,
53 blocks: args.blocks
54 ? args.blocks
55 . split ( "," )
56 . map (( b ) => b. trim ())
57 . filter (Boolean)
58 : undefined ,
59 });
60 if (args.json) console. log ( JSON . stringify ({ ok: true , ... frozen }));
61 else {
62 console. log (
63 `froze recipe ${ frozen . slug } (v${ frozen . version }, ${ frozen . workflow }) → ${ frozen . dir }` ,
64 );
65 if (frozen.workflowOverridden)
66 console. log ( ` (BRIEF.md says "${ frozen . workflow }" — the --workflow flag was ignored)` );
67 if ( ! frozen.briefSkeleton)
68 console. log ( " (no BRIEF.md in the project — brief skeleton skipped)" );
69 }
70 } else if (verb === "list" ) {
71 const list = listRecipes ({ projectDir: args.hyperframes, workflow: args.workflow });
72 if (args.json) console. log ( JSON . stringify (list));
73 else if (list. length === 0 ) console. log ( "no recipes yet" );
74 else {
75 for ( const r of list) {
76 console. log (
77 `${ r . name } v${ r . version } ${ r . workflow } (${ r . source }; approved ${ String ( r . approved_at ?? "?" ). slice ( 0 , 10 ) })` ,
78 );
79 }
80 }
81 } else if (verb === "use" ) {
82 if ( ! args.name) fail ( "use needs --name" );
83 const used = useRecipe ({ projectDir: args.hyperframes, name: args.name });
84 if (args.json) console. log ( JSON . stringify ({ ok: true , ... used }));
85 else {
86 console. log (
87 `using recipe ${ used . recipe . name } (v${ used . recipe . version }, ${ used . recipe . workflow })` ,
88 );
89 console. log ( ` frame spec → ${ used . frameSpecPath } (copied over)` );
90 console. log ( ` storyboard skeleton → ${ used . skeletonPath }` );
91 if (used.briefSkeletonPath) console. log ( ` brief skeleton → ${ used . briefSkeletonPath }` );
92 for ( const key of [ "destination" , "aspect" , "language" , "voice" , "style_preset" ]) {
93 if (used.recipe[key]) console. log ( ` ${ key }: ${ used . recipe [ key ] }` );
94 }
95 }
96 } else {
97 fail (
98 "usage: recipe.mjs <freeze|list|use> --hyperframes . [--name <n>] [--workflow <w>] [--blocks a,b] [--json]" ,
99 );
100 }
101 } catch (err) {
102 fail (err instanceof Error ? err.message : String (err));
103 }