@field/cascade 0.11.0 → 0.13.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/AGENTS.md +8 -5
- package/ARCHITECTURE.md +5 -4
- package/CHANGELOG.md +245 -0
- package/README.md +1 -1
- package/dist/assets/AgentPanel-1JugFjE4.css +1 -0
- package/dist/assets/AgentPanel-BDL5MddA.js +5 -0
- package/dist/assets/{CodeEditor-4O7FQ__R.js → CodeEditor-C-xYG-Wn.js} +120 -120
- package/dist/assets/CodePanel-CtXd50m6.js +2 -0
- package/dist/assets/CookInfoPanel-B3NMhKJF.css +1 -0
- package/dist/assets/CookInfoPanel-DG4_TRsX.js +2 -0
- package/dist/assets/CustomNodeDialog-CHfZUs-r.js +1 -0
- package/dist/assets/DefinitionNode-CaRTXQ_b.js +1 -0
- package/dist/assets/DefinitionPanel-C3CxZY9r.js +1 -0
- package/dist/assets/DefinitionPanel-VNLnAiQD.css +1 -0
- package/dist/assets/OpenGraphDialog-BLdr6k_q.js +1 -0
- package/dist/assets/ProjectSettings-ZnvmIAir.js +2 -0
- package/dist/assets/{SettingsDialog-Bz8JxISH.js → SettingsDialog-CBX3Wa87.js} +1 -1
- package/dist/assets/TimelinePanel-CDeR0arY.css +1 -0
- package/dist/assets/TimelinePanel-CWgnFH1e.js +1 -0
- package/dist/assets/{VersionHistoryDialog-D5Z0nJ5-.js → VersionHistoryDialog-BOSoW1R-.js} +1 -1
- package/dist/assets/assert-BO2_erPD.js +1 -0
- package/dist/assets/assert-hvykGCnP.js +1 -0
- package/dist/assets/builder-BmBKcDix.js +1 -0
- package/dist/assets/camera-DFF7YA3F.js +1 -0
- package/dist/assets/checks-DAvyO9Gf.js +1 -0
- package/dist/assets/contactSheet-N1NcaWxw.js +2 -0
- package/dist/assets/{core-Yqi0Ni61.js → core-DB-MkGjj.js} +3 -4
- package/dist/assets/coreTypes-DtnDATZ7.js +1 -0
- package/dist/assets/{cssMode-CxUzc4vp.js → cssMode-DPVckSOc.js} +1 -1
- package/dist/assets/definitions-B227e7f_.js +1 -0
- package/dist/assets/definitions-D0WOUJd7.js +1 -0
- package/dist/assets/{editor.api-BNFb25CX.js → editor.api-Dkutg_Z1.js} +1 -1
- package/dist/assets/expressions-X-Z-GrgW.js +5 -0
- package/dist/assets/file-DAL6IfjV.js +1 -0
- package/dist/assets/filters-D3k1LRMa.js +1 -0
- package/dist/assets/{freemarker2-0ZDnWxeM.js → freemarker2-CLiLKk3B.js} +1 -1
- package/dist/assets/generators-BhDxRAFC.js +1 -0
- package/dist/assets/geo-BsMImJIJ.js +1 -0
- package/dist/assets/geo-C4YngDob.js +2 -0
- package/dist/assets/{handlebars-Cy18MoaD.js → handlebars-CcD3aMeL.js} +1 -1
- package/dist/assets/{html-B-2Dx7nq.js → html-DvZWGfqb.js} +1 -1
- package/dist/assets/{htmlMode-DUAc9B_d.js → htmlMode-DUD3VaoN.js} +1 -1
- package/dist/assets/image-0SfH-snh.js +1 -0
- package/dist/assets/image-Ck-RdGU4.js +2 -0
- package/dist/assets/index-BWnrmIB9.js +137 -0
- package/dist/assets/index-DIaxEONI.css +1 -0
- package/dist/assets/io-BGmt2g0D.js +1 -0
- package/dist/assets/{javascript-DeQsDqP5.js → javascript-Cap2ahgh.js} +1 -1
- package/dist/assets/{jsonMode-BiFwJVSk.js → jsonMode-B0uLjp9C.js} +1 -1
- package/dist/assets/{liquid-BLoHH68a.js → liquid-CnxwhfLn.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-CNFgm1Kv.js → lspLanguageFeatures-Dn9hlKX6.js} +1 -1
- package/dist/assets/math-GeULS-sk.js +1 -0
- package/dist/assets/{mdx-CFXQVNfs.js → mdx-BV3jbrVa.js} +1 -1
- package/dist/assets/pop-KMF_qloi.js +1 -0
- package/dist/assets/preload-helper-Czpn1I53.js +1 -0
- package/dist/assets/{python-Cf7S7p2E.js → python-CGyFk4XK.js} +1 -1
- package/dist/assets/{razor-CMHBcG-g.js → razor-CQfzX3-N.js} +1 -1
- package/dist/assets/remap-5SjXQU-q.js +1 -0
- package/dist/assets/renderMarkdown-ork0Oir7.js +67 -0
- package/dist/assets/studioImages-CAyH-0Pl.js +1 -0
- package/dist/assets/text-ZpX7qNkx.js +2 -0
- package/dist/assets/time-P_OiBhcf.js +1 -0
- package/dist/assets/{tsMode-BEih0GDj.js → tsMode-BOeXzO9H.js} +1 -1
- package/dist/assets/{typescript-COEKYD_a.js → typescript-J1SnE_Tu.js} +1 -1
- package/dist/assets/{workers-BNhAhMNn.js → workers-CYwwTiVF.js} +1 -1
- package/dist/assets/{xml-CPiMpnPl.js → xml-DnPRNzK9.js} +1 -1
- package/dist/assets/{yaml-Bgp1ITLR.js → yaml-BmmYBNa9.js} +1 -1
- package/dist/cli/DefinitionNode-P7AA4TAU.js +15 -0
- package/dist/cli/{Graph-ZJJTRQTM.js → Graph-OB6EWSGL.js} +12 -12
- package/dist/cli/assert-GROGQNCQ.js +25 -0
- package/dist/cli/checks-3WB44XBL.js +189 -0
- package/dist/cli/{chunk-3JTJHF7V.js → chunk-2L34ERS2.js} +4 -4
- package/dist/cli/chunk-53LGFPWX.js +138 -0
- package/dist/cli/chunk-5ORUQ6ES.js +267 -0
- package/dist/cli/{chunk-YAT5Y25U.js → chunk-7QE2ZNSN.js} +3 -3
- package/dist/cli/{chunk-SGJAET2L.js → chunk-BPODRH52.js} +8 -4
- package/dist/cli/{chunk-XWDSKG7N.js → chunk-BZ63XQ3I.js} +2 -2
- package/dist/cli/{chunk-FCDXJ6EK.js → chunk-CTPLRSWF.js} +2 -13
- package/dist/cli/{chunk-WIH4TEIS.js → chunk-EZRWJ4G2.js} +1 -1
- package/dist/cli/{chunk-BIJO5OFS.js → chunk-FWMSGKEH.js} +1 -1
- package/dist/cli/{chunk-POMMNKZZ.js → chunk-G23A2BZZ.js} +38 -5
- package/dist/cli/{chunk-35D343DC.js → chunk-GRIN2DDP.js} +19 -1
- package/dist/cli/{chunk-WKURDVYP.js → chunk-JEW5MPGI.js} +28 -331
- package/dist/cli/chunk-JVOCK5W4.js +83 -0
- package/dist/cli/chunk-KBGUO27Q.js +15 -0
- package/dist/cli/{chunk-GFS6W3C5.js → chunk-L6B6FUQP.js} +54 -32
- package/dist/cli/chunk-LTXWBXOM.js +438 -0
- package/dist/cli/chunk-MI5JLQYA.js +220 -0
- package/dist/cli/{chunk-A4OAMOZH.js → chunk-NJFMDXHR.js} +13 -3
- package/dist/cli/{chunk-DUIUFVU2.js → chunk-OBZAP3GG.js} +49 -23
- package/dist/cli/chunk-QAGATJGE.js +336 -0
- package/dist/cli/{chunk-EUIAC3U3.js → chunk-QKL7CCRS.js} +966 -132
- package/dist/cli/{chunk-RLCAJBVR.js → chunk-TJW67QSI.js} +8 -7
- package/dist/cli/{chunk-RQZ4SX5R.js → chunk-W5PJ5RMP.js} +156 -84
- package/dist/cli/chunk-W7OUAT7J.js +122 -0
- package/dist/cli/chunk-WGKPJZDY.js +364 -0
- package/dist/cli/{chunk-D6BUOHUG.js → chunk-X4WKAOQP.js} +4 -4
- package/dist/cli/{chunk-VVGSLVSF.js → chunk-X566FWBV.js} +6 -1
- package/dist/cli/chunk-YH637PDL.js +317 -0
- package/dist/cli/chunk-ZSCUZE6I.js +112 -0
- package/dist/cli/{cliCommands-UQSFGEHF.js → cliCommands-XVFRD7CF.js} +23 -17
- package/dist/cli/{commands-Q23M26QM.js → commands-M2XLTPTZ.js} +129 -47
- package/dist/cli/contactSheet-2PQVRUFW.js +11 -0
- package/dist/cli/{definitions-HF2FTHYU.js → definitions-BPOPW52L.js} +7 -7
- package/dist/cli/{doctorCommand-B7BPQMN6.js → doctorCommand-RAEI7GVY.js} +36 -6
- package/dist/cli/{edit-JHCPTQFT.js → edit-S5KEQ5RA.js} +3 -3
- package/dist/cli/editorCommands-5BBG4S6V.js +41 -0
- package/dist/cli/{encode-HAUZTYPT.js → encode-ICPEPMH5.js} +2 -2
- package/dist/cli/file-3HTQHPYQ.js +41 -0
- package/dist/cli/filters-6ODFWYK4.js +379 -0
- package/dist/cli/generators-YU7GB4MD.js +210 -0
- package/dist/cli/{geo-4RNK3QVN.js → geo-6ZPGKZRU.js} +7 -7
- package/dist/cli/{graphCommands-6BMAKGQE.js → graphCommands-MULQ7VD2.js} +4 -4
- package/dist/cli/{graphFile-VPSQ6OF7.js → graphFile-CITF36ZM.js} +25 -19
- package/dist/cli/{headlessCanvas-5XLDZT7M.js → headlessCanvas-ENRHC7GS.js} +3 -2
- package/dist/cli/{helpCommand-3VRE3KVO.js → helpCommand-X2QDANM3.js} +9 -7
- package/dist/cli/image-TXELZZK5.js +55 -0
- package/dist/cli/index.js +14 -14
- package/dist/cli/{math-ZRMLKU2D.js → math-RSYRQ3C6.js} +5 -5
- package/dist/cli/{mcp-ZLEEMYGF.js → mcp-YRIGRLYQ.js} +4 -4
- package/dist/cli/{parity-KINARCP2.js → parity-3N3HTKWX.js} +42 -36
- package/dist/cli/{pop-USDFXB7H.js → pop-B7SIIYKN.js} +5 -5
- package/dist/cli/project-SJF5ZF3F.js +12 -0
- package/dist/cli/{projectDefinition-DMTZN2NE.js → projectDefinition-F3D7UIHJ.js} +8 -8
- package/dist/cli/{projectRuntime-Z5PJOH47.js → projectRuntime-NY4XMDFH.js} +19 -12
- package/dist/cli/registerStandardNodes-BXJCB6E4.js +744 -0
- package/dist/cli/{render-YURAPPUI.js → render-Y23W6MY6.js} +29 -22
- package/dist/cli/{runCommand-PI764LEG.js → runCommand-XOG7AVC5.js} +3 -3
- package/dist/cli/runner-DNJO5WO2.js +43 -0
- package/dist/cli/runtime/image.ts +27 -2
- package/dist/cli/runtime/io.ts +78 -0
- package/dist/cli/share-B7HTCOJX.js +166 -0
- package/dist/cli/stageCache-TY2BFZJR.js +15 -0
- package/dist/cli/{stageRunner-KUNIMQKJ.js → stageRunner-KY2EJP7X.js} +2 -2
- package/dist/cli/text-MB3EKR4H.js +126 -0
- package/dist/cli/{verbs-RCE3K4VQ.js → verbs-PI2JH5FI.js} +2 -2
- package/dist/cli/webBuild-2K4COCGY.js +44 -0
- package/dist/contracts/capabilities.d.ts +39 -1
- package/dist/contracts/color.d.ts +8 -0
- package/dist/contracts/color.js +23 -0
- package/dist/contracts/definition.d.ts +10 -0
- package/dist/contracts/schema.d.ts +1 -1
- package/dist/contracts/schema.js +1 -0
- package/dist/contracts/validate.js +11 -1
- package/dist/contracts/values.d.ts +24 -0
- package/dist/image.d.ts +15 -0
- package/dist/image.js +36 -2
- package/dist/index.html +8 -2
- package/dist/io.d.ts +29 -0
- package/dist/io.js +40 -0
- package/dist/player/app.js +11 -7
- package/dist/player/editor.js +3 -2
- package/dist/player/editorEngine.js +3 -2
- package/dist/player/embed.js +2 -0
- package/dist/player/types.d.ts +6 -0
- package/dist/runtime/builtins/assert/checks.d.ts +18 -0
- package/dist/runtime/builtins/assert/checks.js +207 -0
- package/dist/runtime/builtins/assert/definitions.d.ts +130 -0
- package/dist/runtime/builtins/assert/definitions.js +54 -0
- package/dist/runtime/builtins/assert/index.d.ts +152 -0
- package/dist/runtime/builtins/assert/index.js +36 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +3 -165
- package/dist/runtime/builtins/image/contactSheet.js +0 -49
- package/dist/runtime/builtins/image/definitions.d.ts +950 -0
- package/dist/runtime/builtins/image/definitions.js +343 -0
- package/dist/runtime/builtins/image/file.d.ts +8 -0
- package/dist/runtime/builtins/image/file.js +37 -0
- package/dist/runtime/builtins/image/filters.d.ts +8 -0
- package/dist/runtime/builtins/image/filters.js +394 -0
- package/dist/runtime/builtins/image/generators.d.ts +7 -0
- package/dist/runtime/builtins/image/generators.js +144 -0
- package/dist/runtime/builtins/image/index.d.ts +947 -4
- package/dist/runtime/builtins/image/index.js +41 -6
- package/dist/runtime/builtins/image/io.d.ts +100 -0
- package/dist/runtime/builtins/image/io.js +142 -0
- package/dist/runtime/builtins/image/planar.d.ts +55 -0
- package/dist/runtime/builtins/image/planar.js +274 -0
- package/dist/runtime/builtins/image/simplex.d.ts +22 -0
- package/dist/runtime/builtins/image/simplex.js +92 -0
- package/dist/runtime/builtins/image/text.d.ts +4 -0
- package/dist/runtime/builtins/image/text.js +141 -0
- package/dist/runtime/builtins/index.d.ts +3 -0
- package/dist/runtime/builtins/index.js +7 -0
- package/dist/runtime/definition/architecture.js +89 -0
- package/dist/runtime/gpu.d.ts +25 -0
- package/dist/runtime/gpu.js +40 -0
- package/dist/runtime/runtime.d.ts +2 -0
- package/dist/runtime/runtime.js +268 -44
- package/dist/runtime/types.d.ts +30 -0
- package/doc/CLI_REFERENCE.md +21 -3
- package/doc/EDITOR_EXPORT.md +26 -0
- package/doc/MCP.md +2 -1
- package/doc/NODE_REFERENCE.md +286 -14
- package/doc/PROJECT_AUTHORING.md +158 -4
- package/doc/WEB_PLAYER.md +9 -1
- package/package.json +4 -1
- package/dist/assets/CodePanel-BU-autmq.js +0 -2
- package/dist/assets/CustomNodeDialog-BRpDfOV5.js +0 -1
- package/dist/assets/OpenGraphDialog-BwbRlC0X.js +0 -1
- package/dist/assets/ProjectSettings-DLOXLxcA.js +0 -2
- package/dist/assets/definitions-GreEMXLV.js +0 -1
- package/dist/assets/geo-u0n_jOsD.js +0 -1
- package/dist/assets/image-cAa-Nu9O.js +0 -2062
- package/dist/assets/index-5ZtDAuy2.js +0 -220
- package/dist/assets/index-7vae6YFC.css +0 -1
- package/dist/assets/math-DioIQOPJ.js +0 -1
- package/dist/assets/pop-DC_TQG9t.js +0 -1
- package/dist/cli/chunk-36P5K3SD.js +0 -631
- package/dist/cli/chunk-4UDFYF5G.js +0 -132
- package/dist/cli/chunk-53NMBJAO.js +0 -35
- package/dist/cli/chunk-MIIEFUGG.js +0 -623
- package/dist/cli/chunk-QBBKRNGY.js +0 -90
- package/dist/cli/chunk-WPUDGEFY.js +0 -20
- package/dist/cli/editorCommands-UIF5YLUZ.js +0 -33
- package/dist/cli/project-K3QIPGBB.js +0 -12
- package/dist/cli/registerStandardNodes-S2VLMF6J.js +0 -3081
- package/dist/cli/runner-RA6UKEPD.js +0 -37
- package/dist/cli/webBuild-GT4PZT5D.js +0 -37
- package/dist/runtime/builtins/headless.d.ts +0 -19
- package/dist/runtime/builtins/headless.js +0 -25
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// server/src/stageCache.ts
|
|
2
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
3
|
+
import fs3 from "node:fs";
|
|
4
|
+
import path2 from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
// server/src/atomicWrite.ts
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import fsp from "node:fs/promises";
|
|
10
|
+
var temporaryFor = (file) => `${file}.${process.pid}.tmp`;
|
|
11
|
+
async function writeFileAtomic(file, data, options = {}) {
|
|
12
|
+
const temporary = temporaryFor(file);
|
|
13
|
+
await fsp.writeFile(temporary, data, options.mode === void 0 ? void 0 : { mode: options.mode });
|
|
14
|
+
await fsp.rename(temporary, file);
|
|
15
|
+
}
|
|
16
|
+
function writeFileAtomicSync(file, data) {
|
|
17
|
+
const temporary = temporaryFor(file);
|
|
18
|
+
fs.writeFileSync(temporary, data);
|
|
19
|
+
fs.renameSync(temporary, file);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// server/src/stageSources.ts
|
|
23
|
+
import { createHash } from "node:crypto";
|
|
24
|
+
import fs2 from "node:fs";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
var SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set(["__pycache__", "node_modules", "venv", ".venv", ".git", ".cascade", ".cascade-cache"]);
|
|
27
|
+
var digests = /* @__PURE__ */ new Map();
|
|
28
|
+
function contentDigest(fullPath) {
|
|
29
|
+
let stat;
|
|
30
|
+
try {
|
|
31
|
+
stat = fs2.statSync(fullPath, { bigint: true });
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
if (!stat.isFile()) return null;
|
|
36
|
+
const stamp = `${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
|
|
37
|
+
const known = digests.get(fullPath);
|
|
38
|
+
if (known?.stamp === stamp) return known.digest;
|
|
39
|
+
const hash = createHash("sha256");
|
|
40
|
+
const handle = fs2.openSync(fullPath, "r");
|
|
41
|
+
try {
|
|
42
|
+
const buffer = Buffer.allocUnsafe(1 << 20);
|
|
43
|
+
let read;
|
|
44
|
+
while ((read = fs2.readSync(handle, buffer, 0, buffer.length, null)) > 0) hash.update(buffer.subarray(0, read));
|
|
45
|
+
} finally {
|
|
46
|
+
fs2.closeSync(handle);
|
|
47
|
+
}
|
|
48
|
+
const digest = hash.digest("hex");
|
|
49
|
+
digests.set(fullPath, { stamp, digest });
|
|
50
|
+
return digest;
|
|
51
|
+
}
|
|
52
|
+
var StageSources = class {
|
|
53
|
+
constructor(project, roots) {
|
|
54
|
+
this.project = project;
|
|
55
|
+
this.roots = [...new Set(roots)].sort();
|
|
56
|
+
}
|
|
57
|
+
/** The default roots for a stage configuration without `sources`. */
|
|
58
|
+
static defaultRoots(project, entrypoint, worker) {
|
|
59
|
+
const roots = [path.posix.dirname(entrypoint)];
|
|
60
|
+
if (worker) roots.push(path.posix.dirname(worker));
|
|
61
|
+
if (fs2.existsSync(project.resolve("src"))) roots.push("src");
|
|
62
|
+
return roots.map((root) => root === "" ? "." : root);
|
|
63
|
+
}
|
|
64
|
+
/** Every source file, project-relative and sorted. */
|
|
65
|
+
files() {
|
|
66
|
+
const found = /* @__PURE__ */ new Set();
|
|
67
|
+
for (const root of this.roots) {
|
|
68
|
+
let full;
|
|
69
|
+
try {
|
|
70
|
+
full = this.project.resolveMedia(root);
|
|
71
|
+
} catch {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
let stat;
|
|
75
|
+
try {
|
|
76
|
+
stat = fs2.statSync(full);
|
|
77
|
+
} catch {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (stat.isFile()) found.add(root);
|
|
81
|
+
else if (stat.isDirectory()) this.walk(full, root, found);
|
|
82
|
+
}
|
|
83
|
+
return [...found].sort();
|
|
84
|
+
}
|
|
85
|
+
walk(directory, relative, found) {
|
|
86
|
+
let entries;
|
|
87
|
+
try {
|
|
88
|
+
entries = fs2.readdirSync(directory, { withFileTypes: true });
|
|
89
|
+
} catch {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
for (const entry of entries) {
|
|
93
|
+
const child = relative === "." ? entry.name : path.posix.join(relative, entry.name);
|
|
94
|
+
if (entry.isDirectory()) {
|
|
95
|
+
if (SKIPPED_DIRECTORIES.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
96
|
+
this.walk(path.join(directory, entry.name), child, found);
|
|
97
|
+
} else if (entry.isFile() && entry.name.endsWith(".py")) {
|
|
98
|
+
found.add(child);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
digest(relative) {
|
|
103
|
+
return contentDigest(this.project.resolveMedia(relative)) ?? "missing";
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The code hash, 16 hex characters. A file added, removed or edited changes
|
|
107
|
+
* it. Cheap to call per request: one directory walk and one stat per file,
|
|
108
|
+
* with a file read only when its stat changed.
|
|
109
|
+
*/
|
|
110
|
+
codeHash() {
|
|
111
|
+
const hash = createHash("sha256");
|
|
112
|
+
for (const file of this.files()) hash.update(`${file}\0${this.digest(file)}
|
|
113
|
+
`);
|
|
114
|
+
return hash.digest("hex").slice(0, 16);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// server/src/stageCache.ts
|
|
119
|
+
var CACHE_FORMAT = 1;
|
|
120
|
+
var CACHE_DIRECTORY = ".cascade/cache/stages";
|
|
121
|
+
var version;
|
|
122
|
+
function cascadeVersion() {
|
|
123
|
+
if (version) return version;
|
|
124
|
+
let directory = path2.dirname(fileURLToPath(import.meta.url));
|
|
125
|
+
for (let depth = 0; depth < 6; depth++) {
|
|
126
|
+
try {
|
|
127
|
+
const manifest = JSON.parse(fs3.readFileSync(path2.join(directory, "package.json"), "utf8"));
|
|
128
|
+
if (manifest.name === "@field/cascade" && manifest.version) return version = manifest.version;
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
directory = path2.dirname(directory);
|
|
132
|
+
}
|
|
133
|
+
return version = "unknown";
|
|
134
|
+
}
|
|
135
|
+
function projectFile(project, value) {
|
|
136
|
+
if (!value || value.length > 1024 || value.includes("\0") || /^[a-z][a-z0-9+.-]*:/i.test(value)) return null;
|
|
137
|
+
if (path2.isAbsolute(value) || !/[./]/.test(value)) return null;
|
|
138
|
+
try {
|
|
139
|
+
return project.resolveMedia(value.replace(/^\.\//, ""));
|
|
140
|
+
} catch {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function replaceFiles(project, value, at, skip, onFile) {
|
|
145
|
+
if (typeof value === "string") {
|
|
146
|
+
const full = projectFile(project, value);
|
|
147
|
+
const digest = full ? contentDigest(full) : null;
|
|
148
|
+
if (!digest) return value;
|
|
149
|
+
onFile(at, value, digest);
|
|
150
|
+
return `file:${digest}`;
|
|
151
|
+
}
|
|
152
|
+
if (Array.isArray(value)) return value.map((item, index) => replaceFiles(project, item, `${at}[${index}]`, skip, onFile));
|
|
153
|
+
if (value && typeof value === "object") {
|
|
154
|
+
const out = {};
|
|
155
|
+
for (const name of Object.keys(value).sort()) {
|
|
156
|
+
const child = value[name];
|
|
157
|
+
const where = at ? `${at}.${name}` : name;
|
|
158
|
+
out[name] = !at && skip.has(name) ? child : replaceFiles(project, child, where, skip, onFile);
|
|
159
|
+
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
function stageCacheKey(project, stage, args, code, outputs = []) {
|
|
165
|
+
const inputs = {};
|
|
166
|
+
const params = replaceFiles(project, args, "", new Set(outputs), (where, _relative, digest) => {
|
|
167
|
+
inputs[where] = digest.slice(0, 16);
|
|
168
|
+
});
|
|
169
|
+
const cascade = cascadeVersion();
|
|
170
|
+
const blob = JSON.stringify({ format: CACHE_FORMAT, stage, code, cascade, params });
|
|
171
|
+
return { key: createHash2("sha256").update(blob).digest("hex").slice(0, 32), code, cascade, inputs };
|
|
172
|
+
}
|
|
173
|
+
function entryPath(project, stage, key) {
|
|
174
|
+
return project.resolve(path2.posix.join(CACHE_DIRECTORY, stage, `${key}.json`));
|
|
175
|
+
}
|
|
176
|
+
function resultFiles(project, result) {
|
|
177
|
+
const files = {};
|
|
178
|
+
replaceFiles(project, result, "", /* @__PURE__ */ new Set(), (_where, relative, digest) => {
|
|
179
|
+
files[relative] = digest;
|
|
180
|
+
});
|
|
181
|
+
return files;
|
|
182
|
+
}
|
|
183
|
+
function readEntry(project, stage, key) {
|
|
184
|
+
let entry;
|
|
185
|
+
try {
|
|
186
|
+
entry = JSON.parse(fs3.readFileSync(entryPath(project, stage, key), "utf8"));
|
|
187
|
+
} catch {
|
|
188
|
+
return { why: "no entry" };
|
|
189
|
+
}
|
|
190
|
+
if (entry.format !== CACHE_FORMAT || entry.key !== key) return { why: "no entry" };
|
|
191
|
+
for (const [relative, digest] of Object.entries(entry.outputs ?? {})) {
|
|
192
|
+
const full = projectFile(project, relative);
|
|
193
|
+
if (!full || contentDigest(full) !== digest) return { why: `output changed: ${relative}` };
|
|
194
|
+
}
|
|
195
|
+
return { result: entry.result };
|
|
196
|
+
}
|
|
197
|
+
function writeEntry(project, stage, key, result) {
|
|
198
|
+
const file = entryPath(project, stage, key);
|
|
199
|
+
const entry = { format: CACHE_FORMAT, stage, key, result, outputs: resultFiles(project, result) };
|
|
200
|
+
fs3.mkdirSync(path2.dirname(file), { recursive: true });
|
|
201
|
+
writeFileAtomicSync(file, JSON.stringify(entry));
|
|
202
|
+
}
|
|
203
|
+
function cacheMode(policy, stage, caller, env) {
|
|
204
|
+
if (env.CASCADE_STAGE_CACHE === "off") return { use: false, bypass: true, why: "CASCADE_STAGE_CACHE=off" };
|
|
205
|
+
if (!policy.enabled) return { use: false, bypass: false, why: "not enabled" };
|
|
206
|
+
if (policy.exclude.includes(stage)) return { use: false, bypass: false, why: "excluded" };
|
|
207
|
+
if (policy.scope === "cook" && caller !== "cook") return { use: false, bypass: false, why: "not a cook call" };
|
|
208
|
+
return { use: true, bypass: false };
|
|
209
|
+
}
|
|
210
|
+
function stageSources(project, config) {
|
|
211
|
+
return new StageSources(project, config.sources ?? StageSources.defaultRoots(project, config.entrypoint, config.worker));
|
|
212
|
+
}
|
|
213
|
+
async function callStage(project, config, stage, args, invoke, options = {}) {
|
|
214
|
+
const started = performance.now();
|
|
215
|
+
const code = stageSources(project, config).codeHash();
|
|
216
|
+
const identity = stageCacheKey(project, stage, args, code, config.cache.outputs);
|
|
217
|
+
const mode = cacheMode(config.cache, stage, options.caller ?? "cook", options.env ?? process.env);
|
|
218
|
+
const finish = (result, trace) => {
|
|
219
|
+
const full = {
|
|
220
|
+
stage,
|
|
221
|
+
key: identity.key,
|
|
222
|
+
...trace,
|
|
223
|
+
code: identity.code,
|
|
224
|
+
cascade: identity.cascade,
|
|
225
|
+
inputs: identity.inputs,
|
|
226
|
+
ms: Math.round(performance.now() - started)
|
|
227
|
+
};
|
|
228
|
+
options.onTrace?.(full);
|
|
229
|
+
return { result, trace: full };
|
|
230
|
+
};
|
|
231
|
+
let why = mode.why;
|
|
232
|
+
if (mode.use) {
|
|
233
|
+
const stored = readEntry(project, stage, identity.key);
|
|
234
|
+
if ("result" in stored) return finish(stored.result, { cache: "hit" });
|
|
235
|
+
why = stored.why;
|
|
236
|
+
}
|
|
237
|
+
const answer = await invoke({ key: identity.key, code, cache: mode.bypass ? "off" : "use" });
|
|
238
|
+
if (mode.use) {
|
|
239
|
+
try {
|
|
240
|
+
writeEntry(project, stage, identity.key, answer.result);
|
|
241
|
+
} catch {
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return finish(answer.result, {
|
|
245
|
+
cache: mode.use ? "miss" : "off",
|
|
246
|
+
...why ? { why } : {},
|
|
247
|
+
...answer.projectCache ? { project: answer.projectCache } : {},
|
|
248
|
+
...answer.restarted ? { restarted: true } : {}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function formatStageTrace(trace) {
|
|
252
|
+
const reason = trace.why ? ` (${trace.why})` : "";
|
|
253
|
+
const project = trace.project ? ` project:${trace.project}` : "";
|
|
254
|
+
const restarted = trace.restarted ? " worker restarted for new code" : "";
|
|
255
|
+
return `${trace.stage}: ${trace.cache}${reason}${project} key ${trace.key.slice(0, 12)} code ${trace.code} ${trace.ms} ms${restarted}`;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export {
|
|
259
|
+
writeFileAtomic,
|
|
260
|
+
writeFileAtomicSync,
|
|
261
|
+
cascadeVersion,
|
|
262
|
+
stageCacheKey,
|
|
263
|
+
stageSources,
|
|
264
|
+
callStage,
|
|
265
|
+
formatStageTrace
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=chunk-5ORUQ6ES.js.map
|
|
@@ -52,7 +52,7 @@ async function encodeSequence(options) {
|
|
|
52
52
|
if (frames[index] !== frames[index - 1] + 1) throw new Error("--mp4 needs a contiguous range of whole frames (no step)");
|
|
53
53
|
}
|
|
54
54
|
const { prefix, width, extension } = options.sequence;
|
|
55
|
-
const pattern = path.
|
|
55
|
+
const pattern = path.resolve(options.root, `${prefix}.%0${width}d${extension}`);
|
|
56
56
|
const output = path.resolve(options.root, options.file);
|
|
57
57
|
await fs.mkdir(path.dirname(output), { recursive: true });
|
|
58
58
|
const size = scale === 1 ? "pad=ceil(iw/2)*2:ceil(ih/2)*2" : `scale=trunc(iw*${scale}/2)*2:trunc(ih*${scale}/2)*2:flags=lanczos`;
|
|
@@ -60,7 +60,7 @@ async function encodeSequence(options) {
|
|
|
60
60
|
let pixelFormat;
|
|
61
61
|
let codecArgs;
|
|
62
62
|
if (options.codec === "prores") {
|
|
63
|
-
const first = path.
|
|
63
|
+
const first = path.resolve(options.root, `${prefix}.${String(frames[0]).padStart(width, "0")}${extension}`);
|
|
64
64
|
const alpha = await hasTransparency(first);
|
|
65
65
|
pixelFormat = alpha ? "yuva444p10le" : "yuv422p10le";
|
|
66
66
|
codecArgs = ["-c:v", "prores_ks", "-profile:v", alpha ? "4" : "3", "-vendor", "apl0", "-pix_fmt", pixelFormat];
|
|
@@ -118,4 +118,4 @@ export {
|
|
|
118
118
|
hasFfmpeg,
|
|
119
119
|
encodeSequence
|
|
120
120
|
};
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-7QE2ZNSN.js.map
|
|
@@ -3,15 +3,16 @@ import {
|
|
|
3
3
|
packagePathToType,
|
|
4
4
|
registerNodeClasses,
|
|
5
5
|
registerNodeMetadata
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CTPLRSWF.js";
|
|
7
7
|
import {
|
|
8
8
|
bundleValueProblem,
|
|
9
|
+
gpuLimitShortfall,
|
|
9
10
|
graphSeed,
|
|
10
11
|
isGpuHost,
|
|
11
12
|
nodeSeed,
|
|
12
13
|
seededRandom,
|
|
13
14
|
selectBundleFields
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-L6B6FUQP.js";
|
|
15
16
|
|
|
16
17
|
// src/nodes/definition/DefinitionNode.ts
|
|
17
18
|
var silentProgress = { report: () => {
|
|
@@ -136,7 +137,10 @@ function attachDefinition(node, registration, capabilities) {
|
|
|
136
137
|
const gpuHost = (definition.capabilities ?? []).includes("gpu") && isGpuHost(capabilities.gpu) ? capabilities.gpu : null;
|
|
137
138
|
if (gpuHost) {
|
|
138
139
|
await gpuHost.ensure();
|
|
139
|
-
|
|
140
|
+
const gpu = gpuHost.forNode(node.id);
|
|
141
|
+
const shortfall = gpuLimitShortfall(node.id, definition.gpuLimits, gpu);
|
|
142
|
+
if (shortfall) throw new Error(shortfall);
|
|
143
|
+
nodeCapabilities = { ...capabilities, gpu };
|
|
140
144
|
}
|
|
141
145
|
const seed = nodeSeed(graphSeed({ seed: node.documentSeed }), node.id);
|
|
142
146
|
const context = {
|
|
@@ -194,4 +198,4 @@ export {
|
|
|
194
198
|
attachDefinition,
|
|
195
199
|
registerDefinitionNodes
|
|
196
200
|
};
|
|
197
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-BPODRH52.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
canConnectTypes
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FWMSGKEH.js";
|
|
4
4
|
|
|
5
5
|
// packages/runtime/src/edit/document.ts
|
|
6
6
|
var SUBNET = "cascade.core.Subnet";
|
|
@@ -1298,4 +1298,4 @@ export {
|
|
|
1298
1298
|
applyOperation,
|
|
1299
1299
|
readGraph
|
|
1300
1300
|
};
|
|
1301
|
-
//# sourceMappingURL=chunk-
|
|
1301
|
+
//# sourceMappingURL=chunk-BZ63XQ3I.js.map
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
CORE_TYPES,
|
|
17
17
|
canConnectTypes,
|
|
18
18
|
normalizeCascadeType
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FWMSGKEH.js";
|
|
20
20
|
|
|
21
21
|
// src/utils/nodeTypeUtils.ts
|
|
22
22
|
var nodeClassRegistries = /* @__PURE__ */ new Map();
|
|
@@ -136,16 +136,6 @@ function normalizeColor(input) {
|
|
|
136
136
|
}
|
|
137
137
|
return { r: 0, g: 0, b: 0, a: 1 };
|
|
138
138
|
}
|
|
139
|
-
function colorToCss(color) {
|
|
140
|
-
const r = Math.round(color.r * 255);
|
|
141
|
-
const g = Math.round(color.g * 255);
|
|
142
|
-
const b = Math.round(color.b * 255);
|
|
143
|
-
const a = color.a !== void 0 ? color.a : 1;
|
|
144
|
-
if (a < 1) {
|
|
145
|
-
return `rgba(${r},${g},${b},${a})`;
|
|
146
|
-
}
|
|
147
|
-
return `rgb(${r},${g},${b})`;
|
|
148
|
-
}
|
|
149
139
|
function isColorValue(value) {
|
|
150
140
|
if (typeof value === "string") {
|
|
151
141
|
return value.startsWith("#") || value.startsWith("rgb(");
|
|
@@ -2197,7 +2187,6 @@ export {
|
|
|
2197
2187
|
isStandardLibraryNode,
|
|
2198
2188
|
getNodeClass,
|
|
2199
2189
|
normalizeColor,
|
|
2200
|
-
colorToCss,
|
|
2201
2190
|
isColorValue,
|
|
2202
2191
|
CORE_TYPES2 as CORE_TYPES,
|
|
2203
2192
|
isCoreType,
|
|
@@ -2205,4 +2194,4 @@ export {
|
|
|
2205
2194
|
canConnect,
|
|
2206
2195
|
Node
|
|
2207
2196
|
};
|
|
2208
|
-
//# sourceMappingURL=chunk-
|
|
2197
|
+
//# sourceMappingURL=chunk-CTPLRSWF.js.map
|
|
@@ -118,6 +118,34 @@ var VERBS = [
|
|
|
118
118
|
call: { kind: "cli", argv: (args, resolve) => ["export", resolve(args.graph), ...args.out ? ["--out", resolve(args.out)] : ["--plan"]] }
|
|
119
119
|
}]
|
|
120
120
|
},
|
|
121
|
+
{
|
|
122
|
+
...editorVerb,
|
|
123
|
+
name: "share",
|
|
124
|
+
json: "keep",
|
|
125
|
+
usage: "<graph-file | site-directory> [--name <slug>] [--scope <team>] [--protected]",
|
|
126
|
+
summary: "Export and deploy to Vercel as cascade-<slug>; print the link and record it in shares.json",
|
|
127
|
+
mcp: [{
|
|
128
|
+
name: "share",
|
|
129
|
+
description: "Share a graph's editor, or a static directory with an index.html, as one link (cascade share): export, deploy to the Vercel project cascade-<name> and return `url`, recorded in the project's shares.json. Public unless `protected`.",
|
|
130
|
+
inputSchema: object({
|
|
131
|
+
graph: { type: "string", description: "The .cascade file or site directory, relative to the project directory" },
|
|
132
|
+
name: { type: "string", description: "Slug; the Vercel project is cascade-<name> (default: the editor id or directory name)" },
|
|
133
|
+
scope: { type: "string", description: "Vercel team (default field-io)" },
|
|
134
|
+
protected: { type: "boolean", description: "Require Vercel Authentication instead of a public link" }
|
|
135
|
+
}, ["graph"]),
|
|
136
|
+
call: {
|
|
137
|
+
kind: "cli",
|
|
138
|
+
argv: (args, resolve) => [
|
|
139
|
+
"share",
|
|
140
|
+
resolve(args.graph),
|
|
141
|
+
...args.name ? ["--name", String(args.name)] : [],
|
|
142
|
+
...args.scope ? ["--scope", String(args.scope)] : [],
|
|
143
|
+
...args.protected ? ["--protected"] : []
|
|
144
|
+
],
|
|
145
|
+
timeoutMs: () => 10 * 6e4
|
|
146
|
+
}
|
|
147
|
+
}]
|
|
148
|
+
},
|
|
121
149
|
{ ...editorVerb, name: "publish", usage: "<graph-file> <node>.<prop> [--label ...]", summary: "Publish a node prop as an editor parameter" },
|
|
122
150
|
{ ...editorVerb, name: "freeze", usage: "<graph-file> <node> --fields <a,b>", summary: "Snapshot chosen fields of a live data source for export" },
|
|
123
151
|
{ ...editorVerb, name: "scene", usage: "<graph-file> <scene.json> --out <new-graph-file>", summary: "Apply a scene file to a copy of the graph" },
|
|
@@ -434,11 +462,11 @@ var VERBS = [
|
|
|
434
462
|
{
|
|
435
463
|
...lockVerb,
|
|
436
464
|
name: "ladder",
|
|
437
|
-
usage: "<graph-file> <node> --name <name> --vary <node.prop>=<a,b,c> | --seeds <a,b,c>",
|
|
438
|
-
summary: "Cook 3-5 variants, write a labelled contact sheet and ladders/<id>.json",
|
|
465
|
+
usage: "<graph-file> <node> --name <name> --vary <node.prop>=<a,b,c> | --seeds <a,b,c> [--cairn <vault dir>]",
|
|
466
|
+
summary: "Cook 3-5 variants, write a labelled contact sheet and ladders/<id>.json; --cairn makes a tap-to-pick card",
|
|
439
467
|
mcp: [{
|
|
440
468
|
name: "ladder",
|
|
441
|
-
description:
|
|
469
|
+
description: 'Cook `node` once per variant (cascade ladder) and return the contact sheet, each variant image and the record ladders/<id>.json. `vary` maps node.prop to a list of values (zipped; one value applies to all); `seeds` varies the graph seed. Three to five variants is the usual. `cairn` is a directory in the Substrate vault (the space\'s _attachments/ladders/<id>): each variant is copied there and `data.cairnChoice` is a cairn:choice fence to post as is (at most 8 variants); a tap comes back as "Picked: <label> (pick:<id>:<n>)", then call `pick` with ladder <id> and variant <n>.',
|
|
442
470
|
inputSchema: object({
|
|
443
471
|
graph,
|
|
444
472
|
node: { type: "string" },
|
|
@@ -447,7 +475,9 @@ var VERBS = [
|
|
|
447
475
|
seeds: { type: "array", items: { type: "integer" } },
|
|
448
476
|
columns: { type: "integer" },
|
|
449
477
|
note: { type: "string" },
|
|
450
|
-
live: { type: "boolean" }
|
|
478
|
+
live: { type: "boolean" },
|
|
479
|
+
cairn: { type: "string", description: "Absolute vault directory for the variant images; returns data.cairnChoice" },
|
|
480
|
+
vault: { type: "string", description: "Absolute vault root the cairnChoice image paths are relative to (default: nearest .obsidian or .git above `cairn`)" }
|
|
451
481
|
}, ["graph", "node", "name"]),
|
|
452
482
|
call: {
|
|
453
483
|
kind: "cli",
|
|
@@ -457,6 +487,9 @@ var VERBS = [
|
|
|
457
487
|
args.node,
|
|
458
488
|
"--name",
|
|
459
489
|
args.name,
|
|
490
|
+
// Outside the project by design (the vault), so passed as given: absolute.
|
|
491
|
+
...args.cairn ? ["--cairn", String(args.cairn)] : [],
|
|
492
|
+
...args.vault ? ["--vault", String(args.vault)] : [],
|
|
460
493
|
...Object.entries(args.vary ?? {}).flatMap(([key, values]) => [
|
|
461
494
|
"--vary",
|
|
462
495
|
`${key}=${(Array.isArray(values) ? values : [values]).map((value) => JSON.stringify(value)).join(",")}`
|
|
@@ -669,4 +702,4 @@ export {
|
|
|
669
702
|
graphCommandsHelp,
|
|
670
703
|
mainHelp
|
|
671
704
|
};
|
|
672
|
-
//# sourceMappingURL=chunk-
|
|
705
|
+
//# sourceMappingURL=chunk-G23A2BZZ.js.map
|
|
@@ -100,6 +100,23 @@ var Color = Object.freeze({
|
|
|
100
100
|
opaque(color) {
|
|
101
101
|
return [clamp(color[0]), clamp(color[1]), clamp(color[2]), 1];
|
|
102
102
|
},
|
|
103
|
+
/**
|
|
104
|
+
* A colour saved in an older shape, as the one colour: `{ r, g, b, a? }`
|
|
105
|
+
* (the class-based image nodes stored that until 2026-11-07) or three
|
|
106
|
+
* components, with alpha 1. Components above 1 are read as 0–255, the way
|
|
107
|
+
* those nodes read them. Anything else comes back unchanged, so a reader can
|
|
108
|
+
* apply this to every stored `color` value and validate the result.
|
|
109
|
+
*/
|
|
110
|
+
upgrade(value) {
|
|
111
|
+
const legacy = value !== null && typeof value === "object" && !Array.isArray(value) && "r" in value && "g" in value && "b" in value ? value : Array.isArray(value) && value.length === 3 ? { r: value[0], g: value[1], b: value[2] } : null;
|
|
112
|
+
if (!legacy) return value;
|
|
113
|
+
const parts = [legacy.r, legacy.g, legacy.b, legacy.a ?? 1];
|
|
114
|
+
if (!parts.every((part) => typeof part === "number" && Number.isFinite(part))) return value;
|
|
115
|
+
const numbers = parts;
|
|
116
|
+
const unit2 = numbers.slice(0, 3).every((part) => part <= 1);
|
|
117
|
+
const read = (part) => unit2 ? part : part / 255;
|
|
118
|
+
return [read(numbers[0]), read(numbers[1]), read(numbers[2]), legacy.a === void 0 ? 1 : read(numbers[3])];
|
|
119
|
+
},
|
|
103
120
|
/**
|
|
104
121
|
* Four unit components from anything indexable, clamping and defaulting a
|
|
105
122
|
* missing alpha to 1. The reader for a `Cd` attribute's flat array, and the
|
|
@@ -1438,10 +1455,11 @@ var registrationsById = new Map(
|
|
|
1438
1455
|
);
|
|
1439
1456
|
|
|
1440
1457
|
export {
|
|
1458
|
+
Color,
|
|
1441
1459
|
LIGHT_DEFAULTS,
|
|
1442
1460
|
isLight,
|
|
1443
1461
|
isScene,
|
|
1444
1462
|
geoNodeDefinitions,
|
|
1445
1463
|
geoNodeRegistrations
|
|
1446
1464
|
};
|
|
1447
|
-
//# sourceMappingURL=chunk-
|
|
1465
|
+
//# sourceMappingURL=chunk-GRIN2DDP.js.map
|