eve 0.66.1 → 0.66.3

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 (178) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/src/cli/commands/deploy.d.ts +3 -1
  3. package/dist/src/cli/commands/deploy.js +1 -1
  4. package/dist/src/cli/commands/integration-connect.js +1 -1
  5. package/dist/src/cli/commands/register-project-commands.js +1 -1
  6. package/dist/src/cli/commands/registry-declared-setups.d.ts +0 -1
  7. package/dist/src/cli/commands/registry-declared-setups.js +1 -1
  8. package/dist/src/cli/commands/registry.d.ts +5 -1
  9. package/dist/src/cli/commands/registry.js +1 -1
  10. package/dist/src/cli/commands/vercel-non-interactive.d.ts +7 -0
  11. package/dist/src/cli/commands/vercel-non-interactive.js +1 -1
  12. package/dist/src/cli/dev/tui/argument-typeahead.d.ts +1 -2
  13. package/dist/src/cli/dev/tui/argument-typeahead.js +2 -2
  14. package/dist/src/cli/dev/tui/blocks.d.ts +5 -1
  15. package/dist/src/cli/dev/tui/blocks.js +3 -3
  16. package/dist/src/cli/dev/tui/flow-drawer.d.ts +11 -0
  17. package/dist/src/cli/dev/tui/flow-drawer.js +1 -0
  18. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  19. package/dist/src/cli/dev/tui/prompt-commands.d.ts +199 -0
  20. package/dist/src/cli/dev/tui/prompt-commands.js +2 -2
  21. package/dist/src/cli/dev/tui/registry-result-message.d.ts +15 -4
  22. package/dist/src/cli/dev/tui/registry-result-message.js +4 -4
  23. package/dist/src/cli/dev/tui/remote-auth.js +1 -1
  24. package/dist/src/cli/dev/tui/runner.d.ts +18 -6
  25. package/dist/src/cli/dev/tui/runner.js +3 -2
  26. package/dist/src/cli/dev/tui/setup-commands.d.ts +5 -22
  27. package/dist/src/cli/dev/tui/setup-commands.js +2 -1
  28. package/dist/src/cli/dev/tui/setup-flow.d.ts +2 -10
  29. package/dist/src/cli/dev/tui/setup-panel.d.ts +4 -23
  30. package/dist/src/cli/dev/tui/setup-panel.js +3 -3
  31. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +11 -7
  32. package/dist/src/cli/dev/tui/terminal-renderer.js +11 -10
  33. package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
  34. package/dist/src/cli/dev/tui/tui.js +1 -1
  35. package/dist/src/compiled/.vendor-stamp.json +6 -6
  36. package/dist/src/compiled/@workflow/core/create-hook.d.ts +38 -1
  37. package/dist/src/compiled/@workflow/core/global.d.ts +2 -0
  38. package/dist/src/compiled/@workflow/core/index.js +2 -2
  39. package/dist/src/compiled/@workflow/core/private.js +1 -1
  40. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +9 -0
  41. package/dist/src/compiled/@workflow/core/runtime/helpers.js +1 -1
  42. package/dist/src/compiled/@workflow/core/runtime/hook-wake.d.ts +89 -0
  43. package/dist/src/compiled/@workflow/core/runtime/open-hook-wait-state.d.ts +55 -0
  44. package/dist/src/compiled/@workflow/core/runtime/quickjs-runtime.d.ts +2 -0
  45. package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +8 -1
  46. package/dist/src/compiled/@workflow/core/runtime.js +4 -4
  47. package/dist/src/compiled/@workflow/core/serialization/types.d.ts +8 -0
  48. package/dist/src/compiled/@workflow/core/serialization.d.ts +8 -0
  49. package/dist/src/compiled/@workflow/core/serialization.js +1 -1
  50. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  51. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  52. package/dist/src/compiled/@workflow/errors/index.d.ts +23 -0
  53. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  54. package/dist/src/compiled/@workflow/world/events.d.ts +34 -0
  55. package/dist/src/compiled/@workflow/world/hooks.d.ts +27 -0
  56. package/dist/src/compiled/@workflow/world/index.d.ts +2 -2
  57. package/dist/src/compiled/@workflow/world/interfaces.d.ts +24 -0
  58. package/dist/src/compiled/@workflow/world/spec-version.d.ts +32 -11
  59. package/dist/src/compiled/@workflow/world-local/index.js +3 -3
  60. package/dist/src/compiled/@workflow/world-vercel/index.js +17 -17
  61. package/dist/src/compiled/_chunks/workflow/{attribute-changes-89Nwz7XW.js → attribute-changes-DzJovO_f.js} +1 -1
  62. package/dist/src/compiled/_chunks/workflow/dist-BQSf8Hax.js +1 -0
  63. package/dist/src/compiled/_chunks/workflow/dist-BfMqXLK3.js +3 -0
  64. package/dist/src/compiled/_chunks/workflow/frames-qKc30rjg.js +3 -0
  65. package/dist/src/compiled/_chunks/workflow/{global-DIlFoH2w.js → global-BQnKzRXo.js} +1 -1
  66. package/dist/src/compiled/_chunks/workflow/{helpers-k3zcudWr.js → helpers-CNMO7zB1.js} +1 -1
  67. package/dist/src/compiled/_chunks/workflow/{logger-Bzc8jWWj.js → logger-BCEj9caG.js} +1 -1
  68. package/dist/src/compiled/_chunks/workflow/resume-hook-QS_cMwHn.js +1 -0
  69. package/dist/src/compiled/_chunks/workflow/run-CA5wWV2S.js +1 -0
  70. package/dist/src/compiled/_chunks/workflow/serialization-CJ265vSe.js +3 -0
  71. package/dist/src/compiled/_chunks/workflow/sleep-CBn94Ayv.js +1 -0
  72. package/dist/src/compiled/_chunks/workflow/{wait-until-DXLZx3tU.js → wait-until-Bo2U6ON9.js} +1 -1
  73. package/dist/src/compiled/_chunks/workflow/{ws-transport-BSM_Cl7a.js → ws-transport-BrsMYqJg.js} +1 -1
  74. package/dist/src/discover/filesystem.d.ts +2 -0
  75. package/dist/src/discover/filesystem.js +1 -1
  76. package/dist/src/discover/grammar.d.ts +4 -2
  77. package/dist/src/discover/grammar.js +1 -1
  78. package/dist/src/discover/sandbox.js +1 -1
  79. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  80. package/dist/src/execution/session/entry-input.d.ts +4 -0
  81. package/dist/src/execution/session/entry-input.js +1 -1
  82. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  83. package/dist/src/execution/tools/ask-question-workflow.js +1 -1
  84. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  85. package/dist/src/execution/workflow-runtime.js +1 -1
  86. package/dist/src/extensions/code/extension/lib/connect-authentication.js +1 -1
  87. package/dist/src/extensions/code/extension/lib/github-shell.js +1 -1
  88. package/dist/src/extensions/code/extension/lib/prwatch-github.js +1 -1
  89. package/dist/src/harness/tool-loop.js +1 -1
  90. package/dist/src/internal/application/package.js +1 -1
  91. package/dist/src/internal/instrumentation-layout.js +1 -1
  92. package/dist/src/internal/model-auth/vercel-cli.d.ts +2 -0
  93. package/dist/src/internal/model-auth/vercel-cli.js +1 -1
  94. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  95. package/dist/src/internal/nitro/host/extension-capability-requirements.d.ts +1 -0
  96. package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
  97. package/dist/src/internal/nitro/host/extension-declarations.js +1 -1
  98. package/dist/src/internal/nitro/host/extension-distribution.js +1 -1
  99. package/dist/src/internal/nitro/host/extension-state-usage.d.ts +2 -2
  100. package/dist/src/internal/nitro/host/extension-state-usage.js +1 -1
  101. package/dist/src/internal/workflow/development-world-client.js +1 -1
  102. package/dist/src/public/channels/slack/activity-plan.d.ts +2 -1
  103. package/dist/src/public/channels/slack/activity-plan.js +1 -1
  104. package/dist/src/public/channels/slack/activity.d.ts +2 -0
  105. package/dist/src/public/channels/slack/activity.js +1 -1
  106. package/dist/src/public/channels/slack/api.d.ts +7 -0
  107. package/dist/src/public/channels/slack/api.js +1 -1
  108. package/dist/src/public/channels/slack/attachments.d.ts +5 -2
  109. package/dist/src/public/channels/slack/attachments.js +1 -1
  110. package/dist/src/public/channels/slack/index.d.ts +1 -0
  111. package/dist/src/public/channels/slack/input-response.d.ts +2 -0
  112. package/dist/src/public/channels/slack/input-response.js +1 -1
  113. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  114. package/dist/src/public/channels/slack/interactions.d.ts +2 -0
  115. package/dist/src/public/channels/slack/interactions.js +1 -1
  116. package/dist/src/public/channels/slack/slackChannel.d.ts +3 -0
  117. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  118. package/dist/src/public/channels/slack/slash-command.d.ts +5 -1
  119. package/dist/src/public/channels/slack/slash-command.js +1 -1
  120. package/dist/src/public/channels/slack/transport.d.ts +76 -0
  121. package/dist/src/public/channels/slack/transport.js +1 -0
  122. package/dist/src/setup/boxes/link-project.d.ts +2 -0
  123. package/dist/src/setup/boxes/link-project.js +1 -1
  124. package/dist/src/setup/cli/channel-setup-prompter.d.ts +2 -9
  125. package/dist/src/setup/cli/channel-setup-prompter.js +1 -1
  126. package/dist/src/setup/cli/index.d.ts +1 -1
  127. package/dist/src/setup/connection-connector.js +1 -1
  128. package/dist/src/setup/flows/deploy.d.ts +1 -0
  129. package/dist/src/setup/flows/deploy.js +1 -1
  130. package/dist/src/setup/flows/install-vercel-cli.js +1 -1
  131. package/dist/src/setup/flows/login.js +1 -1
  132. package/dist/src/setup/flows/model-login-connection.d.ts +0 -16
  133. package/dist/src/setup/flows/model-login-connection.js +1 -1
  134. package/dist/src/setup/flows/model-login-options.d.ts +59 -0
  135. package/dist/src/setup/flows/model-login-options.js +1 -0
  136. package/dist/src/setup/flows/model-login.js +1 -1
  137. package/dist/src/setup/flows/model-source-change.d.ts +0 -2
  138. package/dist/src/setup/flows/model-source-change.js +1 -1
  139. package/dist/src/setup/flows/registry-session.d.ts +15 -13
  140. package/dist/src/setup/flows/registry-session.js +1 -1
  141. package/dist/src/setup/flows/registry.js +1 -1
  142. package/dist/src/setup/flows/vercel-model-login.js +1 -1
  143. package/dist/src/setup/integrations/photon/setup-flow.js +1 -1
  144. package/dist/src/setup/integrations/runner.js +1 -1
  145. package/dist/src/setup/prompter.d.ts +2 -2
  146. package/dist/src/setup/registry-setup-client.js +1 -1
  147. package/dist/src/setup/registry-setup-protocol.d.ts +0 -4
  148. package/dist/src/setup/scaffold/create/project.js +1 -1
  149. package/dist/src/setup/slack-connect-lifecycle.js +1 -1
  150. package/dist/src/setup/slackbot.js +1 -1
  151. package/dist/src/setup/vercel-project.d.ts +2 -0
  152. package/dist/src/setup/vercel-project.js +0 -0
  153. package/dist/src/setup/vercel-trace-sampling.d.ts +3 -0
  154. package/dist/src/setup/vercel-trace-sampling.js +1 -0
  155. package/docs/channels/slack.mdx +31 -2
  156. package/docs/guides/deployment/vercel.mdx +2 -0
  157. package/docs/guides/dev-tui.md +1 -1
  158. package/docs/guides/instrumentation/agent-runs.mdx +4 -4
  159. package/docs/reference/agent-files.md +16 -0
  160. package/package.json +6 -6
  161. package/dist/src/compiled/_chunks/workflow/dist-CNT2vjZ4.js +0 -1
  162. package/dist/src/compiled/_chunks/workflow/dist-DtXwQbZr.js +0 -3
  163. package/dist/src/compiled/_chunks/workflow/frames-DnrfSd1P.js +0 -3
  164. package/dist/src/compiled/_chunks/workflow/resume-hook-BmJ263ZR.js +0 -1
  165. package/dist/src/compiled/_chunks/workflow/run-NLvREued.js +0 -1
  166. package/dist/src/compiled/_chunks/workflow/serialization-HCDeQWcR.js +0 -3
  167. package/dist/src/compiled/_chunks/workflow/sleep-Bi508qmg.js +0 -1
  168. package/dist/src/public/channels/slack/api-errors.d.ts +0 -33
  169. package/dist/src/public/channels/slack/api-errors.js +0 -1
  170. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/authorization.js +0 -0
  171. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/connector.js +0 -0
  172. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/index.js +0 -0
  173. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/installation.js +0 -0
  174. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/internal/base-url.js +0 -0
  175. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/internal/default-scopes.js +0 -0
  176. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/internal/env.js +0 -0
  177. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/internal/url-validation.js +0 -0
  178. /package/dist/src/node_modules/.pnpm/{@vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_37d5e4f23f0f03cba2e0819e67e81b38 → @vercel_connect@2.2.0_@ai-sdk_mcp@2.0.52_zod@4.5.4__@auth_core@0.41.2_@chat-adapter_sla_3fe44d656b2dcd93a04011e80966afff}/node_modules/@vercel/connect/dist/token.js +0 -0
@@ -1,3 +1,3 @@
1
1
  import{readProjectLink}from"#setup/project-resolution.js";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";const CREATED_CONNECTOR=/\bConnector created:\s*(scl_[A-Za-z0-9_-]+)\b/u;function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function parseJson(e){try{return JSON.parse(e)}catch{return}}function connectorCreationFailure(e,t){let n=t?.split(`
