@field/cascade 0.11.0 → 0.12.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.
Files changed (216) hide show
  1. package/AGENTS.md +7 -4
  2. package/ARCHITECTURE.md +5 -4
  3. package/CHANGELOG.md +195 -0
  4. package/README.md +1 -1
  5. package/dist/assets/AgentPanel-1JugFjE4.css +1 -0
  6. package/dist/assets/AgentPanel-BDL5MddA.js +5 -0
  7. package/dist/assets/{CodeEditor-4O7FQ__R.js → CodeEditor-C-xYG-Wn.js} +120 -120
  8. package/dist/assets/CodePanel-CtXd50m6.js +2 -0
  9. package/dist/assets/CookInfoPanel-B3NMhKJF.css +1 -0
  10. package/dist/assets/CookInfoPanel-DG4_TRsX.js +2 -0
  11. package/dist/assets/CustomNodeDialog-CHfZUs-r.js +1 -0
  12. package/dist/assets/DefinitionNode-CaRTXQ_b.js +1 -0
  13. package/dist/assets/DefinitionPanel-C3CxZY9r.js +1 -0
  14. package/dist/assets/DefinitionPanel-VNLnAiQD.css +1 -0
  15. package/dist/assets/OpenGraphDialog-BLdr6k_q.js +1 -0
  16. package/dist/assets/ProjectSettings-ZnvmIAir.js +2 -0
  17. package/dist/assets/{SettingsDialog-Bz8JxISH.js → SettingsDialog-CBX3Wa87.js} +1 -1
  18. package/dist/assets/TimelinePanel-CDeR0arY.css +1 -0
  19. package/dist/assets/TimelinePanel-CWgnFH1e.js +1 -0
  20. package/dist/assets/{VersionHistoryDialog-D5Z0nJ5-.js → VersionHistoryDialog-BOSoW1R-.js} +1 -1
  21. package/dist/assets/assert-BO2_erPD.js +1 -0
  22. package/dist/assets/assert-hvykGCnP.js +1 -0
  23. package/dist/assets/builder-BmBKcDix.js +1 -0
  24. package/dist/assets/camera-DFF7YA3F.js +1 -0
  25. package/dist/assets/checks-DAvyO9Gf.js +1 -0
  26. package/dist/assets/contactSheet-N1NcaWxw.js +2 -0
  27. package/dist/assets/{core-Yqi0Ni61.js → core-DB-MkGjj.js} +3 -4
  28. package/dist/assets/coreTypes-DtnDATZ7.js +1 -0
  29. package/dist/assets/{cssMode-CxUzc4vp.js → cssMode-DPVckSOc.js} +1 -1
  30. package/dist/assets/definitions-B227e7f_.js +1 -0
  31. package/dist/assets/definitions-D0WOUJd7.js +1 -0
  32. package/dist/assets/{editor.api-BNFb25CX.js → editor.api-Dkutg_Z1.js} +1 -1
  33. package/dist/assets/expressions-X-Z-GrgW.js +5 -0
  34. package/dist/assets/file-DAL6IfjV.js +1 -0
  35. package/dist/assets/filters-D3k1LRMa.js +1 -0
  36. package/dist/assets/{freemarker2-0ZDnWxeM.js → freemarker2-CLiLKk3B.js} +1 -1
  37. package/dist/assets/generators-BhDxRAFC.js +1 -0
  38. package/dist/assets/geo-BsMImJIJ.js +1 -0
  39. package/dist/assets/geo-C4YngDob.js +2 -0
  40. package/dist/assets/{handlebars-Cy18MoaD.js → handlebars-CcD3aMeL.js} +1 -1
  41. package/dist/assets/{html-B-2Dx7nq.js → html-DvZWGfqb.js} +1 -1
  42. package/dist/assets/{htmlMode-DUAc9B_d.js → htmlMode-DUD3VaoN.js} +1 -1
  43. package/dist/assets/image-0SfH-snh.js +1 -0
  44. package/dist/assets/image-Ck-RdGU4.js +2 -0
  45. package/dist/assets/index-BWnrmIB9.js +137 -0
  46. package/dist/assets/index-DIaxEONI.css +1 -0
  47. package/dist/assets/io-BGmt2g0D.js +1 -0
  48. package/dist/assets/{javascript-DeQsDqP5.js → javascript-Cap2ahgh.js} +1 -1
  49. package/dist/assets/{jsonMode-BiFwJVSk.js → jsonMode-B0uLjp9C.js} +1 -1
  50. package/dist/assets/{liquid-BLoHH68a.js → liquid-CnxwhfLn.js} +1 -1
  51. package/dist/assets/{lspLanguageFeatures-CNFgm1Kv.js → lspLanguageFeatures-Dn9hlKX6.js} +1 -1
  52. package/dist/assets/math-GeULS-sk.js +1 -0
  53. package/dist/assets/{mdx-CFXQVNfs.js → mdx-BV3jbrVa.js} +1 -1
  54. package/dist/assets/pop-KMF_qloi.js +1 -0
  55. package/dist/assets/preload-helper-Czpn1I53.js +1 -0
  56. package/dist/assets/{python-Cf7S7p2E.js → python-CGyFk4XK.js} +1 -1
  57. package/dist/assets/{razor-CMHBcG-g.js → razor-CQfzX3-N.js} +1 -1
  58. package/dist/assets/remap-5SjXQU-q.js +1 -0
  59. package/dist/assets/renderMarkdown-ork0Oir7.js +67 -0
  60. package/dist/assets/studioImages-CAyH-0Pl.js +1 -0
  61. package/dist/assets/text-ZpX7qNkx.js +2 -0
  62. package/dist/assets/time-P_OiBhcf.js +1 -0
  63. package/dist/assets/{tsMode-BEih0GDj.js → tsMode-BOeXzO9H.js} +1 -1
  64. package/dist/assets/{typescript-COEKYD_a.js → typescript-J1SnE_Tu.js} +1 -1
  65. package/dist/assets/{workers-BNhAhMNn.js → workers-CYwwTiVF.js} +1 -1
  66. package/dist/assets/{xml-CPiMpnPl.js → xml-DnPRNzK9.js} +1 -1
  67. package/dist/assets/{yaml-Bgp1ITLR.js → yaml-BmmYBNa9.js} +1 -1
  68. package/dist/cli/DefinitionNode-P7AA4TAU.js +15 -0
  69. package/dist/cli/{Graph-ZJJTRQTM.js → Graph-OB6EWSGL.js} +12 -12
  70. package/dist/cli/assert-GROGQNCQ.js +25 -0
  71. package/dist/cli/checks-3WB44XBL.js +189 -0
  72. package/dist/cli/{chunk-RQZ4SX5R.js → chunk-2JEU3MGB.js} +2 -2
  73. package/dist/cli/{chunk-WKURDVYP.js → chunk-3RXL5GHB.js} +28 -331
  74. package/dist/cli/chunk-53LGFPWX.js +138 -0
  75. package/dist/cli/chunk-5ORUQ6ES.js +267 -0
  76. package/dist/cli/chunk-73S4JZXK.js +336 -0
  77. package/dist/cli/{chunk-YAT5Y25U.js → chunk-7QE2ZNSN.js} +3 -3
  78. package/dist/cli/{chunk-SGJAET2L.js → chunk-BPODRH52.js} +8 -4
  79. package/dist/cli/{chunk-XWDSKG7N.js → chunk-BZ63XQ3I.js} +2 -2
  80. package/dist/cli/{chunk-FCDXJ6EK.js → chunk-CTPLRSWF.js} +2 -13
  81. package/dist/cli/chunk-EU4ZFZ7Y.js +122 -0
  82. package/dist/cli/{chunk-WIH4TEIS.js → chunk-EZRWJ4G2.js} +1 -1
  83. package/dist/cli/{chunk-BIJO5OFS.js → chunk-FWMSGKEH.js} +1 -1
  84. package/dist/cli/{chunk-POMMNKZZ.js → chunk-G23A2BZZ.js} +38 -5
  85. package/dist/cli/{chunk-35D343DC.js → chunk-GRIN2DDP.js} +19 -1
  86. package/dist/cli/chunk-JVOCK5W4.js +83 -0
  87. package/dist/cli/chunk-KBGUO27Q.js +15 -0
  88. package/dist/cli/{chunk-GFS6W3C5.js → chunk-L6B6FUQP.js} +54 -32
  89. package/dist/cli/chunk-LTXWBXOM.js +438 -0
  90. package/dist/cli/chunk-MI5JLQYA.js +220 -0
  91. package/dist/cli/{chunk-EUIAC3U3.js → chunk-MP653A5O.js} +884 -124
  92. package/dist/cli/{chunk-A4OAMOZH.js → chunk-NJFMDXHR.js} +13 -3
  93. package/dist/cli/{chunk-3JTJHF7V.js → chunk-OM6BEME6.js} +4 -4
  94. package/dist/cli/{chunk-DUIUFVU2.js → chunk-ST6LROUG.js} +49 -23
  95. package/dist/cli/{chunk-RLCAJBVR.js → chunk-TJW67QSI.js} +8 -7
  96. package/dist/cli/chunk-WGKPJZDY.js +364 -0
  97. package/dist/cli/{chunk-D6BUOHUG.js → chunk-X4WKAOQP.js} +4 -4
  98. package/dist/cli/{chunk-VVGSLVSF.js → chunk-X566FWBV.js} +6 -1
  99. package/dist/cli/chunk-YH637PDL.js +317 -0
  100. package/dist/cli/chunk-ZSCUZE6I.js +112 -0
  101. package/dist/cli/{cliCommands-UQSFGEHF.js → cliCommands-JJN5Z3ZC.js} +23 -17
  102. package/dist/cli/{commands-Q23M26QM.js → commands-PHYFYA3F.js} +129 -47
  103. package/dist/cli/contactSheet-2PQVRUFW.js +11 -0
  104. package/dist/cli/{definitions-HF2FTHYU.js → definitions-BPOPW52L.js} +7 -7
  105. package/dist/cli/{doctorCommand-B7BPQMN6.js → doctorCommand-ORWQRNYP.js} +36 -6
  106. package/dist/cli/{edit-JHCPTQFT.js → edit-S5KEQ5RA.js} +3 -3
  107. package/dist/cli/editorCommands-NFR32JOY.js +41 -0
  108. package/dist/cli/{encode-HAUZTYPT.js → encode-ICPEPMH5.js} +2 -2
  109. package/dist/cli/file-3HTQHPYQ.js +41 -0
  110. package/dist/cli/filters-6ODFWYK4.js +379 -0
  111. package/dist/cli/generators-YU7GB4MD.js +210 -0
  112. package/dist/cli/{geo-4RNK3QVN.js → geo-6ZPGKZRU.js} +7 -7
  113. package/dist/cli/{graphCommands-6BMAKGQE.js → graphCommands-EOUOBOIJ.js} +4 -4
  114. package/dist/cli/{graphFile-VPSQ6OF7.js → graphFile-YTGJB5F5.js} +25 -19
  115. package/dist/cli/{headlessCanvas-5XLDZT7M.js → headlessCanvas-ENRHC7GS.js} +3 -2
  116. package/dist/cli/{helpCommand-3VRE3KVO.js → helpCommand-PULH6ZYB.js} +9 -7
  117. package/dist/cli/image-TXELZZK5.js +55 -0
  118. package/dist/cli/index.js +14 -14
  119. package/dist/cli/{math-ZRMLKU2D.js → math-RSYRQ3C6.js} +5 -5
  120. package/dist/cli/{mcp-ZLEEMYGF.js → mcp-JVZFQOEX.js} +4 -4
  121. package/dist/cli/{parity-KINARCP2.js → parity-X6DEH2DV.js} +42 -36
  122. package/dist/cli/{pop-USDFXB7H.js → pop-B7SIIYKN.js} +5 -5
  123. package/dist/cli/project-VYGIA7JX.js +12 -0
  124. package/dist/cli/{projectDefinition-DMTZN2NE.js → projectDefinition-F3D7UIHJ.js} +8 -8
  125. package/dist/cli/{projectRuntime-Z5PJOH47.js → projectRuntime-2Q4JKEH3.js} +19 -12
  126. package/dist/cli/registerStandardNodes-BXJCB6E4.js +744 -0
  127. package/dist/cli/{render-YURAPPUI.js → render-PT4MWI6U.js} +24 -22
  128. package/dist/cli/{runCommand-PI764LEG.js → runCommand-HNPQVZMS.js} +3 -3
  129. package/dist/cli/runner-5XPXVW7J.js +43 -0
  130. package/dist/cli/runtime/image.ts +27 -2
  131. package/dist/cli/runtime/io.ts +78 -0
  132. package/dist/cli/share-MHF6TNRK.js +166 -0
  133. package/dist/cli/stageCache-TY2BFZJR.js +15 -0
  134. package/dist/cli/{stageRunner-KUNIMQKJ.js → stageRunner-KY2EJP7X.js} +2 -2
  135. package/dist/cli/text-MB3EKR4H.js +126 -0
  136. package/dist/cli/{verbs-RCE3K4VQ.js → verbs-PI2JH5FI.js} +2 -2
  137. package/dist/cli/webBuild-WPPMGGW7.js +44 -0
  138. package/dist/contracts/capabilities.d.ts +18 -1
  139. package/dist/contracts/color.d.ts +8 -0
  140. package/dist/contracts/color.js +23 -0
  141. package/dist/contracts/definition.d.ts +10 -0
  142. package/dist/contracts/schema.d.ts +1 -1
  143. package/dist/contracts/schema.js +1 -0
  144. package/dist/contracts/validate.js +11 -1
  145. package/dist/contracts/values.d.ts +24 -0
  146. package/dist/image.d.ts +15 -0
  147. package/dist/image.js +36 -2
  148. package/dist/index.html +8 -2
  149. package/dist/io.d.ts +29 -0
  150. package/dist/io.js +40 -0
  151. package/dist/player/app.js +3 -2
  152. package/dist/player/editor.js +3 -2
  153. package/dist/player/editorEngine.js +3 -2
  154. package/dist/runtime/builtins/assert/checks.d.ts +18 -0
  155. package/dist/runtime/builtins/assert/checks.js +207 -0
  156. package/dist/runtime/builtins/assert/definitions.d.ts +130 -0
  157. package/dist/runtime/builtins/assert/definitions.js +54 -0
  158. package/dist/runtime/builtins/assert/index.d.ts +152 -0
  159. package/dist/runtime/builtins/assert/index.js +36 -0
  160. package/dist/runtime/builtins/image/contactSheet.d.ts +3 -165
  161. package/dist/runtime/builtins/image/contactSheet.js +0 -49
  162. package/dist/runtime/builtins/image/definitions.d.ts +950 -0
  163. package/dist/runtime/builtins/image/definitions.js +343 -0
  164. package/dist/runtime/builtins/image/file.d.ts +8 -0
  165. package/dist/runtime/builtins/image/file.js +37 -0
  166. package/dist/runtime/builtins/image/filters.d.ts +8 -0
  167. package/dist/runtime/builtins/image/filters.js +394 -0
  168. package/dist/runtime/builtins/image/generators.d.ts +7 -0
  169. package/dist/runtime/builtins/image/generators.js +144 -0
  170. package/dist/runtime/builtins/image/index.d.ts +947 -4
  171. package/dist/runtime/builtins/image/index.js +41 -6
  172. package/dist/runtime/builtins/image/io.d.ts +100 -0
  173. package/dist/runtime/builtins/image/io.js +142 -0
  174. package/dist/runtime/builtins/image/planar.d.ts +55 -0
  175. package/dist/runtime/builtins/image/planar.js +274 -0
  176. package/dist/runtime/builtins/image/simplex.d.ts +22 -0
  177. package/dist/runtime/builtins/image/simplex.js +92 -0
  178. package/dist/runtime/builtins/image/text.d.ts +4 -0
  179. package/dist/runtime/builtins/image/text.js +141 -0
  180. package/dist/runtime/builtins/index.d.ts +3 -0
  181. package/dist/runtime/builtins/index.js +7 -0
  182. package/dist/runtime/gpu.d.ts +25 -0
  183. package/dist/runtime/gpu.js +40 -0
  184. package/dist/runtime/runtime.d.ts +2 -0
  185. package/dist/runtime/runtime.js +268 -44
  186. package/dist/runtime/types.d.ts +30 -0
  187. package/doc/CLI_REFERENCE.md +21 -3
  188. package/doc/EDITOR_EXPORT.md +26 -0
  189. package/doc/MCP.md +2 -1
  190. package/doc/NODE_REFERENCE.md +286 -14
  191. package/doc/PROJECT_AUTHORING.md +98 -3
  192. package/package.json +4 -1
  193. package/dist/assets/CodePanel-BU-autmq.js +0 -2
  194. package/dist/assets/CustomNodeDialog-BRpDfOV5.js +0 -1
  195. package/dist/assets/OpenGraphDialog-BwbRlC0X.js +0 -1
  196. package/dist/assets/ProjectSettings-DLOXLxcA.js +0 -2
  197. package/dist/assets/definitions-GreEMXLV.js +0 -1
  198. package/dist/assets/geo-u0n_jOsD.js +0 -1
  199. package/dist/assets/image-cAa-Nu9O.js +0 -2062
  200. package/dist/assets/index-5ZtDAuy2.js +0 -220
  201. package/dist/assets/index-7vae6YFC.css +0 -1
  202. package/dist/assets/math-DioIQOPJ.js +0 -1
  203. package/dist/assets/pop-DC_TQG9t.js +0 -1
  204. package/dist/cli/chunk-36P5K3SD.js +0 -631
  205. package/dist/cli/chunk-4UDFYF5G.js +0 -132
  206. package/dist/cli/chunk-53NMBJAO.js +0 -35
  207. package/dist/cli/chunk-MIIEFUGG.js +0 -623
  208. package/dist/cli/chunk-QBBKRNGY.js +0 -90
  209. package/dist/cli/chunk-WPUDGEFY.js +0 -20
  210. package/dist/cli/editorCommands-UIF5YLUZ.js +0 -33
  211. package/dist/cli/project-K3QIPGBB.js +0 -12
  212. package/dist/cli/registerStandardNodes-S2VLMF6J.js +0 -3081
  213. package/dist/cli/runner-RA6UKEPD.js +0 -37
  214. package/dist/cli/webBuild-GT4PZT5D.js +0 -37
  215. package/dist/runtime/builtins/headless.d.ts +0 -19
  216. package/dist/runtime/builtins/headless.js +0 -25
