eve 0.28.0 → 0.29.0

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 (221) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/src/channel/types.d.ts +6 -0
  3. package/dist/src/chunks/{use-eve-agent-hdPX68_i.js → use-eve-agent-CyDt3Lny.js} +2 -0
  4. package/dist/src/chunks/{use-eve-agent-CZkX_ZTT.js → use-eve-agent-DaH3cf8K.js} +2 -0
  5. package/dist/src/cli/commands/agent-prompt/collect-intent.md +1 -1
  6. package/dist/src/cli/commands/channels.d.ts +0 -17
  7. package/dist/src/cli/commands/channels.js +1 -1
  8. package/dist/src/cli/commands/deploy.js +1 -1
  9. package/dist/src/cli/commands/extension-init.js +1 -1
  10. package/dist/src/cli/commands/init.js +1 -1
  11. package/dist/src/cli/commands/integration-connect.d.ts +29 -0
  12. package/dist/src/cli/commands/integration-connect.js +1 -0
  13. package/dist/src/cli/commands/integration-setup.d.ts +2 -3
  14. package/dist/src/cli/commands/integration-setup.js +1 -1
  15. package/dist/src/cli/commands/register-integration-commands.js +1 -1
  16. package/dist/src/cli/commands/registry-setup-command.d.ts +13 -3
  17. package/dist/src/cli/commands/registry-setup-command.js +2 -1
  18. package/dist/src/cli/commands/registry.d.ts +35 -1
  19. package/dist/src/cli/commands/registry.js +1 -1
  20. package/dist/src/cli/commands/trace.js +1 -1
  21. package/dist/src/cli/dev/tui/agent-header.js +1 -1
  22. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  23. package/dist/src/cli/dev/tui/prompt-commands.d.ts +1 -1
  24. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  25. package/dist/src/cli/dev/tui/remote-auth-command.js +1 -1
  26. package/dist/src/cli/dev/tui/runner.d.ts +8 -7
  27. package/dist/src/cli/dev/tui/runner.js +1 -1
  28. package/dist/src/cli/dev/tui/setup-commands.d.ts +8 -13
  29. package/dist/src/cli/dev/tui/setup-commands.js +3 -2
  30. package/dist/src/cli/dev/tui/setup-flow.d.ts +14 -5
  31. package/dist/src/cli/dev/tui/setup-panel.d.ts +5 -1
  32. package/dist/src/cli/dev/tui/setup-panel.js +2 -2
  33. package/dist/src/cli/dev/tui/status-line.d.ts +1 -1
  34. package/dist/src/cli/dev/tui/status-line.js +1 -1
  35. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +2 -5
  36. package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
  37. package/dist/src/cli/dev/tui/test/fake-setup-flow-renderer.js +1 -1
  38. package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
  39. package/dist/src/cli/dev/tui/tui.d.ts +2 -0
  40. package/dist/src/cli/dev/tui/tui.js +1 -1
  41. package/dist/src/cli/dev/tui/vercel-status.d.ts +1 -6
  42. package/dist/src/cli/dev/tui/vercel-status.js +1 -1
  43. package/dist/src/cli/option-parsers.d.ts +11 -0
  44. package/dist/src/cli/option-parsers.js +1 -0
  45. package/dist/src/cli/run.d.ts +1 -12
  46. package/dist/src/cli/run.js +3 -3
  47. package/dist/src/cli/shutdown.d.ts +2 -0
  48. package/dist/src/cli/shutdown.js +1 -1
  49. package/dist/src/compiled/.vendor-stamp.json +5 -5
  50. package/dist/src/compiled/@workflow/core/index.js +1 -1
  51. package/dist/src/compiled/@workflow/core/private.d.ts +21 -5
  52. package/dist/src/compiled/@workflow/core/private.js +1 -1
  53. package/dist/src/compiled/@workflow/core/runtime/world.d.ts +10 -5
  54. package/dist/src/compiled/@workflow/core/runtime.js +3 -3
  55. package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +2 -2
  56. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  57. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  58. package/dist/src/compiled/@workflow/world-local/index.js +3 -3
  59. package/dist/src/compiled/@workflow/world-vercel/index.js +13 -13
  60. package/dist/src/compiled/_chunks/workflow/{attribute-changes-DeZc2RZz.js → attribute-changes-1LmTKuTT.js} +1 -1
  61. package/dist/src/compiled/_chunks/workflow/{private-Cre8uYkA.js → private-BcwCGTV5.js} +1 -1
  62. package/dist/src/compiled/_chunks/workflow/{resume-hook-ip1hbn1b.js → resume-hook-D1_5NCZ6.js} +1 -1
  63. package/dist/src/compiled/_chunks/workflow/{run-CWytxfIp.js → run-C240Ctf4.js} +1 -1
  64. package/dist/src/compiled/_chunks/workflow/sleep-De802yfX.js +1 -0
  65. package/dist/src/compiled/_chunks/workflow/{wait-until-De9yESQN.js → wait-until-z48sPUjU.js} +2 -2
  66. package/dist/src/compiled/shadcn-registry/index.d.ts +1 -0
  67. package/dist/src/evals/assertions/collector.d.ts +2 -10
  68. package/dist/src/evals/assertions/collector.js +1 -1
  69. package/dist/src/evals/cli/eval.d.ts +6 -2
  70. package/dist/src/evals/cli/eval.js +2 -2
  71. package/dist/src/evals/cli/filter.d.ts +14 -0
  72. package/dist/src/evals/cli/filter.js +1 -0
  73. package/dist/src/evals/context.js +1 -1
  74. package/dist/src/evals/diagnostics.d.ts +8 -0
  75. package/dist/src/evals/diagnostics.js +1 -0
  76. package/dist/src/evals/expect/index.d.ts +1 -1
  77. package/dist/src/evals/expect/index.js +1 -1
  78. package/dist/src/evals/index.d.ts +1 -1
  79. package/dist/src/evals/judge.js +2 -1
  80. package/dist/src/evals/runner/artifacts.js +1 -1
  81. package/dist/src/evals/runner/reporters/assertion-diagnostics.d.ts +3 -0
  82. package/dist/src/evals/runner/reporters/assertion-diagnostics.js +3 -0
  83. package/dist/src/evals/runner/reporters/braintrust.js +1 -1
  84. package/dist/src/evals/runner/reporters/console.js +1 -1
  85. package/dist/src/evals/runner/reporters/junit.js +2 -2
  86. package/dist/src/evals/types.d.ts +21 -5
  87. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  88. package/dist/src/execution/turn-cancellation-control.js +1 -1
  89. package/dist/src/execution/turn-workflow.js +1 -1
  90. package/dist/src/execution/workflow-runtime.js +1 -1
  91. package/dist/src/execution/workflow-steps.d.ts +7 -0
  92. package/dist/src/execution/workflow-steps.js +1 -1
  93. package/dist/src/harness/turn-sleep.d.ts +12 -0
  94. package/dist/src/harness/turn-sleep.js +1 -0
  95. package/dist/src/internal/application/compiled-artifacts.js +7 -7
  96. package/dist/src/internal/application/package.js +1 -1
  97. package/dist/src/internal/nitro/host/dev-authored-source-watcher.d.ts +4 -0
  98. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  99. package/dist/src/internal/nitro/host/start-development-server.js +2 -2
  100. package/dist/src/internal/workflow/development-world-protocol.js +1 -1
  101. package/dist/src/internal/workflow/world-target.d.ts +7 -0
  102. package/dist/src/internal/workflow/world-target.js +1 -0
  103. package/dist/src/protocol/routes.d.ts +4 -0
  104. package/dist/src/protocol/routes.js +1 -1
  105. package/dist/src/public/tools/sleep/index.d.ts +18 -0
  106. package/dist/src/public/tools/sleep/index.js +1 -0
  107. package/dist/src/runtime/framework-tools/sleep.d.ts +15 -0
  108. package/dist/src/runtime/framework-tools/sleep.js +1 -0
  109. package/dist/src/services/dev-client/runtime-artifacts.d.ts +7 -0
  110. package/dist/src/services/dev-client/runtime-artifacts.js +1 -1
  111. package/dist/src/setup/boxes/apply-ai-gateway-credential.js +1 -1
  112. package/dist/src/setup/boxes/deploy-project.d.ts +3 -3
  113. package/dist/src/setup/flows/deploy.js +1 -1
  114. package/dist/src/setup/flows/ensure-vercel-project.d.ts +17 -0
  115. package/dist/src/setup/flows/ensure-vercel-project.js +1 -0
  116. package/dist/src/setup/flows/in-project.d.ts +1 -1
  117. package/dist/src/setup/flows/link.js +1 -1
  118. package/dist/src/setup/flows/model.js +1 -1
  119. package/dist/src/setup/flows/provider.js +1 -1
  120. package/dist/src/setup/flows/registry.d.ts +20 -0
  121. package/dist/src/setup/flows/registry.js +1 -0
  122. package/dist/src/setup/index.d.ts +0 -1
  123. package/dist/src/setup/index.js +1 -1
  124. package/dist/src/setup/{channel-setup-environment.d.ts → integrations/channels/environment.d.ts} +2 -2
  125. package/dist/src/setup/integrations/channels/environment.js +1 -0
  126. package/dist/src/setup/{channel-setup-integrations.d.ts → integrations/channels/index.d.ts} +3 -3
  127. package/dist/src/setup/integrations/channels/index.js +1 -0
  128. package/dist/src/setup/{channel-setup-runner.d.ts → integrations/channels/runner.d.ts} +1 -1
  129. package/dist/src/setup/integrations/channels/runner.js +1 -0
  130. package/dist/src/setup/{boxes/add-channels.d.ts → integrations/channels/setup.d.ts} +32 -22
  131. package/dist/src/setup/integrations/channels/setup.js +2 -0
  132. package/dist/src/setup/{channel-setup-slack.d.ts → integrations/channels/slack.d.ts} +1 -1
  133. package/dist/src/setup/integrations/channels/slack.js +1 -0
  134. package/dist/src/setup/{channel-setup-integration.d.ts → integrations/channels/types.d.ts} +23 -7
  135. package/dist/src/setup/{channel-setup-ui.d.ts → integrations/channels/ui.d.ts} +2 -2
  136. package/dist/src/setup/integrations/channels/ui.js +2 -0
  137. package/dist/src/setup/{channel-setup-web.d.ts → integrations/channels/web.d.ts} +1 -1
  138. package/dist/src/setup/integrations/channels/web.js +1 -0
  139. package/dist/src/setup/primitives/run-vercel.d.ts +1 -0
  140. package/dist/src/setup/primitives/run-vercel.js +1 -1
  141. package/dist/src/setup/prompter.d.ts +16 -3
  142. package/dist/src/setup/prompter.js +1 -1
  143. package/dist/src/setup/registry-setup-client.d.ts +18 -0
  144. package/dist/src/setup/registry-setup-client.js +2 -0
  145. package/dist/src/setup/registry-setup-protocol.d.ts +93 -0
  146. package/dist/src/setup/registry-setup-protocol.js +1 -0
  147. package/dist/src/setup/scaffold/channels-catalog.d.ts +1 -1
  148. package/dist/src/setup/scaffold/create/extension.js +2 -2
  149. package/dist/src/setup/scaffold/create/project.js +2 -2
  150. package/dist/src/setup/scaffold/create-in-place.d.ts +1 -0
  151. package/dist/src/setup/scaffold/create-in-place.js +1 -0
  152. package/dist/src/setup/scaffold/index.js +1 -1
  153. package/dist/src/setup/scaffold/update/connections.js +3 -3
  154. package/dist/src/setup/scaffold/update/update-connection-connector.js +1 -1
  155. package/dist/src/setup/vercel-project-framework.d.ts +1 -1
  156. package/dist/src/setup/vercel-project-framework.js +1 -1
  157. package/dist/src/setup/vercel-project.d.ts +17 -2
  158. package/dist/src/setup/vercel-project.js +0 -0
  159. package/dist/src/svelte/index.js +1 -1
  160. package/dist/src/svelte/use-eve-agent.js +1 -1
  161. package/dist/src/vue/index.js +1 -1
  162. package/dist/src/vue/use-eve-agent.js +1 -1
  163. package/docs/channels/overview.mdx +1 -1
  164. package/docs/channels/slack.mdx +2 -2
  165. package/docs/concepts/default-harness.md +12 -0
  166. package/docs/evals/assertions.mdx +8 -1
  167. package/docs/evals/judge.mdx +11 -1
  168. package/docs/evals/reporters.mdx +1 -1
  169. package/docs/evals/running.mdx +3 -0
  170. package/docs/guides/dev-tui.md +9 -14
  171. package/docs/guides/instrumentation.md +1 -1
  172. package/docs/reference/cli.md +25 -38
  173. package/docs/reference/typescript-api.md +2 -1
  174. package/docs/tutorial/ship-it.mdx +2 -2
  175. package/package.json +11 -6
  176. package/dist/src/compiled/@workflow/core/runtime/world-target.d.ts +0 -11
  177. package/dist/src/compiled/_chunks/workflow/sleep-BjrUxUcs.js +0 -1
  178. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/index.js +0 -1
  179. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/parse-name.js +0 -1
  180. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/promise.js +0 -1
  181. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/time.js +0 -1
  182. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/workflow-routes.js +0 -1
  183. package/dist/src/node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/world-target.js +0 -1
  184. package/dist/src/node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js +0 -1
  185. package/dist/src/setup/boxes/add-channels.js +0 -2
  186. package/dist/src/setup/boxes/add-connections.d.ts +0 -26
  187. package/dist/src/setup/boxes/add-connections.js +0 -1
  188. package/dist/src/setup/boxes/install-channel-registry-items.d.ts +0 -8
  189. package/dist/src/setup/boxes/install-channel-registry-items.js +0 -1
  190. package/dist/src/setup/boxes/one-shot-next-steps.d.ts +0 -18
  191. package/dist/src/setup/boxes/one-shot-next-steps.js +0 -2
  192. package/dist/src/setup/boxes/preflight.d.ts +0 -37
  193. package/dist/src/setup/boxes/preflight.js +0 -1
  194. package/dist/src/setup/boxes/resolve-target.d.ts +0 -58
  195. package/dist/src/setup/boxes/resolve-target.js +0 -1
  196. package/dist/src/setup/boxes/scaffold.d.ts +0 -40
  197. package/dist/src/setup/boxes/scaffold.js +0 -1
  198. package/dist/src/setup/boxes/select-channels.d.ts +0 -49
  199. package/dist/src/setup/boxes/select-channels.js +0 -1
  200. package/dist/src/setup/boxes/select-chat.d.ts +0 -38
  201. package/dist/src/setup/boxes/select-chat.js +0 -1
  202. package/dist/src/setup/boxes/select-connections.d.ts +0 -30
  203. package/dist/src/setup/boxes/select-connections.js +0 -1
  204. package/dist/src/setup/boxes/select-setup-mode.d.ts +0 -32
  205. package/dist/src/setup/boxes/select-setup-mode.js +0 -1
  206. package/dist/src/setup/channel-setup-deployment.d.ts +0 -11
  207. package/dist/src/setup/channel-setup-deployment.js +0 -1
  208. package/dist/src/setup/channel-setup-environment.js +0 -1
  209. package/dist/src/setup/channel-setup-integration.js +0 -1
  210. package/dist/src/setup/channel-setup-integrations.js +0 -1
  211. package/dist/src/setup/channel-setup-runner.js +0 -1
  212. package/dist/src/setup/channel-setup-slack.js +0 -1
  213. package/dist/src/setup/channel-setup-ui.js +0 -2
  214. package/dist/src/setup/channel-setup-web.js +0 -1
  215. package/dist/src/setup/flows/channels.d.ts +0 -57
  216. package/dist/src/setup/flows/channels.js +0 -1
  217. package/dist/src/setup/flows/connections.d.ts +0 -37
  218. package/dist/src/setup/flows/connections.js +0 -3
  219. package/dist/src/setup/onboarding.d.ts +0 -60
  220. package/dist/src/setup/onboarding.js +0 -1
  221. /package/dist/src/{node_modules/.pnpm/@workflow_utils@5.0.0-beta.7/node_modules/@workflow/utils/dist/pluralize.js → setup/integrations/channels/types.js} +0 -0
