@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.
Files changed (319) hide show
  1. package/AGENTS.md +168 -0
  2. package/ARCHITECTURE.md +137 -0
  3. package/DESIGN.md +161 -0
  4. package/LICENSE +21 -0
  5. package/README.md +229 -0
  6. package/dist/assets/CodeEditor-DR7u0q7p.css +1 -0
  7. package/dist/assets/CodeEditor-DoaNEUaM.js +641 -0
  8. package/dist/assets/CodePanel-B0_2XJ-t.js +2 -0
  9. package/dist/assets/CodePanel-IT1secyI.css +1 -0
  10. package/dist/assets/CustomNodeDialog-026lzecD.js +1 -0
  11. package/dist/assets/CustomNodeDialog-JGYnWY6m.css +1 -0
  12. package/dist/assets/ExportDialog-DOq0flMV.css +1 -0
  13. package/dist/assets/ExportDialog-DWN4nhXI.js +358 -0
  14. package/dist/assets/ProjectSettings-BzT164Yx.js +2 -0
  15. package/dist/assets/ProjectSettings-DdO9xoQz.css +1 -0
  16. package/dist/assets/SettingsDialog-CeK7ytpY.css +1 -0
  17. package/dist/assets/SettingsDialog-DmHb1V0r.js +1 -0
  18. package/dist/assets/VersionHistoryDialog-CWNmHQ-P.css +1 -0
  19. package/dist/assets/VersionHistoryDialog-hH6VsXLX.js +3 -0
  20. package/dist/assets/abap-08VXUWAP.js +1 -0
  21. package/dist/assets/apex-BWPQTe0t.js +1 -0
  22. package/dist/assets/azcli-Bc_sGQ0U.js +1 -0
  23. package/dist/assets/bat-i0X4ZdIN.js +1 -0
  24. package/dist/assets/bicep-B5-_aFwp.js +2 -0
  25. package/dist/assets/cameligo-DMUM7wLl.js +1 -0
  26. package/dist/assets/cascade.jpg +0 -0
  27. package/dist/assets/clojure-Cm7r79vr.js +1 -0
  28. package/dist/assets/codicon-Brq4_Ui5.ttf +0 -0
  29. package/dist/assets/coffee-Ba7i2nA0.js +1 -0
  30. package/dist/assets/core-Bji4aZUU.js +965 -0
  31. package/dist/assets/cpp-C7h46wYY.js +1 -0
  32. package/dist/assets/csharp-BKxtCVv1.js +1 -0
  33. package/dist/assets/csp-bTuwJoIa.js +1 -0
  34. package/dist/assets/css-DIMkf-bt.js +3 -0
  35. package/dist/assets/css.worker-B3ciXF_0.js +93 -0
  36. package/dist/assets/cssMode-B6Z_Q1Kh.js +1 -0
  37. package/dist/assets/cypher-CVaqCwHa.js +1 -0
  38. package/dist/assets/dart-onAF5SnQ.js +1 -0
  39. package/dist/assets/dockerfile-DZFCIeNp.js +1 -0
  40. package/dist/assets/ecl-D05T4iGw.js +1 -0
  41. package/dist/assets/editor-1FQrmyyI.css +1 -0
  42. package/dist/assets/editor.api-jMoW_43X.js +847 -0
  43. package/dist/assets/editor.worker-q-txB4vs.js +30 -0
  44. package/dist/assets/elixir-6RTg0lbw.js +1 -0
  45. package/dist/assets/flow9-C5_-GSwl.js +1 -0
  46. package/dist/assets/freemarker2-DvvPV6m5.js +3 -0
  47. package/dist/assets/fsharp-C8Ef5oNN.js +1 -0
  48. package/dist/assets/geo-CXmCtzMM.js +2 -0
  49. package/dist/assets/go-C-y9NEjX.js +1 -0
  50. package/dist/assets/graphql-fmXr3nnJ.js +1 -0
  51. package/dist/assets/handlebars-B8rfuSIa.js +1 -0
  52. package/dist/assets/hcl-CpzslTdj.js +1 -0
  53. package/dist/assets/html-DyHm6JCp.js +1 -0
  54. package/dist/assets/html.worker-C93Ht9o9.js +506 -0
  55. package/dist/assets/htmlMode-E9XLWE5u.js +1 -0
  56. package/dist/assets/image-BUcQC7PG.js +2076 -0
  57. package/dist/assets/index-BXYXSdgh.js +224 -0
  58. package/dist/assets/index-CrNke7SW.css +1 -0
  59. package/dist/assets/index-client-DN_FvjN8.js +1 -0
  60. package/dist/assets/ini-sBoK_t0W.js +1 -0
  61. package/dist/assets/java-BEtHBSE6.js +1 -0
  62. package/dist/assets/javascript-C_bM5PCN.js +1 -0
  63. package/dist/assets/json.worker-B2V3pomh.js +62 -0
  64. package/dist/assets/jsonMode-BdyVS7G4.js +7 -0
  65. package/dist/assets/julia-Bri6UV-V.js +1 -0
  66. package/dist/assets/kotlin-BOotOW0E.js +1 -0
  67. package/dist/assets/legacy-DIu3XRwl.js +2 -0
  68. package/dist/assets/less-B9JPFI3C.js +2 -0
  69. package/dist/assets/lexon-CfSJPG6W.js +1 -0
  70. package/dist/assets/liquid-CDkn3spA.js +1 -0
  71. package/dist/assets/lspLanguageFeatures-AB5DMAsr.js +4 -0
  72. package/dist/assets/lua-CsQS60Ue.js +1 -0
  73. package/dist/assets/m3-D-oSqn_W.js +1 -0
  74. package/dist/assets/markdown-Cimd5fb3.js +1 -0
  75. package/dist/assets/mdx-BvH_NjDN.js +1 -0
  76. package/dist/assets/mips-CIPQ_RoX.js +1 -0
  77. package/dist/assets/msdax-DauUninz.js +1 -0
  78. package/dist/assets/mysql-SOo6toE5.js +1 -0
  79. package/dist/assets/nodeTypeUtils-CweA3NHd.js +1 -0
  80. package/dist/assets/objective-c-FvmIjYaQ.js +1 -0
  81. package/dist/assets/pascal-DrH0SRf2.js +1 -0
  82. package/dist/assets/pascaligo-D-ptJ9y-.js +1 -0
  83. package/dist/assets/perl-oz_6vUea.js +1 -0
  84. package/dist/assets/pgsql-DTj74zXo.js +1 -0
  85. package/dist/assets/php-nr791fC2.js +1 -0
  86. package/dist/assets/pla-CopQ2nXW.js +1 -0
  87. package/dist/assets/postiats-43DmfD33.js +1 -0
  88. package/dist/assets/powerquery-D3hlyOfw.js +1 -0
  89. package/dist/assets/powershell-DmHpPYUd.js +1 -0
  90. package/dist/assets/projectSettingsApi-C1WvIwfP.js +1 -0
  91. package/dist/assets/protobuf-C531GsRP.js +2 -0
  92. package/dist/assets/pug-Z5eAx3Zn.js +1 -0
  93. package/dist/assets/python-B7uii4fi.js +1 -0
  94. package/dist/assets/qsharp-DkqhCAOL.js +1 -0
  95. package/dist/assets/quill-DjZ69wL_.js +121 -0
  96. package/dist/assets/r-BwWrilGY.js +1 -0
  97. package/dist/assets/razor-Z48fWdJc.js +1 -0
  98. package/dist/assets/redis-ClamHrr6.js +1 -0
  99. package/dist/assets/redshift-DT7zqm-g.js +1 -0
  100. package/dist/assets/restructuredtext-BYgofb2h.js +1 -0
  101. package/dist/assets/ruby-DezsRK8O.js +1 -0
  102. package/dist/assets/rust-DdL9SqIa.js +1 -0
  103. package/dist/assets/sb-CcwsVR0C.js +1 -0
  104. package/dist/assets/scala-DHpiXF5c.js +1 -0
  105. package/dist/assets/scheme-BeGwcela.js +1 -0
  106. package/dist/assets/scss-gp-XZpBa.js +3 -0
  107. package/dist/assets/shell-CC2rA5mh.js +1 -0
  108. package/dist/assets/solidity-BEEn4gHE.js +1 -0
  109. package/dist/assets/sophia-CRfGWb83.js +1 -0
  110. package/dist/assets/sparql-D_Lu-MrJ.js +1 -0
  111. package/dist/assets/sql-NEE52Syq.js +1 -0
  112. package/dist/assets/st-DbInun42.js +1 -0
  113. package/dist/assets/swift-Bxkupp3x.js +1 -0
  114. package/dist/assets/systemverilog-Bz4Y3fRF.js +1 -0
  115. package/dist/assets/tcl-DISqw1ZD.js +1 -0
  116. package/dist/assets/ts.worker-D7T1-Ig5.js +67738 -0
  117. package/dist/assets/tsMode-BDgacVG4.js +11 -0
  118. package/dist/assets/twig-De2hgUGE.js +1 -0
  119. package/dist/assets/typescript-Derb6Oqa.js +1 -0
  120. package/dist/assets/typespec-B8J7ngcE.js +1 -0
  121. package/dist/assets/vb-DV3o63ZY.js +1 -0
  122. package/dist/assets/wgsl-DpFanUEy.js +298 -0
  123. package/dist/assets/workers-BtoMX_pm.js +1 -0
  124. package/dist/assets/xml-B1CaFSrG.js +1 -0
  125. package/dist/assets/yaml-HmIeA0KH.js +1 -0
  126. package/dist/cli/index.js +11377 -0
  127. package/dist/cli/index.js.map +7 -0
  128. package/dist/cli/runtime/io.ts +445 -0
  129. package/dist/cli/runtime/net.ts +19 -0
  130. package/dist/cli/runtime/shell.ts +46 -0
  131. package/dist/cli/runtime/stage.ts +132 -0
  132. package/dist/contracts/capabilities.d.ts +109 -0
  133. package/dist/contracts/capabilities.d.ts.map +1 -0
  134. package/dist/contracts/capabilities.js +11 -0
  135. package/dist/contracts/capabilities.js.map +1 -0
  136. package/dist/contracts/color.d.ts +67 -0
  137. package/dist/contracts/color.d.ts.map +1 -0
  138. package/dist/contracts/color.js +83 -0
  139. package/dist/contracts/color.js.map +1 -0
  140. package/dist/contracts/definition.d.ts +118 -0
  141. package/dist/contracts/definition.d.ts.map +1 -0
  142. package/dist/contracts/definition.js +2 -0
  143. package/dist/contracts/definition.js.map +1 -0
  144. package/dist/contracts/document.d.ts +50 -0
  145. package/dist/contracts/document.d.ts.map +1 -0
  146. package/dist/contracts/document.js +2 -0
  147. package/dist/contracts/document.js.map +1 -0
  148. package/dist/contracts/geometry.d.ts +301 -0
  149. package/dist/contracts/geometry.d.ts.map +1 -0
  150. package/dist/contracts/geometry.js +604 -0
  151. package/dist/contracts/geometry.js.map +1 -0
  152. package/dist/contracts/index.d.ts +8 -0
  153. package/dist/contracts/index.d.ts.map +1 -0
  154. package/dist/contracts/index.js +8 -0
  155. package/dist/contracts/index.js.map +1 -0
  156. package/dist/contracts/schema.d.ts +6 -0
  157. package/dist/contracts/schema.d.ts.map +1 -0
  158. package/dist/contracts/schema.js +85 -0
  159. package/dist/contracts/schema.js.map +1 -0
  160. package/dist/contracts/validate.d.ts +13 -0
  161. package/dist/contracts/validate.d.ts.map +1 -0
  162. package/dist/contracts/validate.js +202 -0
  163. package/dist/contracts/validate.js.map +1 -0
  164. package/dist/contracts/values.d.ts +100 -0
  165. package/dist/contracts/values.d.ts.map +1 -0
  166. package/dist/contracts/values.js +59 -0
  167. package/dist/contracts/values.js.map +1 -0
  168. package/dist/graphs/default-orig.cascade +128 -0
  169. package/dist/graphs/default.cascade +21 -0
  170. package/dist/index.html +19 -0
  171. package/dist/runtime/browser.d.ts +3 -0
  172. package/dist/runtime/browser.d.ts.map +1 -0
  173. package/dist/runtime/browser.js +12 -0
  174. package/dist/runtime/browser.js.map +1 -0
  175. package/dist/runtime/builtins/core/index.d.ts +9 -0
  176. package/dist/runtime/builtins/core/index.d.ts.map +1 -0
  177. package/dist/runtime/builtins/core/index.js +21 -0
  178. package/dist/runtime/builtins/core/index.js.map +1 -0
  179. package/dist/runtime/builtins/core/random.d.ts +66 -0
  180. package/dist/runtime/builtins/core/random.d.ts.map +1 -0
  181. package/dist/runtime/builtins/core/random.js +46 -0
  182. package/dist/runtime/builtins/core/random.js.map +1 -0
  183. package/dist/runtime/builtins/core/remap.d.ts +105 -0
  184. package/dist/runtime/builtins/core/remap.d.ts.map +1 -0
  185. package/dist/runtime/builtins/core/remap.js +43 -0
  186. package/dist/runtime/builtins/core/remap.js.map +1 -0
  187. package/dist/runtime/builtins/core/routing.d.ts +117 -0
  188. package/dist/runtime/builtins/core/routing.d.ts.map +1 -0
  189. package/dist/runtime/builtins/core/routing.js +114 -0
  190. package/dist/runtime/builtins/core/routing.js.map +1 -0
  191. package/dist/runtime/builtins/core/structural.d.ts +86 -0
  192. package/dist/runtime/builtins/core/structural.d.ts.map +1 -0
  193. package/dist/runtime/builtins/core/structural.js +63 -0
  194. package/dist/runtime/builtins/core/structural.js.map +1 -0
  195. package/dist/runtime/builtins/geo/copyToPoints.d.ts +58 -0
  196. package/dist/runtime/builtins/geo/copyToPoints.d.ts.map +1 -0
  197. package/dist/runtime/builtins/geo/copyToPoints.js +35 -0
  198. package/dist/runtime/builtins/geo/copyToPoints.js.map +1 -0
  199. package/dist/runtime/builtins/geo/definitions.d.ts +526 -0
  200. package/dist/runtime/builtins/geo/definitions.d.ts.map +1 -0
  201. package/dist/runtime/builtins/geo/definitions.js +182 -0
  202. package/dist/runtime/builtins/geo/definitions.js.map +1 -0
  203. package/dist/runtime/builtins/geo/generators.d.ts +94 -0
  204. package/dist/runtime/builtins/geo/generators.d.ts.map +1 -0
  205. package/dist/runtime/builtins/geo/generators.js +41 -0
  206. package/dist/runtime/builtins/geo/generators.js.map +1 -0
  207. package/dist/runtime/builtins/geo/index.d.ts +23 -0
  208. package/dist/runtime/builtins/geo/index.d.ts.map +1 -0
  209. package/dist/runtime/builtins/geo/index.js +35 -0
  210. package/dist/runtime/builtins/geo/index.js.map +1 -0
  211. package/dist/runtime/builtins/geo/merge.d.ts +40 -0
  212. package/dist/runtime/builtins/geo/merge.d.ts.map +1 -0
  213. package/dist/runtime/builtins/geo/merge.js +24 -0
  214. package/dist/runtime/builtins/geo/merge.js.map +1 -0
  215. package/dist/runtime/builtins/geo/namespace.d.ts +15 -0
  216. package/dist/runtime/builtins/geo/namespace.d.ts.map +1 -0
  217. package/dist/runtime/builtins/geo/namespace.js +17 -0
  218. package/dist/runtime/builtins/geo/namespace.js.map +1 -0
  219. package/dist/runtime/builtins/geo/svgExport.d.ts +130 -0
  220. package/dist/runtime/builtins/geo/svgExport.d.ts.map +1 -0
  221. package/dist/runtime/builtins/geo/svgExport.js +50 -0
  222. package/dist/runtime/builtins/geo/svgExport.js.map +1 -0
  223. package/dist/runtime/builtins/geo/transform.d.ts +60 -0
  224. package/dist/runtime/builtins/geo/transform.d.ts.map +1 -0
  225. package/dist/runtime/builtins/geo/transform.js +32 -0
  226. package/dist/runtime/builtins/geo/transform.js.map +1 -0
  227. package/dist/runtime/builtins/index.d.ts +9 -0
  228. package/dist/runtime/builtins/index.d.ts.map +1 -0
  229. package/dist/runtime/builtins/index.js +16 -0
  230. package/dist/runtime/builtins/index.js.map +1 -0
  231. package/dist/runtime/definition/architecture.d.ts +8 -0
  232. package/dist/runtime/definition/architecture.d.ts.map +1 -0
  233. package/dist/runtime/definition/architecture.js +112 -0
  234. package/dist/runtime/definition/architecture.js.map +1 -0
  235. package/dist/runtime/definition/extract.d.ts +12 -0
  236. package/dist/runtime/definition/extract.d.ts.map +1 -0
  237. package/dist/runtime/definition/extract.js +151 -0
  238. package/dist/runtime/definition/extract.js.map +1 -0
  239. package/dist/runtime/error.d.ts +8 -0
  240. package/dist/runtime/error.d.ts.map +1 -0
  241. package/dist/runtime/error.js +11 -0
  242. package/dist/runtime/error.js.map +1 -0
  243. package/dist/runtime/geometry/attributes.d.ts +65 -0
  244. package/dist/runtime/geometry/attributes.d.ts.map +1 -0
  245. package/dist/runtime/geometry/attributes.js +201 -0
  246. package/dist/runtime/geometry/attributes.js.map +1 -0
  247. package/dist/runtime/geometry/builder.d.ts +57 -0
  248. package/dist/runtime/geometry/builder.d.ts.map +1 -0
  249. package/dist/runtime/geometry/builder.js +153 -0
  250. package/dist/runtime/geometry/builder.js.map +1 -0
  251. package/dist/runtime/geometry/copy.d.ts +36 -0
  252. package/dist/runtime/geometry/copy.d.ts.map +1 -0
  253. package/dist/runtime/geometry/copy.js +68 -0
  254. package/dist/runtime/geometry/copy.js.map +1 -0
  255. package/dist/runtime/geometry/generate.d.ts +43 -0
  256. package/dist/runtime/geometry/generate.d.ts.map +1 -0
  257. package/dist/runtime/geometry/generate.js +76 -0
  258. package/dist/runtime/geometry/generate.js.map +1 -0
  259. package/dist/runtime/geometry/groups.d.ts +18 -0
  260. package/dist/runtime/geometry/groups.d.ts.map +1 -0
  261. package/dist/runtime/geometry/groups.js +69 -0
  262. package/dist/runtime/geometry/groups.js.map +1 -0
  263. package/dist/runtime/geometry/index.d.ts +23 -0
  264. package/dist/runtime/geometry/index.d.ts.map +1 -0
  265. package/dist/runtime/geometry/index.js +23 -0
  266. package/dist/runtime/geometry/index.js.map +1 -0
  267. package/dist/runtime/geometry/matrix.d.ts +26 -0
  268. package/dist/runtime/geometry/matrix.d.ts.map +1 -0
  269. package/dist/runtime/geometry/matrix.js +27 -0
  270. package/dist/runtime/geometry/matrix.js.map +1 -0
  271. package/dist/runtime/geometry/merge.d.ts +33 -0
  272. package/dist/runtime/geometry/merge.d.ts.map +1 -0
  273. package/dist/runtime/geometry/merge.js +185 -0
  274. package/dist/runtime/geometry/merge.js.map +1 -0
  275. package/dist/runtime/geometry/primitives.d.ts +41 -0
  276. package/dist/runtime/geometry/primitives.d.ts.map +1 -0
  277. package/dist/runtime/geometry/primitives.js +131 -0
  278. package/dist/runtime/geometry/primitives.js.map +1 -0
  279. package/dist/runtime/geometry/promote.d.ts +44 -0
  280. package/dist/runtime/geometry/promote.d.ts.map +1 -0
  281. package/dist/runtime/geometry/promote.js +203 -0
  282. package/dist/runtime/geometry/promote.js.map +1 -0
  283. package/dist/runtime/geometry/resample.d.ts +29 -0
  284. package/dist/runtime/geometry/resample.d.ts.map +1 -0
  285. package/dist/runtime/geometry/resample.js +165 -0
  286. package/dist/runtime/geometry/resample.js.map +1 -0
  287. package/dist/runtime/geometry/svg.d.ts +91 -0
  288. package/dist/runtime/geometry/svg.d.ts.map +1 -0
  289. package/dist/runtime/geometry/svg.js +216 -0
  290. package/dist/runtime/geometry/svg.js.map +1 -0
  291. package/dist/runtime/geometry/transform.d.ts +18 -0
  292. package/dist/runtime/geometry/transform.d.ts.map +1 -0
  293. package/dist/runtime/geometry/transform.js +56 -0
  294. package/dist/runtime/geometry/transform.js.map +1 -0
  295. package/dist/runtime/index.d.ts +5 -0
  296. package/dist/runtime/index.d.ts.map +1 -0
  297. package/dist/runtime/index.js +4 -0
  298. package/dist/runtime/index.js.map +1 -0
  299. package/dist/runtime/node.d.ts +4 -0
  300. package/dist/runtime/node.d.ts.map +1 -0
  301. package/dist/runtime/node.js +12 -0
  302. package/dist/runtime/node.js.map +1 -0
  303. package/dist/runtime/runtime.d.ts +3 -0
  304. package/dist/runtime/runtime.d.ts.map +1 -0
  305. package/dist/runtime/runtime.js +1198 -0
  306. package/dist/runtime/runtime.js.map +1 -0
  307. package/dist/runtime/types.d.ts +241 -0
  308. package/dist/runtime/types.d.ts.map +1 -0
  309. package/dist/runtime/types.js +2 -0
  310. package/dist/runtime/types.js.map +1 -0
  311. package/dist/shell.d.ts +8 -0
  312. package/dist/shell.js +54 -0
  313. package/dist/shell.js.map +7 -0
  314. package/dist/stage.d.ts +7 -0
  315. package/dist/stage.js +84 -0
  316. package/dist/stage.js.map +7 -0
  317. package/dist/studio/panel.d.ts +48 -0
  318. package/doc/PROJECT_AUTHORING.md +360 -0
  319. 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
+ }