@@ -589,6 +589,104 @@ Runs on `portable`.
589
589
  | --- | --- | --- | --- |
590
590
  | `geometry` | `geometry` | | |
591
591
 
592
+ ### `cascade.image.Blur`
593
+
594
+ Blur — Box (three passes, fast) or true Gaussian blur.
595
+
596
+ Runs on `portable`.
597
+
598
+ **Inputs**
599
+
600
+ | name | type | default | range |
601
+ | --- | --- | --- | --- |
602
+ | `image` | `image` | | |
603
+
604
+ **Props**
605
+
606
+ | name | type | default | range |
607
+ | --- | --- | --- | --- |
608
+ | `method` | `string` | `"box"` | |
609
+ | `radius` | `float` | `5` | 0…100 |
610
+ | `wrapEdges` | `bool` | `false` | |
611
+
612
+ **Outputs**
613
+
614
+ | name | type | default | range |
615
+ | --- | --- | --- | --- |
616
+ | `image` | `image` | | |
617
+
618
+ ### `cascade.image.Checkers`
619
+
620
+ Checkers — A checkerboard.
621
+
622
+ Runs on `portable`.
623
+
624
+ **Props**
625
+
626
+ | name | type | default | range |
627
+ | --- | --- | --- | --- |
628
+ | `color1` | `color` | `[1,1,1,1]` | |
629
+ | `color2` | `color` | `[0,0,0,1]` | |
630
+ | `mode` | `string` | `"size"` | |
631
+ | `size` | `float` | `32` | 1…512 |
632
+ | `divisions` | `int` | `16` | 1…512 |
633
+ | `centered` | `bool` | `false` | |
634
+ | `resolution` | `vec2i` | `[512,512]` | 1…4096 |
635
+
636
+ **Outputs**
637
+
638
+ | name | type | default | range |
639
+ | --- | --- | --- | --- |
640
+ | `image` | `image` | | |
641
+
642
+ ### `cascade.image.Color`
643
+
644
+ Color — A solid colour.
645
+
646
+ Runs on `portable`.
647
+
648
+ **Props**
649
+
650
+ | name | type | default | range |
651
+ | --- | --- | --- | --- |
652
+ | `color` | `color` | `[1,1,1,1]` | |
653
+ | `resolution` | `vec2i` | `[512,512]` | 1…4096 |
654
+
655
+ **Outputs**
656
+
657
+ | name | type | default | range |
658
+ | --- | --- | --- | --- |
659
+ | `image` | `image` | | |
660
+
661
+ ### `cascade.image.Composite`
662
+
663
+ Composite — Blend image2 over image1.
664
+
665
+ Runs on `portable`.
666
+
667
+ **Inputs**
668
+
669
+ | name | type | default | range |
670
+ | --- | --- | --- | --- |
671
+ | `image1` | `image` | | |
672
+ | `image2` | `image` | | |
673
+
674
+ **Props**
675
+
676
+ | name | type | default | range |
677
+ | --- | --- | --- | --- |
678
+ | `blendMode` | `string` | `"multiply"` | |
679
+ | `opacity` | `float` | `1` | 0…1 |
680
+ | `outputResolution` | `string` | `"input1"` | |
681
+ | `customResolution` | `vec2i` | `[512,512]` | 1…4096 |
682
+ | `fitMode` | `string` | `"fill"` | |
683
+
684
+ **Outputs**
685
+
686
+ | name | type | default | range |
687
+ | --- | --- | --- | --- |
688
+ | `image` | `image` | | |
689
+
592
690
  ### `cascade.image.ContactSheet`
