@engenty/wizards-runtime 0.0.0-stage → 0.7.5

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 (518) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +214 -2
  3. package/apps/runtime/dist/agents/architect.js +444 -0
  4. package/apps/runtime/dist/agents/studio-assistant.js +883 -0
  5. package/apps/runtime/dist/agents/subscription.js +207 -0
  6. package/apps/runtime/dist/agents/thought.js +21 -0
  7. package/apps/runtime/dist/agents/website.js +480 -0
  8. package/apps/runtime/dist/app.js +359 -0
  9. package/apps/runtime/dist/apple/wizards-apple +0 -0
  10. package/apps/runtime/dist/assistant/browser.js +26 -0
  11. package/apps/runtime/dist/assistant/docs.js +158 -0
  12. package/apps/runtime/dist/assistant/knows.js +353 -0
  13. package/apps/runtime/dist/assistant/primer.js +26 -0
  14. package/apps/runtime/dist/assistant/runs.js +24 -0
  15. package/apps/runtime/dist/auth/account.js +175 -0
  16. package/apps/runtime/dist/auth/device.js +112 -0
  17. package/apps/runtime/dist/auth/index.js +358 -0
  18. package/apps/runtime/dist/auth/keys.js +55 -0
  19. package/apps/runtime/dist/auth/local-ticket.js +26 -0
  20. package/apps/runtime/dist/authoring/example.js +74 -0
  21. package/apps/runtime/dist/authoring/guide.js +433 -0
  22. package/apps/runtime/dist/authoring/ops.js +117 -0
  23. package/apps/runtime/dist/browser/fast/action-space.js +160 -0
  24. package/apps/runtime/dist/browser/fast/classifier.js +91 -0
  25. package/apps/runtime/dist/browser/fast/decide.js +171 -0
  26. package/apps/runtime/dist/browser/fast/driver.js +141 -0
  27. package/apps/runtime/dist/browser/fast/instructions.js +33 -0
  28. package/apps/runtime/dist/browser/fast/run.js +249 -0
  29. package/apps/runtime/dist/browser/fast/span-picker.js +153 -0
  30. package/apps/runtime/dist/browser/fast/text-helper.js +178 -0
  31. package/apps/runtime/dist/browser/snapshot.js +335 -0
  32. package/apps/runtime/dist/cli/account.js +385 -0
  33. package/apps/runtime/dist/cli/autostart.js +182 -0
  34. package/apps/runtime/dist/cli/autoupdate.js +221 -0
  35. package/apps/runtime/dist/cli/clients.js +44 -0
  36. package/apps/runtime/dist/cli/connect.js +540 -0
  37. package/apps/runtime/dist/cli/environment.js +93 -0
  38. package/apps/runtime/dist/cli/exec.js +45 -0
  39. package/apps/runtime/dist/cli/features.js +50 -0
  40. package/apps/runtime/dist/cli/home.js +88 -0
  41. package/apps/runtime/dist/cli/install-env.js +33 -0
  42. package/apps/runtime/dist/cli/machine.js +107 -0
  43. package/apps/runtime/dist/cli/main.js +222 -0
  44. package/apps/runtime/dist/cli/mcp.js +136 -0
  45. package/apps/runtime/dist/cli/menu.js +202 -0
  46. package/apps/runtime/dist/cli/processes.js +72 -0
  47. package/apps/runtime/dist/cli/report.js +66 -0
  48. package/apps/runtime/dist/cli/setup.js +335 -0
  49. package/apps/runtime/dist/cli/start.js +276 -0
  50. package/apps/runtime/dist/cli/status.js +203 -0
  51. package/apps/runtime/dist/cli/ui.js +59 -0
  52. package/apps/runtime/dist/cli/uninstall-main.js +20 -0
  53. package/apps/runtime/dist/cli/uninstall.js +231 -0
  54. package/apps/runtime/dist/cli/update.js +86 -0
  55. package/apps/runtime/dist/cli/validate.js +75 -0
  56. package/apps/runtime/dist/cli/versions.js +123 -0
  57. package/apps/runtime/dist/connectors/builtin.js +86 -0
  58. package/apps/runtime/dist/connectors/external.js +409 -0
  59. package/apps/runtime/dist/connectors/gmail.js +107 -0
  60. package/apps/runtime/dist/connectors/imap.js +261 -0
  61. package/apps/runtime/dist/connectors/index.js +325 -0
  62. package/apps/runtime/dist/connectors/mail.js +72 -0
  63. package/apps/runtime/dist/connectors/outlook.js +90 -0
  64. package/apps/runtime/dist/connectors/plugin-connections.js +343 -0
  65. package/apps/runtime/dist/connectors/via-account.js +65 -0
  66. package/apps/runtime/dist/credits/credits.js +100 -0
  67. package/apps/runtime/dist/credits/estimate.js +152 -0
  68. package/apps/runtime/dist/db/adopt.js +149 -0
  69. package/apps/runtime/dist/db/client.js +173 -0
  70. package/apps/runtime/dist/db/control-schema.js +133 -0
  71. package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
  72. package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
  73. package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
  74. package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
  75. package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
  76. package/apps/runtime/dist/db/migrations/control/0005_chilly_oracle.sql +1 -0
  77. package/apps/runtime/dist/db/migrations/control/0006_sleepy_mojo.sql +1 -0
  78. package/apps/runtime/dist/db/migrations/control/0007_common_the_hand.sql +15 -0
  79. package/apps/runtime/dist/db/migrations/control/0008_runner.sql +8 -0
  80. package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
  81. package/apps/runtime/dist/db/migrations/control/0010_tan_snowbird.sql +6 -0
  82. package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
  83. package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
  84. package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
  85. package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
  86. package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
  87. package/apps/runtime/dist/db/migrations/control/meta/0005_snapshot.json +358 -0
  88. package/apps/runtime/dist/db/migrations/control/meta/0006_snapshot.json +365 -0
  89. package/apps/runtime/dist/db/migrations/control/meta/0007_snapshot.json +460 -0
  90. package/apps/runtime/dist/db/migrations/control/meta/0008_snapshot.json +505 -0
  91. package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
  92. package/apps/runtime/dist/db/migrations/control/meta/0010_snapshot.json +600 -0
  93. package/apps/runtime/dist/db/migrations/control/meta/_journal.json +83 -0
  94. package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
  95. package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
  96. package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
  97. package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
  98. package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
  99. package/apps/runtime/dist/db/migrations/tenant/0005_reflective_forgotten_one.sql +2 -0
  100. package/apps/runtime/dist/db/migrations/tenant/0006_hard_war_machine.sql +30 -0
  101. package/apps/runtime/dist/db/migrations/tenant/0007_space_data.sql +43 -0
  102. package/apps/runtime/dist/db/migrations/tenant/0008_run_event_note.sql +1 -0
  103. package/apps/runtime/dist/db/migrations/tenant/0009_knowledge.sql +104 -0
  104. package/apps/runtime/dist/db/migrations/tenant/0010_plugin_connection.sql +15 -0
  105. package/apps/runtime/dist/db/migrations/tenant/0011_runners.sql +2 -0
  106. package/apps/runtime/dist/db/migrations/tenant/0012_assistant_chat.sql +40 -0
  107. package/apps/runtime/dist/db/migrations/tenant/0013_run_origin.sql +1 -0
  108. package/apps/runtime/dist/db/migrations/tenant/0014_run_answer.sql +2 -0
  109. package/apps/runtime/dist/db/migrations/tenant/0015_device_calls.sql +13 -0
  110. package/apps/runtime/dist/db/migrations/tenant/0016_even_trish_tilby.sql +12 -0
  111. package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
  112. package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
  113. package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
  114. package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
  115. package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
  116. package/apps/runtime/dist/db/migrations/tenant/meta/0005_snapshot.json +1659 -0
  117. package/apps/runtime/dist/db/migrations/tenant/meta/0006_snapshot.json +1696 -0
  118. package/apps/runtime/dist/db/migrations/tenant/meta/0007_snapshot.json +2012 -0
  119. package/apps/runtime/dist/db/migrations/tenant/meta/0008_snapshot.json +2019 -0
  120. package/apps/runtime/dist/db/migrations/tenant/meta/0009_snapshot.json +2837 -0
  121. package/apps/runtime/dist/db/migrations/tenant/meta/0010_snapshot.json +2942 -0
  122. package/apps/runtime/dist/db/migrations/tenant/meta/0011_snapshot.json +2956 -0
  123. package/apps/runtime/dist/db/migrations/tenant/meta/0012_snapshot.json +3132 -0
  124. package/apps/runtime/dist/db/migrations/tenant/meta/0013_snapshot.json +3139 -0
  125. package/apps/runtime/dist/db/migrations/tenant/meta/0014_snapshot.json +3154 -0
  126. package/apps/runtime/dist/db/migrations/tenant/meta/0015_snapshot.json +3243 -0
  127. package/apps/runtime/dist/db/migrations/tenant/meta/0016_snapshot.json +3326 -0
  128. package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +125 -0
  129. package/apps/runtime/dist/db/schema.js +602 -0
  130. package/apps/runtime/dist/debug.js +196 -0
  131. package/apps/runtime/dist/docs/dev/index.md +41 -0
  132. package/apps/runtime/dist/docs/dev/meta.json +7 -0
  133. package/apps/runtime/dist/docs/dev/plugins/connections.md +74 -0
  134. package/apps/runtime/dist/docs/dev/plugins/events.md +89 -0
  135. package/apps/runtime/dist/docs/dev/plugins/examples.md +101 -0
  136. package/apps/runtime/dist/docs/dev/plugins/index.md +78 -0
  137. package/apps/runtime/dist/docs/dev/plugins/layout.md +90 -0
  138. package/apps/runtime/dist/docs/dev/plugins/meta.json +28 -0
  139. package/apps/runtime/dist/docs/dev/plugins/quick-start.md +94 -0
  140. package/apps/runtime/dist/docs/dev/plugins/reference.md +348 -0
  141. package/apps/runtime/dist/docs/dev/plugins/reloading.md +76 -0
  142. package/apps/runtime/dist/docs/dev/plugins/routes.md +185 -0
  143. package/apps/runtime/dist/docs/dev/plugins/runners.md +230 -0
  144. package/apps/runtime/dist/docs/dev/plugins/server.md +281 -0
  145. package/apps/runtime/dist/docs/dev/plugins/shipping.md +79 -0
  146. package/apps/runtime/dist/docs/dev/plugins/space.md +297 -0
  147. package/apps/runtime/dist/docs/dev/plugins/starters.md +70 -0
  148. package/apps/runtime/dist/docs/dev/plugins/studio.md +363 -0
  149. package/apps/runtime/dist/docs/dev/plugins/styling.md +129 -0
  150. package/apps/runtime/dist/docs/dev/plugins/tables.md +104 -0
  151. package/apps/runtime/dist/docs/dev/plugins/tools.md +139 -0
  152. package/apps/runtime/dist/docs/dev/wizard-format.md +125 -0
  153. package/apps/runtime/dist/docs/meta.json +3 -0
  154. package/apps/runtime/dist/docs/user/ai-apps.md +112 -0
  155. package/apps/runtime/dist/docs/user/assistant.md +77 -0
  156. package/apps/runtime/dist/docs/user/build-a-wizard.md +116 -0
  157. package/apps/runtime/dist/docs/user/command-line.md +83 -0
  158. package/apps/runtime/dist/docs/user/connectors.md +90 -0
  159. package/apps/runtime/dist/docs/user/create-account.md +52 -0
  160. package/apps/runtime/dist/docs/user/data.md +66 -0
  161. package/apps/runtime/dist/docs/user/first-start.md +60 -0
  162. package/apps/runtime/dist/docs/user/index.md +49 -0
  163. package/apps/runtime/dist/docs/user/install.md +123 -0
  164. package/apps/runtime/dist/docs/user/local-only.md +42 -0
  165. package/apps/runtime/dist/docs/user/meta.json +32 -0
  166. package/apps/runtime/dist/docs/user/models.md +156 -0
  167. package/apps/runtime/dist/docs/user/plugins.md +71 -0
  168. package/apps/runtime/dist/docs/user/run.md +98 -0
  169. package/apps/runtime/dist/docs/user/server.md +52 -0
  170. package/apps/runtime/dist/docs/user/space.md +126 -0
  171. package/apps/runtime/dist/docs/user/steps.md +220 -0
  172. package/apps/runtime/dist/docs/user/test-and-share.md +224 -0
  173. package/apps/runtime/dist/docs/user/troubleshooting.md +67 -0
  174. package/apps/runtime/dist/docs/user/wordpress.md +121 -0
  175. package/apps/runtime/dist/documents/parse.js +246 -0
  176. package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
  177. package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
  178. package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
  179. package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
  180. package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
  181. package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
  182. package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
  183. package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
  184. package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
  185. package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
  186. package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
  187. package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
  188. package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
  189. package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
  190. package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
  191. package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +381 -0
  192. package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
  193. package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
  194. package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
  195. package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
  196. package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
  197. package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
  198. package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
  199. package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
  200. package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
  201. package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +492 -0
  202. package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
  203. package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
  204. package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
  205. package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
  206. package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
  207. package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
  208. package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
  209. package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
  210. package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
  211. package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
  212. package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
  213. package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
  214. package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
  215. package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
  216. package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
  217. package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
  218. package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
  219. package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
  220. package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
  221. package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
  222. package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
  223. package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
  224. package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
  225. package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
  226. package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
  227. package/apps/runtime/dist/engenty/shims/web-ingest.js +19 -0
  228. package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
  229. package/apps/runtime/dist/engine/asks.js +82 -0
  230. package/apps/runtime/dist/engine/decide.js +82 -0
  231. package/apps/runtime/dist/engine/device.js +194 -0
  232. package/apps/runtime/dist/engine/events.js +128 -0
  233. package/apps/runtime/dist/engine/input.js +208 -0
  234. package/apps/runtime/dist/engine/owner.js +32 -0
  235. package/apps/runtime/dist/engine/prepare.js +90 -0
  236. package/apps/runtime/dist/engine/push.js +58 -0
  237. package/apps/runtime/dist/engine/requirements.js +355 -0
  238. package/apps/runtime/dist/engine/resources.js +198 -0
  239. package/apps/runtime/dist/engine/runner.js +970 -0
  240. package/apps/runtime/dist/engine/steps.js +1000 -0
  241. package/apps/runtime/dist/engine/surface.js +91 -0
  242. package/apps/runtime/dist/engine/template.js +240 -0
  243. package/apps/runtime/dist/engine/types.js +4 -0
  244. package/apps/runtime/dist/env.js +295 -0
  245. package/apps/runtime/dist/features.js +123 -0
  246. package/apps/runtime/dist/files/blobs.js +22 -0
  247. package/apps/runtime/dist/files/objects.js +86 -0
  248. package/apps/runtime/dist/files/storage.js +120 -0
  249. package/apps/runtime/dist/files/web-images.js +101 -0
  250. package/apps/runtime/dist/film/project.js +257 -0
  251. package/apps/runtime/dist/film/skills.js +91 -0
  252. package/apps/runtime/dist/film/sounds.js +122 -0
  253. package/apps/runtime/dist/film/step.js +289 -0
  254. package/apps/runtime/dist/film/tools.js +99 -0
  255. package/apps/runtime/dist/geocode.js +58 -0
  256. package/apps/runtime/dist/harness/antigravity.js +129 -0
  257. package/apps/runtime/dist/harness/apple.js +270 -0
  258. package/apps/runtime/dist/harness/claude.js +147 -0
  259. package/apps/runtime/dist/harness/codex.js +229 -0
  260. package/apps/runtime/dist/harness/cursor.js +93 -0
  261. package/apps/runtime/dist/harness/env.js +124 -0
  262. package/apps/runtime/dist/harness/index.js +95 -0
  263. package/apps/runtime/dist/harness/model.js +279 -0
  264. package/apps/runtime/dist/harness/prompt.js +121 -0
  265. package/apps/runtime/dist/harness/terminal.js +194 -0
  266. package/apps/runtime/dist/harness/types.js +7 -0
  267. package/apps/runtime/dist/index.js +113 -0
  268. package/apps/runtime/dist/limits.js +81 -0
  269. package/apps/runtime/dist/link-preview.js +60 -0
  270. package/apps/runtime/dist/log.js +106 -0
  271. package/apps/runtime/dist/manage.js +249 -0
  272. package/apps/runtime/dist/mcp/auth.js +161 -0
  273. package/apps/runtime/dist/mcp/bridge.js +59 -0
  274. package/apps/runtime/dist/mcp/flow-app.js +97 -0
  275. package/apps/runtime/dist/mcp/handler.js +54 -0
  276. package/apps/runtime/dist/mcp/scopes.js +14 -0
  277. package/apps/runtime/dist/mcp/seen.js +65 -0
  278. package/apps/runtime/dist/mcp/tools.js +572 -0
  279. package/apps/runtime/dist/media/conversation.js +167 -0
  280. package/apps/runtime/dist/media/ffmpeg.js +121 -0
  281. package/apps/runtime/dist/media/generate.js +120 -0
  282. package/apps/runtime/dist/media/marking.js +121 -0
  283. package/apps/runtime/dist/media/transcribe.js +198 -0
  284. package/apps/runtime/dist/model-errors.js +42 -0
  285. package/apps/runtime/dist/models.js +1164 -0
  286. package/apps/runtime/dist/plugin.js +61 -0
  287. package/apps/runtime/dist/plugins/channels.js +78 -0
  288. package/apps/runtime/dist/plugins/claims.js +56 -0
  289. package/apps/runtime/dist/plugins/discovery.js +155 -0
  290. package/apps/runtime/dist/plugins/events.js +63 -0
  291. package/apps/runtime/dist/plugins/jobs.js +64 -0
  292. package/apps/runtime/dist/plugins/loader.js +508 -0
  293. package/apps/runtime/dist/plugins/migrations.js +69 -0
  294. package/apps/runtime/dist/plugins/pro-keys.js +34 -0
  295. package/apps/runtime/dist/plugins/pro-state.js +83 -0
  296. package/apps/runtime/dist/plugins/pro.js +310 -0
  297. package/apps/runtime/dist/plugins/public.js +44 -0
  298. package/apps/runtime/dist/plugins/registry.js +122 -0
  299. package/apps/runtime/dist/plugins/runs.js +210 -0
  300. package/apps/runtime/dist/render/browser-path.js +54 -0
  301. package/apps/runtime/dist/render/chromium.js +98 -0
  302. package/apps/runtime/dist/render/convert.js +158 -0
  303. package/apps/runtime/dist/render/downloads.js +299 -0
  304. package/apps/runtime/dist/render/guard.js +25 -0
  305. package/apps/runtime/dist/render/shaped.js +137 -0
  306. package/apps/runtime/dist/routes/api.js +440 -0
  307. package/apps/runtime/dist/routes/debug.js +42 -0
  308. package/apps/runtime/dist/routes/delivery.js +90 -0
  309. package/apps/runtime/dist/routes/internal.js +81 -0
  310. package/apps/runtime/dist/routes/lang.js +25 -0
  311. package/apps/runtime/dist/routes/marketplace.js +43 -0
  312. package/apps/runtime/dist/routes/plugin-public.js +113 -0
  313. package/apps/runtime/dist/routes/plugins.js +212 -0
  314. package/apps/runtime/dist/routes/runs.js +1422 -0
  315. package/apps/runtime/dist/routes/studio.js +1629 -0
  316. package/apps/runtime/dist/routes/wizard-stream.js +30 -0
  317. package/apps/runtime/dist/running.js +39 -0
  318. package/apps/runtime/dist/sandbox/docker.js +75 -0
  319. package/apps/runtime/dist/sandbox/index.js +23 -0
  320. package/apps/runtime/dist/sandbox/types.js +1 -0
  321. package/apps/runtime/dist/secrets/crypto.js +28 -0
  322. package/apps/runtime/dist/secrets/signing.js +52 -0
  323. package/apps/runtime/dist/secrets/vault.js +59 -0
  324. package/apps/runtime/dist/services/access.js +88 -0
  325. package/apps/runtime/dist/services/api.js +248 -0
  326. package/apps/runtime/dist/services/architect.js +95 -0
  327. package/apps/runtime/dist/services/assistant-chats.js +311 -0
  328. package/apps/runtime/dist/services/brand.js +85 -0
  329. package/apps/runtime/dist/services/cloud.js +456 -0
  330. package/apps/runtime/dist/services/draft-events.js +27 -0
  331. package/apps/runtime/dist/services/engenty-shapes.js +71 -0
  332. package/apps/runtime/dist/services/errors.js +29 -0
  333. package/apps/runtime/dist/services/files.js +178 -0
  334. package/apps/runtime/dist/services/knowledge-model.js +559 -0
  335. package/apps/runtime/dist/services/knowledge.js +721 -0
  336. package/apps/runtime/dist/services/links.js +16 -0
  337. package/apps/runtime/dist/services/marketplace.js +492 -0
  338. package/apps/runtime/dist/services/onboarding.js +152 -0
  339. package/apps/runtime/dist/services/package-file.js +82 -0
  340. package/apps/runtime/dist/services/package.js +170 -0
  341. package/apps/runtime/dist/services/profile.js +51 -0
  342. package/apps/runtime/dist/services/project-files.js +439 -0
  343. package/apps/runtime/dist/services/project-index.js +707 -0
  344. package/apps/runtime/dist/services/projects.js +387 -0
  345. package/apps/runtime/dist/services/relevance.js +58 -0
  346. package/apps/runtime/dist/services/runners.js +178 -0
  347. package/apps/runtime/dist/services/runs.js +524 -0
  348. package/apps/runtime/dist/services/shares.js +130 -0
  349. package/apps/runtime/dist/services/site.js +270 -0
  350. package/apps/runtime/dist/services/space-categories.js +861 -0
  351. package/apps/runtime/dist/services/space-data.js +792 -0
  352. package/apps/runtime/dist/services/space-origin.js +207 -0
  353. package/apps/runtime/dist/services/spaces.js +656 -0
  354. package/apps/runtime/dist/services/translations.js +306 -0
  355. package/apps/runtime/dist/services/widgets.js +34 -0
  356. package/apps/runtime/dist/services/wizard-icon.js +157 -0
  357. package/apps/runtime/dist/services/wizards.js +420 -0
  358. package/apps/runtime/dist/settings.js +16 -0
  359. package/apps/runtime/dist/store/errors.js +4 -0
  360. package/apps/runtime/dist/store/index.js +299 -0
  361. package/apps/runtime/dist/store/shared-lists.js +123 -0
  362. package/apps/runtime/dist/tenants/control.js +238 -0
  363. package/apps/runtime/dist/tenants/tenant.js +26 -0
  364. package/apps/runtime/dist/texts.js +207 -0
  365. package/apps/runtime/dist/tools/browser.js +703 -0
  366. package/apps/runtime/dist/tools/connector.js +204 -0
  367. package/apps/runtime/dist/tools/index.js +291 -0
  368. package/apps/runtime/dist/tools/mail.js +104 -0
  369. package/apps/runtime/dist/tools/net-guard.js +170 -0
  370. package/apps/runtime/dist/tools/pages.js +81 -0
  371. package/apps/runtime/dist/tools/plugin.js +180 -0
  372. package/apps/runtime/dist/tools/project.js +154 -0
  373. package/apps/runtime/dist/tools/shared.js +69 -0
  374. package/apps/runtime/dist/tools/store.js +238 -0
  375. package/apps/runtime/dist/update.js +113 -0
  376. package/apps/runtime/dist/widgets/bundle.js +99 -0
  377. package/apps/runtime/dist/widgets/render.js +329 -0
  378. package/apps/runtime/dist/widgets/runtime.js +108 -0
  379. package/apps/runtime/dist/widgets/script.js +30 -0
  380. package/apps/runtime/dist/widgets/step.js +223 -0
  381. package/apps/web/dist/ai-labels/ai-black.svg +20 -0
  382. package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
  383. package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
  384. package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
  385. package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
  386. package/apps/web/dist/ai-labels/ai-white.svg +21 -0
  387. package/apps/web/dist/assets/AboutDialog-D4mvc-zu.js +1 -0
  388. package/apps/web/dist/assets/ChangelogDialog-DLqpJsF6.js +1 -0
  389. package/apps/web/dist/assets/ChatView-3laypRcE.js +10 -0
  390. package/apps/web/dist/assets/EditorPage-BalA5U2Y.js +3 -0
  391. package/apps/web/dist/assets/FlowPreview-CusP7ci9.js +1 -0
  392. package/apps/web/dist/assets/Harness-BrP-ENHg.css +1 -0
  393. package/apps/web/dist/assets/Harness-iYLtOLaK.js +16 -0
  394. package/apps/web/dist/assets/NewWizardChannels-CbwJ9A56.js +1 -0
  395. package/apps/web/dist/assets/NewWizardPage-BOBYiB9i.js +7 -0
  396. package/apps/web/dist/assets/OnboardingPage-CUwCiVIr.js +1 -0
  397. package/apps/web/dist/assets/ProjectPage-Bb16MdYG.js +1 -0
  398. package/apps/web/dist/assets/PublicRunner-BCt7Q6C-.js +1 -0
  399. package/apps/web/dist/assets/ReadOnly-kIHX2TEy.js +1 -0
  400. package/apps/web/dist/assets/RunDrawer-hZ9oeSXu.js +4 -0
  401. package/apps/web/dist/assets/RunnerView-DUS9fPmx.js +1 -0
  402. package/apps/web/dist/assets/SettingsPage-BzwR50fi.js +1 -0
  403. package/apps/web/dist/assets/SetupPage-gAp7rPxp.js +1 -0
  404. package/apps/web/dist/assets/SharePage-DqZWHva_.js +1 -0
  405. package/apps/web/dist/assets/changelog-DugmCNSf.js +1 -0
  406. package/apps/web/dist/assets/engenty-eXZ-EAwd.js +1 -0
  407. package/apps/web/dist/assets/esm-DXeMu8Lb.js +7 -0
  408. package/apps/web/dist/assets/fluffy-engenty-ClRou7yu.js +456 -0
  409. package/apps/web/dist/assets/index-AfUa8xKD.css +1 -0
  410. package/apps/web/dist/assets/index-C5Sm7tTR.js +14 -0
  411. package/apps/web/dist/assets/jsx-runtime-BNakU3Ej.js +1 -0
  412. package/apps/web/dist/assets/lock-R_CfU0Xo.js +1 -0
  413. package/apps/web/dist/assets/oss-credits-cZ9NUaLZ.js +1 -0
  414. package/apps/web/dist/assets/pdfmake-Cx9scTbD.js +228 -0
  415. package/apps/web/dist/assets/phone-CgrIS4_-.js +1 -0
  416. package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
  417. package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
  418. package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
  419. package/apps/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  420. package/apps/web/dist/assets/settings-menu-2IMOOlLl.js +1 -0
  421. package/apps/web/dist/assets/ui-dzGvc3xk.js +137 -0
  422. package/apps/web/dist/assets/upload-BSuTilFF.js +1 -0
  423. package/apps/web/dist/assets/vfs_fonts-DllDSYt1.js +1 -0
  424. package/apps/web/dist/embed.js +266 -0
  425. package/apps/web/dist/favicon.svg +1 -0
  426. package/apps/web/dist/icons/apple-touch-icon.png +0 -0
  427. package/apps/web/dist/icons/icon-192.png +0 -0
  428. package/apps/web/dist/icons/icon-512.png +0 -0
  429. package/apps/web/dist/icons/icon-maskable-512.png +0 -0
  430. package/apps/web/dist/index.html +48 -0
  431. package/apps/web/dist/install.sh +577 -0
  432. package/apps/web/dist/manifest.webmanifest +21 -0
  433. package/apps/web/dist/mcp/flow.html +980 -0
  434. package/apps/web/dist/sw.js +15 -0
  435. package/bin/wizards.mjs +288 -0
  436. package/modules/README.md +15 -0
  437. package/node_modules/@engenty/wizards/dist/plugin/index.d.ts +1150 -0
  438. package/node_modules/@engenty/wizards/dist/plugin/index.js +4 -0
  439. package/node_modules/@engenty/wizards/dist/plugin/studio.d.ts +322 -0
  440. package/node_modules/@engenty/wizards/dist/plugin/studio.js +4 -0
  441. package/node_modules/@engenty/wizards/dist/plugin/thread.d.ts +174 -0
  442. package/node_modules/@engenty/wizards/dist/plugin/thread.js +821 -0
  443. package/node_modules/@engenty/wizards/package.json +11 -0
  444. package/node_modules/@engenty-wizards/shared/dist/assistant.d.ts +174 -0
  445. package/node_modules/@engenty-wizards/shared/dist/assistant.js +65 -0
  446. package/node_modules/@engenty-wizards/shared/dist/changes.d.ts +22 -0
  447. package/node_modules/@engenty-wizards/shared/dist/changes.js +61 -0
  448. package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
  449. package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
  450. package/node_modules/@engenty-wizards/shared/dist/decision.d.ts +76 -0
  451. package/node_modules/@engenty-wizards/shared/dist/decision.js +147 -0
  452. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +2922 -0
  453. package/node_modules/@engenty-wizards/shared/dist/definition.js +1920 -0
  454. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
  455. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
  456. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
  457. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
  458. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
  459. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +217 -0
  460. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
  461. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
  462. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
  463. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
  464. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
  465. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
  466. package/node_modules/@engenty-wizards/shared/dist/feature-flags.d.ts +78 -0
  467. package/node_modules/@engenty-wizards/shared/dist/feature-flags.js +70 -0
  468. package/node_modules/@engenty-wizards/shared/dist/features.d.ts +41 -0
  469. package/node_modules/@engenty-wizards/shared/dist/features.js +89 -0
  470. package/node_modules/@engenty-wizards/shared/dist/fit.d.ts +71 -0
  471. package/node_modules/@engenty-wizards/shared/dist/fit.js +382 -0
  472. package/node_modules/@engenty-wizards/shared/dist/json-schema.d.ts +14 -0
  473. package/node_modules/@engenty-wizards/shared/dist/json-schema.js +66 -0
  474. package/node_modules/@engenty-wizards/shared/dist/knowledge.d.ts +199 -0
  475. package/node_modules/@engenty-wizards/shared/dist/knowledge.js +68 -0
  476. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
  477. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +107 -0
  478. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
  479. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +136 -0
  480. package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +227 -0
  481. package/node_modules/@engenty-wizards/shared/dist/marketplace.js +354 -0
  482. package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
  483. package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
  484. package/node_modules/@engenty-wizards/shared/dist/numbers.d.ts +24 -0
  485. package/node_modules/@engenty-wizards/shared/dist/numbers.js +54 -0
  486. package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +224 -0
  487. package/node_modules/@engenty-wizards/shared/dist/projects.js +319 -0
  488. package/node_modules/@engenty-wizards/shared/dist/providers.d.ts +101 -0
  489. package/node_modules/@engenty-wizards/shared/dist/providers.js +390 -0
  490. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +680 -0
  491. package/node_modules/@engenty-wizards/shared/dist/run.js +620 -0
  492. package/node_modules/@engenty-wizards/shared/dist/runner-texts.d.ts +546 -0
  493. package/node_modules/@engenty-wizards/shared/dist/runner-texts.js +523 -0
  494. package/node_modules/@engenty-wizards/shared/dist/runners.d.ts +93 -0
  495. package/node_modules/@engenty-wizards/shared/dist/runners.js +146 -0
  496. package/node_modules/@engenty-wizards/shared/dist/shape.d.ts +102 -0
  497. package/node_modules/@engenty-wizards/shared/dist/shape.js +318 -0
  498. package/node_modules/@engenty-wizards/shared/dist/space-data.d.ts +89 -0
  499. package/node_modules/@engenty-wizards/shared/dist/space-data.js +47 -0
  500. package/node_modules/@engenty-wizards/shared/dist/store.d.ts +117 -0
  501. package/node_modules/@engenty-wizards/shared/dist/store.js +81 -0
  502. package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +115 -0
  503. package/node_modules/@engenty-wizards/shared/dist/surface.js +442 -0
  504. package/node_modules/@engenty-wizards/shared/dist/texts.d.ts +45 -0
  505. package/node_modules/@engenty-wizards/shared/dist/texts.js +54 -0
  506. package/node_modules/@engenty-wizards/shared/dist/translation.d.ts +23 -0
  507. package/node_modules/@engenty-wizards/shared/dist/translation.js +154 -0
  508. package/node_modules/@engenty-wizards/shared/dist/wizard-package.d.ts +48 -0
  509. package/node_modules/@engenty-wizards/shared/dist/wizard-package.js +49 -0
  510. package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
  511. package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
  512. package/node_modules/@engenty-wizards/shared/package.json +10 -0
  513. package/package.json +77 -4
  514. package/plugin/.claude-plugin/plugin.json +9 -0
  515. package/plugin/.mcp.json +8 -0
  516. package/plugin/commands/wizard.md +8 -0
  517. package/plugin/skills/build-wizard/SKILL.md +27 -0
  518. package/plugin/skills/use-wizard/SKILL.md +18 -0
