undercity 1.0.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 (382) hide show
  1. package/AGENTS.md +26 -0
  2. package/README.md +58 -0
  3. package/actions/AGENTS.md +41 -0
  4. package/actions/_shared/container.js +16 -0
  5. package/actions/auth/ask-login/action.json +15 -0
  6. package/actions/auth/ask-signup/action.json +14 -0
  7. package/actions/display/clear/action.json +18 -0
  8. package/actions/display/clear/action.test.js +32 -0
  9. package/actions/display/markdown/action.json +12 -0
  10. package/actions/display/markdown/action.test.js +32 -0
  11. package/actions/display/rawHtml/action.json +24 -0
  12. package/actions/display/rawHtml/action.test.js +32 -0
  13. package/actions/display/safeHtml/action.json +24 -0
  14. package/actions/display/safeHtml/action.test.js +32 -0
  15. package/actions/display/text/action.js +9 -0
  16. package/actions/display/text/action.json +12 -0
  17. package/actions/display/text/action.test.js +40 -0
  18. package/actions/display/value/action.json +24 -0
  19. package/actions/display/value/action.test.js +32 -0
  20. package/actions/dom/addClass/action.json +23 -0
  21. package/actions/dom/addClass/action.test.js +32 -0
  22. package/actions/dom/focus/action.json +17 -0
  23. package/actions/dom/focus/action.test.js +32 -0
  24. package/actions/dom/hide/action.json +18 -0
  25. package/actions/dom/hide/action.test.js +32 -0
  26. package/actions/dom/removeClass/action.json +22 -0
  27. package/actions/dom/removeClass/action.test.js +32 -0
  28. package/actions/dom/scroll/action.json +29 -0
  29. package/actions/dom/scroll/action.test.js +32 -0
  30. package/actions/dom/setAttr/action.json +29 -0
  31. package/actions/dom/setAttr/action.test.js +32 -0
  32. package/actions/dom/setHtml/action.json +22 -0
  33. package/actions/dom/setHtml/action.test.js +32 -0
  34. package/actions/dom/setStyle/action.json +29 -0
  35. package/actions/dom/setStyle/action.test.js +32 -0
  36. package/actions/dom/setText/action.json +24 -0
  37. package/actions/dom/setText/action.test.js +32 -0
  38. package/actions/dom/show/action.json +18 -0
  39. package/actions/dom/show/action.test.js +32 -0
  40. package/actions/dom/toggle/action.json +17 -0
  41. package/actions/dom/toggle/action.test.js +32 -0
  42. package/actions/dom/toggleClass/action.json +22 -0
  43. package/actions/dom/toggleClass/action.test.js +32 -0
  44. package/actions/event/emit/action.json +24 -0
  45. package/actions/event/emit/action.test.js +32 -0
  46. package/actions/event/on/action.json +23 -0
  47. package/actions/event/on/action.test.js +32 -0
  48. package/actions/event/waitFor/action.json +28 -0
  49. package/actions/event/waitFor/action.test.js +32 -0
  50. package/actions/forms/bindField/action.js +27 -0
  51. package/actions/forms/bindField/action.json +24 -0
  52. package/actions/forms/bindField/action.test.js +20 -0
  53. package/actions/forms/check/action.json +22 -0
  54. package/actions/forms/check/action.test.js +32 -0
  55. package/actions/forms/clearErrors/action.json +11 -0
  56. package/actions/forms/clearErrors/action.test.js +35 -0
  57. package/actions/forms/clearField/action.json +17 -0
  58. package/actions/forms/clearField/action.test.js +32 -0
  59. package/actions/forms/getField/action.json +24 -0
  60. package/actions/forms/getField/action.test.js +32 -0
  61. package/actions/forms/getRange/action.json +22 -0
  62. package/actions/forms/getRange/action.test.js +32 -0
  63. package/actions/forms/getSelect/action.json +22 -0
  64. package/actions/forms/getSelect/action.test.js +32 -0
  65. package/actions/forms/index.js +140 -0
  66. package/actions/forms/serialize/action.json +24 -0
  67. package/actions/forms/serialize/action.test.js +32 -0
  68. package/actions/forms/setCheck/action.json +23 -0
  69. package/actions/forms/setCheck/action.test.js +32 -0
  70. package/actions/forms/setError/action.json +22 -0
  71. package/actions/forms/setError/action.test.js +32 -0
  72. package/actions/forms/setField/action.js +14 -0
  73. package/actions/forms/setField/action.json +24 -0
  74. package/actions/forms/setField/action.test.js +32 -0
  75. package/actions/forms/submit/action.json +18 -0
  76. package/actions/forms/submit/action.test.js +32 -0
  77. package/actions/forms/validate/action.json +24 -0
  78. package/actions/forms/validate/action.test.js +32 -0
  79. package/actions/http/delete/action.json +22 -0
  80. package/actions/http/delete/action.test.js +32 -0
  81. package/actions/http/get/action.json +24 -0
  82. package/actions/http/get/action.test.js +32 -0
  83. package/actions/http/post/action.json +30 -0
  84. package/actions/http/post/action.test.js +32 -0
  85. package/actions/http/put/action.json +27 -0
  86. package/actions/http/put/action.test.js +32 -0
  87. package/actions/http/upload/action.json +35 -0
  88. package/actions/http/upload/action.test.js +32 -0
  89. package/actions/index.js +306 -0
  90. package/actions/index.json +5 -0
  91. package/actions/input/askChoice/action.json +29 -0
  92. package/actions/input/askChoice/action.test.js +32 -0
  93. package/actions/input/askConfirm/action.json +24 -0
  94. package/actions/input/askConfirm/action.test.js +32 -0
  95. package/actions/input/askDate/action.json +24 -0
  96. package/actions/input/askDate/action.test.js +32 -0
  97. package/actions/input/askEmail/action.json +24 -0
  98. package/actions/input/askEmail/action.test.js +32 -0
  99. package/actions/input/askNumber/action.json +35 -0
  100. package/actions/input/askNumber/action.test.js +32 -0
  101. package/actions/input/askPassword/action.json +24 -0
  102. package/actions/input/askPassword/action.test.js +32 -0
  103. package/actions/input/askText/action.json +36 -0
  104. package/actions/input/askText/action.test.js +32 -0
  105. package/actions/logic/delay/action.json +18 -0
  106. package/actions/logic/delay/action.test.js +32 -0
  107. package/actions/logic/if/action.json +28 -0
  108. package/actions/logic/if/action.test.js +32 -0
  109. package/actions/logic/log/action.json +18 -0
  110. package/actions/logic/log/action.test.js +32 -0
  111. package/actions/logic/random/action.json +36 -0
  112. package/actions/logic/random/action.test.js +32 -0
  113. package/actions/logic/transform/action.json +24 -0
  114. package/actions/logic/transform/action.test.js +32 -0
  115. package/actions/media/askAudioUpload/action.json +30 -0
  116. package/actions/media/askAudioUpload/action.test.js +32 -0
  117. package/actions/media/askFileUpload/action.json +36 -0
  118. package/actions/media/askFileUpload/action.test.js +32 -0
  119. package/actions/media/askImageUpload/action.json +37 -0
  120. package/actions/media/askImageUpload/action.test.js +32 -0
  121. package/actions/media/askVideoUpload/action.js +74 -0
  122. package/actions/media/askVideoUpload/action.json +44 -0
  123. package/actions/media/askVideoUpload/action.test.js +51 -0
  124. package/actions/media/captureWebcam/action.json +24 -0
  125. package/actions/media/captureWebcam/action.test.js +32 -0
  126. package/actions/nav/back/action.json +11 -0
  127. package/actions/nav/back/action.test.js +35 -0
  128. package/actions/nav/goto/action.json +18 -0
  129. package/actions/nav/goto/action.test.js +32 -0
  130. package/actions/nav/redirect/action.json +28 -0
  131. package/actions/nav/redirect/action.test.js +32 -0
  132. package/actions/nav/reload/action.json +11 -0
  133. package/actions/nav/reload/action.test.js +35 -0
  134. package/actions/nav/reset/action.json +11 -0
  135. package/actions/nav/reset/action.test.js +35 -0
  136. package/actions/render/alert/action.js +12 -0
  137. package/actions/render/alert/action.json +36 -0
  138. package/actions/render/alert/action.test.js +32 -0
  139. package/actions/render/button/action.js +15 -0
  140. package/actions/render/button/action.json +44 -0
  141. package/actions/render/button/action.test.js +37 -0
  142. package/actions/render/clear/action.js +7 -0
  143. package/actions/render/clear/action.json +11 -0
  144. package/actions/render/clear/action.test.js +35 -0
  145. package/actions/render/divider/action.js +8 -0
  146. package/actions/render/divider/action.json +11 -0
  147. package/actions/render/divider/action.test.js +35 -0
  148. package/actions/render/field/action.js +17 -0
  149. package/actions/render/field/action.json +59 -0
  150. package/actions/render/field/action.test.js +57 -0
  151. package/actions/render/link/action.js +20 -0
  152. package/actions/render/link/action.json +30 -0
  153. package/actions/render/link/action.test.js +32 -0
  154. package/actions/render/markdown/action.json +18 -0
  155. package/actions/render/markdown/action.test.js +32 -0
  156. package/actions/render/paragraph/action.js +9 -0
  157. package/actions/render/paragraph/action.json +32 -0
  158. package/actions/render/paragraph/action.test.js +32 -0
  159. package/actions/render/section/action.js +10 -0
  160. package/actions/render/section/action.json +18 -0
  161. package/actions/render/section/action.test.js +32 -0
  162. package/actions/render/subtitle/action.js +9 -0
  163. package/actions/render/subtitle/action.json +18 -0
  164. package/actions/render/subtitle/action.test.js +32 -0
  165. package/actions/render/title/action.js +9 -0
  166. package/actions/render/title/action.json +30 -0
  167. package/actions/render/title/action.test.js +44 -0
  168. package/actions/session/clear/action.json +11 -0
  169. package/actions/session/clear/action.test.js +35 -0
  170. package/actions/session/load/action.json +22 -0
  171. package/actions/session/load/action.test.js +32 -0
  172. package/actions/session/local/action.json +22 -0
  173. package/actions/session/local/action.test.js +32 -0
  174. package/actions/session/save/action.json +22 -0
  175. package/actions/session/save/action.test.js +32 -0
  176. package/actions/ui/accordion/action.json +23 -0
  177. package/actions/ui/accordion/action.test.js +32 -0
  178. package/actions/ui/badge/action.json +22 -0
  179. package/actions/ui/badge/action.test.js +32 -0
  180. package/actions/ui/collapse/action.json +23 -0
  181. package/actions/ui/collapse/action.test.js +32 -0
  182. package/actions/ui/hideModal/action.json +17 -0
  183. package/actions/ui/hideModal/action.test.js +32 -0
  184. package/actions/ui/loading/action.json +18 -0
  185. package/actions/ui/loading/action.test.js +32 -0
  186. package/actions/ui/modal/action.json +18 -0
  187. package/actions/ui/modal/action.test.js +32 -0
  188. package/actions/ui/progress/action.json +24 -0
  189. package/actions/ui/progress/action.test.js +32 -0
  190. package/actions/ui/toast/action.json +29 -0
  191. package/actions/ui/toast/action.test.js +32 -0
  192. package/actions/ui/tooltip/action.json +17 -0
  193. package/actions/ui/tooltip/action.test.js +32 -0
  194. package/actions/user/carry/action.json +25 -0
  195. package/actions/user/carry/action.test.js +32 -0
  196. package/actions/user/check/action.json +24 -0
  197. package/actions/user/check/action.test.js +32 -0
  198. package/actions/user/clear/action.json +11 -0
  199. package/actions/user/clear/action.test.js +35 -0
  200. package/actions/user/delete/action.json +17 -0
  201. package/actions/user/delete/action.test.js +32 -0
  202. package/actions/user/dump/action.json +11 -0
  203. package/actions/user/dump/action.test.js +35 -0
  204. package/actions/user/get/action.json +24 -0
  205. package/actions/user/get/action.test.js +32 -0
  206. package/actions/user/merge/action.json +18 -0
  207. package/actions/user/merge/action.test.js +32 -0
  208. package/actions/user/set/action.json +24 -0
  209. package/actions/user/set/action.test.js +32 -0
  210. package/generator/base/css/bootstrap.min.css +6 -0
  211. package/generator/base/icons/app-indicator.svg +4 -0
  212. package/generator/base/icons/backpack.svg +4 -0
  213. package/generator/base/icons/broadcast.svg +3 -0
  214. package/generator/base/icons/bullseye.svg +6 -0
  215. package/generator/base/icons/chat-dots.svg +4 -0
  216. package/generator/base/icons/check-circle.svg +4 -0
  217. package/generator/base/icons/clipboard-check.svg +5 -0
  218. package/generator/base/icons/clipboard.svg +4 -0
  219. package/generator/base/icons/copy.svg +3 -0
  220. package/generator/base/icons/cursor.svg +3 -0
  221. package/generator/base/icons/diamond.svg +3 -0
  222. package/generator/base/icons/exclamation-triangle.svg +4 -0
  223. package/generator/base/icons/film.svg +3 -0
  224. package/generator/base/icons/floppy.svg +4 -0
  225. package/generator/base/icons/gear-wide-connected.svg +3 -0
  226. package/generator/base/icons/gear.svg +4 -0
  227. package/generator/base/icons/globe.svg +3 -0
  228. package/generator/base/icons/image.svg +4 -0
  229. package/generator/base/icons/layout-text-window.svg +4 -0
  230. package/generator/base/icons/lightning-charge.svg +3 -0
  231. package/generator/base/icons/magic.svg +3 -0
  232. package/generator/base/icons/pencil-square.svg +4 -0
  233. package/generator/base/icons/record-circle.svg +4 -0
  234. package/generator/base/icons/robot.svg +4 -0
  235. package/generator/base/icons/shield-check.svg +4 -0
  236. package/generator/base/icons/shield-lock.svg +4 -0
  237. package/generator/base/icons/signpost.svg +3 -0
  238. package/generator/base/icons/stars.svg +3 -0
  239. package/generator/base/icons/type.svg +3 -0
  240. package/generator/base/js/bootstrap.bundle.min.js +7 -0
  241. package/package.json +14 -0
  242. package/packages/undercity-http-server/index.js +249 -0
  243. package/packages/undercity-http-server/package.json +10 -0
  244. package/packages/undercity-parser/index.js +323 -0
  245. package/packages/undercity-parser/lexer.js +128 -0
  246. package/packages/undercity-parser/package.json +11 -0
  247. package/plugins/forms.js +397 -0
  248. package/plugins/index.js +83 -0
  249. package/plugins/multipage.js +165 -0
  250. package/plugins/wizard.js +239 -0
  251. package/projects/asd/project.json +1031 -0
  252. package/projects/test-1/project.json +335 -0
  253. package/projects/test-a/project.json +456 -0
  254. package/public/icons/arrows-angle-expand.svg +3 -0
  255. package/public/icons/arrows-fullscreen.svg +3 -0
  256. package/public/icons/bezier2.svg +3 -0
  257. package/public/icons/bootstrap/app-indicator.svg +4 -0
  258. package/public/icons/bootstrap/arrow-clockwise.svg +4 -0
  259. package/public/icons/bootstrap/arrow-counterclockwise.svg +4 -0
  260. package/public/icons/bootstrap/arrow-left.svg +3 -0
  261. package/public/icons/bootstrap/arrows-angle-expand.svg +3 -0
  262. package/public/icons/bootstrap/arrows-fullscreen.svg +3 -0
  263. package/public/icons/bootstrap/backpack.svg +4 -0
  264. package/public/icons/bootstrap/bezier2.svg +3 -0
  265. package/public/icons/bootstrap/bookmark-check.svg +4 -0
  266. package/public/icons/bootstrap/bookmark-plus.svg +4 -0
  267. package/public/icons/bootstrap/box-arrow-right.svg +4 -0
  268. package/public/icons/bootstrap/box-arrow-up.svg +4 -0
  269. package/public/icons/bootstrap/broadcast.svg +3 -0
  270. package/public/icons/bootstrap/bullseye.svg +6 -0
  271. package/public/icons/bootstrap/chat-dots.svg +4 -0
  272. package/public/icons/bootstrap/check-circle.svg +4 -0
  273. package/public/icons/bootstrap/check2.svg +3 -0
  274. package/public/icons/bootstrap/clipboard-check.svg +5 -0
  275. package/public/icons/bootstrap/clipboard.svg +4 -0
  276. package/public/icons/bootstrap/clock-history.svg +5 -0
  277. package/public/icons/bootstrap/command.svg +3 -0
  278. package/public/icons/bootstrap/copy.svg +3 -0
  279. package/public/icons/bootstrap/cursor.svg +3 -0
  280. package/public/icons/bootstrap/diagram-3.svg +3 -0
  281. package/public/icons/bootstrap/diamond.svg +3 -0
  282. package/public/icons/bootstrap/exclamation-triangle.svg +4 -0
  283. package/public/icons/bootstrap/eye.svg +4 -0
  284. package/public/icons/bootstrap/file-earmark-plus.svg +4 -0
  285. package/public/icons/bootstrap/film.svg +3 -0
  286. package/public/icons/bootstrap/floppy.svg +4 -0
  287. package/public/icons/bootstrap/folder2-open.svg +3 -0
  288. package/public/icons/bootstrap/gear-wide-connected.svg +3 -0
  289. package/public/icons/bootstrap/gear.svg +4 -0
  290. package/public/icons/bootstrap/globe.svg +3 -0
  291. package/public/icons/bootstrap/grid-3x3-gap.svg +3 -0
  292. package/public/icons/bootstrap/house-door.svg +3 -0
  293. package/public/icons/bootstrap/image.svg +4 -0
  294. package/public/icons/bootstrap/layout-text-window.svg +4 -0
  295. package/public/icons/bootstrap/lightning-charge.svg +3 -0
  296. package/public/icons/bootstrap/magic.svg +3 -0
  297. package/public/icons/bootstrap/pencil-square.svg +4 -0
  298. package/public/icons/bootstrap/pencil.svg +3 -0
  299. package/public/icons/bootstrap/play.svg +3 -0
  300. package/public/icons/bootstrap/plus-circle.svg +4 -0
  301. package/public/icons/bootstrap/plus-lg.svg +3 -0
  302. package/public/icons/bootstrap/record-circle.svg +4 -0
  303. package/public/icons/bootstrap/robot.svg +4 -0
  304. package/public/icons/bootstrap/save.svg +3 -0
  305. package/public/icons/bootstrap/scissors.svg +3 -0
  306. package/public/icons/bootstrap/shield-check.svg +4 -0
  307. package/public/icons/bootstrap/shield-lock.svg +4 -0
  308. package/public/icons/bootstrap/signpost.svg +3 -0
  309. package/public/icons/bootstrap/stars.svg +3 -0
  310. package/public/icons/bootstrap/stop-circle.svg +4 -0
  311. package/public/icons/bootstrap/terminal.svg +4 -0
  312. package/public/icons/bootstrap/trash3.svg +3 -0
  313. package/public/icons/bootstrap/type.svg +3 -0
  314. package/public/icons/bootstrap/x-circle.svg +4 -0
  315. package/public/icons/bootstrap/x-lg.svg +3 -0
  316. package/public/icons/bootstrap/zoom-in.svg +5 -0
  317. package/public/icons/bootstrap/zoom-out.svg +5 -0
  318. package/public/icons/bullseye.svg +6 -0
  319. package/public/icons/check2.svg +3 -0
  320. package/public/icons/cursor.svg +3 -0
  321. package/public/icons/diamond.svg +3 -0
  322. package/public/icons/eye.svg +4 -0
  323. package/public/icons/file-earmark-plus.svg +4 -0
  324. package/public/icons/floppy.svg +4 -0
  325. package/public/icons/gear.svg +4 -0
  326. package/public/icons/lightning-charge.svg +3 -0
  327. package/public/icons/pencil.svg +3 -0
  328. package/public/icons/play.svg +3 -0
  329. package/public/icons/plus-circle.svg +4 -0
  330. package/public/icons/record-circle.svg +4 -0
  331. package/public/icons/robot.svg +4 -0
  332. package/public/icons/save.svg +3 -0
  333. package/public/icons/stop-circle.svg +4 -0
  334. package/public/icons/terminal.svg +4 -0
  335. package/public/icons/trash3.svg +3 -0
  336. package/public/icons/x-circle.svg +4 -0
  337. package/public/icons/zoom-in.svg +5 -0
  338. package/public/icons/zoom-out.svg +5 -0
  339. package/public/index.html +424 -0
  340. package/public/testbench.html +899 -0
  341. package/scripts/extract-actions.js +128 -0
  342. package/server.js +11 -0
  343. package/src/emitter.js +48 -0
  344. package/src/generator/css.js +135 -0
  345. package/src/generator/index.js +122 -0
  346. package/src/generator/md-renderer-src.js +77 -0
  347. package/src/generator/page.js +300 -0
  348. package/src/generator/runtime.js +1632 -0
  349. package/src/generator/templates.js +508 -0
  350. package/src/ide/action-library.js +856 -0
  351. package/src/ide/af-icons.js +127 -0
  352. package/src/ide/app.js +1375 -0
  353. package/src/ide/command-line/commands.js +242 -0
  354. package/src/ide/command-line/index.js +329 -0
  355. package/src/ide/command-line/parser.js +21 -0
  356. package/src/ide/css/ide.css +1501 -0
  357. package/src/ide/graph.js +282 -0
  358. package/src/ide/history.js +46 -0
  359. package/src/ide/map-builder.js +583 -0
  360. package/src/ide/project-api.js +39 -0
  361. package/src/ide/savant-chat.js +513 -0
  362. package/src/ide/savant.js +1287 -0
  363. package/src/ide/thing-library.js +89 -0
  364. package/src/ide/undercity-map.js +978 -0
  365. package/src/lib/icons.js +72 -0
  366. package/src/lib/scope.js +88 -0
  367. package/src/lib/signal.js +155 -0
  368. package/src/lib/state-machine.js +113 -0
  369. package/src/server/index.js +96 -0
  370. package/src/server/routes/actions.js +144 -0
  371. package/src/server/routes/ai.js +176 -0
  372. package/src/server/routes/generate.js +54 -0
  373. package/src/server/routes/projects.js +106 -0
  374. package/src/server/routes/reset.js +30 -0
  375. package/src/server/routes/submit.js +30 -0
  376. package/src/server/routes/templates.js +139 -0
  377. package/src/server/routes/things.js +33 -0
  378. package/templates/auth-flow.json +335 -0
  379. package/templates/blank.json +39 -0
  380. package/things/auth-server/thing.json +17 -0
  381. package/things/persona-live/thing.json +20 -0
  382. package/things/workflow/thing.json +15 -0