593
691
 
594
692
  Contact Sheet — Lay images out as one labelled grid.
@@ -622,6 +720,190 @@ Runs on `portable`.
622
720
  | `image` | `image` | | |
623
721
  | `asset` | `asset` | | |
624
722
 
723
+ ### `cascade.image.Image`
724
+
725
+ File — An image file from the project, or an image input, optionally resized.
726
+
727
+ Runs on `portable`.
728
+
729
+ **Inputs**
730
+
731
+ | name | type | default | range |
732
+ | --- | --- | --- | --- |
733
+ | `image` | `image` | | |
734
+
735
+ **Props**
736
+
737
+ | name | type | default | range |
738
+ | --- | --- | --- | --- |
739
+ | `file` | `string` | `""` | |
740
+ | `resolutionMode` | `string` | `"original"` | |
741
+ | `maxResolution` | `vec2i` | `[2048,2048]` | 1…4096 |
742
+ | `fixedResolution` | `vec2i` | `[512,512]` | 1…4096 |
743
+
744
+ **Outputs**
745
+
746
+ | name | type | default | range |
747
+ | --- | --- | --- | --- |
748
+ | `image` | `image` | | |
749
+
750
+ ### `cascade.image.Noise`
751
+
752
+ Noise — Fractal simplex noise, grey.
753
+
754
+ Runs on `portable`.
755
+
756
+ **Props**
757
+
758
+ | name | type | default | range |
759
+ | --- | --- | --- | --- |
760
+ | `seed` | `int` | `0` | 0…10000 |
761
+ | `scale` | `float` | `0.01` | 0.001…1 |
762
+ | `iterations` | `int` | `4` | 1…8 |
763
+ | `resolution` | `vec2i` | `[512,512]` | 1…4096 |
764
+
765
+ **Outputs**
766
+
767
+ | name | type | default | range |
768
+ | --- | --- | --- | --- |
769
+ | `image` | `image` | | |
770
+
771
+ ### `cascade.image.NormalMap`
772
+
773
+ Normal Map — A normal map from the red (or grey) channel as height.
774
+
775
+ Runs on `portable`.
776
+
777
+ **Inputs**
778
+
779
+ | name | type | default | range |
780
+ | --- | --- | --- | --- |
781
+ | `image` | `image` | | |
782
+
783
+ **Props**
784
+
785
+ | name | type | default | range |
786
+ | --- | --- | --- | --- |
787
+ | `scale` | `float` | `1` | 0…10 |
788
+ | `flipX` | `bool` | `false` | |
789
+ | `flipY` | `bool` | `false` | |
790
+
791
+ **Outputs**
792
+
793
+ | name | type | default | range |
794
+ | --- | --- | --- | --- |
795
+ | `image` | `image` | | |
796
+
797
+ ### `cascade.image.Ramp`
798
+
799
+ Ramp — A colour ramp: horizontal, vertical, radial or concentric.
800
+
801
+ Runs on `portable`.
802
+
803
+ **Props**
804
+
805
+ | name | type | default | range |
806
+ | --- | --- | --- | --- |
807
+ | `type` | `string` | `"horizontal"` | |
808
+ | `points` | `array` | `[{"position":0,"color":{"r":0,"g":0,"b":0},"interpolation":"linear"},{"position":1,"color":{"r":1,"g":1,"b":1},"interpolation":"linear"}]` | |
809
+ | `resolution` | `vec2i` | `[512,512]` | 1…4096 |
810
+
811
+ **Outputs**
812
+
813
+ | name | type | default | range |
814
+ | --- | --- | --- | --- |
815
+ | `image` | `image` | | |
816
+
817
+ ### `cascade.image.Resize`
818
+
819
+ Resize — Scale an image, or resize it to a fixed size, bilinear.
820
+
821
+ Runs on `portable`.
822
+
823
+ **Inputs**
824
+
825
+ | name | type | default | range |
826
+ | --- | --- | --- | --- |
827
+ | `image` | `image` | | |
828
+
829
+ **Props**
830
+
831
+ | name | type | default | range |
832
+ | --- | --- | --- | --- |
833
+ | `mode` | `string` | `"scale"` | |
834
+ | `scale` | `float` | `1` | 0.1…10 |
835
+ | `width` | `int` | `512` | 1…4096 |
836
+ | `height` | `int` | `512` | 1…4096 |
837
+
838
+ **Outputs**
839
+
840
+ | name | type | default | range |
841
+ | --- | --- | --- | --- |
842
+ | `image` | `image` | | |
843
+
844
+ ### `cascade.image.Text`
845
+
846
+ Text — Text drawn with a CSS font family, or a font file from the project.
847
+
848
+ Runs on `portable`.
849
+
850
+ **Props**
851
+
852
+ | name | type | default | range |
853
+ | --- | --- | --- | --- |
854
+ | `text` | `string` | `"Hello, World!"` | |
855
+ | `font` | `string` | `"Inter, system-ui, sans-serif"` | |
856
+ | `fontSize` | `float` | `48` | 1…500 |
857
+ | `fontWeight` | `string` | `"normal"` | |
858
+ | `fontStyle` | `string` | `"normal"` | |
859
+ | `alignH` | `string` | `"center"` | |
860
+ | `alignV` | `string` | `"middle"` | |
861
+ | `color` | `color` | `[1,1,1,1]` | |
862
+ | `backgroundColor` | `color` | `[0,0,0,0]` | |
863
+ | `resolution` | `vec2i` | `[512,512]` | 1…4096 |
864
+ | `offset` | `vec2` | `[0,0]` | -2048…2048 |
865
+ | `rotation` | `float` | `0` | -180…180 |
866
+ | `letterSpacing` | `float` | `0` | -50…100 |
867
+ | `lineHeight` | `float` | `1.2` | 0.5…3 |
868
+ | `opacity` | `float` | `1` | 0…1 |
869
+
870
+ **Outputs**
871
+
872
+ | name | type | default | range |
873
+ | --- | --- | --- | --- |
874
+ | `image` | `image` | | |
875
+
876
+ ### `cascade.image.Transform`
877
+
878
+ Transform — Rotate, translate and scale an image about a pivot.
879
+
880
+ Runs on `portable`.
881
+
882
+ **Inputs**
883
+
884
+ | name | type | default | range |
885
+ | --- | --- | --- | --- |
886
+ | `image` | `image` | | |
887
+
888
+ **Props**
889
+
890
+ | name | type | default | range |
891
+ | --- | --- | --- | --- |
892
+ | `translate` | `vec2` | `[0,0]` | -2048…2048 |
893
+ | `rotation` | `float` | `0` | -180…180 |
894
+ | `scale` | `vec2` | `[1,1]` | 0.01…10 |
895
+ | `uniformScale` | `bool` | `true` | |
896
+ | `pivot` | `string` | `"center"` | |
897
+ | `customPivot` | `vec2` | `[0.5,0.5]` | 0…1 |
898
+ | `filter` | `string` | `"bilinear"` | |
899
+ | `wrap` | `string` | `"clamp"` | |
900
+
901
+ **Outputs**
902
+
903
+ | name | type | default | range |
904
+ | --- | --- | --- | --- |
905
+ | `image` | `image` | | |
906
+
625
907
  ### `cascade.math.Binary`