@@ -0,0 +1,15 @@
1
+ import { z } from "#compiled/zod/index.js";
2
+ export declare const SLEEP_TOOL_DESCRIPTION = "Wait for a specified amount of time before continuing. Use this when a process or condition needs time to change before it is useful to check its progress or status again.";
3
+ export declare const SLEEP_INPUT_SCHEMA: z.ZodObject<{
4
+ seconds: z.ZodNumber;
5
+ }, z.core.$strict>;
6
+ export declare const SLEEP_OUTPUT_SCHEMA: z.ZodObject<{
7
+ waitedSeconds: z.ZodNumber;
8
+ }, z.core.$strict>;
9
+ export type SleepToolInput = z.infer<typeof SLEEP_INPUT_SCHEMA>;
10
+ export type SleepToolOutput = z.infer<typeof SLEEP_OUTPUT_SCHEMA>;
11
+ /**
12
+ * Records a durable wait for the owning turn workflow to fulfill after the
13
+ * current atomic step finishes.
14
+ */
15
+ export declare function executeSleepTool(input: SleepToolInput): SleepToolOutput;
@@ -0,0 +1 @@
1
+ import{z}from"#compiled/zod/index.js";import{requestTurnSleep}from"#harness/turn-sleep.js";const MAX_SLEEP_SECONDS=Math.floor((2**53-1)/1e3),SLEEP_TOOL_DESCRIPTION=`Wait for a specified amount of time before continuing. Use this when a process or condition needs time to change before it is useful to check its progress or status again.`,SLEEP_INPUT_SCHEMA=z.strictObject({seconds:z.number().positive().max(MAX_SLEEP_SECONDS).describe(`How long to wait, in seconds.`)}),SLEEP_OUTPUT_SCHEMA=z.strictObject({waitedSeconds:z.number().positive()});function executeSleepTool(e){return requestTurnSleep(Math.ceil(e.seconds*1e3)),{waitedSeconds:e.seconds}}export{SLEEP_INPUT_SCHEMA,SLEEP_OUTPUT_SCHEMA,SLEEP_TOOL_DESCRIPTION,executeSleepTool};
@@ -11,6 +11,13 @@
11
11
  export declare function readDevelopmentRuntimeArtifactsRevision(input: {
12
12
  readonly serverUrl: string;
13
13
  }): Promise<string | undefined>;
14
+ export declare function suspendDevelopmentRuntimeArtifacts(input: {
15
+ readonly serverUrl: string;
16
+ }): Promise<boolean>;
17
+ export declare function resumeDevelopmentRuntimeArtifacts(input: {
18
+ readonly serverUrl: string;
19
+ readonly silent?: boolean;
20
+ }): Promise<string | undefined>;
14
21
  export declare function rebuildDevelopmentRuntimeArtifacts(input: {
15
22
  readonly force?: boolean;
16
23
  readonly serverUrl: string;
@@ -1 +1 @@
1
- import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(e){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,e.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(n))}catch{return}}async function rebuildDevelopmentRuntimeArtifacts(t){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,t.serverUrl);return t.force===!0&&n.searchParams.set(`force`,`1`),await parseDevelopmentRuntimeArtifactsRevision(await fetch(n,{method:`POST`}))}catch{return}}async function parseDevelopmentRuntimeArtifactsRevision(e){if(!e.ok)return;let t=await e.json();return typeof t.revision==`string`&&t.revision.length>0?t.revision:void 0}export{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts};
1
+ import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_RESUME_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_SUSPEND_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(e){try{let t=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,e.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(t))}catch{return}}async function suspendDevelopmentRuntimeArtifacts(e){return await changeDevelopmentRuntimeArtifacts(e.serverUrl,EVE_DEV_RUNTIME_ARTIFACTS_SUSPEND_ROUTE_PATH)}async function resumeDevelopmentRuntimeArtifacts(e){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_RESUME_ROUTE_PATH,e.serverUrl);return e.silent===!0&&n.searchParams.set(`silent`,`1`),await parseDevelopmentRuntimeArtifactsRevision(await fetch(n,{method:`POST`}))}catch{return}}async function changeDevelopmentRuntimeArtifacts(e,t){try{return(await fetch(new URL(t,e),{method:`POST`})).ok}catch{return!1}}async function rebuildDevelopmentRuntimeArtifacts(t){try{let n=new URL(EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,t.serverUrl);return t.force===!0&&n.searchParams.set(`force`,`1`),await parseDevelopmentRuntimeArtifactsRevision(await fetch(n,{method:`POST`}))}catch{return}}async function parseDevelopmentRuntimeArtifactsRevision(e){if(!e.ok)return;let t=await e.json();return typeof t.revision==`string`&&t.revision.length>0?t.revision:void 0}export{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts,resumeDevelopmentRuntimeArtifacts,suspendDevelopmentRuntimeArtifacts};
@@ -1 +1 @@
1
- import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{isProjectResolved}from"../project-resolution.js";import{requireProjectPath}from"../state.js";import{withSpinner}from"../with-spinner.js";import{runVercelEnvPull}from"../run-vercel-link.js";import{detectAiGatewayResolution}from"./detect-ai-gateway.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function applyAiGatewayCredential(a){let o=a.deps??{appendEnv,runVercelEnvPull,detectAiGatewayResolution};return{id:`apply-ai-gateway-credential`,shouldRun(e){let{aiGateway:t,project:n}=e;return t.kind===`byok`||t.kind===`inherit`&&isProjectResolved(n)},async gather(){return null},async perform({state:e,signal:r}){let{prompter:i}=a,s=requireProjectPath(e),c=e.aiGateway,l=isProjectResolved(e.project);if(c.kind===`byop`)return{kind:`unresolved`};if(c.kind===`byok`){let e=await writeAiGatewayApiKey({projectRoot:s,apiKey:c.apiGatewayKey,appendEnv:o.appendEnv});return a.prompter.log.success(`Wrote ${e.envKey} to ${e.envPath}`),{kind:`api-key`,envFile:e.envFile}}if(!l)return i.log.warning(`No Vercel project linked and no API key provided. The agent will not reach a model until you set ${AI_GATEWAY_API_KEY_ENV_VAR} in ${AI_GATEWAY_API_KEY_ENV_FILE} or link a project.`),{kind:`unresolved`};let u=createPromptCommandOutput(i.log),d=await withSpinner(i,`Pulling Vercel environment variables into .env.local...`,()=>o.runVercelEnvPull(s,u,r));return r?.throwIfAborted(),d||i.log.warning(`Linked the project, but pulling environment variables did not complete.`),o.detectAiGatewayResolution(s)},apply(e,t){return{...e,aiGatewayCredentials:t}}}}export{applyAiGatewayCredential};
1
+ import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{isProjectResolved}from"../project-resolution.js";import{runVercelEnvPull}from"../run-vercel-link.js";import{withSpinner}from"../with-spinner.js";import{requireProjectPath}from"../state.js";import{detectAiGatewayResolution}from"./detect-ai-gateway.js";import{createPromptCommandOutput}from"#setup/cli/index.js";function applyAiGatewayCredential(a){let o=a.deps??{appendEnv,runVercelEnvPull,detectAiGatewayResolution};return{id:`apply-ai-gateway-credential`,shouldRun(e){let{aiGateway:t,project:n}=e;return t.kind===`byok`||t.kind===`inherit`&&isProjectResolved(n)},async gather(){return null},async perform({state:e,signal:r}){let{prompter:i}=a,s=requireProjectPath(e),c=e.aiGateway,l=isProjectResolved(e.project);if(c.kind===`byop`)return{kind:`unresolved`};if(c.kind===`byok`){let e=await writeAiGatewayApiKey({projectRoot:s,apiKey:c.apiGatewayKey,appendEnv:o.appendEnv});return a.prompter.log.success(`Wrote ${e.envKey} to ${e.envPath}`),{kind:`api-key`,envFile:e.envFile}}if(!l)return i.log.warning(`No Vercel project linked and no API key provided. The agent will not reach a model until you set ${AI_GATEWAY_API_KEY_ENV_VAR} in ${AI_GATEWAY_API_KEY_ENV_FILE} or link a project.`),{kind:`unresolved`};let u=createPromptCommandOutput(i.log),d=await withSpinner(i,`Pulling Vercel environment variables into .env.local...`,()=>o.runVercelEnvPull(s,u,r));return r?.throwIfAborted(),d||i.log.warning(`Linked the project, but pulling environment variables did not complete.`),o.detectAiGatewayResolution(s)},apply(e,t){return{...e,aiGatewayCredentials:t}}}}export{applyAiGatewayCredential};
@@ -23,7 +23,7 @@ export interface DeployProjectOptions {
23
23
  skip?: boolean;
24
24
  /**
25
25
  * Run even without a planned or detected project, linking interactively from
26
- * inside `perform` (the `eve channels add` composition; onboarding always has
26
+ * inside `perform` (the `eve add channel/slack` composition; onboarding always has
27
27
  * a plan or skips deploy with the channels).
28
28
  */
29
29
  ensureLinkedProject?: "interactive-vercel-link";
@@ -59,14 +59,14 @@ export interface DeployProjectPayload {
59
59
  * The project was linked up front by the link box, so `perform` reuses
60
60
  * `state.project` and never triggers a second interactive `vercel link` (the
61
61
  * #1020 deadlock). When no resolution exists (no link box ran, e.g. the
62
- * `eve channels add` composition), it falls back to the interactive bare
62
+ * `eve add channel/slack` composition), it falls back to the interactive bare
63
63
  * `vercel link`, or throws {@link HumanActionRequiredError} headlessly.
64
64
  *
65
65
  * Once the project is linked, {@link syncHostFrameworkPreset} runs before the
66
66
  * deploy so a project that gained a host framework (e.g. a web channel) builds
67
67
  * the host app instead of the stale `eve` agent preset. It is a no-op for a
68
68
  * plain agent (no host framework on disk) or an already-correct preset, so
69
- * every deploy surface — `eve channels add`, the dev TUI `/deploy`, onboarding —
69
+ * every deploy surface — `eve add channel/slack`, the dev TUI `/deploy`, onboarding —
70
70
  * gets the reconcile without composing a separate box.
71
71
  */
72
72
  export declare function deployProject(options: DeployProjectOptions): SetupBox<SetupState, DeployProjectInput, DeployProjectPayload>;
@@ -1 +1 @@
1
- import{interactiveAsker,withAnswers}from"../ask.js";import{detectDeployment,isProjectResolved,projectResolutionFromDeployment}from"../project-resolution.js";import{snapshotSetupState}from"../state.js";import{withSpinner}from"../with-spinner.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";function productionUrlOf(e){return e.kind===`deployed`?e.productionUrl:void 0}async function runDeployFlow(t){let{appRoot:n,prompter:r,interactive:i,signal:a}=t,o={detectDeployment,...t.deps},s=await withSpinner(r,`Checking the current Vercel link...`,async()=>{let e=await o.detectDeployment(n,{signal:a});return a?.throwIfAborted(),projectResolutionFromDeployment(e)}),c=isProjectResolved(s);if(!c&&!i)return{kind:`needs-link`};let l=inProjectSetupState(n,s,{deploymentPending:!0}),u=c?[deployProject({prompter:r,headless:!i,deps:o.deployProject})]:[resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(r)),prompter:r,targetDirectory:n,mode:{headless:!1},deps:o.resolveProvisioning}),linkVercelProject({prompter:r,deps:o.linkProject}),deployProject({prompter:r,headless:!i,deps:o.deployProject})],d=prompterSink(r);if(!i)return{kind:`deployed`,productionUrl:productionUrlOf((await runHeadless(u,l,d,{snapshot:snapshotSetupState,signal:a})).project)};let f=await runInteractive(u,l,d,{snapshot:snapshotSetupState,signal:a});return f.kind===`cancelled`?{kind:`cancelled`}:{kind:`deployed`,productionUrl:productionUrlOf(f.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";function productionUrlOf(e){return e.kind===`deployed`?e.productionUrl:void 0}async function runDeployFlow(t){let{appRoot:n,prompter:r,interactive:i,signal:a}=t,o={detectDeployment,...t.deps},s=await withSpinner(r,`Checking the current Vercel link...`,async()=>{let e=await o.detectDeployment(n,{signal:a});return a?.throwIfAborted(),projectResolutionFromDeployment(e)}),c=isProjectResolved(s);if(!c&&!i)return{kind:`needs-link`};let l=inProjectSetupState(n,s,{deploymentPending:!0}),u=c?[deployProject({prompter:r,headless:!i,deps:o.deployProject})]:[resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(r)),prompter:r,targetDirectory:n,mode:{headless:!1},deps:o.resolveProvisioning}),linkVercelProject({prompter:r,deps:o.linkProject}),deployProject({prompter:r,headless:!i,deps:o.deployProject})],d=prompterSink(r);if(!i)return{kind:`deployed`,productionUrl:productionUrlOf((await runHeadless(u,l,d,{snapshot:snapshotSetupState,signal:a})).project)};let f=await runInteractive(u,l,d,{snapshot:snapshotSetupState,signal:a});return f.kind===`cancelled`?{kind:`cancelled`}:{kind:`deployed`,productionUrl:productionUrlOf(f.state.project)}}export{runDeployFlow};
@@ -0,0 +1,17 @@
1
+ import { type LinkProjectDeps } from "../boxes/link-project.js";
2
+ import { type ResolveProvisioningDeps } from "../boxes/resolve-provisioning.js";
3
+ import type { Prompter } from "../prompter.js";
4
+ import { readProjectLink, type VercelProjectReference } from "../project-resolution.js";
5
+ export interface EnsureVercelProjectDeps {
6
+ resolveProvisioning?: ResolveProvisioningDeps;
7
+ linkProject?: LinkProjectDeps;
8
+ readProjectLink: typeof readProjectLink;
9
+ }
10
+ /** Ensures a project link using eve-owned prompts and a non-interactive Vercel command. */
11
+ export declare function ensureVercelProject(input: {
12
+ appRoot: string;
13
+ prompter: Prompter;
14
+ signal?: AbortSignal;
15
+ teamSelectMessage?: (currentTeam: string) => string;
16
+ deps?: Partial<EnsureVercelProjectDeps>;
17
+ }): Promise<VercelProjectReference>;
@@ -0,0 +1 @@
1
+ import{interactiveAsker,withAnswers}from"../ask.js";import{readProjectLink}from"../project-resolution.js";import{snapshotSetupState}from"../state.js";import{linkVercelProject}from"../boxes/link-project.js";import{resolveProvisioning}from"../boxes/resolve-provisioning.js";import{WizardCancelledError}from"../step.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";async function ensureVercelProject(e){let t=e.deps?.readProjectLink??readProjectLink,n=await t(e.appRoot);if(n!==void 0)return n;let r=inProjectSetupState(e.appRoot,{kind:`unresolved`});if((await runInteractive([resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(e.prompter)),prompter:e.prompter,targetDirectory:e.appRoot,mode:{headless:!1},adoptExistingLink:!1,projectSelection:`create-or-link`,teamSelectMessage:e.teamSelectMessage,deps:e.deps?.resolveProvisioning}),linkVercelProject({prompter:e.prompter,deps:e.deps?.linkProject})],r,prompterSink(e.prompter),{snapshot:snapshotSetupState,signal:e.signal})).kind===`cancelled`)throw e.signal?.throwIfAborted(),new WizardCancelledError;let i=await t(e.appRoot);if(i===void 0)throw Error(`Vercel project linking failed.`);return i}export{ensureVercelProject};
@@ -9,7 +9,7 @@ import type { OutputSink } from "../step.js";
9
9
  * named X" row), and the resolved in-place project path. The channels flow