@@ -0,0 +1,335 @@
1
+ {
2
+ "id": "auth-flow",
3
+ "name": "Authentication Flow",
4
+ "description": "A complete sign in · forgot password · sign up flow with diamond-routed logic.",
5
+ "icon": "shield-lock",
6
+ "category": "authentication",
7
+ "preview": "Lobby → Login / Signup / Forgot → Auth API checks → Dashboard",
8
+ "graph": {
9
+ "nodes": [
10
+ {
11
+ "id": "lobby",
12
+ "type": "room",
13
+ "label": "Welcome",
14
+ "x": -240,
15
+ "y": 280,
16
+ "payload": {
17
+ "onEnter": [],
18
+ "onExit": [],
19
+ "onBack": [],
20
+ "onReset": [{ "action": "inventory.clear", "params": {} }],
21
+ "onUnload": []
22
+ },
23
+ "routes": [],
24
+ "template": "lobby",
25
+ "meta": {
26
+ "isEntry": true,
27
+ "appName": "MyApp",
28
+ "tagline": "Sign in to your account, create a new one, or reset your password.",
29
+ "icon": "shield-lock"
30
+ }
31
+ },
32
+ {
33
+ "id": "login",
34
+ "type": "room",
35
+ "label": "Login",
36
+ "x": 80,
37
+ "y": 280,
38
+ "payload": {
39
+ "onEnter": [
40
+ { "action": "render.clear", "params": {} },
41
+ { "action": "render.title", "params": { "text": "Sign In", "size": "h2" } },
42
+ { "action": "render.subtitle", "params": { "text": "Welcome back. Enter your credentials." } },
43
+ { "action": "render.field", "params": { "name": "email", "label": "Email", "type": "email", "placeholder": "you@example.com", "autocomplete": "email", "required": true } },
44
+ { "action": "render.field", "params": { "name": "password", "label": "Password", "type": "password", "placeholder": "••••••••", "autocomplete": "current-password", "required": true } },
45
+ { "action": "render.alert", "params": { "id": "login-alert", "type": "danger" } },
46
+ { "action": "render.button", "params": { "label": "Sign In", "target": "auth-check", "variant": "primary", "full": true } },
47
+ { "action": "render.link", "params": { "text": "Forgot password?", "target": "forgot", "prefix": "" } },
48
+ { "action": "render.link", "params": { "text": "Create an account", "target": "signup", "prefix": "No account?" } },
49
+ { "action": "form.clearErrors", "params": {} }
50
+ ],
51
+ "onExit": [
52
+ { "action": "form.getField", "params": { "name": "email", "into": "email" } },
53
+ { "action": "form.getField", "params": { "name": "password", "into": "password" } }
54
+ ],
55
+ "onBack": [],
56
+ "onReset": [{ "action": "inventory.clear", "params": {} }],
57
+ "onUnload": []
58
+ },
59
+ "routes": [],
60
+ "template": "blank",
61
+ "meta": { "description": "Collects email + password. Feeds into Auth Check diamond.", "isEntry": false }
62
+ },
63
+ {
64
+ "id": "auth-check",
65
+ "type": "diamond",
66
+ "label": "Auth Check",
67
+ "x": 520,
68
+ "y": 160,
69
+ "payload": {
70
+ "onEnter": [
71
+ { "action": "ui.loading", "params": { "show": true } },
72
+ { "action": "http.post", "params": { "url": "/api/auth/login", "body": "{ email, password }", "into": "authResult" } },
73
+ { "action": "user.merge", "params": { "from": "authResult" } },
74
+ { "action": "ui.loading", "params": { "show": false } }
75
+ ],
76
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
77
+ },
78
+ "routes": [
79
+ { "condition": "inventory.authenticated === true", "target": "dashboard", "label": "Authenticated" },
80
+ { "condition": "inventory.authError === 'wrong-password'", "target": "login-error", "label": "Wrong password" },
81
+ { "condition": "inventory.authError === 'not-found'", "target": "signup", "label": "User not found — prompt signup" },
82
+ { "condition": "true", "target": "login-error", "label": "Default error" }
83
+ ],
84
+ "template": null,
85
+ "meta": { "isEntry": false }
86
+ },
87
+ {
88
+ "id": "login-error",
89
+ "type": "room",
90
+ "label": "Login Error",
91
+ "x": 480,
92
+ "y": 400,
93
+ "payload": {
94
+ "onEnter": [
95
+ { "action": "render.clear", "params": {} },
96
+ { "action": "render.title", "params": { "text": "Sign In Failed", "size": "h2" } },
97
+ { "action": "render.alert", "params": { "id": "err-msg", "type": "danger", "text": "Incorrect email or password. Please try again." } },
98
+ { "action": "render.button", "params": { "label": "Try Again", "target": "login", "variant": "primary", "full": true } },
99
+ { "action": "render.link", "params": { "text": "Forgot password?", "target": "forgot", "prefix": "" } },
100
+ { "action": "render.link", "params": { "text": "Create an account", "target": "signup", "prefix": "No account?" } }
101
+ ],
102
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
103
+ },
104
+ "routes": [],
105
+ "template": "blank",
106
+ "meta": { "isEntry": false }
107
+ },
108
+ {
109
+ "id": "dashboard",
110
+ "type": "terminal",
111
+ "label": "Dashboard",
112
+ "x": 720,
113
+ "y": 200,
114
+ "payload": {
115
+ "onEnter": [
116
+ { "action": "ui.toast", "params": { "msg": "Welcome back!", "type": "success" } }
117
+ ],
118
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
119
+ },
120
+ "routes": [],
121
+ "template": "submit-review",
122
+ "meta": {
123
+ "reviewTitle": "Review & Submit",
124
+ "reviewMessage": "You are signed in. Please verify your details before submitting.",
125
+ "submitUrl": "/api/submit",
126
+ "submitLabel": "Submit",
127
+ "reviewFields": ["email", "firstName", "lastName"],
128
+ "isEntry": false
129
+ }
130
+ },
131
+ {
132
+ "id": "forgot",
133
+ "type": "room",
134
+ "label": "Forgot Password",
135
+ "x": 600,
136
+ "y": -40,
137
+ "payload": {
138
+ "onEnter": [
139
+ { "action": "render.clear", "params": {} },
140
+ { "action": "render.title", "params": { "text": "Forgot Password", "size": "h2" } },
141
+ { "action": "render.subtitle", "params": { "text": "We'll send a reset link to your inbox." } },
142
+ { "action": "render.field", "params": { "name": "email", "label": "Email Address", "type": "email", "placeholder": "you@example.com", "autocomplete": "email", "required": true } },
143
+ { "action": "render.alert", "params": { "id": "forgot-alert", "type": "info" } },
144
+ { "action": "render.button", "params": { "label": "Send Reset Link", "target": "reset-check", "variant": "primary", "full": true } },
145
+ { "action": "render.link", "params": { "text": "Back to Sign In", "target": "login", "prefix": "Remember it?" } },
146
+ { "action": "form.clearErrors", "params": {} }
147
+ ],
148
+ "onExit": [
149
+ { "action": "form.getField", "params": { "name": "email", "into": "email" } }
150
+ ],
151
+ "onBack": [], "onReset": [], "onUnload": []
152
+ },
153
+ "routes": [],
154
+ "template": "blank",
155
+ "meta": { "isEntry": false }
156
+ },
157
+ {
158
+ "id": "reset-check",
159
+ "type": "diamond",
160
+ "label": "Reset Check",
161
+ "x": 880,
162
+ "y": 280,
163
+ "payload": {
164
+ "onEnter": [
165
+ { "action": "ui.loading", "params": { "show": true } },
166
+ { "action": "http.post", "params": { "url": "/api/auth/forgot", "body": "{ email }", "into": "resetResult" } },
167
+ { "action": "user.merge","params": { "from": "resetResult" } },
168
+ { "action": "ui.loading", "params": { "show": false } }
169
+ ],
170
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
171
+ },
172
+ "routes": [
173
+ { "condition": "inventory.resetSent === true", "target": "reset-sent", "label": "Email sent" },
174
+ { "condition": "inventory.authError === 'not-found'", "target": "reset-nfe", "label": "Email not found" },
175
+ { "condition": "true", "target": "reset-nfe", "label": "Default error" }
176
+ ],
177
+ "template": null,
178
+ "meta": { "isEntry": false }
179
+ },
180
+ {
181
+ "id": "reset-sent",
182
+ "type": "terminal",
183
+ "label": "Reset Email Sent",
184
+ "x": 1200,
185
+ "y": 280,
186
+ "payload": {
187
+ "onEnter": [],
188
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
189
+ },
190
+ "routes": [],
191
+ "template": "success",
192
+ "meta": {
193
+ "message": "Check your inbox — a password reset link is on its way.",
194
+ "nextLabel": "Back to Sign In",
195
+ "nextHref": "login.html",
196
+ "isEntry": false
197
+ }
198
+ },
199
+ {
200
+ "id": "reset-nfe",
201
+ "type": "room",
202
+ "label": "Reset — Not Found",
203
+ "x": 960,
204
+ "y": 440,
205
+ "payload": {
206
+ "onEnter": [
207
+ { "action": "render.clear", "params": {} },
208
+ { "action": "render.title", "params": { "text": "Email Not Found", "size": "h2" } },
209
+ { "action": "render.alert", "params": { "id": "nfe-msg", "type": "warning", "text": "We don't have an account for that email address." } },
210
+ { "action": "render.button", "params": { "label": "Try a different email", "target": "forgot", "variant": "outline-secondary", "full": true } },
211
+ { "action": "render.link", "params": { "text": "Create an account", "target": "signup", "prefix": "New here?" } }
212
+ ],
213
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
214
+ },
215
+ "routes": [],
216
+ "template": "blank",
217
+ "meta": { "isEntry": false }
218
+ },
219
+ {
220
+ "id": "signup",
221
+ "type": "room",
222
+ "label": "Signup",
223
+ "x": 200,
224
+ "y": 480,
225
+ "payload": {
226
+ "onEnter": [
227
+ { "action": "render.clear", "params": {} },
228
+ { "action": "render.title", "params": { "text": "Create Account", "size": "h2" } },
229
+ { "action": "render.subtitle", "params": { "text": "Join us — it only takes a moment." } },
230
+ { "action": "render.field", "params": { "name": "firstName", "label": "First Name", "type": "text", "placeholder": "Jane", "autocomplete": "given-name", "required": true } },
231
+ { "action": "render.field", "params": { "name": "lastName", "label": "Last Name", "type": "text", "placeholder": "Doe", "autocomplete": "family-name", "required": true } },
232
+ { "action": "render.field", "params": { "name": "email", "label": "Email", "type": "email", "placeholder": "you@example.com", "autocomplete": "email", "required": true } },
233
+ { "action": "render.field", "params": { "name": "password", "label": "Password", "type": "password", "placeholder": "Min. 8 characters", "autocomplete": "new-password","required": true } },
234
+ { "action": "render.alert", "params": { "id": "signup-alert", "type": "danger" } },
235
+ { "action": "render.button", "params": { "label": "Create Account", "target": "register-check", "variant": "primary", "full": true } },
236
+ { "action": "render.link", "params": { "text": "Sign in instead", "target": "login", "prefix": "Already have one?" } },
237
+ { "action": "form.clearErrors", "params": {} }
238
+ ],
239
+ "onExit": [
240
+ { "action": "form.getField", "params": { "name": "firstName", "into": "firstName" } },
241
+ { "action": "form.getField", "params": { "name": "lastName", "into": "lastName" } },
242
+ { "action": "form.getField", "params": { "name": "email", "into": "email" } },
243
+ { "action": "form.getField", "params": { "name": "password", "into": "password" } }
244
+ ],
245
+ "onBack": [], "onReset": [], "onUnload": []
246
+ },
247
+ "routes": [],
248
+ "template": "blank",
249
+ "meta": { "isEntry": false }
250
+ },
251
+ {
252
+ "id": "register-check",
253
+ "type": "diamond",
254
+ "label": "Register Check",
255
+ "x": 720,
256
+ "y": 600,
257
+ "payload": {
258
+ "onEnter": [
259
+ { "action": "ui.loading", "params": { "show": true } },
260
+ { "action": "http.post", "params": { "url": "/api/auth/register", "body": "{ firstName, lastName, email, password }", "into": "registerResult" } },
261
+ { "action": "user.merge","params": { "from": "registerResult" } },
262
+ { "action": "ui.loading", "params": { "show": false } }
263
+ ],
264
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
265
+ },
266
+ "routes": [
267
+ { "condition": "inventory.registered === true", "target": "dashboard", "label": "Registration success" },
268
+ { "condition": "inventory.authError === 'email-exists'", "target": "signup-error","label": "Email already registered" },
269
+ { "condition": "true", "target": "signup-error","label": "Default error" }
270
+ ],
271
+ "template": null,
272
+ "meta": { "isEntry": false }
273
+ },
274
+ {
275
+ "id": "signup-error",
276
+ "type": "room",
277
+ "label": "Signup Error",
278
+ "x": 200,
279
+ "y": 640,
280
+ "payload": {
281
+ "onEnter": [
282
+ { "action": "render.clear", "params": {} },
283
+ { "action": "render.title", "params": { "text": "Registration Failed", "size": "h2" } },
284
+ { "action": "render.alert", "params": { "id": "reg-err", "type": "danger", "text": "This email address is already registered." } },
285
+ { "action": "render.button", "params": { "label": "Try a different email", "target": "signup", "variant": "outline-secondary", "full": true } },
286
+ { "action": "render.link", "params": { "text": "Sign in instead", "target": "login", "prefix": "Already have one?" } }
287
+ ],
288
+ "onExit": [], "onBack": [], "onReset": [], "onUnload": []
289
+ },
290
+ "routes": [],
291
+ "template": "blank",
292
+ "meta": { "isEntry": false }
293
+ }
294
+ ],
295
+ "edges": [
296
+ { "id": "e0a", "fromId": "lobby", "toId": "login", "label": "Sign In", "condition": "" },
297
+ { "id": "e0b", "fromId": "lobby", "toId": "signup", "label": "Create Account", "condition": "" },
298
+ { "id": "e0c", "fromId": "lobby", "toId": "forgot", "label": "Forgot password", "condition": "" },
299
+ { "id": "e2", "fromId": "login", "toId": "auth-check", "label": "Submit", "condition": "" },
300
+ { "id": "e3", "fromId": "login", "toId": "forgot", "label": "Forgot password", "condition": "" },
301
+ { "id": "e4", "fromId": "login", "toId": "signup", "label": "Create account", "condition": "" },
302
+ { "id": "e5", "fromId": "auth-check", "toId": "dashboard", "label": "Authenticated", "condition": "" },
303
+ { "id": "e6", "fromId": "auth-check", "toId": "login-error", "label": "Wrong password", "condition": "" },
304
+ { "id": "e7", "fromId": "auth-check", "toId": "signup", "label": "Not found", "condition": "" },
305
+ { "id": "e8", "fromId": "login-error", "toId": "login", "label": "Retry", "condition": "" },
306
+ { "id": "e8b", "fromId": "login-error", "toId": "forgot", "label": "Forgot password", "condition": "" },
307
+ { "id": "e8c", "fromId": "login-error", "toId": "signup", "label": "Create account", "condition": "" },
308
+ { "id": "e9", "fromId": "forgot", "toId": "reset-check", "label": "Submit", "condition": "" },
309
+ { "id": "e10", "fromId": "forgot", "toId": "login", "label": "Back to login", "condition": "" },
310
+ { "id": "e11", "fromId": "reset-check", "toId": "reset-sent", "label": "Email sent", "condition": "" },
311
+ { "id": "e12", "fromId": "reset-check", "toId": "reset-nfe", "label": "Not found", "condition": "" },
312
+ { "id": "e13", "fromId": "reset-nfe", "toId": "signup", "label": "Create account", "condition": "" },
313
+ { "id": "e13b","fromId": "reset-nfe", "toId": "forgot", "label": "Try again", "condition": "" },
314
+ { "id": "e14", "fromId": "signup", "toId": "register-check", "label": "Submit", "condition": "" },
315
+ { "id": "e15", "fromId": "signup", "toId": "login", "label": "Back to login", "condition": "" },
316
+ { "id": "e16", "fromId": "register-check", "toId": "dashboard", "label": "Success", "condition": "" },
317
+ { "id": "e17", "fromId": "register-check", "toId": "signup-error", "label": "Email exists", "condition": "" },
318
+ { "id": "e18", "fromId": "signup-error", "toId": "signup", "label": "Try again", "condition": "" },
319
+ { "id": "e19", "fromId": "signup-error", "toId": "login", "label": "Sign in instead", "condition": "" }
320
+ ]
321
+ },
322
+ "inventory": {
323
+ "schema": {
324
+ "email": { "type": "string", "default": "", "label": "User email address" },
325
+ "password": { "type": "string", "default": "", "label": "Password" },
326
+ "firstName": { "type": "string", "default": "", "label": "First name" },
327
+ "lastName": { "type": "string", "default": "", "label": "Last name" },
328
+ "authenticated": { "type": "boolean", "default": false, "label": "Authenticated?" },
329
+ "authError": { "type": "string", "default": "", "label": "Auth error code" },
330
+ "resetSent": { "type": "boolean", "default": false, "label": "Reset email sent?" },
331
+ "registered": { "type": "boolean", "default": false, "label": "Signup succeeded?" }
332
+ }
333
+ },
334
+ "customActions": {}
335
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "id": "blank",
3
+ "name": "Blank",
4
+ "description": "An empty canvas — start building your flow from scratch.",
5
+ "icon": "app-indicator",
6
+ "category": "starter",
7
+ "preview": "A lobby entry node, ready for your first room.",
8
+ "graph": {
9
+ "nodes": [
10
+ {
11
+ "id": "lobby",
12
+ "type": "room",
13
+ "label": "Welcome",
14
+ "x": 120,
15
+ "y": 200,
16
+ "payload": {
17
+ "onEnter": [],
18
+ "onExit": [],
19
+ "onBack": [],
20
+ "onReset": [],
21
+ "onUnload": []
22
+ },
23
+ "routes": [],
24
+ "template": "lobby",
25
+ "meta": {
26
+ "isEntry": true,
27
+ "appName": "My App",
28
+ "tagline": "Your tagline goes here.",
29
+ "icon": "stars"
30
+ }
31
+ }
32
+ ],
33
+ "edges": []
34
+ },
35
+ "inventory": {
36
+ "schema": {}
37
+ },
38
+ "customActions": {}
39
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "type": "AuthServerThing",
3
+ "label": "Auth Server",
4
+ "desc": "Handles login, signup, and token validation. Swap in TestAuthServerThing for offline development.",
5
+ "icon": "shield-lock",
6
+ "color": "var(--sol-blue)",
7
+ "config": [
8
+ { "name": "apiUrl", "label": "API base URL", "type": "text", "placeholder": "https://api.example.com/auth" },
9
+ { "name": "tokenInto", "label": "Token into", "type": "text", "placeholder": "authToken", "default": "authToken" }
10
+ ],
11
+ "defaultEvents": [
12
+ { "key": "onEnter", "label": "Enter", "fixed": true }
13
+ ],
14
+ "canAddEvents": true,
15
+ "builtIn": true,
16
+ "mockType": "TestAuthServerThing"
17
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "type": "PersonaLiveThing",
3
+ "label": "Persona",
4
+ "desc": "An AI persona that inhabits the room and responds to messages. Works offline with local models — no server needed.",
5
+ "icon": "robot",
6
+ "color": "var(--sol-violet)",
7
+ "config": [
8
+ { "name": "name", "label": "Name", "type": "text", "placeholder": "Alex", "default": "Persona" },
9
+ { "name": "personality", "label": "Personality", "type": "textarea", "placeholder": "You are a helpful assistant.", "default": "" },
10
+ { "name": "endpoint", "label": "AI Endpoint", "type": "text", "default": "http://localhost:8191/v1/chat/completions" },
11
+ { "name": "model", "label": "Model", "type": "text", "default": "local" },
12
+ { "name": "replyInto", "label": "Reply into", "type": "text", "placeholder": "aiReply", "default": "" }
13
+ ],
14
+ "defaultEvents": [
15
+ { "key": "onEnter", "label": "Enter", "fixed": true },
16
+ { "key": "message", "label": "Message", "fixed": false }
17
+ ],
18
+ "canAddEvents": false,
19
+ "builtIn": true
20
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "type": "WorkflowThing",
3
+ "label": "Workflow",
4
+ "desc": "A scriptable service. Add Savant workflows for each event it listens to. Like Apple Savant Services.",
5
+ "icon": "gear-wide-connected",
6
+ "color": "var(--sol-green)",
7
+ "config": [
8
+ { "name": "name", "label": "Name", "type": "text", "placeholder": "My Service" }
9
+ ],
10
+ "defaultEvents": [
11
+ { "key": "onEnter", "label": "Enter", "fixed": true }
12
+ ],
13
+ "canAddEvents": true,
14
+ "builtIn": true
15
+ }