@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,152 @@
1
+ import { isDecidedField, isDecisionStep, } from "@engenty-wizards/shared/definition";
2
+ import { and, desc, eq, inArray, isNull } from "drizzle-orm";
3
+ import { db, schema } from "../db/client.js";
4
+ import { mostAlongOnePath } from "../engine/requirements.js";
5
+ import { classCatalog } from "../models.js";
6
+ import { MICROS_PER_CREDIT } from "./credits.js";
7
+ /**
8
+ * What a run will cost, in credits, before it starts. A step that has run five times on this
9
+ * version is estimated from its measurements (median, and the 90th percentile as the amount to
10
+ * hold); until then a formula per step type and model class stands in.
11
+ */
12
+ const MIN_SAMPLES = 5;
13
+ const SAMPLE_RUNS = 40;
14
+ /** Tokens a text call of each shape takes, as [input, output]. */
15
+ const TOKENS = {
16
+ plain: [8_000, 1_500],
17
+ tools: [60_000, 4_000],
18
+ browser: [250_000, 8_000],
19
+ document: [6_000, 8_000],
20
+ prompt: [2_000, 300],
21
+ structure: [4_000, 1_000],
22
+ decision: [1_500, 100],
23
+ };
24
+ function textCredits(price, [input, output]) {
25
+ if (!price) {
26
+ return 0;
27
+ }
28
+ return ((input / 1e6) * (price.inputCreditsPerMTok ?? 0) +
29
+ (output / 1e6) * (price.outputCreditsPerMTok ?? 0));
30
+ }
31
+ /** A step's own work, and one decision where `ask` branches or a page's fields are decided. */
32
+ function formula(step, catalog) {
33
+ const decides = step.next?.some((r) => r.ask) || (step.type === "page" && step.fields.some(isDecidedField));
34
+ const decision = decides ? textCredits(catalog.classes.classifier, TOKENS.decision) : 0;
35
+ return decision + stepFormula(step, catalog);
36
+ }
37
+ function stepFormula(step, catalog) {
38
+ const cls = (c) => catalog.classes[c];
39
+ if (step.type === "agent") {
40
+ // A call runs one tool and no model: nothing to pay for.
41
+ if (step.call) {
42
+ return 0;
43
+ }
44
+ // A decision is one small call to the classifier class.
45
+ if (isDecisionStep(step)) {
46
+ return textCredits(cls("classifier"), TOKENS.decision);
47
+ }
48
+ const shape = step.tools.includes("browser")
49
+ ? TOKENS.browser
50
+ : step.tools.length || step.mcp?.length || step.connections?.length
51
+ ? TOKENS.tools
52
+ : TOKENS.plain;
53
+ // A step with `each` runs once per entry; until it has run, three stand in.
54
+ let credits = textCredits(cls(step.model ?? "high"), shape) * (step.each ? 3 : 1);
55
+ if (step.tools.includes("web_search")) {
56
+ credits += 4 * catalog.webSearchCredits;
57
+ }
58
+ if (step.tools.includes("image")) {
59
+ credits += catalog.classes.image?.creditsPerImage ?? 0;
60
+ }
61
+ if (step.output.format === "json") {
62
+ credits += textCredits(cls("classifier"), TOKENS.structure);
63
+ }
64
+ if (step.output.surface === true) {
65
+ credits += textCredits(cls("standard"), TOKENS.structure);
66
+ }
67
+ return credits;
68
+ }
69
+ if (step.type === "generate") {
70
+ if (step.asset === "image") {
71
+ return ((catalog.classes.image?.creditsPerImage ?? 0) + textCredits(cls("standard"), TOKENS.prompt));
72
+ }
73
+ if (step.asset === "video") {
74
+ const seconds = Math.min(Math.max(Math.round(step.options?.duration ?? 8), 4), 10);
75
+ return (seconds * (catalog.classes.video?.creditsPerSecond ?? 0) +
76
+ textCredits(cls("standard"), TOKENS.prompt));
77
+ }
78
+ return textCredits(cls(step.model ?? "high"), TOKENS.document);
79
+ }
80
+ return 0;
81
+ }
82
+ /**
83
+ * What a run of a definition costs by the formula alone — before anyone has run it — along its
84
+ * most expensive way that avoids the steps in `closed`.
85
+ */
86
+ export function formulaEstimate(definition, catalog, closed) {
87
+ const credits = mostAlongOnePath(definition, (step) => formula(step, catalog), closed);
88
+ return { credits: round(credits), high: Math.ceil(credits * 2) };
89
+ }
90
+ function percentile(sorted, p) {
91
+ return sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))];
92
+ }
93
+ /** Credits each step cost in the latest finished runs of this wizard version. */
94
+ async function measurements(wizardId, version) {
95
+ const runs = await db
96
+ .select({ id: schema.run.id })
97
+ .from(schema.run)
98
+ .where(and(eq(schema.run.wizardId, wizardId), eq(schema.run.status, "done"), version === null ? isNull(schema.run.version) : eq(schema.run.version, version)))
99
+ .orderBy(desc(schema.run.createdAt))
100
+ .limit(SAMPLE_RUNS);
101
+ const out = new Map();
102
+ if (!runs.length) {
103
+ return out;
104
+ }
105
+ const costs = await db
106
+ .select()
107
+ .from(schema.runCost)
108
+ .where(inArray(schema.runCost.runId, runs.map((r) => r.id)));
109
+ for (const c of costs) {
110
+ const list = out.get(c.stepId) ?? [];
111
+ list.push(c.micros / MICROS_PER_CREDIT);
112
+ out.set(c.stepId, list);
113
+ }
114
+ return out;
115
+ }
116
+ const round = (credits) => Math.round(credits * 10) / 10;
117
+ /**
118
+ * What a run will cost and how much to hold, along its most expensive way: steps on branches
119
+ * that exclude each other are not added up. `closed`: steps the run cannot take here.
120
+ */
121
+ export async function estimateRun(wizardId, version, definition, closed) {
122
+ const catalog = await classCatalog();
123
+ if (!catalog) {
124
+ // A runtime that resolves models itself has no credits to estimate in.
125
+ return { available: false, credits: 0, reserve: 0, steps: {} };
126
+ }
127
+ const measured = await measurements(wizardId, version);
128
+ const steps = {};
129
+ for (const step of definition.steps) {
130
+ const samples = (measured.get(step.id) ?? []).sort((a, b) => a - b);
131
+ let estimate;
132
+ if (samples.length >= MIN_SAMPLES) {
133
+ estimate = {
134
+ credits: round(percentile(samples, 0.5)),
135
+ high: round(percentile(samples, 0.9)),
136
+ measured: true,
137
+ };
138
+ }
139
+ else {
140
+ const value = formula(step, catalog);
141
+ if (value <= 0) {
142
+ continue;
143
+ }
144
+ // A formula knows little: hold twice as much as it says.
145
+ estimate = { credits: round(value), high: round(value * 2), measured: false };
146
+ }
147
+ steps[step.id] = estimate;
148
+ }
149
+ const credits = mostAlongOnePath(definition, (s) => steps[s.id]?.credits ?? 0, closed);
150
+ const reserve = mostAlongOnePath(definition, (s) => steps[s.id]?.high ?? 0, closed);
151
+ return { available: true, credits: round(credits), reserve: Math.ceil(reserve), steps };
152
+ }
@@ -0,0 +1,149 @@
1
+ import { existsSync } from "node:fs";
2
+ import { cp } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { createClient } from "@libsql/client";
5
+ import { env } from "../env.js";
6
+ import { readSetting, writeSetting } from "../settings.js";
7
+ import { LOCAL_TENANT } from "../tenants/tenant.js";
8
+ import { control, controlDb, openTenantDb } from "./client.js";
9
+ /**
10
+ * A data folder from before tenants had their own database holds everything in `wizards.db`,
11
+ * owned by a user. Its wizards, runs and files become the local tenant's, once. The old file
12
+ * and folders stay where they are.
13
+ */
14
+ const TABLES = [
15
+ "project",
16
+ "wizard",
17
+ "wizard_version",
18
+ "wizard_file",
19
+ "wizard_message",
20
+ "run",
21
+ "run_event",
22
+ "asset",
23
+ "project_connector",
24
+ "store_holder",
25
+ "store_row",
26
+ "store_file",
27
+ "store_secret",
28
+ ];
29
+ const CLASS_OF = { fast: "standard", smart: "high" };
30
+ /** Steps named a model speed before they named a model class. */
31
+ function withClasses(json) {
32
+ if (typeof json !== "string") {
33
+ return json;
34
+ }
35
+ try {
36
+ const def = JSON.parse(json);
37
+ for (const step of def.steps ?? []) {
38
+ if (step.model && CLASS_OF[step.model]) {
39
+ step.model = CLASS_OF[step.model];
40
+ }
41
+ }
42
+ return JSON.stringify(def);
43
+ }
44
+ catch {
45
+ return json;
46
+ }
47
+ }
48
+ const personOf = (holder) => typeof holder === "string" && holder.startsWith("u:") ? "u:local" : holder;
49
+ export async function adoptLegacyData() {
50
+ const legacyFile = join(env.dataDir, "wizards.db");
51
+ const targetFile = join(env.dataDir, "tenants", `${LOCAL_TENANT}.db`);
52
+ if (!existsSync(legacyFile) || existsSync(targetFile) || (await readSetting("adopted"))) {
53
+ return;
54
+ }
55
+ const legacy = createClient({ url: `file:${legacyFile}` });
56
+ const hasOwner = (await legacy.execute("PRAGMA table_info(project)")).rows.some((r) => r.name === "owner_id");
57
+ if (!hasOwner) {
58
+ return;
59
+ }
60
+ await openTenantDb(LOCAL_TENANT);
61
+ const target = createClient({ url: `file:${targetFile}` });
62
+ const statements = [];
63
+ const links = [];
64
+ const runs = [];
65
+ for (const table of TABLES) {
66
+ const targetColumns = new Set((await target.execute(`PRAGMA table_info(${table})`)).rows.map((r) => String(r.name)));
67
+ const rows = (await legacy.execute(`SELECT * FROM ${table}`).catch(() => ({ rows: [] }))).rows;
68
+ for (const row of rows) {
69
+ const values = {};
70
+ for (const [column, value] of Object.entries(row)) {
71
+ const name = column === "owner_id" ? "tenant_id" : column;
72
+ if (targetColumns.has(name)) {
73
+ values[name] = value;
74
+ }
75
+ }
76
+ if ("tenant_id" in values) {
77
+ values.tenant_id = LOCAL_TENANT;
78
+ }
79
+ if ("holder" in values) {
80
+ values.holder = personOf(values.holder);
81
+ }
82
+ if (table === "wizard") {
83
+ values.draft = withClasses(values.draft);
84
+ links.push({
85
+ token: String(values.share_token),
86
+ tenantId: LOCAL_TENANT,
87
+ kind: "wizard",
88
+ ref: String(values.id),
89
+ });
90
+ }
91
+ if (table === "wizard_version" || table === "run") {
92
+ values.definition = withClasses(values.definition);
93
+ }
94
+ if (table === "run") {
95
+ values.user_id = values.user_id ? "local" : null;
96
+ runs.push({
97
+ runId: String(values.id),
98
+ tenantId: LOCAL_TENANT,
99
+ visitorId: values.visitor_id ?? null,
100
+ ipHash: values.ip_hash ?? null,
101
+ active: values.status === "running",
102
+ createdAt: new Date(Number(values.created_at)),
103
+ });
104
+ if (values.share_token) {
105
+ links.push({
106
+ token: String(values.share_token),
107
+ tenantId: LOCAL_TENANT,
108
+ kind: "result",
109
+ ref: String(values.id),
110
+ });
111
+ }
112
+ }
113
+ if (table === "asset" && values.kind === "logo") {
114
+ links.push({
115
+ token: String(values.id),
116
+ tenantId: LOCAL_TENANT,
117
+ kind: "logo",
118
+ ref: String(values.id),
119
+ });
120
+ }
121
+ const columns = Object.keys(values);
122
+ statements.push({
123
+ sql: `INSERT INTO ${table} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`,
124
+ args: columns.map((c) => values[c]),
125
+ });
126
+ }
127
+ }
128
+ await target.batch(statements, "write");
129
+ for (let i = 0; i < links.length; i += 100) {
130
+ await controlDb
131
+ .insert(control.link)
132
+ .values(links.slice(i, i + 100))
133
+ .onConflictDoNothing();
134
+ }
135
+ for (let i = 0; i < runs.length; i += 100) {
136
+ await controlDb
137
+ .insert(control.runIndex)
138
+ .values(runs.slice(i, i + 100))
139
+ .onConflictDoNothing();
140
+ }
141
+ for (const folder of ["assets", "blobs"]) {
142
+ const from = join(env.dataDir, folder);
143
+ if (existsSync(from)) {
144
+ await cp(from, join(env.dataDir, "objects", "t", LOCAL_TENANT, folder), { recursive: true });
145
+ }
146
+ }
147
+ await writeSetting("adopted", new Date().toISOString());
148
+ console.log(`Adopted ${statements.length} rows from ${legacyFile} into the local tenant.`);
149
+ }
@@ -0,0 +1,173 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { mkdirSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { createClient } from "@libsql/client";
6
+ import { eq } from "drizzle-orm";
7
+ import { drizzle } from "drizzle-orm/libsql";
8
+ import { migrate } from "drizzle-orm/libsql/migrator";
9
+ import { env } from "../env.js";
10
+ import { currentTenant, inTenant } from "../tenants/tenant.js";
11
+ import * as control from "./control-schema.js";
12
+ import * as schema from "./schema.js";
13
+ mkdirSync(join(env.dataDir, "tenants"), { recursive: true });
14
+ const here = dirname(fileURLToPath(import.meta.url));
15
+ /** Migrations are SQL files next to this module; the build copies them next to the built one. */
16
+ function migrationsFolder(name) {
17
+ return join(here, "migrations", name);
18
+ }
19
+ function open(url, authToken) {
20
+ return createClient({ url, ...(authToken ? { authToken } : {}) });
21
+ }
22
+ async function prepare(client, url) {
23
+ if (url.startsWith("file:")) {
24
+ await client.execute("PRAGMA journal_mode = WAL");
25
+ await client.execute("PRAGMA busy_timeout = 5000");
26
+ }
27
+ await client.execute("PRAGMA foreign_keys = ON");
28
+ }
29
+ // --- control database --------------------------------------------------------
30
+ const controlUrl = env.databaseUrl || `file:${join(env.dataDir, "control.db")}`;
31
+ const controlClient = open(controlUrl, env.databaseAuthToken);
32
+ /** Links, the run index, sessions and settings: what is known before a tenant's database opens. */
33
+ export const controlDb = drizzle(controlClient, { schema: control });
34
+ export { control };
35
+ export async function migrateControlDb() {
36
+ await prepare(controlClient, controlUrl);
37
+ await migrate(controlDb, { migrationsFolder: migrationsFolder("control") });
38
+ }
39
+ // --- tenant databases --------------------------------------------------------
40
+ function makeTenantDb(client) {
41
+ return drizzle(client, { schema });
42
+ }
43
+ const opened = new Map();
44
+ const clients = new Map();
45
+ /** Where a tenant's database lives: the URL the Manage-App handed out, else a file in the data folder. */
46
+ function tenantUrl(id, dbUrl) {
47
+ if (dbUrl) {
48
+ return dbUrl;
49
+ }
50
+ if (env.tenantDbUrlTemplate) {
51
+ return env.tenantDbUrlTemplate.replaceAll("{tenant}", id.toLowerCase());
52
+ }
53
+ return `file:${join(env.dataDir, "tenants", `${id}.db`)}`;
54
+ }
55
+ async function openTenant(id) {
56
+ let row = await controlDb.query.tenant.findFirst({ where: eq(control.tenant.id, id) });
57
+ if (!row) {
58
+ await controlDb.insert(control.tenant).values({ id }).onConflictDoNothing();
59
+ row = (await controlDb.query.tenant.findFirst({ where: eq(control.tenant.id, id) }));
60
+ }
61
+ const url = tenantUrl(id, row.dbUrl);
62
+ const client = open(url, url.startsWith("file:") ? "" : env.tenantDbAuthToken);
63
+ clients.set(id, client);
64
+ await prepare(client, url);
65
+ const db = makeTenantDb(client);
66
+ // Every database is brought to the current schema when it is first opened.
67
+ await migrate(db, { migrationsFolder: migrationsFolder("tenant") });
68
+ for (const hook of openHooks) {
69
+ await hook(id, client);
70
+ }
71
+ return db;
72
+ }
73
+ const openHooks = [];
74
+ /** Runs for every tenant database right after it was opened and migrated (plugins' own tables). */
75
+ export function onTenantOpen(hook) {
76
+ openHooks.push(hook);
77
+ }
78
+ /** The tenant databases this process has open, once each of them finished opening. */
79
+ export async function openTenantClients() {
80
+ await Promise.allSettled(opened.values());
81
+ return [...clients.entries()];
82
+ }
83
+ /** The only way to a tenant's tables. Opens the database once per process and migrates it then. */
84
+ export function tenantDb(id) {
85
+ let db = opened.get(id);
86
+ if (!db) {
87
+ db = openTenant(id).catch((err) => {
88
+ opened.delete(id);
89
+ throw err;
90
+ });
91
+ opened.set(id, db);
92
+ }
93
+ return db;
94
+ }
95
+ const ready = new Map();
96
+ /** Closes and forgets an open tenant database (the tenant was deleted or moved). */
97
+ export function closeTenantDb(id) {
98
+ opened.delete(id);
99
+ ready.delete(id);
100
+ clients.get(id)?.close();
101
+ clients.delete(id);
102
+ }
103
+ /** Opens the current tenant's database; `db` works synchronously afterwards. */
104
+ export async function openTenantDb(id) {
105
+ if (!ready.has(id)) {
106
+ ready.set(id, await tenantDb(id));
107
+ }
108
+ }
109
+ /** Runs `fn` for one tenant: opens its database, then sets the context `db` resolves from. */
110
+ export async function withTenant(id, fn) {
111
+ await openTenantDb(id);
112
+ return inTenant(id, fn);
113
+ }
114
+ /** The transaction the current context writes in, while `inTransaction()` runs. */
115
+ const transactions = new AsyncLocalStorage();
116
+ /**
117
+ * Runs `fn` as one transaction of the current tenant's database: inside it, `db` is the
118
+ * transaction, so every write of the services called there stands or falls with the others.
119
+ * Already inside one, `fn` just joins it. Only this database takes part: the object store and
120
+ * the control database are written as before, so do those first or after.
121
+ */
122
+ export async function inTransaction(fn) {
123
+ if (transactions.getStore()) {
124
+ return fn();
125
+ }
126
+ const id = currentTenant();
127
+ const target = ready.get(id);
128
+ if (!target) {
129
+ throw new Error(`Tenant database "${id}" is not open: enter it with withTenant().`);
130
+ }
131
+ return target.transaction((tx) => transactions.run(tx, fn));
132
+ }
133
+ /**
134
+ * The current tenant's database, resolved from the context `inTenant()` set — or the
135
+ * transaction `inTransaction()` opened there. Code that reads or writes wizards, runs or files
136
+ * never names a tenant itself.
137
+ */
138
+ export const db = new Proxy({}, {
139
+ get(_target, prop) {
140
+ const id = currentTenant();
141
+ const target = transactions.getStore() ?? ready.get(id);
142
+ if (!target) {
143
+ throw new Error(`Tenant database "${id}" is not open: enter it with withTenant().`);
144
+ }
145
+ const value = Reflect.get(target, prop);
146
+ return typeof value === "function" ? value.bind(target) : value;
147
+ },
148
+ });
149
+ export { schema };
150
+ /** Brings every known tenant database to the current schema (after a release). */
151
+ export async function migrateAllTenants() {
152
+ const tenants = await controlDb.select({ id: control.tenant.id }).from(control.tenant);
153
+ const failed = [];
154
+ let migrated = 0;
155
+ const queue = [...tenants];
156
+ await Promise.all(Array.from({ length: 4 }, async () => {
157
+ for (let t = queue.shift(); t; t = queue.shift()) {
158
+ try {
159
+ await openTenantDb(t.id);
160
+ migrated++;
161
+ }
162
+ catch (err) {
163
+ console.error(`[migrate ${t.id}]`, err);
164
+ failed.push(t.id);
165
+ }
166
+ }
167
+ }));
168
+ return { migrated, failed };
169
+ }
170
+ export async function knownTenants() {
171
+ const rows = await controlDb.select({ id: control.tenant.id }).from(control.tenant);
172
+ return rows.map((r) => r.id);
173
+ }
@@ -0,0 +1,133 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from "drizzle-orm/sqlite-core";
3
+ const now = sql `(unixepoch() * 1000)`;
4
+ const createdAt = () => integer("created_at", { mode: "timestamp_ms" }).notNull().default(now);
5
+ // The control database: what the runtime must know before it can open a tenant's database,
6
+ // and what it counts across tenants. No wizard, run content or file lives here.
7
+ /** Every tenant this runtime has opened. `dbUrl` null = a libSQL file in the data folder. */
8
+ export const tenant = sqliteTable("tenant", {
9
+ id: text("id").primaryKey(),
10
+ status: text("status", { enum: ["active", "suspended"] })
11
+ .notNull()
12
+ .default("active"),
13
+ dbUrl: text("db_url"),
14
+ createdAt: createdAt(),
15
+ });
16
+ /** Public tokens that arrive without a session: which tenant, and which row there. */
17
+ export const link = sqliteTable("link", {
18
+ token: text("token").primaryKey(),
19
+ tenantId: text("tenant_id").notNull(),
20
+ /**
21
+ * `wizard` = a share link `/w/<token>`, `result` = a shared result `/s/<token>`, `logo` = a
22
+ * brand logo, `code` = a wizard's ID to type in (its `ref` is the wizard's share token).
23
+ */
24
+ kind: text("kind", { enum: ["wizard", "result", "logo", "code"] }).notNull(),
25
+ ref: text("ref").notNull(),
26
+ createdAt: createdAt(),
27
+ }, (t) => [index("link_tenant").on(t.tenantId), index("link_ref").on(t.kind, t.ref)]);
28
+ /**
29
+ * One row per run: finds the run's tenant, counts a visitor's runs across all wizards, and
30
+ * marks the runs that are working (resumed after a restart, counted against the tenant's limit).
31
+ */
32
+ export const runIndex = sqliteTable("run_index", {
33
+ runId: text("run_id").primaryKey(),
34
+ tenantId: text("tenant_id").notNull(),
35
+ visitorId: text("visitor_id"),
36
+ ipHash: text("ip_hash"),
37
+ active: integer("active", { mode: "boolean" }).notNull().default(false),
38
+ /** The runner working on the run; null while it waits for one. */
39
+ owner: text("owner"),
40
+ /** The owner's last heartbeat; one silent for RUNNER_STALE_MS has lost the run. */
41
+ seen: integer("seen", { mode: "timestamp_ms" }),
42
+ /**
43
+ * The mobile app's device for push, set by the app for this run (`POST /api/runs/:id/notify`):
44
+ * `{ token, platform: "ios" | "android", lang }`. Told through the Manage-App when the run is
45
+ * done, failed or waits for the person.
46
+ */
47
+ push: text("push", { mode: "json" }).$type(),
48
+ createdAt: createdAt(),
49
+ }, (t) => [
50
+ index("run_index_visitor").on(t.visitorId, t.createdAt),
51
+ index("run_index_ip").on(t.ipHash, t.createdAt),
52
+ index("run_index_active").on(t.active, t.tenantId),
53
+ ]);
54
+ /**
55
+ * The runners that execute runs (RUNTIME_ROLE=runner or all): where the web reaches one for what
56
+ * only the process holding a run can answer (its browser's screen), and when it last reported.
57
+ */
58
+ export const runner = sqliteTable("runner", {
59
+ id: text("id").primaryKey(),
60
+ url: text("url"),
61
+ seen: integer("seen", { mode: "timestamp_ms" }).notNull(),
62
+ });
63
+ /** A studio session of someone signed in at the Manage-App. The refresh token is encrypted. */
64
+ export const session = sqliteTable("session", {
65
+ id: text("id").primaryKey(),
66
+ userId: text("user_id").notNull(),
67
+ tenantId: text("tenant_id").notNull(),
68
+ role: text("role").notNull(),
69
+ name: text("name").notNull(),
70
+ email: text("email").notNull(),
71
+ image: text("image"),
72
+ refreshToken: text("refresh_token"),
73
+ /** When the access token's claims (tenant, role) must be renewed. */
74
+ claimsExpireAt: integer("claims_expire_at", { mode: "timestamp_ms" }).notNull(),
75
+ expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
76
+ createdAt: createdAt(),
77
+ }, (t) => [index("session_expires").on(t.expiresAt)]);
78
+ /** Settings of a runtime that runs alone: model bindings, the linked account. Never secrets. */
79
+ export const setting = sqliteTable("setting", {
80
+ key: text("key").primaryKey(),
81
+ value: text("value", { mode: "json" }).$type().notNull(),
82
+ });
83
+ /**
84
+ * The runner's own words in a language outside `LANGS`, translated once for the runtime:
85
+ * `source` is the hash of the English tables they were made from.
86
+ */
87
+ export const uiTranslation = sqliteTable("ui_translation", {
88
+ lang: text("lang").primaryKey(),
89
+ source: text("source").notNull(),
90
+ texts: text("texts", { mode: "json" }).$type().notNull(),
91
+ createdAt: createdAt(),
92
+ });
93
+ // --- marketplace -----------------------------------------------------------------
94
+ // The marketplace is an app of its own (docs/marketplace-contract.md). What this runtime keeps
95
+ // of it for offline use: its starters and what people starred, as the marketplace exports them.
96
+ export const marketplaceCache = sqliteTable("marketplace_cache", {
97
+ id: text("id").primaryKey(),
98
+ /** The marketplace's hash of the entry: a different one in its list means it changed. */
99
+ hash: text("hash").notNull(),
100
+ entry: text("entry", { mode: "json" }).$type().notNull(),
101
+ fetchedAt: integer("fetched_at", { mode: "timestamp_ms" }).notNull().default(now),
102
+ });
103
+ /** When a plugin's job (`server.every`) last ran for a tenant: the next turn counts from it. */
104
+ export const pluginJob = sqliteTable("plugin_job", {
105
+ tenantId: text("tenant_id").notNull(),
106
+ plugin: text("plugin").notNull(),
107
+ name: text("name").notNull(),
108
+ lastRunAt: integer("last_run_at", { mode: "timestamp_ms" }).notNull(),
109
+ }, (t) => [primaryKey({ columns: [t.tenantId, t.plugin, t.name] })]);
110
+ /**
111
+ * The part of a plugin's public address (`server.publicUrl`) that names the tenant, without
112
+ * giving its id away: `/api/public/plugins/<plugin>/<ref>/…`.
113
+ */
114
+ export const pluginAddress = sqliteTable("plugin_address", {
115
+ ref: text("ref").primaryKey(),
116
+ tenantId: text("tenant_id").notNull(),
117
+ plugin: text("plugin").notNull(),
118
+ createdAt: createdAt(),
119
+ }, (t) => [uniqueIndex("plugin_address_tenant").on(t.tenantId, t.plugin)]);
120
+ /**
121
+ * Keys a plugin holds across tenants (`server.claims`), each for one tenant at a time: a keyword
122
+ * on a number every tenant shares, who writes to it, a number a tenant connected. What a shared
123
+ * route asks to find the tenant of a call.
124
+ */
125
+ export const pluginClaim = sqliteTable("plugin_claim", {
126
+ plugin: text("plugin").notNull(),
127
+ key: text("key").notNull(),
128
+ tenantId: text("tenant_id").notNull(),
129
+ updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull().default(now),
130
+ }, (t) => [
131
+ primaryKey({ columns: [t.plugin, t.key] }),
132
+ index("plugin_claim_tenant").on(t.tenantId, t.plugin),
133
+ ]);
@@ -0,0 +1,47 @@
1
+ CREATE TABLE `link` (
2
+ `token` text PRIMARY KEY NOT NULL,
3
+ `tenant_id` text NOT NULL,
4
+ `kind` text NOT NULL,
5
+ `ref` text NOT NULL,
6
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
7
+ );
8
+ --> statement-breakpoint
9
+ CREATE INDEX `link_tenant` ON `link` (`tenant_id`);--> statement-breakpoint
10
+ CREATE TABLE `run_index` (
11
+ `run_id` text PRIMARY KEY NOT NULL,
12
+ `tenant_id` text NOT NULL,
13
+ `visitor_id` text,
14
+ `ip_hash` text,
15
+ `active` integer DEFAULT false NOT NULL,
16
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
17
+ );
18
+ --> statement-breakpoint
19
+ CREATE INDEX `run_index_visitor` ON `run_index` (`visitor_id`,`created_at`);--> statement-breakpoint
20
+ CREATE INDEX `run_index_ip` ON `run_index` (`ip_hash`,`created_at`);--> statement-breakpoint
21
+ CREATE INDEX `run_index_active` ON `run_index` (`active`,`tenant_id`);--> statement-breakpoint
22
+ CREATE TABLE `session` (
23
+ `id` text PRIMARY KEY NOT NULL,
24
+ `user_id` text NOT NULL,
25
+ `tenant_id` text NOT NULL,
26
+ `role` text NOT NULL,
27
+ `name` text NOT NULL,
28
+ `email` text NOT NULL,
29
+ `image` text,
30
+ `refresh_token` text,
31
+ `claims_expire_at` integer NOT NULL,
32
+ `expires_at` integer NOT NULL,
33
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
34
+ );
35
+ --> statement-breakpoint
36
+ CREATE INDEX `session_expires` ON `session` (`expires_at`);--> statement-breakpoint
37
+ CREATE TABLE `setting` (
38
+ `key` text PRIMARY KEY NOT NULL,
39
+ `value` text NOT NULL
40
+ );
41
+ --> statement-breakpoint
42
+ CREATE TABLE `tenant` (
43
+ `id` text PRIMARY KEY NOT NULL,
44
+ `status` text DEFAULT 'active' NOT NULL,
45
+ `db_url` text,
46
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL
47
+ );