@field/cascade 0.8.0 → 0.11.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 +36 -3
- package/CHANGELOG.md +401 -0
- package/DESIGN.md +14 -0
- package/README.md +41 -26
- package/dist/assets/CodeEditor-4O7FQ__R.js +623 -0
- package/dist/assets/CodePanel-BU-autmq.js +2 -0
- package/dist/assets/{CustomNodeDialog-BQbEhIwL.js → CustomNodeDialog-BRpDfOV5.js} +1 -1
- package/dist/assets/OpenGraphDialog-BwbRlC0X.js +1 -0
- package/dist/assets/ProjectSettings-DLOXLxcA.js +2 -0
- package/dist/assets/SettingsDialog-Bz8JxISH.js +1 -0
- package/dist/assets/{VersionHistoryDialog-D6VBzSQ0.js → VersionHistoryDialog-D5Z0nJ5-.js} +2 -2
- package/dist/assets/{core-BInLG4gw.js → core-Yqi0Ni61.js} +8 -8
- package/dist/assets/{cssMode-DfR2qmYG.js → cssMode-CxUzc4vp.js} +1 -1
- package/dist/assets/definitions-GreEMXLV.js +1 -0
- package/dist/assets/{editor.api-Ck8_vgQV.js → editor.api-BNFb25CX.js} +1 -1
- package/dist/assets/{freemarker2-fVn10Wn3.js → freemarker2-0ZDnWxeM.js} +1 -1
- package/dist/assets/geo-u0n_jOsD.js +1 -0
- package/dist/assets/{handlebars-BCSchLT2.js → handlebars-Cy18MoaD.js} +1 -1
- package/dist/assets/{html-CVpSv_k9.js → html-B-2Dx7nq.js} +1 -1
- package/dist/assets/{htmlMode-Da4ESTv0.js → htmlMode-DUAc9B_d.js} +1 -1
- package/dist/assets/{image-BLn--oSF.js → image-cAa-Nu9O.js} +3 -3
- package/dist/assets/index-5ZtDAuy2.js +220 -0
- package/dist/assets/index-7vae6YFC.css +1 -0
- package/dist/assets/index-client-DqYmKstU.js +1 -0
- package/dist/assets/{javascript-BpX0Gvcf.js → javascript-DeQsDqP5.js} +1 -1
- package/dist/assets/{jsonMode-CsLqaou7.js → jsonMode-BiFwJVSk.js} +1 -1
- package/dist/assets/legacy-CTEeXeqF.js +2 -0
- package/dist/assets/{liquid-efUz51Wf.js → liquid-BLoHH68a.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-DCi5-K0n.js → lspLanguageFeatures-CNFgm1Kv.js} +1 -1
- package/dist/assets/math-DioIQOPJ.js +1 -0
- package/dist/assets/{mdx-DP_sjGVy.js → mdx-CFXQVNfs.js} +1 -1
- package/dist/assets/pop-DC_TQG9t.js +1 -0
- package/dist/assets/{python-aAuP3LUi.js → python-Cf7S7p2E.js} +1 -1
- package/dist/assets/{razor-7M6sMmC5.js → razor-CMHBcG-g.js} +1 -1
- package/dist/assets/studioScenes-8sq9FfFg.js +1 -0
- package/dist/assets/{tsMode-Bf4CnoYK.js → tsMode-BEih0GDj.js} +1 -1
- package/dist/assets/{typescript-ddhYBGyT.js → typescript-COEKYD_a.js} +1 -1
- package/dist/assets/{workers-X5la8DDT.js → workers-BNhAhMNn.js} +1 -1
- package/dist/assets/{xml-BzbXa3Ps.js → xml-CPiMpnPl.js} +1 -1
- package/dist/assets/{yaml-CXs-VzxL.js → yaml-Bgp1ITLR.js} +1 -1
- package/dist/cli/Graph-ZJJTRQTM.js +2975 -0
- package/dist/cli/chunk-2KXB47FP.js +115 -0
- package/dist/cli/chunk-35D343DC.js +1447 -0
- package/dist/cli/chunk-36P5K3SD.js +631 -0
- package/dist/cli/chunk-3JTJHF7V.js +267 -0
- package/dist/cli/chunk-4UDFYF5G.js +132 -0
- package/dist/cli/chunk-53NMBJAO.js +35 -0
- package/dist/cli/chunk-A4OAMOZH.js +310 -0
- package/dist/cli/chunk-BIJO5OFS.js +71 -0
- package/dist/cli/chunk-BP7UKF36.js +376 -0
- package/dist/cli/chunk-CKS2FQWR.js +89 -0
- package/dist/cli/chunk-CO22XHNG.js +593 -0
- package/dist/cli/chunk-D6BUOHUG.js +634 -0
- package/dist/cli/chunk-DEQSEFFH.js +153 -0
- package/dist/cli/chunk-DUIUFVU2.js +241 -0
- package/dist/cli/chunk-EUIAC3U3.js +3006 -0
- package/dist/cli/chunk-FCDXJ6EK.js +2208 -0
- package/dist/cli/chunk-GFS6W3C5.js +308 -0
- package/dist/cli/chunk-HFHWYL55.js +139 -0
- package/dist/cli/chunk-HSNOBIVT.js +263 -0
- package/dist/cli/chunk-ICH7N5PN.js +26 -0
- package/dist/cli/chunk-J7VK7MNF.js +418 -0
- package/dist/cli/chunk-KH4MUBKF.js +1551 -0
- package/dist/cli/chunk-MIIEFUGG.js +623 -0
- package/dist/cli/chunk-OWWBYLHC.js +136 -0
- package/dist/cli/chunk-POMMNKZZ.js +672 -0
- package/dist/cli/chunk-QBBKRNGY.js +90 -0
- package/dist/cli/chunk-QQPA2ZHH.js +273 -0
- package/dist/cli/chunk-RLCAJBVR.js +224 -0
- package/dist/cli/chunk-RQZ4SX5R.js +1125 -0
- package/dist/cli/chunk-RUU3YWXU.js +99 -0
- package/dist/cli/chunk-RXDIMXN5.js +98 -0
- package/dist/cli/chunk-SGJAET2L.js +197 -0
- package/dist/cli/chunk-VVGSLVSF.js +151 -0
- package/dist/cli/chunk-WD62JIP6.js +118 -0
- package/dist/cli/chunk-WIH4TEIS.js +104 -0
- package/dist/cli/chunk-WKURDVYP.js +1119 -0
- package/dist/cli/chunk-WPUDGEFY.js +20 -0
- package/dist/cli/chunk-XWDSKG7N.js +1301 -0
- package/dist/cli/chunk-YAT5Y25U.js +121 -0
- package/dist/cli/chunk-ZL4JTG5Y.js +37 -0
- package/dist/cli/cliCommands-UQSFGEHF.js +3464 -0
- package/dist/cli/commands-Q23M26QM.js +1292 -0
- package/dist/cli/definitions-HF2FTHYU.js +32 -0
- package/dist/cli/doctorCommand-B7BPQMN6.js +76 -0
- package/dist/cli/edit-JHCPTQFT.js +28 -0
- package/dist/cli/editorCommands-UIF5YLUZ.js +33 -0
- package/dist/cli/encode-HAUZTYPT.js +17 -0
- package/dist/cli/frames-LSAUBZ7P.js +16 -0
- package/dist/cli/geo-4RNK3QVN.js +43 -0
- package/dist/cli/graphCommands-6BMAKGQE.js +184 -0
- package/dist/cli/graphFile-VPSQ6OF7.js +286 -0
- package/dist/cli/headlessCanvas-5XLDZT7M.js +15 -0
- package/dist/cli/helpCommand-3VRE3KVO.js +155 -0
- package/dist/cli/index.js +106 -14207
- package/dist/cli/math-ZRMLKU2D.js +16 -0
- package/dist/cli/mcp-ZLEEMYGF.js +164 -0
- package/dist/cli/parity-KINARCP2.js +328 -0
- package/dist/cli/pop-USDFXB7H.js +39 -0
- package/dist/cli/project-K3QIPGBB.js +12 -0
- package/dist/cli/projectDefinition-DMTZN2NE.js +27 -0
- package/dist/cli/projectRuntime-Z5PJOH47.js +48 -0
- package/dist/cli/registerStandardNodes-S2VLMF6J.js +3081 -0
- package/dist/cli/render-YURAPPUI.js +436 -0
- package/dist/cli/runCommand-PI764LEG.js +198 -0
- package/dist/cli/runner-RA6UKEPD.js +37 -0
- package/dist/cli/runtime/image.ts +277 -0
- package/dist/cli/runtime/stage.ts +74 -11
- package/dist/cli/stageRunner-KUNIMQKJ.js +10 -0
- package/dist/cli/verbs-RCE3K4VQ.js +19 -0
- package/dist/cli/webBuild-GT4PZT5D.js +37 -0
- package/dist/contracts/bundle.d.ts +75 -0
- package/dist/contracts/bundle.js +112 -0
- package/dist/contracts/definition.d.ts +67 -4
- package/dist/contracts/document.d.ts +29 -0
- package/dist/contracts/documentFormat.d.ts +18 -0
- package/dist/contracts/documentFormat.js +195 -0
- package/dist/contracts/editor.d.ts +189 -0
- package/dist/contracts/editor.js +2 -0
- package/dist/contracts/index.d.ts +3 -0
- package/dist/contracts/index.js +3 -0
- package/dist/contracts/validate.js +59 -3
- package/dist/contracts/values.d.ts +3 -3
- package/dist/contracts/values.js +1 -0
- package/dist/image.d.ts +141 -0
- package/dist/image.js +127 -0
- package/dist/index.html +4 -4
- package/dist/player/app.js +17 -5
- package/dist/player/editor.js +1919 -0
- package/dist/player/editorEngine.js +477 -0
- package/dist/runtime/builtins/core/bundle.d.ts +70 -0
- package/dist/runtime/builtins/core/bundle.js +81 -0
- package/dist/runtime/builtins/core/index.d.ts +3 -2
- package/dist/runtime/builtins/core/index.js +6 -2
- package/dist/runtime/builtins/core/routing.d.ts +27 -0
- package/dist/runtime/builtins/core/routing.js +28 -0
- package/dist/runtime/builtins/headless.d.ts +19 -0
- package/dist/runtime/builtins/headless.js +25 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +226 -0
- package/dist/runtime/builtins/image/contactSheet.js +199 -0
- package/dist/runtime/builtins/image/index.d.ts +9 -0
- package/dist/runtime/builtins/image/index.js +9 -0
- package/dist/runtime/edit/document.d.ts +94 -0
- package/dist/runtime/edit/document.js +194 -0
- package/dist/runtime/edit/graphEditor.d.ts +223 -0
- package/dist/runtime/edit/graphEditor.js +893 -0
- package/dist/runtime/edit/index.d.ts +12 -0
- package/dist/runtime/edit/index.js +6 -0
- package/dist/runtime/edit/layout.d.ts +50 -0
- package/dist/runtime/edit/layout.js +126 -0
- package/dist/runtime/edit/operations.d.ts +65 -0
- package/dist/runtime/edit/operations.js +57 -0
- package/dist/runtime/edit/parameters.d.ts +75 -0
- package/dist/runtime/edit/parameters.js +284 -0
- package/dist/runtime/edit/read.d.ts +35 -0
- package/dist/runtime/edit/read.js +65 -0
- package/dist/runtime/editor/index.d.ts +104 -0
- package/dist/runtime/editor/index.js +439 -0
- package/dist/runtime/expressions/bundlePaths.d.ts +37 -0
- package/dist/runtime/expressions/bundlePaths.js +55 -0
- package/dist/runtime/expressions/index.d.ts +2 -0
- package/dist/runtime/expressions/index.js +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/params/animator.d.ts +5 -0
- package/dist/runtime/params/animator.js +16 -0
- package/dist/runtime/runtime.js +238 -12
- package/dist/runtime/seed.d.ts +29 -0
- package/dist/runtime/seed.js +52 -0
- package/dist/runtime/types.d.ts +12 -0
- package/dist/stage.js +43 -9
- package/dist/studio/panel.d.ts +2 -0
- package/doc/CLI_REFERENCE.md +171 -0
- package/doc/EDITOR_EXPORT.md +235 -0
- package/doc/HEADLESS_GPU.md +27 -0
- package/doc/MCP.md +69 -0
- package/doc/NODE_REFERENCE.md +208 -0
- package/doc/PROJECT_AUTHORING.md +258 -1
- package/package.json +29 -8
- package/dist/assets/CodeEditor-BEk-kIBd.js +0 -623
- package/dist/assets/CodePanel-CeSdjXkg.js +0 -2
- package/dist/assets/ExportDialog-CjTbbTZJ.js +0 -358
- package/dist/assets/ExportDialog-DOq0flMV.css +0 -1
- package/dist/assets/OpenGraphDialog-DCwH9itM.js +0 -1
- package/dist/assets/ProjectSettings-Dg7M5xt9.js +0 -2
- package/dist/assets/SettingsDialog-e7GgsjB9.js +0 -1
- package/dist/assets/definitions-DZpOjWKR.js +0 -1
- package/dist/assets/geo-D2VPjAdt.js +0 -1
- package/dist/assets/index-CMiBdEuT.js +0 -212
- package/dist/assets/index-DMIuml9a.css +0 -1
- package/dist/assets/index-client-BI2H82FJ.js +0 -1
- package/dist/assets/legacy-ZA7textG.js +0 -2
- package/dist/assets/math-B6hpxPJO.js +0 -1
- package/dist/assets/pop-CYUIjT6x.js +0 -1
- package/dist/assets/projectSettingsApi-C1WvIwfP.js +0 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PythonWorker,
|
|
3
|
+
callStage,
|
|
4
|
+
stageSources
|
|
5
|
+
} from "./chunk-MIIEFUGG.js";
|
|
6
|
+
import {
|
|
7
|
+
readStageConfig,
|
|
8
|
+
runProjectStage
|
|
9
|
+
} from "./chunk-VVGSLVSF.js";
|
|
10
|
+
|
|
11
|
+
// server/src/runtime/stage.ts
|
|
12
|
+
var BRIDGE_KEY = "__cascadeStageBridge";
|
|
13
|
+
function installStageBridge(bridge) {
|
|
14
|
+
const globals = globalThis;
|
|
15
|
+
const previous = globals[BRIDGE_KEY];
|
|
16
|
+
globals[BRIDGE_KEY] = bridge ?? void 0;
|
|
17
|
+
return () => {
|
|
18
|
+
globals[BRIDGE_KEY] = previous;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/cli/projectStages.ts
|
|
23
|
+
function installProjectStages(project, options = {}) {
|
|
24
|
+
let worker = null;
|
|
25
|
+
const warmWorker = (config) => {
|
|
26
|
+
if (options.worker === false || !config.worker) return null;
|
|
27
|
+
const sources = stageSources(project, config);
|
|
28
|
+
const key = `${config.python}\0${config.worker}\0${sources.roots.join("\0")}`;
|
|
29
|
+
if (worker?.key !== key) {
|
|
30
|
+
worker?.process.shutdown();
|
|
31
|
+
worker = {
|
|
32
|
+
key,
|
|
33
|
+
process: new PythonWorker(project, config.worker, config.python, process.env, {
|
|
34
|
+
sources,
|
|
35
|
+
// The one-shot path's bound, not Studio's two minutes: an offline
|
|
36
|
+
// render may run a stage for several.
|
|
37
|
+
requestTimeoutMs: 10 * 60 * 1e3,
|
|
38
|
+
// What a stage prints is shown with --verbose only, as before.
|
|
39
|
+
onStderr: options.onOutput ? (text) => {
|
|
40
|
+
for (const line of text.split("\n")) options.onOutput(null, "stderr", line);
|
|
41
|
+
} : options.verbose ? (text) => {
|
|
42
|
+
for (const line of text.split("\n")) console.warn(`[stage-worker] ${line}`);
|
|
43
|
+
} : () => {
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return worker.process;
|
|
49
|
+
};
|
|
50
|
+
const dispose = installStageBridge(async (stage, args, callOptions) => {
|
|
51
|
+
const config = readStageConfig(project);
|
|
52
|
+
const warm = warmWorker(config);
|
|
53
|
+
if (warm) {
|
|
54
|
+
const { result: result2 } = await callStage(project, config, stage, args, (envelope) => warm.callWithMeta(stage, args, { signal: callOptions?.signal, cascade: envelope }), { onTrace: options.onTrace });
|
|
55
|
+
return result2;
|
|
56
|
+
}
|
|
57
|
+
const { result } = await callStage(project, config, stage, args, async (envelope) => ({
|
|
58
|
+
result: await runProjectStage(project, stage, args, {
|
|
59
|
+
// A superseded cook kills its subprocess rather than waiting for it.
|
|
60
|
+
signal: callOptions?.signal,
|
|
61
|
+
cascade: envelope,
|
|
62
|
+
codeHash: envelope.code,
|
|
63
|
+
/**
|
|
64
|
+
* A stage can log, and until 0.8 nobody could read it: `stderr` was
|
|
65
|
+
* consulted only on failure and `stdout` only for its last line. Behind
|
|
66
|
+
* `--verbose`, because a stage that prints per mark would bury the
|
|
67
|
+
* render it is part of; prefixed with the stage name, because a graph
|
|
68
|
+
* runs several.
|
|
69
|
+
*/
|
|
70
|
+
onOutput: options.onOutput ? (stream, text) => {
|
|
71
|
+
for (const line of text.split("\n")) options.onOutput(stage, stream, line);
|
|
72
|
+
} : options.verbose ? (stream, text) => {
|
|
73
|
+
const write = stream === "stderr" ? console.warn : console.log;
|
|
74
|
+
for (const line of text.split("\n")) write(`[${stage}] ${line}`);
|
|
75
|
+
} : void 0
|
|
76
|
+
})
|
|
77
|
+
}), { onTrace: options.onTrace });
|
|
78
|
+
return result;
|
|
79
|
+
});
|
|
80
|
+
return () => {
|
|
81
|
+
dispose();
|
|
82
|
+
worker?.process.shutdown();
|
|
83
|
+
worker = null;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
installProjectStages
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=chunk-QBBKRNGY.js.map
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
// packages/runtime/src/builtins/math/definitions.ts
|
|
2
|
+
function asComponents(value, label2) {
|
|
3
|
+
if (typeof value === "number") return [value];
|
|
4
|
+
if (Array.isArray(value) && value.every((part) => typeof part === "number"))
|
|
5
|
+
return value;
|
|
6
|
+
if (value === void 0 || value === null) return [0];
|
|
7
|
+
throw new Error(
|
|
8
|
+
`${label2} needs a number or a vector of numbers, and got ${describe(value)}`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
function describe(value) {
|
|
12
|
+
if (Array.isArray(value)) return `an array of ${value.length}`;
|
|
13
|
+
return `a ${typeof value}`;
|
|
14
|
+
}
|
|
15
|
+
function combine(left, right, operate) {
|
|
16
|
+
const a = asComponents(left, "the first input");
|
|
17
|
+
const b = asComponents(right, "the second input");
|
|
18
|
+
if (a.length !== b.length && a.length !== 1 && b.length !== 1)
|
|
19
|
+
throw new Error(
|
|
20
|
+
`cannot combine a vector of ${a.length} with a vector of ${b.length}`
|
|
21
|
+
);
|
|
22
|
+
const width = Math.max(a.length, b.length);
|
|
23
|
+
const out = [];
|
|
24
|
+
for (let index = 0; index < width; index += 1)
|
|
25
|
+
out.push(operate(a[a.length === 1 ? 0 : index], b[b.length === 1 ? 0 : index]));
|
|
26
|
+
return width === 1 ? out[0] : out;
|
|
27
|
+
}
|
|
28
|
+
function map(value, operate) {
|
|
29
|
+
const components = asComponents(value, "the input");
|
|
30
|
+
const out = components.map(operate);
|
|
31
|
+
return out.length === 1 ? out[0] : out;
|
|
32
|
+
}
|
|
33
|
+
function divide(a, b) {
|
|
34
|
+
return b === 0 ? 0 : a / b;
|
|
35
|
+
}
|
|
36
|
+
var BINARY = {
|
|
37
|
+
add: (a, b) => a + b,
|
|
38
|
+
subtract: (a, b) => a - b,
|
|
39
|
+
multiply: (a, b) => a * b,
|
|
40
|
+
divide,
|
|
41
|
+
power: (a, b) => a ** b,
|
|
42
|
+
modulo: (a, b) => b === 0 ? 0 : a % b,
|
|
43
|
+
min: (a, b) => Math.min(a, b),
|
|
44
|
+
max: (a, b) => Math.max(a, b),
|
|
45
|
+
atan2: (a, b) => Math.atan2(a, b)
|
|
46
|
+
};
|
|
47
|
+
var DEG = Math.PI / 180;
|
|
48
|
+
var UNARY = {
|
|
49
|
+
abs: Math.abs,
|
|
50
|
+
negate: (a) => -a,
|
|
51
|
+
floor: Math.floor,
|
|
52
|
+
ceil: Math.ceil,
|
|
53
|
+
round: Math.round,
|
|
54
|
+
sqrt: (a) => a < 0 ? 0 : Math.sqrt(a),
|
|
55
|
+
sign: Math.sign,
|
|
56
|
+
// Trigonometry in RADIANS, matching the expression engine, where bare `sin`
|
|
57
|
+
// is radians too. `radians` and `degrees` are here for the conversion, and
|
|
58
|
+
// the divergence from `Transform`'s degrees is recorded in AGENTS.md.
|
|
59
|
+
sin: Math.sin,
|
|
60
|
+
cos: Math.cos,
|
|
61
|
+
tan: Math.tan,
|
|
62
|
+
asin: (a) => Math.asin(Math.max(-1, Math.min(1, a))),
|
|
63
|
+
acos: (a) => Math.acos(Math.max(-1, Math.min(1, a))),
|
|
64
|
+
exp: Math.exp,
|
|
65
|
+
log: (a) => a <= 0 ? 0 : Math.log(a),
|
|
66
|
+
radians: (a) => a * DEG,
|
|
67
|
+
degrees: (a) => a / DEG,
|
|
68
|
+
/** The fractional part, always positive — `fract(-0.25)` is `0.75`, which is
|
|
69
|
+
* what a repeating pattern wants and what GLSL's `fract` does. */
|
|
70
|
+
fract: (a) => a - Math.floor(a)
|
|
71
|
+
};
|
|
72
|
+
var COMPARE = {
|
|
73
|
+
greater: (a, b) => a > b,
|
|
74
|
+
"greater-or-equal": (a, b) => a >= b,
|
|
75
|
+
less: (a, b) => a < b,
|
|
76
|
+
"less-or-equal": (a, b) => a <= b,
|
|
77
|
+
equal: (a, b) => a === b,
|
|
78
|
+
"not-equal": (a, b) => a !== b
|
|
79
|
+
};
|
|
80
|
+
function options(table) {
|
|
81
|
+
return Object.keys(table).map((value) => ({ value, label: label(value) }));
|
|
82
|
+
}
|
|
83
|
+
function label(value) {
|
|
84
|
+
return value.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
85
|
+
}
|
|
86
|
+
var binaryDefinition = {
|
|
87
|
+
apiVersion: 1,
|
|
88
|
+
label: "Binary Math",
|
|
89
|
+
description: "Two values, one operation. Component-wise, and a scalar broadcasts against a vector.",
|
|
90
|
+
icon: "Plus",
|
|
91
|
+
runsOn: "portable",
|
|
92
|
+
inputs: {
|
|
93
|
+
a: { kind: "data", type: "any", default: 0, description: "First value." },
|
|
94
|
+
b: { kind: "data", type: "any", default: 0, description: "Second value." }
|
|
95
|
+
},
|
|
96
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
97
|
+
props: {
|
|
98
|
+
operation: {
|
|
99
|
+
type: "string",
|
|
100
|
+
default: "add",
|
|
101
|
+
control: "select",
|
|
102
|
+
options: options(BINARY),
|
|
103
|
+
label: "Operation"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
function executeBinary(context) {
|
|
108
|
+
const operate = BINARY[context.props.operation];
|
|
109
|
+
if (!operate)
|
|
110
|
+
throw new Error(
|
|
111
|
+
`cascade.math.Binary has no operation "${context.props.operation}"`
|
|
112
|
+
);
|
|
113
|
+
context.outputs.value.set(combine(context.inputs.a, context.inputs.b, operate));
|
|
114
|
+
}
|
|
115
|
+
var unaryDefinition = {
|
|
116
|
+
apiVersion: 1,
|
|
117
|
+
label: "Unary Math",
|
|
118
|
+
description: "One value, one operation. Trigonometry is in radians.",
|
|
119
|
+
icon: "FunctionSquare",
|
|
120
|
+
runsOn: "portable",
|
|
121
|
+
inputs: {
|
|
122
|
+
value: { kind: "data", type: "any", default: 0 }
|
|
123
|
+
},
|
|
124
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
125
|
+
props: {
|
|
126
|
+
operation: {
|
|
127
|
+
type: "string",
|
|
128
|
+
default: "abs",
|
|
129
|
+
control: "select",
|
|
130
|
+
options: options(UNARY),
|
|
131
|
+
label: "Operation"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
function executeUnary(context) {
|
|
136
|
+
const operate = UNARY[context.props.operation];
|
|
137
|
+
if (!operate)
|
|
138
|
+
throw new Error(
|
|
139
|
+
`cascade.math.Unary has no operation "${context.props.operation}"`
|
|
140
|
+
);
|
|
141
|
+
context.outputs.value.set(map(context.inputs.value, operate));
|
|
142
|
+
}
|
|
143
|
+
var clampDefinition = {
|
|
144
|
+
apiVersion: 1,
|
|
145
|
+
label: "Clamp",
|
|
146
|
+
description: "Hold a value between two bounds.",
|
|
147
|
+
icon: "Brackets",
|
|
148
|
+
runsOn: "portable",
|
|
149
|
+
inputs: {
|
|
150
|
+
value: { kind: "data", type: "any", default: 0 },
|
|
151
|
+
min: { kind: "data", type: "any", default: 0 },
|
|
152
|
+
max: { kind: "data", type: "any", default: 1 }
|
|
153
|
+
},
|
|
154
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
155
|
+
props: {}
|
|
156
|
+
};
|
|
157
|
+
function executeClamp(context) {
|
|
158
|
+
const lower = combine(context.inputs.value, context.inputs.min, Math.max);
|
|
159
|
+
context.outputs.value.set(combine(lower, context.inputs.max, Math.min));
|
|
160
|
+
}
|
|
161
|
+
var mixDefinition = {
|
|
162
|
+
apiVersion: 1,
|
|
163
|
+
label: "Mix",
|
|
164
|
+
description: "Blend between two values. Houdini's lerp.",
|
|
165
|
+
icon: "Blend",
|
|
166
|
+
runsOn: "portable",
|
|
167
|
+
inputs: {
|
|
168
|
+
a: { kind: "data", type: "any", default: 0, description: "The value at 0." },
|
|
169
|
+
b: { kind: "data", type: "any", default: 1, description: "The value at 1." },
|
|
170
|
+
bias: {
|
|
171
|
+
kind: "data",
|
|
172
|
+
type: "float",
|
|
173
|
+
default: 0.5,
|
|
174
|
+
min: 0,
|
|
175
|
+
max: 1,
|
|
176
|
+
step: 0.01,
|
|
177
|
+
description: "Not clamped: past 0..1 this extrapolates, which is useful."
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
outputs: { value: { kind: "data", type: "any" } },
|
|
181
|
+
props: {}
|
|
182
|
+
};
|
|
183
|
+
function executeMix(context) {
|
|
184
|
+
const bias = context.inputs.bias ?? 0.5;
|
|
185
|
+
const delta = combine(context.inputs.b, context.inputs.a, (b, a) => b - a);
|
|
186
|
+
context.outputs.value.set(
|
|
187
|
+
combine(context.inputs.a, delta, (a, d) => a + d * bias)
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
var compareDefinition = {
|
|
191
|
+
apiVersion: 1,
|
|
192
|
+
label: "Compare",
|
|
193
|
+
description: "Test two values. Outputs a bool, for a Switch.",
|
|
194
|
+
icon: "Equal",
|
|
195
|
+
runsOn: "portable",
|
|
196
|
+
inputs: {
|
|
197
|
+
a: { kind: "data", type: "float", default: 0 },
|
|
198
|
+
b: { kind: "data", type: "float", default: 0 }
|
|
199
|
+
},
|
|
200
|
+
outputs: { result: { kind: "data", type: "bool" } },
|
|
201
|
+
props: {
|
|
202
|
+
operation: {
|
|
203
|
+
type: "string",
|
|
204
|
+
default: "greater",
|
|
205
|
+
control: "select",
|
|
206
|
+
options: options(COMPARE),
|
|
207
|
+
label: "Test"
|
|
208
|
+
},
|
|
209
|
+
/**
|
|
210
|
+
* Scalars only, unlike the rest of this namespace.
|
|
211
|
+
*
|
|
212
|
+
* "Is this vector greater than that one" has no single right answer — all
|
|
213
|
+
* components, any component, or the length — and a node that picked one
|
|
214
|
+
* silently would be wrong for the other two readings. A comparison feeding
|
|
215
|
+
* a `Switch` wants one boolean, so the input is a `float` and the question
|
|
216
|
+
* does not arise.
|
|
217
|
+
*/
|
|
218
|
+
tolerance: {
|
|
219
|
+
type: "float",
|
|
220
|
+
default: 0,
|
|
221
|
+
min: 0,
|
|
222
|
+
label: "Tolerance",
|
|
223
|
+
description: "Slack for Equal and Not Equal. Floating point rarely lands on exactly equal."
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
function executeCompare(context) {
|
|
228
|
+
const operation = context.props.operation;
|
|
229
|
+
const test = COMPARE[operation];
|
|
230
|
+
if (!test)
|
|
231
|
+
throw new Error(`cascade.math.Compare has no test "${context.props.operation}"`);
|
|
232
|
+
const a = context.inputs.a ?? 0;
|
|
233
|
+
const b = context.inputs.b ?? 0;
|
|
234
|
+
const tolerance = context.props.tolerance;
|
|
235
|
+
if (tolerance > 0 && (operation === "equal" || operation === "not-equal")) {
|
|
236
|
+
const near = Math.abs(a - b) <= tolerance;
|
|
237
|
+
context.outputs.result.set(operation === "equal" ? near : !near);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
context.outputs.result.set(test(a, b));
|
|
241
|
+
}
|
|
242
|
+
function registration(name, definition, execute) {
|
|
243
|
+
return {
|
|
244
|
+
kind: "definition-v1",
|
|
245
|
+
moduleId: `cascade.math.${name}`,
|
|
246
|
+
definition,
|
|
247
|
+
loadExecute: async () => execute
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
var binaryRegistration = registration("Binary", binaryDefinition, executeBinary);
|
|
251
|
+
var unaryRegistration = registration("Unary", unaryDefinition, executeUnary);
|
|
252
|
+
var clampRegistration = registration("Clamp", clampDefinition, executeClamp);
|
|
253
|
+
var mixRegistration = registration("Mix", mixDefinition, executeMix);
|
|
254
|
+
var compareRegistration = registration("Compare", compareDefinition, executeCompare);
|
|
255
|
+
var mathNodeRegistrations = Object.freeze([
|
|
256
|
+
binaryRegistration,
|
|
257
|
+
unaryRegistration,
|
|
258
|
+
clampRegistration,
|
|
259
|
+
mixRegistration,
|
|
260
|
+
compareRegistration
|
|
261
|
+
]);
|
|
262
|
+
var mathNodeDefinitions = Object.freeze([
|
|
263
|
+
["cascade.math.Binary", binaryDefinition],
|
|
264
|
+
["cascade.math.Unary", unaryDefinition],
|
|
265
|
+
["cascade.math.Clamp", clampDefinition],
|
|
266
|
+
["cascade.math.Mix", mixDefinition],
|
|
267
|
+
["cascade.math.Compare", compareDefinition]
|
|
268
|
+
]);
|
|
269
|
+
|
|
270
|
+
export {
|
|
271
|
+
mathNodeRegistrations
|
|
272
|
+
};
|
|
273
|
+
//# sourceMappingURL=chunk-QQPA2ZHH.js.map
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import {
|
|
2
|
+
browserAssetCapability
|
|
3
|
+
} from "./chunk-53NMBJAO.js";
|
|
4
|
+
import {
|
|
5
|
+
attachDefinition
|
|
6
|
+
} from "./chunk-SGJAET2L.js";
|
|
7
|
+
import {
|
|
8
|
+
createGpuHost
|
|
9
|
+
} from "./chunk-GFS6W3C5.js";
|
|
10
|
+
import {
|
|
11
|
+
validateNodeDefinition
|
|
12
|
+
} from "./chunk-A4OAMOZH.js";
|
|
13
|
+
|
|
14
|
+
// src/nodes/definition/browserShellCapability.ts
|
|
15
|
+
var capability = null;
|
|
16
|
+
function forgetShellCapability() {
|
|
17
|
+
capability = null;
|
|
18
|
+
}
|
|
19
|
+
async function token() {
|
|
20
|
+
if (capability) return capability;
|
|
21
|
+
const response = await fetch("/api/shell/capability", { cache: "no-store" });
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
response.status === 404 ? "The shell capability is disabled on this server. It is available on a loopback server, or one started with an explicit trusted host." : `Could not obtain the shell capability (${response.status})`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const { capability: issued } = await response.json();
|
|
28
|
+
if (typeof issued !== "string" || !issued) {
|
|
29
|
+
throw new Error("Server issued no shell capability");
|
|
30
|
+
}
|
|
31
|
+
capability = issued;
|
|
32
|
+
return issued;
|
|
33
|
+
}
|
|
34
|
+
function domSignal(signal) {
|
|
35
|
+
if (!signal) return void 0;
|
|
36
|
+
const controller = new AbortController();
|
|
37
|
+
if (signal.aborted) controller.abort(signal.reason);
|
|
38
|
+
else signal.addEventListener("abort", () => controller.abort(signal.reason), { once: true });
|
|
39
|
+
return controller.signal;
|
|
40
|
+
}
|
|
41
|
+
async function post(body, signal) {
|
|
42
|
+
const bridged = domSignal(signal);
|
|
43
|
+
const send = async (issued) => fetch("/api/shell", {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: {
|
|
46
|
+
"Content-Type": "application/json",
|
|
47
|
+
"X-Cascade-Shell-Capability": issued
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify(body),
|
|
50
|
+
...bridged ? { signal: bridged } : {}
|
|
51
|
+
});
|
|
52
|
+
let response = await send(await token());
|
|
53
|
+
if (response.status === 403) {
|
|
54
|
+
capability = null;
|
|
55
|
+
response = await send(await token());
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
}
|
|
59
|
+
function requestBody(command, args, options) {
|
|
60
|
+
const { signal: _signal, ...rest } = options ?? {};
|
|
61
|
+
return {
|
|
62
|
+
command,
|
|
63
|
+
...args ? { args } : {},
|
|
64
|
+
// `/api/shell` has always accepted execution options at the top level;
|
|
65
|
+
// keep the Studio adapter on that wire contract. Nesting them under
|
|
66
|
+
// `options` silently drops stdin, timeout, cwd and env in the route parser.
|
|
67
|
+
...rest
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function fail(response) {
|
|
71
|
+
let payload = null;
|
|
72
|
+
try {
|
|
73
|
+
payload = await response.json();
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
const message = typeof payload?.error === "string" ? payload.error : `Shell request failed (${response.status})`;
|
|
77
|
+
if (payload?.code === "COMMAND_NOT_ALLOWED") {
|
|
78
|
+
throw new Error(`${message}. Add it under Allowed Commands in Project Settings.`);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(message);
|
|
81
|
+
}
|
|
82
|
+
var browserShellCapability = {
|
|
83
|
+
async run(command, args, options) {
|
|
84
|
+
const response = await post(requestBody(command, args, options), options?.signal);
|
|
85
|
+
if (!response.ok) await fail(response);
|
|
86
|
+
const { ok: _ok, ...result } = await response.json();
|
|
87
|
+
return result;
|
|
88
|
+
},
|
|
89
|
+
async runJson(command, args, options) {
|
|
90
|
+
const result = await this.run(command, args, options);
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(result.stdout);
|
|
93
|
+
} catch {
|
|
94
|
+
throw new Error(`${command} did not print JSON`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
async function shellRouteAvailable() {
|
|
99
|
+
const forget = () => {
|
|
100
|
+
forgetShellCapability();
|
|
101
|
+
return false;
|
|
102
|
+
};
|
|
103
|
+
if (typeof fetch !== "function") return forget();
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch("/api/shell/capability", { cache: "no-store" });
|
|
106
|
+
if (!response.ok) return forget();
|
|
107
|
+
const { capability: issued } = await response.json();
|
|
108
|
+
if (typeof issued !== "string" || !issued) return forget();
|
|
109
|
+
capability = issued;
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return forget();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/browser/gpu.ts
|
|
117
|
+
function createBrowserGpuHost() {
|
|
118
|
+
const gpu = globalThis.navigator?.gpu;
|
|
119
|
+
if (!gpu) return void 0;
|
|
120
|
+
return createGpuHost({
|
|
121
|
+
async acquire() {
|
|
122
|
+
const adapter = await gpu.requestAdapter();
|
|
123
|
+
if (!adapter) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"No WebGPU adapter is available \u2014 the browser reports WebGPU but the system offers no GPU to render on."
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const device = await adapter.requestDevice();
|
|
129
|
+
const info = adapter.info;
|
|
130
|
+
return {
|
|
131
|
+
device,
|
|
132
|
+
info: {
|
|
133
|
+
vendor: info?.vendor ?? "",
|
|
134
|
+
architecture: info?.architecture ?? "",
|
|
135
|
+
device: info?.device ?? "",
|
|
136
|
+
description: info?.description ?? ""
|
|
137
|
+
},
|
|
138
|
+
limits: device.limits ?? adapter.limits
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/nodes/definition/projectDefinition.ts
|
|
145
|
+
var studioCapabilities = {
|
|
146
|
+
assets: browserAssetCapability,
|
|
147
|
+
// Installed only where the browser has WebGPU, and absent rather than
|
|
148
|
+
// stubbed otherwise. That is what makes the failure a sentence: the preflight
|
|
149
|
+
// reports `runtime/missing-capability` and the adapter throws "requires the
|
|
150
|
+
// Studio gpu capability", both naming what is missing. A stub that threw on
|
|
151
|
+
// first use would name nothing.
|
|
152
|
+
...gpuCapabilityIfAvailable(),
|
|
153
|
+
/**
|
|
154
|
+
* Shell is present up front and withdrawn if the route turns out not to be
|
|
155
|
+
* there, which is the opposite way round from gpu and worth the sentence.
|
|
156
|
+
*
|
|
157
|
+
* `navigator.gpu` is a synchronous check, so gpu can be absent from the map
|
|
158
|
+
* before anything reads it. Whether the shell route exists takes a fetch, and
|
|
159
|
+
* this object is a module-level const read by three default parameters — so
|
|
160
|
+
* the choice is between delaying Studio's boot on a request, racing the
|
|
161
|
+
* probe, or installing and withdrawing. Installing is the one where the
|
|
162
|
+
* common case (a loopback server, where the route is always there) has no
|
|
163
|
+
* race at all and no cost.
|
|
164
|
+
*
|
|
165
|
+
* What it costs: on a server that does NOT offer the route, a cook in the
|
|
166
|
+
* first few milliseconds after boot sees the capability present and fails at
|
|
167
|
+
* the fetch instead of at the gate. That failure still names itself — *"the
|
|
168
|
+
* shell capability is disabled on this server"* — so it is a worse-shaped
|
|
169
|
+
* error rather than a silent one, and once the probe lands the preflight is
|
|
170
|
+
* correct from then on.
|
|
171
|
+
*/
|
|
172
|
+
shell: browserShellCapability
|
|
173
|
+
};
|
|
174
|
+
void shellRouteAvailable().then((available) => {
|
|
175
|
+
if (!available) delete studioCapabilities.shell;
|
|
176
|
+
});
|
|
177
|
+
function gpuCapabilityIfAvailable() {
|
|
178
|
+
const gpu = createBrowserGpuHost();
|
|
179
|
+
return gpu ? { gpu } : {};
|
|
180
|
+
}
|
|
181
|
+
function declaresDefinitionV1(value) {
|
|
182
|
+
return typeof value === "object" && value !== null && value.apiVersion === 1;
|
|
183
|
+
}
|
|
184
|
+
function definitionAdapterError(value) {
|
|
185
|
+
const diagnostics = validateNodeDefinition(value);
|
|
186
|
+
if (!diagnostics.length) return null;
|
|
187
|
+
return diagnostics.map((item) => `${item.code}: ${item.message}`).join("\n");
|
|
188
|
+
}
|
|
189
|
+
function missingStudioCapabilities(definition, capabilities = studioCapabilities) {
|
|
190
|
+
const declared = definition?.capabilities;
|
|
191
|
+
if (!Array.isArray(declared)) return [];
|
|
192
|
+
return declared.filter((name) => typeof name === "string").filter((name) => !capabilities[name]);
|
|
193
|
+
}
|
|
194
|
+
function moduleNodeFunction(node, moduleId, modulePromise, capabilities = studioCapabilities) {
|
|
195
|
+
const prepared = modulePromise.then((module) => adaptModule(node, moduleId, module, capabilities));
|
|
196
|
+
prepared.catch(() => {
|
|
197
|
+
});
|
|
198
|
+
return (n, g) => prepared.then((fn) => fn(n, g));
|
|
199
|
+
}
|
|
200
|
+
function adaptModule(node, moduleId, module, capabilities = studioCapabilities) {
|
|
201
|
+
if (!declaresDefinitionV1(module.definition)) {
|
|
202
|
+
return (n, g) => module.execute(n, g);
|
|
203
|
+
}
|
|
204
|
+
const invalid = definitionAdapterError(module.definition);
|
|
205
|
+
if (invalid) throw new Error(`${moduleId} exports an invalid definition-v1 literal:
|
|
206
|
+
${invalid}`);
|
|
207
|
+
const registration = {
|
|
208
|
+
kind: "definition-v1",
|
|
209
|
+
moduleId,
|
|
210
|
+
definition: module.definition,
|
|
211
|
+
loadExecute: async () => module.execute
|
|
212
|
+
};
|
|
213
|
+
return attachDefinition(node, registration, capabilities);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export {
|
|
217
|
+
studioCapabilities,
|
|
218
|
+
declaresDefinitionV1,
|
|
219
|
+
definitionAdapterError,
|
|
220
|
+
missingStudioCapabilities,
|
|
221
|
+
moduleNodeFunction,
|
|
222
|
+
adaptModule
|
|
223
|
+
};
|
|
224
|
+
//# sourceMappingURL=chunk-RLCAJBVR.js.map
|