10
10
  * seeds its own state instead — it must keep the default empty agent name so
11
11
  * the Slack connector slug falls back to the package.json name, exactly like
12
- * `eve channels add`.
12
+ * `eve add channel/slack`.
13
13
  */
14
14
  export declare function inProjectSetupState(appRoot: string, project: ProjectResolution, seed?: Partial<SetupState>): SetupState;
15
15
  /** Routes runner sink output through the prompter's log. */
@@ -1 +1 @@
1
- import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{interactiveAsker,withAnswers}from"../ask.js";import{detectProjectIdentity}from"../project-resolution.js";import{snapshotSetupState}from"../state.js";import{WizardCancelledError}from"../step.js";import{withSpinner}from"../with-spinner.js";import{detectAiGateway,findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"../boxes/apply-ai-gateway-credential.js";import{linkVercelProject}from"../boxes/link-project.js";import{resolveProvisioning}from"../boxes/resolve-provisioning.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{hasEnvValue,resolveGatewayCredential}from"#internal/resolve-model-endpoint-status.js";var import_picocolors=__toESM(require_picocolors(),1);async function runLinkFlow(e){let{appRoot:t,prompter:a,signal:o,projectSelection:s=`existing-only`}=e,c={detectProjectIdentity,findEnvFileWithKey,env:process.env,...e.deps},l=await withSpinner(a,`Checking the current Vercel link...`,async()=>{let e=await c.detectProjectIdentity(t,{signal:o});return o?.throwIfAborted(),e});if(l===void 0){let[n,r]=await Promise.all([c.findEnvFileWithKey(t,AI_GATEWAY_API_KEY_ENV_VAR),c.findEnvFileWithKey(t,`VERCEL_OIDC_TOKEN`)]),i=n??r;i!==void 0&&e.teamSelectMessage===void 0&&a.log.message(`This directory is not linked to a Vercel project yet — the model currently runs on credentials from ${i}.`)}else{let e=l.teamName===void 0?import_picocolors.default.bold(l.projectName):`${import_picocolors.default.bold(l.projectName)} in ${import_picocolors.default.bold(l.teamName)}`;try{if(await a.select({message:`This directory is already linked to\n${e}`,options:[{value:`relink`,label:`Link to another project`},{value:`dismiss`,label:`Dismiss`}]})===`dismiss`)return{kind:`cancelled`}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}let u=inProjectSetupState(t,{kind:`unresolved`});if((await runInteractive([resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(a)),prompter:a,targetDirectory:t,mode:{headless:!1},adoptExistingLink:!1,projectSelection:s,teamSelectMessage:e.teamSelectMessage,deps:c.resolveProvisioning}),linkVercelProject({prompter:a,deps:c.linkProject}),detectAiGateway(),applyAiGatewayCredential({prompter:a,deps:c.applyAiGatewayCredential})],u,prompterSink(a),{snapshot:snapshotSetupState,signal:o})).kind===`cancelled`)return{kind:`cancelled`};let[d,f]=await Promise.all([c.findEnvFileWithKey(t,`VERCEL_OIDC_TOKEN`),c.findEnvFileWithKey(t,AI_GATEWAY_API_KEY_ENV_VAR)]);o?.throwIfAborted(),d===void 0&&f===void 0&&a.log.warning("Linked, but no model credential landed in an env file (VERCEL_OIDC_TOKEN or AI_GATEWAY_API_KEY). Run `vercel env pull` once the project has AI Gateway access.");let p={kind:`done`},m={apiKeyInEnv:hasEnvValue(c.env[AI_GATEWAY_API_KEY_ENV_VAR])};f!==void 0&&(m.apiKeyFile=f),d!==void 0&&(m.oidcFile=d);let h=resolveGatewayCredential(m);return h!==void 0&&(p.resolution=h),p}export{runLinkFlow};
1
+ import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{interactiveAsker,withAnswers}from"../ask.js";import{detectProjectIdentity}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{snapshotSetupState}from"../state.js";import{detectAiGateway,findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{applyAiGatewayCredential}from"../boxes/apply-ai-gateway-credential.js";import{linkVercelProject}from"../boxes/link-project.js";import{resolveProvisioning}from"../boxes/resolve-provisioning.js";import{WizardCancelledError}from"../step.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{hasEnvValue,resolveGatewayCredential}from"#internal/resolve-model-endpoint-status.js";var import_picocolors=__toESM(require_picocolors(),1);async function runLinkFlow(e){let{appRoot:t,prompter:a,signal:o,projectSelection:s=`existing-only`}=e,c={detectProjectIdentity,findEnvFileWithKey,env:process.env,...e.deps},l=await withSpinner(a,`Checking the current Vercel link...`,async()=>{let e=await c.detectProjectIdentity(t,{signal:o});return o?.throwIfAborted(),e});if(l===void 0){let[n,r]=await Promise.all([c.findEnvFileWithKey(t,AI_GATEWAY_API_KEY_ENV_VAR),c.findEnvFileWithKey(t,`VERCEL_OIDC_TOKEN`)]),i=n??r;i!==void 0&&e.teamSelectMessage===void 0&&a.log.message(`This directory is not linked to a Vercel project yet — the model currently runs on credentials from ${i}.`)}else{let e=l.teamName===void 0?import_picocolors.default.bold(l.projectName):`${import_picocolors.default.bold(l.projectName)} in ${import_picocolors.default.bold(l.teamName)}`;try{if(await a.select({message:`This directory is already linked to\n${e}`,options:[{value:`relink`,label:`Link to another project`},{value:`dismiss`,label:`Dismiss`}]})===`dismiss`)return{kind:`cancelled`}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}}let u=inProjectSetupState(t,{kind:`unresolved`});if((await runInteractive([resolveProvisioning({asker:withAnswers({deploy:`vercel`})(interactiveAsker(a)),prompter:a,targetDirectory:t,mode:{headless:!1},adoptExistingLink:!1,projectSelection:s,teamSelectMessage:e.teamSelectMessage,deps:c.resolveProvisioning}),linkVercelProject({prompter:a,deps:c.linkProject}),detectAiGateway(),applyAiGatewayCredential({prompter:a,deps:c.applyAiGatewayCredential})],u,prompterSink(a),{snapshot:snapshotSetupState,signal:o})).kind===`cancelled`)return{kind:`cancelled`};let[d,f]=await Promise.all([c.findEnvFileWithKey(t,`VERCEL_OIDC_TOKEN`),c.findEnvFileWithKey(t,AI_GATEWAY_API_KEY_ENV_VAR)]);o?.throwIfAborted(),d===void 0&&f===void 0&&a.log.warning("Linked, but no model credential landed in an env file (VERCEL_OIDC_TOKEN or AI_GATEWAY_API_KEY). Run `vercel env pull` once the project has AI Gateway access.");let p={kind:`done`},m={apiKeyInEnv:hasEnvValue(c.env[AI_GATEWAY_API_KEY_ENV_VAR])};f!==void 0&&(m.apiKeyFile=f),d!==void 0&&(m.oidcFile=d);let h=resolveGatewayCredential(m);return h!==void 0&&(p.resolution=h),p}export{runLinkFlow};
@@ -1 +1 @@
1
- import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{detectProjectIdentity}from"../project-resolution.js";import{WizardCancelledError}from"../step.js";import{withSpinner}from"../with-spinner.js";import{findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import{inspectApplication}from"#services/inspect-application.js";import{hasEnvValue,resolveGatewayCredential}from"#internal/resolve-model-endpoint-status.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";var import_picocolors=__toESM(require_picocolors(),1);const MODEL_MENU_MESSAGE=``;function providerStatusHint(e,t=e=>e){if(e.kind===`gateway-project`)return`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`;let n=e.source.kind===`shell`?`your shell`:e.source.path;return`AI Gateway (${e.envKey} in ${n})`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o){let s;a||o?(s={value:`model`,label:`Change model`,description:a?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(s.hint=formatModelDraftHint(e,t,n))):s={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let c;return c=i?.kind===`external`?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:r.kind===`unset`?{value:`provider`,label:import_picocolors.default.bold(`Configure model access`),hint:import_picocolors.default.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`}:{value:`provider`,label:`Change provider`,hint:providerStatusHint(r,import_picocolors.default.bold),description:`How your agent reaches the model provider`},[s,c,{value:`done`,label:`Done`}]}async function detectModelProviderStatus(e,t={},i=process.env){let[a,s,c]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(a!==void 0){let e={kind:`gateway-project`,projectName:a.projectName};return a.teamName!==void 0&&(e.teamName=a.teamName),e}let l={apiKeyInEnv:hasEnvValue(i[AI_GATEWAY_API_KEY_ENV_VAR])};s!==void 0&&(l.apiKeyFile=s),c!==void 0&&(l.oidcFile=c);let u=resolveGatewayCredential(l);return u===void 0?{kind:`unset`}:u.credential===`api-key`?{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,source:u.source}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,source:{kind:`env-file`,path:u.file}}}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,o={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,detectProviderStatus:detectModelProviderStatus,runProviderFlow,...e.deps},detectProvider=(e=!0)=>o.detectProviderStatus(t,e&&r!==void 0?{signal:r}:{}),l=o.selectModel?.fetchModels??fetchGatewayCatalog,[d,f,p]=await withSpinner(n,`Checking the project…`,()=>Promise.all([o.readCurrentModel(t),detectProvider(),l(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:m,routing:h,serviceTier:g,editable:_,settingsEditable:v}=d,y=d.reasoning===`provider-default`?null:d.reasoning,b=f,x={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},S,C,w=!1,T=h?.kind===`external`?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,E=b.kind===`unset`&&h?.kind!==`external`?`provider`:_||v?`model`:`provider`,D=h?.kind!==`external`&&(e.initialStep===`provider`||b.kind===`unset`);for(;;){let e;if(D)D=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(m,y,g,b,h,_,v),hintLayout:`stacked`,initialValue:E,notices:T===void 0?[]:[T]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(x))return{kind:`cancelled`,discardedDraft:!0};break}if(e===`done`){w=!0;break}if(e===`model`){let e=o.pickModelSettings;if(e===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let t=await e({model:_?{kind:`pick`,options:modelListRows(p),current:m}:{kind:`fixed`,current:m,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:y,serviceTier:g,settingsEditable:v,externalRouting:h?.kind===`external`,capabilitiesFor:e=>gatewayModelCapabilities(p,e)});if(r?.throwIfAborted(),t===void 0){E=`model`;continue}t.model!==void 0&&(m=t.model,h={kind:`gateway`,target:t.model.split(`/`)[0]??``},x.model={kind:`set`,value:t.model}),t.reasoning!==void 0&&(y=t.reasoning==="default"?null:t.reasoning,x.reasoning=y===null?{kind:`remove`}:{kind:`set`,value:y}),t.serviceTier!==void 0&&(g=t.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},x.gatewayServiceTier=t.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),E=`done`;continue}let c=await o.runProviderFlow({appRoot:t,prompter:n,signal:r,currentProvider:b});if(c.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};E=`provider`;continue}if(c.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};E=`done`;continue}b=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),C={status:b},c.kind===`done`&&c.resolution!==void 0&&(C.resolution=c.resolution),w=!0;break}if(w&&hasModelSettingsChanges(x)&&(S=await o.applySettings({appRoot:t,patch:x}),r?.throwIfAborted()),S===void 0&&C===void 0)return{kind:`cancelled`};let O={kind:`done`};return S!==void 0&&(O.modelMessage=formatApplyModelSettingsOutcome(S)),C!==void 0&&(O.providerOutcome=C),O}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model;return{id:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&r.source===void 0,settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,detectModelProviderStatus,modelChangeRefusalForUneditableModel,runModelFlow};
1
+ import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{AI_GATEWAY_API_KEY_ENV_VAR}from"../ai-gateway-api-key.js";import{detectProjectIdentity}from"../project-resolution.js";import{withSpinner}from"../with-spinner.js";import{findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{gatewayModelCapabilities}from"../boxes/model-capabilities.js";import{fetchGatewayCatalog,modelOptionsFromCatalog}from"../boxes/select-model.js";import{WizardCancelledError}from"../step.js";import{changeAgentModelSettings,formatApplyModelSettingsOutcome}from"./model-source-change.js";import{runProviderFlow}from"./provider.js";import{inspectApplication}from"#services/inspect-application.js";import{hasEnvValue,resolveGatewayCredential}from"#internal/resolve-model-endpoint-status.js";import{formatModelSummary}from"#shared/model-summary.js";import{readGatewayServiceTier}from"#shared/gateway-service-tier.js";var import_picocolors=__toESM(require_picocolors(),1);const MODEL_MENU_MESSAGE=``;function providerStatusHint(e,t=e=>e){if(e.kind===`gateway-project`)return`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`;let n=e.source.kind===`shell`?`your shell`:e.source.path;return`AI Gateway (${e.envKey} in ${n})`}function modelListRows(e){return modelOptionsFromCatalog(e).map(e=>{let t={value:e.value,label:e.value};return e.featured===!0&&(t.featured=!0),t})}function formatModelDraftHint(e,t,n){let r={model:e};return t!==null&&(r.reasoning=t),n.kind===`priority`&&(r.fastGlyph=`↯`),formatModelSummary(r)}function modelMenuRows(e,t,n,r,i,a,o){let s;a||o?(s={value:`model`,label:`Change model`,description:a?`The model, its reasoning effort, and the Gateway service tier`:`Reasoning and service tier; the model itself is an SDK model call in agent.ts`},e!==null&&(s.hint=formatModelDraftHint(e,t,n))):s={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let c;return c=i?.kind===`external`?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:r.kind===`unset`?{value:`provider`,label:import_picocolors.default.bold(`Configure model access`),hint:import_picocolors.default.yellow(`Not configured`),description:`How your agent reaches the model provider`,accent:`warning`}:{value:`provider`,label:`Change provider`,hint:providerStatusHint(r,import_picocolors.default.bold),description:`How your agent reaches the model provider`},[s,c,{value:`done`,label:`Done`}]}async function detectModelProviderStatus(e,t={},i=process.env){let[o,s,c]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(o!==void 0){let e={kind:`gateway-project`,projectName:o.projectName};return o.teamName!==void 0&&(e.teamName=o.teamName),e}let l={apiKeyInEnv:hasEnvValue(i[AI_GATEWAY_API_KEY_ENV_VAR])};s!==void 0&&(l.apiKeyFile=s),c!==void 0&&(l.oidcFile=c);let u=resolveGatewayCredential(l);return u===void 0?{kind:`unset`}:u.credential===`api-key`?{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,source:u.source}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,source:{kind:`env-file`,path:u.file}}}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,a={readCurrentModel:readCurrentAgentModel,applySettings:changeAgentModelSettings,detectProviderStatus:detectModelProviderStatus,runProviderFlow,...e.deps},detectProvider=(e=!0)=>a.detectProviderStatus(t,e&&r!==void 0?{signal:r}:{}),c=a.selectModel?.fetchModels??fetchGatewayCatalog,[d,f,p]=await withSpinner(n,`Checking the project…`,()=>Promise.all([a.readCurrentModel(t),detectProvider(),c(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:m,routing:h,serviceTier:g,editable:_,settingsEditable:v}=d,y=d.reasoning===`provider-default`?null:d.reasoning,b=f,x={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},S,C,w=!1,T=h?.kind===`external`?{tone:`warning`,text:"`agent.ts` specifies the model provider directly. Model, provider, and service-tier changes stay source-owned; reasoning remains configurable here."}:void 0,E=b.kind===`unset`&&h?.kind!==`external`?`provider`:_||v?`model`:`provider`,D=h?.kind!==`external`&&(e.initialStep===`provider`||b.kind===`unset`);for(;;){let e;if(D)D=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(m,y,g,b,h,_,v),hintLayout:`stacked`,initialValue:E,notices:T===void 0?[]:[T]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(x))return{kind:`cancelled`,discardedDraft:!0};break}if(e===`done`){w=!0;break}if(e===`model`){let e=a.pickModelSettings;if(e===void 0)throw Error(`runModelFlow requires a pickModelSettings dep to open the model screen.`);let t=await e({model:_?{kind:`pick`,options:modelListRows(p),current:m}:{kind:`fixed`,current:m,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:y,serviceTier:g,settingsEditable:v,externalRouting:h?.kind===`external`,capabilitiesFor:e=>gatewayModelCapabilities(p,e)});if(r?.throwIfAborted(),t===void 0){E=`model`;continue}t.model!==void 0&&(m=t.model,h={kind:`gateway`,target:t.model.split(`/`)[0]??``},x.model={kind:`set`,value:t.model}),t.reasoning!==void 0&&(y=t.reasoning==="default"?null:t.reasoning,x.reasoning=y===null?{kind:`remove`}:{kind:`set`,value:y}),t.serviceTier!==void 0&&(g=t.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},x.gatewayServiceTier=t.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),E=`done`;continue}let s=await a.runProviderFlow({appRoot:t,prompter:n,signal:r,currentProvider:b});if(s.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};E=`provider`;continue}if(s.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};E=`done`;continue}b=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),C={status:b},s.kind===`done`&&s.resolution!==void 0&&(C.resolution=s.resolution),w=!0;break}if(w&&hasModelSettingsChanges(x)&&(S=await a.applySettings({appRoot:t,patch:x}),r?.throwIfAborted()),S===void 0&&C===void 0)return{kind:`cancelled`};let O={kind:`done`};return S!==void 0&&(O.modelMessage=formatApplyModelSettingsOutcome(S)),C!==void 0&&(O.providerOutcome=C),O}function hasModelSettingsChanges(e){return e.model.kind!==`keep`||e.reasoning.kind!==`keep`||e.gatewayServiceTier.kind!==`keep`}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config,r=n?.model;return{id:r?.id??null,routing:r?.routing??null,reasoning:n?.reasoning??null,serviceTier:readGatewayServiceTier(r?.providerOptions),editable:r!==void 0&&r.source===void 0,settingsEditable:n?.source!==void 0}}catch{return{id:null,routing:null,reasoning:null,serviceTier:{kind:`standard`},editable:!1,settingsEditable:!1}}}async function modelChangeRefusalForUneditableModel(e){let{editable:t,routing:n}=await readCurrentAgentModel(e);return t?null:`Model is set via ${n?.kind===`external`?`the external provider \`${n.provider}\``:`an SDK model call`} in agent.ts, not a string literal; /model can't rewrite it. Edit \`model\` in agent.ts.`}export{MODEL_MENU_MESSAGE,detectModelProviderStatus,modelChangeRefusalForUneditableModel,runModelFlow};
@@ -1,4 +1,4 @@
1
- import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{WizardCancelledError}from"../step.js";import{withSpinner}from"../with-spinner.js";import{getVercelAuthStatus,vercelAuthBlockerReason}from"../vercel-project.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";var import_picocolors=__toESM(require_picocolors(),1);const PROVIDER_QUESTION=`Which model provider do you want to use?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${AI_GATEWAY_API_KEY_ENV_FILE} — e.g. ANTHROPIC_API_KEY or OPENAI_API_KEY.`,'In agent/agent.ts, set `model` to a provider-authored model — e.g. `anthropic("claude-opus-4.8")` from `@ai-sdk/anthropic`.',`See https://eve.dev/docs/agent-config for details.`,"A running `eve dev` reloads env files automatically — no restart needed."];function projectConnectionOption(e){let t={value:`project`,label:`AI Gateway via Project`,hint:`Authenticates with AI Gateway automatically
1
+ import{__toESM}from"../../_virtual/_rolldown/runtime.js";import{require_picocolors}from"../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js";import{appendEnv}from"../append-env.js";import{AI_GATEWAY_API_KEY_ENV_FILE,AI_GATEWAY_API_KEY_ENV_VAR,writeAiGatewayApiKey}from"../ai-gateway-api-key.js";import{withSpinner}from"../with-spinner.js";import{getVercelAuthStatus,vercelAuthBlockerReason}from"../vercel-project.js";import{WizardCancelledError}from"../step.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";var import_picocolors=__toESM(require_picocolors(),1);const PROVIDER_QUESTION=`Which model provider do you want to use?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${AI_GATEWAY_API_KEY_ENV_FILE} — e.g. ANTHROPIC_API_KEY or OPENAI_API_KEY.`,'In agent/agent.ts, set `model` to a provider-authored model — e.g. `anthropic("claude-opus-4.8")` from `@ai-sdk/anthropic`.',`See https://eve.dev/docs/agent-config for details.`,"A running `eve dev` reloads env files automatically — no restart needed."];function projectConnectionOption(e){let t={value:`project`,label:`AI Gateway via Project`,hint:`Authenticates with AI Gateway automatically
2
2
  in a new or existing project. No keys to manage.`},n=e===void 0?void 0:vercelAuthBlockerReason(e);return n===void 0?t:{...t,disabled:!0,disabledReason:n,disabledReasonTone:`warning`}}function providerOptions(e,t){let n=projectConnectionOption(e);if(t?.kind===`gateway-project`){let e=t.teamName===void 0?import_picocolors.default.bold(t.projectName):`${import_picocolors.default.bold(t.projectName)} in team ${import_picocolors.default.bold(t.teamName)}`;n={...n,checked:!0,hint:`Linked to ${e}`}}let r={value:`own-key`,label:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`,hint:`⎿ type your key`};if(t?.kind===`gateway-key`){let e=t.source.kind===`shell`?`your shell`:t.source.path;r={...r,checked:!0,hint:`${t.envKey} set in ${e}`}}return[n,r,{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider
3
3
  via OPENAI_API_KEY or ANTHROPIC_API_KEY.`}]}async function selectProvider(e){let t={message:PROVIDER_QUESTION,options:e.options,initialValue:e.initialValue,validateInlineKey:e.validateInlineKey};if(e.picker===void 0)throw Error(`The provider flow requires the Dev TUI provider picker.`);let n=await e.picker(t);if(n===void 0)throw new WizardCancelledError;return n}async function runProviderFlow(e){let{appRoot:t,prompter:r,signal:i}=e,o={getVercelAuthStatus,runLinkFlow,appendEnv,validateGatewayApiKey,...e.deps},s,c=e.currentProvider?.kind===`gateway-key`?`own-key`:`project`,l;try{for(;;){let n=await selectProvider({picker:e.picker,options:providerOptions(s,e.currentProvider),initialValue:c,validateInlineKey:(e,t)=>o.validateGatewayApiKey(e,i===void 0?t:AbortSignal.any([i,t]))});if(n.kind===`external`)return r.acknowledge?await r.acknowledge({message:EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,lines:EXTERNAL_PROVIDER_INSTRUCTIONS}):r.note(EXTERNAL_PROVIDER_INSTRUCTIONS.join(`
4
4
  `),EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE),{kind:`external-provider`};if(n.kind===`inline-key`){l=n;break}let a=await withSpinner(r,`Checking your Vercel login…`,()=>o.getVercelAuthStatus(t,{signal:i}));if(i?.throwIfAborted(),s=a,vercelAuthBlockerReason(s)!==void 0){c=`own-key`;continue}return await o.runLinkFlow({appRoot:t,prompter:r,signal:i,projectSelection:`create-or-link`})}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}let u=l.key.trim(),d=l.validation;i?.throwIfAborted(),d.kind===`inconclusive`&&r.log.warning(`Couldn't reach the gateway to validate (${d.message}). Saving the key anyway.`);let f=await writeAiGatewayApiKey({projectRoot:t,apiKey:u,appendEnv:o.appendEnv});return r.log.success(`${f.envKey} set.`),{kind:`done`,resolution:{credential:`api-key`,source:{kind:`env-file`,path:f.envFile}}}}export{EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runProviderFlow};
@@ -0,0 +1,20 @@
1
+ import type { Prompter } from "#setup/prompter.js";
2
+ export interface RegistryFlowDeps {
3
+ browseRegistryCatalog: (typeof import("#cli/commands/registry.js"))["browseRegistryCatalog"];
4
+ getRegistryItemManifest: (typeof import("#cli/commands/registry.js"))["getRegistryItemManifest"];
5
+ installRegistryItem: (typeof import("#cli/commands/registry.js"))["installRegistryItem"];
6
+ }
7
+ export type RegistryFlowResult = {
8
+ kind: "done";
9
+ addedItems: readonly string[];
10
+ output?: readonly string[];
11
+ } | {
12
+ kind: "cancelled";
13
+ };
14
+ /** Runs the categorized interactive registry catalog used by the dev TUI's `/add`. */
15
+ export declare function runRegistryFlow(input: {
16
+ appRoot: string;
17
+ prompter: Prompter;
18
+ signal?: AbortSignal;
19
+ deps?: Partial<RegistryFlowDeps>;
20
+ }): Promise<RegistryFlowResult>;
@@ -0,0 +1 @@
1
+ import{WizardCancelledError}from"#setup/step.js";import{withSpinner}from"#setup/with-spinner.js";const ADDRESS_PREFIX=`address:`,BACK=`action:back`,DONE=`action:done`,ALL=`category:all`,REGISTRY_CATEGORIES=[{value:`category:channel`,prefix:`channel/`,label:`Chat channels`,hint:`Web, Slack, Discord, Teams`},{value:`category:connection`,prefix:`connection/`,label:`Tools & data`,hint:`Linear, Notion, GitHub, Vercel`},{value:`category:extension`,prefix:`extension/`,label:`Capabilities`,hint:`Browser automation, memory, developer tools`},{value:`category:instrumentation`,prefix:`instrumentation/`,label:`Observability`,hint:`Sentry, Braintrust, Honeycomb`}];function itemLabel(e){return(e.name.split(`/`).at(-1)??e.name).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function itemRows(e){return e.map((e,t)=>({value:`item:${t}`,label:itemLabel(e),hint:e.description??e.type}))}function categoryRows(){return[...REGISTRY_CATEGORIES.map(e=>({value:e.value,label:e.label,hint:e.hint})),{value:ALL,label:`All integrations`,hint:`Search by name or enter an item address`},{value:DONE,label:`Back to chat`,trailingAction:!0}]}function itemsForCategory(e,t){if(t===ALL)return e;let n=REGISTRY_CATEGORIES.find(e=>e.value===t);return n===void 0?e:e.filter(e=>e.address.startsWith(n.prefix)||e.name.startsWith(n.prefix))}function stringArray(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function itemSource(e){if(e.startsWith(`@`))return e.split(`/`)[0]??e;if(/^https?:\/\//u.test(e))try{return new URL(e).host}catch{return e}return`Vercel`}function manifestRecord(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:{}}function summarizeDetails(e,t=3){let n=e.slice(0,t),r=e.length-n.length;return r>0?`${n.join(`, `)} … (+${r} more)`:n.join(`, `)}function itemDetails(e,t){let n=[{label:`Source`,value:e.source}],r=[...stringArray(t.dependencies),...stringArray(t.devDependencies),...stringArray(t.registryDependencies)];r.length>0&&n.push({label:`Packages`,value:summarizeDetails(r)});let i=t.envVars;if(typeof i==`object`&&i&&!Array.isArray(i)){let e=Object.keys(i);e.length>0&&n.push({label:`Environment`,value:summarizeDetails(e)})}let a=(Array.isArray(t.files)?t.files:[]).flatMap(e=>{if(typeof e!=`object`||!e||Array.isArray(e))return[];let t=e.target;return typeof t==`string`?[t]:[]});return a.length>0&&n.push({label:`Files`,value:summarizeDetails(a)}),n}async function inspectItem(e,n,r,i,a,o){let s=a??manifestRecord(await withSpinner(e,`Loading registry item…`,()=>n.getRegistryItemManifest(r,i.address)));for(;;){let t={message:typeof s.title==`string`?s.title:i.name,metadata:itemDetails(i,s),options:[{value:`add`,label:`Add to project`},{value:`back`,label:`Back`}]},a=typeof s.description==`string`?s.description:i.description;if(a!==void 0&&(t.description=a),await e.select(t)===`back`)return{kind:`back`};let c=e.log.spinner?.(`Installing ${itemLabel(i)} and dependencies…`);try{c?.stop();let install=()=>n.installRegistryItem(r,i.address,{silent:!0,prompter:e,signal:o});return{kind:`added`,output:await(e.withExclusiveTerminal?.(install)??install())}}finally{c?.stop()}}}async function resolveAddressItem(e,n,r,i){let a=manifestRecord(await withSpinner(e,`Loading registry item…`,()=>n.getRegistryItemManifest(r,i))),o={address:i,name:typeof a.name==`string`?a.name:i,source:itemSource(i)};return typeof a.type==`string`&&(o.type=a.type),typeof a.description==`string`&&(o.description=a.description),{item:o,manifest:a}}async function runRegistryFlow(a){let o;(a.deps?.browseRegistryCatalog===void 0||a.deps.getRegistryItemManifest===void 0||a.deps.installRegistryItem===void 0)&&(o=await import(`#cli/commands/registry.js`));let s={browseRegistryCatalog:a.deps?.browseRegistryCatalog??o.browseRegistryCatalog,getRegistryItemManifest:a.deps?.getRegistryItemManifest??o.getRegistryItemManifest,installRegistryItem:a.deps?.installRegistryItem??o.installRegistryItem},c=[];try{for(;;){a.signal?.throwIfAborted();let e=await withSpinner(a.prompter,`Loading registry…`,()=>s.browseRegistryCatalog(a.appRoot));c=[...c,...e.errors.map(e=>({tone:`warning`,text:`${e.registry}: ${e.message}`}))];let o=await a.prompter.select({message:``,options:categoryRows(),hintLayout:`inline`,notices:c});if(c=[],o===DONE)return{kind:`done`,addedItems:[]};let l=itemsForCategory(e.items,o),u=itemRows(l);u.push({value:BACK,label:`Back`,trailingAction:!0});let d=await a.prompter.select({message:`Browse registry integrations`,options:u,search:!0,placeholder:`Search or enter an item address`,searchAction:{label:e=>`Add “${e}”`,value:e=>`${ADDRESS_PREFIX}${e.trim()}`},hintLayout:`inline`});if(d===BACK)continue;let f=d.startsWith(ADDRESS_PREFIX)?await resolveAddressItem(a.prompter,s,a.appRoot,d.slice(8)):{item:l[Number(d.slice(5))]};if(f.item===void 0)throw Error(`The selected registry item is no longer available.`);let p=await inspectItem(a.prompter,s,a.appRoot,f.item,`manifest`in f?f.manifest:void 0,a.signal);if(p.kind===`added`)return p.output.length===0?{kind:`done`,addedItems:[f.item.address]}:{kind:`done`,addedItems:[f.item.address],output:p.output}}}catch(t){if(t instanceof WizardCancelledError)return{kind:`cancelled`};throw t}}export{runRegistryFlow};
@@ -4,7 +4,6 @@ export { type AiGatewayEnvFile, type ArgsHeadlessAiGateway, type ArgsHeadlessPro
4
4
  export { type AnySetupBox, runHeadless, runInteractive, type RunnerOptions, type RunResult, } from "./runner.js";
5
5
  export { createPrompter, type MultiSelectOptions, type NoteTone, type Prompter, type PrompterValue, type SelectCommonOptions, type SelectOption, type SingleSelectOptions, } from "./prompter.js";
6
6
  export { createHeadlessPrompter, formatHeadlessEvent, type HeadlessEvent, type HeadlessLogSink, type HeadlessNextStep, HeadlessPromptError, } from "./headless.js";
7
- export { composeOnboardingBoxes, type OnboardingBoxesOptions } from "./onboarding.js";
8
7
  export { createPromptCommandOutput, type PromptCommandLog } from "./cli/index.js";
9
8
  export { getPackageManagerStrategy, runPackageManagerInstall, runPnpmInstall, runVercel, spawnPackageManager, spawnPnpm, type PackageManagerStrategy, type RunPackageManagerOptions, type RunPnpmOptions, type RunVercelOptions, } from "./primitives/index.js";
10
9
  export { detectDeployment, detectProjectResolution, projectProductionUrlFromResolution, type DeploymentInfo, type DeploymentState, type ProjectResolution, } from "./project-resolution.js";
@@ -1 +1 @@
1
- import{InteractionRequired}from"./ask.js";import{runVercel}from"./primitives/run-vercel.js";import{detectDeployment,detectProjectResolution,projectProductionUrlFromResolution}from"./project-resolution.js";import{provisionSlackbot,reconcileSlackUid}from"./slackbot.js";import{createDefaultSetupState,requireProjectPath,snapshotSetupState}from"./state.js";import{WizardCancelledError}from"./step.js";import{setupConnectionConnector}from"./connection-connector.js";import{getPackageManagerStrategy}from"./primitives/pm/index.js";import{linkProject,requireAuth,resolveProjectByNameOrId,resolveTeam}from"./vercel-project.js";import{runVercelEnvPull}from"./run-vercel-link.js";import{runHeadless,runInteractive}from"./runner.js";import{createPromptCommandOutput}from"./cli/command-output.js";import"./cli/index.js";import{HeadlessPromptError,createHeadlessPrompter,formatHeadlessEvent}from"./headless.js";import{createPrompter}from"./prompter.js";import{composeOnboardingBoxes}from"./onboarding.js";import{runPackageManagerInstall,runPnpmInstall,spawnPackageManager,spawnPnpm}from"./primitives/pm/run.js";import"./primitives/index.js";export{HeadlessPromptError,InteractionRequired,WizardCancelledError,composeOnboardingBoxes,createDefaultSetupState,createHeadlessPrompter,createPromptCommandOutput,createPrompter,detectDeployment,detectProjectResolution,formatHeadlessEvent,getPackageManagerStrategy,linkProject,projectProductionUrlFromResolution,provisionSlackbot,reconcileSlackUid,requireAuth,requireProjectPath,resolveProjectByNameOrId,resolveTeam,runHeadless,runInteractive,runPackageManagerInstall,runPnpmInstall,runVercel,runVercelEnvPull,setupConnectionConnector,snapshotSetupState,spawnPackageManager,spawnPnpm};
1
+ import{InteractionRequired}from"./ask.js";import{runVercel}from"./primitives/run-vercel.js";import{detectDeployment,detectProjectResolution,projectProductionUrlFromResolution}from"./project-resolution.js";import{runVercelEnvPull}from"./run-vercel-link.js";import{createDefaultSetupState,requireProjectPath,snapshotSetupState}from"./state.js";import{getPackageManagerStrategy}from"./primitives/pm/index.js";import{linkProject,requireAuth,resolveProjectByNameOrId,resolveTeam}from"./vercel-project.js";import{createPromptCommandOutput}from"./cli/command-output.js";import"./cli/index.js";import{setupConnectionConnector}from"./connection-connector.js";import{WizardCancelledError}from"./step.js";import{runHeadless,runInteractive}from"./runner.js";import{HeadlessPromptError,createHeadlessPrompter,formatHeadlessEvent}from"./headless.js";import{createPrompter}from"./prompter.js";import{runPackageManagerInstall,runPnpmInstall,spawnPackageManager,spawnPnpm}from"./primitives/pm/run.js";import"./primitives/index.js";import{provisionSlackbot,reconcileSlackUid}from"./slackbot.js";export{HeadlessPromptError,InteractionRequired,WizardCancelledError,createDefaultSetupState,createHeadlessPrompter,createPromptCommandOutput,createPrompter,detectDeployment,detectProjectResolution,formatHeadlessEvent,getPackageManagerStrategy,linkProject,projectProductionUrlFromResolution,provisionSlackbot,reconcileSlackUid,requireAuth,requireProjectPath,resolveProjectByNameOrId,resolveTeam,runHeadless,runInteractive,runPackageManagerInstall,runPnpmInstall,runVercel,runVercelEnvPull,setupConnectionConnector,snapshotSetupState,spawnPackageManager,spawnPnpm};
@@ -1,5 +1,5 @@
1
- import type { ProjectResolution } from "./project-resolution.js";
2
- import type { VercelAuthStatus } from "./vercel-project.js";
1
+ import type { ProjectResolution } from "../../project-resolution.js";
2
+ import type { VercelAuthStatus } from "../../vercel-project.js";
3
3
  /** Read-only hosting facts available to channel-owned setup hooks. */
4
4
  export interface ChannelSetupEnvironment {
5
5
  vercel: {
@@ -0,0 +1 @@
1
+ function describeChannelSetupEnvironment(e){if(e.vercel.kind===`available`)switch(e.vercel.project.kind){case`deployed`:return`Found an authenticated Vercel account and deployed project (${e.vercel.project.productionUrl}).`;case`linked`:return`Found an authenticated Vercel account and linked project.`;case`unresolved`:return`Found an authenticated Vercel account; this directory is not linked to a project.`}switch(e.vercel.reason){case`logged-out`:return`No authenticated Vercel account found; choose Vercel Connect or portable credentials.`;case`cli-missing`:return`Vercel CLI not found; choose Vercel Connect or portable credentials.`;case`unavailable`:return`Could not verify the Vercel account; choose Vercel Connect or portable credentials.`}}function channelSetupEnvironment(e,t){return e===`authenticated`?{vercel:{kind:`available`,project:t}}:{vercel:{kind:`unavailable`,reason:e}}}export{channelSetupEnvironment,describeChannelSetupEnvironment};
@@ -1,7 +1,7 @@
1
- import type { ChannelSetupIntegration } from "./channel-setup-integration.js";
2
- import type { ChannelKind } from "./scaffold/index.js";
1
+ import type { ChannelSetupIntegration } from "./types.js";
2
+ import type { ChannelKind } from "../../scaffold/index.js";
3
3
  /** Built-in channel integrations in canonical picker order. */
4
4
  export declare const CHANNEL_SETUP_INTEGRATIONS: readonly ChannelSetupIntegration[];
5
5
  /** Resolves a channel setup integration by its filesystem-facing kind. */
6
6
  export declare function channelSetupIntegration(kind: ChannelKind): ChannelSetupIntegration;
7
- export { createChannelSetupUi } from "./channel-setup-ui.js";
7
+ export { createChannelSetupUi } from "./ui.js";
@@ -0,0 +1 @@
1
+ import{SLACK_CHANNEL_SETUP}from"./slack.js";import{WEB_CHANNEL_SETUP}from"./web.js";import{createChannelSetupUi}from"./ui.js";const CHANNEL_SETUP_INTEGRATIONS=[WEB_CHANNEL_SETUP,SLACK_CHANNEL_SETUP];function channelSetupIntegration(e){let t=CHANNEL_SETUP_INTEGRATIONS.find(t=>t.kind===e);if(t===void 0)throw Error(`No channel setup integration for "${e}".`);return t}export{CHANNEL_SETUP_INTEGRATIONS,channelSetupIntegration,createChannelSetupUi};
@@ -1,4 +1,4 @@
1
- import type { ChannelSetupContext, ChannelSetupResult } from "./channel-setup-integration.js";
1
+ import type { ChannelSetupContext, ChannelSetupResult } from "./types.js";
2
2
  /** Runs the shared scaffold box with decisions supplied by a channel integration. */
3
3
  export declare function runChannelSetup(context: ChannelSetupContext, options: {
4
4
  configureVercelServices?: boolean;
@@ -0,0 +1 @@
1
+ import{runInteractive}from"../../runner.js";import{addChannels}from"./setup.js";async function runChannelSetup(t,n){let r=await runInteractive([addChannels({asker:t.ui.asker,prompter:t.ui.prompter,headless:t.headless,presetCreateSlackbot:t.presetCreateSlackbot,force:t.force,configureVercelServices:n.configureVercelServices,slackCredentials:n.slackCredentials,ensureLinkedProject:n.ensureLinkedProject,skipDependencyMutation:t.skipDependencyMutation,deps:t.deps})],t.state,{write:e=>t.ui.prompter.log.message(e)},{signal:t.signal});return r.kind===`done`?{kind:`done`,state:r.state}:{kind:`cancelled`}}export{runChannelSetup};
@@ -1,13 +1,28 @@
1
1
  import { deriveSlackConnectorSlug, ensureChannel, type ChannelKind, type EvePackageContract } from "#setup/scaffold/index.js";
2
2
  import { detectPackageManager } from "#setup/package-manager.js";
3
3
  import { runPackageManagerInstall } from "#setup/primitives/pm/run.js";
4
- import { runVercel } from "#setup/primitives/run-vercel.js";
5
- import { detectDeployment, type ProjectResolution } from "../project-resolution.js";
6
- import type { Asker } from "../ask.js";
7
- import type { Prompter } from "../prompter.js";
8
- import { provisionSlackbot, reconcileSlackUid } from "../slackbot.js";
9
- import { type SetupState } from "../state.js";
10
- import { type SetupBox } from "../step.js";
4
+ import { ensureVercelProject } from "#setup/flows/ensure-vercel-project.js";
5
+ import { type ProjectResolution } from "../../project-resolution.js";
6
+ import type { Asker } from "../../ask.js";
7
+ import type { Prompter } from "../../prompter.js";
8
+ import { provisionSlackbot, reconcileSlackUid } from "../../slackbot.js";
9
+ import { type SetupBox } from "../../step.js";
10
+ /** State required by channel setup, kept narrow so the integration can move packages. */
11
+ export interface AddChannelsState {
12
+ projectPath: string | {
13
+ kind: "unresolved";
14
+ inPlace: boolean;
15
+ } | {
16
+ kind: "resolved";
17
+ inPlace: boolean;
18
+ path: string;
19
+ };
20
+ project: ProjectResolution;
21
+ channelSelection: ChannelKind[];
22
+ channels: ChannelKind[];
23
+ webScaffolded: boolean;
24
+ slackScaffolded: boolean;
25
+ }
11
26
  /** Injected for tests; defaults to the real scaffold, Connect, and Vercel effects. */
12
27
  export interface AddChannelsDeps {
13
28
  ensureChannel: typeof ensureChannel;
@@ -16,8 +31,7 @@ export interface AddChannelsDeps {
16
31
  reconcileSlackUid: typeof reconcileSlackUid;
17
32
  detectPackageManager: typeof detectPackageManager;
18
33
  runPackageManagerInstall: typeof runPackageManagerInstall;
19
- runVercel: typeof runVercel;
20
- detectDeployment: typeof detectDeployment;
34
+ ensureVercelProject: typeof ensureVercelProject;
21
35
  }
22
36
  export interface AddChannelsOptions {
23
37
  /** Resolves the slackbot question; the composed stack decides how. */
@@ -41,7 +55,7 @@ export interface AddChannelsOptions {
41
55
  evePackage?: EvePackageContract;
42
56
  /** Reuse the preferred existing Slack connector without prompting. */
43
57
  presetCreateSlackbot?: boolean;
44
- /** Overwrite existing channel files (`eve channels add --force`). */
58
+ /** Overwrite existing channel files (`eve add --overwrite channel/slack`). */
45
59
  force?: boolean;
46
60
  /** Credential source for Slack. Defaults to Vercel Connect. */
47
61
  slackCredentials?: "vercel-connect" | "environment";
@@ -53,17 +67,15 @@ export interface AddChannelsOptions {
53
67
  configureVercelServices?: boolean;
54
68
  /**
55
69
  * Opt-in fallback when Slack is chosen interactively but `state.project` is
56
- * unresolved: run the interactive bare `vercel link` before provisioning the
57
- * slackbot. Only the `eve channels add` composition sets this; onboarding
58
- * resolves the project up front via the link box and keeps the hard gate.
70
+ * unresolved: link the project before provisioning the slackbot. The Slack
71
+ * integration sets this so Vercel Connect setup can link an unlinked project.
59
72
  */
60
73
  ensureLinkedProject?: "interactive-vercel-link";
61
74
  /**
62
75
  * What a failed slackbot provision (create or attach) does to the run. The
63
- * default, "abort", fails the whole box — right for `eve channels add slack`,
64
- * where Slack is the point. Onboarding passes "warn-and-continue": the agent
65
- * still scaffolds, deploys, and chats without Slack (recorded as nothing, so
66
- * a later `eve channels add slack` starts clean).
76
+ * default, "abort", fails the whole box — right for `eve add channel/slack`,
77
+ * where Slack is the point. "warn-and-continue" records nothing so a later
78
+ * `eve add channel/slack` starts clean.
67
79
  */
68
80
  slackbotFailure?: "abort" | "warn-and-continue";
69
81
  deps?: AddChannelsDeps;
@@ -98,8 +110,7 @@ export interface AddChannelsPayload {
98
110
  slackScaffolded: boolean;
99
111
  /**
100
112
  * Whether the post-scaffold dependency install succeeded. False both when no
101
- * channels were recorded (nothing ran) and when the install failed; only a
102
- * success lets `apply` mark the deploy-time install as already done.
113
+ * channels were recorded and when the install failed.
103
114
  */
104
115
  dependenciesChanged: boolean;
105
116
  dependenciesInstalled: boolean;
@@ -107,8 +118,7 @@ export interface AddChannelsPayload {
107
118
  slackbot?: AddChannelsSlackbotFacts;
108
119
  }
109
120
  /**
110
- * THE CHANNEL SCAFFOLD BOX. Scaffolds the channels chosen up front by the
111
- * select-channels box (`state.channelSelection`): writes the Web Chat files,
121
+ * Channel integration setup. Scaffolds the requested channel: writes the Web Chat files,
112
122
  * provisions the Slackbot through Vercel Connect, writes the Slack channel
113
123
  * definition, reconciles a Connect-assigned connector UID, and installs the
114
124
  * dependencies the scaffold added to `package.json` so a running `eve dev`
@@ -117,4 +127,4 @@ export interface AddChannelsPayload {
117
127
  * and reads `state.project` directly, resolved earlier by the link box or the
118
128
  * in-project seed.
119
129
  */
120
- export declare function addChannels(options: AddChannelsOptions): SetupBox<SetupState, AddChannelsInput, AddChannelsPayload>;
130
+ export declare function addChannels<State extends AddChannelsState = AddChannelsState>(options: AddChannelsOptions): SetupBox<State, AddChannelsInput, AddChannelsPayload>;
@@ -0,0 +1,2 @@
1
+ import{isProjectResolved,mergeProjectResolution}from"../../project-resolution.js";import{WizardCancelledError}from"../../step.js";import{provisionSlackbot,reconcileSlackUid}from"../../slackbot.js";import{deriveSlackConnectorSlug,ensureChannel}from"#setup/scaffold/index.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectPackageManager}from"#setup/package-manager.js";import{HumanActionRequiredError}from"#setup/human-action.js";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{runPackageManagerInstall}from"#setup/primitives/pm/run.js";import{ensureVercelProject}from"#setup/flows/ensure-vercel-project.js";function slackbotFailureCopy(e){switch(e.state){case`not-installed`:return{reason:`Slackbot is not connected to a Slack workspace. Slack channel was not added.`,followUp:"Continuing without Slack — the install timed out and was cleaned up; re-run `eve add channel/slack` to try again."};case`cleanup-failed`:return{reason:`The abandoned Slack connector could not be removed. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the cleanup warning above before trying again.`};case`connector-lookup-failed`:return{reason:`Existing Slack connectors could not be inspected. Slack channel was not added.`,followUp:"Continuing without Slack — restore Vercel CLI access, then re-run `eve add channel/slack`."};case`installation-check-failed`:return{reason:`Slack workspace installation could not be verified. Slack channel was not added.`,followUp:"Continuing without Slack — verify Vercel Connect is reachable, then re-run `eve add channel/slack`."};case`existing-not-installed`:return{reason:`The existing Slack connector is not connected to a Slack workspace. Slack channel was not added.`,followUp:`Continuing without Slack — resolve the existing connector warning above before trying again.`};case`detach-failed`:return{reason:`Slackbot provisioning could not replace the existing trigger destination. Slack channel was not added.`,followUp:"Continuing without Slack — run the `vercel connect detach` and `vercel connect attach` commands above."};case`attach-failed`:return{reason:`Slackbot provisioning did not attach this project. Slack channel was not added.`,followUp:"Continuing without Slack — finish event delivery with the `vercel connect attach` command above."};case`create-failed`:return{reason:`Slackbot creation failed.`,followUp:"Continuing without Slack — add it later with `eve add channel/slack`."}}}function warnOverwrittenFiles(e,t){for(let n of t??[])e.warning(`Overwrote ${n}`)}function warnCompetingNextConfigFiles(e,t){for(let n of t??[])e.warning(`Found competing Next.js config at ${n}; merge any needed settings into next.config.ts and remove it before starting the preview, or Next.js may ignore the generated eve rewrite.`)}function addChannels(f){let p=f.deps??{ensureChannel,deriveSlackConnectorSlug,provisionSlackbot,reconcileSlackUid,detectPackageManager,runPackageManagerInstall,ensureVercelProject};async function scaffoldSlackChannel(e,t,n,r,i,a){let o=!1;if(!t.slackScaffolded){let t=await p.ensureChannel({projectRoot:n,kind:`slack`,slackConnectorUid:a,slackConnectorSlug:r,force:f.force,skipDependencyMutation:f.skipDependencyMutation});i.dependenciesChanged||=t.packageJsonUpdated.length>0,warnOverwrittenFiles(e,t.filesOverwritten),t.action===`created`||t.action===`overwritten`?e.success(`Scaffolded channel: slack`):e.info(`Channel "slack" already exists. Skipping file creation.`),o=t.action!==`skipped`,i.slackScaffolded=!0}return i.channelsAdded.push(`slack`),o}async function addWebChannelToPayload(t,n,r,i,a,o){if(!n.channelSelection.includes(`web`))return;if(n.webScaffolded){a.channelsAdded.push(`web`);return}t.message(`Scaffolding Web Chat channel files...`);let c={projectRoot:r,kind:`web`,packageManager:i,force:f.force,configureVercelServices:f.configureVercelServices??isProjectResolved(n.project),skipDependencyMutation:f.skipDependencyMutation};f.evePackage!==void 0&&(c.webPackageVersions={evePackage:f.evePackage});let l=await p.ensureChannel(c);if(a.dependenciesChanged||=l.packageJsonUpdated.length>0,o?.throwIfAborted(),warnOverwrittenFiles(t,l.filesOverwritten),l.kind===`web`&&l.action!==`skipped`&&l.nodeEngineOverride!==void 0&&t.warning(formatNodeEngineOverrideWarning(l.nodeEngineOverride)),warnCompetingNextConfigFiles(t,`competingNextConfigFiles`in l?l.competingNextConfigFiles:void 0),l.action===`created`||l.action===`overwritten`){t.success(`Scaffolded channel: web`),a.webScaffolded=!0,a.channelsAdded.push(`web`);return}t.info(`Next.js project detected. Skipping Web Chat scaffolding.`)}function assertSlackProjectReady(t){if(f.ensureLinkedProject===void 0){if(!isProjectResolved(t.project))throw Error(`Slack setup with Vercel Connect requires a linked Vercel project.`);if(!isProjectResolved(t.project))throw Error(`Expected a linked Vercel project for Slack, but none was resolved.`)}}async function provisionSlackbotWithControls(e,t,n,r){let i={selectConnector:async(e,t)=>{if(f.presetCreateSlackbot===!0)return t??e[0];let n={message:`Which Slack app would you like to use?`,options:[...e.map(e=>{let n={value:e.uid,label:`Use ${e.uid}`};return e.uid===t?.uid&&(n.hint=`Matches this agent`),n}),{value:`create`,label:`Create a new Slack app`}],initialValue:t?.uid},r=await f.prompter.select(n);return r===`create`?`create`:e.find(e=>e.uid===r)}};return r!==void 0&&(i.signal=r),f.prompter.awaitChoice!==void 0&&(i.awaitChoice=f.prompter.awaitChoice),p.provisionSlackbot(e,t,n,void 0,i)}async function scaffoldAttachedSlackChannel(e,t,n,r,i,a){if(!await scaffoldSlackChannel(e,t,n,r,i,a.connectorUid)&&!await p.reconcileSlackUid(e,n,a,`slack/${r}`))throw Error(`Slack connector UID update is required before deployment.`)}async function addSlackChannelToPayload(r,i,a,o,s,c){if(!i.channelSelection.includes(`slack`))return;let u=await p.deriveSlackConnectorSlug(o);if(f.slackCredentials===`environment`){if(!i.slackScaffolded){let e=await p.ensureChannel({projectRoot:o,kind:`slack`,slackConnectorSlug:u,slackCredentials:`environment`,force:f.force,skipDependencyMutation:f.skipDependencyMutation});s.dependenciesChanged||=e.packageJsonUpdated.length>0,warnOverwrittenFiles(r,e.filesOverwritten),e.action===`created`||e.action===`overwritten`?r.success(`Scaffolded channel: slack`):r.info(`Channel "slack" already exists. Skipping file creation.`),s.slackScaffolded=!0}s.channelsAdded.push(`slack`);return}if(assertSlackProjectReady(i),!isProjectResolved(s.project)){if(a.headless)throw new HumanActionRequiredError({kind:`vercel-link`,command:`vercel link`,reason:`Slackbot creation needs this directory linked to a Vercel project.`});let e=await p.ensureVercelProject({appRoot:o,prompter:f.prompter,signal:c});s.project=mergeProjectResolution(s.project,{kind:`linked`,projectId:e.projectId})}let d=await provisionSlackbotWithControls(r,o,u,c);if(c?.throwIfAborted(),d.state===`cancelled`)throw new WizardCancelledError;if(d.state!==`attached`){let e=slackbotFailureCopy(d);if(f.slackbotFailure!==`warn-and-continue`)throw Error(e.reason);r.warning(`${e.reason} ${e.followUp}`);return}s.slackbot={connectorUid:d.connectorUid,chatUrl:d.chatUrl,workspaceName:d.workspaceName},await scaffoldAttachedSlackChannel(r,i,o,u,s,d)}async function installChannelDependencies(e,t,n,r,i){if(!(f.skipDependencyMutation||!r.dependenciesChanged)){if(await withPhase(e,`Installing channel dependencies (${n} install)...`,()=>p.runPackageManagerInstall(n,t,{onOutput:createPromptCommandOutput(e),signal:i}))){r.dependenciesInstalled=!0;return}e.warning(`Dependency installation failed. The new channels stay unloadable until \`${n} install\` or a deploy succeeds.`)}}async function performAddChannels(e,t,n){n?.throwIfAborted();let r=f.prompter.log,i=typeof e.projectPath==`string`?e.projectPath:e.projectPath.kind===`resolved`?e.projectPath.path:void 0;if(i===void 0)throw Error(`Project path has not been resolved.`);let a={channelsAdded:[],webScaffolded:e.webScaffolded,slackScaffolded:e.slackScaffolded,dependenciesChanged:!1,dependenciesInstalled:!1,project:e.project},o=await p.detectPackageManager(i);return await addWebChannelToPayload(r,e,i,o.kind,a,n),await addSlackChannelToPayload(r,e,t,i,a,n),await installChannelDependencies(r,i,o.kind,a,n),a}return{id:`add-channels`,async gather({state:e}){let t=f.headless??!1;if(t&&e.channelSelection.includes(`slack`)&&f.slackCredentials!==`environment`)throw Error("Slack setup is interactive. Run `eve add channel/slack` from an interactive terminal.");return{headless:t,createSlackbot:f.presetCreateSlackbot}},async perform({state:e,input:t,signal:r}){try{return await performAddChannels(e,t,r)}catch(e){if(!(e instanceof WizardCancelledError)){let t=e instanceof Error?e.message:String(e),n=t.split(`
2
+ `)[0]?.trim()??t;f.prompter.log.error(n)}throw e}},apply(e,n){let r=[...e.channels];for(let e of n.channelsAdded)r.includes(e)||r.push(e);let i={...e,channels:r,webScaffolded:n.webScaffolded,slackScaffolded:n.slackScaffolded,project:mergeProjectResolution(e.project,n.project)};return n.slackbot,i}}}export{addChannels};
@@ -1,3 +1,3 @@
1
- import type { ChannelSetupIntegration } from "./channel-setup-integration.js";
1
+ import type { ChannelSetupIntegration } from "./types.js";
2
2
  /** Slack's channel-owned credential choice, provisioning, and scaffold behavior. */
3
3
  export declare const SLACK_CHANNEL_SETUP: ChannelSetupIntegration;
@@ -0,0 +1 @@
1
+ import{WizardCancelledError}from"../../step.js";import{runChannelSetup}from"./runner.js";async function choosePortableCredentials(t){if(t.presetPortableCredentials!==void 0)return t.presetPortableCredentials?`environment`:`vercel-connect`;try{return await t.ui.prompter.select({message:`How would you like to configure Slack?`,options:[{value:`vercel`,label:`Set up Vercel Connect`,hint:`Sign in and link this project`},{value:`portable`,label:`Use portable credentials`,hint:`Read Slack tokens from environment variables`}]})===`portable`?`environment`:`vercel-connect`}catch(t){if(t instanceof WizardCancelledError)return`cancelled`;throw t}}const SLACK_CHANNEL_SETUP={kind:`slack`,label:`Slack`,hint:`Slack app mentions and DMs`,async setup(e){let n=await choosePortableCredentials(e);if(n===`cancelled`)return{kind:`cancelled`};if(n===`vercel-connect`&&e.environment.vercel.kind===`unavailable`)throw Error("Vercel Connect requires an authenticated Vercel CLI. Run `vercel login`, then retry Slack setup.");let r=await runChannelSetup(e,n===`environment`?{slackCredentials:`environment`}:{slackCredentials:`vercel-connect`,ensureLinkedProject:`interactive-vercel-link`});return r.kind===`done`&&n===`environment`&&r.state.channels.includes(`slack`)&&e.ui.nextSteps([`Set SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in .env.local (listed in .env.example).`,`Configure your Slack app to send events to /eve/v1/slack on your public agent URL.`]),r}};export{SLACK_CHANNEL_SETUP};
@@ -1,12 +1,28 @@
1
- import type { AddChannelsDeps } from "./boxes/add-channels.js";
2
- import type { ChannelSetupEnvironment } from "./channel-setup-environment.js";
3
- import type { ChannelSetupUi } from "./channel-setup-ui.js";
4
- import type { ChannelKind } from "./scaffold/index.js";
5
- import type { SetupState } from "./state.js";
1
+ import type { AddChannelsDeps } from "./setup.js";
2
+ import type { ChannelSetupEnvironment } from "./environment.js";
3
+ import type { ChannelSetupUi } from "./ui.js";
4
+ import type { ChannelKind } from "../../scaffold/index.js";
5
+ import type { ProjectResolution } from "../../project-resolution.js";
6
+ /** Narrow state owned by one channel setup invocation. */
7
+ export interface ChannelSetupState {
8
+ readonly projectPath: string | {
9
+ kind: "unresolved";
10
+ inPlace: boolean;
11
+ } | {
12
+ kind: "resolved";
13
+ inPlace: boolean;
14
+ path: string;
15
+ };
16
+ readonly project: ProjectResolution;
17
+ readonly channelSelection: ChannelKind[];
18
+ readonly channels: ChannelKind[];
19
+ readonly webScaffolded: boolean;
20
+ readonly slackScaffolded: boolean;
21
+ }
6
22
  /** Shared inputs available to a channel-owned setup implementation. */
7
23
  export interface ChannelSetupContext {
8
24
  readonly environment: ChannelSetupEnvironment;
9
- readonly state: Readonly<SetupState>;
25
+ readonly state: Readonly<ChannelSetupState>;
10
26
  readonly ui: ChannelSetupUi;
11
27
  readonly signal?: AbortSignal;
12
28
  readonly force?: boolean;
@@ -20,7 +36,7 @@ export interface ChannelSetupContext {
20
36
  /** Structured outcome from a channel-owned setup implementation. */
21
37
  export type ChannelSetupResult = {
22
38
  readonly kind: "done";
23
- readonly state: SetupState;
39
+ readonly state: ChannelSetupState;
24
40
  } | {
25
41
  readonly kind: "cancelled";
26
42
  };
@@ -1,5 +1,5 @@
1
- import { type Asker } from "./ask.js";
2
- import type { Prompter } from "./prompter.js";
1
+ import { type Asker } from "../../ask.js";
2
+ import type { Prompter } from "../../prompter.js";
3
3
  /** UI capabilities available to a channel-owned setup hook. */
4
4
  export interface ChannelSetupUi {
5
5
  readonly asker: Asker;
@@ -0,0 +1,2 @@
1
+ import{SkippedSignal,confirm}from"../../ask.js";function createChannelSetupUi(n){return{...n,async confirm(r){try{return await n.asker.ask(confirm(r))}catch(t){if(t instanceof SkippedSignal)return!1;throw t}},nextSteps(e){e.length!==0&&n.prompter.note(e.join(`
2
+ `),`Next steps`,{tone:`success`})}}}export{createChannelSetupUi};
@@ -1,3 +1,3 @@
1
- import type { ChannelSetupIntegration } from "./channel-setup-integration.js";
1
+ import type { ChannelSetupIntegration } from "./types.js";
2
2
  /** Web Chat's channel-owned setup behavior. */
3
3
  export declare const WEB_CHANNEL_SETUP: ChannelSetupIntegration;
@@ -0,0 +1 @@
1
+ import{runChannelSetup}from"./runner.js";const WEB_CHANNEL_SETUP={kind:`web`,label:`Web Chat`,hint:`Browser-based chat interface`,setup(e){return runChannelSetup(e,{configureVercelServices:e.environment.vercel.kind===`available`})}};export{WEB_CHANNEL_SETUP};
@@ -35,6 +35,7 @@ export declare function runVercel(args: string[], options: RunVercelOptions): Pr
35
35
  export interface RunVercelCaptureResult {
36
36
  ok: boolean;
37
37
  stdout: string;
38
+ stderr?: string;
38
39
  }
39
40
  /**
40
41
  * Runs an interactive Vercel CLI command while capturing its stdout.
@@ -1 +1 @@
1
- import{withoutCodingAgentMarkers}from"./coding-agent-env.js";import{createProcessOutputBuffer}from"./process-output.js";import{armProcessAbort}from"./process-abort.js";import{accessSync,constants,existsSync,statSync}from"node:fs";import{dirname,join,resolve}from"node:path";import{spawn}from"node:child_process";const CONNECT_FEATURE_FLAG_ENV={FF_CONNECT_ENABLED:`1`},VERCEL_NOT_FOUND_MESSAGE=`Vercel CLI not found. Install with: npm i -g vercel@latest`;function buildSpawnEnv(t){return{...withoutCodingAgentMarkers(process.env),...CONNECT_FEATURE_FLAG_ENV,...t}}function commandArgs(e,t){return!t||e.includes(`--non-interactive`)?e:[...e,`--non-interactive`]}function existingDir(e){let t=resolve(e);for(;!existsSync(t);){let e=dirname(t);if(e===t)break;t=e}return t}function armDeadline(e,t,n){if(t===void 0)return()=>{};let r=setTimeout(()=>{n(),e.kill(`SIGTERM`);let t=setTimeout(()=>e.kill(`SIGKILL`),5e3);t.unref(),e.once(`close`,()=>clearTimeout(t))},t);return r.unref(),()=>clearTimeout(r)}function timeoutMessage(e,t){return`vercel ${e.join(` `)} timed out after ${Math.round(t/1e3)}s and was aborted.`}function abortMessage(e){return`vercel ${e.join(` `)} was aborted.`}function isAbortError(e,t){return t?.aborted===!0||e.name===`AbortError`||e.code===`ABORT_ERR`}function ancestorDirectories(e){let t=[],n=resolve(e);for(;;){t.push(n);let e=dirname(n);if(e===n)return t;n=e}}function findExecutable(e){try{if(accessSync(e,constants.F_OK|constants.X_OK),statSync(e).isFile())return e}catch{return}}function vercelExecutableNames(e){return e===`win32`?[`vercel.cmd`,`vercel.exe`]:[`vercel`]}function findLocalVercel(e,t){for(let n of ancestorDirectories(e))for(let e of vercelExecutableNames(t)){let t=findExecutable(join(n,`node_modules`,`.bin`,e));if(t!==void 0)return t}}function resolveVercelInvocation(e,t=[],n=process.platform){let r=findLocalVercel(e,n);return n===`win32`?{command:r??`vercel`,commandArgs:t,shell:!0}:r===void 0?{command:`vercel`,commandArgs:t}:{command:r,commandArgs:t}}function stdioForRun(e){return e.onOutput?[e.nonInteractive?`ignore`:`inherit`,`pipe`,`pipe`]:e.nonInteractive?[`ignore`,`pipe`,`pipe`]:`inherit`}async function runVercel(e,r){return r.signal?.aborted!==!0&&new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:stdioForRun(r),env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal);c.stdout?.on(`data`,e=>s?.write(`stdout`,e)),c.stderr?.on(`data`,e=>s?.write(`stderr`,e));let u=!1;function settle(e){u||(u=!0,s?.flush(),i(e))}function reportFailure(e){r.onOutput?r.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let d=armDeadline(c,r.timeoutMs,()=>{reportFailure(timeoutMessage(e,r.timeoutMs??0)),settle(!1)});c.on(`error`,t=>{isAbortError(t,r.signal)||(t.code===`ENOENT`?(l(),d(),reportFailure(VERCEL_NOT_FOUND_MESSAGE),settle(!1)):(l(),d(),reportFailure(`vercel ${e.join(` `)} failed: ${t.message}`),settle(!1)))}),c.on(`close`,t=>{if(l(),d(),r.signal?.aborted===!0){settle(!1);return}!u&&t!==0&&t!==null&&(s?.flush(),reportFailure(`vercel ${e.join(` `)} exited with code ${t}.`)),settle(t===0)})})}async function runVercelCaptureStdout(e,r){return r.signal?.aborted===!0?{ok:!1,stdout:``}:new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:[r.nonInteractive?`ignore`:`inherit`,`pipe`,r.onOutput?`pipe`:`inherit`],env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal),u=[];c.stdout?.on(`data`,e=>u.push(e.toString(`utf8`))),c.stderr?.on(`data`,e=>s?.write(`stderr`,e));let d=!1;function settle(e){d||(d=!0,s?.flush(),i({ok:e,stdout:u.join(``)}))}function reportFailure(e){r.onOutput?r.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let f=armDeadline(c,r.timeoutMs,()=>{reportFailure(timeoutMessage(e,r.timeoutMs??0)),settle(!1)});c.on(`error`,t=>{isAbortError(t,r.signal)||(l(),f(),reportFailure(t.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${e.join(` `)} failed: ${t.message}`),settle(!1))}),c.on(`close`,t=>{if(l(),f(),r.signal?.aborted===!0){settle(!1);return}!d&&t!==0&&t!==null&&reportFailure(`vercel ${e.join(` `)} exited with code ${t}.`),settle(t===0)})})}async function captureVercel(e,r){return r.signal?.aborted===!0?{ok:!1,failure:{errno:`ABORT_ERR`,stdout:``,stderr:``,message:abortMessage(e)}}:new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:[`ignore`,`pipe`,`pipe`],env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal),u=[],d=[];c.stdout?.on(`data`,e=>u.push(e.toString(`utf8`))),c.stderr?.on(`data`,e=>{d.push(e.toString(`utf8`)),s?.write(`stderr`,e)});let f=!1;function fail(e,t=!0){f||(f=!0,s?.flush(),t&&r.onOutput?.({stream:`stderr`,text:e.message}),i({ok:!1,failure:e}))}function succeed(){f||(f=!0,s?.flush(),i({ok:!0,stdout:u.join(``)}))}let p=armDeadline(c,r.timeoutMs,()=>{fail({code:null,stdout:u.join(``),stderr:d.join(``),message:timeoutMessage(e,r.timeoutMs??0)})});c.on(`error`,t=>{isAbortError(t,r.signal)||(l(),p(),fail({errno:t.code,stdout:u.join(``),stderr:d.join(``),message:t.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${e.join(` `)} failed: ${t.message}`}))}),c.on(`close`,t=>{if(l(),p(),r.signal?.aborted===!0){fail({errno:`ABORT_ERR`,stdout:u.join(``),stderr:d.join(``),message:abortMessage(e)},!1);return}if(t!==0&&t!==null){fail({code:t,stdout:u.join(``),stderr:d.join(``),message:`vercel ${e.join(` `)} exited with code ${t}.`});return}succeed()})})}export{captureVercel,resolveVercelInvocation,runVercel,runVercelCaptureStdout};
1
+ import{withoutCodingAgentMarkers}from"./coding-agent-env.js";import{createProcessOutputBuffer}from"./process-output.js";import{armProcessAbort}from"./process-abort.js";import{accessSync,constants,existsSync,statSync}from"node:fs";import{dirname,join,resolve}from"node:path";import{spawn}from"node:child_process";const CONNECT_FEATURE_FLAG_ENV={FF_CONNECT_ENABLED:`1`},VERCEL_NOT_FOUND_MESSAGE=`Vercel CLI not found. Install with: npm i -g vercel@latest`;function buildSpawnEnv(t){return{...withoutCodingAgentMarkers(process.env),...CONNECT_FEATURE_FLAG_ENV,...t}}function commandArgs(e,t){return!t||e.includes(`--non-interactive`)?e:[...e,`--non-interactive`]}function existingDir(e){let t=resolve(e);for(;!existsSync(t);){let e=dirname(t);if(e===t)break;t=e}return t}function armDeadline(e,t,n){if(t===void 0)return()=>{};let r=setTimeout(()=>{n(),e.kill(`SIGTERM`);let t=setTimeout(()=>e.kill(`SIGKILL`),5e3);t.unref(),e.once(`close`,()=>clearTimeout(t))},t);return r.unref(),()=>clearTimeout(r)}function timeoutMessage(e,t){return`vercel ${e.join(` `)} timed out after ${Math.round(t/1e3)}s and was aborted.`}function abortMessage(e){return`vercel ${e.join(` `)} was aborted.`}function isAbortError(e,t){return t?.aborted===!0||e.name===`AbortError`||e.code===`ABORT_ERR`}function ancestorDirectories(e){let t=[],n=resolve(e);for(;;){t.push(n);let e=dirname(n);if(e===n)return t;n=e}}function findExecutable(e){try{if(accessSync(e,constants.F_OK|constants.X_OK),statSync(e).isFile())return e}catch{return}}function vercelExecutableNames(e){return e===`win32`?[`vercel.cmd`,`vercel.exe`]:[`vercel`]}function findLocalVercel(e,t){for(let n of ancestorDirectories(e))for(let e of vercelExecutableNames(t)){let t=findExecutable(join(n,`node_modules`,`.bin`,e));if(t!==void 0)return t}}function resolveVercelInvocation(e,t=[],n=process.platform){let r=findLocalVercel(e,n);return n===`win32`?{command:r??`vercel`,commandArgs:t,shell:!0}:r===void 0?{command:`vercel`,commandArgs:t}:{command:r,commandArgs:t}}function stdioForRun(e){return e.onOutput?[e.nonInteractive?`ignore`:`inherit`,`pipe`,`pipe`]:e.nonInteractive?[`ignore`,`pipe`,`pipe`]:`inherit`}async function runVercel(e,r){return r.signal?.aborted!==!0&&new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:stdioForRun(r),env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal);c.stdout?.on(`data`,e=>s?.write(`stdout`,e)),c.stderr?.on(`data`,e=>s?.write(`stderr`,e));let u=!1;function settle(e){u||(u=!0,s?.flush(),i(e))}function reportFailure(e){r.onOutput?r.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let d=armDeadline(c,r.timeoutMs,()=>{reportFailure(timeoutMessage(e,r.timeoutMs??0)),settle(!1)});c.on(`error`,t=>{isAbortError(t,r.signal)||(t.code===`ENOENT`?(l(),d(),reportFailure(VERCEL_NOT_FOUND_MESSAGE),settle(!1)):(l(),d(),reportFailure(`vercel ${e.join(` `)} failed: ${t.message}`),settle(!1)))}),c.on(`close`,t=>{if(l(),d(),r.signal?.aborted===!0){settle(!1);return}!u&&t!==0&&t!==null&&(s?.flush(),reportFailure(`vercel ${e.join(` `)} exited with code ${t}.`)),settle(t===0)})})}async function runVercelCaptureStdout(e,r){return r.signal?.aborted===!0?{ok:!1,stdout:``,stderr:``}:new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:[r.nonInteractive?`ignore`:`inherit`,`pipe`,r.onOutput?`pipe`:`inherit`],env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal),u=[],d=[];c.stdout?.on(`data`,e=>u.push(e.toString(`utf8`))),c.stderr?.on(`data`,e=>{d.push(e.toString(`utf8`)),s?.write(`stderr`,e)});let f=!1;function settle(e){if(f)return;f=!0,s?.flush();let t=u.join(``),n=d.join(``);i(n.length===0?{ok:e,stdout:t}:{ok:e,stdout:t,stderr:n})}function reportFailure(e){r.onOutput?r.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let p=armDeadline(c,r.timeoutMs,()=>{reportFailure(timeoutMessage(e,r.timeoutMs??0)),settle(!1)});c.on(`error`,t=>{isAbortError(t,r.signal)||(l(),p(),reportFailure(t.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${e.join(` `)} failed: ${t.message}`),settle(!1))}),c.on(`close`,t=>{if(l(),p(),r.signal?.aborted===!0){settle(!1);return}!f&&t!==0&&t!==null&&reportFailure(`vercel ${e.join(` `)} exited with code ${t}.`),settle(t===0)})})}async function captureVercel(e,r){return r.signal?.aborted===!0?{ok:!1,failure:{errno:`ABORT_ERR`,stdout:``,stderr:``,message:abortMessage(e)}}:new Promise(i=>{let a=existingDir(r.cwd),o=resolveVercelInvocation(a,commandArgs(e,r.nonInteractive)),s=r.onOutput&&createProcessOutputBuffer(r.onOutput),c=spawn(o.command,o.commandArgs,{cwd:a,stdio:[`ignore`,`pipe`,`pipe`],env:buildSpawnEnv(r.extraEnv??{}),shell:o.shell,signal:r.signal}),l=armProcessAbort(c,r.signal),u=[],d=[];c.stdout?.on(`data`,e=>u.push(e.toString(`utf8`))),c.stderr?.on(`data`,e=>{d.push(e.toString(`utf8`)),s?.write(`stderr`,e)});let f=!1;function fail(e,t=!0){f||(f=!0,s?.flush(),t&&r.onOutput?.({stream:`stderr`,text:e.message}),i({ok:!1,failure:e}))}function succeed(){f||(f=!0,s?.flush(),i({ok:!0,stdout:u.join(``)}))}let p=armDeadline(c,r.timeoutMs,()=>{fail({code:null,stdout:u.join(``),stderr:d.join(``),message:timeoutMessage(e,r.timeoutMs??0)})});c.on(`error`,t=>{isAbortError(t,r.signal)||(l(),p(),fail({errno:t.code,stdout:u.join(``),stderr:d.join(``),message:t.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${e.join(` `)} failed: ${t.message}`}))}),c.on(`close`,t=>{if(l(),p(),r.signal?.aborted===!0){fail({errno:`ABORT_ERR`,stdout:u.join(``),stderr:d.join(``),message:abortMessage(e)},!1);return}if(t!==0&&t!==null){fail({code:t,stdout:u.join(``),stderr:d.join(``),message:`vercel ${e.join(` `)} exited with code ${t}.`});return}succeed()})})}export{captureVercel,resolveVercelInvocation,runVercel,runVercelCaptureStdout};