2
- `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`Vercel CLI `)).at(-1);return n===void 0?`Could not create the ${e} connector.`:`Could not create the ${e} connector. Vercel returned: ${n}`}function parseConnectorRef(e){if(!isRecord(e)||typeof e.uid!=`string`||typeof e.id!=`string`)return;let t={uid:e.uid,id:e.id};return typeof e.name==`string`&&(t.name=e.name),t}function parseCreatedConnector(e,t=`user`){let n=parseJson(e),r=parseConnectorRef(n);if(!isRecord(n)||r===void 0)return;let i=n.supportedSubjectTypes;return Array.isArray(i)&&i.includes(t)?r:void 0}function parseConnectorList(e,t){let n=[];for(let r of e){if(!isRecord(r)||typeof r.service==`string`&&r.service!==t)continue;let e=parseConnectorRef(r);e!==void 0&&n.push(e)}return n}function parseConnectorListPage(e,t){if(!isRecord(e)||!Array.isArray(e.connectors))return;let n=typeof e.cursor==`string`?e.cursor:void 0;return n===void 0?{connectors:parseConnectorList(e.connectors,t)}:{connectors:parseConnectorList(e.connectors,t),cursor:n}}async function listConnectors(e,t,n){let r=[],i=new Set,a;do{let o=[`connect`,`list`,`-F`,`json`,`--all-projects`,`--service`,e.service,`--scope`,t.orgId];a!==void 0&&o.push(`--next`,a);let s=await captureVercel(o,{cwd:e.projectRoot,onOutput:n,signal:e.signal});if(!s.ok)throw Error(s.failure.message);let c=parseConnectorListPage(parseJson(s.stdout),e.service);if(c===void 0)throw Error(`Vercel returned an invalid connector list for ${e.service}.`);r.push(...c.connectors);let l=c.cursor;if(l!==void 0&&i.has(l))throw Error(`The connector list repeated cursor ${l}.`);l!==void 0&&i.add(l),a=l}while(a!==void 0);return r}async function supportsPrincipalType(e,t,n,r){let i=`/v1/connect/connectors/${encodeURIComponent(n.id)}`,a=await captureVercel([`api`,i,`--scope`,t.orgId,`--raw`],{cwd:e.projectRoot,onOutput:r,signal:e.signal});if(!a.ok)throw Error(`Could not verify connector ${n.uid}.`);let o=parseJson(a.stdout);if(!isRecord(o)||o.id!==n.id||o.uid!==n.uid||typeof o.service==`string`&&o.service!==e.service)throw Error(`Vercel returned invalid details for connector ${n.uid}.`);let s=o.supportedSubjectTypes;return Array.isArray(s)&&s.includes(e.principalType??`user`)}function connectorNames(e){let t=new Set;for(let n of e){n.name!==void 0&&t.add(n.name.toLowerCase());let e=n.uid.slice(n.uid.lastIndexOf(`/`)+1).trim();e.length>0&&t.add(e.toLowerCase())}return t}function connectorMatchesCanonicalName(e,t){let n=t.toLowerCase();return e.name?.toLowerCase()===n||e.uid.slice(e.uid.lastIndexOf(`/`)+1).trim().toLowerCase()===n}function nextConnectorName(e,t){if(!t.has(e.toLowerCase()))return e;let n=2;for(;t.has(`${e}-${n}`.toLowerCase());)n+=1;return`${e}-${n}`}async function cleanupCreatedConnectionConnector(e){let t=e.orgId??(await readProjectLink(e.projectRoot))?.orgId,n=[`connect`,`remove`,e.connectorId,`--disconnect-all`,`--yes`];if(t!==void 0&&n.push(`--scope`,t),!await runVercel(n,{cwd:e.projectRoot,onOutput:createPromptCommandOutput(e.log)}))throw Error(`Could not remove connector ${e.connectorId}; run \`vercel connect remove ${e.connectorId} --disconnect-all --yes\`.`)}async function attach(e,t,n,r){return runVercel([`connect`,`attach`,n,`--yes`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:r,signal:e.signal})}async function resolveFallbackConnector(e,t,n,r,i){let a=e.principalType??`user`,o=i;for(;;){if(await e.prompter.select({message:`Which connector should ${e.slug} use?`,hintLayout:`inline`,notices:[{tone:`warning`,text:o}],options:[{value:`find`,label:`Find a new one`,hint:`Browse existing connectors`},{value:`create`,label:`Create a new one`,hint:`Register another connector`}]})===`find`){let i=[];for(let a of r)await supportsPrincipalType(e,t,a,n)&&i.push(a);if(i.length===0){o=`No existing ${e.service} connectors support ${a} credentials.`;continue}let s=new Map(i.map(e=>[e.uid,e])),c=await e.prompter.select({message:`Select a connector for ${e.slug}`,hintLayout:`inline`,search:!0,placeholder:`type to search connectors`,options:i.map(e=>({value:e.uid,label:e.uid,hint:e.name??e.id}))}),l=s.get(c);if(l===void 0)throw Error(`Connector ${c} is no longer available.`);return{kind:`existing`,connector:l}}let i=connectorNames(r),s=(await e.prompter.text({message:`New connector name`,defaultValue:nextConnectorName(e.slug,i),validate:e=>{let t=e.trim().toLowerCase();return t.length===0?`A name is required.`:i.has(t)?`A connector with this name already exists.`:void 0}})).trim(),c=[],createOutput=e=>{c.push(e.text),n(e)},l=await withPhase(e.log,`Waiting for you to complete setup in the browser…`,()=>runVercelCaptureStdout([`connect`,`create`,e.creationType??e.service,`--name`,s,...e.connectionMethod===void 0?[]:[`--connection-method`,e.connectionMethod],`-F`,`json`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:createOutput,signal:e.signal}),{kind:`external-action`,emphasis:`browser`}),u=parseConnectorRef(parseJson(l.stdout))?.id??CREATED_CONNECTOR.exec(c.join(`
2
+ `).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`Vercel CLI `)).at(-1);return n===void 0?`Could not create the ${e} connector.`:`Could not create the ${e} connector. Vercel returned: ${n}`}function parseConnectorRef(e){if(!isRecord(e)||typeof e.uid!=`string`||typeof e.id!=`string`)return;let t={uid:e.uid,id:e.id};return typeof e.name==`string`&&(t.name=e.name),t}function parseCreatedConnector(e,t=`user`){let n=parseJson(e),r=parseConnectorRef(n);if(!isRecord(n)||r===void 0)return;let i=n.supportedSubjectTypes;return Array.isArray(i)&&i.includes(t)?r:void 0}function parseConnectorList(e,t){let n=[];for(let r of e){if(!isRecord(r)||typeof r.service==`string`&&r.service!==t)continue;let e=parseConnectorRef(r);e!==void 0&&n.push(e)}return n}function parseConnectorListPage(e,t){if(!isRecord(e)||!Array.isArray(e.connectors))return;let n=typeof e.cursor==`string`?e.cursor:void 0;return n===void 0?{connectors:parseConnectorList(e.connectors,t)}:{connectors:parseConnectorList(e.connectors,t),cursor:n}}async function listConnectors(e,t,n){let r=[],i=new Set,a;do{let o=[`connect`,`list`,`-F`,`json`,`--all-projects`,`--service`,e.service,`--scope`,t.orgId];a!==void 0&&o.push(`--next`,a);let s=await captureVercel(o,{cwd:e.projectRoot,onOutput:n,signal:e.signal});if(!s.ok)throw Error(s.failure.message);let c=parseConnectorListPage(parseJson(s.stdout),e.service);if(c===void 0)throw Error(`Vercel returned an invalid connector list for ${e.service}.`);r.push(...c.connectors);let l=c.cursor;if(l!==void 0&&i.has(l))throw Error(`The connector list repeated cursor ${l}.`);l!==void 0&&i.add(l),a=l}while(a!==void 0);return r}async function supportsPrincipalType(e,t,n,r){let i=`/v1/connect/connectors/${encodeURIComponent(n.id)}`,a=await captureVercel([`api`,i,`--scope`,t.orgId,`--raw`],{cwd:e.projectRoot,onOutput:r,signal:e.signal});if(!a.ok)throw Error(`Could not verify connector ${n.uid}.`);let o=parseJson(a.stdout);if(!isRecord(o)||o.id!==n.id||o.uid!==n.uid||typeof o.service==`string`&&o.service!==e.service)throw Error(`Vercel returned invalid details for connector ${n.uid}.`);let s=o.supportedSubjectTypes;return Array.isArray(s)&&s.includes(e.principalType??`user`)}function connectorNames(e){let t=new Set;for(let n of e){n.name!==void 0&&t.add(n.name.toLowerCase());let e=n.uid.slice(n.uid.lastIndexOf(`/`)+1).trim();e.length>0&&t.add(e.toLowerCase())}return t}function connectorMatchesCanonicalName(e,t){let n=t.toLowerCase();return e.name?.toLowerCase()===n||e.uid.slice(e.uid.lastIndexOf(`/`)+1).trim().toLowerCase()===n}function nextConnectorName(e,t){if(!t.has(e.toLowerCase()))return e;let n=2;for(;t.has(`${e}-${n}`.toLowerCase());)n+=1;return`${e}-${n}`}async function cleanupCreatedConnectionConnector(e){let t=e.orgId??(await readProjectLink(e.projectRoot))?.orgId,n=[`connect`,`remove`,e.connectorId,`--disconnect-all`,`--yes`];if(t!==void 0&&n.push(`--scope`,t),!await runVercel(n,{cwd:e.projectRoot,onOutput:createPromptCommandOutput(e.log)}))throw Error(`Could not remove connector ${e.connectorId}; run \`vercel connect remove ${e.connectorId} --disconnect-all --yes\`.`)}async function attach(e,t,n,r){return runVercel([`connect`,`attach`,n,`--yes`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:r,signal:e.signal})}async function resolveFallbackConnector(e,t,n,r,i){let a=e.principalType??`user`,o=i;for(;;){if(await e.prompter.select({message:`Which connector should ${e.slug} use?`,hintLayout:`inline`,notices:[{tone:`warning`,text:o}],options:[{value:`find`,label:`Find a new one`,hint:`Browse existing connectors`},{value:`create`,label:`Create a new one`,hint:`Register another connector`}]})===`find`){let i=[];for(let a of r)await supportsPrincipalType(e,t,a,n)&&i.push(a);if(i.length===0){o=`No existing ${e.service} connectors support ${a} credentials.`;continue}let s=new Map(i.map(e=>[e.uid,e])),c=await e.prompter.select({message:`Select a connector for ${e.slug}`,hintLayout:`inline`,search:!0,placeholder:`type to search connectors`,options:i.map(e=>({value:e.uid,label:e.uid,hint:e.name??e.id}))}),l=s.get(c);if(l===void 0)throw Error(`Connector ${c} is no longer available.`);return{kind:`existing`,connector:l}}let i=connectorNames(r),s=(await e.prompter.text({message:`New connector name`,defaultValue:nextConnectorName(e.slug,i),validate:e=>{let t=e.trim().toLowerCase();return t.length===0?`A name is required.`:i.has(t)?`A connector with this name already exists.`:void 0}})).trim(),c=[],createOutput=e=>{c.push(e.text),n(e)},l=await withPhase(e.log,`Waiting for you to complete setup in the browser…`,()=>runVercelCaptureStdout([`connect`,`create`,e.creationType??e.service,`--name`,s,...e.connectionMethod===void 0?[]:[`--connection-method`,e.connectionMethod],`-F`,`json`,`--scope`,t.orgId],{cwd:e.projectRoot,onOutput:createOutput,signal:e.signal})),u=parseConnectorRef(parseJson(l.stdout))?.id??CREATED_CONNECTOR.exec(c.join(`
3
3
  `))?.[1],d=l.ok?parseCreatedConnector(l.stdout,a):void 0;if(d!==void 0)return{kind:`created`,connector:d};let f=l.ok?`The ${e.service} connector does not support ${a} credentials.`:connectorCreationFailure(e.service,l.stderr);if(u!==void 0){try{await cleanupCreatedConnectionConnector({log:e.log,projectRoot:e.projectRoot,connectorId:u,orgId:t.orgId})}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`${f} ${t}`)}e.signal?.throwIfAborted()}throw Error(f)}}async function setupConnectionConnector(e){let t=e.principalType??`user`,n=createPromptCommandOutput(e.log),r=e.project,i=await listConnectors(e,r,n),a=i.find(t=>connectorMatchesCanonicalName(t,e.canonicalConnectorName)),o=`Could not find a connector named ${e.canonicalConnectorName}.`;if(a!==void 0){if(await supportsPrincipalType(e,r,a,n)){if(await attach(e,r,a.uid,n))return e.log.success(`Attached ${a.uid} connector`),{kind:`existing`,connectorUid:a.uid};e.signal?.throwIfAborted(),o=`Could not attach ${a.uid}.`}else o=`${a.uid} does not support ${t} credentials.`}let s=await resolveFallbackConnector(e,r,n,i,o);if(!await attach(e,r,s.connector.uid,n)){if(s.kind===`created`){let t=`Could not attach ${s.connector.uid} to the linked project.`;try{await cleanupCreatedConnectionConnector({log:e.log,projectRoot:e.projectRoot,connectorId:s.connector.id,orgId:r.orgId})}catch(e){let n=e instanceof Error?e.message:String(e);throw Error(`${t} ${n}`)}throw e.signal?.throwIfAborted(),Error(t)}throw Error(`Could not attach ${s.connector.uid} to the linked project.`)}return e.log.success(`Attached ${s.connector.uid} connector`),s.kind===`created`?{kind:`created`,connectorUid:s.connector.uid,connectorId:s.connector.id}:{kind:`existing`,connectorUid:s.connector.uid}}export{cleanupCreatedConnectionConnector,parseCreatedConnector,setupConnectionConnector};
@@ -36,6 +36,7 @@ export declare function runDeployFlow(input: {
36
36
  appRoot: string;
37
37
  prompter: Prompter;
38
38
  signal?: AbortSignal;
39
+ traceSampling?: boolean;
39
40
  /** False when no TTY: an unlinked directory refuses instead of prompting. */
40
41
  interactive: boolean;
41
42
  deps?: Partial<DeployFlowDeps>;
@@ -1 +1 @@
1
- import{interactiveAsker,withAnswers}from"../ask.js";import{detectDeployment,isProjectResolved,projectResolutionFromDeployment}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{snapshotSetupState}from"../state.js";import{deployProject}from"../boxes/deploy-project.js";import{linkVercelProject}from"../boxes/link-project.js";import{resolveProvisioning}from"../boxes/resolve-provisioning.js";import{runHeadless,runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{runInstallVercelCliFlow}from"./install-vercel-cli.js";import{runLoginFlow}from"./login.js";import{inspectApplication}from"#services/inspect-application.js";import{isChatGptModelRouting}from"#shared/chatgpt-model.js";function productionUrlOf(e){return e.kind===`deployed`?e.productionUrl:void 0}async function runDeployFlow(e){let{appRoot:t,prompter:n,interactive:r,signal:i}=e,a={detectDeployment,inspectApplication,runLoginFlow,runInstallVercelCliFlow,...e.deps};try{let e=(await a.inspectApplication(t)).compiledState?.manifest.config.model?.routing;if(isChatGptModelRouting(e))return{kind:`local-model`}}catch{}let o=await withSpinner(n,`Checking the current Vercel link...`,async()=>{let e=await a.detectDeployment(t,{signal:i});return i?.throwIfAborted(),projectResolutionFromDeployment(e)}),s=isProjectResolved(o);if(!s&&!r)return{kind:`needs-link`};if(r){let e=await a.runLoginFlow({appRoot:t,prompter:n,signal:i});if(e.kind===`cli-missing`){let r=await a.runInstallVercelCliFlow({appRoot:t,prompter:n,signal:i});if(r.kind===`cancelled`)return{kind:`cancelled`};if(r.kind===`failed`)throw Error("Could not install the Vercel CLI. Install it with `npm i -g vercel@latest`, then retry deployment.");e=await a.runLoginFlow({appRoot:t,prompter:n,signal:i})}if(e.kind===`cancelled`)return{kind:`cancelled`};if(e.kind!==`already`&&e.kind!==`logged-in`)throw Error(e.kind===`unavailable`?`Could not reach Vercel. Check your connection and retry deployment.`:`Vercel login did not complete. Retry deployment to sign in.`)}let c=inProjectSetupState(t,o,{deploymentPending:!0}),l=s?[deployProject({prompter:n,headless:!r,deps:a.deployProject})]:[resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(n)),prompter:n,targetDirectory:t,mode:{headless:!1},deps:a.resolveProvisioning}),linkVercelProject({prompter:n,deps:a.linkProject}),deployProject({prompter:n,headless:!r,deps:a.deployProject})],u=prompterSink(n);if(!r)return{kind:`deployed`,productionUrl:productionUrlOf((await runHeadless(l,c,u,{snapshot:snapshotSetupState,signal:i})).project)};let d=await runInteractive(l,c,u,{snapshot:snapshotSetupState,signal:i});return d.kind===`cancelled`?{kind:`cancelled`}:{kind:`deployed`,productionUrl:productionUrlOf(d.state.project)}}export{runDeployFlow};
1
+ import{interactiveAsker,withAnswers}from"../ask.js";import{detectDeployment,isProjectResolved,projectResolutionFromDeployment}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{snapshotSetupState}from"../state.js";import{deployProject}from"../boxes/deploy-project.js";import{linkVercelProject}from"../boxes/link-project.js";import{resolveProvisioning}from"../boxes/resolve-provisioning.js";import{runHeadless,runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{runInstallVercelCliFlow}from"./install-vercel-cli.js";import{runLoginFlow}from"./login.js";import{inspectApplication}from"#services/inspect-application.js";import{isChatGptModelRouting}from"#shared/chatgpt-model.js";function productionUrlOf(e){return e.kind===`deployed`?e.productionUrl:void 0}async function runDeployFlow(e){let{appRoot:t,prompter:n,interactive:r,signal:i}=e,a={detectDeployment,inspectApplication,runLoginFlow,runInstallVercelCliFlow,...e.deps};try{let e=(await a.inspectApplication(t)).compiledState?.manifest.config.model?.routing;if(isChatGptModelRouting(e))return{kind:`local-model`}}catch{}let o=await withSpinner(n,`Checking the current Vercel link...`,async()=>{let e=await a.detectDeployment(t,{signal:i});return i?.throwIfAborted(),projectResolutionFromDeployment(e)}),s=isProjectResolved(o);if(!s&&!r)return{kind:`needs-link`};if(r){let e=await a.runLoginFlow({appRoot:t,prompter:n,signal:i});if(e.kind===`cli-missing`){let r=await a.runInstallVercelCliFlow({appRoot:t,prompter:n,signal:i});if(r.kind===`cancelled`)return{kind:`cancelled`};if(r.kind===`failed`)throw Error("Could not install the Vercel CLI. Install it with `npm i -g vercel@latest`, then retry deployment.");e=await a.runLoginFlow({appRoot:t,prompter:n,signal:i})}if(e.kind===`cancelled`)return{kind:`cancelled`};if(e.kind!==`already`&&e.kind!==`logged-in`)throw Error(e.kind===`unavailable`?`Could not reach Vercel. Check your connection and retry deployment.`:`Vercel login did not complete. Retry deployment to sign in.`)}let c=inProjectSetupState(t,o,{deploymentPending:!0}),l=s?[deployProject({prompter:n,headless:!r,deps:a.deployProject})]:[resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(n)),prompter:n,targetDirectory:t,mode:{headless:!1},deps:a.resolveProvisioning}),linkVercelProject({prompter:n,traceSampling:e.traceSampling,deps:a.linkProject}),deployProject({prompter:n,headless:!r,deps:a.deployProject})],u=prompterSink(n);if(!r)return{kind:`deployed`,productionUrl:productionUrlOf((await runHeadless(l,c,u,{snapshot:snapshotSetupState,signal:i})).project)};let d=await runInteractive(l,c,u,{snapshot:snapshotSetupState,signal:i});return d.kind===`cancelled`?{kind:`cancelled`}:{kind:`deployed`,productionUrl:productionUrlOf(d.state.project)}}export{runDeployFlow};
@@ -1 +1 @@
1
- import{withSpinner}from"../with-spinner.js";import{resultSucceeded,runVercel,spawnPackageManager}from"#setup/primitives/index.js";import{detectPackageManager}from"#setup/package-manager.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";import{createPromptCommandOutput}from"#setup/cli/index.js";const defaultDeps={getVercelAuthStatus,detectPackageManager,runVercel,spawnPackageManager};function globalInstallArguments(e){switch(e){case`npm`:return[`install`,`-g`,`vercel@latest`];case`yarn`:return[`global`,`add`,`vercel@latest`];case`pnpm`:case`bun`:return[`add`,`-g`,`vercel@latest`]}}function summarizeUpgradeFailure(e){let t=e.map(e=>e.trim().replace(/\s+/gu,` `)).filter(e=>e!==``&&e!==`}`&&!e.startsWith(`at `)&&!/^vercel upgrade exited with code \d+\.$/u.test(e)),n=t.find(e=>/^(?:error\b|err_|.*\b(?:cannot|failed|could not)\b)/iu.test(e))??t.at(-1);if(n!==void 0)return n.length<=240?n:`${n.slice(0,239)}…`}async function runInstallVercelCliFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={...defaultDeps,...e.deps},a=createPromptCommandOutput(n.log),probe=async()=>await i.getVercelAuthStatus(t,{signal:r})!==`cli-missing`;if(!e.upgrade&&await withSpinner(n,`Checking for the Vercel CLI…`,probe))return r?.throwIfAborted(),{kind:`already`};r?.throwIfAborted();let o,s;if(e.upgrade){let e=[];o=await withSpinner(n,`Upgrading the Vercel CLI…`,async()=>{let n=await i.runVercel([`upgrade`],{cwd:t,onOutput:t=>{a(t),t.stream===`stderr`&&e.push(t.text)},signal:r,nonInteractive:!0});return n||(s=summarizeUpgradeFailure(e)),n})}else{let e=await i.detectPackageManager(t);o=await withSpinner(n,`Installing the Vercel CLI with ${e.kind}…`,async()=>resultSucceeded(await i.spawnPackageManager(e.kind,t,globalInstallArguments(e.kind),{onOutput:a,signal:r,nonInteractive:!0})))}if(r?.aborted===!0)return{kind:`cancelled`};if(!o)return s===void 0?{kind:`failed`}:{kind:`failed`,reason:s};let c=await withSpinner(n,`Verifying the Vercel CLI…`,probe);return r?.throwIfAborted(),c?{kind:`installed`}:e.upgrade?{kind:`failed`,reason:`The Vercel CLI could not be found after the upgrade completed.`}:{kind:`failed`}}export{runInstallVercelCliFlow};
1
+ import{withSpinner}from"../with-spinner.js";import{resultSucceeded,runVercel,spawnPackageManager}from"#setup/primitives/index.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";import{detectPackageManager}from"#setup/package-manager.js";import{createPromptCommandOutput}from"#setup/cli/index.js";const defaultDeps={getVercelAuthStatus,detectPackageManager,runVercel,spawnPackageManager};function globalInstallArguments(e){switch(e){case`npm`:return[`install`,`-g`,`vercel@latest`];case`yarn`:return[`global`,`add`,`vercel@latest`];case`pnpm`:case`bun`:return[`add`,`-g`,`vercel@latest`]}}function summarizeUpgradeFailure(e){let t=e.map(e=>e.trim().replace(/\s+/gu,` `)).filter(e=>e!==``&&e!==`}`&&!e.startsWith(`at `)&&!/^vercel upgrade exited with code \d+\.$/u.test(e)),n=t.find(e=>/^(?:error\b|err_|.*\b(?:cannot|failed|could not)\b)/iu.test(e))??t.at(-1);if(n!==void 0)return n.length<=240?n:`${n.slice(0,239)}…`}async function runInstallVercelCliFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={...defaultDeps,...e.deps},a=createPromptCommandOutput(n.log),probe=async()=>await i.getVercelAuthStatus(t,{signal:r})!==`cli-missing`;if(!e.upgrade&&await withSpinner(n,`Checking for the Vercel CLI…`,probe))return r?.throwIfAborted(),{kind:`already`};r?.throwIfAborted();let o,s;if(e.upgrade){let e=[];o=await withSpinner(n,`Upgrading the Vercel CLI…`,async()=>{let n=await i.runVercel([`upgrade`],{cwd:t,onOutput:t=>{a(t),t.stream===`stderr`&&e.push(t.text)},signal:r,nonInteractive:!0});return n||(s=summarizeUpgradeFailure(e)),n})}else{let e=await i.detectPackageManager(t);o=await withSpinner(n,`Installing the Vercel CLI with ${e.kind}…`,async()=>resultSucceeded(await i.spawnPackageManager(e.kind,t,globalInstallArguments(e.kind),{onOutput:a,signal:r,nonInteractive:!0})))}if(r?.aborted===!0)return{kind:`cancelled`};if(!o)return s===void 0?{kind:`failed`}:{kind:`failed`,reason:s};let c=await withSpinner(n,`Verifying the Vercel CLI…`,probe);return r?.throwIfAborted(),c?{kind:`installed`}:e.upgrade?{kind:`failed`,reason:`The Vercel CLI could not be found after the upgrade completed.`}:{kind:`failed`}}export{runInstallVercelCliFlow};
@@ -1 +1 @@
1
- import{withSpinner}from"../with-spinner.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function vercelLoginUrl(e){return e.match(/https:\/\/vercel\.com\/oauth\/device\?[^\s]+/u)?.[0]}const defaultDeps={getVercelAuthStatus,runVercelLogin:({cwd:e,onOutput:t,signal:n})=>runVercel([`login`],{cwd:e,nonInteractive:!0,onOutput:t,timeoutMs:3e5,signal:n})};async function runVercelLoginWithControls(e,t,n,r,i){if(r.awaitChoice===void 0)return withSpinner(r,`Opening Vercel login in your browser…`,()=>e.runVercelLogin({cwd:t,onOutput:n,signal:i}));let a=new AbortController,o=i?AbortSignal.any([i,a.signal]):a.signal,s=r.awaitChoice({status:`Logging in to Vercel…`,context:`Complete the login in your browser`,actions:[{value:`cancel`,label:`Cancel`}]}),c=e.runVercelLogin({cwd:t,onOutput:n,signal:o});try{let e=await Promise.race([c.then(e=>({via:`work`,ok:e})),s.choice.then(()=>({via:`choice`}))]);return e.via===`work`?e.ok:(a.abort(),await c.catch(()=>{}),`cancelled`)}finally{s.close()}}async function runLoginFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={...defaultDeps,...e.deps},a=createPromptCommandOutput(n.log),o,onOutput=e=>{a(e);let t=vercelLoginUrl(e.text);t!==void 0&&t!==o&&(o=t,n.log.info(`Open ${t}`))},probeAuth=()=>i.getVercelAuthStatus(t,{signal:r}),s=await withSpinner(n,`Checking your Vercel login…`,probeAuth);switch(r?.throwIfAborted(),s){case`authenticated`:if(e.force!==!0)return{kind:`already`};break;case`cli-missing`:return{kind:`cli-missing`};case`unavailable`:return{kind:`unavailable`};case`logged-out`:break;default:return s}if(e.allowLogin===!1)return{kind:`failed`};let c=await runVercelLoginWithControls(i,t,onOutput,n,r);if(c===`cancelled`)return{kind:`cancelled`};if(!c)return{kind:`failed`};let l=await withSpinner(n,`Confirming your Vercel login…`,probeAuth);switch(r?.throwIfAborted(),l){case`authenticated`:return{kind:`logged-in`};case`logged-out`:return{kind:`failed`};case`cli-missing`:return{kind:`cli-missing`};case`unavailable`:return{kind:`unavailable`};default:return l}}export{runLoginFlow};
1
+ import{withSpinner}from"../with-spinner.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";import{runVercel}from"#setup/primitives/run-vercel.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function vercelLoginUrl(e){return e.match(/https:\/\/vercel\.com\/oauth\/device\?[^\s]+/u)?.[0]}const defaultDeps={getVercelAuthStatus,runVercelLogin:({cwd:e,onOutput:t,signal:n})=>runVercel([`login`],{cwd:e,nonInteractive:!0,onOutput:t,timeoutMs:3e5,signal:n})};async function runVercelLoginWithControls(e,t,n,r,i){if(r.awaitChoice===void 0)return withSpinner(r,`Opening Vercel login in your browser…`,()=>e.runVercelLogin({cwd:t,onOutput:n,signal:i}));let a=new AbortController,o=i?AbortSignal.any([i,a.signal]):a.signal,s=r.awaitChoice({status:`Logging in to Vercel…`,context:`Complete the login in your browser`,actions:[{value:`cancel`,label:`Cancel`}]}),c=e.runVercelLogin({cwd:t,onOutput:n,signal:o});try{let e=await Promise.race([c.then(e=>({via:`work`,ok:e})),s.choice.then(()=>({via:`choice`}))]);return e.via===`work`?e.ok:(a.abort(),await c.catch(()=>{}),`cancelled`)}finally{s.close()}}async function runLoginFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={...defaultDeps,...e.deps},a=createPromptCommandOutput(n.log),o,onOutput=e=>{a(e);let t=vercelLoginUrl(e.text);t!==void 0&&t!==o&&(o=t,n.log.info(`Open ${t}`))},probeAuth=()=>i.getVercelAuthStatus(t,{signal:r}),s=await withSpinner(n,`Checking your Vercel login…`,probeAuth);switch(r?.throwIfAborted(),s){case`authenticated`:if(e.force!==!0)return{kind:`already`};break;case`cli-missing`:return{kind:`cli-missing`};case`unavailable`:return{kind:`unavailable`};case`logged-out`:break;default:return s}if(e.allowLogin===!1)return{kind:`failed`};let c=await runVercelLoginWithControls(i,t,onOutput,n,r);if(c===`cancelled`)return{kind:`cancelled`};if(!c)return{kind:`failed`};let l=await withSpinner(n,`Confirming your Vercel login…`,probeAuth);switch(r?.throwIfAborted(),l){case`authenticated`:return{kind:`logged-in`};case`logged-out`:return{kind:`failed`};case`cli-missing`:return{kind:`cli-missing`};case`unavailable`:return{kind:`unavailable`};default:return l}}export{runLoginFlow};
@@ -1,21 +1,5 @@
1
1
  import { type ModelConnectionSelection } from "#internal/model-auth/store.js";
