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,329 @@
1
+ import { createHash, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { userInfo } from "node:os";
3
+ import { eq, lt } from "drizzle-orm";
4
+ import { Hono } from "hono";
5
+ import { deleteCookie, getCookie, setCookie } from "hono/cookie";
6
+ import { nanoid } from "nanoid";
7
+ import { control, controlDb } from "../db/client.js";
8
+ import { basePath, env } from "../env.js";
9
+ import { discovery, managed, tokenRequest, verifyToken, } from "../manage.js";
10
+ import { seal, unseal } from "../secrets/crypto.js";
11
+ import { LOCAL_TENANT } from "../tenants/tenant.js";
12
+ import { finishLink } from "./account.js";
13
+ import { localTicketExpiry } from "./local-ticket.js";
14
+ const secure = env.appUrl.startsWith("https");
15
+ // --- a runtime that runs alone ------------------------------------------------
16
+ // One person, one tenant. The studio answers only with a cookie that is set by opening the
17
+ // one-time link once: a web page in the same browser cannot reach it.
18
+ const LOCAL_COOKIE = "wz_local";
19
+ const localCookieValue = createHmac("sha256", env.authSecret).update("local-studio").digest("hex");
20
+ let accessKey = managed
21
+ ? null
22
+ : env.local.accessKey || randomBytes(24).toString("hex");
23
+ /** The link that lets the person in; printed at start, opened by the desktop app. */
24
+ export function localEntryUrl() {
25
+ return accessKey ? `${env.appUrl}/api/local/enter?k=${accessKey}` : null;
26
+ }
27
+ const localUser = () => ({
28
+ id: "local",
29
+ tenantId: LOCAL_TENANT,
30
+ role: "owner",
31
+ name: userInfo().username || "Admin",
32
+ email: "",
33
+ });
34
+ function sameValue(a, b) {
35
+ const x = Buffer.from(a);
36
+ const y = Buffer.from(b);
37
+ return x.length === y.length && timingSafeEqual(x, y);
38
+ }
39
+ function setLocalCookie(c) {
40
+ setCookie(c, LOCAL_COOKIE, localCookieValue, {
41
+ httpOnly: true,
42
+ sameSite: "Strict",
43
+ secure,
44
+ path: cookiePath,
45
+ maxAge: 60 * 60 * 24 * 365,
46
+ });
47
+ }
48
+ // --- signed in at the Manage-App ------------------------------------------------
49
+ const SESSION_COOKIE = "wz_session";
50
+ const STATE_COOKIE = "wz_oauth";
51
+ const SESSION_DAYS = 30;
52
+ const SCOPE = "openid profile email offline_access wizards:read wizards:write wizards:publish runs:test";
53
+ // The desktop app shows a server in its window but signs in through the system browser
54
+ // (Google refuses embedded views). The finished session travels back as a one-time code in an
55
+ // `engenty-wizards://` link; it only counts in the window that asked for it, which holds the
56
+ // matching cookie — so a link sent by some web page signs nobody in.
57
+ const DESKTOP_COOKIE = "wz_desktop";
58
+ const usedHandoffs = new Set();
59
+ /** Tickets of the local one-time link that were opened, until they run out. */
60
+ const usedTickets = new Map();
61
+ const sessions = new Map();
62
+ const client = () => ({ id: env.manage.clientId, secret: env.manage.clientSecret || undefined });
63
+ /** Cookies and redirects stay under the path the app is served at. */
64
+ const cookiePath = basePath || "/";
65
+ /** Where a sign-in and the local link lead: the studio. */
66
+ const home = `${basePath}/studio/`;
67
+ const callbackUrl = () => `${env.appUrl}/api/auth/callback`;
68
+ function safeReturn(path) {
69
+ return path?.startsWith("/") && !path.startsWith("//") ? path : home;
70
+ }
71
+ function setSessionCookie(c, id) {
72
+ setCookie(c, SESSION_COOKIE, id, {
73
+ httpOnly: true,
74
+ sameSite: "Lax",
75
+ secure,
76
+ path: cookiePath,
77
+ maxAge: SESSION_DAYS * 24 * 3600,
78
+ });
79
+ }
80
+ async function claimsOf(tokens) {
81
+ const claims = await verifyToken(tokens.access_token, [env.appUrl]);
82
+ if (!claims) {
83
+ throw new Error("The Manage-App's token did not verify.");
84
+ }
85
+ return claims;
86
+ }
87
+ /** Renews tenant and role from the Manage-App once the access token they came from has run out. */
88
+ async function renew(row) {
89
+ const refresh = row.refreshToken ? unseal(row.refreshToken) : null;
90
+ if (!refresh) {
91
+ return null;
92
+ }
93
+ try {
94
+ const tokens = await tokenRequest({ grant_type: "refresh_token", refresh_token: refresh, resource: env.appUrl }, client());
95
+ const claims = await claimsOf(tokens);
96
+ const next = {
97
+ ...row,
98
+ tenantId: claims.tenantId,
99
+ role: claims.role,
100
+ name: claims.name || row.name,
101
+ email: claims.email || row.email,
102
+ refreshToken: tokens.refresh_token ? seal(tokens.refresh_token) : row.refreshToken,
103
+ claimsExpireAt: new Date(claims.expiresAt),
104
+ };
105
+ await controlDb.update(control.session).set(next).where(eq(control.session.id, row.id));
106
+ return next;
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ async function sessionPrincipal(id) {
113
+ const hit = sessions.get(id);
114
+ let row = hit && Date.now() - hit.at < 60_000
115
+ ? hit.row
116
+ : await controlDb.query.session.findFirst({ where: eq(control.session.id, id) });
117
+ if (!row || row.expiresAt.getTime() < Date.now()) {
118
+ sessions.delete(id);
119
+ return null;
120
+ }
121
+ if (row.claimsExpireAt.getTime() < Date.now()) {
122
+ const renewed = await renew(row);
123
+ if (!renewed) {
124
+ await controlDb.delete(control.session).where(eq(control.session.id, id));
125
+ sessions.delete(id);
126
+ return null;
127
+ }
128
+ row = renewed;
129
+ }
130
+ sessions.set(id, { at: Date.now(), row });
131
+ return {
132
+ id: row.userId,
133
+ tenantId: row.tenantId,
134
+ role: row.role,
135
+ name: row.name,
136
+ email: row.email,
137
+ image: row.image,
138
+ };
139
+ }
140
+ /** Sessions that ran out go once an hour, with the retention job. */
141
+ export async function purgeSessions() {
142
+ await controlDb.delete(control.session).where(lt(control.session.expiresAt, new Date()));
143
+ }
144
+ // --- both ------------------------------------------------------------------------
145
+ export async function principalOf(c) {
146
+ if (!managed) {
147
+ const cookie = getCookie(c, LOCAL_COOKIE);
148
+ return cookie && sameValue(cookie, localCookieValue) ? localUser() : null;
149
+ }
150
+ const id = getCookie(c, SESSION_COOKIE);
151
+ return id ? sessionPrincipal(id) : null;
152
+ }
153
+ const closePage = (message) => `<!doctype html><meta charset="utf-8"><title>engenty wizards</title>
154
+ <body style="font:16px system-ui;display:grid;place-items:center;height:100vh;margin:0;color:#333">
155
+ <p>${message}</p>`;
156
+ export const authRoutes = new Hono()
157
+ // Local: the one-time link. The key works once per start; a ticket (`wizards open`,
158
+ // the desktop app entering a runtime that already runs) once within its minute.
159
+ .get("/local/enter", (c) => {
160
+ const given = c.req.query("k") ?? "";
161
+ const ticket = c.req.query("t") ?? "";
162
+ const now = Date.now();
163
+ for (const [used, expires] of usedTickets) {
164
+ if (expires <= now) {
165
+ usedTickets.delete(used);
166
+ }
167
+ }
168
+ const expires = !managed && ticket && !usedTickets.has(ticket)
169
+ ? localTicketExpiry(env.authSecret, ticket, now)
170
+ : null;
171
+ if (expires) {
172
+ usedTickets.set(ticket, expires);
173
+ }
174
+ else if (managed || !accessKey || !sameValue(given, accessKey)) {
175
+ return c.text("This link is no longer valid. Start the app again.", 403);
176
+ }
177
+ else {
178
+ accessKey = null;
179
+ }
180
+ setLocalCookie(c);
181
+ return c.redirect(home);
182
+ })
183
+ // Local development only: the "Dev-Login" button.
184
+ .post("/dev/login", (c) => {
185
+ if (managed || !env.devLogin) {
186
+ return c.notFound();
187
+ }
188
+ setLocalCookie(c);
189
+ return c.json({ ok: true });
190
+ })
191
+ // The desktop app's window asks for a sign-in that will run in the system browser.
192
+ .post("/auth/desktop/start", (c) => {
193
+ if (!managed) {
194
+ return c.notFound();
195
+ }
196
+ const desktop = randomBytes(24).toString("base64url");
197
+ setCookie(c, DESKTOP_COOKIE, desktop, {
198
+ httpOnly: true,
199
+ sameSite: "Lax",
200
+ secure,
201
+ path: `${basePath}/api/auth`,
202
+ maxAge: 900,
203
+ });
204
+ const ticket = seal({ desktop, exp: Date.now() + 15 * 60_000 });
205
+ return c.json({ url: `${env.appUrl}/api/auth/login?desktop=${encodeURIComponent(ticket)}` });
206
+ })
207
+ .get("/auth/handoff", async (c) => {
208
+ const code = c.req.query("code") ?? "";
209
+ const handoff = unseal(code);
210
+ const desktop = getCookie(c, DESKTOP_COOKIE);
211
+ deleteCookie(c, DESKTOP_COOKIE, { path: `${basePath}/api/auth` });
212
+ if (!managed ||
213
+ !handoff ||
214
+ handoff.exp < Date.now() ||
215
+ !desktop ||
216
+ !sameValue(desktop, handoff.desktop) ||
217
+ usedHandoffs.has(handoff.sid)) {
218
+ return c.redirect(`${home}?signin=failed`);
219
+ }
220
+ usedHandoffs.add(handoff.sid);
221
+ setSessionCookie(c, handoff.sid);
222
+ return c.redirect(home);
223
+ })
224
+ .get("/auth/login", async (c) => {
225
+ if (!managed) {
226
+ return c.notFound();
227
+ }
228
+ const d = await discovery();
229
+ const verifier = randomBytes(32).toString("base64url");
230
+ const ticket = unseal(c.req.query("desktop") ?? "");
231
+ const state = {
232
+ verifier,
233
+ nonce: nanoid(16),
234
+ returnTo: safeReturn(c.req.query("return")),
235
+ exp: Date.now() + 15 * 60_000,
236
+ ...(ticket && ticket.exp > Date.now() ? { desktop: ticket.desktop } : {}),
237
+ };
238
+ setCookie(c, STATE_COOKIE, seal(state), {
239
+ httpOnly: true,
240
+ sameSite: "Lax",
241
+ secure,
242
+ path: `${basePath}/api/auth`,
243
+ maxAge: 900,
244
+ });
245
+ const url = new URL(d.authorization_endpoint);
246
+ url.search = new URLSearchParams({
247
+ response_type: "code",
248
+ client_id: env.manage.clientId,
249
+ redirect_uri: callbackUrl(),
250
+ scope: SCOPE,
251
+ resource: env.appUrl,
252
+ code_challenge: createHash("sha256").update(verifier).digest("base64url"),
253
+ code_challenge_method: "S256",
254
+ state: state.nonce,
255
+ }).toString();
256
+ return c.redirect(url.toString());
257
+ })
258
+ .get("/auth/callback", async (c) => {
259
+ const code = c.req.query("code");
260
+ const rawState = c.req.query("state") ?? "";
261
+ if (!managed) {
262
+ // The linked account of a runtime that runs alone: the system browser lands here.
263
+ if (!code) {
264
+ return c.html(closePage("Anmeldung abgebrochen. Du kannst dieses Fenster schließen."), 400);
265
+ }
266
+ try {
267
+ await finishLink(code, rawState);
268
+ return c.html(closePage("Angemeldet. Du kannst dieses Fenster schließen."));
269
+ }
270
+ catch (err) {
271
+ console.error("[account]", err);
272
+ return c.html(closePage("Anmeldung hat nicht geklappt. Bitte noch einmal versuchen."), 400);
273
+ }
274
+ }
275
+ const state = unseal(getCookie(c, STATE_COOKIE) ?? "");
276
+ deleteCookie(c, STATE_COOKIE, { path: `${basePath}/api/auth` });
277
+ if (!code || !state || state.exp < Date.now() || state.nonce !== rawState) {
278
+ return c.redirect(`${home}?signin=failed`);
279
+ }
280
+ try {
281
+ const tokens = await tokenRequest({
282
+ grant_type: "authorization_code",
283
+ code,
284
+ redirect_uri: callbackUrl(),
285
+ code_verifier: state.verifier,
286
+ resource: env.appUrl,
287
+ }, client());
288
+ const claims = await claimsOf(tokens);
289
+ const id = randomBytes(32).toString("base64url");
290
+ await controlDb.insert(control.session).values({
291
+ id,
292
+ userId: claims.userId,
293
+ tenantId: claims.tenantId,
294
+ role: claims.role,
295
+ name: claims.name || claims.email,
296
+ email: claims.email,
297
+ refreshToken: tokens.refresh_token ? seal(tokens.refresh_token) : null,
298
+ claimsExpireAt: new Date(claims.expiresAt),
299
+ expiresAt: new Date(Date.now() + SESSION_DAYS * 24 * 3600_000),
300
+ });
301
+ if (state.desktop) {
302
+ // The session belongs to the app's window, not to this browser.
303
+ const code = seal({
304
+ sid: id,
305
+ desktop: state.desktop,
306
+ exp: Date.now() + 2 * 60_000,
307
+ });
308
+ const link = `engenty-wizards://signin?code=${encodeURIComponent(code)}`;
309
+ return c.html(`${closePage("Angemeldet. Kehre jetzt zu engenty wizards zurück.")}
310
+ <script>location.href = ${JSON.stringify(link)};</script>`);
311
+ }
312
+ setSessionCookie(c, id);
313
+ return c.redirect(state.returnTo);
314
+ }
315
+ catch (err) {
316
+ console.error("[sign-in]", err);
317
+ return c.redirect(`${home}?signin=failed`);
318
+ }
319
+ })
320
+ .post("/auth/sign-out", async (c) => {
321
+ const id = getCookie(c, SESSION_COOKIE);
322
+ if (id) {
323
+ await controlDb.delete(control.session).where(eq(control.session.id, id));
324
+ sessions.delete(id);
325
+ }
326
+ deleteCookie(c, SESSION_COOKIE, { path: cookiePath });
327
+ deleteCookie(c, LOCAL_COOKIE, { path: cookiePath });
328
+ return c.json({ ok: true });
329
+ });
@@ -0,0 +1,55 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { nanoid } from "nanoid";
3
+ import { readSetting, writeSetting } from "../settings.js";
4
+ /**
5
+ * API keys of a runtime that runs alone: the person's own MCP client (Claude Code, Cursor,
6
+ * Codex) and scripts sign in with them. Only the hash is kept. A runtime of a Manage-App has
7
+ * none of its own — keys are issued and checked there.
8
+ */
9
+ export const API_KEY_PREFIX = "wz_";
10
+ const hashOf = (key) => createHash("sha256").update(key).digest("hex");
11
+ /** A key that lives only as long as this process: the studio chat's own client signs in with it. */
12
+ let internal = null;
13
+ export function internalKey() {
14
+ internal ??= `${API_KEY_PREFIX}${randomBytes(24).toString("base64url")}`;
15
+ return internal;
16
+ }
17
+ const INTERNAL_CLIENT = "Claude (Abo)";
18
+ async function all() {
19
+ return (await readSetting("apiKeys")) ?? [];
20
+ }
21
+ export async function listLocalKeys() {
22
+ return (await all()).map(({ hash: _hash, ...rest }) => rest);
23
+ }
24
+ export async function createLocalKey(name) {
25
+ const key = `${API_KEY_PREFIX}${randomBytes(24).toString("base64url")}`;
26
+ const row = {
27
+ id: nanoid(12),
28
+ name,
29
+ start: key.slice(0, 8),
30
+ hash: hashOf(key),
31
+ createdAt: new Date().toISOString(),
32
+ lastRequest: null,
33
+ };
34
+ await writeSetting("apiKeys", [...(await all()), row]);
35
+ return { id: row.id, name, key };
36
+ }
37
+ export async function deleteLocalKey(id) {
38
+ await writeSetting("apiKeys", (await all()).filter((k) => k.id !== id));
39
+ }
40
+ export async function verifyLocalKey(key) {
41
+ if (internal && key === internal) {
42
+ return { id: "internal", name: INTERNAL_CLIENT };
43
+ }
44
+ const keys = await all();
45
+ const found = keys.find((k) => k.hash === hashOf(key));
46
+ if (!found) {
47
+ return null;
48
+ }
49
+ // One write a minute is enough to show the key is in use.
50
+ if (!found.lastRequest || Date.now() - Date.parse(found.lastRequest) > 60_000) {
51
+ found.lastRequest = new Date().toISOString();
52
+ await writeSetting("apiKeys", keys);
53
+ }
54
+ return { id: found.id, name: found.name };
55
+ }
@@ -0,0 +1,23 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ /**
3
+ * A second way through the one-time link: a ticket signed with the data folder's secret, good
4
+ * for a minute. Who can read that secret can already make the studio's cookie, so a ticket opens
5
+ * nothing new — it lets the command line and the desktop app enter a runtime that already runs.
6
+ */
7
+ const TTL_MS = 60_000;
8
+ const sign = (secret, expires) => createHmac("sha256", secret).update(`local-enter.${expires}`).digest("hex");
9
+ export function mintLocalTicket(secret, now = Date.now()) {
10
+ const expires = now + TTL_MS;
11
+ return `${expires}.${sign(secret, expires)}`;
12
+ }
13
+ /** When a ticket runs out, or null when it is not one of ours or already ran out. */
14
+ export function localTicketExpiry(secret, ticket, now = Date.now()) {
15
+ const [head, signature] = ticket.split(".");
16
+ const expires = Number(head);
17
+ if (!signature || !Number.isSafeInteger(expires) || expires <= now || expires > now + TTL_MS) {
18
+ return null;
19
+ }
20
+ const given = Buffer.from(signature);
21
+ const expected = Buffer.from(sign(secret, expires));
22
+ return given.length === expected.length && timingSafeEqual(given, expected) ? expires : null;
23
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The wizard the authoring guide shows as an example of the schema: a post with an image. It is
3
+ * the guide's own, not a marketplace entry, so the guide never depends on the marketplace.
4
+ */
5
+ export const EXAMPLE_WIZARD = {
6
+ version: 1,
7
+ title: "X-Post mit Bild",
8
+ description: "Aus einem Thema wird ein fertiger Post mit Bild.",
9
+ avatar: "flame",
10
+ intro: "Erzähl mir kurz, worum es geht – ich schreibe den Post und zeichne das Bild dazu.",
11
+ steps: [
12
+ {
13
+ id: "about",
14
+ type: "page",
15
+ title: "Worum geht's?",
16
+ fields: [
17
+ {
18
+ id: "topic",
19
+ label: "Thema oder Anlass",
20
+ kind: "textarea",
21
+ required: true,
22
+ placeholder: "z. B. Wir eröffnen am Freitag unser neues Studio in Wien",
23
+ },
24
+ {
25
+ id: "tone",
26
+ label: "Ton",
27
+ kind: "select",
28
+ options: ["Locker", "Professionell", "Witzig", "Inspirierend"],
29
+ default: "Locker",
30
+ },
31
+ { id: "link", label: "Link (optional)", kind: "url" },
32
+ ],
33
+ },
34
+ {
35
+ id: "post",
36
+ type: "agent",
37
+ title: "Post schreiben",
38
+ working: "Schreibt den Post …",
39
+ instructions: "Schreibe einen Post für X (Twitter) zum Thema: {{topic}}. Ton: {{tone}}. Höchstens 270 Zeichen inklusive Link und höchstens zwei Hashtags. Wenn ein Link angegeben ist ({{link}}), setze ihn ans Ende. Ein starker erster Satz. Nur den Post ausgeben.",
40
+ tools: [],
41
+ output: { format: "text" },
42
+ model: "standard",
43
+ },
44
+ {
45
+ id: "visual",
46
+ type: "generate",
47
+ title: "Bild zeichnen",
48
+ working: "Zeichnet das Bild …",
49
+ asset: "image",
50
+ prompt: "Ein auffälliges Bild, das diesen Post begleitet: {{steps.post}}. Thema: {{topic}}. Kein Text im Bild.",
51
+ options: { aspectRatio: "16:9", style: "modern editorial, clean, high contrast" },
52
+ },
53
+ {
54
+ id: "check",
55
+ type: "review",
56
+ title: "Passt das so?",
57
+ description: "Du kannst den Text direkt ändern oder eine neue Variante anfordern.",
58
+ show: ["post", "visual"],
59
+ edit: true,
60
+ regenerate: true,
61
+ },
62
+ {
63
+ id: "done",
64
+ type: "result",
65
+ title: "Fertig zum Posten",
66
+ message: "Kopiere den Text und lade das Bild herunter.",
67
+ deliverables: [
68
+ { from: "post", label: "Post", formats: ["txt", "md"] },
69
+ { from: "visual", label: "Bild", formats: ["png"] },
70
+ ],
71
+ },
72
+ ],
73
+ };