wizards 0.1.9

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 (308) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +170 -0
  3. package/apps/runtime/dist/agents/architect.js +453 -0
  4. package/apps/runtime/dist/agents/project-assistant.js +354 -0
  5. package/apps/runtime/dist/agents/subscription.js +206 -0
  6. package/apps/runtime/dist/agents/thought.js +21 -0
  7. package/apps/runtime/dist/agents/website.js +197 -0
  8. package/apps/runtime/dist/app.js +153 -0
  9. package/apps/runtime/dist/auth/account.js +121 -0
  10. package/apps/runtime/dist/auth/index.js +329 -0
  11. package/apps/runtime/dist/auth/keys.js +55 -0
  12. package/apps/runtime/dist/auth/local-ticket.js +23 -0
  13. package/apps/runtime/dist/authoring/example.js +73 -0
  14. package/apps/runtime/dist/authoring/guide.js +259 -0
  15. package/apps/runtime/dist/authoring/ops.js +117 -0
  16. package/apps/runtime/dist/cli/autostart.js +134 -0
  17. package/apps/runtime/dist/cli/clients.js +44 -0
  18. package/apps/runtime/dist/cli/environment.js +81 -0
  19. package/apps/runtime/dist/cli/exec.js +45 -0
  20. package/apps/runtime/dist/cli/home.js +74 -0
  21. package/apps/runtime/dist/cli/machine.js +145 -0
  22. package/apps/runtime/dist/cli/main.js +125 -0
  23. package/apps/runtime/dist/cli/setup.js +273 -0
  24. package/apps/runtime/dist/cli/start.js +190 -0
  25. package/apps/runtime/dist/cli/status.js +120 -0
  26. package/apps/runtime/dist/cli/ui.js +12 -0
  27. package/apps/runtime/dist/cli/update.js +58 -0
  28. package/apps/runtime/dist/connectors/builtin.js +70 -0
  29. package/apps/runtime/dist/connectors/external.js +400 -0
  30. package/apps/runtime/dist/connectors/gmail.js +107 -0
  31. package/apps/runtime/dist/connectors/imap.js +217 -0
  32. package/apps/runtime/dist/connectors/index.js +266 -0
  33. package/apps/runtime/dist/connectors/mail.js +72 -0
  34. package/apps/runtime/dist/connectors/outlook.js +90 -0
  35. package/apps/runtime/dist/credits/credits.js +103 -0
  36. package/apps/runtime/dist/credits/estimate.js +132 -0
  37. package/apps/runtime/dist/db/adopt.js +149 -0
  38. package/apps/runtime/dist/db/client.js +146 -0
  39. package/apps/runtime/dist/db/control-schema.js +70 -0
  40. package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
  41. package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
  42. package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
  43. package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
  44. package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
  45. package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
  46. package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
  47. package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
  48. package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
  49. package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
  50. package/apps/runtime/dist/db/migrations/control/meta/_journal.json +41 -0
  51. package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
  52. package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
  53. package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
  54. package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
  55. package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
  56. package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
  57. package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
  58. package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
  59. package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
  60. package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
  61. package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +41 -0
  62. package/apps/runtime/dist/db/schema.js +278 -0
  63. package/apps/runtime/dist/documents/parse.js +230 -0
  64. package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
  65. package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
  66. package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
  67. package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
  68. package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
  69. package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
  70. package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
  71. package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
  72. package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
  73. package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
  74. package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
  75. package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
  76. package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
  77. package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
  78. package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
  79. package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +359 -0
  80. package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
  81. package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
  82. package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
  83. package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
  84. package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
  85. package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
  86. package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
  87. package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
  88. package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
  89. package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +464 -0
  90. package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
  91. package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
  92. package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
  93. package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
  94. package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
  95. package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
  96. package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
  97. package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
  98. package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
  99. package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
  100. package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
  101. package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
  102. package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
  103. package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
  104. package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
  105. package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
  106. package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
  107. package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
  108. package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
  109. package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
  110. package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
  111. package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
  112. package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
  113. package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
  114. package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
  115. package/apps/runtime/dist/engenty/shims/web-ingest.js +3 -0
  116. package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
  117. package/apps/runtime/dist/engine/asks.js +60 -0
  118. package/apps/runtime/dist/engine/events.js +46 -0
  119. package/apps/runtime/dist/engine/input.js +170 -0
  120. package/apps/runtime/dist/engine/prepare.js +51 -0
  121. package/apps/runtime/dist/engine/requirements.js +124 -0
  122. package/apps/runtime/dist/engine/resources.js +89 -0
  123. package/apps/runtime/dist/engine/runner.js +560 -0
  124. package/apps/runtime/dist/engine/steps.js +598 -0
  125. package/apps/runtime/dist/engine/template.js +183 -0
  126. package/apps/runtime/dist/engine/types.js +3 -0
  127. package/apps/runtime/dist/env.js +224 -0
  128. package/apps/runtime/dist/files/blobs.js +22 -0
  129. package/apps/runtime/dist/files/objects.js +86 -0
  130. package/apps/runtime/dist/files/storage.js +95 -0
  131. package/apps/runtime/dist/geocode.js +58 -0
  132. package/apps/runtime/dist/harness/claude.js +138 -0
  133. package/apps/runtime/dist/harness/codex.js +228 -0
  134. package/apps/runtime/dist/harness/cursor.js +93 -0
  135. package/apps/runtime/dist/harness/env.js +124 -0
  136. package/apps/runtime/dist/harness/gemini.js +126 -0
  137. package/apps/runtime/dist/harness/index.js +99 -0
  138. package/apps/runtime/dist/harness/model.js +267 -0
  139. package/apps/runtime/dist/harness/prompt.js +121 -0
  140. package/apps/runtime/dist/harness/terminal.js +193 -0
  141. package/apps/runtime/dist/harness/types.js +7 -0
  142. package/apps/runtime/dist/index.js +76 -0
  143. package/apps/runtime/dist/limits.js +57 -0
  144. package/apps/runtime/dist/link-preview.js +59 -0
  145. package/apps/runtime/dist/manage.js +151 -0
  146. package/apps/runtime/dist/mcp/auth.js +102 -0
  147. package/apps/runtime/dist/mcp/bridge.js +59 -0
  148. package/apps/runtime/dist/mcp/handler.js +42 -0
  149. package/apps/runtime/dist/mcp/scopes.js +5 -0
  150. package/apps/runtime/dist/mcp/tools.js +401 -0
  151. package/apps/runtime/dist/media/ffmpeg.js +121 -0
  152. package/apps/runtime/dist/media/generate.js +120 -0
  153. package/apps/runtime/dist/media/marking.js +121 -0
  154. package/apps/runtime/dist/media/transcribe.js +30 -0
  155. package/apps/runtime/dist/model-errors.js +3 -0
  156. package/apps/runtime/dist/models.js +489 -0
  157. package/apps/runtime/dist/plugin.js +61 -0
  158. package/apps/runtime/dist/render/chromium.js +85 -0
  159. package/apps/runtime/dist/render/convert.js +161 -0
  160. package/apps/runtime/dist/render/downloads.js +277 -0
  161. package/apps/runtime/dist/render/guard.js +25 -0
  162. package/apps/runtime/dist/routes/api.js +74 -0
  163. package/apps/runtime/dist/routes/delivery.js +52 -0
  164. package/apps/runtime/dist/routes/internal.js +49 -0
  165. package/apps/runtime/dist/routes/marketplace.js +36 -0
  166. package/apps/runtime/dist/routes/runs.js +805 -0
  167. package/apps/runtime/dist/routes/studio.js +702 -0
  168. package/apps/runtime/dist/routes/wizard-stream.js +30 -0
  169. package/apps/runtime/dist/running.js +39 -0
  170. package/apps/runtime/dist/sandbox/agentos.js +191 -0
  171. package/apps/runtime/dist/sandbox/docker.js +77 -0
  172. package/apps/runtime/dist/sandbox/index.js +30 -0
  173. package/apps/runtime/dist/sandbox/types.js +1 -0
  174. package/apps/runtime/dist/secrets/crypto.js +28 -0
  175. package/apps/runtime/dist/secrets/signing.js +34 -0
  176. package/apps/runtime/dist/secrets/vault.js +59 -0
  177. package/apps/runtime/dist/services/architect.js +92 -0
  178. package/apps/runtime/dist/services/brand.js +20 -0
  179. package/apps/runtime/dist/services/cloud.js +52 -0
  180. package/apps/runtime/dist/services/draft-events.js +27 -0
  181. package/apps/runtime/dist/services/errors.js +24 -0
  182. package/apps/runtime/dist/services/files.js +129 -0
  183. package/apps/runtime/dist/services/links.js +16 -0
  184. package/apps/runtime/dist/services/marketplace.js +292 -0
  185. package/apps/runtime/dist/services/package.js +202 -0
  186. package/apps/runtime/dist/services/profile.js +23 -0
  187. package/apps/runtime/dist/services/project-files.js +266 -0
  188. package/apps/runtime/dist/services/project-index.js +109 -0
  189. package/apps/runtime/dist/services/projects.js +181 -0
  190. package/apps/runtime/dist/services/runs.js +224 -0
  191. package/apps/runtime/dist/services/shares.js +129 -0
  192. package/apps/runtime/dist/services/widgets.js +34 -0
  193. package/apps/runtime/dist/services/wizards.js +342 -0
  194. package/apps/runtime/dist/settings.js +16 -0
  195. package/apps/runtime/dist/store/index.js +279 -0
  196. package/apps/runtime/dist/tenants/control.js +106 -0
  197. package/apps/runtime/dist/tenants/tenant.js +26 -0
  198. package/apps/runtime/dist/tools/browser.js +380 -0
  199. package/apps/runtime/dist/tools/connector.js +204 -0
  200. package/apps/runtime/dist/tools/index.js +234 -0
  201. package/apps/runtime/dist/tools/mail.js +104 -0
  202. package/apps/runtime/dist/tools/net-guard.js +59 -0
  203. package/apps/runtime/dist/tools/project.js +53 -0
  204. package/apps/runtime/dist/tools/shared.js +42 -0
  205. package/apps/runtime/dist/tools/store.js +238 -0
  206. package/apps/runtime/dist/update.js +118 -0
  207. package/apps/runtime/dist/widgets/bundle.js +99 -0
  208. package/apps/runtime/dist/widgets/render.js +312 -0
  209. package/apps/runtime/dist/widgets/runtime.js +84 -0
  210. package/apps/runtime/dist/widgets/script.js +30 -0
  211. package/apps/runtime/dist/widgets/step.js +192 -0
  212. package/apps/web/dist/ai-labels/ai-black.svg +20 -0
  213. package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
  214. package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
  215. package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
  216. package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
  217. package/apps/web/dist/ai-labels/ai-white.svg +21 -0
  218. package/apps/web/dist/assets/ChangelogDialog-O00vEnbm.js +1 -0
  219. package/apps/web/dist/assets/ChatPanel-CH9ry0Hp.js +1 -0
  220. package/apps/web/dist/assets/CreditsDialog-DRzecwUw.js +1 -0
  221. package/apps/web/dist/assets/EditorPage-BRnBf02Q.js +2 -0
  222. package/apps/web/dist/assets/FlowPreview-DDOj8IAH.js +1 -0
  223. package/apps/web/dist/assets/HomePage-CAGTTG3N.js +1 -0
  224. package/apps/web/dist/assets/ImportWizard-0RRrAnX3.js +1 -0
  225. package/apps/web/dist/assets/LocalRuntime-BrP-ENHg.css +1 -0
  226. package/apps/web/dist/assets/LocalRuntime-C-TBYrzs.js +16 -0
  227. package/apps/web/dist/assets/NewWizardPage-kI90h3_9.js +2 -0
  228. package/apps/web/dist/assets/PublicRunner-CKRDeIVd.js +1 -0
  229. package/apps/web/dist/assets/RunnerView-Rc4H8wYH.js +2 -0
  230. package/apps/web/dist/assets/SettingsPage-CESMuZxq.js +2 -0
  231. package/apps/web/dist/assets/SetupPage-D1rrYU14.js +1 -0
  232. package/apps/web/dist/assets/SharePage-COTAmOgh.js +1 -0
  233. package/apps/web/dist/assets/api-BY28cjGY.js +10 -0
  234. package/apps/web/dist/assets/arrow-left-UpjOBfQp.js +1 -0
  235. package/apps/web/dist/assets/arrow-right-CucQycEy.js +1 -0
  236. package/apps/web/dist/assets/changelog-p3wsaDDS.js +1 -0
  237. package/apps/web/dist/assets/check-Bjx41xbB.js +1 -0
  238. package/apps/web/dist/assets/createLucideIcon-DBu2Ovxj.js +1 -0
  239. package/apps/web/dist/assets/definition-cy7uvY5L.js +55 -0
  240. package/apps/web/dist/assets/engenty-CWIFpgKq.js +1 -0
  241. package/apps/web/dist/assets/esm-D1OEhjTK.js +7 -0
  242. package/apps/web/dist/assets/external-link-CRg6DVdO.js +1 -0
  243. package/apps/web/dist/assets/fluffy-engenty-CJ3wCQgT.js +456 -0
  244. package/apps/web/dist/assets/index-CQ_q9iMO.css +1 -0
  245. package/apps/web/dist/assets/index-D0gxh90t.js +10 -0
  246. package/apps/web/dist/assets/jsx-runtime-Dk72oS4N.js +1 -0
  247. package/apps/web/dist/assets/meta-BbSdtTUa.js +1 -0
  248. package/apps/web/dist/assets/mic-CeqQ89Dj.js +1 -0
  249. package/apps/web/dist/assets/oss-credits-cPuZUFHD.js +1 -0
  250. package/apps/web/dist/assets/outputs-D6pxH6ve.js +69 -0
  251. package/apps/web/dist/assets/plus-HA210wXA.js +1 -0
  252. package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
  253. package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
  254. package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
  255. package/apps/web/dist/assets/type-BzYgVWKL.js +1 -0
  256. package/apps/web/dist/assets/ui-Ddwl35A6.js +1 -0
  257. package/apps/web/dist/assets/upload-DsgLfQ3U.js +1 -0
  258. package/apps/web/dist/assets/video-Dk1fuTDl.js +1 -0
  259. package/apps/web/dist/assets/wand-sparkles-Bf97fs8T.js +1 -0
  260. package/apps/web/dist/embed.js +102 -0
  261. package/apps/web/dist/favicon.svg +1 -0
  262. package/apps/web/dist/icons/apple-touch-icon.png +0 -0
  263. package/apps/web/dist/icons/icon-192.png +0 -0
  264. package/apps/web/dist/icons/icon-512.png +0 -0
  265. package/apps/web/dist/icons/icon-maskable-512.png +0 -0
  266. package/apps/web/dist/index.html +46 -0
  267. package/apps/web/dist/install.sh +532 -0
  268. package/apps/web/dist/manifest.webmanifest +20 -0
  269. package/apps/web/dist/sw.js +15 -0
  270. package/bin/wizards.mjs +13 -0
  271. package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
  272. package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
  273. package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +1415 -0
  274. package/node_modules/@engenty-wizards/shared/dist/definition.js +762 -0
  275. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
  276. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
  277. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
  278. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
  279. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
  280. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +216 -0
  281. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
  282. package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
  283. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
  284. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
  285. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
  286. package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
  287. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
  288. package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +86 -0
  289. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
  290. package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +133 -0
  291. package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +298 -0
  292. package/node_modules/@engenty-wizards/shared/dist/marketplace.js +211 -0
  293. package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
  294. package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
  295. package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +74 -0
  296. package/node_modules/@engenty-wizards/shared/dist/projects.js +96 -0
  297. package/node_modules/@engenty-wizards/shared/dist/run.d.ts +219 -0
  298. package/node_modules/@engenty-wizards/shared/dist/run.js +1 -0
  299. package/node_modules/@engenty-wizards/shared/dist/store.d.ts +100 -0
  300. package/node_modules/@engenty-wizards/shared/dist/store.js +44 -0
  301. package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
  302. package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
  303. package/node_modules/@engenty-wizards/shared/package.json +10 -0
  304. package/package.json +62 -0
  305. package/plugin/.claude-plugin/plugin.json +9 -0
  306. package/plugin/.mcp.json +8 -0
  307. package/plugin/commands/wizard.md +8 -0
  308. package/plugin/skills/build-wizard/SKILL.md +27 -0
