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,336 @@
1
+ import { z } from "zod";
2
+ import { createGuardedFetch } from "./net/guarded-fetch.js";
3
+ /**
4
+ * Client for the integrations.sh registry (payload `version: 3`). Contacted
5
+ * ONLY during admin search/preview/import — never at agent runtime.
6
+ *
7
+ * The registry's own wire schema is the contract: `/api/search` returns
8
+ * domain-level hits each carrying a `surfaces[]` summary, and
9
+ * `GET /api/{domain}/surface` returns the cached catalog document shown on the
10
+ * public page — `surfaces[]` as a discriminated union on `type` (`http`,
11
+ * `mcp`, `graphql`, `cli`) plus a `credentials` registry keyed by id. Parsing
12
+ * stays loose (unknown keys pass through) and the raw payload is persisted on
13
+ * the imported record for forensics, but every field this module *acts* on is
14
+ * validated here.
15
+ *
16
+ * `/surface` is preferred over `/discover` (live re-probe — often hangs past
17
+ * our request timeout while `/surface` returns in hundreds of ms).
18
+ */
19
+ const DEFAULT_REGISTRY_URL = "https://integrations.sh";
20
+ const REQUEST_TIMEOUT_MS = 20_000;
21
+ /** Remote MCP transports this module can actually speak. */
22
+ const SUPPORTED_MCP_TRANSPORTS = ["streamable-http", "sse"];
23
+ export function registryBaseUrl() {
24
+ return (process.env.ENGENTY_INTEGRATIONS_REGISTRY_URL ?? DEFAULT_REGISTRY_URL).replace(/\/+$/u, "");
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Wire schemas
28
+ // ---------------------------------------------------------------------------
29
+ /** RFC 6902 operation, as the registry publishes spec corrections. */
30
+ const jsonPatchOperationSchema = z
31
+ .object({
32
+ from: z.string().optional(),
33
+ op: z.enum(["add", "remove", "replace", "move", "copy", "test"]),
34
+ path: z.string(),
35
+ value: z.unknown().optional(),
36
+ })
37
+ .loose();
38
+ /**
39
+ * How one credential rides the request. `source` decides what we can map:
40
+ * `http` (header/query placement) and `spec`/`well-known` (auth described by
41
+ * the spec or an OAuth discovery document) are actionable; `cli` and
42
+ * `unknown` are not.
43
+ */
44
+ const authMechanicsSchema = z
45
+ .object({
46
+ command: z.string().optional(),
47
+ env: z.array(z.string()).optional(),
48
+ headerName: z.string().optional(),
49
+ in: z.string().optional(),
50
+ scheme: z.string().optional(),
51
+ source: z.string(),
52
+ })
53
+ .loose();
54
+ /** One credential an entry needs; an entry's `use[]` are needed together (AND). */
55
+ const authUseSchema = z
56
+ .object({ id: z.string(), mechanics: authMechanicsSchema })
57
+ .loose();
58
+ /** `entries[]` are alternatives (OR) — any one of them authenticates. */
59
+ const authEntrySchema = z
60
+ .object({ use: z.array(authUseSchema).default([]) })
61
+ .loose();
62
+ const surfaceAuthSchema = z
63
+ .object({
64
+ entries: z.array(authEntrySchema).default([]),
65
+ status: z.string().default("unknown"),
66
+ })
67
+ .loose();
68
+ const requiredHeaderSchema = z
69
+ .object({
70
+ description: z.string().nullish(),
71
+ name: z.string(),
72
+ source: z
73
+ .object({ kind: z.string(), value: z.string().nullish() })
74
+ .loose()
75
+ .nullish(),
76
+ })
77
+ .loose();
78
+ const surfaceVariableSchema = z
79
+ .object({
80
+ description: z.string().nullish(),
81
+ in: z.string().nullish(),
82
+ name: z.string(),
83
+ resolveFrom: z.string().nullish(),
84
+ })
85
+ .loose();
86
+ const surfaceSchema = z
87
+ .object({
88
+ auth: surfaceAuthSchema.nullish(),
89
+ docs: z.string().nullish(),
90
+ name: z.string().nullish(),
91
+ requiredHeaders: z.array(requiredHeaderSchema).default([]),
92
+ slug: z.string().nullish(),
93
+ spec: z.string().nullish(),
94
+ specAlternates: z.array(z.string()).default([]),
95
+ specOverrides: z.array(jsonPatchOperationSchema).default([]),
96
+ transports: z.array(z.string()).nullish(),
97
+ type: z.string(),
98
+ url: z.string().nullish(),
99
+ variables: z.array(surfaceVariableSchema).default([]),
100
+ })
101
+ .loose();
102
+ const credentialSchema = z
103
+ .object({
104
+ generateUrl: z.string().nullish(),
105
+ label: z.string().nullish(),
106
+ setup: z.string().nullish(),
107
+ type: z.string(),
108
+ })
109
+ .loose();
110
+ /**
111
+ * OAuth facts probed from `/.well-known/oauth-authorization-server` &co. The
112
+ * `credentials` registry describes OAuth in prose only, so these endpoints are
113
+ * the sole machine-readable source for an authorization-code mapping.
114
+ */
115
+ const oauthFactsSchema = z
116
+ .object({
117
+ authorizationEndpoint: z.string().optional(),
118
+ dcr: z.boolean().optional(),
119
+ grantTypes: z.array(z.string()).default([]),
120
+ registrationEndpoint: z.string().optional(),
121
+ scopes: z.array(z.string()).default([]),
122
+ tokenEndpoint: z.string().optional(),
123
+ })
124
+ .loose();
125
+ const discoverSchema = z
126
+ .object({
127
+ credentials: z.record(z.string(), credentialSchema).default({}),
128
+ description: z.string().nullish(),
129
+ detect: z
130
+ .object({
131
+ auth: z.object({ oauth: oauthFactsSchema.nullish() }).loose().nullish(),
132
+ })
133
+ .loose()
134
+ .nullish(),
135
+ domain: z.string(),
136
+ summary: z.string().nullish(),
137
+ surfaces: z.array(surfaceSchema).default([]),
138
+ version: z.number().optional(),
139
+ })
140
+ .loose();
141
+ /** Surface summary carried on a search hit (same identity, fewer facts). */
142
+ const searchSurfaceSchema = z
143
+ .object({
144
+ auth: z
145
+ .object({
146
+ header: z.string().nullish(),
147
+ kind: z.string().nullish(),
148
+ note: z.string().nullish(),
149
+ })
150
+ .loose()
151
+ .nullish(),
152
+ icon: z.string().nullish(),
153
+ kind: z.string(),
154
+ slug: z.string(),
155
+ specOverrides: z.array(jsonPatchOperationSchema).default([]),
156
+ url: z.string().nullish(),
157
+ })
158
+ .loose();
159
+ const searchResultSchema = z.object({
160
+ description: z.string().default(""),
161
+ domain: z.string(),
162
+ kinds: z.array(z.string()).default([]),
163
+ name: z.string(),
164
+ surfaces: z.array(searchSurfaceSchema).default([]),
165
+ url: z.string().default(""),
166
+ });
167
+ const searchResponseSchema = z.object({
168
+ results: z.array(searchResultSchema).default([]),
169
+ });
170
+ /** Parse a `/api/{domain}/surface` body. Exported so fixtures parse identically. */
171
+ export function parseSurfacePayload(data) {
172
+ return discoverSchema.parse(data);
173
+ }
174
+ /** Parse an `/api/search` body. */
175
+ export function parseSearchResponse(data) {
176
+ return searchResponseSchema.parse(data).results;
177
+ }
178
+ function normalizeSurface(surface) {
179
+ if (!surface.slug) {
180
+ // Without a slug the surface has no stable identity to persist against.
181
+ return null;
182
+ }
183
+ return {
184
+ auth: surface.auth ?? { entries: [], status: "unknown" },
185
+ connect_url: surface.url ?? null,
186
+ docs: surface.docs ?? null,
187
+ kind: surface.type,
188
+ name: surface.name ?? null,
189
+ required_headers: surface.requiredHeaders,
190
+ slug: surface.slug,
191
+ spec: surface.spec ?? null,
192
+ spec_alternates: surface.specAlternates,
193
+ spec_overrides: surface.specOverrides,
194
+ transports: surface.transports ?? [],
195
+ variables: surface.variables,
196
+ };
197
+ }
198
+ /** Every slugged surface on the domain, in registry order. */
199
+ export function registrySurfaces(payload) {
200
+ return payload.surfaces
201
+ .map(normalizeSurface)
202
+ .filter((surface) => surface !== null);
203
+ }
204
+ /**
205
+ * Transport to speak to an MCP surface. A surface that declares transports but
206
+ * no remote one (stdio-only) is not importable; an undeclared transport means
207
+ * the registry never probed it, and streamable HTTP is the remote default the
208
+ * adapter falls back from anyway.
209
+ */
210
+ export function resolveMcpTransport(surface) {
211
+ if (surface.transports.length === 0) {
212
+ return "streamable-http";
213
+ }
214
+ if (surface.transports.includes("streamable-http")) {
215
+ return "streamable-http";
216
+ }
217
+ return surface.transports.includes("sse") ? "sse" : null;
218
+ }
219
+ /**
220
+ * Registry surfaces as import candidates. HTTP surfaces need an OpenAPI spec
221
+ * (a bare base URL describes no operations); MCP surfaces need a supported
222
+ * remote transport. GraphQL and CLI surfaces are out of scope for this module
223
+ * and are listed with a reason rather than hidden.
224
+ */
225
+ export function discoverImportableSources(payload) {
226
+ const sources = [];
227
+ for (const surface of registrySurfaces(payload)) {
228
+ if (surface.kind === "http") {
229
+ sources.push({
230
+ blocked_reason: surface.spec
231
+ ? null
232
+ : "the registry lists no OpenAPI spec for this API — paste a spec URL on the Manual URL tab",
233
+ source_kind: "openapi",
234
+ source_url: surface.spec ?? surface.connect_url ?? "",
235
+ surface,
236
+ transport: null,
237
+ });
238
+ continue;
239
+ }
240
+ if (surface.kind === "mcp") {
241
+ const transport = resolveMcpTransport(surface);
242
+ // Transport first: a stdio-only server has no connect URL *because* it
243
+ // is not a remote server, and naming the transport says more.
244
+ let blocked = null;
245
+ if (!transport) {
246
+ blocked = `unsupported MCP transport (${surface.transports.join(", ")}) — only streamable-http and sse can be imported`;
247
+ }
248
+ else if (!surface.connect_url) {
249
+ blocked = "the registry lists no connect URL for this MCP server";
250
+ }
251
+ sources.push({
252
+ blocked_reason: blocked,
253
+ source_kind: "mcp",
254
+ source_url: surface.connect_url ?? "",
255
+ surface,
256
+ transport,
257
+ });
258
+ continue;
259
+ }
260
+ sources.push({
261
+ blocked_reason: `${surface.kind} surfaces cannot be imported — this module covers OpenAPI and MCP`,
262
+ source_kind: "openapi",
263
+ source_url: surface.connect_url ?? "",
264
+ surface,
265
+ transport: null,
266
+ });
267
+ }
268
+ return sources;
269
+ }
270
+ /**
271
+ * Re-derive the registry surface a source URL belongs to. Import calls this
272
+ * server-side from `domain` + `source_url` instead of trusting slug/override
273
+ * metadata echoed back by the client.
274
+ */
275
+ export function findSurfaceForSource(payload, sourceUrl) {
276
+ const wanted = sourceUrl.trim();
277
+ for (const surface of registrySurfaces(payload)) {
278
+ const candidates = [
279
+ surface.spec,
280
+ ...surface.spec_alternates,
281
+ surface.connect_url,
282
+ ].filter((value) => Boolean(value));
283
+ if (candidates.some((value) => value === wanted)) {
284
+ return surface;
285
+ }
286
+ }
287
+ return null;
288
+ }
289
+ /** Discovered OAuth facts (nested under `detect.auth`). */
290
+ export function discoverOAuthFacts(payload) {
291
+ return payload.detect?.auth?.oauth ?? null;
292
+ }
293
+ // ---------------------------------------------------------------------------
294
+ // Requests
295
+ // ---------------------------------------------------------------------------
296
+ async function fetchJson(url, fetchImpl) {
297
+ const response = await fetchImpl(url, {
298
+ headers: { accept: "application/json" },
299
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
300
+ });
301
+ if (!response.ok) {
302
+ throw new Error(`registry request failed (${response.status}): ${url}`);
303
+ }
304
+ return await response.json();
305
+ }
306
+ /**
307
+ * The registry host comes from `ENGENTY_INTEGRATIONS_REGISTRY_URL` — settings
308
+ * input, so it goes through the guard like every other outbound URL here.
309
+ */
310
+ function defaultRegistryFetch() {
311
+ return createGuardedFetch();
312
+ }
313
+ export async function registrySearch(params, fetchImpl = defaultRegistryFetch()) {
314
+ const url = new URL(`${registryBaseUrl()}/api/search`);
315
+ url.searchParams.set("q", params.query);
316
+ if (params.kind) {
317
+ url.searchParams.set("kind", params.kind);
318
+ }
319
+ url.searchParams.set("limit", String(params.limit ?? 20));
320
+ const data = await fetchJson(url.toString(), fetchImpl);
321
+ return parseSearchResponse(data);
322
+ }
323
+ /**
324
+ * Load the registry's cached surface document for a domain (same facts as
325
+ * https://integrations.sh/{domain}/). Named "discover" for historical call
326
+ * sites; the upstream path is `/surface`, not the live `/discover` probe.
327
+ */
328
+ export async function registryDiscover(domain, fetchImpl = defaultRegistryFetch()) {
329
+ const safeDomain = encodeURIComponent(domain.trim().toLowerCase());
330
+ const data = await fetchJson(`${registryBaseUrl()}/api/${safeDomain}/surface`, fetchImpl);
331
+ return {
332
+ parsed: parseSurfacePayload(data),
333
+ raw: (data ?? {}),
334
+ };
335
+ }
336
+ export { SUPPORTED_MCP_TRANSPORTS };
@@ -0,0 +1,82 @@
1
+ import { findSurfaceForSource, registryDiscover, registrySearch, } from "./registry-client.js";
2
+ /**
3
+ * The registry publishes a service's surfaces twice: the per-domain catalog
4
+ * document (`/api/{domain}/surface`) carries the rich facts — required
5
+ * headers, URL variables, transports, credential mechanics — while the search
6
+ * catalog carries a summary per surface, and today it is the search view that
7
+ * carries the `specOverrides` corrections. Neither is a superset.
8
+ *
9
+ * `resolveRegistrySource` takes the two facts the caller is allowed to supply
10
+ * — domain and source URL — and re-derives one surface from both views by
11
+ * exact URL match. Nothing is matched fuzzily: a correction published against
12
+ * one spec URL is never applied to a different one.
13
+ */
14
+ /** Catalog `kind` values mapped onto surface-document `type` values. */
15
+ function catalogKindToSurfaceKind(kind) {
16
+ return kind === "openapi" ? "http" : kind;
17
+ }
18
+ /** A search-catalog surface expressed in the surface-document shape. */
19
+ function surfaceFromCatalog(entry) {
20
+ if (!entry.url) {
21
+ return null;
22
+ }
23
+ const kind = catalogKindToSurfaceKind(entry.kind);
24
+ return {
25
+ auth: {
26
+ entries: [],
27
+ // The catalog states only whether a credential is needed, never how it
28
+ // rides the request — `mapAuth` falls back to the spec and OAuth facts.
29
+ status: entry.auth?.kind === "none" ? "none" : "unknown",
30
+ },
31
+ connect_url: kind === "http" ? null : entry.url,
32
+ docs: null,
33
+ kind,
34
+ name: null,
35
+ required_headers: [],
36
+ slug: entry.slug,
37
+ spec: kind === "http" ? entry.url : null,
38
+ spec_alternates: [],
39
+ spec_overrides: entry.specOverrides,
40
+ transports: [],
41
+ variables: [],
42
+ };
43
+ }
44
+ function catalogSurfacesForDomain(results, domain) {
45
+ const wanted = domain.trim().toLowerCase();
46
+ return results
47
+ .filter((result) => result.domain.trim().toLowerCase() === wanted)
48
+ .flatMap((result) => result.surfaces);
49
+ }
50
+ /**
51
+ * Resolve the registry surface behind `sourceUrl`. Registry lookups are best
52
+ * effort: a registry outage degrades an import to a plain URL import rather
53
+ * than failing it.
54
+ */
55
+ export async function resolveRegistrySource(params) {
56
+ const [discover, searchResults] = await Promise.all([
57
+ registryDiscover(params.domain, params.fetchImpl).catch(() => null),
58
+ registrySearch({ limit: 10, query: params.domain }, params.fetchImpl).catch(() => []),
59
+ ]);
60
+ const documentSurface = discover
61
+ ? findSurfaceForSource(discover.parsed, params.sourceUrl)
62
+ : null;
63
+ const catalogEntry = catalogSurfacesForDomain(searchResults, params.domain).find((entry) => entry.url === params.sourceUrl.trim());
64
+ if (!documentSurface) {
65
+ return {
66
+ discover,
67
+ surface: catalogEntry ? surfaceFromCatalog(catalogEntry) : null,
68
+ };
69
+ }
70
+ if (documentSurface.spec_overrides.length > 0 || !catalogEntry) {
71
+ return { discover, surface: documentSurface };
72
+ }
73
+ // Same URL in both views: take the document's facts and the catalog's
74
+ // corrections.
75
+ return {
76
+ discover,
77
+ surface: {
78
+ ...documentSurface,
79
+ spec_overrides: catalogEntry.specOverrides,
80
+ },
81
+ };
82
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Shared shapes for imported external connectors. The importer normalizes an
3
+ * OpenAPI spec or MCP tool list into `NormalizedAction[]` at import time; the
4
+ * stored record is the single source the boot path registers from — no spec
5
+ * re-parsing (and no executor/Effect code) runs at boot or execute time.
6
+ */
7
+ export {};
@@ -0,0 +1,209 @@
1
+ import { defineConnector, } from "../shims/connections-sdk.js";
2
+ import { z } from "zod";
3
+ /**
4
+ * The GitHub connector exposes the repository + pull-request surface the hosted
5
+ * coder needs. Deliberately NARROW in v1:
6
+ *
7
+ * - read actions (`repos_list`, `repo_get`, `pr_get`) are auto-allowed and,
8
+ * because they are low-risk, are reachable from Code Mode's read-only execute.
9
+ * - `pr_create` is the sole `write` action (approval-gated by the connections
10
+ * policy) — the human sign-off on delivering a coder's work as a PR.
11
+ *
12
+ * The clone/push CREDENTIAL is intentionally NOT a connector action: read
13
+ * actions are reachable from Code Mode (any low-risk catalog op can be invoked
14
+ * there), so returning a raw token as an action output would leak it into an
15
+ * agent-visible surface. The coder's repo checkout obtains its token through a
16
+ * dedicated, non-gateway core route instead (see PLAN-engenty-coder Phase 2).
17
+ *
18
+ * The single `repo` OAuth scope is requested up front (via `baseScopes`) so
19
+ * enabling `pr_create` later never forces a re-consent.
20
+ */
21
+ const GITHUB_API_BASE = "https://api.github.com";
22
+ const GITHUB_API_VERSION = "2022-11-28";
23
+ /** GitHub returns application-level failures as non-2xx with a JSON `message`. */
24
+ async function githubApi(ctx, path, init) {
25
+ const response = await ctx.fetchImpl(`${GITHUB_API_BASE}${path}`, {
26
+ method: init?.method ?? "GET",
27
+ headers: {
28
+ accept: "application/vnd.github+json",
29
+ authorization: `Bearer ${ctx.accessToken}`,
30
+ "x-github-api-version": GITHUB_API_VERSION,
31
+ ...(init?.body === undefined
32
+ ? {}
33
+ : { "content-type": "application/json" }),
34
+ },
35
+ ...(init?.body === undefined ? {} : { body: JSON.stringify(init.body) }),
36
+ });
37
+ if (!response.ok) {
38
+ let message = `${response.status}`;
39
+ try {
40
+ const data = (await response.json());
41
+ if (data.message) {
42
+ message = `${data.message} (${response.status})`;
43
+ }
44
+ }
45
+ catch {
46
+ // Non-JSON error body; fall back to the status code.
47
+ }
48
+ throw new Error(`github_api_error: ${message}`);
49
+ }
50
+ return (await response.json());
51
+ }
52
+ function mapRepo(repo) {
53
+ return {
54
+ default_branch: repo.default_branch ?? "",
55
+ description: repo.description ?? null,
56
+ full_name: repo.full_name ?? "",
57
+ html_url: repo.html_url ?? "",
58
+ private: repo.private ?? false,
59
+ };
60
+ }
61
+ function mapPull(pull) {
62
+ return {
63
+ base: pull.base?.ref ?? "",
64
+ head: pull.head?.ref ?? "",
65
+ html_url: pull.html_url ?? "",
66
+ merged: pull.merged ?? false,
67
+ number: pull.number ?? 0,
68
+ state: pull.state ?? "",
69
+ title: pull.title ?? "",
70
+ };
71
+ }
72
+ const repoFullName = z
73
+ .string()
74
+ .regex(/^[^/\s]+\/[^/\s]+$/, "Expected 'owner/repo'.")
75
+ .describe("Repository in 'owner/repo' form (e.g. engenty/engenty).");
76
+ const listReposInput = z.object({
77
+ limit: z
78
+ .number()
79
+ .int()
80
+ .min(1)
81
+ .max(50)
82
+ .optional()
83
+ .describe("Maximum repositories to return (1-50, default 30)."),
84
+ });
85
+ const getRepoInput = z.object({ repo: repoFullName });
86
+ const getPullInput = z.object({
87
+ repo: repoFullName,
88
+ number: z.number().int().positive().describe("Pull request number."),
89
+ });
90
+ const createPullInput = z.object({
91
+ repo: repoFullName,
92
+ title: z.string().min(1).describe("Pull request title."),
93
+ head: z
94
+ .string()
95
+ .min(1)
96
+ .describe("Name of the branch with the changes (e.g. coder/task-123)."),
97
+ base: z
98
+ .string()
99
+ .min(1)
100
+ .describe("Branch to merge into (e.g. the repository default branch)."),
101
+ body: z.string().optional().describe("Pull request description (Markdown)."),
102
+ draft: z
103
+ .boolean()
104
+ .optional()
105
+ .describe("Open the pull request as a draft (default false)."),
106
+ });
107
+ const actions = [
108
+ {
109
+ description: "List repositories the connected GitHub account can access, most recently updated first.",
110
+ group: "read",
111
+ handler: async (input, ctx) => {
112
+ const args = listReposInput.parse(input);
113
+ const repos = await githubApi(ctx, `/user/repos?per_page=${args.limit ?? 30}&sort=updated&affiliation=owner,collaborator,organization_member`);
114
+ return { repositories: repos.map(mapRepo) };
115
+ },
116
+ id: "repos_list",
117
+ inputSchema: listReposInput,
118
+ providerScopes: [],
119
+ summary: "List GitHub repositories",
120
+ },
121
+ {
122
+ description: "Fetch metadata for a single repository (default branch, visibility).",
123
+ group: "read",
124
+ handler: async (input, ctx) => {
125
+ const args = getRepoInput.parse(input);
126
+ const repo = await githubApi(ctx, `/repos/${args.repo}`);
127
+ return mapRepo(repo);
128
+ },
129
+ id: "repo_get",
130
+ inputSchema: getRepoInput,
131
+ providerScopes: [],
132
+ summary: "Get a GitHub repository",
133
+ },
134
+ {
135
+ description: "Fetch a pull request by number (state, branches, merge status, URL).",
136
+ group: "read",
137
+ handler: async (input, ctx) => {
138
+ const args = getPullInput.parse(input);
139
+ const pull = await githubApi(ctx, `/repos/${args.repo}/pulls/${args.number}`);
140
+ return mapPull(pull);
141
+ },
142
+ id: "pr_get",
143
+ inputSchema: getPullInput,
144
+ providerScopes: [],
145
+ summary: "Get a GitHub pull request",
146
+ },
147
+ {
148
+ description: "Open a pull request from an already-pushed head branch into a base branch.",
149
+ group: "write",
150
+ handler: async (input, ctx) => {
151
+ const args = createPullInput.parse(input);
152
+ const pull = await githubApi(ctx, `/repos/${args.repo}/pulls`, {
153
+ method: "POST",
154
+ body: {
155
+ title: args.title,
156
+ head: args.head,
157
+ base: args.base,
158
+ ...(args.body === undefined ? {} : { body: args.body }),
159
+ ...(args.draft === undefined ? {} : { draft: args.draft }),
160
+ },
161
+ });
162
+ return mapPull(pull);
163
+ },
164
+ id: "pr_create",
165
+ inputSchema: createPullInput,
166
+ providerScopes: [],
167
+ summary: "Create a GitHub pull request",
168
+ },
169
+ ];
170
+ export const githubConnector = defineConnector({
171
+ actions,
172
+ auth: {
173
+ kind: "oauth2",
174
+ oauth2: {
175
+ authUrl: "https://github.com/login/oauth/authorize",
176
+ // `repo` up front so enabling pr_create later never forces re-consent.
177
+ baseScopes: ["repo"],
178
+ clientIdEnv: "GITHUB_OAUTH_CLIENT_ID",
179
+ clientSecretEnv: "GITHUB_OAUTH_CLIENT_SECRET",
180
+ resolveAccount: async (accessToken, fetchImpl) => {
181
+ const response = await fetchImpl(`${GITHUB_API_BASE}/user`, {
182
+ headers: {
183
+ accept: "application/vnd.github+json",
184
+ authorization: `Bearer ${accessToken}`,
185
+ "x-github-api-version": GITHUB_API_VERSION,
186
+ },
187
+ });
188
+ if (!response.ok) {
189
+ throw new Error(`github_http_error: /user returned ${response.status}`);
190
+ }
191
+ const data = (await response.json());
192
+ return {
193
+ label: data.login ?? "GitHub",
194
+ ...(data.id ? { externalId: String(data.id) } : {}),
195
+ };
196
+ },
197
+ scopeSeparator: " ",
198
+ // GitHub returns a form-encoded token body unless JSON is requested.
199
+ tokenRequestHeaders: { accept: "application/json" },
200
+ tokenUrl: "https://github.com/login/oauth/access_token",
201
+ },
202
+ },
203
+ description: "GitHub access as the connected account: repositories and pull requests.",
204
+ icon: "logo:github",
205
+ id: "github",
206
+ moduleId: "connections-github",
207
+ name: "GitHub",
208
+ toolPrefix: "github",
209
+ });