@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,70 @@
1
+ ---
2
+ title: Starters
3
+ description: Wizards a plugin brings as templates – how to register one, where it shows, and what a wizard made from it gets.
4
+ version: 0.5.0
5
+ ---
6
+
7
+ A starter is a wizard a plugin brings as a template. For the tenants that have the plugin, it
8
+ stands beside the marketplace’s templates wherever a wizard is made.
9
+
10
+ ```ts
11
+ import { readFileSync } from "node:fs";
12
+
13
+ const read = (path: string) => readFileSync(wizards.resolvePath(path), "utf8");
14
+
15
+ server.registerStarter({
16
+ id: "follow-up",
17
+ title: "Follow up a contact",
18
+ description: "Looks the person up and drafts a follow-up email.",
19
+ language: "en",
20
+ definition: JSON.parse(read("starters/follow-up.json")),
21
+ files: { "widget/card.html": read("starters/card.html") },
22
+ });
23
+ ```
24
+
25
+ | Field | |
26
+ |---|---|
27
+ | `id` | Lower case, digits and `-`, starting with a letter, at most 40 characters. Unique in the plugin |
28
+ | `title` | What the list of templates calls it |
29
+ | `description` | What it makes, in one or two sentences. Shown under the title |
30
+ | `language` | `"de"` or `"en"`, the language its texts are in. Default: `"en"` |
31
+ | `definition` | A complete wizard definition: the JSON the studio keeps and `get_authoring_guide` describes |
32
+ | `files` | Files of the wizard’s workspace by path: widgets, sample data. A string is written as UTF-8, a `Uint8Array` as it is |
33
+
34
+ ## Checked when it is registered
35
+
36
+ The definition is read as a wizard when `registerStarter` is called. A starter that is not a
37
+ valid wizard, an id that is not allowed and an id registered twice all throw, and the plugin does
38
+ not load. The error names the starter:
39
+
40
+ ```
41
+ Starter "follow-up": steps.2.fields: …
42
+ ```
43
+
44
+ ## Where it shows
45
+
46
+ The starter is known as `<plugin id>.<starter id>`: `contacts.follow-up`. A marketplace entry’s id
47
+ has no dot, so the two never clash.
48
+
49
+ | Where | |
50
+ |---|---|
51
+ | New wizard in the studio | First among the gallery’s templates, and under “Similar wizards” when the wish someone types comes close to it. Its card shows the plugin’s name. It cannot be starred: it is always there, also without a connection |
52
+ | `GET /api/studio/marketplace` | First on the first page, with `plugin: { id, name }` |
53
+ | MCP `list_starters`, `get_starter`, `create_wizard` | Listed first with `plugin`; `starterId` takes its id |
54
+ | `GET /api/v1/templates`, for programs with a key | First, with `plugin`; `POST /api/v1/wizards` takes its id as `starterId` |
55
+
56
+ Only the tenants that have the plugin see it, by the same rule as its tools
57
+ ([Which tenant has a plugin](./shipping.md#which-tenant-has-a-plugin)). A search finds it by its
58
+ title, its description and the plugin’s name.
59
+
60
+ A marketplace entry can stand for a plugin’s starter. Where the tenant has that plugin, the
61
+ entry is left out and the plugin’s own starter is listed. Where it doesn’t, the entry is marked
62
+ Pro with the plugins it needs, and a wizard cannot be made from it.
63
+
64
+ ## A wizard made from it
65
+
66
+ - gets a copy of the definition and the files. Later changes to the starter do not reach it.
67
+ - keeps the starter’s id in `starter`. `starterRevision` stays empty: the starter changes with
68
+ the plugin’s version, not with a revision of its own.
69
+ - is written in the starter’s `language`, whatever language the person asked for.
70
+ - is not counted at the marketplace.
@@ -0,0 +1,363 @@
1
+ ---
2
+ title: The studio half
3
+ description: Pages, icons in the app bar, sections of the settings and of the space page – written in React, built once, drawn inside the studio.
4
+ version: 0.5.0
5
+ ---
6
+
7
+ The studio half is `ui/plugin.tsx`. Its default export is a function; the studio calls it after
8
+ sign-in and hands it `studio`. What the plugin draws is part of the studio: the same React, the
9
+ same router, the same components.
10
+
11
+ ```tsx
12
+ import { defineStudioPlugin } from "@engenty/wizards/plugin/studio";
13
+ import { Button, Card, Empty, Spinner } from "@engenty-wizards/web/ui";
14
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
15
+ import { Users } from "lucide-react";
16
+
17
+ interface Person {
18
+ id: number;
19
+ email: string;
20
+ name: string | null;
21
+ wizard: string;
22
+ }
23
+
24
+ const messages = {
25
+ de: {
26
+ title: "Kontakte",
27
+ hint: "Wer einen Wizard bis zum Ende durchlaufen hat.",
28
+ empty: "Noch keine Kontakte.",
29
+ remove: "Entfernen",
30
+ },
31
+ en: {
32
+ title: "Contacts",
33
+ hint: "Everyone who ran a wizard to its end.",
34
+ empty: "No contacts yet.",
35
+ remove: "Remove",
36
+ },
37
+ };
38
+
39
+ export default defineStudioPlugin((studio) => {
40
+ const t = studio.i18n.register(messages);
41
+
42
+ function ContactsPage() {
43
+ const list = useQuery({
44
+ queryKey: ["contacts"],
45
+ queryFn: () => studio.api.get<{ contacts: Person[] }>("/"),
46
+ });
47
+ const cache = useQueryClient();
48
+ const remove = useMutation({
49
+ mutationFn: (id: number) => studio.api.del(`/${id}`),
50
+ onSuccess: () => cache.invalidateQueries({ queryKey: ["contacts"] }),
51
+ });
52
+ const admin = studio.me().tenant.role !== "member";
53
+ return (
54
+ <div>
55
+ <h1 className="font-display font-semibold text-[1.75rem] tracking-tight">{t("title")}</h1>
56
+ <p className="mt-1 text-[0.9375rem] text-ink-3">{t("hint")}</p>
57
+ <div className="mt-8 flex flex-col gap-2">
58
+ {list.isLoading ? <Spinner className="mx-auto" /> : null}
59
+ {list.data && !list.data.contacts.length ? <Empty>{t("empty")}</Empty> : null}
60
+ {list.data?.contacts.map((person) => (
61
+ <Card key={person.id} className="flex items-center gap-3 px-5 py-3.5">
62
+ <span className="min-w-0 flex-1 truncate font-medium text-[0.9375rem]">
63
+ {person.name ?? person.email}
64
+ </span>
65
+ <span className="text-[0.8125rem] text-ink-3 max-sm:hidden">{person.wizard}</span>
66
+ {admin ? (
67
+ <Button variant="ghost" size="sm" onClick={() => remove.mutate(person.id)}>
68
+ {t("remove")}
69
+ </Button>
70
+ ) : null}
71
+ </Card>
72
+ ))}
73
+ </div>
74
+ </div>
75
+ );
76
+ }
77
+
78
+ studio.registerPage({ path: "/contacts", component: ContactsPage });
79
+ studio.registerNav({ to: "/contacts", label: () => t("title"), icon: Users });
80
+ });
81
+ ```
82
+
83
+ ## What it registers
84
+
85
+ | Call | Adds |
86
+ |---|---|
87
+ | `studio.registerPage({ path, component, wide? })` | A page of the studio at `/studio<path>`, inside the studio’s frame. `path` takes `:name` parts. `wide`: the page lays out its own columns and takes the screen’s width |
88
+ | `studio.registerNav({ to, label, icon })` | An icon in the app bar that opens a page |
89
+ | `studio.registerSettingsSection({ id, label, icon, component, menu? })` | A section of the settings at `/studio/settings/<id>`. `menu`: the user menu links to it directly |
90
+ | `studio.registerSpaceSection({ id, group?, label, hint?, component })` | A section of a part of the space page at `/studio/space/<group>#<id>`, below the part’s own. See [The space](#the-space) |
91
+ | `studio.registerSpacePart({ id, label, icon, after?, component })` | A part of the space page of the plugin’s own, at `/studio/space/<id>`. See [A part of the plugin’s own](#a-part-of-the-plugins-own) |
92
+ | `studio.registerShareSection({ runner, component })` | A runner’s own settings for a wizard (a keyword), under the share dialog’s gear once the runner is on and set up. See [Runners](./runners.md#the-runners-part-of-the-share-dialog) |
93
+ | `studio.registerShareSetup({ runner, title, component, notice? })` | What “Set up” in the runner’s row opens: a view inside the share dialog, with its buttons at the dialog’s foot, and a banner of the runner’s news. See [Runners](./runners.md#setting-up-inside-the-dialog) |
94
+ | `studio.registerAssistantCard({ tool, component })` | A card in the assistant’s chat for what a tool of the server half returned. See [The space](./space.md#a-card-in-the-chat) |
95
+
96
+ - The studio’s own addresses are taken: `/new`, `/edit`, `/settings`, `/space`, `/setup`,
97
+ `/sign-in`.
98
+ - The settings’ own sections are taken as ids: `account`, `team`, `connectors`, `models`,
99
+ `integrate` and `plugins`.
100
+ - `label` is a function, since the language can change while the studio is open.
101
+ - `icon` is a component that takes `className`: any icon of `lucide-react`.
102
+
103
+ A settings section draws its own heading and cards:
104
+
105
+ ```tsx
106
+ function ContactsSettings() {
107
+ return (
108
+ <section className="flex flex-col gap-2.5">
109
+ <h2 className="px-1 font-display font-semibold text-lg leading-tight">{t("title")}</h2>
110
+ <Card className="p-5 text-[0.875rem] text-ink-2">…</Card>
111
+ </section>
112
+ );
113
+ }
114
+
115
+ studio.registerSettingsSection({
116
+ id: "contacts",
117
+ label: () => t("title"),
118
+ icon: Users,
119
+ component: ContactsSettings,
120
+ });
121
+ ```
122
+
123
+ ## The space
124
+
125
+ A space holds what all its wizards share: a title, logos, colours, facts and Knowledge. The
126
+ space page, behind the house icon (Space) in the app bar, shows them in four parts:
127
+
128
+ | Part | `group` | Holds |
129
+ |---|---|---|
130
+ | Info & brand | `info` | Basics, Facts, Logos, Colours, Brand assets |
131
+ | Knowledge | `knowledge` | Documents, pages, tables and files with their categories: what every AI step looks things up in |
132
+ | Data | `data` | What the wizards keep |
133
+ | Results | `results` | The runs that reached their result |
134
+
135
+ A plugin adds a section to one of them, below the part’s own:
136
+
137
+ ```tsx
138
+ function ContactsOfSpace() {
139
+ const space = studio.useSpace();
140
+ const list = useQuery({
141
+ queryKey: ["contacts", space?.id],
142
+ queryFn: () => studio.api.get<{ contacts: Person[] }>(`/?space=${space?.id}`),
143
+ enabled: Boolean(space),
144
+ });
145
+ return <Card className="p-5 text-[0.875rem] text-ink-2">…</Card>;
146
+ }
147
+
148
+ studio.registerSpaceSection({
149
+ id: "contacts",
150
+ group: "data",
151
+ label: () => t("title"),
152
+ hint: () => t("hint"),
153
+ component: ContactsOfSpace,
154
+ });
155
+ ```
156
+
157
+ - `group` is the part; without one the section stands under Knowledge.
158
+ - The studio draws the heading and the hint above the section, as it does for the space’s own,
159
+ and lists the section in the part’s menu under the plugin’s name. The component draws the
160
+ rest, usually a `Card`.
161
+ - `id` is the section’s anchor: `/studio/space/data#contacts` opens the page there, and so does
162
+ `/studio/space#contacts`. In Knowledge a section is a page of its own:
163
+ `/studio/space/knowledge?show=s:<id>`, where `#<id>` leads too. Ids are unique on the whole
164
+ page; the space’s own are taken: `base`, `facts`, `logos`, `colors`, `typography`, `assets`,
165
+ `documents`.
166
+ - `studio.useSpace()` is a hook: `{ id, name, readOnly, brand }`, or `null` while there is none.
167
+ A component that calls it draws again when the person picks another space, or changes its
168
+ brand. `readOnly`: the space is edited in engenty wizards on a computer and only shown here,
169
+ or nothing is built on this runtime. Show it, but change nothing. `brand` is what Info & brand
170
+ holds of the look: `name`, `colors` (`{ name, value }`, the first is the accent) and `fonts`
171
+ (`{ family, role, weights }`).
172
+ - Every wizard belongs to a space: a [run event](./events.md) names it as
173
+ `wizard.projectId`. Keep it with what the plugin stores to show a space’s part of it.
174
+
175
+ ### A part of the plugin’s own
176
+
177
+ A plugin whose subject is as big as one of the parts adds a part of its own: an entry in the
178
+ parts’ menu, with a page at `/studio/space/<id>` that the plugin draws whole. The part’s menu
179
+ lists what the page holds; `studio.useSpaceMenu` fills it while the page is drawn.
180
+
181
+ ```tsx
182
+ function Library() {
183
+ const space = studio.useSpace();
184
+ const sections = useSections(space?.id);
185
+ studio.useSpaceMenu(sections.map((s) => ({ id: s.id, label: s.title, icon: Component })));
186
+ return sections.map((s) => (
187
+ <Anchor key={s.id} id={s.id}>
188
+ <Section title={s.title}>…</Section>
189
+ </Anchor>
190
+ ));
191
+ }
192
+
193
+ studio.registerSpacePart({
194
+ id: "library",
195
+ label: () => t("title"),
196
+ icon: Blocks,
197
+ after: "info",
198
+ component: Library,
199
+ });
200
+ ```
201
+
202
+ - `id` is the address: `/studio/space/library`. The parts’ own (`info`, `knowledge`, `data`,
203
+ `results`) are taken.
204
+ - `after` is the part it follows in the menu: `info`, `knowledge` or `data` (default).
205
+ - Each entry of `useSpaceMenu` jumps to the element with its `id` in what the part draws, and
206
+ the menu marks the one in view. `Anchor` and `Section` draw them as the space’s own parts do.
207
+ - The component is drawn again for another space: keep the space’s data under its id.
208
+
209
+ ## Words in two languages
210
+
211
+ The studio speaks German and English. `studio.i18n.register` takes the plugin’s words and gives
212
+ the function that reads them in the language in effect:
213
+
214
+ ```ts
215
+ const t = studio.i18n.register({
216
+ de: { count: "{n} Kontakte sind gespeichert." },
217
+ en: { count: "{n} contacts are kept." },
218
+ });
219
+
220
+ t("count", { n: 12 });
221
+ ```
222
+
223
+ - `de` is the source: a key missing in `en` shows the German, so give every key in both.
224
+ - `{name}` in a text is filled from the second argument.
225
+ - `studio.i18n.lang()` is `"de"` or `"en"`, for dates and numbers:
226
+ `new Date(at).toLocaleString(studio.i18n.lang())`.
227
+
228
+ ## The plugin’s own routes
229
+
230
+ `studio.api` calls the routes the server half registered, signed in as the person:
231
+
232
+ | Call | Asks |
233
+ |---|---|
234
+ | `studio.api.get<T>(path)` | `GET /api/studio/plugins/<id><path>` |
235
+ | `studio.api.post<T>(path, body?)` | `POST`, the body as JSON |
236
+ | `studio.api.put<T>(path, body?)`, `studio.api.patch<T>(path, body?)` | `PUT`, `PATCH` |
237
+ | `studio.api.del<T>(path)` | `DELETE` |
238
+
239
+ Each gives the parsed JSON. Use them with `useQuery` and `useMutation`, as the page above does.
240
+
241
+ ## The person
242
+
243
+ `studio.me()` is the signed-in person:
244
+
245
+ | | |
246
+ |---|---|
247
+ | `user` | `{ id, name, email }` |
248
+ | `tenant` | `{ id, role }`, the role `owner`, `admin` or `member` |
249
+ | `mode` | `"local"`: the runtime runs alone. `"managed"`: on engenty.ai |
250
+
251
+ Hide what a member may not do, and guard it on the server too with `role: "admin"` on the
252
+ route.
253
+
254
+ `studio.plugin` is the plugin itself: `{ id, name, version }`.
255
+
256
+ ## Where the page stands
257
+
258
+ The top bar shows a trail after the space’s name. `studio.useCrumbs` is a hook that sets it
259
+ while the page is shown, in place of a heading of the page’s own:
260
+
261
+ ```tsx
262
+ studio.useCrumbs([{ label: t("title"), to: "/contacts" }, { label: person.name ?? person.email }]);
263
+ ```
264
+
265
+ - Each step is `{ label, to? }`; the last one is the page itself. A phone does not show the trail.
266
+ - The assistant names the page by its trail.
267
+
268
+ ## A page with a menu
269
+
270
+ A page with parts of its own puts its menu where the studio’s own pages put theirs. `MenuPage`
271
+ from `@engenty-wizards/web/ui` draws the menu in the studio’s sidebar while that is open, and at
272
+ the page’s left otherwise, so there is only ever one menu at the left. `PageMenu` draws the menu
273
+ as the settings do: a list with one level below it, and tabs on a phone.
274
+
275
+ ```tsx
276
+ import { MenuPage, PageMenu } from "@engenty-wizards/web/ui";
277
+ import { useParams } from "react-router";
278
+
279
+ function ContactsPage() {
280
+ const { tab = "all" } = useParams();
281
+ return (
282
+ <MenuPage
283
+ menu={
284
+ <PageMenu
285
+ title={t("title")}
286
+ current={tab}
287
+ entries={[
288
+ { id: "all", label: t("all"), to: "/contacts/all" },
289
+ { id: "new", label: t("new"), to: "/contacts/new" },
290
+ ]}
291
+ />
292
+ }
293
+ >
294
+ <ContactList tab={tab} />
295
+ </MenuPage>
296
+ );
297
+ }
298
+ ```
299
+
300
+ - An entry is `{ id, label, icon?, to, entries? }`; `entries` is the level below.
301
+ - `current` is the id of the entry shown, at either level.
302
+
303
+ ## The assistant
304
+
305
+ The studio’s assistant stands on a plugin’s pages too. `studio.Assistant`,
306
+ `studio.useAssistantPage` and `studio.useAssistantTool` tell it what to say there, what the page
307
+ shows and what it may do in it. See [The space](./space.md#the-assistant-on-the-plugins-own-page).
308
+
309
+ For now the studio shows its assistant only where it is switched on, and it is off by default.
310
+ While it is off, these calls do no harm and nobody sees what they say.
311
+
312
+ ## Build it
313
+
314
+ The studio half is built to two files, `dist/client.js` and `dist/client.css`. The build needs
315
+ a checkout of the repository, since it uses the studio’s own tools:
316
+
317
+ ```bash
318
+ node scripts/build-plugin.mjs <plugin folder>
319
+ ```
320
+
321
+ ```bash
322
+ node scripts/build-plugin.mjs <plugin folder> --watch
323
+ ```
324
+
325
+ The plugin’s folder may be anywhere, also outside the checkout. With `--watch` the files are
326
+ built again on every save, and an open studio takes them in place.
327
+
328
+ Ship `dist/` with the plugin: an install without a checkout cannot build it.
329
+
330
+ ## What the studio shares
331
+
332
+ These imports are not in `client.js`. The script takes them from the studio that loads it, so
333
+ there is one React and one router on the page:
334
+
335
+ | Import | What a plugin gets of it |
336
+ |---|---|
337
+ | `react`, `react/jsx-runtime` | All of it |
338
+ | `react-dom` | `createPortal`, `flushSync` |
339
+ | `react-router` | `Link`, `NavLink`, `Navigate`, `useNavigate`, `useParams`, `useLocation`, `useSearchParams` |
340
+ | `@tanstack/react-query` | `useQuery`, `useMutation`, `useQueryClient` |
341
+ | `@engenty-wizards/web/ui` | The studio’s components, see [Styles and components](./styling.md) |
342
+ | `@engenty/wizards/plugin/studio` | `defineStudioPlugin` and the types |
343
+
344
+ Everything else a plugin imports is bundled into `client.js`. A package the plugin’s folder
345
+ does not have, such as `lucide-react`, comes from the studio’s.
346
+
347
+ ## Undo on reload
348
+
349
+ The studio half loads again when its built files change. Pages, icons and sections, also those
350
+ of the space page, are taken back for it. Anything else it started, it undoes itself:
351
+
352
+ ```ts
353
+ const timer = setInterval(refresh, 30_000);
354
+ studio.onUnload(() => clearInterval(timer));
355
+ ```
356
+
357
+ ## When it fails
358
+
359
+ - A studio half that throws while it loads registers nothing. Settings → Plugins says “The
360
+ studio part didn’t load. Check the plugin and reload” with the reason. The server half keeps
361
+ working.
362
+ - A page or section that throws while it draws shows “This part of a plugin crashed.” in its
363
+ place. The rest of the studio stays up.
@@ -0,0 +1,129 @@
1
+ ---
2
+ title: Styles and components
3
+ description: The studio's components, Tailwind against the studio's theme, and why a plugin's styles never leak.
4
+ version: 0.5.0
5
+ ---
6
+
7
+ A plugin’s page should look like the studio. Two things make that easy: the studio’s components
8
+ and its theme.
9
+
10
+ ## Components
11
+
12
+ `@engenty-wizards/web/ui` is what the studio itself is drawn with:
13
+
14
+ | Component | For | Props beside the element’s own |
15
+ |---|---|---|
16
+ | `Button` | An action | `variant`: `primary` (default), `secondary`, `ghost`, `quiet`, `danger` · `size`: `sm`, `md`, `lg` · `busy` |
17
+ | `IconButton` | An action that is only an icon | `label`: its name for screen readers and the tooltip |
18
+ | `Input`, `Textarea` | Text. The textarea grows with its content | `minRows`, `maxRows` on the textarea |
19
+ | `Select` | One of a list | `value`, `onChange(value)`, `options: { value, label, disabled? }[]`, `placeholder` |
20
+ | `Segmented` | One or several of a few | `value`, `onChange`, `options: string[]`, `multi`, `disabled` (options shown but not to be picked) |
21
+ | `Tabs` | A row of tabs; the panels are yours | `value`, `onChange`, `options: { id, label }[]`, `label` (for screen readers) |
22
+ | `Switch` | On or off | `checked`, `onChange(checked)`, `label`, `disabled` |
23
+ | `Swatch` | A colour | The native colour input’s |
24
+ | `Label` | A field’s label | `hint`, `required` |
25
+ | `Card` | A surface | |
26
+ | `Chip` | A state in a word | `tone`: `neutral` (default), `live`, `warn`, `ember` · `icon` (in place of the live dot) · `title` (on hover) |
27
+ | `DatePicker` | A date from a month | `value` (“YYYY-MM-DD” or “”), `onChange`, `min`, `max`, `clearable` |
28
+ | `DateRangePicker` | A day or a period in one month: the first click is the start, the second the end | `from`, `to`, `onChange({ from, to })`, `min`, `max` |
29
+ | `TimePicker` | A time of day from an hour and a minute column; arrow keys on the field move it by `step` | `value` (“HH:MM” or “”), `onChange`, `step` (minutes, default 5), `compact` (narrow, no clock) |
30
+ | `PageMenu` | A page’s own menu: a list at the side with one level below that slides in, tabs on a phone | `title`, `entries` ({ id, label, icon?, to, entries? }), `current`, `footer` |
31
+ | `MenuPage` | A page with a menu of its own: the menu stands at the page’s left, or in the studio’s sidebar while that is open, so there is only ever one menu at the left | `menu` (a `PageMenu`, or any), `children` (the page) |
32
+ | `Composer` | The field a message is written in: text, dictation, files, send | `onSend(text, files)` (false keeps the draft), `placeholder`, `disabled`, `attach`, `floating` |
33
+ | `Dialog` | A modal; on a phone it fills the screen | `open`, `onClose`, `title`, `wide` (`true`, or `"page"` for a document), `height="tall"` (for tabs, folds or lists: its height does not jump), `bare` (the children are the panel) |
34
+ | `Spinner`, `Empty` | Loading, and nothing there yet | |
35
+ | `LinkedText` | A sentence with its web addresses as links, named by their host | `text` |
36
+ | `QrCode` | A QR code of a text, such as a link or a `tel:` number, as the share dialog draws it | `text`, `label` (for screen readers) |
37
+ | `cn(...)` | Joins class names, skipping what is false | |
38
+ | `dateText(date, withWeekday?)` | A “YYYY-MM-DD” date in the studio’s language: “Wed 14 Oct 2026” | |
39
+ | `Anchor`, `Section` | A section of the space page and the spot the menu jumps to: the heading and its hint above the card | `id` on the anchor · `title`, `hint`, `save` (how the last save went), `action` (beside the heading), `plain` (the content draws its own cards) |
40
+ | `InlineText` | Text edited where it stands, without a field’s frame | `value`, `onChange`, `placeholder`, `label`, `maxLength`, `fit` (as wide as its text) |
41
+ | `AddMenu` | The “Add” menu of a section’s heading | `entries: { label, icon, onPick }[]` |
42
+ | `AddRow` | A quiet “+ …” row at the end of a list | `label`, `onClick` |
43
+ | `RuleRows`, `useRuleRows(saved)` | Rules as rows, each with its sign (bullet, do, don’t, to check, important, numbered) | `rules` (what the hook gives), `placeholder`, `readOnly` |
44
+ | `useAutosave(value, save)` | Saves a value a moment after it last changed; gives the state for a section’s `save` | |
45
+ | `newId()` | A short id for something new | |
46
+
47
+ ```tsx
48
+ import { Button, Card, Chip, Label, Input } from "@engenty-wizards/web/ui";
49
+
50
+ <Card className="flex flex-col gap-4 p-5">
51
+ <Label hint="Where the message goes.">Address</Label>
52
+ <Input value={url} onChange={(e) => setUrl(e.target.value)} />
53
+ <div className="flex items-center gap-3">
54
+ <Button busy={save.isPending} onClick={() => save.mutate()}>Save</Button>
55
+ <Chip tone="live">connected</Chip>
56
+ </div>
57
+ </Card>
58
+ ```
59
+
60
+ Icons are from `lucide-react`.
61
+
62
+ Most of these components live in the runner package (`@engenty-wizards/runner`), so a wizard’s
63
+ run page looks like the studio. Import them from `@engenty-wizards/web/ui` all the same: that is
64
+ the import the studio shares. `@engenty-wizards/runner` is not shared, so the build would bundle
65
+ it into `client.js`.
66
+
67
+ ## Tailwind
68
+
69
+ A plugin writes Tailwind classes, as the studio does. The build collects the classes the
70
+ plugin’s files use into `dist/client.css`.
71
+
72
+ The theme’s names are the studio’s:
73
+
74
+ | | Names |
75
+ |---|---|
76
+ | Surfaces | `bg-paper`, `bg-paper-2`, `bg-paper-3`, `bg-card`, `bg-popover`, `bg-accent` |
77
+ | Text | `text-ink`, `text-ink-2`, `text-ink-3`, `text-ink-4` |
78
+ | Lines | `border-border`, `border-border-soft`, `ring-border-soft` |
79
+ | The accent | `ember`, `ember-strong`, `ember-tint`; `primary`, `primary-foreground` |
80
+ | States | `moss` and `moss-tint` (good), `amber` and `amber-tint` (attention), `rose` and `rose-tint` (danger), `cobalt` and `cobalt-tint` (information) |
81
+ | Type | `font-sans`, `font-display` (headings), `font-mono` |
82
+ | Corners | `rounded-sm` to `rounded-3xl`, from the theme’s radius |
83
+ | Shadows | `shadow-soft`, `shadow-elevated`, `shadow-overlay` |
84
+ | Variants | `dark:` and `coarse:` (a finger, not a mouse) beside Tailwind’s own |
85
+
86
+ The full list is
87
+ [packages/runner/src/theme.css](https://github.com/engenty/wizards/blob/main/packages/runner/src/theme.css):
88
+ the studio and a wizard’s run page share it.
89
+
90
+ ## Rules
91
+
92
+ - **Colours come from the names.** The dark theme is derived from the theme’s values, not from a
93
+ fixed palette. A literal colour (`#1a1a1a`, `text-gray-700`) breaks in the other theme.
94
+ - **Check both themes.** Dark is the studio’s default. The user menu and the app bar’s own menu
95
+ switch between light, dark and the system’s.
96
+ - **Touch targets.** `coarse:min-h-11` gives a control the 44 px a finger needs. The studio’s
97
+ components do that themselves.
98
+ - **Don’t style outside your own part.** It would not work anyway: see below.
99
+
100
+ ## Why a plugin’s styles never leak
101
+
102
+ `client.css` is built so that it cannot change how the studio looks:
103
+
104
+ - Every rule applies only inside what the plugin draws. The studio wraps each page, section,
105
+ part of the space page, app bar icon, part of the share dialog and assistant card of a plugin
106
+ in an element with `data-plugin="<id>"`, and every rule of `client.css` is nested below that.
107
+ - The rules sit in a layer above the studio’s utilities, so inside the plugin’s part the
108
+ plugin’s stylesheet decides.
109
+ - The theme is used by reference: `client.css` carries the names’ uses, none of the variables
110
+ and no resets.
111
+
112
+ ## Your own CSS
113
+
114
+ A stylesheet imported in `ui/plugin.tsx` lands in `client.css` as it is:
115
+
116
+ ```tsx
117
+ import "./contacts.css";
118
+ ```
119
+
120
+ The build doesn’t nest it for you. Begin its class names with the plugin’s id
121
+ (`.contacts-chart`) and use the theme’s variables for colours: `var(--ink-2)`, `var(--paper-2)`,
122
+ `var(--ember)`.
123
+
124
+ ## The theme is a contract
125
+
126
+ A plugin is built against the names the theme has at the time of its build. If a later release
127
+ renames or removes a name, plugins built before break without an error: the class is simply not
128
+ there. That is why whoever changes `theme.css` treats its names as a contract. If you build
129
+ against a name a release added, say in your plugin’s description which release it needs.
@@ -0,0 +1,104 @@
1
+ ---
2
+ title: Tables
3
+ description: A plugin's own tables in every tenant's database – SQL files that run once, and Drizzle to read and write.
4
+ version: 0.5.0
5
+ ---
6
+
7
+ Every tenant has a database of its own (libSQL, the SQLite dialect). The runtime makes a plugin’s
8
+ tables in each of them, from `.sql` files the plugin brings.
9
+
10
+ ## 1. The table, as SQL
11
+
12
+ `migrations/0001_init.sql`:
13
+
14
+ ```sql
15
+ CREATE TABLE contacts_person (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ email TEXT NOT NULL UNIQUE,
18
+ name TEXT,
19
+ wizard TEXT NOT NULL,
20
+ seen_at INTEGER NOT NULL
21
+ );
22
+ ```
23
+
24
+ Register the folder when the plugin loads:
25
+
26
+ ```ts
27
+ server.registerMigrations("migrations");
28
+ ```
29
+
30
+ ## 2. The table, for Drizzle
31
+
32
+ `src/schema.ts` describes the same table, so queries are typed:
33
+
34
+ ```ts
35
+ import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
36
+
37
+ export const person = sqliteTable("contacts_person", {
38
+ id: integer("id").primaryKey({ autoIncrement: true }),
39
+ email: text("email").notNull().unique(),
40
+ name: text("name"),
41
+ wizard: text("wizard").notNull(),
42
+ seenAt: integer("seen_at", { mode: "timestamp_ms" }).notNull(),
43
+ });
44
+ ```
45
+
46
+ The runtime does not read this file. It is yours: keep it in step with the SQL by hand.
47
+
48
+ ## 3. Read and write
49
+
50
+ `server.getTenantDb()` is the database of the tenant the current request, step or event belongs
51
+ to, as a Drizzle database:
52
+
53
+ ```ts
54
+ import { desc, eq } from "drizzle-orm";
55
+ import { person } from "./schema";
56
+
57
+ const db = () => server.getTenantDb();
58
+
59
+ const newest = await db().select().from(person).orderBy(desc(person.seenAt)).limit(200);
60
+
61
+ await db()
62
+ .insert(person)
63
+ .values({ email, name, wizard, seenAt: new Date() })
64
+ .onConflictDoUpdate({ target: person.email, set: { name, wizard, seenAt: new Date() } });
65
+
66
+ await db().delete(person).where(eq(person.id, id));
67
+ ```
68
+
69
+ Call `getTenantDb()` inside the handler, the tool, the listener or the job. Outside of them
70
+ there is no tenant.
71
+
72
+ ## How the files run
73
+
74
+ | | |
75
+ |---|---|
76
+ | Once | Each `.sql` file runs once per tenant database. The table `plugin_migration` records which ran |
77
+ | In order | By file name: `0001_init.sql`, `0002_note.sql` |
78
+ | Whole or not | A file and its record go in together or not at all. A file may hold several statements |
79
+ | When | A database gets the files when it opens. The open ones get them when the plugin loads, also when it loads again with a new file |
80
+ | Never back | Nothing is taken back. Unloading or removing a plugin leaves its tables and rows |
81
+
82
+ A file that fails is logged with the plugin’s id and the file’s name. The files after it, other
83
+ plugins’ included, wait for that database until the file is fixed. The tenant’s database still
84
+ opens.
85
+
86
+ ## Rules
87
+
88
+ - **Begin table names with the plugin’s id**: `contacts_person`. All plugins and the runtime
89
+ share the database. A `-` in the id becomes `_`.
90
+ - **Never change a file that ran.** It will not run again. Add a new file:
91
+
92
+ ```sql
93
+ ALTER TABLE contacts_person ADD COLUMN phone TEXT;
94
+ ```
95
+
96
+ - **Do not touch the runtime’s own tables** in a migration. Their shape changes with releases.
97
+ - **Dates** are integers in milliseconds (`mode: "timestamp_ms"`); they leave a route as ISO
98
+ strings.
99
+
100
+ ## The runtime’s own data
101
+
102
+ `getTenantDb()` reaches the whole tenant database, the runtime’s tables included. They are not
103
+ a public interface: a release can rename a column. A plugin that must know about runs listens
104
+ to [run events](./events.md) and keeps what it needs in its own table.