@@ -0,0 +1,560 @@
1
+ import { branchValues, dataRef, formatsFor, LIST_FORMATS, listRef, nextStepId, } from "@engenty-wizards/shared/definition";
2
+ import { eq } from "drizzle-orm";
3
+ import { nanoid } from "nanoid";
4
+ import { connectionViews } from "../connectors/index.js";
5
+ import { addLocalCost, canSpend, releaseRun, reserveForRun, syncRunCost, } from "../credits/credits.js";
6
+ import { estimateRun } from "../credits/estimate.js";
7
+ import { db, schema, withTenant } from "../db/client.js";
8
+ import { env } from "../env.js";
9
+ import { saveAsset } from "../files/storage.js";
10
+ import { managed, tenantInfo } from "../manage.js";
11
+ import { hasFfmpeg } from "../media/ffmpeg.js";
12
+ import { ModelUnavailableError } from "../models.js";
13
+ import { projectFiles } from "../services/project-files.js";
14
+ import { projectProfile } from "../services/projects.js";
15
+ import { listRows, scopeOf } from "../store/index.js";
16
+ import { activeRuns, indexRun, markRunActive } from "../tenants/control.js";
17
+ import { currentTenant } from "../tenants/tenant.js";
18
+ import { askPerson, clearStaleAsk, unattended } from "./asks.js";
19
+ import { emitEvent, recentEvents, signalChanged } from "./events.js";
20
+ import { readPageInput } from "./input.js";
21
+ import { blockingMessage, missingModels } from "./requirements.js";
22
+ import { releaseResources, resourcesFor } from "./resources.js";
23
+ import { runAutomaticStep } from "./steps.js";
24
+ import { resolveRef } from "./template.js";
25
+ import { StepError } from "./types.js";
26
+ /** A command the run cannot take in its current state. */
27
+ export class RunConflict extends Error {
28
+ }
29
+ export class RunInputError extends Error {
30
+ errors;
31
+ constructor(errors) {
32
+ super("Bitte die markierten Felder prüfen.");
33
+ this.errors = errors;
34
+ }
35
+ }
36
+ export class NoCreditsError extends Error {
37
+ constructor() {
38
+ super("Dieser Wizard hat gerade kein Guthaben mehr. Bitte später erneut versuchen.");
39
+ }
40
+ }
41
+ const active = new Map();
42
+ // --- a tenant's runs that work at the same time ---------------------------------
43
+ // Runs beyond the limit wait in line; nothing is refused.
44
+ const slots = new Map();
45
+ async function concurrencyLimit(tenant) {
46
+ if (!managed) {
47
+ return env.limits.concurrentRuns;
48
+ }
49
+ const info = await tenantInfo(tenant).catch(() => null);
50
+ return info?.limits.concurrentRuns || env.limits.concurrentRuns;
51
+ }
52
+ async function acquireSlot(tenant, signal) {
53
+ const limit = await concurrencyLimit(tenant);
54
+ let slot = slots.get(tenant);
55
+ if (!slot) {
56
+ slot = { busy: 0, waiting: [] };
57
+ slots.set(tenant, slot);
58
+ }
59
+ if (slot.busy < limit) {
60
+ slot.busy++;
61
+ return true;
62
+ }
63
+ const queue = slot.waiting;
64
+ return new Promise((resolve) => {
65
+ const go = () => {
66
+ signal.removeEventListener("abort", stop);
67
+ resolve(true);
68
+ };
69
+ const stop = () => {
70
+ queue.splice(queue.indexOf(go), 1);
71
+ resolve(false);
72
+ };
73
+ queue.push(go);
74
+ signal.addEventListener("abort", stop, { once: true });
75
+ });
76
+ }
77
+ function releaseSlot(tenant) {
78
+ const slot = slots.get(tenant);
79
+ if (!slot) {
80
+ return;
81
+ }
82
+ const next = slot.waiting.shift();
83
+ if (next) {
84
+ // The slot passes straight to the next run in line.
85
+ next();
86
+ }
87
+ else {
88
+ slot.busy--;
89
+ }
90
+ }
91
+ async function loadRun(runId) {
92
+ return db.query.run.findFirst({ where: eq(schema.run.id, runId) });
93
+ }
94
+ /** The project a run's wizard belongs to — where its imported connectors live. */
95
+ export async function projectIdOf(run) {
96
+ const w = await db.query.wizard.findFirst({ where: eq(schema.wizard.id, run.wizardId) });
97
+ return w?.projectId ?? "";
98
+ }
99
+ async function loadProject(run) {
100
+ const w = await db.query.wizard.findFirst({ where: eq(schema.wizard.id, run.wizardId) });
101
+ const p = w && (await db.query.project.findFirst({ where: eq(schema.project.id, w.projectId) }));
102
+ if (!p) {
103
+ throw new Error("project missing");
104
+ }
105
+ return p;
106
+ }
107
+ async function updateRun(runId, patch) {
108
+ await db
109
+ .update(schema.run)
110
+ .set({ ...patch, updatedAt: new Date() })
111
+ .where(eq(schema.run.id, runId));
112
+ // A run that ended needs no credits held for it any more.
113
+ if (patch.status === "done" || patch.status === "failed" || patch.status === "cancelled") {
114
+ await releaseRun(runId);
115
+ }
116
+ signalChanged(runId);
117
+ }
118
+ function stepOf(def, id) {
119
+ return id ? def.steps.find((s) => s.id === id) : undefined;
120
+ }
121
+ function friendly(err) {
122
+ if (err instanceof StepError || err instanceof ModelUnavailableError) {
123
+ return err.message;
124
+ }
125
+ const msg = err?.message ?? String(err);
126
+ // The model-gateway answers 402 once the tenant's credits are used up.
127
+ if (/insufficient_credits|\b402\b/i.test(msg)) {
128
+ return new NoCreditsError().message;
129
+ }
130
+ // A runtime that runs alone pays its provider itself: its admin can top the account up.
131
+ if (!managed && /minimum balance|insufficient_funds|top up your credits/i.test(msg)) {
132
+ return "Das Guthaben beim Modell-Anbieter reicht dafür nicht aus (Videos brauchen dort ein Mindestguthaben). Bitte dort aufladen und noch einmal versuchen.";
133
+ }
134
+ if (/rate.?limit|429/i.test(msg)) {
135
+ return "Der KI-Dienst ist gerade ausgelastet. Bitte gleich noch einmal versuchen.";
136
+ }
137
+ if (/timeout|timed out/i.test(msg)) {
138
+ return "Der Schritt hat zu lange gedauert. Bitte noch einmal versuchen.";
139
+ }
140
+ // The platform's own provider account (budget, quota, key): nothing the person can fix.
141
+ if (/budget|quota|insufficient|billing|credit balance|api key|unauthori[sz]ed|401|403/i.test(msg)) {
142
+ return "Der KI-Dienst ist gerade nicht erreichbar. Bitte später noch einmal versuchen.";
143
+ }
144
+ return `Dieser Schritt ist fehlgeschlagen: ${msg.slice(0, 300)}`;
145
+ }
146
+ // --- creating & driving ------------------------------------------------------
147
+ export async function createRun(input) {
148
+ const id = nanoid(18);
149
+ const first = input.definition.steps[0];
150
+ const state = { values: {}, outputs: {}, history: [], notes: {} };
151
+ // A step every run passes through needs a model this runtime cannot serve: refuse before anything is held.
152
+ const blocked = blockingMessage(await missingModels(input.definition));
153
+ if (blocked) {
154
+ throw new ModelUnavailableError(blocked);
155
+ }
156
+ // The run's expected cost is held before it starts; what it really costs is booked per call.
157
+ const estimate = await estimateRun(input.wizardId, input.version, input.definition);
158
+ if (!(await reserveForRun(id, estimate.reserve))) {
159
+ throw new NoCreditsError();
160
+ }
161
+ await db.insert(schema.run).values({
162
+ id,
163
+ wizardId: input.wizardId,
164
+ tenantId: currentTenant(),
165
+ definition: input.definition,
166
+ files: input.files,
167
+ version: input.version,
168
+ mode: input.mode,
169
+ visitorId: input.visitorId ?? null,
170
+ userId: input.userId ?? null,
171
+ ipHash: input.ipHash ?? null,
172
+ status: first.type === "page" ? "waiting_input" : "running",
173
+ cursor: first.id,
174
+ state,
175
+ // Without an account nobody can come back for a result later: it is kept a week.
176
+ expiresAt: input.mode === "live"
177
+ ? new Date(Date.now() + env.limits.resultTtlDays * 24 * 60 * 60 * 1000)
178
+ : null,
179
+ });
180
+ await indexRun({ runId: id, visitorId: input.visitorId, ipHash: input.ipHash });
181
+ if (first.type !== "page") {
182
+ kick(id);
183
+ }
184
+ return id;
185
+ }
186
+ export function kick(runId) {
187
+ if (active.has(runId)) {
188
+ return;
189
+ }
190
+ const abort = new AbortController();
191
+ active.set(runId, abort);
192
+ const tenant = currentTenant();
193
+ const work = async () => {
194
+ await markRunActive(runId, true);
195
+ if (!(await acquireSlot(tenant, abort.signal))) {
196
+ return;
197
+ }
198
+ try {
199
+ await drive(runId, abort.signal);
200
+ }
201
+ finally {
202
+ releaseSlot(tenant);
203
+ }
204
+ };
205
+ work()
206
+ .catch(async (err) => {
207
+ console.error(`[run ${runId}]`, err);
208
+ await updateRun(runId, { status: "failed", error: friendly(err) }).catch(() => undefined);
209
+ })
210
+ .finally(async () => {
211
+ active.delete(runId);
212
+ await markRunActive(runId, false).catch(() => undefined);
213
+ await releaseResources(runId);
214
+ signalChanged(runId);
215
+ });
216
+ }
217
+ /** The wizard's lists with the person's rows, by list id. */
218
+ async function storedLists(run) {
219
+ const scope = scopeOf(run);
220
+ const out = {};
221
+ for (const def of run.definition.lists ?? []) {
222
+ out[def.id] = { def, rows: await listRows(scope, def.id) };
223
+ }
224
+ return out;
225
+ }
226
+ async function makeContext(run, project, state, signal) {
227
+ const store = scopeOf(run);
228
+ const resources = resourcesFor(run.id);
229
+ resources.bind(store);
230
+ const stepId = run.cursor ?? "";
231
+ return {
232
+ runId: run.id,
233
+ tenantId: run.tenantId,
234
+ stepId,
235
+ store,
236
+ def: run.definition,
237
+ files: run.files,
238
+ state,
239
+ scope: {
240
+ def: run.definition,
241
+ state,
242
+ brand: projectProfile(project),
243
+ lists: await storedLists(run),
244
+ },
245
+ project,
246
+ projectFiles: (await projectFiles(project.id)).filter((f) => f.status === "ready"),
247
+ signal,
248
+ resources,
249
+ ask: (ask) => unattended.has(run.id)
250
+ ? Promise.resolve(null)
251
+ : askPerson(run.id, { ...ask, stepId }, signal),
252
+ emit: (type, message, asset) => emitEvent(run.id, run.cursor, type, message, asset),
253
+ call: { runId: run.id, stepId },
254
+ chargeUsd: (usd) => addLocalCost(run.id, stepId, usd),
255
+ saveAsset: (input) => saveAsset({
256
+ ...input,
257
+ runId: run.id,
258
+ stepId: input.stepId ?? run.cursor,
259
+ }),
260
+ };
261
+ }
262
+ async function drive(runId, signal) {
263
+ await clearStaleAsk(runId);
264
+ while (!signal.aborted) {
265
+ const run = await loadRun(runId);
266
+ if (run?.status !== "running") {
267
+ return;
268
+ }
269
+ const def = run.definition;
270
+ const step = stepOf(def, run.cursor);
271
+ if (!step) {
272
+ await updateRun(runId, { status: "done" });
273
+ return;
274
+ }
275
+ if (step.type === "result") {
276
+ await updateRun(runId, { status: "done" });
277
+ return;
278
+ }
279
+ if (step.type === "page" || step.type === "review") {
280
+ await updateRun(runId, { status: "waiting_input" });
281
+ return;
282
+ }
283
+ if (!(await canSpend())) {
284
+ const message = new NoCreditsError().message;
285
+ await emitEvent(runId, step.id, "error", message);
286
+ await updateRun(runId, { status: "failed", error: message });
287
+ return;
288
+ }
289
+ await emitEvent(runId, step.id, "step_started", step.working ?? step.title);
290
+ const project = await loadProject(run);
291
+ const state = structuredClone(run.state);
292
+ try {
293
+ const output = await runAutomaticStep(step, await makeContext(run, project, state, signal));
294
+ if (signal.aborted) {
295
+ return;
296
+ }
297
+ await syncRunCost(runId);
298
+ state.outputs[step.id] = output;
299
+ delete state.notes[step.id];
300
+ delete state.redo?.[step.id];
301
+ const cursor = nextStepId(def, step.id, branchValues(state.values, state.outputs));
302
+ await updateRun(runId, { state, cursor, status: cursor ? "running" : "done", error: null });
303
+ await emitEvent(runId, step.id, "step_done", step.title);
304
+ }
305
+ catch (err) {
306
+ if (signal.aborted) {
307
+ return;
308
+ }
309
+ console.error(`[run ${runId} step ${step.id}]`, err);
310
+ const message = friendly(err);
311
+ await emitEvent(runId, step.id, "error", message);
312
+ await updateRun(runId, { status: "failed", error: message });
313
+ return;
314
+ }
315
+ }
316
+ }
317
+ /** Runs a restart left mid-step go on where they were. */
318
+ export async function resumeInterruptedRuns() {
319
+ for (const r of await activeRuns()) {
320
+ await withTenant(r.tenantId, async () => {
321
+ const run = await loadRun(r.runId);
322
+ if (run?.status === "running") {
323
+ kick(r.runId);
324
+ }
325
+ else {
326
+ await markRunActive(r.runId, false);
327
+ }
328
+ }).catch((err) => console.error(`[resume ${r.runId}]`, err));
329
+ }
330
+ }
331
+ // --- commands ----------------------------------------------------------------
332
+ async function requireWaiting(runId, stepId) {
333
+ const run = await loadRun(runId);
334
+ if (!run) {
335
+ throw new RunConflict("Run not found");
336
+ }
337
+ if (run.status !== "waiting_input" && run.status !== "done") {
338
+ throw new RunConflict("Der Wizard arbeitet gerade.");
339
+ }
340
+ if (run.cursor !== stepId) {
341
+ throw new RunConflict("Diese Seite ist nicht mehr aktuell.");
342
+ }
343
+ return run;
344
+ }
345
+ export async function submitPage(runId, stepId, input) {
346
+ const run = await requireWaiting(runId, stepId);
347
+ const step = stepOf(run.definition, stepId);
348
+ if (step?.type !== "page") {
349
+ throw new RunConflict("Not a page");
350
+ }
351
+ const { values, errors } = readPageInput(step, input);
352
+ if (errors.length) {
353
+ throw new RunInputError(errors);
354
+ }
355
+ const connections = step.fields.some((f) => f.kind === "connection")
356
+ ? await connectionViews(run.definition.connections ?? [], scopeOf(run), await projectIdOf(run))
357
+ : [];
358
+ for (const field of step.fields) {
359
+ if (field.kind === "image" || field.kind === "file") {
360
+ const value = values[field.id];
361
+ for (const id of Array.isArray(value) ? value : value ? [value] : []) {
362
+ const asset = await db.query.asset.findFirst({ where: eq(schema.asset.id, String(id)) });
363
+ if (asset?.runId !== runId) {
364
+ throw new RunInputError([{ field: field.id, message: "Datei nicht gefunden" }]);
365
+ }
366
+ }
367
+ }
368
+ if (field.kind === "connection") {
369
+ // What the step later reads as {{field}} is the connected account, as the server knows it.
370
+ const account = connections.find((c) => c.id === field.connection)?.account;
371
+ if (account) {
372
+ values[field.id] = account.label;
373
+ }
374
+ else if (field.required) {
375
+ throw new RunInputError([{ field: field.id, message: "Bitte zuerst verbinden" }]);
376
+ }
377
+ }
378
+ }
379
+ const state = structuredClone(run.state);
380
+ state.values = { ...state.values, ...values };
381
+ // Fields left empty on a revisited page are cleared, not kept from before.
382
+ for (const field of step.fields) {
383
+ if (!(field.id in values)) {
384
+ delete state.values[field.id];
385
+ }
386
+ }
387
+ state.history.push(stepId);
388
+ const cursor = nextStepId(run.definition, stepId, branchValues(state.values, state.outputs));
389
+ await updateRun(runId, { state, cursor, status: "running", error: null });
390
+ kick(runId);
391
+ }
392
+ export async function reviewStep(runId, stepId, action) {
393
+ const run = await requireWaiting(runId, stepId);
394
+ const step = stepOf(run.definition, stepId);
395
+ if (step?.type !== "review") {
396
+ throw new RunConflict("Not a review");
397
+ }
398
+ const state = structuredClone(run.state);
399
+ if (action.type === "accept") {
400
+ for (const [target, text] of Object.entries(action.edits ?? {})) {
401
+ if (step.edit && step.show.includes(target) && state.outputs[target]) {
402
+ state.outputs[target] = { ...state.outputs[target], text: String(text).slice(0, 50_000) };
403
+ }
404
+ }
405
+ state.history.push(stepId);
406
+ const cursor = nextStepId(run.definition, stepId, branchValues(state.values, state.outputs));
407
+ await updateRun(runId, { state, cursor, status: "running", error: null });
408
+ kick(runId);
409
+ return;
410
+ }
411
+ if (!step.show.includes(action.target)) {
412
+ throw new RunConflict("Unknown target");
413
+ }
414
+ state.notes[action.target] = action.note.slice(0, 2000) || "Bitte eine neue Variante.";
415
+ // A step with several results makes only the named ones again.
416
+ if (action.items?.length) {
417
+ state.redo = { ...state.redo, [action.target]: action.items };
418
+ }
419
+ else {
420
+ delete state.redo?.[action.target];
421
+ }
422
+ await updateRun(runId, { state, cursor: action.target, status: "running", error: null });
423
+ await emitEvent(runId, action.target, "info", "Wird neu erstellt …");
424
+ kick(runId);
425
+ }
426
+ export async function goBack(runId) {
427
+ const run = await loadRun(runId);
428
+ if (!run ||
429
+ (run.status !== "waiting_input" && run.status !== "done" && run.status !== "failed")) {
430
+ throw new RunConflict("Der Wizard arbeitet gerade.");
431
+ }
432
+ const state = structuredClone(run.state);
433
+ const previous = state.history.pop();
434
+ if (!previous) {
435
+ throw new RunConflict("Kein vorheriger Schritt.");
436
+ }
437
+ await updateRun(runId, { state, cursor: previous, status: "waiting_input", error: null });
438
+ }
439
+ export async function retry(runId) {
440
+ const run = await loadRun(runId);
441
+ if (run?.status !== "failed") {
442
+ throw new RunConflict("Nothing to retry");
443
+ }
444
+ await updateRun(runId, { status: "running", error: null });
445
+ kick(runId);
446
+ }
447
+ export async function cancel(runId) {
448
+ active.get(runId)?.abort();
449
+ await updateRun(runId, { status: "cancelled" });
450
+ }
451
+ // --- view --------------------------------------------------------------------
452
+ /** The formats a deliverable can really be downloaded in: a still widget has no video. */
453
+ export async function availableFormats(step, run, wanted) {
454
+ const possible = formatsFor(step);
455
+ let formats = wanted ? wanted.filter((f) => possible.includes(f)) : possible;
456
+ const output = run.state.outputs[step.id];
457
+ if (step.type === "widget" && formats.includes("mp4")) {
458
+ // A film is rendered when its step runs; any other widget on demand.
459
+ const has = step.video
460
+ ? output?.assets?.some((a) => a.kind === "video")
461
+ : output?.widget?.duration && (await hasFfmpeg());
462
+ if (!has) {
463
+ formats = formats.filter((f) => f !== "mp4");
464
+ }
465
+ }
466
+ // A zip holds the files a step collected, or its several results; with one there is nothing to zip.
467
+ if (formats.includes("zip")) {
468
+ const has = step.type === "generate"
469
+ ? (output?.assets?.length ?? 0) > 1
470
+ : output?.assets?.some((a) => a.kind === "file");
471
+ if (!has) {
472
+ formats = formats.filter((f) => f !== "zip");
473
+ }
474
+ }
475
+ return formats;
476
+ }
477
+ /** What the page's fields start with, where they name an earlier step's result. */
478
+ function prefillOf(step, run) {
479
+ const scope = { def: run.definition, state: run.state, brand: {} };
480
+ const out = {};
481
+ for (const field of step.fields) {
482
+ if (!field.prefill) {
483
+ continue;
484
+ }
485
+ const value = resolveRef(dataRef(field.prefill), scope);
486
+ if (value !== undefined && value !== null && value !== "") {
487
+ out[field.id] = value;
488
+ }
489
+ }
490
+ return out;
491
+ }
492
+ export async function runView(run, brand) {
493
+ const def = run.definition;
494
+ const step = stepOf(def, run.cursor) ?? null;
495
+ const index = step ? def.steps.indexOf(step) : def.steps.length;
496
+ const refs = step?.type === "review"
497
+ ? step.show
498
+ : step?.type === "result"
499
+ ? [...new Set(step.deliverables.map((d) => d.from))]
500
+ : [];
501
+ const shownIds = refs.filter((ref) => !listRef(ref));
502
+ const listIds = [
503
+ ...refs.map(listRef),
504
+ ...(step?.type === "page" ? step.fields.map((f) => (f.kind === "list" ? f.list : null)) : []),
505
+ ].filter((id) => Boolean(id));
506
+ const stored = listIds.length ? await storedLists(run) : {};
507
+ const lists = [...new Set(listIds)]
508
+ .filter((id) => stored[id])
509
+ .map((id) => {
510
+ const deliverable = step?.type === "result" ? step.deliverables.find((d) => listRef(d.from) === id) : undefined;
511
+ return {
512
+ ...stored[id],
513
+ formats: deliverable
514
+ ? deliverable.formats.filter((f) => LIST_FORMATS.includes(f) && (f !== "zip" || stored[id].def.check?.file))
515
+ : [],
516
+ label: deliverable?.label ?? null,
517
+ };
518
+ });
519
+ const shown = await Promise.all(shownIds
520
+ .map((id) => stepOf(def, id))
521
+ .filter((s) => Boolean(s))
522
+ .map(async (s) => {
523
+ const deliverable = step?.type === "result" ? step.deliverables.find((d) => d.from === s.id) : undefined;
524
+ return {
525
+ step: s,
526
+ output: run.state.outputs[s.id] ?? null,
527
+ formats: await availableFormats(s, run, deliverable?.formats),
528
+ label: deliverable?.label ?? null,
529
+ };
530
+ }));
531
+ return {
532
+ id: run.id,
533
+ status: run.status,
534
+ mode: run.mode,
535
+ wizard: {
536
+ title: def.title,
537
+ description: def.description,
538
+ avatar: def.avatar,
539
+ intro: def.intro,
540
+ },
541
+ step,
542
+ values: run.state.values,
543
+ prefill: step?.type === "page" ? prefillOf(step, run) : {},
544
+ outputs: Object.fromEntries(shownIds.map((id) => [id, run.state.outputs[id]]).filter(([, o]) => o)),
545
+ shown,
546
+ progress: { done: run.status === "done" ? def.steps.length : index, total: def.steps.length },
547
+ canBack: run.state.history.length > 0 && run.status !== "running",
548
+ error: run.error,
549
+ events: await recentEvents(run.id, 0, 30),
550
+ brand,
551
+ ask: run.status === "running" ? run.ask : null,
552
+ lists,
553
+ connections: step?.type === "page" && step.fields.some((f) => f.kind === "connection")
554
+ ? await connectionViews(def.connections ?? [], scopeOf(run), await projectIdOf(run))
555
+ : [],
556
+ keeps: Boolean(def.lists?.length || def.connections?.length),
557
+ shareUrl: run.shareToken ? `${env.appUrl}/s/${run.shareToken}` : null,
558
+ expiresAt: run.expiresAt?.toISOString() ?? null,
559
+ };
560
+ }