@field/cascade 0.2.22
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 +168 -0
- package/ARCHITECTURE.md +137 -0
- package/DESIGN.md +161 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/dist/assets/CodeEditor-DR7u0q7p.css +1 -0
- package/dist/assets/CodeEditor-DoaNEUaM.js +641 -0
- package/dist/assets/CodePanel-B0_2XJ-t.js +2 -0
- package/dist/assets/CodePanel-IT1secyI.css +1 -0
- package/dist/assets/CustomNodeDialog-026lzecD.js +1 -0
- package/dist/assets/CustomNodeDialog-JGYnWY6m.css +1 -0
- package/dist/assets/ExportDialog-DOq0flMV.css +1 -0
- package/dist/assets/ExportDialog-DWN4nhXI.js +358 -0
- package/dist/assets/ProjectSettings-BzT164Yx.js +2 -0
- package/dist/assets/ProjectSettings-DdO9xoQz.css +1 -0
- package/dist/assets/SettingsDialog-CeK7ytpY.css +1 -0
- package/dist/assets/SettingsDialog-DmHb1V0r.js +1 -0
- package/dist/assets/VersionHistoryDialog-CWNmHQ-P.css +1 -0
- package/dist/assets/VersionHistoryDialog-hH6VsXLX.js +3 -0
- package/dist/assets/abap-08VXUWAP.js +1 -0
- package/dist/assets/apex-BWPQTe0t.js +1 -0
- package/dist/assets/azcli-Bc_sGQ0U.js +1 -0
- package/dist/assets/bat-i0X4ZdIN.js +1 -0
- package/dist/assets/bicep-B5-_aFwp.js +2 -0
- package/dist/assets/cameligo-DMUM7wLl.js +1 -0
- package/dist/assets/cascade.jpg +0 -0
- package/dist/assets/clojure-Cm7r79vr.js +1 -0
- package/dist/assets/codicon-Brq4_Ui5.ttf +0 -0
- package/dist/assets/coffee-Ba7i2nA0.js +1 -0
- package/dist/assets/core-Bji4aZUU.js +965 -0
- package/dist/assets/cpp-C7h46wYY.js +1 -0
- package/dist/assets/csharp-BKxtCVv1.js +1 -0
- package/dist/assets/csp-bTuwJoIa.js +1 -0
- package/dist/assets/css-DIMkf-bt.js +3 -0
- package/dist/assets/css.worker-B3ciXF_0.js +93 -0
- package/dist/assets/cssMode-B6Z_Q1Kh.js +1 -0
- package/dist/assets/cypher-CVaqCwHa.js +1 -0
- package/dist/assets/dart-onAF5SnQ.js +1 -0
- package/dist/assets/dockerfile-DZFCIeNp.js +1 -0
- package/dist/assets/ecl-D05T4iGw.js +1 -0
- package/dist/assets/editor-1FQrmyyI.css +1 -0
- package/dist/assets/editor.api-jMoW_43X.js +847 -0
- package/dist/assets/editor.worker-q-txB4vs.js +30 -0
- package/dist/assets/elixir-6RTg0lbw.js +1 -0
- package/dist/assets/flow9-C5_-GSwl.js +1 -0
- package/dist/assets/freemarker2-DvvPV6m5.js +3 -0
- package/dist/assets/fsharp-C8Ef5oNN.js +1 -0
- package/dist/assets/geo-CXmCtzMM.js +2 -0
- package/dist/assets/go-C-y9NEjX.js +1 -0
- package/dist/assets/graphql-fmXr3nnJ.js +1 -0
- package/dist/assets/handlebars-B8rfuSIa.js +1 -0
- package/dist/assets/hcl-CpzslTdj.js +1 -0
- package/dist/assets/html-DyHm6JCp.js +1 -0
- package/dist/assets/html.worker-C93Ht9o9.js +506 -0
- package/dist/assets/htmlMode-E9XLWE5u.js +1 -0
- package/dist/assets/image-BUcQC7PG.js +2076 -0
- package/dist/assets/index-BXYXSdgh.js +224 -0
- package/dist/assets/index-CrNke7SW.css +1 -0
- package/dist/assets/index-client-DN_FvjN8.js +1 -0
- package/dist/assets/ini-sBoK_t0W.js +1 -0
- package/dist/assets/java-BEtHBSE6.js +1 -0
- package/dist/assets/javascript-C_bM5PCN.js +1 -0
- package/dist/assets/json.worker-B2V3pomh.js +62 -0
- package/dist/assets/jsonMode-BdyVS7G4.js +7 -0
- package/dist/assets/julia-Bri6UV-V.js +1 -0
- package/dist/assets/kotlin-BOotOW0E.js +1 -0
- package/dist/assets/legacy-DIu3XRwl.js +2 -0
- package/dist/assets/less-B9JPFI3C.js +2 -0
- package/dist/assets/lexon-CfSJPG6W.js +1 -0
- package/dist/assets/liquid-CDkn3spA.js +1 -0
- package/dist/assets/lspLanguageFeatures-AB5DMAsr.js +4 -0
- package/dist/assets/lua-CsQS60Ue.js +1 -0
- package/dist/assets/m3-D-oSqn_W.js +1 -0
- package/dist/assets/markdown-Cimd5fb3.js +1 -0
- package/dist/assets/mdx-BvH_NjDN.js +1 -0
- package/dist/assets/mips-CIPQ_RoX.js +1 -0
- package/dist/assets/msdax-DauUninz.js +1 -0
- package/dist/assets/mysql-SOo6toE5.js +1 -0
- package/dist/assets/nodeTypeUtils-CweA3NHd.js +1 -0
- package/dist/assets/objective-c-FvmIjYaQ.js +1 -0
- package/dist/assets/pascal-DrH0SRf2.js +1 -0
- package/dist/assets/pascaligo-D-ptJ9y-.js +1 -0
- package/dist/assets/perl-oz_6vUea.js +1 -0
- package/dist/assets/pgsql-DTj74zXo.js +1 -0
- package/dist/assets/php-nr791fC2.js +1 -0
- package/dist/assets/pla-CopQ2nXW.js +1 -0
- package/dist/assets/postiats-43DmfD33.js +1 -0
- package/dist/assets/powerquery-D3hlyOfw.js +1 -0
- package/dist/assets/powershell-DmHpPYUd.js +1 -0
- package/dist/assets/projectSettingsApi-C1WvIwfP.js +1 -0
- package/dist/assets/protobuf-C531GsRP.js +2 -0
- package/dist/assets/pug-Z5eAx3Zn.js +1 -0
- package/dist/assets/python-B7uii4fi.js +1 -0
- package/dist/assets/qsharp-DkqhCAOL.js +1 -0
- package/dist/assets/quill-DjZ69wL_.js +121 -0
- package/dist/assets/r-BwWrilGY.js +1 -0
- package/dist/assets/razor-Z48fWdJc.js +1 -0
- package/dist/assets/redis-ClamHrr6.js +1 -0
- package/dist/assets/redshift-DT7zqm-g.js +1 -0
- package/dist/assets/restructuredtext-BYgofb2h.js +1 -0
- package/dist/assets/ruby-DezsRK8O.js +1 -0
- package/dist/assets/rust-DdL9SqIa.js +1 -0
- package/dist/assets/sb-CcwsVR0C.js +1 -0
- package/dist/assets/scala-DHpiXF5c.js +1 -0
- package/dist/assets/scheme-BeGwcela.js +1 -0
- package/dist/assets/scss-gp-XZpBa.js +3 -0
- package/dist/assets/shell-CC2rA5mh.js +1 -0
- package/dist/assets/solidity-BEEn4gHE.js +1 -0
- package/dist/assets/sophia-CRfGWb83.js +1 -0
- package/dist/assets/sparql-D_Lu-MrJ.js +1 -0
- package/dist/assets/sql-NEE52Syq.js +1 -0
- package/dist/assets/st-DbInun42.js +1 -0
- package/dist/assets/swift-Bxkupp3x.js +1 -0
- package/dist/assets/systemverilog-Bz4Y3fRF.js +1 -0
- package/dist/assets/tcl-DISqw1ZD.js +1 -0
- package/dist/assets/ts.worker-D7T1-Ig5.js +67738 -0
- package/dist/assets/tsMode-BDgacVG4.js +11 -0
- package/dist/assets/twig-De2hgUGE.js +1 -0
- package/dist/assets/typescript-Derb6Oqa.js +1 -0
- package/dist/assets/typespec-B8J7ngcE.js +1 -0
- package/dist/assets/vb-DV3o63ZY.js +1 -0
- package/dist/assets/wgsl-DpFanUEy.js +298 -0
- package/dist/assets/workers-BtoMX_pm.js +1 -0
- package/dist/assets/xml-B1CaFSrG.js +1 -0
- package/dist/assets/yaml-HmIeA0KH.js +1 -0
- package/dist/cli/index.js +11377 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/runtime/io.ts +445 -0
- package/dist/cli/runtime/net.ts +19 -0
- package/dist/cli/runtime/shell.ts +46 -0
- package/dist/cli/runtime/stage.ts +132 -0
- package/dist/contracts/capabilities.d.ts +109 -0
- package/dist/contracts/capabilities.d.ts.map +1 -0
- package/dist/contracts/capabilities.js +11 -0
- package/dist/contracts/capabilities.js.map +1 -0
- package/dist/contracts/color.d.ts +67 -0
- package/dist/contracts/color.d.ts.map +1 -0
- package/dist/contracts/color.js +83 -0
- package/dist/contracts/color.js.map +1 -0
- package/dist/contracts/definition.d.ts +118 -0
- package/dist/contracts/definition.d.ts.map +1 -0
- package/dist/contracts/definition.js +2 -0
- package/dist/contracts/definition.js.map +1 -0
- package/dist/contracts/document.d.ts +50 -0
- package/dist/contracts/document.d.ts.map +1 -0
- package/dist/contracts/document.js +2 -0
- package/dist/contracts/document.js.map +1 -0
- package/dist/contracts/geometry.d.ts +301 -0
- package/dist/contracts/geometry.d.ts.map +1 -0
- package/dist/contracts/geometry.js +604 -0
- package/dist/contracts/geometry.js.map +1 -0
- package/dist/contracts/index.d.ts +8 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +8 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/schema.d.ts +6 -0
- package/dist/contracts/schema.d.ts.map +1 -0
- package/dist/contracts/schema.js +85 -0
- package/dist/contracts/schema.js.map +1 -0
- package/dist/contracts/validate.d.ts +13 -0
- package/dist/contracts/validate.d.ts.map +1 -0
- package/dist/contracts/validate.js +202 -0
- package/dist/contracts/validate.js.map +1 -0
- package/dist/contracts/values.d.ts +100 -0
- package/dist/contracts/values.d.ts.map +1 -0
- package/dist/contracts/values.js +59 -0
- package/dist/contracts/values.js.map +1 -0
- package/dist/graphs/default-orig.cascade +128 -0
- package/dist/graphs/default.cascade +21 -0
- package/dist/index.html +19 -0
- package/dist/runtime/browser.d.ts +3 -0
- package/dist/runtime/browser.d.ts.map +1 -0
- package/dist/runtime/browser.js +12 -0
- package/dist/runtime/browser.js.map +1 -0
- package/dist/runtime/builtins/core/index.d.ts +9 -0
- package/dist/runtime/builtins/core/index.d.ts.map +1 -0
- package/dist/runtime/builtins/core/index.js +21 -0
- package/dist/runtime/builtins/core/index.js.map +1 -0
- package/dist/runtime/builtins/core/random.d.ts +66 -0
- package/dist/runtime/builtins/core/random.d.ts.map +1 -0
- package/dist/runtime/builtins/core/random.js +46 -0
- package/dist/runtime/builtins/core/random.js.map +1 -0
- package/dist/runtime/builtins/core/remap.d.ts +105 -0
- package/dist/runtime/builtins/core/remap.d.ts.map +1 -0
- package/dist/runtime/builtins/core/remap.js +43 -0
- package/dist/runtime/builtins/core/remap.js.map +1 -0
- package/dist/runtime/builtins/core/routing.d.ts +117 -0
- package/dist/runtime/builtins/core/routing.d.ts.map +1 -0
- package/dist/runtime/builtins/core/routing.js +114 -0
- package/dist/runtime/builtins/core/routing.js.map +1 -0
- package/dist/runtime/builtins/core/structural.d.ts +86 -0
- package/dist/runtime/builtins/core/structural.d.ts.map +1 -0
- package/dist/runtime/builtins/core/structural.js +63 -0
- package/dist/runtime/builtins/core/structural.js.map +1 -0
- package/dist/runtime/builtins/geo/copyToPoints.d.ts +58 -0
- package/dist/runtime/builtins/geo/copyToPoints.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/copyToPoints.js +35 -0
- package/dist/runtime/builtins/geo/copyToPoints.js.map +1 -0
- package/dist/runtime/builtins/geo/definitions.d.ts +526 -0
- package/dist/runtime/builtins/geo/definitions.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/definitions.js +182 -0
- package/dist/runtime/builtins/geo/definitions.js.map +1 -0
- package/dist/runtime/builtins/geo/generators.d.ts +94 -0
- package/dist/runtime/builtins/geo/generators.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/generators.js +41 -0
- package/dist/runtime/builtins/geo/generators.js.map +1 -0
- package/dist/runtime/builtins/geo/index.d.ts +23 -0
- package/dist/runtime/builtins/geo/index.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/index.js +35 -0
- package/dist/runtime/builtins/geo/index.js.map +1 -0
- package/dist/runtime/builtins/geo/merge.d.ts +40 -0
- package/dist/runtime/builtins/geo/merge.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/merge.js +24 -0
- package/dist/runtime/builtins/geo/merge.js.map +1 -0
- package/dist/runtime/builtins/geo/namespace.d.ts +15 -0
- package/dist/runtime/builtins/geo/namespace.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/namespace.js +17 -0
- package/dist/runtime/builtins/geo/namespace.js.map +1 -0
- package/dist/runtime/builtins/geo/svgExport.d.ts +130 -0
- package/dist/runtime/builtins/geo/svgExport.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/svgExport.js +50 -0
- package/dist/runtime/builtins/geo/svgExport.js.map +1 -0
- package/dist/runtime/builtins/geo/transform.d.ts +60 -0
- package/dist/runtime/builtins/geo/transform.d.ts.map +1 -0
- package/dist/runtime/builtins/geo/transform.js +32 -0
- package/dist/runtime/builtins/geo/transform.js.map +1 -0
- package/dist/runtime/builtins/index.d.ts +9 -0
- package/dist/runtime/builtins/index.d.ts.map +1 -0
- package/dist/runtime/builtins/index.js +16 -0
- package/dist/runtime/builtins/index.js.map +1 -0
- package/dist/runtime/definition/architecture.d.ts +8 -0
- package/dist/runtime/definition/architecture.d.ts.map +1 -0
- package/dist/runtime/definition/architecture.js +112 -0
- package/dist/runtime/definition/architecture.js.map +1 -0
- package/dist/runtime/definition/extract.d.ts +12 -0
- package/dist/runtime/definition/extract.d.ts.map +1 -0
- package/dist/runtime/definition/extract.js +151 -0
- package/dist/runtime/definition/extract.js.map +1 -0
- package/dist/runtime/error.d.ts +8 -0
- package/dist/runtime/error.d.ts.map +1 -0
- package/dist/runtime/error.js +11 -0
- package/dist/runtime/error.js.map +1 -0
- package/dist/runtime/geometry/attributes.d.ts +65 -0
- package/dist/runtime/geometry/attributes.d.ts.map +1 -0
- package/dist/runtime/geometry/attributes.js +201 -0
- package/dist/runtime/geometry/attributes.js.map +1 -0
- package/dist/runtime/geometry/builder.d.ts +57 -0
- package/dist/runtime/geometry/builder.d.ts.map +1 -0
- package/dist/runtime/geometry/builder.js +153 -0
- package/dist/runtime/geometry/builder.js.map +1 -0
- package/dist/runtime/geometry/copy.d.ts +36 -0
- package/dist/runtime/geometry/copy.d.ts.map +1 -0
- package/dist/runtime/geometry/copy.js +68 -0
- package/dist/runtime/geometry/copy.js.map +1 -0
- package/dist/runtime/geometry/generate.d.ts +43 -0
- package/dist/runtime/geometry/generate.d.ts.map +1 -0
- package/dist/runtime/geometry/generate.js +76 -0
- package/dist/runtime/geometry/generate.js.map +1 -0
- package/dist/runtime/geometry/groups.d.ts +18 -0
- package/dist/runtime/geometry/groups.d.ts.map +1 -0
- package/dist/runtime/geometry/groups.js +69 -0
- package/dist/runtime/geometry/groups.js.map +1 -0
- package/dist/runtime/geometry/index.d.ts +23 -0
- package/dist/runtime/geometry/index.d.ts.map +1 -0
- package/dist/runtime/geometry/index.js +23 -0
- package/dist/runtime/geometry/index.js.map +1 -0
- package/dist/runtime/geometry/matrix.d.ts +26 -0
- package/dist/runtime/geometry/matrix.d.ts.map +1 -0
- package/dist/runtime/geometry/matrix.js +27 -0
- package/dist/runtime/geometry/matrix.js.map +1 -0
- package/dist/runtime/geometry/merge.d.ts +33 -0
- package/dist/runtime/geometry/merge.d.ts.map +1 -0
- package/dist/runtime/geometry/merge.js +185 -0
- package/dist/runtime/geometry/merge.js.map +1 -0
- package/dist/runtime/geometry/primitives.d.ts +41 -0
- package/dist/runtime/geometry/primitives.d.ts.map +1 -0
- package/dist/runtime/geometry/primitives.js +131 -0
- package/dist/runtime/geometry/primitives.js.map +1 -0
- package/dist/runtime/geometry/promote.d.ts +44 -0
- package/dist/runtime/geometry/promote.d.ts.map +1 -0
- package/dist/runtime/geometry/promote.js +203 -0
- package/dist/runtime/geometry/promote.js.map +1 -0
- package/dist/runtime/geometry/resample.d.ts +29 -0
- package/dist/runtime/geometry/resample.d.ts.map +1 -0
- package/dist/runtime/geometry/resample.js +165 -0
- package/dist/runtime/geometry/resample.js.map +1 -0
- package/dist/runtime/geometry/svg.d.ts +91 -0
- package/dist/runtime/geometry/svg.d.ts.map +1 -0
- package/dist/runtime/geometry/svg.js +216 -0
- package/dist/runtime/geometry/svg.js.map +1 -0
- package/dist/runtime/geometry/transform.d.ts +18 -0
- package/dist/runtime/geometry/transform.d.ts.map +1 -0
- package/dist/runtime/geometry/transform.js +56 -0
- package/dist/runtime/geometry/transform.js.map +1 -0
- package/dist/runtime/index.d.ts +5 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/node.d.ts +4 -0
- package/dist/runtime/node.d.ts.map +1 -0
- package/dist/runtime/node.js +12 -0
- package/dist/runtime/node.js.map +1 -0
- package/dist/runtime/runtime.d.ts +3 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +1198 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/types.d.ts +241 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/shell.d.ts +8 -0
- package/dist/shell.js +54 -0
- package/dist/shell.js.map +7 -0
- package/dist/stage.d.ts +7 -0
- package/dist/stage.js +84 -0
- package/dist/stage.js.map +7 -0
- package/dist/studio/panel.d.ts +48 -0
- package/doc/PROJECT_AUTHORING.md +360 -0
- package/package.json +126 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# Authoring Cascade projects
|
|
2
|
+
|
|
3
|
+
Cascade projects are filesystem-native. The graph, custom nodes, assets, presets, and host policy live together in an ordinary repository, while Cascade supplies the stable runtime and optional Studio workspace.
|
|
4
|
+
|
|
5
|
+
## Create and open a project
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cascade new my-artwork
|
|
9
|
+
cd ~/Documents/Cascade/my-artwork
|
|
10
|
+
cascade .
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For a workstation reached by name over a trusted VPN or LAN, bind deliberately
|
|
14
|
+
and allow the exact hostname used by the browser:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
cascade . --host KURO --port 3030
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Open `http://KURO:3030`. Loopback remains the default. Cascade trusts the
|
|
21
|
+
specific non-loopback bind hostname; `--trusted-host` is only needed when the
|
|
22
|
+
browser uses a different hostname. Wildcard remote binds are rejected.
|
|
23
|
+
|
|
24
|
+
Cascade and generated projects require Node.js 22.13 or newer. Generated
|
|
25
|
+
projects use TypeScript 6 so their static node definitions match Cascade's
|
|
26
|
+
compiler and definition extractor.
|
|
27
|
+
|
|
28
|
+
`index.cascade` is the default graph name. A project may contain several `.cascade` files; pass one explicitly when there is no unambiguous default:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cascade print.cascade
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The portable project shape is:
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
my-artwork/
|
|
38
|
+
├── cascade.json
|
|
39
|
+
├── index.cascade
|
|
40
|
+
├── nodes/
|
|
41
|
+
├── panels/ # optional Studio-only extensions
|
|
42
|
+
├── assets/
|
|
43
|
+
├── package.json
|
|
44
|
+
└── tsconfig.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Keep generated output in a project-specific directory such as `renders/`. Keep reusable algorithms in `nodes/` or a normal TypeScript package rather than in Studio components.
|
|
48
|
+
|
|
49
|
+
## Add a project panel
|
|
50
|
+
|
|
51
|
+
A project can provide an optional dockable Studio panel without adding UI code to Cascade. Create `panels/asset-browser/index.ts`:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import type { ProjectPanelApi } from 'cascade/studio/panel';
|
|
55
|
+
|
|
56
|
+
export const title = 'Assets';
|
|
57
|
+
export const icon = 'Images';
|
|
58
|
+
|
|
59
|
+
export function mount(element: HTMLElement, api: ProjectPanelApi) {
|
|
60
|
+
const button = document.createElement('button');
|
|
61
|
+
button.textContent = 'Use selected asset';
|
|
62
|
+
button.onclick = () => {
|
|
63
|
+
if (api.sourceNodeId) api.setParam(api.sourceNodeId, 'asset_id', 'asset-42');
|
|
64
|
+
api.close();
|
|
65
|
+
};
|
|
66
|
+
element.append(button);
|
|
67
|
+
return () => button.remove();
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Panels are trusted browser code. Cascade discovers literal `title`, `icon`, and optional `rendererTypes` exports without executing the module, then compiles it only when Studio needs it. `mount` may be async and returns an instance disposer; `api.signal` aborts when its dock closes. Panels can call project stages, build media URLs, read/write node parameters, inspect selection, or close themselves.
|
|
72
|
+
|
|
73
|
+
Reusable panels may live under `shared/panels/`. `shared/` may be a directory or
|
|
74
|
+
a project-owned symlink to a sibling library; Cascade confines panel discovery
|
|
75
|
+
and compilation to that link's canonical target. A project-local panel with the
|
|
76
|
+
same name still wins.
|
|
77
|
+
|
|
78
|
+
The same module can provide project-owned value renderers without teaching Cascade about project data types:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
export const rendererTypes = ['my-project.asset'];
|
|
82
|
+
|
|
83
|
+
export const renderers = {
|
|
84
|
+
'my-project.asset': {
|
|
85
|
+
mount(element, props) {
|
|
86
|
+
const draw = ({ value }) => { element.textContent = String(value ?? ''); };
|
|
87
|
+
draw(props);
|
|
88
|
+
return { update: draw, dispose: () => element.replaceChildren() };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Each renderer instance owns its cleanup. An optional `update` method receives later values without remounting.
|
|
95
|
+
|
|
96
|
+
To open a panel from the Inspector, declare an action parameter:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
node.param('asset_id', '', {
|
|
100
|
+
label: 'Choose asset',
|
|
101
|
+
action: 'panel:asset-browser',
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The initiating node ID is captured as `api.sourceNodeId`; `setParam` uses the same history/dirty/cook path as the Inspector, so undo and save continue to work. Panels and project value renderers are Studio-only and are never imported during `cascade run` or by `cascade/runtime`.
|
|
106
|
+
|
|
107
|
+
## Project settings and credentials
|
|
108
|
+
|
|
109
|
+
`cascade.json` describes the whole folder, so every `.cascade` graph in the repository sees the same non-secret settings:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"name": "My Artwork",
|
|
114
|
+
"credentials": ["image-api"],
|
|
115
|
+
"settings": { "workingWidth": 1400, "outputUnits": "mm" }
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Read settings without giving nodes write access:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { config } from 'cascade/config';
|
|
123
|
+
const width = config.number('workingWidth', 1400);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Credential values never belong in the project. Cascade reads them from `~/.cascade/credentials.yaml` (or `CASCADE_CREDENTIALS`) and reports only whether each declared name is set. Server stages receive declared values through environment variables. A Studio/browser project node can use Cascade's compiler-injected authorized proxy:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { authorizedFetch } from 'cascade/net';
|
|
130
|
+
const response = await authorizedFetch('image-api', 'https://api.example.com/v1/render', {
|
|
131
|
+
method: 'POST', body: JSON.stringify(payload)
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`cascade/net` is resolved by Cascade's project compiler and backed by the
|
|
136
|
+
Studio server's `/api/net` route. It is not a published package export or a
|
|
137
|
+
neutral headless runtime capability. A standalone headless host must provide
|
|
138
|
+
its own remote-I/O adapter or run the integration through an injected shell,
|
|
139
|
+
Python, or application-specific server bridge.
|
|
140
|
+
|
|
141
|
+
Browser proxy credentials must declare the exact allowed hosts and header metadata alongside the secret:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
image-api:
|
|
145
|
+
api_key: "..."
|
|
146
|
+
env: IMAGE_API_KEY
|
|
147
|
+
hosts: [api.example.com]
|
|
148
|
+
header: Authorization
|
|
149
|
+
scheme: Bearer
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The proxy accepts HTTPS only, refuses undeclared hosts, strips caller-supplied authorization headers, and never returns the credential value to the page. Studio defers its initial cook when a required credential is missing and links to File → Project Settings.
|
|
153
|
+
|
|
154
|
+
## Add a custom node
|
|
155
|
+
|
|
156
|
+
Create `nodes/Multiply/index.ts`. The directory name defines the module ID `project.Multiply`.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import type { NodeDefinition, NodeExecutionContext } from 'cascade/contracts';
|
|
160
|
+
|
|
161
|
+
export const definition = {
|
|
162
|
+
apiVersion: 1,
|
|
163
|
+
label: 'Multiply',
|
|
164
|
+
description: 'Scales a numeric value.',
|
|
165
|
+
runsOn: 'portable',
|
|
166
|
+
inputs: {
|
|
167
|
+
value: { kind: 'data', type: 'float', default: 0 },
|
|
168
|
+
factor: { kind: 'data', type: 'float', default: 2 }
|
|
169
|
+
},
|
|
170
|
+
outputs: {
|
|
171
|
+
result: { kind: 'data', type: 'float' }
|
|
172
|
+
}
|
|
173
|
+
} as const satisfies NodeDefinition;
|
|
174
|
+
|
|
175
|
+
export function execute(context: NodeExecutionContext<typeof definition>) {
|
|
176
|
+
context.outputs.result.set(context.inputs.value * context.inputs.factor);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The definition is the complete static interface. Cascade and code agents can inspect it without importing the module, build the node UI, validate graph connections, and type-check `execute`. Do not create ports, props, or types inside `execute`.
|
|
181
|
+
|
|
182
|
+
Choose the narrowest execution locus:
|
|
183
|
+
|
|
184
|
+
- `portable` — deterministic TypeScript with host-neutral capabilities; usable in Node and browsers.
|
|
185
|
+
- `browser` — browser-only values or WebGL.
|
|
186
|
+
- `server` — filesystem, Python, shell, or other server-only work.
|
|
187
|
+
|
|
188
|
+
Capabilities are explicit:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
export const definition = {
|
|
192
|
+
apiVersion: 1,
|
|
193
|
+
runsOn: 'server',
|
|
194
|
+
capabilities: ['python'],
|
|
195
|
+
inputs: { prompt: { kind: 'data', type: 'string', default: '' } },
|
|
196
|
+
outputs: { result: { kind: 'data', type: 'object' } }
|
|
197
|
+
} as const satisfies NodeDefinition;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The runtime refuses unsupported host/capability combinations before executing the graph.
|
|
201
|
+
|
|
202
|
+
Some portable operations have genuinely useful browser and server
|
|
203
|
+
implementations. Keep one literal definition and one module ID; let the host's
|
|
204
|
+
registration load the implementation for its environment. Do not add an
|
|
205
|
+
`engine: browser | server` graph parameter or duplicate the node type. The two
|
|
206
|
+
executors are an implementation detail and must produce the same declared
|
|
207
|
+
types, coordinate conventions, metadata, and edge-case behavior. Lock that
|
|
208
|
+
contract with shared golden tests. Use a graph parameter only when the choice
|
|
209
|
+
changes the artistic result, cost, or model—not merely where equivalent work
|
|
210
|
+
runs.
|
|
211
|
+
|
|
212
|
+
## Use runtime-native core nodes
|
|
213
|
+
|
|
214
|
+
Core modules are reserved runtime registrations; do not create files for them
|
|
215
|
+
under `nodes/`:
|
|
216
|
+
|
|
217
|
+
| Module | Purpose |
|
|
218
|
+
| --- | --- |
|
|
219
|
+
| `cascade.core.Input` | Public root or subnet input |
|
|
220
|
+
| `cascade.core.Output` | Public root or subnet output |
|
|
221
|
+
| `cascade.core.Subnet` | Nested graph container |
|
|
222
|
+
| `cascade.core.Switch` | Select one variadic input by index |
|
|
223
|
+
| `cascade.core.Null` | Pass any value through unchanged while retaining downstream wiring |
|
|
224
|
+
| `cascade.core.Merge` | Collect variadic inputs into an array |
|
|
225
|
+
| `cascade.core.Select` | Select an array item, with optional wrapping |
|
|
226
|
+
| `cascade.core.Random` | Stable float in `[0, 1)` from explicit `seed` and `sample` integers |
|
|
227
|
+
| `cascade.core.Remap` | Scalar range mapping with optional `clamp` prop |
|
|
228
|
+
|
|
229
|
+
Use root Input and Output nodes as the graph's named, typed public API for headless hosts.
|
|
230
|
+
Keep implementation nodes behind that boundary so a server or custom frontend
|
|
231
|
+
does not depend on internal IDs. A child Input/Output node's index defines the
|
|
232
|
+
matching `input_N`/`output_N` port on its parent Subnet.
|
|
233
|
+
|
|
234
|
+
Portable nodes must not read ambient time or randomness. Pass frame/time through
|
|
235
|
+
root inputs and use seeded Random when a procedural stage needs variation.
|
|
236
|
+
|
|
237
|
+
## Integrate external services and AI
|
|
238
|
+
|
|
239
|
+
Cascade does not embed model providers or a generic `ai` capability. Provider
|
|
240
|
+
SDKs, credentials, model names, retries, and response normalization belong to
|
|
241
|
+
the project that uses them. This keeps graph/runtime contracts stable while
|
|
242
|
+
services evolve.
|
|
243
|
+
|
|
244
|
+
Keep the node definition provider-neutral and deterministic. For example, a
|
|
245
|
+
server node can invoke a project-owned Python operation and expose the result as
|
|
246
|
+
a normal image:
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import type {
|
|
250
|
+
ImageRef,
|
|
251
|
+
NodeDefinition,
|
|
252
|
+
NodeExecutionContext
|
|
253
|
+
} from 'cascade/contracts';
|
|
254
|
+
|
|
255
|
+
export const definition = {
|
|
256
|
+
apiVersion: 1,
|
|
257
|
+
label: 'Generate Image',
|
|
258
|
+
runsOn: 'server',
|
|
259
|
+
capabilities: ['python'],
|
|
260
|
+
inputs: {
|
|
261
|
+
prompt: { kind: 'data', type: 'string', default: '' }
|
|
262
|
+
},
|
|
263
|
+
outputs: {
|
|
264
|
+
image: { kind: 'data', type: 'image' }
|
|
265
|
+
}
|
|
266
|
+
} as const satisfies NodeDefinition;
|
|
267
|
+
|
|
268
|
+
export async function execute(
|
|
269
|
+
context: NodeExecutionContext<typeof definition>
|
|
270
|
+
) {
|
|
271
|
+
const image = await context.capabilities.python.invoke(
|
|
272
|
+
{ operation: 'generate_image', input: { prompt: context.inputs.prompt } },
|
|
273
|
+
{ signal: context.signal, progress: context.progress }
|
|
274
|
+
);
|
|
275
|
+
if (!image || typeof image !== 'object' || !('path' in image)) {
|
|
276
|
+
throw new Error('generate_image did not return an ImageRef');
|
|
277
|
+
}
|
|
278
|
+
context.outputs.image.set(image as ImageRef);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Choose the path that matches the host:
|
|
283
|
+
|
|
284
|
+
- Studio/browser: use the compiler-injected `cascade/net` proxy with a declared
|
|
285
|
+
project credential and exact remote-host allowlist.
|
|
286
|
+
- Cascade's server host: use configured Python operations or an allowlisted
|
|
287
|
+
`cascade/shell` command.
|
|
288
|
+
- Standalone headless embedding: inject the declared capability from the host,
|
|
289
|
+
or supply an application-owned server bridge that keeps credentials and
|
|
290
|
+
remote I/O outside the neutral runtime.
|
|
291
|
+
|
|
292
|
+
Return `ImageRef`, `AssetRef`, or another ordinary Cascade type. Downstream
|
|
293
|
+
nodes should not need to know which service produced the value.
|
|
294
|
+
|
|
295
|
+
### Project Python stages
|
|
296
|
+
|
|
297
|
+
Dynamic compatibility nodes call project-owned Python through `cascade/stage`.
|
|
298
|
+
Declare the dispatcher once in `cascade.json`:
|
|
299
|
+
|
|
300
|
+
```json
|
|
301
|
+
{
|
|
302
|
+
"exec": {
|
|
303
|
+
"stages": {
|
|
304
|
+
"entrypoint": "runtime/node_cli.py",
|
|
305
|
+
"python": "python3"
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Cascade starts the dispatcher as `node_cli.py --stage <name> --args -` and sends
|
|
312
|
+
the JSON argument object on stdin. Reading stdin avoids operating-system command
|
|
313
|
+
line limits for geometry and other large structured values. The dispatcher must
|
|
314
|
+
write its JSON result as its final stdout line; diagnostics belong on stderr.
|
|
315
|
+
It may also accept inline JSON after `--args` for manual compatibility. Projects
|
|
316
|
+
with expensive imports may additionally declare a newline-delimited JSON
|
|
317
|
+
`worker`; Cascade keeps that process warm and correlates requests by `id`.
|
|
318
|
+
|
|
319
|
+
## Work with `.cascade` files
|
|
320
|
+
|
|
321
|
+
A graph document stores authored elements separately from runtime state. Nodes and annotations remain flat even inside subnets:
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"nodes": [
|
|
326
|
+
{ "id": "process", "module": "cascade.core.Subnet", "position": [400, 200] },
|
|
327
|
+
{ "id": "multiply", "module": "project.Multiply", "parent": "process", "position": [80, 60] }
|
|
328
|
+
],
|
|
329
|
+
"annotations": [],
|
|
330
|
+
"connections": []
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
`parent` is omitted at the root. Child positions are relative to their parent. IDs are globally unique, and connections refer to element/port identities. When changing structure, load and validate the whole candidate before replacing the live graph.
|
|
335
|
+
|
|
336
|
+
## Run without Studio
|
|
337
|
+
|
|
338
|
+
Use the CLI for automation and CI:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
cascade validate index.cascade
|
|
342
|
+
cascade check index.cascade
|
|
343
|
+
cascade inspect index.cascade
|
|
344
|
+
cascade run index.cascade
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Applications can use `createRuntime()` from `cascade/runtime` directly. Register node modules and host capabilities, load the graph, mutate inputs or presets, run or trigger it, read outputs, then dispose it. This path loads no Svelte or Studio code and works in a backend service or a custom browser application.
|
|
348
|
+
|
|
349
|
+
Server and browser hosts are deliberately explicit. A graph that uses Python or shell stages belongs on the server or behind an application-defined bridge; the runtime does not silently move computation between environments.
|
|
350
|
+
|
|
351
|
+
## Verify a project
|
|
352
|
+
|
|
353
|
+
Before committing a custom node or graph:
|
|
354
|
+
|
|
355
|
+
1. Type-check the project with its normal TypeScript command.
|
|
356
|
+
2. Run `cascade validate <graph>` and `cascade check <graph>` to check the document plus static definitions, types, hierarchy, and connections without rendering.
|
|
357
|
+
3. Run the graph headlessly when its capabilities are available.
|
|
358
|
+
4. Open Studio only for visual inspection or authoring that benefits from the graph UI.
|
|
359
|
+
|
|
360
|
+
Treat warnings about legacy dynamic nodes as migration work. New nodes should always use deterministic definitions.
|
package/package.json
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@field/cascade",
|
|
3
|
+
"version": "0.2.22",
|
|
4
|
+
"description": "Visual programming for generative art",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "FIELD.IO <marcus@field.io>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/marcuswendt/cascade.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/marcuswendt/cascade#readme",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"node-graph",
|
|
14
|
+
"visual-programming",
|
|
15
|
+
"generative-art",
|
|
16
|
+
"creative-coding",
|
|
17
|
+
"dataflow"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=22.13.0"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"AGENTS.md",
|
|
29
|
+
"ARCHITECTURE.md",
|
|
30
|
+
"DESIGN.md",
|
|
31
|
+
"doc/PROJECT_AUTHORING.md",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"workspaces": [
|
|
36
|
+
"packages/contracts",
|
|
37
|
+
"packages/runtime"
|
|
38
|
+
],
|
|
39
|
+
"bin": {
|
|
40
|
+
"cascade": "./dist/cli/index.js"
|
|
41
|
+
},
|
|
42
|
+
"exports": {
|
|
43
|
+
"./contracts": {
|
|
44
|
+
"types": "./dist/contracts/index.d.ts",
|
|
45
|
+
"default": "./dist/contracts/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./contracts/schema": {
|
|
48
|
+
"types": "./dist/contracts/schema.d.ts",
|
|
49
|
+
"default": "./dist/contracts/schema.js"
|
|
50
|
+
},
|
|
51
|
+
"./runtime": {
|
|
52
|
+
"types": "./dist/runtime/index.d.ts",
|
|
53
|
+
"default": "./dist/runtime/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./runtime/node": {
|
|
56
|
+
"types": "./dist/runtime/node.d.ts",
|
|
57
|
+
"default": "./dist/runtime/node.js"
|
|
58
|
+
},
|
|
59
|
+
"./runtime/browser": {
|
|
60
|
+
"types": "./dist/runtime/browser.d.ts",
|
|
61
|
+
"default": "./dist/runtime/browser.js"
|
|
62
|
+
},
|
|
63
|
+
"./runtime/definition/extract": {
|
|
64
|
+
"types": "./dist/runtime/definition/extract.d.ts",
|
|
65
|
+
"default": "./dist/runtime/definition/extract.js"
|
|
66
|
+
},
|
|
67
|
+
"./shell": {
|
|
68
|
+
"types": "./dist/shell.d.ts",
|
|
69
|
+
"default": "./dist/shell.js"
|
|
70
|
+
},
|
|
71
|
+
"./stage": {
|
|
72
|
+
"types": "./dist/stage.d.ts",
|
|
73
|
+
"default": "./dist/stage.js"
|
|
74
|
+
},
|
|
75
|
+
"./studio/panel": {
|
|
76
|
+
"types": "./dist/studio/panel.d.ts"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"dev": "vite",
|
|
81
|
+
"dev:client": "vite",
|
|
82
|
+
"build": "vite build",
|
|
83
|
+
"postbuild": "npm run build:cli",
|
|
84
|
+
"build:packages": "npm run build --workspace @cascade/contracts && npm run build --workspace @cascade/runtime && node scripts/copy-package-builds.mjs",
|
|
85
|
+
"check:packages": "npm run check --workspace @cascade/contracts && npm run build --workspace @cascade/contracts && npm run check --workspace @cascade/runtime",
|
|
86
|
+
"test:packages": "npm run test --workspace @cascade/contracts && npm run test --workspace @cascade/runtime",
|
|
87
|
+
"build:cli": "npm run build:packages && node scripts/build-cli.mjs",
|
|
88
|
+
"prepack": "npm run build",
|
|
89
|
+
"preview": "vite preview",
|
|
90
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
91
|
+
"test": "vitest",
|
|
92
|
+
"test:run": "vitest run",
|
|
93
|
+
"test:coverage": "vitest run --coverage",
|
|
94
|
+
"test:package": "node scripts/smoke-package.mjs"
|
|
95
|
+
},
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"esbuild": "^0.28.2",
|
|
98
|
+
"express": "^5.2.1",
|
|
99
|
+
"multer": "^2.3.0",
|
|
100
|
+
"sharp": "^0.35.4",
|
|
101
|
+
"typescript": "^6.0.3"
|
|
102
|
+
},
|
|
103
|
+
"devDependencies": {
|
|
104
|
+
"@lucide/svelte": "^1.37.0",
|
|
105
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
106
|
+
"@testing-library/svelte": "^5.4.2",
|
|
107
|
+
"@testing-library/user-event": "^14.6.6",
|
|
108
|
+
"@tsconfig/svelte": "^5.0.8",
|
|
109
|
+
"@types/express": "^5.0.6",
|
|
110
|
+
"@types/node": "^24.13.3",
|
|
111
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
112
|
+
"dockview": "^8.2.0",
|
|
113
|
+
"dompurify": "^3.4.14",
|
|
114
|
+
"jsdom": "^29.1.1",
|
|
115
|
+
"marked": "^18.0.11",
|
|
116
|
+
"monaco-editor": "^0.56.0",
|
|
117
|
+
"svelte": "^5.0.0",
|
|
118
|
+
"svelte-check": "^4.7.6",
|
|
119
|
+
"tsx": "^4.23.12",
|
|
120
|
+
"vite": "^8.2.2",
|
|
121
|
+
"vitest": "^4.1.11"
|
|
122
|
+
},
|
|
123
|
+
"overrides": {
|
|
124
|
+
"dompurify": "$dompurify"
|
|
125
|
+
}
|
|
126
|
+
}
|