626
908
 
627
909
  Binary Math — Two values, one operation. Component-wise, and a scalar broadcasts against a vector.
@@ -1006,13 +1288,13 @@ Runs on `portable`.
1006
1288
  | --- | --- | --- | --- |
1007
1289
  | `scene` | `scene` | | |
1008
1290
 
1009
- ## Assertions, headless only
1291
+ ## Assertions
1010
1292
 
1011
1293
  `cascade.assert.*` fail a `cascade run` (non-zero exit, the message in
1012
1294
  `run --json`'s `error.message`) when their check does not hold, and pass
1013
- their input through. The CLI registers them; Studio does not yet, and shows
1014
- them as unresolved. An image wired only into assertions still counts as the
1015
- graph's final image for `run --out`.
1295
+ their input through. In Studio a failed assertion is the node's error. An image
1296
+ wired only into assertions still counts as the graph's final image for
1297
+ `run --out`.
1016
1298
 
1017
1299
  ### `cascade.assert.Equals`
1018
1300
 
@@ -1133,16 +1415,6 @@ under `src/nodes/<library>/nodes/`.
1133
1415
  ### Geometry — `cascade.geo.*`
1134
1416
 
1135
1417
  **Geometry.** `cascade.geo.Rectangle` (A closed four-point polygon, counter-clockwise from bottom-left.), `cascade.geo.Circle` (A closed circle, as one cubic Bezier chain or as a polygon of divisions segments.), `cascade.geo.Transform` (Translate, rotate and scale geometry about a pivot.), `cascade.geo.Merge` (Concatenate geometries, taking the union of their attributes.), `cascade.geo.CopyToPoints` (Instance one geometry onto every point of another.), `cascade.geo.SvgExport` (Write geometry as an SVG document, one group element per group.), `cascade.geo.Render` (Draw a scene through a camera, as a raster.), `cascade.geo.FromRects` (Convert rects into geometry, one closed polygon each, keeping the tag.)
1136
-
1137
- ### Image — `cascade.image.*`
1138
-
1139
- **Create.** `Image` (Load images from files), `Color` (Create a solid color canvas), `Checkers` (Generate a checkerboard pattern), `Noise` (Generate procedural noise patterns), `Ramp` (Generate color ramps), `Text` (Render text with customizable font and style)
1140
-
1141
- **Filter.** `Blur` (Gaussian blur), `NormalMap` (Compute normal map from height map)
1142
-
1143
- **Transform.** `Transform` (2D rotation, translation, and scaling), `Resize` (Scale or resize an image)
1144
-
1145
- **Composite.** `Composite` (Blend two images together)
1146
1418
  ## A project's own nodes
1147
1419
 
1148
1420
  Not listed here, because they belong to the project rather than to Cascade. Ask
@@ -61,6 +61,40 @@ difference. Use a deliberate local package override
61
61
  for framework development rather than committing a machine-specific
62
62
  `file:../../Dev/cascade` dependency to a shared project.
63
63
 
64
+ ### Pin the core
65
+
66
+ A sketch pins one published Cascade, exactly, rather than linking the live
67
+ checkout, so a change on Cascade main cannot move its pixels until it opts in:
68
+
69
+ ```json
70
+ "devDependencies": {
71
+ "cascade": "npm:@field/cascade@0.11.0",
72
+ "@field/cascade-kit": "file:../../Dev/cascade/packages/kit"
73
+ }
74
+ ```
75
+
76
+ Keep the dependency name `cascade`: imports stay `cascade/io`,
77
+ `cascade/stage` and so on, which is what Studio's compiler resolves. Only the
78
+ core is pinned; the kit is not on npm and stays a `file:` dependency. Commit
79
+ the lockfile, since it holds the core's own dependencies (a newer
80
+ `@napi-rs/canvas` shifts antialiasing by a few levels). To move from a link:
81
+
82
+ ```bash
83
+ npm install --save-dev --save-exact cascade@npm:@field/cascade@0.11.0
84
+ ```
85
+
86
+ If `node_modules/cascade` is still a link afterwards, or npm fails with
87
+ `Cannot destructure property 'package' of 'node.target'`, the kit link is the
88
+ cause: its target sits inside the checkout, whose own package is
89
+ `@field/cascade`, so npm reuses the checkout. Move `node_modules` and
90
+ `package-lock.json` aside, install with the kit removed from `package.json`,
91
+ then add it back with `npm install --save-dev ../../Dev/cascade/packages/kit`.
92
+
93
+ To bump: change the version, `npm install`, `npx cascade check <graph>`, and
94
+ render a frame to compare. A sketch that needs something only on main (for
95
+ example `cascade share` before it ships) keeps the `file:` link and says why in
96
+ its README until the next release.
97
+
64
98
  `index.cascade` is the default graph name. A project may contain several `.cascade` files; pass one explicitly when there is no unambiguous default:
65
99
 
66
100
  ```bash
@@ -209,7 +243,7 @@ Clean graph design is clean code design:
209
243
  - **What varies is a parameter**; seeds, counts and colours are on the node, not constants in the code.
210
244
  - **Shared helpers go in `lib/` or the kit** (`KIT.md`); the node is the unit you compose and reuse.
211
245
 
212
- Split a node when it does two of load, generate, style, render and export, or when its `execute` grows past about 150 lines.
246
+ Split a node when it does two of load, generate, style, render and export, or when its `execute` grows past about 150 lines. `cascade check` warns on both (`shape/long-execute`, `shape/mixed-jobs`); the warnings are advice and never fail the check. Drawing with noise and colour is one job's worth of calls, so it only flags a module doing four of the five, or loading and exporting in the same node.
213
247
 
214
248
  ## Add a custom node
215
249
 
@@ -423,8 +457,8 @@ export async function execute(context: NodeExecutionContext<typeof definition>)
423
457
  | | Browser (Studio, exported editor) | Headless (CLI, MCP) |
424
458
  | --- | --- | --- |
425
459
  | `createCanvas`, `surface` | the realm's `OffscreenCanvas` | Skia's, from `@napi-rs/canvas` |
426
- | `decodeImage`, `readImage` | `createImageBitmap` | Skia's decoder |
427
- | `writeImage` | an in-memory generated asset | `.cascade-cache/<name>.<hash>.png` |
460
+ | `decodeImage`, `readImage` | `createImageBitmap` | the pixels from memory while the run holds them, else Skia's decoder |
461
+ | `writeImage` | an in-memory generated asset | `.cascade-cache/<name>.<hash>.png`, pixels held in memory and the file written behind |
428
462
  | `registerFont` | `FontFace` added to the page's or worker's font set | Skia's `GlobalFonts` |
429
463
  | `readBytes` | shipped files only (`editor.assets`, literal asset props, frozen files) | any project file |
430
464
 
@@ -445,6 +479,38 @@ export async function execute(context: NodeExecutionContext<typeof definition>)
445
479
  its output in an editor, freeze it (`cascade freeze <graph> <node> --fields
