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,400 @@
1
+ import { and, asc, eq } from "drizzle-orm";
2
+ import { z } from "zod";
3
+ import { db, schema } from "../db/client.js";
4
+ import { buildImportedConnector, mcpHeaders, } from "../engenty/connections-external/build-connector.js";
5
+ import { ImportValidationError } from "../engenty/connections-external/errors.js";
6
+ import { assembleRecord, connectorIdFromSlug, prepareSource, resolveRequiredHeaders, surfaceRequiresAuth, toolPrefixFromSlug, } from "../engenty/connections-external/import-service.js";
7
+ import { createGuardedFetch } from "../engenty/connections-external/net/guarded-fetch.js";
8
+ import { discoverImportableSources, discoverOAuthFacts, registryDiscover, registrySearch, resolveMcpTransport, } from "../engenty/connections-external/registry-client.js";
9
+ import { resolveRegistrySource } from "../engenty/connections-external/registry-source.js";
10
+ import { encryptToken } from "../engenty/shims/connections-sdk.js";
11
+ import { env } from "../env.js";
12
+ import { ServiceError } from "../services/errors.js";
13
+ import { BUILTIN_CONNECTORS, builtinConnector, missingSetup, usable } from "./builtin.js";
14
+ /**
15
+ * Imported connectors: any service becomes a connector from its OpenAPI spec or MCP server,
16
+ * found through the integrations registry or pasted as a URL. Searching, normalising, auth
17
+ * mapping and invoking are engenty's (`apps/runtime/src/engenty/connections-external`); kept here is what
18
+ * engenty leaves to its host — where the records live and who may import.
19
+ */
20
+ // engenty's dynamic client registration reads the redirect from this variable.
21
+ process.env.CONNECTIONS_REDIRECT_URI ??=
22
+ env.connectRedirectUrl || `${env.appUrl}/api/connect/callback`;
23
+ const where = (projectId, id) => and(eq(schema.projectConnector.projectId, projectId), eq(schema.projectConnector.id, id));
24
+ async function load(projectId, id) {
25
+ const row = await db.query.projectConnector.findFirst({ where: where(projectId, id) });
26
+ return row?.record ?? null;
27
+ }
28
+ async function save(projectId, record) {
29
+ await db
30
+ .insert(schema.projectConnector)
31
+ .values({ projectId, id: record.id, record })
32
+ .onConflictDoUpdate({
33
+ target: [schema.projectConnector.projectId, schema.projectConnector.id],
34
+ set: { record, updatedAt: new Date() },
35
+ });
36
+ }
37
+ const actionView = (a) => ({
38
+ id: a.id,
39
+ summary: (a.summary || a.description).slice(0, 160),
40
+ group: a.classification,
41
+ });
42
+ function view(record) {
43
+ const auth = record.auth_config;
44
+ const needsOAuthClient = auth.kind === "oauth2" && !record.client_id_enc && !(auth.dcr && auth.registration_endpoint);
45
+ return {
46
+ usable: !needsOAuthClient,
47
+ missingSetup: null,
48
+ id: record.id,
49
+ name: record.name,
50
+ domain: record.domain,
51
+ sourceKind: record.source_kind,
52
+ sourceUrl: record.source_url,
53
+ toolPrefix: record.tool_prefix,
54
+ auth: auth.kind,
55
+ needsOAuthClient,
56
+ toolsPending: record.source_kind === "mcp" && record.actions.length === 0,
57
+ actions: record.actions.map(actionView),
58
+ importedAt: record.imported_at,
59
+ refreshedAt: record.refreshed_at,
60
+ };
61
+ }
62
+ /** What the admin can fix is told as it is; anything else is the registry or the source failing. */
63
+ function importFailure(err) {
64
+ const message = err instanceof Error ? err.message : String(err);
65
+ return new ServiceError(err instanceof ImportValidationError ? "invalid" : "refused", message);
66
+ }
67
+ /** What the studio, the architect and MCP clients send to import a connector. */
68
+ export const connectorImportSchema = z.object({
69
+ domain: z.string().min(1).max(253),
70
+ sourceKind: z.enum(["openapi", "mcp"]),
71
+ sourceUrl: z.string().url(),
72
+ id: z.string().min(2).max(60),
73
+ toolPrefix: z.string().min(2).max(31),
74
+ name: z.string().min(1).max(120).optional(),
75
+ actions: z.array(z.string()).max(500).optional(),
76
+ oauthClientId: z.string().max(500).optional(),
77
+ oauthClientSecret: z.string().max(500).optional(),
78
+ });
79
+ // --- the registry ----------------------------------------------------------------
80
+ export async function searchRegistry(query) {
81
+ const results = await registrySearch({ query, limit: 12 });
82
+ return results.map((r) => ({
83
+ domain: r.domain,
84
+ name: r.name,
85
+ description: r.description,
86
+ kinds: r.kinds.filter((k) => k === "openapi" || k === "mcp"),
87
+ }));
88
+ }
89
+ export async function registryService(domain) {
90
+ const { parsed } = await registryDiscover(domain).catch((err) => {
91
+ throw importFailure(err);
92
+ });
93
+ return {
94
+ domain: parsed.domain,
95
+ summary: parsed.summary ?? parsed.description ?? null,
96
+ sources: discoverImportableSources(parsed).map((s) => ({
97
+ sourceKind: s.source_kind,
98
+ sourceUrl: s.source_url,
99
+ name: s.surface.name,
100
+ blocked: s.blocked_reason,
101
+ auth: s.surface.auth.status,
102
+ suggestedId: connectorIdFromSlug(s.surface.slug),
103
+ suggestedToolPrefix: toolPrefixFromSlug(s.surface.slug),
104
+ })),
105
+ credentials: Object.values(parsed.credentials).map((c) => ({
106
+ label: c.label ?? c.type,
107
+ setup: c.setup ?? null,
108
+ url: c.generateUrl ?? null,
109
+ })),
110
+ };
111
+ }
112
+ /**
113
+ * OAuth facts straight from an MCP server. The registry says "OAuth, see the server's well-known
114
+ * document" for most MCP servers but probes only the service's main domain, so its own document
115
+ * carries no endpoints for them. The server publishes them itself (RFC 9728, RFC 8414).
116
+ */
117
+ async function probeOAuth(sourceUrl) {
118
+ const guarded = createGuardedFetch();
119
+ const json = async (url) => {
120
+ const res = await guarded(url, {
121
+ headers: { accept: "application/json" },
122
+ signal: AbortSignal.timeout(10_000),
123
+ }).catch(() => null);
124
+ return res?.ok
125
+ ? (await res.json().catch(() => null))
126
+ : null;
127
+ };
128
+ const origin = new URL(sourceUrl).origin;
129
+ const resource = await json(`${origin}/.well-known/oauth-protected-resource`);
130
+ const issuer = resource?.authorization_servers?.[0] ?? origin;
131
+ const server = (await json(`${issuer.replace(/\/+$/, "")}/.well-known/oauth-authorization-server`)) ??
132
+ (await json(`${origin}/.well-known/oauth-authorization-server`));
133
+ const text = (v) => (typeof v === "string" && v ? v : undefined);
134
+ const list = (v) => (Array.isArray(v) ? v.filter((x) => typeof x === "string") : []);
135
+ const authorizationEndpoint = text(server?.authorization_endpoint);
136
+ const tokenEndpoint = text(server?.token_endpoint);
137
+ if (!(authorizationEndpoint && tokenEndpoint)) {
138
+ return null;
139
+ }
140
+ const registrationEndpoint = text(server?.registration_endpoint);
141
+ const scopes = list(server?.scopes_supported);
142
+ return {
143
+ authorizationEndpoint,
144
+ tokenEndpoint,
145
+ grantTypes: list(server?.grant_types_supported),
146
+ // A long list is a catalogue, not what one client should ask for.
147
+ scopes: scopes.length <= 8 ? scopes : [],
148
+ ...(registrationEndpoint ? { registrationEndpoint, dcr: true } : {}),
149
+ };
150
+ }
151
+ /** Fetch and normalise a source with the facts the registry holds about it. */
152
+ async function prepare(input) {
153
+ const resolved = input.domain
154
+ ? await resolveRegistrySource({ domain: input.domain, sourceUrl: input.sourceUrl })
155
+ : { discover: null, surface: null };
156
+ const { surface } = resolved;
157
+ if (input.sourceKind === "mcp" &&
158
+ resolved.discover &&
159
+ surfaceRequiresAuth(surface) &&
160
+ !discoverOAuthFacts(resolved.discover.parsed)) {
161
+ const oauth = await probeOAuth(input.sourceUrl);
162
+ if (oauth) {
163
+ const parsed = resolved.discover.parsed;
164
+ resolved.discover.parsed = {
165
+ ...parsed,
166
+ detect: { ...parsed.detect, auth: { ...parsed.detect?.auth, oauth } },
167
+ };
168
+ }
169
+ }
170
+ const blockers = [];
171
+ if (surface) {
172
+ try {
173
+ resolveRequiredHeaders(surface);
174
+ }
175
+ catch (err) {
176
+ blockers.push(err.message);
177
+ }
178
+ if (surface.variables.length) {
179
+ blockers.push(`this source needs ${surface.variables.map((v) => v.name).join(", ")} in its address — paste the resolved URL instead`);
180
+ }
181
+ if (input.sourceKind === "mcp" && !resolveMcpTransport(surface)) {
182
+ blockers.push(`unsupported MCP transport (${surface.transports.join(", ")})`);
183
+ }
184
+ }
185
+ const prepared = await prepareSource({
186
+ deferMcpTools: input.sourceKind === "mcp" && surfaceRequiresAuth(surface),
187
+ requiredHeaders: !blockers.length && surface ? resolveRequiredHeaders(surface) : [],
188
+ sourceKind: input.sourceKind,
189
+ sourceUrl: input.sourceUrl,
190
+ specOverrides: surface?.spec_overrides ?? [],
191
+ transport: surface ? resolveMcpTransport(surface) : null,
192
+ });
193
+ return { ...resolved, prepared, blockers };
194
+ }
195
+ export async function previewSource(input) {
196
+ const { prepared, blockers } = await prepare(input).catch((err) => {
197
+ throw importFailure(err);
198
+ });
199
+ return {
200
+ title: prepared.normalized.title,
201
+ actions: prepared.normalized.actions.map(actionView),
202
+ blockers,
203
+ dropped: prepared.normalized.dropped_count,
204
+ toolsPending: prepared.deferred_mcp_tools === true,
205
+ };
206
+ }
207
+ // --- a project's connectors --------------------------------------------------------
208
+ async function builtinView(connector) {
209
+ const ready = await usable(connector);
210
+ return {
211
+ id: connector.id,
212
+ name: connector.name,
213
+ domain: "",
214
+ sourceKind: "builtin",
215
+ sourceUrl: "",
216
+ toolPrefix: connector.toolPrefix,
217
+ auth: connector.auth.kind === "oauth2" ? "oauth2" : "api_key",
218
+ usable: ready,
219
+ missingSetup: ready ? null : missingSetup(connector),
220
+ needsOAuthClient: false,
221
+ toolsPending: false,
222
+ actions: connector.actions.map((a) => ({
223
+ id: a.id,
224
+ summary: a.summary.slice(0, 160),
225
+ group: a.group,
226
+ })),
227
+ importedAt: "",
228
+ refreshedAt: null,
229
+ };
230
+ }
231
+ /** Every connector a wizard of the project can name: the built-in ones, then its imports. */
232
+ export async function listConnectors(projectId) {
233
+ const rows = await db.query.projectConnector.findMany({
234
+ where: eq(schema.projectConnector.projectId, projectId),
235
+ orderBy: [asc(schema.projectConnector.createdAt)],
236
+ });
237
+ return [
238
+ ...(await Promise.all(BUILTIN_CONNECTORS.map(builtinView))),
239
+ ...rows.map((r) => view(r.record)),
240
+ ];
241
+ }
242
+ /**
243
+ * A connector by id, ready to run, with the JSON schema of each action's input: a built-in one,
244
+ * or one the project imported.
245
+ */
246
+ export async function resolveConnector(projectId, id) {
247
+ const builtin = builtinConnector(id);
248
+ if (builtin) {
249
+ return {
250
+ connector: builtin,
251
+ imported: false,
252
+ inputSchema: (actionId) => {
253
+ const action = builtin.actions.find((a) => a.id === actionId);
254
+ try {
255
+ return action ? z.toJSONSchema(action.inputSchema) : {};
256
+ }
257
+ catch {
258
+ return {};
259
+ }
260
+ },
261
+ };
262
+ }
263
+ const found = await importedConnector(projectId, id);
264
+ return found
265
+ ? {
266
+ connector: found.connector,
267
+ imported: true,
268
+ inputSchema: (actionId) => found.record.actions.find((a) => a.id === actionId)?.input_json_schema ?? {},
269
+ }
270
+ : null;
271
+ }
272
+ export async function importConnector(userId, projectId, input) {
273
+ if (await load(projectId, input.id)) {
274
+ throw new ServiceError("invalid", `Connector "${input.id}" already exists in this project.`);
275
+ }
276
+ try {
277
+ const { discover, surface, prepared } = await prepare(input);
278
+ const { record, warnings } = assembleRecord({
279
+ actionFilter: input.actions ?? null,
280
+ discover: discover?.parsed ?? null,
281
+ domain: input.domain,
282
+ id: input.id,
283
+ importedBy: userId,
284
+ name: input.name ?? null,
285
+ oauthClient: input.oauthClientId && input.oauthClientSecret
286
+ ? { clientId: input.oauthClientId, clientSecret: input.oauthClientSecret }
287
+ : null,
288
+ prepared,
289
+ // The registry's own document is not kept: the record holds what was made of it.
290
+ rawDiscover: null,
291
+ sourceKind: input.sourceKind,
292
+ sourceUrl: input.sourceUrl,
293
+ surface,
294
+ tenantId: projectId,
295
+ toolPrefix: input.toolPrefix,
296
+ });
297
+ const { skippedActions } = buildImportedConnector(record);
298
+ if (skippedActions.length) {
299
+ warnings.push(`${skippedActions.length} action(s) have an input the tools cannot express`);
300
+ }
301
+ await save(projectId, record);
302
+ return { connector: view(record), warnings };
303
+ }
304
+ catch (err) {
305
+ throw err instanceof ServiceError ? err : importFailure(err);
306
+ }
307
+ }
308
+ /**
309
+ * Imports a registry service by its domain, for callers that do not pick a source by hand (the
310
+ * architect, MCP clients): the first importable source of the wanted kind, MCP before OpenAPI —
311
+ * an MCP server is the service's own, curated set of actions.
312
+ */
313
+ export async function importFromRegistry(userId, projectId, input) {
314
+ const service = await registryService(input.domain);
315
+ const order = input.kind ? [input.kind] : ["mcp", "openapi"];
316
+ const source = order
317
+ .flatMap((kind) => service.sources.filter((s) => s.sourceKind === kind))
318
+ .find((s) => !s.blocked);
319
+ if (!source) {
320
+ const why = service.sources.map((s) => `${s.sourceKind}: ${s.blocked}`).join("; ");
321
+ throw new ServiceError("invalid", `${input.domain} has nothing that can be imported${why ? ` (${why})` : ""}.`);
322
+ }
323
+ const taken = (await listConnectors(projectId)).find((c) => c.id === source.suggestedId);
324
+ if (taken) {
325
+ return { connector: taken, warnings: ["already imported"] };
326
+ }
327
+ return importConnector(userId, projectId, {
328
+ domain: service.domain,
329
+ sourceKind: source.sourceKind,
330
+ sourceUrl: source.sourceUrl,
331
+ id: source.suggestedId,
332
+ toolPrefix: source.suggestedToolPrefix,
333
+ ...(source.name ? { name: source.name } : {}),
334
+ });
335
+ }
336
+ export async function removeConnector(projectId, id) {
337
+ await db.delete(schema.projectConnector).where(where(projectId, id));
338
+ }
339
+ /**
340
+ * Re-reads the source and replaces the connector's actions. An MCP server that only lists its
341
+ * tools to a signed-in account needs that account's token.
342
+ */
343
+ export async function refreshConnector(projectId, id, accessToken) {
344
+ const record = await load(projectId, id);
345
+ if (!record) {
346
+ throw new ServiceError("not_found", "No such connector.");
347
+ }
348
+ try {
349
+ const { surface } = record.registry_surface_slug
350
+ ? await resolveRegistrySource({ domain: record.domain, sourceUrl: record.source_url })
351
+ : { surface: null };
352
+ const requiredHeaders = surface ? resolveRequiredHeaders(surface) : record.required_headers;
353
+ const transport = record.source_kind === "mcp"
354
+ ? ((surface ? resolveMcpTransport(surface) : null) ??
355
+ record.mcp_transport ??
356
+ "streamable-http")
357
+ : null;
358
+ const prepared = await prepareSource({
359
+ deferOnUnauthorized: false,
360
+ mcpHeaders: accessToken ? mcpHeaders(record, accessToken) : undefined,
361
+ requiredHeaders,
362
+ sourceKind: record.source_kind,
363
+ sourceUrl: record.source_url,
364
+ specOverrides: surface?.spec_overrides ?? [],
365
+ transport,
366
+ });
367
+ const updated = {
368
+ ...record,
369
+ actions: prepared.normalized.actions,
370
+ base_url: record.base_url ?? prepared.normalized.base_url,
371
+ mcp_transport: transport,
372
+ refreshed_at: new Date().toISOString(),
373
+ required_headers: requiredHeaders,
374
+ spec_hash: prepared.spec_hash,
375
+ };
376
+ await save(projectId, updated);
377
+ return view(updated);
378
+ }
379
+ catch (err) {
380
+ throw importFailure(err);
381
+ }
382
+ }
383
+ /** The connector as engenty's framework runs it: actions with handlers, auth with its flows. */
384
+ export async function importedConnector(projectId, id) {
385
+ const record = await load(projectId, id);
386
+ if (!record) {
387
+ return null;
388
+ }
389
+ // The record is read at call time, so a client registered a moment ago is the one used.
390
+ let current = record;
391
+ const { connector } = buildImportedConnector(record, () => current, async (client) => {
392
+ current = {
393
+ ...current,
394
+ client_id_enc: encryptToken(client.clientId),
395
+ client_secret_enc: client.clientSecret ? encryptToken(client.clientSecret) : null,
396
+ };
397
+ await save(projectId, current);
398
+ });
399
+ return { connector, record };
400
+ }
@@ -0,0 +1,107 @@
1
+ import { GOOGLE_OAUTH2, googleJson } from "../engenty/connections-google/shared.js";
2
+ import { htmlToMarkdown } from "../render/convert.js";
3
+ import { dayAfter, mailActions, snippetOf, } from "./mail.js";
4
+ const GMAIL_API = "https://gmail.googleapis.com/gmail/v1/users/me";
5
+ const SCOPE_READONLY = "https://www.googleapis.com/auth/gmail.readonly";
6
+ const header = (payload, name) => payload?.headers?.find((h) => h.name.toLowerCase() === name.toLowerCase())?.value ?? null;
7
+ function body(payload, mime) {
8
+ if (!payload) {
9
+ return null;
10
+ }
11
+ if (payload.mimeType === mime && payload.body?.data) {
12
+ return Buffer.from(payload.body.data, "base64url").toString("utf8");
13
+ }
14
+ for (const part of payload.parts ?? []) {
15
+ const found = body(part, mime);
16
+ if (found) {
17
+ return found;
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ function attachments(payload, out = []) {
23
+ if (payload?.filename && payload.body?.attachmentId) {
24
+ out.push({
25
+ id: payload.body.attachmentId,
26
+ name: payload.filename,
27
+ mime: payload.mimeType ?? "application/octet-stream",
28
+ size: payload.body.size ?? null,
29
+ });
30
+ }
31
+ for (const part of payload?.parts ?? []) {
32
+ attachments(part, out);
33
+ }
34
+ return out;
35
+ }
36
+ function toMessage(raw) {
37
+ const html = body(raw.payload, "text/html");
38
+ const text = body(raw.payload, "text/plain") ?? (html ? htmlToMarkdown(html) : (raw.snippet ?? ""));
39
+ return {
40
+ id: raw.id,
41
+ date: raw.internalDate ? new Date(Number(raw.internalDate)).toISOString() : null,
42
+ from: header(raw.payload, "From"),
43
+ to: (header(raw.payload, "To") ?? "")
44
+ .split(",")
45
+ .map((s) => s.trim())
46
+ .filter(Boolean),
47
+ subject: header(raw.payload, "Subject"),
48
+ snippet: raw.snippet ?? snippetOf(text),
49
+ attachments: attachments(raw.payload),
50
+ text,
51
+ html,
52
+ };
53
+ }
54
+ /** Gmail's own search syntax: `{a b}` is "a OR b", dates are `after:`/`before:` days. */
55
+ function query(input) {
56
+ const quoted = (input.terms ?? []).map((t) => (/\s/.test(t) ? `"${t.replace(/"/g, "")}"` : t));
57
+ return [
58
+ quoted.length ? `{${quoted.join(" ")}}` : "",
59
+ input.from ? `from:${input.from}` : "",
60
+ input.since ? `after:${input.since.replace(/-/g, "/")}` : "",
61
+ input.until ? `before:${dayAfter(input.until).replace(/-/g, "/")}` : "",
62
+ input.has_attachment ? "has:attachment" : "",
63
+ ]
64
+ .filter(Boolean)
65
+ .join(" ");
66
+ }
67
+ const getMessage = (ctx, id) => googleJson(ctx, `${GMAIL_API}/messages/${encodeURIComponent(id)}?format=full`);
68
+ const backend = {
69
+ async search(input, ctx) {
70
+ const url = new URL(`${GMAIL_API}/messages`);
71
+ url.searchParams.set("q", query(input));
72
+ url.searchParams.set("maxResults", String(input.limit ?? 40));
73
+ const list = await googleJson(ctx, url.toString());
74
+ const out = [];
75
+ const ids = (list.messages ?? []).map((m) => m.id);
76
+ for (let i = 0; i < ids.length; i += 10) {
77
+ const batch = await Promise.all(ids.slice(i, i + 10).map((id) => getMessage(ctx, id)));
78
+ out.push(...batch.map(toMessage));
79
+ }
80
+ return out.map(({ text: _text, html: _html, to: _to, ...summary }) => summary);
81
+ },
82
+ async read(id, ctx) {
83
+ return toMessage(await getMessage(ctx, id));
84
+ },
85
+ async attachment(id, attachmentId, ctx) {
86
+ const info = attachments((await getMessage(ctx, id)).payload).find((a) => a.id === attachmentId);
87
+ const data = await googleJson(ctx, `${GMAIL_API}/messages/${encodeURIComponent(id)}/attachments/${encodeURIComponent(attachmentId)}`);
88
+ if (!data.data) {
89
+ throw new Error("gmail attachment has no data");
90
+ }
91
+ return {
92
+ name: info?.name ?? "attachment",
93
+ mime: info?.mime ?? "application/octet-stream",
94
+ data_base64: Buffer.from(data.data, "base64url").toString("base64"),
95
+ };
96
+ },
97
+ };
98
+ export const gmailConnector = {
99
+ id: "mail-gmail",
100
+ moduleId: "wizards-mail",
101
+ name: "Gmail",
102
+ description: "Read mail in a Gmail or Google Workspace account.",
103
+ icon: "logo:gmail",
104
+ toolPrefix: "mail",
105
+ auth: { kind: "oauth2", oauth2: GOOGLE_OAUTH2 },
106
+ actions: mailActions(backend, [SCOPE_READONLY]),
107
+ };