@@ -0,0 +1,433 @@
1
+ import { SURFACE_GUIDE } from "@engenty-wizards/shared/surface";
2
+ import { WIZARD_SCHEMA_URL } from "@engenty-wizards/shared/wizard-package";
3
+ import { sandboxGuideLine } from "../sandbox/index.js";
4
+ import { EXAMPLE_WIZARD } from "./example.js";
5
+ /**
6
+ * How a wizard is written down and what makes a good one. The studio's architect and the MCP
7
+ * tools hand the same text to whichever model authors the wizard.
8
+ */
9
+ export const SCHEMA_DOC = `
10
+ type Wizard = {
11
+ version: 1
12
+ title: string // short, what the end user gets ("Rechnung erstellen")
13
+ description: string // one sentence
14
+ avatar: "round"|"drop"|"dome"|"flame"|"oval"|"bean"|"pebble"|"sprout"|"tower"|"wedge" // the engenty mascot shown to end users
15
+ intro?: string // one friendly sentence above the first page
16
+ lang?: string // two-letter code of the language the wizard's texts are in ("en", "de", "it", "fr") — ALWAYS set it to the language you write them in
17
+ lists?: List[] // tabular data the wizard KEEPS between runs — separately for each person who runs it, or for all with "shared"
18
+ connections?: Connection[] // accounts the PERSON connects during a run (their mailbox); kept for their next run
19
+ steps: Step[] // run top to bottom; the LAST step is always a "result"
20
+ }
21
+
22
+ type List = {
23
+ id, title, description?,
24
+ key?: columnId // rows are matched on this column: saving a row with a known key updates that row
25
+ shared?: true // ONE list for every run (leads, sign-ups, bookings, a log) instead of one per person.
26
+ // The person running the wizard never sees it: no list field, review or deliverable of it;
27
+ // the admin sees and edits it in the studio under Space → Data
28
+ check?: { file?: columnId, status?: columnId }
29
+ // a review that shows the list lets the person go through it ROW BY ROW on a split screen:
30
+ // "file" = a text column holding the path of a kept file (PDF, photo), previewed beside the row;
31
+ // "status" = a select column whose options are the answer buttons (the FIRST option = not looked at yet)
32
+ columns: Column[] // { id (lowercase_slug), name (shown to the person), type, format?, required? }
33
+ }
34
+ // type "text": format? { style: "single"|"multiline" }
35
+ // type "number": format { style: "integer"|"decimal"|"percent"|"currency", currency?: "EUR" } // currency only with style "currency"
36
+ // type "date": format { kind: "date"|"datetime" } // values are YYYY-MM-DD
37
+ // type "select": format { options: { id, label }[], allowCustom: boolean }
38
+ // type "boolean"
39
+
40
+ type Connection =
41
+ | { id, kind: "mail", title?, description? }
42
+ // the person picks how to connect (Gmail, Outlook, or any mailbox over IMAP); steps only ever READ it
43
+ | { id, connector: connectorId, actions?: actionId[], policy?: { [actionId]: "allow"|"ask" }, title?, description? }
44
+ // connector = a service the wizard works in for the person: a built-in one (Gmail, Google Drive, Calendar and
45
+ // Contacts, Outlook, OneDrive, Slack, GitHub, HubSpot, S3) or one imported into the project from the
46
+ // integrations registry. The person connects their own account (OAuth or API key) on a page.
47
+ // kind "mail" reads any mailbox the same way and keeps attachments as files; use the gmail / outlook
48
+ // connectors only for what it cannot do (drafts, sending, labels, calendar).
49
+ // A step that lists the connection gets the connector's actions as tools named <toolPrefix>_<actionId>.
50
+ // actions: exactly the actions the wizard may use. Default: only those marked "read".
51
+ // policy: "allow" = runs without asking, "ask" = the person confirms each call first.
52
+ // Default: read → allow, write → ask. Deleting always asks. Set "allow" for an action marked
53
+ // "write" that in truth only looks something up (MCP servers often leave the mark out).
54
+
55
+ // Every step: { id (camelCase, unique), title, description?, next?: Branch[] }
56
+ // Branch = { when: Condition | Condition[], goto: stepId | "end", max? }
57
+ // | { ask: "a statement about the run", goto: stepId | "end", max? }
58
+ // | { goto: stepId | "end" } // otherwise: where the run goes when no other branch holds (one per step)
59
+ // ask: a decision reads the person's answers and what the steps made so far and takes the branch when the
60
+ // statement is true ("The person wants a refund, not an exchange"). All ask branches of a step are decided
61
+ // together in one cheap call, after no "when" branch matched; if none clearly holds the next step follows.
62
+ // Use ask where a rule on one field cannot say it; never one decision step per branch.
63
+ // max: how often the branch may be taken in one run. A branch BACK to an earlier step is a loop ("improve until
64
+ // the check passes": a decision step branches back to the writing step) — give it max (at most 10 without);
65
+ // the step that runs again sees what it made last time.
66
+ // Condition = { field, op: "equals"|"notEquals"|"in"|"notEmpty"|"empty"|"gt"|"lt"|"contains", value? }
67
+ // field is a page field id, an output field of this or an earlier agent step as "steps.<stepId>.<fieldId>",
68
+ // or how many rows a stored list has as "lists.<listId>.count"
69
+ // gt / lt compare numbers (value is a number); contains looks into a multiselect, a list output or a text;
70
+ // in takes a list of values. A list of conditions holds when every one holds.
71
+ // first matching branch wins, otherwise the step's "otherwise" branch, else the next step in the list.
72
+ // A step only some runs take sits right after the step that branches to it; that step's otherwise branch
73
+ // leads every other run past it, and the step itself goes on as the next in the list.
74
+
75
+ type PageStep = { type: "page", fields: Field[] (1–5 per page), groups?: { id, instructions, optional? }[], cta?: string }
76
+ // Decided fields: a field with ask: "statement" is shown when a decision finds the statement true of the run;
77
+ // fields with group: groupId are alternatives of which the decision shows one ("How should we reach the person?"),
78
+ // or none when the group is optional. Decided once as the run reaches the page. Such a page has up to 12 fields
79
+ // and shows at most 5. Use them where the earlier answers decide which question makes sense and no single field
80
+ // rule can say it; "when" stays the first choice.
81
+ type Field = {
82
+ id (camelCase, unique across the WHOLE wizard), label, kind, required?, placeholder?, help?,
83
+ options?: string[] // select / multiselect / slot
84
+ default?: string|number|boolean|string[]
85
+ columns?: { id, label, kind: "text"|"number"|"money" }[] // items only; row amount = product of number/money columns
86
+ vat?: { rate?: number, field?: fieldId } // items only; VAT % fixed or read from a field
87
+ currency?: "EUR"|... // items only
88
+ multiple?: boolean // image / file: several files, in the order the person puts them (they can drag them)
89
+ min?: number, max?: number // image / file with multiple: how many files at least / at most (up to 30). Set max wherever
90
+ // every file costs something later (a video clip per photo)
91
+ camera?: boolean // file: also offer the camera, for papers the person has not scanned (image always offers it)
92
+ video?: boolean // file: the camera also records a short clip (up to 30 s); the clip is a file like any other
93
+ listen?: boolean // file: a recording (video/audio) is listened to before the next step: {{field.speech}} gives what is
94
+ // said piece by piece between pauses, with exact times "[12.40–15.10] text" — to cut slips and pauses
95
+ scan?: boolean // text: a "scan" button fills it from a QR code or barcode (serial number, ticket, article number)
96
+ connection?: connectionId // kind "connection": the page shows "connect your account"; with required the person must connect
97
+ list?: listId // kind "list": the page shows that stored list for the person to check, correct and extend
98
+ prefill?: "steps.<id>.<key>" // what the field starts with, from an earlier step. An "items" field takes a table whose
99
+ // columns are exactly its column ids — the step proposes the positions, the person corrects them
100
+ when?: Condition | Condition[] // the field is shown only while this holds: it reads another field of the SAME page (decided as
101
+ // the person types) or anything known before the page (an earlier answer, steps.<id>.<field>).
102
+ // A hidden field is not required and not kept; its {{template}} is empty.
103
+ optionsFrom?: "steps.<id>.<key>" | "steps.<id>.<key>.<column>" | "lists.<id>.<column>"
104
+ // select / multiselect / slot: the choices come from earlier data — a "list" output, one column of a
105
+ // "table" output, or a column of a stored list. "options" stand in while that data is empty.
106
+ cards?: { label, value?, image?, subtitle?, meta?, link? }
107
+ // select / multiselect with optionsFrom "steps.<id>.<key>" naming a TABLE output: every row is a
108
+ // choice drawn as a card. Each entry names a column of that table: label (the title), value (what the
109
+ // answer holds, default the label — an id column when there is one), image (a URL or asset id),
110
+ // subtitle, meta (a price), link (a page "Details" opens). Products, places, candidates to pick.
111
+ }
112
+ // kinds: text textarea number select multiselect date email url toggle color image file items connection list
113
+ // location audio signature slot
114
+ // location: where the person is — the phone's position on a tap (with its accuracy), or an address they type.
115
+ // {{field}} → "Herrengasse 16, 8010 Graz (47.07071, 15.43950, ±12 m)" · {{field.lat}} {{field.lng}}
116
+ // {{field.accuracy}} (metres) · {{field.label}} (the address line) · {{field.map}} (a map link).
117
+ // A typed address has no lat/lng. Widgets take the numbers: data { lat: "place.lat", lng: "place.lng" }.
118
+ // audio: a voice note recorded on the page (up to 5 minutes). It is written down before the next step runs:
119
+ // {{field}} is what the person said, as text. {{field.seconds}} is its length.
120
+ // signature: drawn with the finger — a picture (dark ink, clear ground). A document step can place it:
121
+ // {{field}} → asset://ID, used as <img src="asset://ID">.
122
+ // slot: the person picks one appointment time, shown by day. Options are ISO 8601 date-times with their offset
123
+ // ("2026-10-12T09:00:00+02:00"), nearly always from optionsFrom; {{field}} is the chosen one, as offered.
124
+ // Booking: agent step "free" with call { tool: "appointments.availability", input: { duration_minutes: 30, days: 14 } }
125
+ // and output { format: "json", fields: [{ id: "slots", kind: "table", columns: ["start","end","label"] }] };
126
+ // then a page { kind: "slot", optionsFrom: "steps.free.slots.start" }; then an agent step with appointments.book.
127
+
128
+ type AgentStep = {
129
+ type: "agent"
130
+ instructions: string // the task, with {{templates}} ("" with call)
131
+ call?: { tool: "<plugin>.<tool>", input: { … } }
132
+ // NO MODEL: one plugin tool called once with this input; its answer IS the json output
133
+ // (fields name the keys later steps read). Use it where a model would only fetch and copy
134
+ // data (free appointment times) — it answers in a second instead of half a minute.
135
+ // String inputs are templates; a filled-in whole number or true/false is passed as one.
136
+ tools: ("web_search"|"web_fetch"|"browser"|"sandbox"|"image"|"http"|"pages")[]
137
+ mcp?: string[] // ids of the project's MCP servers this step may use
138
+ connections?: string[] // ids of wizard connections this step may read (mail → mail_search, mail_read, mail_save)
139
+ output: { format: "text"|"markdown"|"json", fields?: { id, kind: "text"|"number"|"list"|"table"|"yesno"|"choice"|"score", description, columns?: string[], options?: string[] }[], schema?: Schema, surface?: SurfaceComponent[] | true }
140
+ // "score" answers its description on the scale in options, lowest first ("low", "medium", "high")
141
+ // fields: one level of keys (the short form). schema: nested data, below. One of the two, not both.
142
+ each?: "steps.<id>.<key>" | "lists.<id>"
143
+ // ONE RUN PER ENTRY (at most 20): the rows of a table output, the entries of a list output, or the
144
+ // rows of a stored list; the instructions read {{item.<column>}}, {{index}}, {{count}}. The output is
145
+ // one table, steps.<id>.rows: the entry's columns plus the step's output fields, a row per entry.
146
+ // a table with columns gives rows as objects with exactly those keys — what widgets read
147
+ // "yesno" answers the question in its description with true/false; "choice" picks one of its options
148
+ model?: "classifier"|"standard"|"high"|"highest" // the kind of model, see "Models"; default "high"
149
+ effort?: "low"|"medium"|"high" // how hard it should think; leave out unless it matters
150
+ working?: string // shown while it runs ("Recherchiert im Web …")
151
+ }
152
+ // Every agent step also has, without listing them: list_read / list_write (the wizard's lists), files_list,
153
+ // read_document (PDF, scans and photos, Word, Excel, CSV, saved mails) and scan_documents (invoice / receipt fields, many at once)
154
+ // — on an installed client only where there is something to read: tools or connections, uploads, lists or kept files;
155
+ // and where the space has Knowledge: project_search (a question, "where" on its typed categories, hits checked for relevance),
156
+ // project_list (by categories), page_read / table_read / project_document (an item whole, by its path).
157
+ // "pages" brings: page_read / page_write — Markdown pages of the space the wizard keeps for every run (notes, a log
158
+ // that grows with append), shown to the admin under Space → Data; page_read also reads Knowledge by path.
159
+ // "browser" brings: browser_open/read/click/type/select/scroll/press/back/wait, browser_screenshot (the model looks at the page),
160
+ // browser_run_fast (a decision model clicks through a page's mechanical part, where one is reached),
161
+ // browser_request_credentials (the PERSON types a login into the page — the model never sees it; sign-ins can be remembered),
162
+ // browser_request_user (the person solves a captcha or "continue with Google" in the live page; they can also take the browser over any time),
163
+ // browser_download (keeps a file from a signed-in site).
164
+ // It clicks cookie banners away by itself with the least consent (only necessary / reject all) —
165
+ // no need to say so in the instructions.
166
+
167
+ type SurfaceStep = {
168
+ type: "surface"
169
+ components: SurfaceComponent[] // a view from the surface catalog (below), written once; every run brings new data
170
+ data: { [key]: "fieldId" | "steps.<id>" | "steps.<id>.<key>" | "lists.<id>" | "brand.name" | "today" }
171
+ // what the components read by path: {"path": "/<key>/..."}
172
+ // or instead of components — pieces a decision picks per run (no chart when there is nothing to chart):
173
+ candidates?: { id, description, components: SurfaceComponent[] (the first has the piece's id), group?, required? }[]
174
+ groups?: { id, instructions, optional? }[]
175
+ }
176
+ // SCHEMA (json only): nested data — lists of entries that hold lists of their own (days with meals, recipes with
177
+ // ingredients and steps). Its root is { kind: "object", label, fields: { <key>: Field } }; a Field is
178
+ // { kind: "text", label, description?, long?: true } long: paragraphs, not a line
179
+ // { kind: "number", label, description?, unit?: "Min" }
180
+ // { kind: "yesno", label, description?, yes?: "da", no?: "einkaufen" } (yes/no: the words people read)
181
+ // { kind: "choice", label, description?, options: string[] }
182
+ // { kind: "ref", label, description?, to: "<top-level list key>" } the id of an entry of that list; its entries
183
+ // need { id: { kind: "text" } }
184
+ // { kind: "list", label, description?, of: Field-without-list | { kind: "object", label, fields: { … } } }
185
+ // Labels are in the wizard's language: column heads, part titles, "add <label>" in the admin's editor. Description:
186
+ // what the model is to put there. Objects nest at most 4 deep (the root counted), at most 100 keys in all.
187
+ // The model gets it as a strict JSON Schema: every key is always filled.
188
+ // DESIGN THE VIEW FIRST, then the schema it needs: write output.surface (Tabs, Card, Fold, Group, Chips, Checklist,
189
+ // Steps, Link, Callout …) for what the person should see, then give the schema exactly the lists and keys that
190
+ // view binds — nothing it does not show or a later step does not read. One step returns the whole tree.
191
+ // Paths: {"path": "/recipes"} from the data; inside a repeated entry "title" or "meals" reads the entry; a Link's
192
+ // view reads the entry it opens. The view is checked against the schema.
193
+ // Later steps read top-level keys ({{steps.id.key}}, optionsFrom, each, conditions); a list of entries is a table
194
+ // there ("steps.id.recipes.title"). Downloads: xlsx one sheet per top-level list, csv the first list of flat
195
+ // entries, md and pdf the whole tree.
196
+ // Example (Kühlschrank-Koch): { kind: "object", label: "Menüplan", fields: {
197
+ // summary: { kind: "text", label: "Zusammenfassung", long: true },
198
+ // days: { kind: "list", label: "Tage", of: { kind: "object", label: "Tag", fields: {
199
+ // label: { kind: "text", label: "Tag" }, theme: { kind: "text", label: "Motto" },
200
+ // meals: { kind: "list", label: "Mahlzeiten", of: { kind: "object", label: "Mahlzeit", fields: {
201
+ // slot: { kind: "choice", label: "Mahlzeit", options: ["Frühstück", "Mittag", "Abend"] },
202
+ // recipe_id: { kind: "ref", label: "Rezept", to: "recipes" } } } } } } },
203
+ // recipes: { kind: "list", label: "Rezepte", of: { kind: "object", label: "Rezept", fields: {
204
+ // id: { kind: "text", label: "Kennung" }, title: { kind: "text", label: "Titel" },
205
+ // time_minutes: { kind: "number", label: "Zeit", unit: "Min" },
206
+ // steps: { kind: "list", label: "Zubereitung", of: { kind: "object", label: "Schritt", fields: {
207
+ // text: { kind: "text", label: "Schritt", long: true }, minutes: { kind: "number", label: "Dauer", unit: "Min" } } } } } } } } }
208
+ // with a view: Tabs over a Grid of day Cards (each meal a Link to its recipe) and a Grid of recipe Links whose
209
+ // view is a Card, a Fold of ingredients and the Steps.
210
+ // A SURFACE is a native view in the runner — facts, a list of results, key figures, a chart — themed, on phones, free per run.
211
+ // Prefer it to a widget for such views; a widget is for what the catalog cannot show (a map, an animation).
212
+ // An agent step with output.format "json" can also carry such a view of its own result: output.surface: [components],
213
+ // written once and bound to its fields or schema by path ({"path": "/<key>"}; a step with "each": "/rows"). Prefer it to
214
+ // output.surface: true, which has a model compose a new view on every run.
215
+ // Reviews and the result show a step's view instead of its plain table.
216
+ type GenerateStep = {
217
+ type: "generate"
218
+ asset: "image"|"video"|"voice"|"document"|"dashboard"
219
+ prompt: string // the brief, with {{templates}}; for "voice" the exact text that is read aloud
220
+ options?: { aspectRatio?: "1:1"|"16:9"|"9:16"|"4:5"|"3:2"|"2:3", duration?: 4–10 (video seconds; 4, 6 or 8 are safe),
221
+ resolution?: "720p"|"480p", // video: 720p by default and at most; 480p for drafts and many clips
222
+ style?: string, // image/video: the look · voice: how to speak ("ruhig, warm"; may name a field: "{{voiceStyle}}")
223
+ template?: "invoice"|"offer"|"briefing"|"letter"|"report"|"free" } // template for documents
224
+ referenceImage?: fieldId | stepId // the image the image/video starts from: an image field, or an earlier step that made images
225
+ each?: fieldId | stepId | "steps.<id>.<key>"
226
+ // image/video: ONE RESULT PER ENTRY (at most 8) — per upload of an image field (multiple), per image
227
+ // of an earlier step, or per row of an agent step's table. The prompt reads the row as
228
+ // {{item.<column>}} (plus {{index}}, {{count}}); referenceImage gives entry n its n-th image.
229
+ // With each the prompt goes to the model AS WRITTEN (no rewriting step): let the agent step
230
+ // that makes the table write complete visual descriptions.
231
+ // In a review the person can make single results again.
232
+ working?: string
233
+ }
234
+
235
+ type WidgetStep = {
236
+ type: "widget"
237
+ entry: string // workspace path of the widget's HTML, e.g. "weather/index.html"
238
+ data: { [key]: string } // what the widget gets as wizard.data: key → fieldId | steps.stepId | steps.stepId.key | brand.name | facts.key | today
239
+ sample?: string // workspace path of example data (same shape as data) for previews
240
+ layout?: "fixed"|"page" // fixed (default): drawn at size and scaled to the page — maps, charts, films.
241
+ // page: part of the run page, as wide as it and as tall as its content, never scaled —
242
+ // a result people scroll and use (a cook mode, a configurator, a planner)
243
+ size?: { width, height } // design size in px, default 1280×720 (9:16 → 1080×1920); exports render at it
244
+ video?: boolean // a FILM: the timeline is rendered to an MP4 WITH SOUND when the step runs; the person sees and
245
+ // downloads that video. data may then name generate steps: "steps.<id>" of an image / video / voice
246
+ // step arrives as a URL (a list of URLs for a step with "each").
247
+ // "steps.<agentStepId>.assets" gives the pictures an agent step kept (browser screenshots
248
+ // with save, export_file, generate_image) as { assetId: URL }; the step's JSON names them by id.
249
+ working?: string
250
+ }
251
+ // an interactive HTML app written ONCE into the workspace; every run only brings new data (no model call, no cost)
252
+
253
+ type FilmStep = {
254
+ type: "film"
255
+ brief: string // a template: what the film is — story, look, length, what to use. The kit carries the craft.
256
+ skills?: string[] // skill packages the client reads; default ["hyperframes"]. A workspace package: "skills/<name>" (has SKILL.md)
257
+ kit?: string // workspace path of a STYLE KIT (.zip): a showreel made once with its rules (frame.md),
258
+ // techniques (SHOWCASE.md), helpers and stills — the bar every film of this wizard reaches
259
+ inputs?: { [name]: string } // name (lowercase, -) → fieldId | steps.stepId: voice lines, pictures, uploads become files in
260
+ // input/<name>/, text in input/<name>.md, json in input/<name>.json
261
+ format?: "16:9" | "9:16" | "1:1"
262
+ seconds?: number // about how long
263
+ model?: "standard" | "high" // default standard
264
+ effort?: Effort
265
+ working?: string
266
+ }
267
+ // the AI client installed on the person's computer (Claude Code) writes the film as code in a folder of its own, with the
268
+ // skills, the kit, the space's brand (colours, logo, facts) and the inputs; it looks at its frames and fixes them; the
269
+ // runtime renders the MP4. It runs only where Claude Code is set up as the AI subscription — never on credits or in the
270
+ // cloud — and takes 10–40 minutes. Sounds come from a fixed catalog (CC0); voice comes from a generate voice step before it.
271
+
272
+ type ReviewStep = { type: "review", show: (stepId | "lists.<listId>")[], edit?: boolean, regenerate?: boolean }
273
+ // shows earlier outputs; the person accepts, edits text outputs (edit), or asks for a new version with a note (regenerate)
274
+ // a shown list is edited in place by the person
275
+
276
+ type ResultStep = { type: "result", message?: string, deliverables: { from: stepId | "lists.<listId>", label?, formats: Format[] }[] }
277
+ // formats per source: image→png · video→mp4 (several results: zip) · voice→mp3 · document→pdf docx html md png · dashboard→html pdf png
278
+ // film widget (video: true)→mp4 png · film→mp4
279
+ // widget→html png pdf mp4 json (mp4 only when the widget registers a timeline)
280
+ // agent text/markdown→md txt docx pdf html · agent json→json csv xlsx md (xlsx: one sheet per table)
281
+ // agent json with schema→json csv xlsx md pdf
282
+ // agent, any format→zip: the FILES the step kept with mail_save / browser_download
283
+ // lists.<id>→xlsx csv json md · zip (a list with check.file: the kept files its rows name, plus the list)
284
+
285
+ Templates (in instructions/prompt): {{fieldId}} · {{steps.stepId}} (whole output) · {{steps.stepId.key}} (json key)
286
+ · {{itemsField}} (line items as a table WITH computed net/VAT/total) · {{itemsField.net|vat|gross}} · {{today}}
287
+ · the project (its settings): {{brand.name}} {{brand.about}} {{brand.colors}} · {{facts.key}} (one fact: address, VAT ID, …) · {{facts}} (all facts)
288
+ — every AI step already knows them, name one only where the text must carry it; agent steps also search the space's Knowledge
289
+ and are told its categories: say in a step's instructions which category to filter by when the task names one
290
+ · {{lists.listId}} (the stored list as a table, as it is when the step starts) · {{fileField}} (the names of the uploads, for read_document)
291
+ · {{locationField}} {{locationField.lat|lng|accuracy|label|map}} · {{audioField}} (the transcript) · {{signatureField}} (asset://ID)
292
+ A template may only use fields asked and steps run EARLIER.`;
293
+ export const PRINCIPLES = `
294
+ How good wizards look:
295
+ - For non-technical end users. Plain words, friendly titles phrased as questions ("What is the post for?").
296
+ - The wizard speaks for itself: the first page invites in its own voice ("Show me your fridge."), every field's help says in
297
+ one line why it is asked ("For the amounts in the recipes"), every step that takes a while has a "working" line that
298
+ names what happens ("Looking into your fridge…"). Choices with up to five options are buttons, not a dropdown.
299
+ - The result is what people come for: design how it looks first, then the data it needs. A json step's result gets a view
300
+ (output.surface, written once) or a widget; give its data the fields only the view uses — a yes/no that picks a colour
301
+ ("in_fridge"), a key that groups ("category"), one human line (a summary, a tip, a theme per day) — and links instead of
302
+ copies (a meal names its recipe's id). Things are cards, ordered work is Steps, things to get or do are a Checklist;
303
+ never a table of things for a person — a table only for figures compared across columns (prices, dates).
304
+ - A page whose fields depend on an earlier answer uses "when" on its fields, never one copy of the page per answer and a branch to each copy. Choices that depend on what an earlier step found use "optionsFrom", never one page per possible result.
305
+ - Few pages, 1–5 fields each, one theme per page. Only ask what the result really needs; prefer selects with sensible defaults.
306
+ - Put a review step before anything expensive (video) and before anything written elsewhere (mail, CRM), so people can
307
+ correct or regenerate. A result people can simply make again needs no review before it.
308
+ - Money/totals: use an "items" field with vat — the runner computes totals; documents must use {{items}} verbatim. Never let a model compute totals.
309
+ - Facts from the web need an agent step with web_search + web_fetch BEFORE writing; documents then cite those notes.
310
+ - Live data with a free public JSON API (weather and wind: api.open-meteo.com; sunrise/sunset is in it too) → an agent step with the http tool and model "standard" that calls the API and returns json. Far cheaper and more exact than web research; use web research only when no API exists.
311
+ - Writing into other systems (CRM, database, spreadsheet, website): an agent step with the matching mcp server, http, or browser tool, preceded by a review step.
312
+ ${sandboxGuideLine()}
313
+ - Remembering between runs ("merke dir", "führe eine Liste"): declare a list and let an agent step save into it with list_write; a later run reads it as {{lists.id}} or list_read. Give it a key column so known rows are updated, not duplicated. Never make the person re-upload last time's result.
314
+ - Collecting from everyone who runs the wizard (requests, leads, sign-ups, feedback): a list with "shared": true, saved with list_write. It is the admin's, under Space → Data; never show one person's rows to another. Longer text for every run (a running summary, a log): the "pages" tool.
315
+ - The person's mail: one connection of kind "mail", a page field of kind "connection" early in the wizard, and the agent step lists it in "connections". Do not ask for the provider or the address in other fields — the connect field does that.
316
+ - Working in a service for the person (read their Notion, create an issue, look up a customer): import the service as a connector, declare a connection with "connector", put a page field of kind "connection" before the step, and list the connection in the step's "connections". Prefer a connector over the browser whenever the service has one.
317
+ - Logins on websites: never ask for passwords in page fields. An agent step with the browser tool asks the person at the moment it meets the login (browser_request_credentials); write that into its instructions, and that it must go on without the site when the person skips.
318
+ - Most people open a wizard on their phone. Keep pages short, and let the phone do the typing: photos with an "image" field (multiple) instead of descriptions, the place with a "location" field instead of an address form, what happened as an "audio" field instead of a long textarea (keep an optional textarea beside it), a sign-off as a "signature" field, a serial or ticket number as a "text" field with scan. Typical: damage report, handover protocol, site inspection, delivery note.
319
+ - How it runs: the first message may name the channels ("Läuft als: …" / "Runs as: …"); they are set already, never ask about them. A call, an SMS or WhatsApp asks by voice or text only: where one of them is named, keep each answer to text, a choice, a number or a date, and leave photos, files, signatures and maps to pages that only the browser shows (a call hands over a link by SMS).
320
+ - Photos in documents: a document step can place the photos of an earlier "image" field and a "signature" (it gets them as asset:// images); say in its prompt where they go.
321
+ - Pictures from the web (a listing's photos, a product shot an agent found): a document's <img src="https://…"> and image URLs in a widget's data (keys like image, photo, thumbnail, or a URL ending in .jpg/.png/.webp) are fetched once when the step runs and kept with the run — up to 40 per step. The page itself loads nothing from the network, so a URL left as is stays blank.
322
+ - Looking at photos: an agent step whose instructions name an image field ({{photos}}) gets up to 8 of its photos attached and sees them itself, in the person's order — do not tell it to call read_document for them. Photos in a "file" field, PDFs and scans are read with read_document / scan_documents.
323
+ - Papers and scans: a "file" field with multiple and camera. Agent steps read uploads with read_document; for invoices and receipts scan_documents returns the fields (vendor, number, date, totals, currency) exactly as printed.
324
+ - Collecting documents (invoices from mail or portals): the step keeps each file with mail_save / browser_download under a dated path ("invoices/2026-09/2026-09-03_Notion_INV-123.pdf"); its deliverable offers "zip". Split a big job into steps (mail, then statements, then portals) — one step manages about 60 tool calls.
325
+ - Going through documents one by one (receipts against payments): never one model step per document. One step reads them in batches (scan_documents takes 30 at once) and writes rows into a list with "check"; the review shows that list split-screen — the person answers each row beside its file, without any model call.
326
+ - Video that convinces is built in stages, each with its own review: idea and script (agent, json with a table of shots) → one still per shot (generate image with "each", starting from the person's product photo) → one clip per still (generate video with "each" and referenceImage = the stills step) → a voice-over (generate voice) → a film widget (video: true) that cuts clips, captions, voice and a closing card with the call to action. The starters "facebook-video-ad" and "property-film" carry such a widget (film/film.js) to copy. Offer a cheaper path without clips: the film animates the stills.
327
+ - Motion-graphics films (explainers, product spots, shorts) are a "film" step after the preparation, each with a review:
328
+ research and script (agent, high) → the voice-over (one generate voice step for the whole script; the film step finds the
329
+ word timings itself) → film (inputs: the voice, pictures, the script). The look comes from a style kit in the workspace (kit), so the film step stays on "standard".
330
+ - Prices come from a file the admin keeps in the workspace (a CSV price list): the agent step looks them up with read_workspace_file and proposes positions as a table; the next page shows them in an "items" field with "prefill" for the person to correct; the runner computes the totals.
331
+ - AI media is marked for you (EU AI Act, Art. 50): images, clips, voice-overs and films carry the marking in their file metadata, and the pages lay the EU's "AI" label over them. Never ask an image step to draw such a label into the picture. A film is different — it leaves the page as a video file, so its widget shows the EU label in the picture: wizard.ai tells a widget whether the run's media in its data is "generated" or "edited" (film/film.js draws the matching icon).
332
+ - Every step a person sees later (review/result) must come from an earlier step id.
333
+ - Write all wizard texts in the admin's language.`;
334
+ export const WIDGET_GUIDE = `
335
+ Widgets — when to use: the result must look the same every run, animate, or be explored (a map with
336
+ animated arrows, a timeline with a scrubber, a dashboard with filters, a configurator). Documents and
337
+ one-off pages stay "generate" steps. A widget is code in the wizard's WORKSPACE (files), written once:
338
+ - Files: "<widget>/index.html" (+ optional app.js, style.css), libraries under "lib/", reference data
339
+ (GeoJSON shapes, station lists, price lists) as JSON/CSV files, and "<widget>/sample.json" with
340
+ example data in exactly the shape of the step's data.
341
+ - Its data usually comes from an agent step with output.format "json"; give its table fields fixed
342
+ "columns" so rows have known keys, and write sample.json in that exact shape.
343
+ - NO NETWORK when it runs: no CDN, no fetch, no external fonts or images — everything is inlined.
344
+ Put libraries into the workspace (cdnjs.cloudflare.com, cdn.jsdelivr.net) and include them with
345
+ <script src="lib/name.min.js">. Fetch reference data ONCE now (e.g. lake outlines
346
+ from nominatim.openstreetmap.org/search?q=…&format=json&polygon_geojson=1&polygon_threshold=0.0005)
347
+ and save it as a workspace file.
348
+ - Runtime, window.wizard: data · brand {name, accent, logo, colors [{name, value}], facts {key: value}, theme} · ai "generated"|"edited"|null · mode "view"|"export" · file(path) ·
349
+ json(path) · url(path) (data URL for images/fonts) · ready() · timeline({ duration, seek, poster }) ·
350
+ state (what the person did last time, kept with the run) · save(state) (keep ticks, an open tab, a step reached: small JSON) ·
351
+ share(text) (the device's share sheet).
352
+ - layout "page": let the document grow with its content (no height: 100vh, no fixed body height) and lay out for phones
353
+ first; the page sets the frame's height from it. Keep what the person does with wizard.save and start from wizard.state.
354
+ - Animation: call wizard.timeline({ duration: seconds, seek: t => draw(t) }) and drive your own
355
+ play/pause and <input type=range> scrubber from it. seek(t) must draw time t synchronously — the MP4
356
+ export steps through it frame by frame. In mode "export" hide all controls and do not autoplay.
357
+ - A film (step.video): seek(t) may return a promise that resolves once the frame is drawn (set a clip's
358
+ currentTime, wait for "seeked", draw it to a canvas). Name the sound in the timeline:
359
+ audio: [{ src, start, duration?, from?, volume? }] with the URLs from wizard.data (the voice-over, the
360
+ clips themselves for their own sound; up to 48 tracks). "from" is the second of the source a track
361
+ plays from — a recording cut into pieces names one track per piece. Clips and images of the run
362
+ arrive as URLs, not inlined.
363
+ - Call wizard.ready() once the first frame is drawn. Lay out for the step's size and scale to fit
364
+ the window on every "resize" event — the window can be 0×0 when your script first runs.
365
+ - Plain HTML/CSS/JS, SVG or canvas. Take the look from wizard.brand.theme: accent for actions, second for meaning (done,
366
+ there, a tip), background for the ground, display for headings, body for text (system fonts behind them); dark: a dark
367
+ ground. Cards for things, generous spacing, legible labels; no table of things.
368
+ - After writing, ALWAYS run check_widget, read its errors and look at the screenshot; fix until clean.`;
369
+ export function connectorsLine(connectors) {
370
+ const lines = connectors.map((c) => {
371
+ const actions = c.actions
372
+ .slice(0, 40)
373
+ .map((a) => `${a.id}${a.group === "read" ? "" : ` (${a.group})`}`)
374
+ .join(", ");
375
+ const more = c.actions.length > 40 ? `, … ${c.actions.length - 40} more (list_connectors)` : "";
376
+ const state = c.usable
377
+ ? ""
378
+ : " — NOT SET UP on this server: tell the admin before you build on it";
379
+ return `- ${c.id} — ${c.name}${state}, tools ${c.toolPrefix}_*: ${actions || "actions appear once an account is connected"}${more}`;
380
+ });
381
+ return `Connectors a wizard of this project can use (built in, or imported from the integrations registry; find more with find_connectors + import_connector):\n${lines.join("\n")}`;
382
+ }
383
+ /** The tools this app's plugins add; nothing where there are none. */
384
+ export function pluginToolsLine(tools) {
385
+ if (!tools.length) {
386
+ return "";
387
+ }
388
+ const lines = tools.map((t) => `- ${t.id} — ${t.description}`);
389
+ return `\n\nTools of this app's plugins. An agent step lists one in "tools" by its full id, next to the built-in ones; a wizard that uses one runs only where that plugin is installed:\n${lines.join("\n")}`;
390
+ }
391
+ export function mcpServersLine(mcp) {
392
+ return `Project MCP servers available to agent steps: ${mcp.length ? mcp.map((m) => `${m.id} (${m.name})`).join(", ") : "none — if the admin wants to write into an external system that needs one, build the step with http or browser, and tell them they can connect a server in the project settings"}.`;
393
+ }
394
+ export function exampleWizard() {
395
+ return JSON.stringify(EXAMPLE_WIZARD, null, 2);
396
+ }
397
+ /** The guide an MCP client reads before it writes a wizard. */
398
+ export function authoringGuide(mcp, connectors = [], pluginTools = []) {
399
+ return `engenty wizards: a wizard is a page-by-page flow an end user walks through on a shared link. Pages ask questions; AI steps research, write, draw images, render video, build documents and dashboards, or write into other systems. You author the wizard as JSON; the person who asked you is the ADMIN, the people who later open the link are END USERS.
400
+
401
+ ${SCHEMA_DOC}
402
+ ${PRINCIPLES}
403
+ ${WIDGET_GUIDE}
404
+
405
+ Surface catalog (for surface steps and output.surface):
406
+ ${SURFACE_GUIDE}
407
+
408
+ ${mcpServersLine(mcp)}
409
+
410
+ ${connectorsLine(connectors)}${pluginToolsLine(pluginTools)}
411
+
412
+ Models: a step names the KIND of model it needs, never a model. Pick the cheapest class that does the job:
413
+ - "classifier": routing, yes/no, picking from options, pulling a few values out of text.
414
+ A DECISION is a "classifier" step with no tools whose json output has only "yesno", "choice" and "score" fields: it is answered in one fast, very cheap call. A branch can also read how sure it is: "steps.<id>.<field>.p" is the probability of its answer (a number 0–1; 1 or 0 where no decision model is set up), e.g. { field: "steps.check.urgent.p", op: "gt", value: 0.8 }. Write the question into each field's description, give the step everything it must judge in its instructions via {{templates}}, and branch on the answer with "next" (e.g. { when: { field: "steps.check.refund", op: "equals", value: true }, goto: "refund" }).
415
+ - "standard": short copy, calling an API, reformatting, simple summaries.
416
+ - "high": research with tools, long documents, reasoning over many sources (the default).
417
+ - "highest": hard reasoning or writing code; rare in a run, several times the cost of "high".
418
+ "effort" ("low" | "medium" | "high") tells the model how hard to think where it can be told; leave it out unless a step is clearly trivial ("low") or clearly hard ("high").
419
+ A generate step for a document or dashboard takes the same "model" (default "high"). Image and video steps use the image and video class; which model serves a class is set by the platform, not in the wizard.
420
+
421
+ Editing:
422
+ - Every write returns the new "revision" and the validator's "issues". Pass the revision you last saw as "baseRevision"; on revision_conflict re-read with get_wizard and apply your change again.
423
+ - Prefer edit_wizard with small ops; use replace_wizard only to rewrite most of the wizard.
424
+ - A draft may have issues while you work. publish_wizard and start_test_run refuse until there are none.
425
+ - Put a short "note" on writes (what changed, in the admin's language) — the admin sees it in the studio.
426
+ - A wizard written as a file instead (a .wizard package, its wizard.json, or the JSON alone) follows the JSON Schema at ${WIZARD_SCHEMA_URL}; \`wizards validate <path>\` checks it as the import does.
427
+ - Test runs and published runs spend the admin's credits (research ~150, video ~250, short copy with an image ~15).
428
+
429
+ Example of a complete wizard:
430
+ \`\`\`json
431
+ ${exampleWizard()}
432
+ \`\`\``;
433
+ }
@@ -0,0 +1,117 @@
1
+ import { ENGENTY_KINDS } from "@engenty-wizards/shared/definition";
2
+ import { z } from "zod";
3
+ const position = {
4
+ /** Place the step directly before this step id. */
5
+ before: z.string().optional(),
6
+ /** Place the step directly after this step id. */
7
+ after: z.string().optional(),
8
+ };
9
+ export const wizardOpSchema = z.discriminatedUnion("op", [
10
+ z.object({
11
+ op: z.literal("set_meta"),
12
+ title: z.string().min(1).optional(),
13
+ description: z.string().optional(),
14
+ avatar: z.enum(ENGENTY_KINDS).optional(),
15
+ /** null removes the intro. */
16
+ intro: z.string().nullable().optional(),
17
+ }),
18
+ z.object({
19
+ op: z.literal("upsert_step"),
20
+ /** The complete step. Replaces the step with the same id, otherwise inserts it. */
21
+ step: z.looseObject({ id: z.string(), type: z.string() }),
22
+ ...position,
23
+ }),
24
+ /** The wizard's lists, all of them: what it keeps between runs. An empty array removes them. */
25
+ z.object({ op: z.literal("set_lists"), lists: z.array(z.looseObject({ id: z.string() })) }),
26
+ /** The wizard's connections, all of them: accounts the person connects. */
27
+ z.object({
28
+ op: z.literal("set_connections"),
29
+ connections: z.array(z.looseObject({ id: z.string() })),
30
+ }),
31
+ z.object({ op: z.literal("remove_step"), stepId: z.string() }),
32
+ z.object({ op: z.literal("move_step"), stepId: z.string(), ...position }),
33
+ ]);
34
+ export class OpError extends Error {
35
+ }
36
+ function anchorIndex(steps, op, at) {
37
+ if (op.before && op.after) {
38
+ throw new OpError(`${at}: give "before" or "after", not both.`);
39
+ }
40
+ const ref = op.before ?? op.after;
41
+ if (!ref) {
42
+ return null;
43
+ }
44
+ const i = steps.findIndex((s) => s.id === ref);
45
+ if (i === -1) {
46
+ throw new OpError(`${at}: there is no step "${ref}".`);
47
+ }
48
+ return op.before ? i : i + 1;
49
+ }
50
+ /**
51
+ * Applies ops in order to a copy of the draft. The result is checked against the schema by the
52
+ * caller; here only the ops themselves can fail (unknown step, both anchors).
53
+ */
54
+ export function applyOps(def, ops) {
55
+ const next = structuredClone(def);
56
+ ops.forEach((op, n) => {
57
+ const at = `op ${n + 1} (${op.op})`;
58
+ const steps = next.steps;
59
+ switch (op.op) {
60
+ case "set_meta": {
61
+ const { op: _, intro, ...meta } = op;
62
+ Object.assign(next, Object.fromEntries(Object.entries(meta).filter(([, v]) => v !== undefined)));
63
+ if (intro === null) {
64
+ delete next.intro;
65
+ }
66
+ else if (intro !== undefined) {
67
+ next.intro = intro;
68
+ }
69
+ return;
70
+ }
71
+ case "set_lists":
72
+ Object.assign(next, { lists: op.lists.length ? op.lists : undefined });
73
+ return;
74
+ case "set_connections":
75
+ Object.assign(next, { connections: op.connections.length ? op.connections : undefined });
76
+ return;
77
+ case "upsert_step": {
78
+ const existing = steps.findIndex((s) => s.id === op.step.id);
79
+ const anchor = anchorIndex(steps, op, at);
80
+ if (existing !== -1 && anchor === null) {
81
+ steps[existing] = op.step;
82
+ return;
83
+ }
84
+ if (existing !== -1) {
85
+ steps.splice(existing, 1);
86
+ }
87
+ const target = anchorIndex(steps, op, at);
88
+ // New steps go before the closing result step unless placed explicitly.
89
+ const last = steps.length - 1;
90
+ const fallback = last >= 0 && steps[last].type === "result" ? last : steps.length;
91
+ steps.splice(target ?? fallback, 0, op.step);
92
+ return;
93
+ }
94
+ case "remove_step": {
95
+ const i = steps.findIndex((s) => s.id === op.stepId);
96
+ if (i === -1) {
97
+ throw new OpError(`${at}: there is no step "${op.stepId}".`);
98
+ }
99
+ steps.splice(i, 1);
100
+ return;
101
+ }
102
+ case "move_step": {
103
+ const i = steps.findIndex((s) => s.id === op.stepId);
104
+ if (i === -1) {
105
+ throw new OpError(`${at}: there is no step "${op.stepId}".`);
106
+ }
107
+ if (!op.before && !op.after) {
108
+ throw new OpError(`${at}: give "before" or "after".`);
109
+ }
110
+ const [step] = steps.splice(i, 1);
111
+ steps.splice(anchorIndex(steps, op, at), 0, step);
112
+ return;
113
+ }
114
+ }
115
+ });
116
+ return next;
117
+ }