446
480
  path,size,channels,depth,space` ships the image file with the snapshot).
447
481
 
482
+ #### How an image travels between nodes
483
+
484
+ An `image` port carries an `ImageRef` (a path plus size, channels, depth and
485
+ space), never the pixels, so a value stays cheap to snapshot, hash, trace and
486
+ send to Python. What sits behind the path is the host's business, and the
487
+ headless host keeps it in memory:
488
+
489
+ - `writeImage` (and `saveImage` in `cascade/io`) hands the canvas to the host
490
+ as `ImagePixels` (8-bit RGBA, sRGB, unpremultiplied, top row first: what
491
+ `getImageData` returns and what a PNG decodes to) through the optional
492
+ `assets.keepImage`. Under `cascade run`/`render` the host holds those pixels,
493
+ names the file by their hash, and writes a lossless PNG at zlib level 1
494
+ behind the run, off the main thread.
495
+ - `readImage` (and `loadBitmap`/`loadImage`) asks `assets.imagePixels` first
496
+ and gets a canvas holding the pixels: no file read and no decode. The next
497
+ node sees the same numbers a PNG round trip would give it.
498
+ - Anything that reads the path as a file gets a whole file: a Python stage
499
+ call, `assets.read`, a run's end, `freeze`, `lock` and `ladder` all wait for
500
+ the write behind, and so does every `runsOn: 'server'` node before it
501
+ starts, since it may read an input with `node:fs`. A run's saved outputs
502
+ (`--out`, `run --frames`, `render`) are encoded from the pixels at full
503
+ compression, never copied from the level-1 intermediate.
504
+ - Hosts without `keepImage` (an exported editor, the web player, and Studio
505
+ for project nodes) encode and store as before, so a node written against
506
+ `readImage`/`writeImage` works unchanged in each. Studio gives `keepImage`
507
+ to the built-in image library only: its images stay in the page under
508
+ `.cascade-studio/…` paths, which `readImage`, `assets.read` and the Viewer
509
+ all resolve, but which name no file a server stage could open.
510
+
511
+ On field-logo (12 canvas nodes at 1024²) this took a frame from 1,791 ms to
512
+ about 860 ms; most of what remains is the nodes' own pixel loops.
513
+
448
514
  ### GPU nodes today
449
515
 
450
516
  A definition-v1 node may declare `capabilities: ['gpu']`. Studio and the optional
@@ -453,6 +519,26 @@ a cache scoped to each node instance for pipelines, samplers, and other
453
519
  resources that outlive one cook. The host clears cached resources on host
454
520
  disposal or device loss and requests a fresh device on a later cook.
455
521
 
522
+ The device is asked for with every limit the adapter allows, not WebGPU's
523
+ defaults: on an M3 Max that is 4 GiB per storage binding (default 128 MiB),
524
+ 1,024 invocations per workgroup (256), 32 KiB of workgroup storage (16 KiB) and
525
+ 10 storage buffers per stage (8). Read what you got from
526
+ `context.capabilities.gpu.limits` and size buffers and workgroups from it. A
527
+ node that cannot run below some limit declares it, and a smaller GPU then fails
528
+ before the cook with a sentence naming the limit:
529
+
530
+ ```ts
531
+ export const definition = {
532
+ apiVersion: 1,
533
+ runsOn: 'portable',
534
+ capabilities: ['gpu'],
535
+ gpuLimits: { maxStorageBufferBindingSize: 512 * 2 ** 20 },
536
+ // ...
537
+ } as const;
538
+ ```
539
+
540
+ `max*` limits are floors; `min*Alignment` limits are ceilings.
541
+
456
542
  Use `runsOn: 'portable'` for shared WebGPU code without browser APIs. Render into
457
543
  a texture and use `readTexture` from `cascade/gpu` for explicit RGBA8 pixels,
458
544
  then encode through the image/IO host. See [headless GPU rendering](HEADLESS_GPU.md)
@@ -684,6 +770,15 @@ in `cascade run --json` under `stages`, and in the run trace.
684
770
  keeps running its old code in a live Studio. Its bytecode cache is keyed by
685
771
  the code hash, because Python accepts a `.pyc` whose source kept its size
686
772
  within the same second.
773
+ - `workers` (headless runs only) is how many warm workers `cascade run` keeps
774
+ for the project, and so how many independent nodes it cooks at once: sibling
775
+ stage calls in one frame (the morph's four renders) run side by side. Default
776
+ 2–4, one per four cores and per 8 GB of memory; `CASCADE_STAGE_WORKERS`
777
+ overrides it, and `cascade render` workers keep one each. A second worker
778
+ starts only when a call finds the first busy. Nodes still start in the
779
+ graph's order, so the run trace lists them the same way every run; a stage
780
+ that writes a fixed path shared with another node is the one thing this can
781
+ break, and `"workers": 1` turns it off.
687
782
  - `cache` controls Cascade's own result cache. A stored result is served only
688
783
  while every file it names still has the bytes it had, so a stage that writes
689
784
  a fixed path and was re-run with other inputs misses rather than serving the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@field/cascade",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Visual programming for generative art",
5
5
  "license": "MIT",
6
6
  "author": "FIELD.IO <marcus@field.io>",
@@ -147,6 +147,8 @@
147
147
  "check": "svelte-check --tsconfig ./tsconfig.json",
148
148
  "verify": "node scripts/verify.mjs",
149
149
  "verify:fast": "node scripts/verify.mjs --fast",
150
+ "verify:push": "node scripts/verify.mjs --push",
151
+ "prepare": "node scripts/install-hooks.mjs",
150
152
  "check:architecture": "vitest run tests/architecture-",
151
153
  "check:bundle": "node scripts/bundle-budget.mjs",
152
154
  "check:node-reference": "tsx scripts/build-node-reference.mjs --check",
@@ -183,6 +185,7 @@
183
185
  "svelte": "^5.0.0",
184
186
  "svelte-check": "^4.7.6",
185
187
  "tsx": "^4.23.12",
188
+ "typescript7": "npm:typescript@^7.0.2",
186
189
  "vite": "^8.2.2",
187
190
  "vitest": "^4.1.11"
188
191
  },
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/CodeEditor-4O7FQ__R.js","assets/legacy-CTEeXeqF.js","assets/nodeTypeUtils-BDJsc2Ks.js","assets/index-5ZtDAuy2.js","assets/index-client-DqYmKstU.js","assets/index-7vae6YFC.css","assets/editor.api-BNFb25CX.js","assets/editor-1FQrmyyI.css","assets/CodeEditor-DR7u0q7p.css"])))=>i.map(i=>d[i]);
2
- import{Dt as e,G as t,M as n,Ot as r,Q as i,U as a,V as o,W as s,Z as c,ct as l,dt as u,et as d,ht as f,i as p,it as m,jt as h,l as g,nt as _,ot as v,pt as y,r as b,rt as x,st as S,vt as C,yt as w,z as T}from"./legacy-CTEeXeqF.js";import{P as E,et as D}from"./index-5ZtDAuy2.js";var O=t(`<div class="loading svelte-1pkj8m">Loading editor...</div>`),k=t(`<div class="error svelte-1pkj8m">Loading...</div>`),A=t(`<div class="error svelte-1pkj8m"> </div>`),j=t(`<div class="panel-wrapper svelte-1pkj8m"><!></div>`);function M(t,M){r(M,!1);let N=()=>w(D,`$sharedContextStore`,P),[P,F]=C(),I=u(null);b(async()=>{let e=await E(()=>import(`./CodeEditor-4O7FQ__R.js`).then(e=>e.t),__vite__mapDeps([0,1,2,3,4,5,6,7,8]));y(I,e.default)});let L=p(M,`panelParams`,8),R=p(M,`panelApi`,8),z=p(M,`graph`,12,void 0),B=p(M,`onRecordHistory`,12,void 0),V=u(null),H=L()?.nodeId;function U(){R()?.close&&R().close()}_(()=>N(),()=>{N()&&(z(N().graph),B(N().onRecordHistory))}),_(()=>c(z()),()=>{z()&&H?y(V,z().getNode(H)||null):y(V,null)}),_(()=>(c(R()),i(V)),()=>{R()?.setTitle&&i(V)&&R().setTitle(`Code: ${i(V).id}`)}),x(),g();var W=j(),G=v(W),K=e=>{var t=s(),r=S(t);{let e=f(()=>(c(z()),d(()=>z().packageManager||null)));n(r,()=>i(I),(t,n)=>{n(t,{get node(){return i(V)},get graph(){return z()},get packageManager(){return i(e)},onClose:U,showCloseButton:!1,get onRecordHistory(){return B()}})})}a(e,t)},q=e=>{var t=O();a(e,t)},J=e=>{var t=k();a(e,t)},Y=e=>{var t=A(),n=l(t);m(()=>o(n,`Node not found: ${H??``}`)),a(e,t)};T(G,e=>{i(V)&&z()&&i(I)?e(K):i(I)?z()?e(Y,-1):e(J,2):e(q,1)}),h(W),a(t,W),e(),F()}export{M as default};
@@ -1 +0,0 @@
1
- import{At as e,Dt as t,G as n,I as r,L as i,O as ee,Ot as a,Q as o,U as s,V as c,W as l,X as u,Z as d,_ as te,at as f,b as p,ct as m,d as h,dt as g,et as _,f as ne,i as v,it as y,jt as b,l as x,lt as S,nt as C,ot as w,p as re,pt as T,rt as E,s as ie,st as D,t as O,u as ae,v as k,z as A}from"./legacy-CTEeXeqF.js";import{H as j,U as M}from"./index-5ZtDAuy2.js";var N=n(`<span class="auto-badge svelte-1c1mvak">auto</span>`),P=n(`<span class="radio-path svelte-1c1mvak"> </span>`),F=n(`<input type="text" class="custom-base-input svelte-1c1mvak" placeholder="e.g., cascade.mylib.MyBaseNode" autocomplete="off"/>`),I=n(`<label><input type="radio" name="baseClass" class="svelte-1c1mvak"/> <div class="radio-content svelte-1c1mvak"><div class="radio-header svelte-1c1mvak"><span class="radio-label svelte-1c1mvak"> </span> <!></div> <!></div></label>`),oe=n(`<div class="dialog-overlay svelte-1c1mvak"><div class="dialog svelte-1c1mvak" role="dialog" aria-modal="true" aria-labelledby="custom-node-title"><div class="dialog-header svelte-1c1mvak"><h2 id="custom-node-title" class="svelte-1c1mvak">Create Custom Node</h2> <button class="close-button svelte-1c1mvak" aria-label="Close"><!></button></div> <form class="svelte-1c1mvak"><div class="form-group svelte-1c1mvak"><label for="node-name" class="svelte-1c1mvak">Node Name</label> <input id="node-name" type="text" placeholder="e.g., ParticleField" autocomplete="off" class="svelte-1c1mvak"/> <span class="hint svelte-1c1mvak">The display name for your node</span></div> <div class="form-group svelte-1c1mvak"><label for="module-path" class="svelte-1c1mvak">Module Path</label> <input id="module-path" type="text" placeholder="e.g., project.particle-field" autocomplete="off" class="svelte-1c1mvak"/> <span class="hint svelte-1c1mvak">Unique identifier for the node module <!></span></div> <div class="form-group svelte-1c1mvak"><span class="field-label svelte-1c1mvak">Base Class</span> <div class="base-class-options svelte-1c1mvak"></div></div> <div class="dialog-footer svelte-1c1mvak"><button type="button" class="cancel-button svelte-1c1mvak">Cancel</button> <button type="submit" class="create-button svelte-1c1mvak"><!> Create Node</button></div></form></div></div>`);function L(n,L){a(L,!1);let R=g(),se=[],z=v(L,`open`,12,!1),B=O(),V=g(``),H=g(``),U=g(`cascade.Node`),W=g(``),G=g(!0),K=[{id:`cascade.Node`,label:`Node`,description:`Base class for all nodes - use for general purpose computation`,template:`node`},{id:`cascade.image.ImageNodeBase`,label:`ImageNodeBase`,description:`Image processing base class with canvas/image utilities`,template:`image`},{id:`custom`,label:`Other`,description:`Specify a custom base class path`,template:`node`}];function ce(){T(G,!1)}function le(){let e=`local.${o(V).toLowerCase().replace(/[^a-z0-9]/g,``)}`;(o(H)===e||o(H)===``)&&T(G,!0)}function q(){if(!o(V).trim()||o(U)===`custom`&&!o(W).trim())return;let e=K.find(e=>e.id===o(U));B(`create`,{name:o(V).trim(),modulePath:o(H)||`local.${o(V).toLowerCase().replace(/[^a-z0-9]/g,``)}`,baseClass:o(R),template:e?.template||`node`}),Y()}function J(){Y(),B(`close`)}function Y(){T(V,``),T(H,``),T(U,`cascade.Node`),T(W,``),T(G,!0),z(!1)}function X(e){e.key===`Escape`?J():e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),q())}let Z=g();C(()=>(o(U),o(W)),()=>{T(R,o(U)===`custom`?o(W):o(U))}),C(()=>(o(G),o(V)),()=>{if(o(G)&&o(V)){let e=o(V).toLowerCase().replace(/[^a-z0-9]/g,``);T(H,`local.${e}`)}}),C(()=>(d(z()),o(Z)),()=>{z()&&o(Z)&&setTimeout(()=>o(Z)?.focus(),50)}),E(),x();var Q=l();u(`keydown`,f,X);var $=D(Q),ue=t=>{var n=oe(),a=w(n),l=w(a),d=S(w(l),2),f=w(d);M(f,{size:18}),b(d),b(l);var g=S(l,2),v=w(g),x=S(w(v),2);p(x),re(x,e=>T(Z,e),()=>o(Z)),e(2),b(v);var C=S(v,2),E=S(w(C),2);p(E);var D=S(E,2),O=S(w(D)),R=e=>{var t=N();s(e,t)};A(O,e=>{o(G)&&e(R)}),b(D),b(C);var z=S(C,2),B=S(w(z),2);r(B,5,()=>K,i,(e,t)=>{var n=I();let r;var i=w(n);p(i);var a,l=S(i,2),d=w(l),f=w(d),h=m(f,!0),g=S(f,2),v=e=>{var n=P(),r=m(n,!0);y(()=>c(r,(o(t),_(()=>o(t).id)))),s(e,n)};A(g,e=>{o(t),_(()=>o(t).id!==`custom`)&&e(v)}),b(d);var x=S(d,2),C=e=>{var t=F();p(t),k(t,()=>o(W),e=>T(W,e)),u(`click`,t,ne(function(e){ie.call(this,L,e)})),s(e,t)};A(x,e=>{o(t),o(U),_(()=>o(t).id===`custom`&&o(U)===`custom`)&&e(C)}),b(l),b(n),y(()=>{r=ee(n,1,`radio-option svelte-1c1mvak`,null,r,{selected:o(U)===o(t).id}),a!==(a=(o(t),_(()=>o(t).id)))&&(i.value=(i.__value=a)??``),c(h,(o(t),_(()=>o(t).label)))}),te(se,[],i,()=>(o(t),_(()=>o(t).id),o(U)),e=>T(U,e)),s(e,n)}),b(B),b(z);var Y=S(z,2),X=w(Y),Q=S(X,2),$=w(Q);j($,{name:`Zap`,size:14}),e(),b(Q),b(Y),b(g),b(a),b(n),y(e=>Q.disabled=e,[()=>(o(V),o(U),o(W),_(()=>!o(V).trim()||o(U)===`custom`&&!o(W).trim()))]),u(`click`,d,J),k(x,()=>o(V),e=>T(V,e)),u(`input`,x,le),k(E,()=>o(H),e=>T(H,e)),u(`input`,E,ce),u(`click`,X,J),u(`submit`,g,ae(q)),u(`click`,n,h(J)),s(t,n)};A($,e=>{z()&&e(ue)}),s(n,Q),t()}export{L as default};
@@ -1 +0,0 @@
1
- import{Dt as e,G as t,I as n,O as r,Ot as i,Q as a,U as o,V as s,W as c,X as l,Z as u,at as d,ct as f,d as p,dt as m,et as h,i as g,it as _,jt as v,l as y,lt as b,nt as x,ot as S,pt as C,rt as w,st as T,t as E,x as D,z as O}from"./legacy-CTEeXeqF.js";import{U as k}from"./index-5ZtDAuy2.js";var A=t(`<p class="root svelte-1j8ra8p"> </p>`),j=t(`<p class="note svelte-1j8ra8p">Loading…</p>`),M=t(`<p class="note error svelte-1j8ra8p"> </p>`),N=t(`<p class="note svelte-1j8ra8p">No <code>.cascade</code> files at the project root.</p>`),P=t(`<span class="tag svelte-1j8ra8p">open</span>`),F=t(`<li><button><span class="name"> </span> <!></button></li>`),I=t(`<ul class="graphs svelte-1j8ra8p"></ul>`),L=t(`<div class="dialog-overlay svelte-1j8ra8p"><div class="dialog svelte-1j8ra8p" role="dialog" aria-modal="true" aria-labelledby="open-graph-title"><div class="dialog-header svelte-1j8ra8p"><h2 id="open-graph-title" class="svelte-1j8ra8p">Open graph</h2> <button class="close-button svelte-1j8ra8p" aria-label="Close"><!></button></div> <!> <div class="body svelte-1j8ra8p"><!></div> <div class="dialog-footer svelte-1j8ra8p"><button class="secondary svelte-1j8ra8p">Open from this computer…</button></div></div></div>`);function R(t,R){i(R,!1);let z=g(R,`open`,8,!1),B=g(R,`current`,8,null),V=E(),H=m([]),U=m(``),W=m(!1),G=m(null);async function K(){C(W,!0),C(G,null);try{let e=await fetch(`/api/graph`);if(!e.ok)throw Error(await e.text());let t=await e.json();C(H,Array.isArray(t.graphs)?t.graphs:[]),C(U,typeof t.root==`string`?t.root:``)}catch(e){C(G,e instanceof Error?e.message:String(e)),C(H,[])}finally{C(W,!1)}}function q(e){V(`choose`,{filename:e})}function J(){V(`close`)}function Y(e){e.key===`Escape`&&J()}x(()=>u(z()),()=>{z()&&K()}),w(),y();var X=c();l(`keydown`,d,Y);var Z=T(X),Q=e=>{var t=L(),i=S(t),c=S(i),u=b(S(c),2),d=S(u);k(d,{size:16}),v(u),v(c);var m=b(c,2),g=e=>{var t=A(),n=f(t,!0);_(()=>{D(t,`title`,a(U)),s(n,a(U))}),o(e,t)};O(m,e=>{a(U)&&e(g)});var y=b(m,2),x=S(y),C=e=>{var t=j();o(e,t)},w=e=>{var t=M(),n=f(t);_(()=>s(n,`No project on this server — ${a(G)??``}`)),o(e,t)},T=e=>{var t=N();o(e,t)},E=e=>{var t=I();n(t,5,()=>a(H),e=>e,(e,t)=>{var n=F(),i=S(n);let c;var u=S(i),d=f(u,!0),p=b(u,2),m=e=>{var t=P();o(e,t)};O(p,e=>{a(t)===B()&&e(m)}),v(i),v(n),_(()=>{c=r(i,1,`graph svelte-1j8ra8p`,null,c,{current:a(t)===B()}),s(d,a(t))}),l(`click`,i,()=>q(a(t))),o(e,n)}),v(t),o(e,t)};O(x,e=>{a(W)?e(C):a(G)?e(w,1):(a(H),h(()=>a(H).length===0)?e(T,2):e(E,-1))}),v(y);var R=b(y,2),z=f(R);v(i),v(t),l(`click`,u,J),l(`click`,z,()=>V(`local`)),l(`click`,t,p(J)),o(e,t)};O(Z,e=>{z()&&e(Q)}),o(t,X),e()}export{R as default};
@@ -1,2 +0,0 @@
1
- import{At as e,C as t,Dt as n,G as r,I as i,L as a,O as o,Ot as s,Q as c,U as l,V as u,W as d,X as f,Z as p,_t as m,a as h,at as g,b as _,ct as v,d as ee,dt as y,et as b,i as te,it as x,jt as S,l as C,lt as w,nt as T,o as E,ot as D,pt as O,rt as ne,st as re,t as k,v as A,z as j}from"./legacy-CTEeXeqF.js";import{$ as M,G as ie,K as ae,U as oe,W as se,Z as ce,b as N,x as P}from"./index-5ZtDAuy2.js";var F=new Set([`$$slots`,`$$events`,`$$legacy`]);function le(e,t){let n=h(t,F),r=[[`path`,{d:`M10 11v6`}],[`path`,{d:`M14 11v6`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`}],[`path`,{d:`M3 6h18`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`}]];M(e,E({name:`trash-2`},()=>n,{get iconNode(){return r}}))}var ue=r(`<span> </span>`),de=r(`<div class="credentials-status svelte-9d4ggp"><!> <small class="svelte-9d4ggp">Add missing values to <code>~/.cascade/credentials.yaml</code> or the file named by <code>CASCADE_CREDENTIALS</code>. Values are never shown here.</small></div>`),fe=r(`<div class="empty-state svelte-9d4ggp"><!> <p class="svelte-9d4ggp">No project packages configured</p> <button class="add-button svelte-9d4ggp"><!> Add Package</button></div>`),pe=r(`<div class="package-item svelte-9d4ggp"><div class="package-info svelte-9d4ggp"><span class="package-alias svelte-9d4ggp"> </span> <span class="package-path svelte-9d4ggp"> </span></div> <button class="remove-button svelte-9d4ggp" aria-label="Remove package"><!></button></div>`),me=r(`<button class="add-button secondary svelte-9d4ggp"><!> Add Package</button>`),he=r(`<div class="packages-list svelte-9d4ggp"></div> <!>`,1),ge=r(`<div class="error-message svelte-9d4ggp"><!> </div>`),_e=r(`<div class="add-form svelte-9d4ggp"><div class="form-row svelte-9d4ggp"><label for="package-path" class="svelte-9d4ggp">Path</label> <div class="input-with-button svelte-9d4ggp"><input id="package-path" type="text" placeholder="./src or ../shared-lib" class="svelte-9d4ggp"/> <button class="browse-button svelte-9d4ggp" title="Browse folder"><!></button></div></div> <div class="form-row svelte-9d4ggp"><label for="package-alias" class="svelte-9d4ggp">Alias</label> <input id="package-alias" type="text" placeholder="myproject" class="svelte-9d4ggp"/></div> <!> <div class="form-actions svelte-9d4ggp"><button class="cancel-button svelte-9d4ggp">Cancel</button> <button class="confirm-button svelte-9d4ggp">Add Package</button></div></div>`),ve=r(`<div class="modal-overlay svelte-9d4ggp"><div class="modal svelte-9d4ggp" role="dialog" aria-modal="true" aria-labelledby="modal-title"><div class="modal-header svelte-9d4ggp"><h2 id="modal-title" class="svelte-9d4ggp"><!> Project Settings</h2> <button class="close-button svelte-9d4ggp" aria-label="Close"><!></button></div> <div class="modal-body svelte-9d4ggp"><section class="section svelte-9d4ggp"><h3 class="svelte-9d4ggp">Graph Metadata <small class="svelte-9d4ggp">(current .cascade file)</small></h3> <div class="form-row svelte-9d4ggp"><label for="graph-name" class="svelte-9d4ggp">Name</label><input id="graph-name" class="svelte-9d4ggp"/></div> <div class="form-row svelte-9d4ggp"><label for="graph-description" class="svelte-9d4ggp">Description</label><input id="graph-description" class="svelte-9d4ggp"/></div> <div class="form-row svelte-9d4ggp"><label for="graph-author" class="svelte-9d4ggp">Author</label><input id="graph-author" class="svelte-9d4ggp"/></div> <div class="form-row svelte-9d4ggp"><label for="graph-created" class="svelte-9d4ggp">Created</label><input id="graph-created" readonly="" class="svelte-9d4ggp"/></div></section> <section class="section svelte-9d4ggp"><h3 class="svelte-9d4ggp">Project Manifest <small class="svelte-9d4ggp">(cascade.json, shared by every graph)</small></h3> <div class="form-row svelte-9d4ggp"><label for="project-name" class="svelte-9d4ggp">Project name</label><input id="project-name" class="svelte-9d4ggp"/></div> <div class="form-row svelte-9d4ggp"><label for="commands-json" class="svelte-9d4ggp">Allowed commands</label><textarea id="commands-json" rows="4" class="svelte-9d4ggp"></textarea></div> <div class="form-row svelte-9d4ggp"><label for="settings-json" class="svelte-9d4ggp">Node settings</label><textarea id="settings-json" rows="5" class="svelte-9d4ggp"></textarea></div> <div class="form-row svelte-9d4ggp"><label for="credentials-list" class="svelte-9d4ggp">Required credentials</label><textarea id="credentials-list" rows="3" placeholder="one credential name per line" class="svelte-9d4ggp"></textarea></div> <!></section> <section class="section svelte-9d4ggp"><h3 class="svelte-9d4ggp">Project Packages</h3> <p class="section-description svelte-9d4ggp">Add local folders as packages. Each package gets an alias that you can use to import modules. <br/> Example: <code class="svelte-9d4ggp">myproject.filters.Blur</code> for file <code class="svelte-9d4ggp">./src/filters/Blur.ts</code></p> <!> <!></section> <section class="section svelte-9d4ggp"><h3 class="svelte-9d4ggp">Project Info</h3> <div class="info-grid svelte-9d4ggp"><div class="info-item svelte-9d4ggp"><span class="info-label svelte-9d4ggp">Embedded Modules</span> <span class="info-value svelte-9d4ggp"> </span></div> <div class="info-item svelte-9d4ggp"><span class="info-label svelte-9d4ggp">External Modules</span> <span class="info-value svelte-9d4ggp"> </span></div></div></section></div> <div class="modal-footer svelte-9d4ggp"><button class="cancel-button svelte-9d4ggp">Cancel</button> <button class="save-button svelte-9d4ggp">Save Changes</button></div></div></div>`);function I(r,h){s(h,!1);let E=te(h,`open`,12,!1),M=te(h,`graph`,12,void 0),F=k(),I=y([]),L=y(``),R=y(``),z=y(!1),B=y(``),V=y(``),H=y(``),U=y(``),W=y(``),G=y(`{}`),K=y(`{}`),q=y(``),J=y([]),Y=y(!1),X=y(!1);function Z(){E(!1),F(`close`)}async function ye(){O(B,``);let e,t;try{if(e=JSON.parse(c(G)||`{}`),t=JSON.parse(c(K)||`{}`),c(X)){let n=await P({name:c(W).trim(),commands:e,settings:t,credentials:c(q).split(/\r?\n|,/).map(e=>e.trim()).filter(Boolean)});O(J,n.requiredCredentials)}}catch(e){O(B,e instanceof Error?e.message:String(e));return}M()&&(M(M().project.name=c(V).trim(),!0),M(M().project.description=c(H).trim(),!0),M(M().project.author=c(U).trim(),!0),M(M().project.packages=[...c(I)],!0),c(I).forEach(e=>{M().moduleResolver.addProjectPackage(e)})),F(`save`,{packages:[...c(I)],graphName:c(V).trim(),projectName:c(W).trim(),missingCredentials:c(J).filter(e=>!e.set).map(e=>e.name)}),Z()}function be(){if(O(B,``),!c(L).trim()){O(B,`Path is required`);return}if(!c(R).trim()){O(B,`Alias is required`);return}if(!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(c(R))){O(B,`Alias must start with a letter and contain only letters, numbers, and underscores`);return}if(c(I).some(e=>e.alias===c(R))){O(B,`Alias "${c(R)}" already exists`);return}O(I,[...c(I),{path:c(L).trim(),alias:c(R).trim()}]),O(L,``),O(R,``),O(z,!1)}function xe(e){O(I,c(I).filter((t,n)=>n!==e))}function Q(e){e.key===`Escape`&&(c(z)?O(z,!1):Z())}function $(e){let t=e.replace(/\\/g,`/`).split(`/`).filter(Boolean);return(t[t.length-1]||`mypackage`).replace(/[^a-zA-Z0-9]/g,``).toLowerCase()||`mypackage`}T(()=>(p(E()),p(M())),()=>{E()&&M()&&(O(I,[...M().project.packages]),O(z,!1),O(B,``),O(L,``),O(R,``))}),T(()=>p(E()),()=>{E()||O(Y,!1)}),T(()=>(p(E()),p(M()),c(Y),N),()=>{E()&&M()&&!c(Y)&&(O(Y,!0),O(V,M().project.name??``),O(H,M().project.description??``),O(U,M().project.author??``),N().then(e=>{O(X,!0),O(W,e.manifest.name),O(G,JSON.stringify(e.manifest.commands,null,2)),O(K,JSON.stringify(e.manifest.settings,null,2)),O(q,e.manifest.credentials.join(`
2
- `)),O(J,e.requiredCredentials)}).catch(()=>{O(X,!1)}))}),T(()=>(c(L),c(R)),()=>{c(L)&&!c(R)&&O(R,$(c(L)))}),ne(),C();var Se=d();f(`keydown`,g,Q);var Ce=re(Se),we=n=>{var r=ve(),s=D(r),d=D(s),h=D(d),g=D(h);ie(g,{size:20}),e(),S(h);var y=w(h,2),te=D(y);oe(te,{size:20}),S(y),S(d);var C=w(d,2),T=D(C),E=w(D(T),2),ne=w(D(E));_(ne),S(E);var k=w(E,2),N=w(D(k));_(N),S(k);var P=w(k,2),F=w(D(P));_(F),S(P);var Y=w(P,2),X=w(D(Y));_(X),S(Y),S(T);var Q=w(T,2),$=w(D(Q),2),Se=w(D($));_(Se),S($);var Ce=w($,2),we=w(D(Ce));m(we),S(Ce);var Te=w(Ce,2),Ee=w(D(Te));m(Ee),S(Te);var De=w(Te,2),Oe=w(D(De));m(Oe),S(De);var ke=w(De,2),Ae=t=>{var n=de(),r=D(n);i(r,1,()=>c(J),a,(e,t)=>{var n=ue();let r;var i=v(n);x(()=>{r=o(n,1,`svelte-9d4ggp`,null,r,{set:c(t).set}),u(i,`${c(t),b(()=>c(t).name)??``}: ${c(t),b(()=>c(t).set?`set`:`not set`)??``}`)}),l(e,n)}),e(2),S(n),l(t,n)};j(ke,e=>{c(J),b(()=>c(J).length)&&e(Ae)}),S(Q);var je=w(Q,2),Me=w(D(je),4),Ne=t=>{var n=fe(),r=D(n);ae(r,{size:32});var i=w(r,4),a=D(i);se(a,{size:16}),e(),S(i),S(n),f(`click`,i,()=>O(z,!0)),l(t,n)},Pe=t=>{var n=he(),r=re(n);i(r,5,()=>c(I),a,(e,t,n)=>{var r=pe(),i=D(r),a=D(i),o=v(a,!0),s=w(a,2),d=v(s,!0);S(i);var p=w(i,2);le(D(p),{size:16}),S(p),S(r),x(()=>{u(o,(c(t),b(()=>c(t).alias))),u(d,(c(t),b(()=>c(t).path)))}),f(`click`,p,()=>xe(n)),l(e,r)}),S(r);var o=w(r,2),s=t=>{var n=me(),r=D(n);se(r,{size:16}),e(),S(n),f(`click`,n,()=>O(z,!0)),l(t,n)};j(o,e=>{c(z)||e(s)}),l(t,n)};j(Me,e=>{c(I),c(z),b(()=>c(I).length===0&&!c(z))?e(Ne):e(Pe,-1)});var Fe=w(Me,2),Ie=e=>{var t=_e(),n=D(t),r=w(D(n),2),i=D(r);_(i);var a=w(i,2),o=D(a);ae(o,{size:16}),S(a),S(r),S(n);var s=w(n,2),d=w(D(s),2);_(d),S(s);var p=w(s,2),m=e=>{var t=ge(),n=D(t);ce(n,{size:14});var r=w(n);S(t),x(()=>u(r,` ${c(B)??``}`)),l(e,t)};j(p,e=>{c(B)&&e(m)});var h=w(p,2),g=D(h),v=w(g,2);S(h),S(t),A(i,()=>c(L),e=>O(L,e)),A(d,()=>c(R),e=>O(R,e)),f(`click`,g,()=>O(z,!1)),f(`click`,v,be),l(e,t)};j(Fe,e=>{c(z)&&e(Ie)}),S(je);var Le=w(je,2),Re=w(D(Le),2),ze=D(Re),Be=w(D(ze),2),Ve=v(Be,!0);S(ze);var He=w(ze,2),Ue=w(D(He),2),We=v(Ue,!0);S(He),S(Re),S(Le),S(C);var Ge=w(C,2),Ke=D(Ge),qe=w(Ke,2);S(Ge),S(s),S(r),x((e,n)=>{t(X,(p(M()),b(()=>M()?.created??``))),u(Ve,e),u(We,n)},[()=>(p(M()),b(()=>M()?Object.keys(M().moduleResolver.exportConfig().embeddedModules).length:0)),()=>(p(M()),b(()=>M()?Object.keys(M().moduleResolver.exportConfig().externalModules).length:0))]),f(`click`,y,Z),A(ne,()=>c(V),e=>O(V,e)),A(N,()=>c(H),e=>O(H,e)),A(F,()=>c(U),e=>O(U,e)),A(Se,()=>c(W),e=>O(W,e)),A(we,()=>c(G),e=>O(G,e)),A(Ee,()=>c(K),e=>O(K,e)),A(Oe,()=>c(q),e=>O(q,e)),f(`click`,Ke,Z),f(`click`,qe,ye),f(`click`,r,ee(Z)),l(n,r)};j(Ce,e=>{E()&&e(we)}),l(r,Se),n()}export{I as default};
@@ -1 +0,0 @@
1
- import{N as e,_ as t,d as n,f as r,g as i,h as a,l as o,u as s}from"./index-5ZtDAuy2.js";e([a,o,s,n,t,i,r]);
@@ -1 +0,0 @@
1
- import{M as e,N as t,c as n,w as r}from"./index-5ZtDAuy2.js";t(n,{assets:e});export{r as geoLibrary};