2
2
  import type { Prompter } from "#setup/prompter.js";
3
- export declare const CONNECTION_OPTIONS: readonly [{
4
- readonly value: "vercel";
5
- readonly label: "Vercel Account";
6
- }, {
7
- readonly value: "ai-gateway-key";
8
- readonly label: "Vercel AI Gateway API Key";
9
- }, {
10
- readonly value: "chatgpt";
11
- readonly label: "ChatGPT Subscription";
12
- }, {
13
- readonly value: "openai";
14
- readonly label: "OpenAI API Key";
15
- }, {
16
- readonly value: "anthropic";
17
- readonly label: "Anthropic API Key";
18
- }];
19
3
  type Team = {
20
4
  teamId: string;
21
5
  teamName: string;
@@ -1 +1 @@
1
- import{ensureChatGptAuth}from"./chatgpt-auth.js";import{withLoginProgress}from"./model-login-progress.js";import{loginVercelModel}from"./vercel-model-login.js";import{resolveModelApiKey}from"#internal/model-auth/transport.js";import{getVercelOidcToken}from"#compiled/@vercel/oidc/index.js";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{availableDirectModels}from"#internal/model-auth/available-models.js";import{modelKeySecretName,readVercelSession,writeModelSecret}from"#internal/model-auth/store.js";import{readVercelCliConnection,refreshVercelCliConnection}from"#internal/model-auth/vercel-cli.js";import{VERCEL_MODEL_CLIENT_ID,resolveVercelSession,validateVercelAccess}from"#internal/model-auth/vercel.js";import{validateGatewayApiKey}from"#setup/validate-gateway-key.js";const CONNECTION_OPTIONS=[{value:`vercel`,label:`Vercel Account`},{value:`ai-gateway-key`,label:`Vercel AI Gateway API Key`},{value:`chatgpt`,label:`ChatGPT Subscription`},{value:`openai`,label:`OpenAI API Key`},{value:`anthropic`,label:`Anthropic API Key`}];async function reuseModelConnection(e,t,n){switch(e){case`chatgpt`:return(await getDefaultCodexTokenBroker().refreshState()).kind===`ready`?{selected:e}:void 0;case`vercel`:{if(!await readVercelSession(VERCEL_MODEL_CLIENT_ID))return;let r=await resolveVercelSession();return t??={teamId:r.teamId,teamName:r.teamName},await validateVercelAccess(r.accessToken,t.teamId,n),{selected:e,team:t}}case`vercel-cli`:{let r=await readVercelCliConnection();if(!r)return;t??={teamId:r.teamId,teamName:r.teamId};try{await validateVercelAccess(r.token,t.teamId,n)}catch{if(n?.throwIfAborted(),await refreshVercelCliConnection(),r=await readVercelCliConnection(),!r)return;await validateVercelAccess(r.token,t.teamId,n)}return{selected:e,team:t}}case`ai-gateway-project`:return await getVercelOidcToken().catch(()=>void 0)?{selected:e}:void 0;case`ai-gateway-key`:{let t=await resolveModelApiKey(e);return(await validateGatewayApiKey(t,n)).kind===`valid`?{selected:e}:void 0}case`openai`:case`anthropic`:return{selected:e,availableModels:await availableDirectModels(e,await resolveModelApiKey(e),n)}}}async function authenticateModelConnection(e){let{selected:t,prompter:n,signal:r}=e;if(t===`vercel`)return{selected:t,team:await loginVercelModel(n,r,e.team?.teamId)};if(t===`chatgpt`)return await ensureChatGptAuth({signal:r,log:e=>n.log.info(e)}),{selected:t};if(t===`vercel-cli`||t===`ai-gateway-project`)throw Error(`Choose a connection with /login.`);let i=CONNECTION_OPTIONS.find(e=>e.value===t).label,a=(await n.password({message:i,validate:e=>e.trim()?void 0:`Enter an API key.`})).trim(),o=await withLoginProgress(n,`Checking ${i}…`,async()=>{if(t!==`ai-gateway-key`)return availableDirectModels(t,a,r);if((await validateGatewayApiKey(a,r)).kind!==`valid`)throw Error(`Could not validate the Gateway key. Check the key and your connection, then retry.`)});return r?.throwIfAborted(),await writeModelSecret(modelKeySecretName(t),a),{selected:t,availableModels:o}}export{CONNECTION_OPTIONS,authenticateModelConnection,reuseModelConnection};
1
+ import{ensureChatGptAuth}from"./chatgpt-auth.js";import{withLoginProgress}from"./model-login-progress.js";import{loginVercelModel}from"./vercel-model-login.js";import{CONNECTION_OPTIONS}from"./model-login-options.js";import{resolveModelApiKey}from"#internal/model-auth/transport.js";import{getVercelOidcToken}from"#compiled/@vercel/oidc/index.js";import{getDefaultCodexTokenBroker}from"#public/models/openai/chatgpt/token-broker.js";import{readVercelCliConnection,refreshVercelCliConnection}from"#internal/model-auth/vercel-cli.js";import{availableDirectModels}from"#internal/model-auth/available-models.js";import{modelKeySecretName,readVercelSession,writeModelSecret}from"#internal/model-auth/store.js";import{VERCEL_MODEL_CLIENT_ID,resolveVercelSession,validateVercelAccess}from"#internal/model-auth/vercel.js";import{validateGatewayApiKey}from"#setup/validate-gateway-key.js";async function reuseModelConnection(e,t,n){switch(e){case`chatgpt`:return(await getDefaultCodexTokenBroker().refreshState()).kind===`ready`?{selected:e}:void 0;case`vercel`:{if(!await readVercelSession(VERCEL_MODEL_CLIENT_ID))return;let r=await resolveVercelSession();return t??={teamId:r.teamId,teamName:r.teamName},await validateVercelAccess(r.accessToken,t.teamId,n),{selected:e,team:t}}case`vercel-cli`:{let r=await readVercelCliConnection();if(!r)return;t??={teamId:r.teamId,teamName:r.teamId};try{await validateVercelAccess(r.token,t.teamId,n)}catch{if(n?.throwIfAborted(),await refreshVercelCliConnection(),r=await readVercelCliConnection(),!r)return;await validateVercelAccess(r.token,t.teamId,n)}return{selected:e,team:t}}case`ai-gateway-project`:return await getVercelOidcToken().catch(()=>void 0)?{selected:e}:void 0;case`ai-gateway-key`:{let t=await resolveModelApiKey(e);return(await validateGatewayApiKey(t,n)).kind===`valid`?{selected:e}:void 0}case`openai`:case`anthropic`:return{selected:e,availableModels:await availableDirectModels(e,await resolveModelApiKey(e),n)}}}async function authenticateModelConnection(e){let{selected:t,prompter:n,signal:r}=e;if(t===`vercel`)return{selected:t,team:await loginVercelModel(n,r,e.team?.teamId)};if(t===`chatgpt`)return await ensureChatGptAuth({signal:r,log:e=>n.log.info(e)}),{selected:t};if(t===`vercel-cli`||t===`ai-gateway-project`)throw Error(`Choose a connection with /login.`);let i=CONNECTION_OPTIONS.find(e=>e.value===t).label,a=(await n.password({message:i,validate:e=>e.trim()?void 0:`Enter an API key.`})).trim(),o=await withLoginProgress(n,`Checking ${i}…`,async()=>{if(t!==`ai-gateway-key`)return availableDirectModels(t,a,r);if((await validateGatewayApiKey(a,r)).kind!==`valid`)throw Error(`Could not validate the Gateway key. Check the key and your connection, then retry.`)});return r?.throwIfAborted(),await writeModelSecret(modelKeySecretName(t),a),{selected:t,availableModels:o}}export{authenticateModelConnection,reuseModelConnection};
@@ -0,0 +1,59 @@
1
+ import type { ModelConnectionSelection } from "#shared/model-connection.js";
2
+ export declare const LOGIN_CONNECTION_OPTIONS: readonly [{
3
+ readonly command: "vercel";
4
+ readonly commandOrder: 0;
5
+ readonly value: "vercel";
6
+ readonly label: "Vercel Account";
7
+ }, {
8
+ readonly command: "vercel-api-key";
9
+ readonly commandOrder: 2;
10
+ readonly value: "ai-gateway-key";
11
+ readonly label: "Vercel AI Gateway API Key";
12
+ }, {
13
+ readonly command: "chatgpt";
14
+ readonly commandOrder: 1;
15
+ readonly value: "chatgpt";
16
+ readonly label: "ChatGPT Subscription";
17
+ }, {
18
+ readonly command: "openai-api-key";
19
+ readonly commandOrder: 3;
20
+ readonly value: "openai";
21
+ readonly label: "OpenAI API Key";
22
+ }, {
23
+ readonly command: "anthropic-api-key";
24
+ readonly commandOrder: 4;
25
+ readonly value: "anthropic";
26
+ readonly label: "Anthropic API Key";
27
+ }];
28
+ export declare const CONNECTION_OPTIONS: {
29
+ value: "ai-gateway-key" | "anthropic" | "chatgpt" | "openai" | "vercel";
30
+ label: "Anthropic API Key" | "ChatGPT Subscription" | "OpenAI API Key" | "Vercel AI Gateway API Key" | "Vercel Account";
31
+ }[];
32
+ export declare const LOGIN_CONNECTION_COMMAND_OPTIONS: ({
33
+ readonly command: "vercel";
34
+ readonly commandOrder: 0;
35
+ readonly value: "vercel";
36
+ readonly label: "Vercel Account";
37
+ } | {
38
+ readonly command: "vercel-api-key";
39
+ readonly commandOrder: 2;
40
+ readonly value: "ai-gateway-key";
41
+ readonly label: "Vercel AI Gateway API Key";
42
+ } | {
43
+ readonly command: "chatgpt";
44
+ readonly commandOrder: 1;
45
+ readonly value: "chatgpt";
46
+ readonly label: "ChatGPT Subscription";
47
+ } | {
48
+ readonly command: "openai-api-key";
49
+ readonly commandOrder: 3;
50
+ readonly value: "openai";
51
+ readonly label: "OpenAI API Key";
52
+ } | {
53
+ readonly command: "anthropic-api-key";
54
+ readonly commandOrder: 4;
55
+ readonly value: "anthropic";
56
+ readonly label: "Anthropic API Key";
57
+ })[];
58
+ export declare function loginConnectionForCommand(command: string): ModelConnectionSelection | undefined;
59
+ export declare const LOGIN_CONNECTION_COMMAND_HINT: string;
@@ -0,0 +1 @@
1
+ const LOGIN_CONNECTION_OPTIONS=[{command:`vercel`,commandOrder:0,value:`vercel`,label:`Vercel Account`},{command:`vercel-api-key`,commandOrder:2,value:`ai-gateway-key`,label:`Vercel AI Gateway API Key`},{command:`chatgpt`,commandOrder:1,value:`chatgpt`,label:`ChatGPT Subscription`},{command:`openai-api-key`,commandOrder:3,value:`openai`,label:`OpenAI API Key`},{command:`anthropic-api-key`,commandOrder:4,value:`anthropic`,label:`Anthropic API Key`}],CONNECTION_OPTIONS=LOGIN_CONNECTION_OPTIONS.map(({value:e,label:t})=>({value:e,label:t})),LOGIN_CONNECTION_COMMAND_OPTIONS=[...LOGIN_CONNECTION_OPTIONS].sort((e,t)=>e.commandOrder-t.commandOrder);function loginConnectionForCommand(e){return LOGIN_CONNECTION_OPTIONS.find(t=>t.command===e)?.value}const LOGIN_CONNECTION_COMMAND_HINT=LOGIN_CONNECTION_COMMAND_OPTIONS.map(e=>e.command).join(`|`);export{CONNECTION_OPTIONS,LOGIN_CONNECTION_COMMAND_HINT,LOGIN_CONNECTION_COMMAND_OPTIONS,LOGIN_CONNECTION_OPTIONS,loginConnectionForCommand};
@@ -1 +1 @@
1
- import{fetchGatewayCatalog}from"../boxes/select-model.js";import{measureLoginStage,withLoginProgress}from"./model-login-progress.js";import{CONNECTION_OPTIONS,authenticateModelConnection,reuseModelConnection}from"./model-login-connection.js";import{changeValidatedAgentModel,readAuthoredModelSelection}from"./model-source-change.js";import{MODEL_CONNECTION_ENV}from"#internal/model-auth/transport.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{WizardCancelledError}from"#setup/step.js";import{MODEL_HELPERS,parseModelHelper}from"#shared/model-helper.js";import{providerSettingsMatch,readProviderKeySourceSync,readProviderSelection,readProviderTeamSync,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{resolveModelEndpointStatus}from"#internal/resolve-model-endpoint-status.js";import{classifyModelRouting}from"#internal/classify-model-routing.js";import{availableHelperModels}from"#internal/model-auth/available-models.js";import{isModelConnection,readDefaultConnection,writeDefaultConnection}from"#internal/model-auth/store.js";function environmentConnection(e){if(e.AI_GATEWAY_API_KEY?.trim())return`ai-gateway-key`;if(e.VERCEL_OIDC_TOKEN?.trim())return`ai-gateway-project`;if(e.OPENAI_API_KEY?.trim())return`openai`;if(e.ANTHROPIC_API_KEY?.trim())return`anthropic`}async function readLoginModel(e){let t=await readAuthoredModelSelection(e);if(t!==void 0)return{selection:t,external:parseModelHelper(t)!==void 0};let n=(await inspectApplication(e)).compiledState?.manifest.config.model;return{selection:n?.routing.kind===`gateway`&&n.source===void 0?n.id:void 0,external:n?.routing.kind===`external`}}function modelSelection(e,t){let n=e===`chatgpt`||e===`openai`||e===`anthropic`?e:void 0,r=t.selection===void 0?void 0:parseModelHelper(t.selection),i=n?r?.helper===n:t.selection!==void 0&&!t.external,a=n?MODEL_HELPERS[n].defaultModel:DEFAULT_AGENT_MODEL_ID,o=r?.id??t.selection;return{helper:n,compatible:i,defaultId:a,needsModels:!i||o===a}}async function applyConnection(e,t,n,r){let{appRoot:i,prompter:a,signal:o}=e,{selected:s,team:c}=t,{helper:l,compatible:u,defaultId:d,needsModels:f}=modelSelection(s,n),p;if(f){let e=t.availableModels??r??(l?await withLoginProgress(a,`Loading available models…`,()=>availableHelperModels(l,o)):[]),i=d;if(!e.includes(i)){if(e.length===0)throw Error(`No models are available for this connection. Choose another connection with /login.`);i=await a.select({message:`Choose an available model`,search:!0,options:e.map(e=>({value:e,label:e}))})}let s=l?MODEL_HELPERS[l].prefix+i:i;(!u||s!==n.selection)&&(p=s)}let m=s===`openai`||s===`anthropic`||s===`ai-gateway-key`?e.automatic?readProviderKeySourceSync(i)??(environmentConnection(process.env)===s?`environment`:`secret`):`secret`:void 0,h={selected:s,...c,keySource:m},g=!await providerSettingsMatch(i,h),save=async()=>{if(o?.throwIfAborted(),p!==void 0){let t=await changeValidatedAgentModel({appRoot:e.agentRoot??i,slug:p});if(t.kind===`rejected`)throw Error(t.message)}g&&await writeProviderSelection(i,s,c,m),process.env[MODEL_CONNECTION_ENV]=s,m?process.env.EVE_MODEL_KEY_SOURCE=m:delete process.env.EVE_MODEL_KEY_SOURCE,c?(process.env.EVE_MODEL_TEAM=c.teamId,process.env.EVE_MODEL_TEAM_NAME=c.teamName):(delete process.env.EVE_MODEL_TEAM,delete process.env.EVE_MODEL_TEAM_NAME)};p===void 0?await save():await withLoginProgress(a,`Loading selected model…`,()=>measureLoginStage(`activation`,()=>e.withConnectionUpdate?e.withConnectionUpdate(save):save())),e.automatic||await writeDefaultConnection(s);let _=p??n.selection,v=l&&_?parseModelHelper(_)?.id:_,y;if(v){let e=l?{kind:`external`,provider:MODEL_HELPERS[l].provider}:classifyModelRouting(v);y={id:v,routing:e,endpoint:resolveModelEndpointStatus(e,{apiKey:s===`ai-gateway-key`,oidc:s===`ai-gateway-project`,account:s===`vercel`||s===`vercel-cli`,team:c?.teamName},{state:`ready`})}}return{kind:`ready`,reload:p!==void 0&&e.withConnectionUpdate===void 0,...y&&{model:y}}}async function runModelLogin(e){let{appRoot:t,prompter:n,signal:r}=e,i,getModel=()=>i??=measureLoginStage(`source_inspection`,()=>readLoginModel(e.agentRoot??t)),connect=async(i,a)=>{let o=new AbortController,s=r?AbortSignal.any([r,o.signal]):o.signal,c=getModel().then(async e=>{let t=modelSelection(i,e);return{model:e,models:!t.helper&&t.needsModels?(await measureLoginStage(`gateway_catalog`,()=>fetchGatewayCatalog(s))).filter(e=>e.type===`language`).map(e=>e.id):void 0}}).then(e=>({value:e}),e=>({error:e}));try{let r=readProviderTeamSync(t),o=await measureLoginStage(`authentication`,async()=>a?await withLoginProgress(n,`Checking model access…`,()=>reuseModelConnection(i,r,s)):await authenticateModelConnection({selected:i,team:r,prompter:n,signal:s}));if(!o)return;let l=await withLoginProgress(n,`Loading available models…`,()=>c);if(`error`in l)throw l.error;return await applyConnection({...e,automatic:a,signal:s},o,l.value.model,l.value.models)}finally{o.abort()}};try{if(e.automatic){let{model:e,selected:a}=await withLoginProgress(n,`Reading saved connection…`,async()=>{let[e,n,r,i]=await Promise.all([getModel(),readProviderSelection(t),resolveAvailableProviders(t),readDefaultConnection()]),a=e.selection===void 0?void 0:parseModelHelper(e.selection)?.helper;return{model:e,selected:n??a??environmentConnection(process.env)??(r.includes(`ai-gateway-project`)?`ai-gateway-project`:void 0)??i??`vercel-cli`}});if(e.external&&e.selection===void 0)return{kind:`ready`,reload:!1};try{let e=await connect(a,!0);if(e)return e}catch(e){i=void 0,r?.throwIfAborted(),n.log.warning(e instanceof Error?e.message:`Could not connect automatically. Retry /login.`)}}let a=e.selected;for(;;){let t=a??await n.select({message:e.connectionMessage??`Choose a connection`,search:!0,options:[...CONNECTION_OPTIONS]});if(a=void 0,!isModelConnection(t))throw Error(`Choose a model connection.`);try{let e=await connect(t,!1);if(e)return e}catch(e){if(i=void 0,e instanceof WizardCancelledError)return{kind:`cancelled`};r?.throwIfAborted(),n.log.warning(e instanceof Error?e.message:`Connection failed. Retry /login.`)}}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}export{environmentConnection,runModelLogin};
1
+ import{fetchGatewayCatalog}from"../boxes/select-model.js";import{measureLoginStage,withLoginProgress}from"./model-login-progress.js";import{CONNECTION_OPTIONS}from"./model-login-options.js";import{authenticateModelConnection,reuseModelConnection}from"./model-login-connection.js";import{changeValidatedAgentModel,readAuthoredModelSelection}from"./model-source-change.js";import{MODEL_CONNECTION_ENV}from"#internal/model-auth/transport.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{inspectApplication}from"#services/inspect-application.js";import{WizardCancelledError}from"#setup/step.js";import{MODEL_HELPERS,parseModelHelper}from"#shared/model-helper.js";import{providerSettingsMatch,readProviderKeySourceSync,readProviderSelection,readProviderTeamSync,resolveAvailableProviders,writeProviderSelection}from"#setup/provider-settings.js";import{resolveModelEndpointStatus}from"#internal/resolve-model-endpoint-status.js";import{classifyModelRouting}from"#internal/classify-model-routing.js";import{availableHelperModels}from"#internal/model-auth/available-models.js";import{isModelConnection,readDefaultConnection,writeDefaultConnection}from"#internal/model-auth/store.js";function environmentConnection(e){if(e.AI_GATEWAY_API_KEY?.trim())return`ai-gateway-key`;if(e.VERCEL_OIDC_TOKEN?.trim())return`ai-gateway-project`;if(e.OPENAI_API_KEY?.trim())return`openai`;if(e.ANTHROPIC_API_KEY?.trim())return`anthropic`}async function readLoginModel(e){let t=await readAuthoredModelSelection(e);if(t!==void 0)return{selection:t,external:parseModelHelper(t)!==void 0};let n=(await inspectApplication(e)).compiledState?.manifest.config.model;return{selection:n?.routing.kind===`gateway`&&n.source===void 0?n.id:void 0,external:n?.routing.kind===`external`}}function modelSelection(e,t){let n=e===`chatgpt`||e===`openai`||e===`anthropic`?e:void 0,r=t.selection===void 0?void 0:parseModelHelper(t.selection),i=n?r?.helper===n:t.selection!==void 0&&!t.external,a=n?MODEL_HELPERS[n].defaultModel:DEFAULT_AGENT_MODEL_ID,o=r?.id??t.selection;return{helper:n,compatible:i,defaultId:a,needsModels:!i||o===a}}async function applyConnection(e,t,n,r){let{appRoot:i,prompter:a,signal:o}=e,{selected:s,team:c}=t,{helper:l,compatible:u,defaultId:d,needsModels:f}=modelSelection(s,n),p;if(f){let e=t.availableModels??r??(l?await withLoginProgress(a,`Loading available models…`,()=>availableHelperModels(l,o)):[]),i=d;if(!e.includes(i)){if(e.length===0)throw Error(`No models are available for this connection. Choose another connection with /login.`);i=await a.select({message:`Choose an available model`,search:!0,options:e.map(e=>({value:e,label:e}))})}let s=l?MODEL_HELPERS[l].prefix+i:i;(!u||s!==n.selection)&&(p=s)}let m=s===`openai`||s===`anthropic`||s===`ai-gateway-key`?e.automatic?readProviderKeySourceSync(i)??(environmentConnection(process.env)===s?`environment`:`secret`):`secret`:void 0,h={selected:s,...c,keySource:m},g=!await providerSettingsMatch(i,h),save=async()=>{if(o?.throwIfAborted(),p!==void 0){let t=await changeValidatedAgentModel({appRoot:e.agentRoot??i,slug:p});if(t.kind===`rejected`)throw Error(t.message)}g&&await writeProviderSelection(i,s,c,m),process.env[MODEL_CONNECTION_ENV]=s,m?process.env.EVE_MODEL_KEY_SOURCE=m:delete process.env.EVE_MODEL_KEY_SOURCE,c?(process.env.EVE_MODEL_TEAM=c.teamId,process.env.EVE_MODEL_TEAM_NAME=c.teamName):(delete process.env.EVE_MODEL_TEAM,delete process.env.EVE_MODEL_TEAM_NAME)};p===void 0?await save():await withLoginProgress(a,`Loading selected model…`,()=>measureLoginStage(`activation`,()=>e.withConnectionUpdate?e.withConnectionUpdate(save):save())),e.automatic||await writeDefaultConnection(s);let _=p??n.selection,v=l&&_?parseModelHelper(_)?.id:_,y;if(v){let e=l?{kind:`external`,provider:MODEL_HELPERS[l].provider}:classifyModelRouting(v);y={id:v,routing:e,endpoint:resolveModelEndpointStatus(e,{apiKey:s===`ai-gateway-key`,oidc:s===`ai-gateway-project`,account:s===`vercel`||s===`vercel-cli`,team:c?.teamName},{state:`ready`})}}return{kind:`ready`,reload:p!==void 0&&e.withConnectionUpdate===void 0,...y&&{model:y}}}async function runModelLogin(e){let{appRoot:t,prompter:n,signal:r}=e,i,getModel=()=>i??=measureLoginStage(`source_inspection`,()=>readLoginModel(e.agentRoot??t)),connect=async(i,a)=>{let o=new AbortController,s=r?AbortSignal.any([r,o.signal]):o.signal,c=getModel().then(async e=>{let t=modelSelection(i,e);return{model:e,models:!t.helper&&t.needsModels?(await measureLoginStage(`gateway_catalog`,()=>fetchGatewayCatalog(s))).filter(e=>e.type===`language`).map(e=>e.id):void 0}}).then(e=>({value:e}),e=>({error:e}));try{let r=readProviderTeamSync(t),o=await measureLoginStage(`authentication`,async()=>a?await withLoginProgress(n,`Checking model access…`,()=>reuseModelConnection(i,r,s)):await authenticateModelConnection({selected:i,team:r,prompter:n,signal:s}));if(!o)return;let l=await withLoginProgress(n,`Loading available models…`,()=>c);if(`error`in l)throw l.error;return await applyConnection({...e,automatic:a,signal:s},o,l.value.model,l.value.models)}finally{o.abort()}};try{if(e.automatic){let{model:e,selected:a}=await withLoginProgress(n,`Reading saved connection…`,async()=>{let[e,n,r,i]=await Promise.all([getModel(),readProviderSelection(t),resolveAvailableProviders(t),readDefaultConnection()]),a=e.selection===void 0?void 0:parseModelHelper(e.selection)?.helper;return{model:e,selected:n??a??environmentConnection(process.env)??(r.includes(`ai-gateway-project`)?`ai-gateway-project`:void 0)??i??`vercel-cli`}});if(e.external&&e.selection===void 0)return{kind:`ready`,reload:!1};try{let e=await connect(a,!0);if(e)return e}catch(e){i=void 0,r?.throwIfAborted(),n.log.warning(e instanceof Error?e.message:`Could not connect automatically. Retry /login.`)}}let a=e.selected;for(;;){let t=a??await n.select({message:e.connectionMessage??`Choose a connection`,search:!0,options:[...CONNECTION_OPTIONS]});if(a=void 0,!isModelConnection(t))throw Error(`Choose a model connection.`);try{let e=await connect(t,!1);if(e)return e}catch(e){if(i=void 0,e instanceof WizardCancelledError)return{kind:`cancelled`};r?.throwIfAborted(),n.log.warning(e instanceof Error?e.message:`Connection failed. Retry /login.`)}}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}export{environmentConnection,runModelLogin};
@@ -24,8 +24,6 @@ export type ApplyModelOutcome = {
24
24
  kind: "rejected";
25
25
  message: string;
26
26
  };
27
- /** The one-line transcript form of an apply outcome (`/model <slug>`'s reply). */
28
- export declare function formatApplyModelOutcome(outcome: ApplyModelOutcome): string;
29
27
  /** Applies one completed `/model` draft through a single atomic source write. */
30
28
  export declare function changeAgentModelSettings(input: {
31
29
  readonly appRoot: string;
@@ -1 +1 @@
1
- import{readFile}from"node:fs/promises";import{join}from"node:path";import{resolveDiscoveryProject}from"#discover/project.js";import pc from"#compiled/picocolors/index.js";import{discoverAgent}from"#discover/discover-agent.js";import{parseModelHelper}from"#shared/model-helper.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{CHATGPT_MODEL_SELECTION_PREFIX}from"#shared/chatgpt-model.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{readModelSelectionFromSource}from"#source-change/apply-model-selection.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";function formatApplyModelSettingsOutcome(e){return e.kind===`rejected`?e.message:e.kind===`unchanged`?`Model settings are already up to date.`:e.changed.length===1&&e.changed[0]===`model`&&e.model!==void 0?`Model changed to ${pc.bold(e.model)}. Live on your next prompt.`:`Model settings updated: ${e.changed.map(t=>t===`model`?`model ${e.model??`updated`}`:t===`reasoning`?`reasoning ${e.reasoning??`provider default`}`:`Fast mode ${e.fastMode?`on`:`off`}`).join(`, `)}. Live on your next prompt.`}function formatApplyModelOutcome(e){switch(e.kind){case`changed`:return`Model changed to ${pc.bold(e.to)}. Live on your next prompt.`;case`unchanged`:return`Model is already \`${e.model}\`.`;case`rejected`:return e.message}}async function changeAgentModelSettings(e){let{appRoot:t,patch:n}=e;if(n.model.kind===`set`){let e=await validateModelSlug(t,n.model.value);if(e!==null)return{kind:`rejected`,message:e}}let r=await resolveDiscoveryProject(t),{manifest:i}=await discoverAgent(r),a=await createStaticSourceChange(i).updateModelSettings(n);if(a.kind===`bail`)return{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change the model settings by hand.`};if(a.changed.length===0)return{kind:`unchanged`};let o={kind:`changed`,changed:a.changed};return n.model.kind===`set`&&(o.model=n.model.value),n.reasoning.kind!==`keep`&&(o.reasoning=n.reasoning.kind===`set`?n.reasoning.value:null),n.gatewayServiceTier.kind!==`keep`&&(o.fastMode=n.gatewayServiceTier.kind===`set`),o}async function changeAgentModel(e){let{appRoot:t,slug:n}=e,r=await validateModelSlug(t,n);return r===null?changeValidatedAgentModel(e):{kind:`rejected`,message:r}}async function changeValidatedAgentModel(e){let{appRoot:t,slug:n}=e,r=await resolveDiscoveryProject(t),{manifest:i}=await discoverAgent(r),a=await createStaticSourceChange(i).updateModelName(n);return a.kind===`bail`?{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change \`model\` by hand.`}:a.from===a.to?{kind:`unchanged`,model:a.to}:{kind:`changed`,to:a.to}}async function validateModelSlug(e,t){if(parseModelHelper(t)!==void 0)return null;if(t.startsWith(CHATGPT_MODEL_SELECTION_PREFIX))return"Choose a bare OpenAI model id after `chatgpt/`.";if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-5).`;let n=createCompiledRuntimeModelCatalogLoader(e);try{if(await n.getModelLimits(formatLanguageModelGatewayId(t))===null)return`I couldn't confirm \`${t}\` in the AI Gateway model catalog, so I didn't change agent.ts.`}catch{return null}return null}async function readAuthoredModelSelection(e){let t=await resolveDiscoveryProject(e),{manifest:n}=await discoverAgent(t);if(!n.configModule)return;let r=await readFile(join(t.agentRoot,n.configModule.logicalPath),`utf8`);return readModelSelectionFromSource(r)}export{changeAgentModel,changeAgentModelSettings,changeValidatedAgentModel,formatApplyModelOutcome,formatApplyModelSettingsOutcome,readAuthoredModelSelection,validateModelSlug};
1
+ import{readFile}from"node:fs/promises";import{join}from"node:path";import{resolveDiscoveryProject}from"#discover/project.js";import pc from"#compiled/picocolors/index.js";import{discoverAgent}from"#discover/discover-agent.js";import{parseModelHelper}from"#shared/model-helper.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{CHATGPT_MODEL_SELECTION_PREFIX}from"#shared/chatgpt-model.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{readModelSelectionFromSource}from"#source-change/apply-model-selection.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";function formatApplyModelSettingsOutcome(e){return e.kind===`rejected`?e.message:e.kind===`unchanged`?`Model settings are already up to date.`:e.changed.length===1&&e.changed[0]===`model`&&e.model!==void 0?`Model changed to ${pc.bold(e.model)}. Live on your next prompt.`:`Model settings updated: ${e.changed.map(t=>t===`model`?`model ${e.model??`updated`}`:t===`reasoning`?`reasoning ${e.reasoning??`provider default`}`:`Fast mode ${e.fastMode?`on`:`off`}`).join(`, `)}. Live on your next prompt.`}async function changeAgentModelSettings(e){let{appRoot:t,patch:n}=e;if(n.model.kind===`set`){let e=await validateModelSlug(t,n.model.value);if(e!==null)return{kind:`rejected`,message:e}}let r=await resolveDiscoveryProject(t),{manifest:i}=await discoverAgent(r),a=await createStaticSourceChange(i).updateModelSettings(n);if(a.kind===`bail`)return{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change the model settings by hand.`};if(a.changed.length===0)return{kind:`unchanged`};let o={kind:`changed`,changed:a.changed};return n.model.kind===`set`&&(o.model=n.model.value),n.reasoning.kind!==`keep`&&(o.reasoning=n.reasoning.kind===`set`?n.reasoning.value:null),n.gatewayServiceTier.kind!==`keep`&&(o.fastMode=n.gatewayServiceTier.kind===`set`),o}async function changeAgentModel(e){let{appRoot:t,slug:n}=e,r=await validateModelSlug(t,n);return r===null?changeValidatedAgentModel(e):{kind:`rejected`,message:r}}async function changeValidatedAgentModel(e){let{appRoot:t,slug:n}=e,r=await resolveDiscoveryProject(t),{manifest:i}=await discoverAgent(r),a=await createStaticSourceChange(i).updateModelName(n);return a.kind===`bail`?{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change \`model\` by hand.`}:a.from===a.to?{kind:`unchanged`,model:a.to}:{kind:`changed`,to:a.to}}async function validateModelSlug(e,t){if(parseModelHelper(t)!==void 0)return null;if(t.startsWith(CHATGPT_MODEL_SELECTION_PREFIX))return"Choose a bare OpenAI model id after `chatgpt/`.";if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-5).`;let n=createCompiledRuntimeModelCatalogLoader(e);try{if(await n.getModelLimits(formatLanguageModelGatewayId(t))===null)return`I couldn't confirm \`${t}\` in the AI Gateway model catalog, so I didn't change agent.ts.`}catch{return null}return null}async function readAuthoredModelSelection(e){let t=await resolveDiscoveryProject(e),{manifest:n}=await discoverAgent(t);if(!n.configModule)return;let r=await readFile(join(t.agentRoot,n.configModule.logicalPath),`utf8`);return readModelSelectionFromSource(r)}export{changeAgentModel,changeAgentModelSettings,changeValidatedAgentModel,formatApplyModelSettingsOutcome,readAuthoredModelSelection,validateModelSlug};
@@ -6,37 +6,39 @@ export interface RegistrySessionDeps {
6
6
  detectDeployment: typeof detectDeployment;
7
7
  runDeployFlow: typeof runDeployFlow;
8
8
  }
9
- export interface RegistrySessionItemResult {
9
+ export type RegistrySessionOutcome = {
10
+ kind: "installed";
10
11
  title: string;
11
12
  facts: readonly RegistrySetupFact[];
12
13
  output: readonly string[];
13
14
  }
14
- /** An item the user chose to skip after its installation could not complete. */
15
- export interface RegistrySessionItemFailure {
15
+ /** Files were added, but the item's setup was cancelled or skipped. */
16
+ | {
17
+ kind: "incomplete";
16
18
  title: string;
17
- /** User-facing installation error, including any actionable follow-up lines. */
18
- message: string;
19
+ resumeCommand: string;
19
20
  }
20
- export type RegistrySessionOutcome = ({
21
- kind: "installed";
22
- } & RegistrySessionItemResult) | ({
21
+ /** User-facing installation error, including any actionable follow-up lines. */
22
+ | {
23
23
  kind: "failed";
24
- } & RegistrySessionItemFailure) | {
24
+ title: string;
25
+ message: string;
26
+ }
27
+ /** Stopped before anything was written. */
28
+ | {
25
29
  kind: "cancelled";
26
30
  title: string;
27
31
  };
28
32
  export interface RegistrySessionResult {
29
- items: readonly RegistrySessionItemResult[];
30
- /** Installation failures retained when a user skips an item. */
31
- failures: readonly RegistrySessionItemFailure[];
32
33
  /** Every item outcome in installation order. */
33
- outcomes?: readonly RegistrySessionOutcome[];
34
+ outcomes: readonly RegistrySessionOutcome[];
34
35
  /** Setup stopped outside an individual item after preserving settled results. */
35
36
  cancelled?: true;
36
37
  deployed?: "production";
37
38
  }
38
39
  export interface RegistrySession {
39
40
  add(title: string, output: readonly string[], setup?: RegistrySetupCompletion): void;
41
+ addIncomplete(title: string, resumeCommand: string): void;
40
42
  addFailure(title: string, message: string): void;
41
43
  addCancellation(title: string): void;
42
44
  result(deployed?: "production"): RegistrySessionResult;
@@ -1 +1 @@
1
- import"./deploy.js";import"#setup/project-resolution.js";function createRegistrySession(e){let t=[],n=!1;function result(e){let n={items:t.flatMap(e=>e.kind===`installed`?[{title:e.title,facts:e.facts,output:e.output}]:[]),failures:t.flatMap(e=>e.kind===`failed`?[{title:e.title,message:e.message}]:[])};return t.some(e=>e.kind!==`installed`)&&(n.outcomes=t),e!==void 0&&(n.deployed=e),n}return{add(e,r,i={facts:[]}){t.push({kind:`installed`,title:e,facts:i.facts,output:r}),n||=i.deploymentRequired===!0},addFailure(e,n){t.push({kind:`failed`,title:e,message:n})},addCancellation(e){t.push({kind:`cancelled`,title:e})},result,async continueAfterInstall(t){if(!n)return result();let r=await e.detectDeployment(t.appRoot,{signal:t.signal}),i=r.state===`linked`||r.state===`deployed`;for(t.prompter.replaceContent?.();;){if(await t.prompter.select({message:`What would you like to do next?`,initialValue:`finish`,hintLayout:`inline`,options:[...i?[{value:`deploy`,label:`Deploy`}]:[],{value:`finish`,label:`Start chatting`}]})===`finish`)return result();if(await t.prompter.select({message:`Deploy to prod?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`back`,label:`Back`}]})!==`back`)return result((await e.runDeployFlow({appRoot:t.appRoot,prompter:t.prompter,signal:t.signal,interactive:!0})).kind===`deployed`?`production`:void 0)}}}}export{createRegistrySession};
1
+ import"./deploy.js";import"#setup/project-resolution.js";function createRegistrySession(e){let t=[],n=!1;function result(e){let n={outcomes:[...t]};return e!==void 0&&(n.deployed=e),n}return{add(e,r,i={facts:[]}){t.push({kind:`installed`,title:e,facts:i.facts,output:r}),n||=i.deploymentRequired===!0},addIncomplete(e,n){t.push({kind:`incomplete`,title:e,resumeCommand:n})},addFailure(e,n){t.push({kind:`failed`,title:e,message:n})},addCancellation(e){t.push({kind:`cancelled`,title:e})},result,async continueAfterInstall(t){if(!n)return result();let r=await e.detectDeployment(t.appRoot,{signal:t.signal}),i=r.state===`linked`||r.state===`deployed`;for(t.prompter.replaceContent?.();;){if(await t.prompter.select({message:`What would you like to do next?`,initialValue:`finish`,hintLayout:`inline`,options:[...i?[{value:`deploy`,label:`Deploy`}]:[],{value:`finish`,label:`Start chatting`}]})===`finish`)return result();if(await t.prompter.select({message:`Deploy to prod?`,initialValue:`yes`,options:[{value:`yes`,label:`Yes`},{value:`back`,label:`Back`}]})!==`back`)return result((await e.runDeployFlow({appRoot:t.appRoot,prompter:t.prompter,signal:t.signal,interactive:!0})).kind===`deployed`?`production`:void 0)}}}}export{createRegistrySession};
@@ -1 +1 @@
1
- import{createRegistrySession}from"./registry-session.js";import{WizardCancelledError}from"#setup/step.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{withSpinner}from"#setup/with-spinner.js";function label(e){return e.name}var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};function hasSettledOutcomes(e){return e!==void 0&&(e.items.length>0||e.failures.length>0||e.outcomes!==void 0)}async function runRegistryFlow(e){let t;try{let n=e.initialAddress?.trim(),r;if(n!==void 0&&n!==``)r=[{address:n,name:n,source:`Registry`}];else{let t=e.deps?.browseRegistryCatalog??(await import(`#cli/commands/registry.js`)).browseRegistryCatalog,n=await withSpinner(e.prompter,`Loading registry…`,()=>t(e.appRoot)),i=[...n.items],a=await e.prompter.select({message:`Add to your agent`,search:!0,options:i.map(e=>({value:e.address,label:e.name,hint:e.address,keywords:[e.title??``,e.description??``]})),notices:n.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`}))}),o=i.find(e=>e.address===a);if(o===void 0)throw Error(`That registry item is no longer available. Run /add to try again.`);r=[o]}let i=e.deps?.installRegistryItem??(await import(`#cli/commands/registry.js`)).installRegistryItem,a=e.installRoot??e.appRoot,o=e.deps?.detectDeployment??(await import(`#setup/project-resolution.js`)).detectDeployment,s=e.deps?.runDeployFlow??(await import(`./deploy.js`)).runDeployFlow;t=createRegistrySession({detectDeployment:o,runDeployFlow:s}),e.onScreen?.({screen:`registry_install`});let c=t;for(let[t,n]of r.entries()){e.signal?.throwIfAborted(),e.onItemStart?.(n,t,r.length);try{let install=(t=e.signal)=>i(a,n.address,{silent:!0,prompter:e.prompter,signal:t}),run=()=>e.runItem===void 0?install():e.runItem(install),t=await(e.prompter.withExclusiveTerminal?.(run)??run());c.add(label(n),t.output,t.setup)}catch(t){if(e.signal?.throwIfAborted(),t instanceof WizardCancelledError){c.addCancellation(label(n));continue}if(t instanceof HumanActionRequiredError)throw t;let r=(t instanceof Error?t.message:String(t)).trim()||`Installation failed.`;c.addFailure(label(n),r)}}return{kind:`done`,result:await c.continueAfterInstall({appRoot:e.appRoot,prompter:e.prompter,signal:e.signal})}}catch(e){if(e instanceof WizardCancelledError){let e=t?.result();return hasSettledOutcomes(e)?{kind:`done`,result:{...e,cancelled:!0}}:{kind:`cancelled`}}let n=t?.result();throw hasSettledOutcomes(n)?new RegistryFlowFailedError(e,n):e}}export{RegistryFlowFailedError,runRegistryFlow};
1
+ import{createRegistrySession}from"./registry-session.js";import{WizardCancelledError}from"#setup/step.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{withSpinner}from"#setup/with-spinner.js";function label(e){return e.name}var RegistryFlowFailedError=class extends Error{completed;constructor(e,t){super(e instanceof Error?e.message:String(e),{cause:e}),this.name=`RegistryFlowFailedError`,this.completed=t}};function hasSettledOutcomes(e){return e!==void 0&&e.outcomes.length>0}async function runRegistryFlow(e){let t;try{let n=e.initialAddress?.trim(),r;if(n!==void 0&&n!==``)r=[{address:n,name:n,source:`Registry`}];else{let t=e.deps?.browseRegistryCatalog??(await import(`#cli/commands/registry.js`)).browseRegistryCatalog,n=await withSpinner(e.prompter,`Loading registry…`,()=>t(e.appRoot)),i=[...n.items],a=await e.prompter.select({message:`Add to your agent`,search:!0,options:i.map(e=>({value:e.address,label:e.name,hint:e.address,keywords:[e.title??``,e.description??``]})),notices:n.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`}))}),o=i.find(e=>e.address===a);if(o===void 0)throw Error(`That registry item is no longer available. Run /add to try again.`);r=[o]}let i=e.deps?.installRegistryItem??(await import(`#cli/commands/registry.js`)).installRegistryItem,a=e.installRoot??e.appRoot,o=e.deps?.detectDeployment??(await import(`#setup/project-resolution.js`)).detectDeployment,s=e.deps?.runDeployFlow??(await import(`./deploy.js`)).runDeployFlow;t=createRegistrySession({detectDeployment:o,runDeployFlow:s}),e.onScreen?.({screen:`registry_install`});let c=t;for(let[t,n]of r.entries()){e.signal?.throwIfAborted(),e.onItemStart?.(n,t,r.length);try{let install=(t=e.signal)=>i(a,n.address,{silent:!0,prompter:e.prompter,signal:t}),run=()=>e.runItem===void 0?install():e.runItem(install),t=await(e.prompter.withExclusiveTerminal?.(run)??run());t.setupIncomplete===void 0?c.add(label(n),t.output,t.setup):c.addIncomplete(label(n),t.setupIncomplete.resumeCommand)}catch(t){if(e.signal?.throwIfAborted(),t instanceof WizardCancelledError){c.addCancellation(label(n));continue}if(t instanceof HumanActionRequiredError)throw t;let r=(t instanceof Error?t.message:String(t)).trim()||`Installation failed.`;c.addFailure(label(n),r)}}return{kind:`done`,result:await c.continueAfterInstall({appRoot:e.appRoot,prompter:e.prompter,signal:e.signal})}}catch(e){if(e instanceof WizardCancelledError){let e=t?.result();return hasSettledOutcomes(e)?{kind:`done`,result:{...e,cancelled:!0}}:{kind:`cancelled`}}let n=t?.result();throw hasSettledOutcomes(n)?new RegistryFlowFailedError(e,n):e}}export{RegistryFlowFailedError,runRegistryFlow};
@@ -1 +1 @@
1
- import{withLoginProgress}from"./model-login-progress.js";import{isObject}from"#shared/guards.js";import{rememberModelTeamSlug}from"#internal/model-auth/vercel-team.js";import{setTimeout}from"node:timers/promises";import{openUrl}from"#setup/primitives/open-url.js";import{writeVercelSession}from"#internal/model-auth/store.js";import{readVercelCliTeam}from"#internal/model-auth/vercel-cli.js";import{VERCEL_MODEL_CLIENT_ID,VERCEL_OAUTH_ISSUER,authJson,sessionFromToken,validateVercelAccess,vercelApiJson,vercelOAuthEndpoints}from"#internal/model-auth/vercel.js";async function loginVercelModel(e,t,n){let{endpoints:r,device:i}=await withLoginProgress(e,`Opening Vercel sign-in…`,async()=>{let e=await vercelOAuthEndpoints(t);return{endpoints:e,device:await authJson(e.device,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,scope:`openid offline_access`}),signal:t})}});if(typeof i.device_code!=`string`||typeof i.verification_uri!=`string`||typeof i.user_code!=`string`)throw Error(`Could not start Vercel sign-in. Retry /login.`);let a=typeof i.verification_uri_complete==`string`?i.verification_uri_complete:i.verification_uri;if(URL.parse(a)?.origin!==VERCEL_OAUTH_ISSUER)throw Error(`Vercel returned an unexpected sign-in URL. Retry /login.`);e.log.info(`Open ${a} · code ${i.user_code}`),openUrl(a);let o=typeof i.interval==`number`?Math.max(1,Math.min(30,i.interval)):5,s=typeof i.expires_in==`number`?Math.min(600,i.expires_in):300,c=Date.now()+s*1e3,l=e.log.spinner?.(`Finish signing in to Vercel in your browser`,{kind:`external-action`,emphasis:`your browser`}),u;try{for(;Date.now()<c;){await setTimeout(o*1e3,void 0,{signal:t});let e=await authJson(r.token,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,grant_type:`urn:ietf:params:oauth:grant-type:device_code`,device_code:i.device_code}),signal:t});if(e.error!==`authorization_pending`){if(e.error===`slow_down`){o=Math.min(30,o+5);continue}if(e.error)throw Error(`Vercel sign-in was declined or expired. Retry /login.`);u=sessionFromToken(e);break}}}finally{l?.stop()}if(!u)throw Error(`Vercel sign-in timed out. Retry /login.`);let[d,f]=await withLoginProgress(e,`Loading Vercel teams…`,()=>Promise.all([loadTeams(u.accessToken,t),readVercelCliTeam()])),p=d.find(e=>e.id===n)??d.find(e=>e.id===f),m=d.length===1?d[0]:void 0;for(;;){if(!m){let t=await e.select({message:`Choose a Vercel team`,search:!0,initialValue:p?.id,options:d.map(e=>({value:e.id,label:e.name}))});m=d.find(e=>e.id===t)}if(!m)throw Error(`That Vercel team is no longer available. Retry /login.`);let n=m;try{await withLoginProgress(e,`Checking AI Gateway access for ${m.slug??m.name}…`,()=>validateVercelAccess(u.accessToken,n.id,t));break}catch(n){if(t?.throwIfAborted(),d.length===1)throw n;e.log.warning(`AI Gateway is unavailable for that team. Choose another team or press Esc to return.`),m=void 0}}return u.teamId=m.id,u.teamName=m.name,t?.throwIfAborted(),await writeVercelSession(u,VERCEL_MODEL_CLIENT_ID),m.slug&&rememberModelTeamSlug(m.id,m.slug),{teamId:m.id,teamName:m.name}}async function loadTeams(e,t){let n=[],r;for(let i=0;i<20;i++){let i=await vercelApiJson(`https://api.vercel.com/v2/teams?limit=100${r===void 0?``:`&until=${r}`}`,{headers:{authorization:`Bearer ${e}`},signal:t});if(!Array.isArray(i.teams))throw Error(`Could not list Vercel teams. Retry /login.`);for(let e of i.teams)isObject(e)&&typeof e.id==`string`&&typeof e.name==`string`&&n.push({id:e.id,name:e.name,slug:typeof e.slug==`string`?e.slug:void 0});if(r=isObject(i.pagination)&&typeof i.pagination.next==`number`?i.pagination.next:void 0,r===void 0)break}if(n.length===0)throw Error(`No Vercel team is available. Join a team or choose another connection in /login.`);return n}export{loginVercelModel};
1
+ import{withLoginProgress}from"./model-login-progress.js";import{isObject}from"#shared/guards.js";import{rememberModelTeamSlug}from"#internal/model-auth/vercel-team.js";import{setTimeout}from"node:timers/promises";import{readVercelCliTeam}from"#internal/model-auth/vercel-cli.js";import{openUrl}from"#setup/primitives/open-url.js";import{writeVercelSession}from"#internal/model-auth/store.js";import{VERCEL_MODEL_CLIENT_ID,VERCEL_OAUTH_ISSUER,authJson,sessionFromToken,validateVercelAccess,vercelApiJson,vercelOAuthEndpoints}from"#internal/model-auth/vercel.js";async function loginVercelModel(e,t,n){let{endpoints:r,device:i}=await withLoginProgress(e,`Opening Vercel sign-in…`,async()=>{let e=await vercelOAuthEndpoints(t);return{endpoints:e,device:await authJson(e.device,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,scope:`openid offline_access`}),signal:t})}});if(typeof i.device_code!=`string`||typeof i.verification_uri!=`string`||typeof i.user_code!=`string`)throw Error(`Could not start Vercel sign-in. Retry /login.`);let a=typeof i.verification_uri_complete==`string`?i.verification_uri_complete:i.verification_uri;if(URL.parse(a)?.origin!==VERCEL_OAUTH_ISSUER)throw Error(`Vercel returned an unexpected sign-in URL. Retry /login.`);e.log.info(`Open ${a} · code ${i.user_code}`),openUrl(a);let o=typeof i.interval==`number`?Math.max(1,Math.min(30,i.interval)):5,s=typeof i.expires_in==`number`?Math.min(600,i.expires_in):300,c=Date.now()+s*1e3,l=e.log.spinner?.(`Finish signing in to Vercel in your browser`),u;try{for(;Date.now()<c;){await setTimeout(o*1e3,void 0,{signal:t});let e=await authJson(r.token,{method:`POST`,body:new URLSearchParams({client_id:VERCEL_MODEL_CLIENT_ID,grant_type:`urn:ietf:params:oauth:grant-type:device_code`,device_code:i.device_code}),signal:t});if(e.error!==`authorization_pending`){if(e.error===`slow_down`){o=Math.min(30,o+5);continue}if(e.error)throw Error(`Vercel sign-in was declined or expired. Retry /login.`);u=sessionFromToken(e);break}}}finally{l?.stop()}if(!u)throw Error(`Vercel sign-in timed out. Retry /login.`);let[d,f]=await withLoginProgress(e,`Loading Vercel teams…`,()=>Promise.all([loadTeams(u.accessToken,t),readVercelCliTeam()])),p=d.find(e=>e.id===n)??d.find(e=>e.id===f),m=d.length===1?d[0]:void 0;for(;;){if(!m){let t=await e.select({message:`Choose a Vercel team`,search:!0,initialValue:p?.id,options:d.map(e=>({value:e.id,label:e.name}))});m=d.find(e=>e.id===t)}if(!m)throw Error(`That Vercel team is no longer available. Retry /login.`);let n=m;try{await withLoginProgress(e,`Checking AI Gateway access for ${m.slug??m.name}…`,()=>validateVercelAccess(u.accessToken,n.id,t));break}catch(n){if(t?.throwIfAborted(),d.length===1)throw n;e.log.warning(`AI Gateway is unavailable for that team. Choose another team or press Esc to return.`),m=void 0}}return u.teamId=m.id,u.teamName=m.name,t?.throwIfAborted(),await writeVercelSession(u,VERCEL_MODEL_CLIENT_ID),m.slug&&rememberModelTeamSlug(m.id,m.slug),{teamId:m.id,teamName:m.name}}async function loadTeams(e,t){let n=[],r;for(let i=0;i<20;i++){let i=await vercelApiJson(`https://api.vercel.com/v2/teams?limit=100${r===void 0?``:`&until=${r}`}`,{headers:{authorization:`Bearer ${e}`},signal:t});if(!Array.isArray(i.teams))throw Error(`Could not list Vercel teams. Retry /login.`);for(let e of i.teams)isObject(e)&&typeof e.id==`string`&&typeof e.name==`string`&&n.push({id:e.id,name:e.name,slug:typeof e.slug==`string`?e.slug:void 0});if(r=isObject(i.pagination)&&typeof i.pagination.next==`number`?i.pagination.next:void 0,r===void 0)break}if(n.length===0)throw Error(`No Vercel team is available. Join a team or choose another connection in /login.`);return n}export{loginVercelModel};
@@ -4,7 +4,7 @@ import { photonIMessageChannel } from "eve/channels/photon";
4
4
  export default photonIMessageChannel({
5
5
  credentials: connectPhotonCredentials(${JSON.stringify(e)}),
6
6
  });
7
- `}async function preparePhotonSetup(e,t=defaultDeps){let n=basename(e.appRoot),r=await e.asker.ask(select({key:`photon-credentials`,message:`How would you like to configure Photon?`,options:[{id:`vercel`,value:`vercel-connect`,label:`Set up Vercel Connect`,hint:`Use a linked Vercel project`},{id:`portable`,value:`environment`,label:`Use portable credentials`,hint:`Configure the Photon webhook manually after deployment`}],recommended:e.environment.vercel.kind===`available`?`vercel-connect`:`environment`,required:!0})),i=`eve · ${n||`agent`}`,a=await e.asker.askEditable({key:`photon-project-source`,message:`Photon project`,options:[{id:`create`,value:`create`,label:`Create a new Photon project`,hint:`Name: ${i}`},{id:`existing`,value:`existing`,label:`Use an existing Photon project`,hint:`Enter its project credentials`}],recommended:`create`,required:!0,editable:{key:`photon-project-name`,value:`create`,label:`Name`,recommended:i,validate:e=>e.trim().length===0?`Project name cannot be empty.`:null}}),o=`create`;if(a.value===`existing`){let t=await e.asker.ask(text({key:`photon-project-id`,message:`Photon project ID`,required:!0})),n=await e.asker.ask(text({key:`photon-project-secret`,message:`Photon project secret`,required:!0,sensitive:!0,environment:`IMESSAGE_PROJECT_SECRET`}));o={projectId:t.trim(),projectSecret:n.trim()}}let s=o===`create`?void 0:await t.findDedicatedLine(o),c=s===void 0?await e.asker.ask(text({key:`photon-phone-number`,message:`Your iMessage phone number`,placeholder:`+15551234567`,required:!0,validate:validatePhotonPhoneNumber})):void 0,l=r===`vercel-connect`?await e.resolveVercelProject(`Photon`):void 0,u={agentName:n,credentials:r,photonProject:o,dedicatedLine:s,phoneNumber:c};return a.value===`create`&&(u.photonProjectName=a.text??i),l!==void 0&&(u.vercelProject=l),u}async function resolvePhotonProject(e,t,n){if(e.photonProject!==`create`)return n.useProject({...e.photonProject,dedicatedLine:e.dedicatedLine,phoneNumber:e.phoneNumber});if(e.phoneNumber===void 0)throw Error(`Photon phone number is required.`);let r=t.presenter.log.spinner?.(`Waiting for Photon approval…`,{kind:`external-action`,emphasis:`browser`}),i;try{let r=await n.provisionProject({projectName:e.photonProjectName??`eve · ${e.agentName||`agent`}`,phoneNumber:e.phoneNumber,signal:t.signal,onAuthorization(e){i=t.presenter.beginExternalAction({message:`Authorize Photon`,url:e.verificationUrl,userCode:e.userCode}),n.openUrl(e.verificationUrl)}});return i?.complete(),r}finally{r?.stop()}}async function applyPhotonSetup(e,t,n=defaultDeps){let r=await resolvePhotonProject(e,t,n);try{let i=join(t.appRoot,`agent/channels/photon.ts`);if(e.credentials===`vercel-connect`){let a=await n.deriveConnectorSlug(t.appRoot,e.agentName),o=await n.provisionConnector({credentials:r,log:t.presenter.log,project:e.vercelProject,projectRoot:t.projectRoot,slug:a,signal:t.signal});await n.writeTextFile(i,connectTemplate(o.uid),{force:t.force})}else await n.appendEnv(join(t.projectRoot,`.env.local`),{IMESSAGE_PROJECT_ID:r.projectId,IMESSAGE_PROJECT_SECRET:r.projectSecret}),await n.writeTextFile(i,`import { photonIMessageChannel } from "eve/channels/photon";
7
+ `}async function preparePhotonSetup(e,t=defaultDeps){let n=basename(e.appRoot),r=await e.asker.ask(select({key:`photon-credentials`,message:`How would you like to configure Photon?`,options:[{id:`vercel`,value:`vercel-connect`,label:`Set up Vercel Connect`,hint:`Use a linked Vercel project`},{id:`portable`,value:`environment`,label:`Use portable credentials`,hint:`Configure the Photon webhook manually after deployment`}],recommended:e.environment.vercel.kind===`available`?`vercel-connect`:`environment`,required:!0})),i=`eve · ${n||`agent`}`,a=await e.asker.askEditable({key:`photon-project-source`,message:`Photon project`,options:[{id:`create`,value:`create`,label:`Create a new Photon project`,hint:`Name: ${i}`},{id:`existing`,value:`existing`,label:`Use an existing Photon project`,hint:`Enter its project credentials`}],recommended:`create`,required:!0,editable:{key:`photon-project-name`,value:`create`,label:`Name`,recommended:i,validate:e=>e.trim().length===0?`Project name cannot be empty.`:null}}),o=`create`;if(a.value===`existing`){let t=await e.asker.ask(text({key:`photon-project-id`,message:`Photon project ID`,required:!0})),n=await e.asker.ask(text({key:`photon-project-secret`,message:`Photon project secret`,required:!0,sensitive:!0,environment:`IMESSAGE_PROJECT_SECRET`}));o={projectId:t.trim(),projectSecret:n.trim()}}let s=o===`create`?void 0:await t.findDedicatedLine(o),c=s===void 0?await e.asker.ask(text({key:`photon-phone-number`,message:`Your iMessage phone number`,placeholder:`+15551234567`,required:!0,validate:validatePhotonPhoneNumber})):void 0,l=r===`vercel-connect`?await e.resolveVercelProject(`Photon`):void 0,u={agentName:n,credentials:r,photonProject:o,dedicatedLine:s,phoneNumber:c};return a.value===`create`&&(u.photonProjectName=a.text??i),l!==void 0&&(u.vercelProject=l),u}async function resolvePhotonProject(e,t,n){if(e.photonProject!==`create`)return n.useProject({...e.photonProject,dedicatedLine:e.dedicatedLine,phoneNumber:e.phoneNumber});if(e.phoneNumber===void 0)throw Error(`Photon phone number is required.`);let r=t.presenter.log.spinner?.(`Waiting for Photon approval…`),i;try{let r=await n.provisionProject({projectName:e.photonProjectName??`eve · ${e.agentName||`agent`}`,phoneNumber:e.phoneNumber,signal:t.signal,onAuthorization(e){i=t.presenter.beginExternalAction({message:`Authorize Photon`,url:e.verificationUrl,userCode:e.userCode}),n.openUrl(e.verificationUrl)}});return i?.complete(),r}finally{r?.stop()}}async function applyPhotonSetup(e,t,n=defaultDeps){let r=await resolvePhotonProject(e,t,n);try{let i=join(t.appRoot,`agent/channels/photon.ts`);if(e.credentials===`vercel-connect`){let a=await n.deriveConnectorSlug(t.appRoot,e.agentName),o=await n.provisionConnector({credentials:r,log:t.presenter.log,project:e.vercelProject,projectRoot:t.projectRoot,slug:a,signal:t.signal});await n.writeTextFile(i,connectTemplate(o.uid),{force:t.force})}else await n.appendEnv(join(t.projectRoot,`.env.local`),{IMESSAGE_PROJECT_ID:r.projectId,IMESSAGE_PROJECT_SECRET:r.projectSecret}),await n.writeTextFile(i,`import { photonIMessageChannel } from "eve/channels/photon";
8
8
 
9
9
  async function photonCredentials() {
10
10
  const projectId = process.env.IMESSAGE_PROJECT_ID;
@@ -1 +1 @@
1
- import{describeIntegrationSetupEnvironment,integrationSetupEnvironment}from"./shared/environment.js";import{createSetupContexts}from"./shared/ui.js";import{setupIntegration}from"./registry.js";import{resolveIntegrationVercelProject}from"./shared/vercel-project.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{interactiveAsker}from"#setup/ask.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";const defaultDeps={detectDeployment,getVercelAuthStatus};async function runIntegrationSetup(e,t,n=defaultDeps){let r=setupIntegration(e),i=t.projectRoot??t.appRoot;t.prompter.intro(`Set up ${r.label}`,r.hint),t.prompter.log.message(`Checking Vercel setup...`);let[a,o]=await Promise.all([n.detectDeployment(i,{signal:t.signal}),n.getVercelAuthStatus(i,{signal:t.signal})]),s=projectResolutionFromDeployment(a),c=integrationSetupEnvironment(o,s);return t.prompter.log.info(r.describeEnvironment?.(c)??describeIntegrationSetupEnvironment(c)),r.run(createSetupContexts({appRoot:t.appRoot,projectRoot:i,asker:t.asker??interactiveAsker(t.prompter),environment:c,prompter:t.prompter,resolveVercelProject:t.resolveVercelProject??(e=>resolveIntegrationVercelProject({appRoot:i,integration:e,signal:t.signal})),signal:t.signal,force:t.force,beginExternalAction:t.beginExternalAction}))}export{runIntegrationSetup};
1
+ import{describeIntegrationSetupEnvironment,integrationSetupEnvironment}from"./shared/environment.js";import{createSetupContexts}from"./shared/ui.js";import{setupIntegration}from"./registry.js";import{resolveIntegrationVercelProject}from"./shared/vercel-project.js";import{detectDeployment,projectResolutionFromDeployment}from"#setup/project-resolution.js";import{getVercelAuthStatus}from"#setup/vercel-project.js";import{interactiveAsker}from"#setup/ask.js";const defaultDeps={detectDeployment,getVercelAuthStatus};async function runIntegrationSetup(e,t,n=defaultDeps){let r=setupIntegration(e),i=t.projectRoot??t.appRoot;t.prompter.intro(`Set up ${r.label}`,r.hint),t.prompter.log.message(`Checking Vercel setup...`);let[a,o]=await Promise.all([n.detectDeployment(i,{signal:t.signal}),n.getVercelAuthStatus(i,{signal:t.signal})]),s=projectResolutionFromDeployment(a),c=integrationSetupEnvironment(o,s);return t.prompter.log.info(r.describeEnvironment?.(c)??describeIntegrationSetupEnvironment(c)),r.run(createSetupContexts({appRoot:t.appRoot,projectRoot:i,asker:t.asker??interactiveAsker(t.prompter),environment:c,prompter:t.prompter,resolveVercelProject:t.resolveVercelProject??(e=>resolveIntegrationVercelProject({appRoot:i,integration:e,signal:t.signal})),signal:t.signal,force:t.force,beginExternalAction:t.beginExternalAction}))}export{runIntegrationSetup};
@@ -1,4 +1,4 @@
1
- import { type ChannelSetupAwaitChoice, type SetupSpinnerIntent } from "#setup/cli/index.js";
1
+ import { type ChannelSetupAwaitChoice } from "#setup/cli/index.js";
2
2
  import { type RailSpinner } from "#setup/cli/index.js";
3
3
  /**
4
4
  * Clack constrains option values to readonly primitives. Our scaffold flow
@@ -258,7 +258,7 @@ export interface Prompter {
258
258
  * returning a handle whose `stop()` clears it. Present on the real prompter;
259
259
  * optional so lightweight test fakes can omit it.
260
260
  */
261
- spinner?(message: string, intent?: SetupSpinnerIntent): RailSpinner;
261
+ spinner?(message: string): RailSpinner;
262
262
  };
263
263
  }
264
264
  /**
@@ -1,2 +1,2 @@
1
1
  import{InteractionRequired,InvalidAnswerError}from"./ask-signals.js";import{SetupPrerequisiteRequired}from"./integrations/shared/prerequisite.js";import"./ask.js";import{WizardCancelledError}from"./step.js";import{setupQuestionToWire}from"./setup-question-wire.js";import"./registry-setup-protocol.js";function send(e,t){if(e.send===void 0||!e.connected)throw Error(`The registry setup host disconnected.`);e.send(t)}function registrySetupBlocker(e){if(e instanceof InteractionRequired)return{status:`input_required`,question:setupQuestionToWire(e.question)};if(e instanceof InvalidAnswerError)return{status:`input_required`,question:setupQuestionToWire(e.question),issue:{code:`invalid_answer`,message:e.message}};if(e instanceof SetupPrerequisiteRequired)return{status:`prerequisite_required`,prerequisite:e.prerequisite}}function registrySetupError(e){if(!(e instanceof Error))return{message:String(e)};let t=e.stack?.split(`
2
- `).slice(1).map(e=>e.trim()).filter(Boolean);return t===void 0||t.length===0?{message:e.message}:{message:e.message,details:t}}function createRegistrySetupClient(e={}){let t=e.process??process;if(t.send===void 0||process.env.EVE_SETUP_PROTOCOL===void 0)return;let n=new AbortController;e.signal!==void 0&&e.signal.addEventListener(`abort`,()=>n.abort(e.signal?.reason),{once:!0});let r=1,i=new Map,onMessage=e=>{if(e.type===`cancel`){n.abort(new WizardCancelledError);for(let e of i.values())e({type:`cancel`});i.clear();return}i.get(e.id)?.(e)};t.on(`message`,onMessage),send(t,{type:`ready`,version:2});async function prompt(e){n.signal.throwIfAborted();let a=r++,o=await new Promise(n=>{i.set(a,n),send(t,{type:`prompt`,id:a,prompt:e})});if(i.delete(a),o.type===`cancel`||o.cancelled===!0)throw new WizardCancelledError;return o.value}async function validatedText(e,t){let n=t.notices;for(;;){let r=await prompt({kind:e,message:t.message,placeholder:t.placeholder,defaultValue:t.defaultValue,notices:n}),i=t.validate?.(r);if(i===void 0)return r;n=[{tone:`error`,text:i}]}}function select(e){return prompt({kind:`select`,options:e})}let a={text:e=>validatedText(`text`,e),password:e=>validatedText(`password`,e),select,async selectEditable(e){let t=await prompt({kind:`editable-select`,options:{...e,editable:{value:e.editable.value,defaultValue:e.editable.defaultValue}}});if(t.kind===`selected`)return{kind:`selected`,value:t.value};let n=e.editable.validate?.(t.text);if(n!==void 0)throw Error(n);return{kind:`edited`,value:t.value,text:t.text}},acknowledge:e=>prompt({kind:`acknowledge`,options:e}),awaitChoice(e){let n=r++;return{choice:new Promise((r,a)=>{i.set(n,e=>{i.delete(n),e.type===`cancel`||e.cancelled===!0?a(new WizardCancelledError):r(e.value)}),send(t,{type:`prompt`,id:n,prompt:{kind:`choice`,options:e}})}),close:()=>{i.delete(n),send(t,{type:`close-prompt`,id:n})}}},note(e,n,r){send(t,{type:`note`,message:e,title:n,tone:r?.tone})},intro(e,n){send(t,{type:`intro`,text:e,subtitle:n})},outro(e){send(t,{type:`outro`,text:e})},log:{message:e=>send(t,{type:`log`,level:`message`,text:e}),info:e=>send(t,{type:`log`,level:`info`,text:e}),success:e=>send(t,{type:`log`,level:`success`,text:e}),warning:e=>send(t,{type:`log`,level:`warning`,text:e}),error:e=>send(t,{type:`log`,level:`error`,text:e}),commandOutput:e=>send(t,{type:`log`,level:`commandOutput`,text:e}),spinner(e,n){let i=r++;return send(t,{type:`status`,id:i,status:e,intent:n?.kind===`external-action`?n:void 0}),{stop:()=>send(t,{type:`status`,id:i})}}}},o=!1,finish=e=>{o||(o=!0,send(t,{type:`result`,outcome:e}),t.off(`message`,onMessage),t.disconnect?.())};return{prompter:a,signal:n.signal,complete:(e={facts:[]})=>finish({kind:`completed`,...e}),cancel:()=>finish({kind:`cancelled`}),fail(e){let t=registrySetupBlocker(e);finish(t===void 0?{kind:`failed`,error:registrySetupError(e)}:{kind:`blocked`,blocker:t})}}}export{createRegistrySetupClient};
2
+ `).slice(1).map(e=>e.trim()).filter(Boolean);return t===void 0||t.length===0?{message:e.message}:{message:e.message,details:t}}function createRegistrySetupClient(e={}){let t=e.process??process;if(t.send===void 0||process.env.EVE_SETUP_PROTOCOL===void 0)return;let n=new AbortController;e.signal!==void 0&&e.signal.addEventListener(`abort`,()=>n.abort(e.signal?.reason),{once:!0});let r=1,i=new Map,onMessage=e=>{if(e.type===`cancel`){n.abort(new WizardCancelledError);for(let e of i.values())e({type:`cancel`});i.clear();return}i.get(e.id)?.(e)};t.on(`message`,onMessage),send(t,{type:`ready`,version:2});async function prompt(e){n.signal.throwIfAborted();let a=r++,o=await new Promise(n=>{i.set(a,n),send(t,{type:`prompt`,id:a,prompt:e})});if(i.delete(a),o.type===`cancel`||o.cancelled===!0)throw new WizardCancelledError;return o.value}async function validatedText(e,t){let n=t.notices;for(;;){let r=await prompt({kind:e,message:t.message,placeholder:t.placeholder,defaultValue:t.defaultValue,notices:n}),i=t.validate?.(r);if(i===void 0)return r;n=[{tone:`error`,text:i}]}}function select(e){return prompt({kind:`select`,options:e})}let a={text:e=>validatedText(`text`,e),password:e=>validatedText(`password`,e),select,async selectEditable(e){let t=await prompt({kind:`editable-select`,options:{...e,editable:{value:e.editable.value,defaultValue:e.editable.defaultValue}}});if(t.kind===`selected`)return{kind:`selected`,value:t.value};let n=e.editable.validate?.(t.text);if(n!==void 0)throw Error(n);return{kind:`edited`,value:t.value,text:t.text}},acknowledge:e=>prompt({kind:`acknowledge`,options:e}),awaitChoice(e){let n=r++;return{choice:new Promise((r,a)=>{i.set(n,e=>{i.delete(n),e.type===`cancel`||e.cancelled===!0?a(new WizardCancelledError):r(e.value)}),send(t,{type:`prompt`,id:n,prompt:{kind:`choice`,options:e}})}),close:()=>{i.delete(n),send(t,{type:`close-prompt`,id:n})}}},note(e,n,r){send(t,{type:`note`,message:e,title:n,tone:r?.tone})},intro(e,n){send(t,{type:`intro`,text:e,subtitle:n})},outro(e){send(t,{type:`outro`,text:e})},log:{message:e=>send(t,{type:`log`,level:`message`,text:e}),info:e=>send(t,{type:`log`,level:`info`,text:e}),success:e=>send(t,{type:`log`,level:`success`,text:e}),warning:e=>send(t,{type:`log`,level:`warning`,text:e}),error:e=>send(t,{type:`log`,level:`error`,text:e}),commandOutput:e=>send(t,{type:`log`,level:`commandOutput`,text:e}),spinner(e){let n=r++;return send(t,{type:`status`,id:n,status:e}),{stop:()=>send(t,{type:`status`,id:n})}}}},o=!1,finish=e=>{o||(o=!0,send(t,{type:`result`,outcome:e}),t.off(`message`,onMessage),t.disconnect?.())};return{prompter:a,signal:n.signal,complete:(e={facts:[]})=>finish({kind:`completed`,...e}),cancel:()=>finish({kind:`cancelled`}),fail(e){let t=registrySetupBlocker(e);finish(t===void 0?{kind:`failed`,error:registrySetupError(e)}:{kind:`blocked`,blocker:t})}}}export{createRegistrySetupClient};
@@ -96,10 +96,6 @@ export type RegistrySetupChildMessage = {
96
96
  type: "status";
97
97
  id: number;
98
98
  status?: string;
99
- intent?: {
100
- kind: "external-action";
101
- emphasis: string;
102
- };
103
99
  };
104
100
  export type RegistrySetupParentMessage = {
105
101
  type: "prompt-result";
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.105`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.66.1`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_CHANNEL_TEMPLATES.default,"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{parseChatGptModelSelection}from"../../../shared/chatgpt-model.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{blockingCreateInPlaceEntries}from"../create-in-place.js";import{DEFAULT_CONNECT_PACKAGE_VERSION,resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_CHANNEL_TEMPLATES}from"./web-template.js";import{mkdir,readdir,stat}from"node:fs/promises";import{basename,join,resolve}from"node:path";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,DEFAULT_AI_PACKAGE_VERSION=`^7.0.105`,DEFAULT_ZOD_PACKAGE_VERSION=`4.5.4`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.66.3`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e,t){return{"agent/agent.ts":renderAgentTemplate(e,t),"agent/channels/eve.ts":WEB_CHANNEL_TEMPLATES.default,"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderAgentTemplate(e,t){let n=parseChatGptModelSelection(e);return n===void 0?BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t)):`import { defineAgent } from "eve";\nimport { chatgpt } from "eve/models/openai";\n\nexport default defineAgent({\n model: chatgpt(${JSON.stringify(n)}),\n${reasoningTemplateLine(t)}});\n`}function reasoningTemplateLine(e){return e===void 0||e===`provider-default`?``:` reasoning: "${e}",\n`}function renderTemplate(e,t){return e===BASE_AGENT_TEMPLATE&&parseChatGptModelSelection(t.model)!==void 0?renderAgentTemplate(t.model,t.reasoning):e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_REASONING__`,reasoningTemplateLine(t.reasoning)).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -1 +1 @@
1
- import{parseSlackConnectorDetails,parseSlackConnectors}from"./slack-connect.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import"#setup/primitives/run-vercel.js";import"#setup/cli/index.js";import{CONNECT_MUTATION_TIMEOUT_MS,replaceConnectTrigger}from"#setup/connect-provisioning.js";const CONNECT_LOOKUP_TIMEOUT_MS=6e4;async function listSlackConnectors(e,t,n,r){let i=await e.captureVercel([`connect`,`list`,`-F`,`json`,`--all-projects`],{cwd:t,onOutput:n,timeoutMs:CONNECT_LOOKUP_TIMEOUT_MS,signal:r});if(!i.ok)return{state:`failed`,message:i.failure.message};try{let e=JSON.parse(i.stdout);if(typeof e!=`object`||!e)return{state:`failed`,message:`Vercel returned a malformed connector list.`};let t=e;return Array.isArray(t.connectors??t.clients)?{state:`ok`,body:e,connectors:parseSlackConnectors(e)}:{state:`failed`,message:`Vercel returned a malformed connector list.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the connector list.`}}}async function findSlackConnector(e,t,n,r,i,a){let o=await listSlackConnectors(e,t,i,a);if(o.state===`failed`)return o;let s=new Set(o.connectors.map(e=>e.uid));if(n===void 0)return{state:`not-found`,connectorUids:s};let c=o.connectors.filter(e=>e.id!==void 0&&e.projectIds.includes(n)).sort((e,t)=>t.createdAt-e.createdAt).map(({uid:e,id:t})=>({uid:e,id:t}));if(c.length===0)return{state:`not-found`,connectorUids:s};let l=c.find(e=>e.uid===r);return l===void 0?{state:`found`,connectors:c,connectorUids:s}:{state:`found`,connectors:c,preferred:l,connectorUids:s}}async function attachSlackConnector(e,t,n,r,i){return replaceConnectTrigger({connectorUid:n.uid,projectRoot:t,triggerPath:SLACK_CHANNEL_DEFAULT_ROUTE,onOutput:r,signal:i,deps:e})}async function fetchSlackConnectorDetails(e){let t=e.orgId===void 0?``:`?teamId=${encodeURIComponent(e.orgId)}`,n=[`api`,`/v1/connect/connectors/${encodeURIComponent(e.connectorId)}${t}`];e.orgId!==void 0&&n.push(`--scope`,e.orgId);let r=await e.deps.captureVercel(n,{cwd:e.projectRoot,onOutput:e.onOutput,timeoutMs:e.timeoutMs,signal:e.signal});if(!r.ok)return{state:`failed`,message:r.failure.message};try{let t=JSON.parse(r.stdout),n=parseSlackConnectorDetails(t);return n?.ref.id===e.connectorId?{state:`found`,details:n}:{state:`failed`,message:`Vercel returned an invalid Slack connector.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the Slack connector.`}}}async function fetchSlackWorkspace(e){let t=await fetchSlackConnectorDetails(e);return t.state===`failed`?t:t.details.workspace===void 0?{state:`pending`}:{state:`connected`,workspace:t.details.workspace}}async function cleanupConnectorUid(e,t){let{log:n,deps:r,projectRoot:i,onOutput:a}=e;return await r.runVercel([`connect`,`remove`,t,`--disconnect-all`,`--yes`],{cwd:i,onOutput:a,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS})?!0:(n.warning(`Could not remove the abandoned Slack connector. Run \`vercel connect remove ${t} --disconnect-all --yes\` to clean it up.`),!1)}async function cleanupConnectorUids(e,t){let n=[];for(let r of new Set(t))await cleanupConnectorUid(e,r)||n.push(r);return n.length===0?{state:`clean`}:{state:`failed`,connectorUids:n}}async function cleanupCreatedAttempt(e,t){if(t.createdRef)return cleanupConnectorUids(e,[t.createdRef.uid]);e.log.warning(`Vercel returned no connector UID for the abandoned Slack Connect request, so eve cannot prove that request was cancelled. No connector was removed; do not retry until the browser request is no longer usable.`);let n=await listSlackConnectors(e.deps,e.projectRoot,e.onOutput);return n.state===`failed`?{state:`failed`,connectorUids:[]}:{state:`failed`,connectorUids:n.connectors.map(e=>e.uid).filter(e=>(e===t.expectedUid||e.startsWith(`${t.expectedUid}-`))&&!t.baselineConnectorUids.has(e))}}export{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackConnectorDetails,fetchSlackWorkspace,findSlackConnector,listSlackConnectors};
1
+ import{parseSlackConnectorDetails,parseSlackConnectors}from"./slack-connect.js";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import"#setup/primitives/run-vercel.js";import"#setup/cli/index.js";import{CONNECT_MUTATION_TIMEOUT_MS,replaceConnectTrigger}from"#setup/connect-provisioning.js";const CONNECT_LOOKUP_TIMEOUT_MS=6e4;async function listSlackConnectors(e,t,n,r){let i=await e.captureVercel([`connect`,`list`,`-F`,`json`,`--all-projects`],{cwd:t,onOutput:n,timeoutMs:CONNECT_LOOKUP_TIMEOUT_MS,signal:r});if(!i.ok)return{state:`failed`,message:i.failure.message};try{let e=JSON.parse(i.stdout);if(typeof e!=`object`||!e)return{state:`failed`,message:`Vercel returned a malformed connector list.`};let t=e;return Array.isArray(t.connectors??t.clients)?{state:`ok`,body:e,connectors:parseSlackConnectors(e)}:{state:`failed`,message:`Vercel returned a malformed connector list.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the connector list.`}}}async function findSlackConnector(e,t,n,r,i,a){let o=await listSlackConnectors(e,t,i,a);if(o.state===`failed`)return o;let s=new Set(o.connectors.map(e=>e.uid));if(n===void 0)return{state:`not-found`,connectorUids:s};let c=o.connectors.filter(e=>e.id!==void 0&&e.projectIds.includes(n)).sort((e,t)=>t.createdAt-e.createdAt).map(({uid:e,id:t})=>({uid:e,id:t}));if(c.length===0)return{state:`not-found`,connectorUids:s};let l=c.find(e=>e.uid===r);return l===void 0?{state:`found`,connectors:c,connectorUids:s}:{state:`found`,connectors:c,preferred:l,connectorUids:s}}async function attachSlackConnector(e,t,n,r,i){return replaceConnectTrigger({connectorUid:n.uid,projectRoot:t,triggerPath:SLACK_CHANNEL_DEFAULT_ROUTE,onOutput:r,signal:i,deps:e})}async function fetchSlackConnectorDetails(e){let t=e.orgId===void 0?``:`?teamId=${encodeURIComponent(e.orgId)}`,n=[`api`,`/v1/connect/connectors/${encodeURIComponent(e.connectorId)}${t}`];e.orgId!==void 0&&n.push(`--scope`,e.orgId);let r=await e.deps.captureVercel(n,{cwd:e.projectRoot,onOutput:e.onOutput,timeoutMs:e.timeoutMs,signal:e.signal});if(!r.ok)return{state:`failed`,message:r.failure.message};try{let t=JSON.parse(r.stdout),n=parseSlackConnectorDetails(t);return n?.ref.id===e.connectorId?{state:`found`,details:n}:{state:`failed`,message:`Vercel returned an invalid Slack connector.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the Slack connector.`}}}async function fetchSlackWorkspace(e){let t=await fetchSlackConnectorDetails(e);return t.state===`failed`?t:t.details.workspace===void 0?{state:`pending`}:{state:`connected`,workspace:t.details.workspace}}async function cleanupConnectorUid(e,t){let{log:n,deps:r,projectRoot:i,onOutput:a}=e;return await r.runVercel([`connect`,`remove`,t,`--disconnect-all`,`--yes`],{cwd:i,onOutput:a,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS})?!0:(n.warning(`Could not remove the abandoned Slack connector. Run \`vercel connect remove ${t} --disconnect-all --yes\` to clean it up.`),!1)}async function cleanupConnectorUids(e,t){let n=[];for(let r of new Set(t))await cleanupConnectorUid(e,r)||n.push(r);return n.length===0?{state:`clean`}:{state:`failed`,connectorUids:n}}async function cleanupCreatedAttempt(e,t){if(t.createdRef)return cleanupConnectorUids(e,[t.createdRef.uid]);e.log.warning(`eve couldn't confirm the Slack request in your browser was cancelled. Wait for it to expire before retrying.`);let n=await listSlackConnectors(e.deps,e.projectRoot,e.onOutput);return n.state===`failed`?{state:`failed`,connectorUids:[]}:{state:`failed`,connectorUids:n.connectors.map(e=>e.uid).filter(e=>(e===t.expectedUid||e.startsWith(`${t.expectedUid}-`))&&!t.baselineConnectorUids.has(e))}}export{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackConnectorDetails,fetchSlackWorkspace,findSlackConnector,listSlackConnectors};
@@ -1 +1 @@
1
- import{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector}from"./slack-connect.js";import{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackWorkspace,findSlackConnector,listSlackConnectors}from"./slack-connect-lifecycle.js";import{createSlackConnector}from"./slack-connect-create.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{performance}from"node:perf_hooks";import{readProjectLink}from"#setup/project-resolution.js";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{setTimeout}from"node:timers/promises";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{updateSlackChannelConnectorUid}from"#setup/scaffold/update/update-slack-channel.js";const defaultDeps={captureVercel,runVercel,runVercelCaptureStdout},realDelay=(e,t)=>setTimeout(e,void 0,{signal:t}),monotonicNow=()=>performance.now();async function pollSlackWorkspace(e,t,n,r,i,a){let o=e.delay??realDelay,s=e.now??monotonicNow,c=s()+3e5;for(;;){a?.throwIfAborted();let l=c-s();if(l<=0)return{state:`timed-out`};let u=await fetchSlackWorkspace({deps:e,projectRoot:t,connectorId:n,orgId:r,onOutput:i,timeoutMs:Math.min(CONNECT_LOOKUP_TIMEOUT_MS,l),signal:a});if(a?.throwIfAborted(),u.state!==`pending`)return u;let d=c-s();if(d<=0)return{state:`timed-out`};await o(Math.min(3e3,d),a)}}function isAbortFromSignal(e,t){return t?.aborted===!0&&(e===t.reason||e instanceof Error&&e.name===`AbortError`)}function cleanupFailureResult(e){return{state:`cleanup-failed`,connectorUids:e.connectorUids}}async function runAttempt(e){let{log:t,deps:n,projectRoot:r,orgId:i,onOutput:a,signal:o,phase:s}=e,c,l;if(e.source.state===`existing`)c=e.source.ref;else{let u=await createSlackConnector({deps:n,projectRoot:r,orgId:i,slug:e.slug,onOutput:a,signal:o,phase:s,onCreated:e.onCreated,waitForWorkspace:async(e,t)=>{let o=await pollSlackWorkspace(n,r,e.id,i,a,t);return o.state===`connected`?o.workspace:void 0}});if(u.state===`failed`)return{state:`create-failed`};if(u.state===`unresolved`)return t.warning(`Vercel did not return an exact Slack connector UID for this request, so eve cannot attach or remove it safely.`),{state:`unresolved`};c=u.ref,u.via===`workspace`&&(l=u.workspace)}if(e.source.state===`existing`&&l===void 0){let e=await s(`Waiting for the Slack workspace connection...`,()=>pollSlackWorkspace(n,r,c.id,i,a,o));if(e.state===`timed-out`)return{state:`timed-out`,ref:c};if(e.state===`failed`)return{state:`failed`,ref:c,message:e.message};l=e.workspace}let u=await s(`Configuring Slack event delivery for this agent...`,()=>attachSlackConnector(n,r,c,a,o));return o?.throwIfAborted(),u.state===`attached`?l===void 0?{state:`attached`,ref:c}:{state:`attached`,ref:c,workspace:l}:{state:u.state,ref:c}}async function raceAttemptAgainstChoice(e){let t=new AbortController,n=e.outerSignal?AbortSignal.any([e.outerSignal,t.signal]):t.signal,r=e.run(n);try{let i=await Promise.race([r.then(e=>({via:`work`,outcome:e})),e.prompt.choice.then(e=>({via:`choice`,choice:e}))]);if(i.via===`work`)return i;t.abort();let a;try{a=await r}catch(e){if(!isAbortFromSignal(e,n))throw e}return{via:`choice`,choice:i.choice,settled:a}}catch(e){t.abort();try{await r}catch{}throw e}finally{e.prompt.close()}}async function inspectSlackbotConnectors(e,t,n,r,i=defaultDeps){let a=await(i.readProjectLink??readProjectLink)(t),o=await findSlackConnector(i,t,a?.projectId,`slack/${n}`,createPromptCommandOutput(e),r);if(o.state===`failed`)throw Error(o.message);return o}async function provisionSlackbot(e,t,n,r=defaultDeps,i={}){i.signal?.throwIfAborted();let a=createPromptCommandOutput(e),o={log:e,deps:r,projectRoot:t,onOutput:a},s=await(r.readProjectLink??readProjectLink)(t),c=s?.projectId,l=s?.orgId,u=`slack/${n}`,d=await withPhase(e,`Checking for an existing Slackbot...`,()=>findSlackConnector(r,t,c,u,a,i.signal));if(i.signal?.throwIfAborted(),d.state===`failed`)return e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${d.message}`),{state:`connector-lookup-failed`};if(c===void 0&&d.connectorUids.size>0)return e.warning("Could not verify which Slack connectors belong to this Vercel project, so eve did not create another one. Restore `.vercel/project.json`, then try again."),{state:`connector-lookup-failed`};let finishOutcome=async(t,n,r)=>{let i=n.state===`new`;switch(t.state){case`create-failed`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`unresolved`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`detach-failed`:return e.warning(`Could not remove the connector's existing trigger destination. Run \`vercel connect detach ${t.ref.uid} --yes\`, then \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\`.`),{state:`detach-failed`,connectorUid:t.ref.uid};case`attach-failed`:return e.warning(`Could not register this project as a trigger destination. Run \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\` to enable event delivery.`),{state:`attach-failed`,connectorUid:t.ref.uid};case`attached`:return t.workspace===void 0?{state:`attached`,connectorUid:t.ref.uid}:{state:`attached`,connectorUid:t.ref.uid,chatUrl:t.workspace.workspaceUrl,workspaceName:t.workspace.workspaceName};case`failed`:return e.warning(`Could not verify the Slack workspace connection. ${t.message}`),{state:`installation-check-failed`,connectorUid:t.ref.uid};case`timed-out`:if(e.warning(`The Slackbot did not connect to a Slack workspace in time.`),i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`not-installed`}}},cleanupNewAttempt=async(e,t)=>cleanupCreatedAttempt(o,{expectedUid:u,baselineConnectorUids:e.baselineConnectorUids,createdRef:t});function attemptInput(i,o){return{log:e,deps:r,projectRoot:t,orgId:l,slug:n,source:i,onOutput:a,onCreated:o}}async function runExistingConnector(t){let cleanupCurrentAttempt=async()=>({state:`clean`}),notInstalled=()=>(e.warning(`The existing Slack connector \`${t.ref.uid}\` is not connected to a Slack workspace. eve did not remove it because this run did not create it. If its original browser request is still open, complete it; otherwise run \`vercel connect remove ${t.ref.uid} --disconnect-all --yes\` before trying again.`),{state:`existing-not-installed`,connectorUid:t.ref.uid}),finishExistingOutcome=async e=>e.state===`timed-out`?notInstalled():finishOutcome(e,t,cleanupCurrentAttempt);if(i.awaitChoice!==void 0){let e=await raceAttemptAgainstChoice({prompt:i.awaitChoice({status:`Waiting for the existing Slack workspace connection...`,context:`Complete the original setup in the browser`,actions:[{value:`cancel`,label:`Stop waiting`}]}),outerSignal:i.signal,run:e=>runAttempt({...attemptInput(t,()=>{}),signal:e,phase:(e,t)=>t()})});return e.via===`work`?finishExistingOutcome(e.outcome):e.settled?.state===`attached`?finishExistingOutcome(e.settled):notInstalled()}return finishExistingOutcome(await runAttempt({...attemptInput(t,()=>{}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)}))}async function runUncontrolledAttempt(t){let n,cleanupCurrentAttempt=()=>cleanupNewAttempt(t,n),r=runAttempt({...attemptInput(t,e=>{n=e}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)});try{return await finishOutcome(await r,t,cleanupCurrentAttempt)}catch(e){throw i.signal?.aborted===!0&&await cleanupCurrentAttempt(),e}}async function runInteractiveAttempt(n,o){let s,cleanupCurrentAttempt=()=>cleanupNewAttempt(n,s),c=o({status:`Waiting for Slack setup to finish...`,context:`Complete setup in the browser, then wait while eve verifies the connection`,actions:[{value:`retry`,label:`Did your browser not open? Try again`},{value:`cancel`,label:`Cancel`}]}),l;try{l=await raceAttemptAgainstChoice({prompt:c,outerSignal:i.signal,run:t=>runAttempt({...attemptInput(n,e=>{s=e}),signal:t,phase:e.spinner===void 0?(e,t)=>t():(t,n)=>withPhase(e,t,n)})})}catch(e){throw await cleanupCurrentAttempt(),e}if(l.via===`work`)return{state:`finished`,result:await finishOutcome(l.outcome,n,cleanupCurrentAttempt)};if(l.settled?.state===`attached`)return{state:`finished`,result:await finishOutcome(l.settled,n,cleanupCurrentAttempt)};let u=await cleanupCurrentAttempt();if(u.state===`failed`)return{state:`finished`,result:cleanupFailureResult(u)};if(l.choice===`retry`){let n=await withPhase(e,`Checking existing Slack connectors...`,()=>listSlackConnectors(r,t,a,i.signal));return i.signal?.throwIfAborted(),n.state===`failed`?(e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${n.message}`),{state:`finished`,result:{state:`connector-lookup-failed`}}):{state:`retry`,source:{state:`new`,baselineConnectorUids:new Set(n.connectors.map(e=>e.uid))}}}return{state:`finished`,result:{state:`cancelled`}}}if(d.state===`found`){let e=i.selectConnector===void 0?d.preferred??d.connectors[0]:await i.selectConnector(d.connectors,d.preferred);if(i.signal?.throwIfAborted(),e!==`create`)return runExistingConnector({state:`existing`,ref:e})}let f={state:`new`,baselineConnectorUids:d.connectorUids};if(i.awaitChoice===void 0)return runUncontrolledAttempt(f);for(;;){let e=await runInteractiveAttempt(f,i.awaitChoice);if(e.state===`finished`)return e.result;f=e.source}}async function reconcileSlackUid(e,t,n,r){if(n.state!==`attached`||n.connectorUid===r)return!0;let i=join(t,`agent/channels/slack.ts`),{patched:a}=await updateSlackChannelConnectorUid(i,n.connectorUid);return a?!0:(e.warning(`Could not patch agent/channels/slack.ts automatically. Update \`connectSlackCredentials("...")\` to \`"${n.connectorUid}"\` and run \`vercel deploy --prod\`.`),!1)}export{inspectSlackbotConnectors,parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector,provisionSlackbot,reconcileSlackUid};
1
+ import{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector}from"./slack-connect.js";import{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackWorkspace,findSlackConnector,listSlackConnectors}from"./slack-connect-lifecycle.js";import{createSlackConnector}from"./slack-connect-create.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{readProjectLink}from"#setup/project-resolution.js";import{performance}from"node:perf_hooks";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{setTimeout}from"node:timers/promises";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{updateSlackChannelConnectorUid}from"#setup/scaffold/update/update-slack-channel.js";const defaultDeps={captureVercel,runVercel,runVercelCaptureStdout},realDelay=(e,t)=>setTimeout(e,void 0,{signal:t}),monotonicNow=()=>performance.now();async function pollSlackWorkspace(e,t,n,r,i,a){let o=e.delay??realDelay,s=e.now??monotonicNow,c=s()+3e5;for(;;){a?.throwIfAborted();let l=c-s();if(l<=0)return{state:`timed-out`};let u=await fetchSlackWorkspace({deps:e,projectRoot:t,connectorId:n,orgId:r,onOutput:i,timeoutMs:Math.min(CONNECT_LOOKUP_TIMEOUT_MS,l),signal:a});if(a?.throwIfAborted(),u.state!==`pending`)return u;let d=c-s();if(d<=0)return{state:`timed-out`};await o(Math.min(3e3,d),a)}}function isAbortFromSignal(e,t){return t?.aborted===!0&&(e===t.reason||e instanceof Error&&e.name===`AbortError`)}function cleanupFailureResult(e){return{state:`cleanup-failed`,connectorUids:e.connectorUids}}async function runAttempt(e){let{log:t,deps:n,projectRoot:r,orgId:i,onOutput:a,signal:o,phase:s}=e,c,l;if(e.source.state===`existing`)c=e.source.ref;else{let u=await createSlackConnector({deps:n,projectRoot:r,orgId:i,slug:e.slug,onOutput:a,signal:o,phase:s,onCreated:e.onCreated,waitForWorkspace:async(e,t)=>{let o=await pollSlackWorkspace(n,r,e.id,i,a,t);return o.state===`connected`?o.workspace:void 0}});if(u.state===`failed`)return{state:`create-failed`};if(u.state===`unresolved`)return t.warning(`Vercel did not return an exact Slack connector UID for this request, so eve cannot attach or remove it safely.`),{state:`unresolved`};c=u.ref,u.via===`workspace`&&(l=u.workspace)}if(e.source.state===`existing`&&l===void 0){let e=await s(`Waiting for the Slack workspace connection...`,()=>pollSlackWorkspace(n,r,c.id,i,a,o));if(e.state===`timed-out`)return{state:`timed-out`,ref:c};if(e.state===`failed`)return{state:`failed`,ref:c,message:e.message};l=e.workspace}let u=await s(`Configuring Slack event delivery for this agent...`,()=>attachSlackConnector(n,r,c,a,o));return o?.throwIfAborted(),u.state===`attached`?l===void 0?{state:`attached`,ref:c}:{state:`attached`,ref:c,workspace:l}:{state:u.state,ref:c}}async function raceAttemptAgainstChoice(e){let t=new AbortController,n=e.outerSignal?AbortSignal.any([e.outerSignal,t.signal]):t.signal,r=e.run(n);try{let i=await Promise.race([r.then(e=>({via:`work`,outcome:e})),e.prompt.choice.then(e=>({via:`choice`,choice:e}))]);if(i.via===`work`)return i;t.abort();let a;try{a=await r}catch(e){if(!isAbortFromSignal(e,n))throw e}return{via:`choice`,choice:i.choice,settled:a}}catch(e){t.abort();try{await r}catch{}throw e}finally{e.prompt.close()}}async function inspectSlackbotConnectors(e,t,n,r,i=defaultDeps){let a=await(i.readProjectLink??readProjectLink)(t),o=await findSlackConnector(i,t,a?.projectId,`slack/${n}`,createPromptCommandOutput(e),r);if(o.state===`failed`)throw Error(o.message);return o}async function provisionSlackbot(e,t,n,r=defaultDeps,i={}){i.signal?.throwIfAborted();let a=createPromptCommandOutput(e),o={log:e,deps:r,projectRoot:t,onOutput:a},s=await(r.readProjectLink??readProjectLink)(t),c=s?.projectId,l=s?.orgId,u=`slack/${n}`,d=await withPhase(e,`Checking for an existing Slackbot...`,()=>findSlackConnector(r,t,c,u,a,i.signal));if(i.signal?.throwIfAborted(),d.state===`failed`)return e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${d.message}`),{state:`connector-lookup-failed`};if(c===void 0&&d.connectorUids.size>0)return e.warning("Could not verify which Slack connectors belong to this Vercel project, so eve did not create another one. Restore `.vercel/project.json`, then try again."),{state:`connector-lookup-failed`};let finishOutcome=async(t,n,r)=>{let i=n.state===`new`;switch(t.state){case`create-failed`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`unresolved`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`detach-failed`:return e.warning(`Could not remove the connector's existing trigger destination. Run \`vercel connect detach ${t.ref.uid} --yes\`, then \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\`.`),{state:`detach-failed`,connectorUid:t.ref.uid};case`attach-failed`:return e.warning(`Could not register this project as a trigger destination. Run \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\` to enable event delivery.`),{state:`attach-failed`,connectorUid:t.ref.uid};case`attached`:return t.workspace===void 0?{state:`attached`,connectorUid:t.ref.uid}:{state:`attached`,connectorUid:t.ref.uid,chatUrl:t.workspace.workspaceUrl,workspaceName:t.workspace.workspaceName};case`failed`:return e.warning(`Could not verify the Slack workspace connection. ${t.message}`),{state:`installation-check-failed`,connectorUid:t.ref.uid};case`timed-out`:if(e.warning(`The Slackbot did not connect to a Slack workspace in time.`),i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`not-installed`}}},cleanupNewAttempt=async(e,t)=>cleanupCreatedAttempt(o,{expectedUid:u,baselineConnectorUids:e.baselineConnectorUids,createdRef:t});function attemptInput(i,o){return{log:e,deps:r,projectRoot:t,orgId:l,slug:n,source:i,onOutput:a,onCreated:o}}async function runExistingConnector(t){let cleanupCurrentAttempt=async()=>({state:`clean`}),notInstalled=()=>(e.warning(`The existing Slack connector \`${t.ref.uid}\` is not connected to a Slack workspace. eve did not remove it because this run did not create it. If its original browser request is still open, complete it; otherwise run \`vercel connect remove ${t.ref.uid} --disconnect-all --yes\` before trying again.`),{state:`existing-not-installed`,connectorUid:t.ref.uid}),finishExistingOutcome=async e=>e.state===`timed-out`?notInstalled():finishOutcome(e,t,cleanupCurrentAttempt);if(i.awaitChoice!==void 0){let e=await raceAttemptAgainstChoice({prompt:i.awaitChoice({status:`Waiting for the existing Slack workspace connection...`,context:`Complete the original setup in the browser`,actions:[{value:`cancel`,label:`Stop waiting`}]}),outerSignal:i.signal,run:e=>runAttempt({...attemptInput(t,()=>{}),signal:e,phase:(e,t)=>t()})});return e.via===`work`?finishExistingOutcome(e.outcome):e.settled?.state===`attached`?finishExistingOutcome(e.settled):notInstalled()}return finishExistingOutcome(await runAttempt({...attemptInput(t,()=>{}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)}))}async function runUncontrolledAttempt(t){let n,cleanupCurrentAttempt=()=>cleanupNewAttempt(t,n),r=runAttempt({...attemptInput(t,e=>{n=e}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)});try{return await finishOutcome(await r,t,cleanupCurrentAttempt)}catch(e){throw i.signal?.aborted===!0&&await cleanupCurrentAttempt(),e}}async function runInteractiveAttempt(n,o){let s,cleanupCurrentAttempt=()=>cleanupNewAttempt(n,s),c=o({status:`Waiting for Slack setup to finish...`,context:`Complete setup in the browser, then wait while eve verifies the connection`,actions:[{value:`retry`,label:`Did your browser not open? Try again`},{value:`cancel`,label:`Cancel`}]}),l;try{l=await raceAttemptAgainstChoice({prompt:c,outerSignal:i.signal,run:t=>runAttempt({...attemptInput(n,e=>{s=e}),signal:t,phase:e.spinner===void 0?(e,t)=>t():(t,n)=>withPhase(e,t,n)})})}catch(e){throw await cleanupCurrentAttempt(),e}if(l.via===`work`)return{state:`finished`,result:await finishOutcome(l.outcome,n,cleanupCurrentAttempt)};if(l.settled?.state===`attached`)return{state:`finished`,result:await finishOutcome(l.settled,n,cleanupCurrentAttempt)};let u=await cleanupCurrentAttempt();if(u.state===`failed`)return{state:`finished`,result:cleanupFailureResult(u)};if(l.choice===`retry`){let n=await withPhase(e,`Checking existing Slack connectors...`,()=>listSlackConnectors(r,t,a,i.signal));return i.signal?.throwIfAborted(),n.state===`failed`?(e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${n.message}`),{state:`finished`,result:{state:`connector-lookup-failed`}}):{state:`retry`,source:{state:`new`,baselineConnectorUids:new Set(n.connectors.map(e=>e.uid))}}}return{state:`finished`,result:{state:`cancelled`}}}if(d.state===`found`){let e=i.selectConnector===void 0?d.preferred??d.connectors[0]:await i.selectConnector(d.connectors,d.preferred);if(i.signal?.throwIfAborted(),e!==`create`)return runExistingConnector({state:`existing`,ref:e})}let f={state:`new`,baselineConnectorUids:d.connectorUids};if(i.awaitChoice===void 0)return runUncontrolledAttempt(f);for(;;){let e=await runInteractiveAttempt(f,i.awaitChoice);if(e.state===`finished`)return e.result;f=e.source}}async function reconcileSlackUid(e,t,n,r){if(n.state!==`attached`||n.connectorUid===r)return!0;let i=join(t,`agent/channels/slack.ts`),{patched:a}=await updateSlackChannelConnectorUid(i,n.connectorUid);return a?!0:(e.warning(`Could not patch agent/channels/slack.ts automatically. Update \`connectSlackCredentials("...")\` to \`"${n.connectorUid}"\` and run \`vercel deploy --prod\`.`),!1)}export{inspectSlackbotConnectors,parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector,provisionSlackbot,reconcileSlackUid};
@@ -20,6 +20,8 @@ export interface PickTeamOptions extends VercelProjectOperationOptions {
20
20
  selectMessage?: (currentTeam: string) => string;
21
21
  }
22
22
  export interface LinkProjectOperationOptions extends CreatedProjectFrameworkOptions {
23
+ /** Configure 100% trace sampling when creating a Vercel project. */
24
+ traceSampling?: boolean;
23
25
  }
24
26
  /** Effects used to ensure an interactive Vercel project link. */
25
27
  export interface EnsureLinkedVercelProjectDeps {
Binary file
@@ -0,0 +1,3 @@
1
+ import type { VercelProjectReference } from "./project-resolution.js";
2
+ import type { Prompter } from "./prompter.js";
3
+ export declare function configureTraceSampling(link: VercelProjectReference, prompter: Pick<Prompter, "log">, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1 @@
1
+ import{readVercelCliToken}from"#internal/model-auth/vercel-cli.js";const AGENT_PROJECT_TRACING_SAMPLING=[{type:`head_sampling`,rate:1}];async function configureTraceSampling(e,t,n){try{let t=await readVercelCliToken();if(t===void 0)throw Error(`Vercel CLI credentials are unavailable.`);let r=new URLSearchParams({projectId:e.projectId,teamId:e.orgId});if(!(await fetch(`https://api.vercel.com/v1/drains/tracing/config?${r.toString()}`,{body:JSON.stringify({enabled:!0,sampling:AGENT_PROJECT_TRACING_SAMPLING}),headers:{authorization:`Bearer ${t}`,"content-type":`application/json`},method:`PUT`,redirect:`error`,signal:n?AbortSignal.any([n,AbortSignal.timeout(15e3)]):AbortSignal.timeout(15e3)})).ok)throw Error(`Vercel rejected the trace sampling configuration.`)}catch{n?.throwIfAborted(),t.log.warning(`The Vercel project was created, but trace sampling could not be configured. Set it to 100% for all environments in the Vercel project settings.`)}}export{configureTraceSampling};