eve 0.25.3 → 0.26.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 (178) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/src/chunks/{use-eve-agent-Cy73lgA6.js → use-eve-agent-BkztZA0v.js} +76 -55
  3. package/dist/src/chunks/{use-eve-agent-CQIeqmKc.js → use-eve-agent-CruinZmd.js} +76 -55
  4. package/dist/src/cli/commands/logs-events.d.ts +36 -0
  5. package/dist/src/cli/commands/logs-events.js +2 -0
  6. package/dist/src/cli/commands/logs.d.ts +64 -0
  7. package/dist/src/cli/commands/logs.js +4 -0
  8. package/dist/src/cli/dev/diagnostic-dump.d.ts +60 -0
  9. package/dist/src/cli/dev/diagnostic-dump.js +1 -0
  10. package/dist/src/cli/dev/diagnostic-sink.d.ts +37 -0
  11. package/dist/src/cli/dev/diagnostic-sink.js +1 -0
  12. package/dist/src/cli/dev/diagnostics.d.ts +42 -0
  13. package/dist/src/cli/dev/diagnostics.js +1 -0
  14. package/dist/src/cli/dev/tui/blocks.d.ts +4 -0
  15. package/dist/src/cli/dev/tui/blocks.js +7 -7
  16. package/dist/src/cli/dev/tui/command-typeahead.js +1 -1
  17. package/dist/src/cli/dev/tui/diagnostic-presentation.d.ts +14 -0
  18. package/dist/src/cli/dev/tui/diagnostic-presentation.js +2 -0
  19. package/dist/src/cli/dev/tui/errors.d.ts +21 -16
  20. package/dist/src/cli/dev/tui/errors.js +1 -1
  21. package/dist/src/cli/dev/tui/line-editor.js +1 -1
  22. package/dist/src/cli/dev/tui/markdown.js +1 -1
  23. package/dist/src/cli/dev/tui/model-editor.d.ts +103 -0
  24. package/dist/src/cli/dev/tui/model-editor.js +1 -0
  25. package/dist/src/cli/dev/tui/prompt-command-handler.d.ts +1 -1
  26. package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
  27. package/dist/src/cli/dev/tui/remote-auth-command.js +1 -1
  28. package/dist/src/cli/dev/tui/runner.d.ts +5 -0
  29. package/dist/src/cli/dev/tui/runner.js +1 -1
  30. package/dist/src/cli/dev/tui/setup-commands.d.ts +1 -1
  31. package/dist/src/cli/dev/tui/setup-commands.js +2 -2
  32. package/dist/src/cli/dev/tui/setup-flow.d.ts +3 -0
  33. package/dist/src/cli/dev/tui/setup-panel.d.ts +33 -0
  34. package/dist/src/cli/dev/tui/setup-panel.js +4 -4
  35. package/dist/src/cli/dev/tui/status-line.d.ts +8 -6
  36. package/dist/src/cli/dev/tui/status-line.js +1 -1
  37. package/dist/src/cli/dev/tui/terminal-renderer.d.ts +3 -0
  38. package/dist/src/cli/dev/tui/terminal-renderer.js +11 -10
  39. package/dist/src/cli/dev/tui/test/fake-setup-flow-renderer.js +1 -1
  40. package/dist/src/cli/dev/tui/theme.d.ts +14 -0
  41. package/dist/src/cli/dev/tui/theme.js +1 -1
  42. package/dist/src/cli/dev/tui/tool-format.js +1 -1
  43. package/dist/src/cli/dev/tui/tui.js +1 -1
  44. package/dist/src/cli/run.js +2 -2
  45. package/dist/src/cli/ui/live-row.js +1 -1
  46. package/dist/src/client/agent-info-schema.d.ts +9 -0
  47. package/dist/src/client/agent-info-schema.js +1 -1
  48. package/dist/src/client/client.js +1 -1
  49. package/dist/src/client/eve-agent-store.d.ts +1 -2
  50. package/dist/src/client/eve-agent-store.js +1 -1
  51. package/dist/src/client/open-stream.d.ts +14 -10
  52. package/dist/src/client/open-stream.js +1 -1
  53. package/dist/src/client/session-utils.d.ts +2 -1
  54. package/dist/src/client/session-utils.js +1 -1
  55. package/dist/src/client/session.d.ts +3 -5
  56. package/dist/src/client/session.js +1 -1
  57. package/dist/src/client/types.d.ts +0 -6
  58. package/dist/src/compiler/extension-compatibility.d.ts +2 -2
  59. package/dist/src/compiler/extension-compatibility.js +1 -1
  60. package/dist/src/context/build-dynamic-tools.js +1 -1
  61. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  62. package/dist/src/execution/node-step.js +1 -1
  63. package/dist/src/execution/sandbox/bindings/docker-cli.d.ts +4 -0
  64. package/dist/src/execution/sandbox/bindings/docker-cli.js +1 -1
  65. package/dist/src/execution/sandbox/bindings/microsandbox-create.js +1 -1
  66. package/dist/src/execution/terminal-session-failure-step.js +1 -1
  67. package/dist/src/harness/emission.js +1 -1
  68. package/dist/src/harness/model-call-error.d.ts +11 -30
  69. package/dist/src/harness/model-call-error.js +1 -1
  70. package/dist/src/harness/semantic-errors/index.d.ts +9 -0
  71. package/dist/src/harness/semantic-errors/index.js +1 -0
  72. package/dist/src/harness/semantic-errors/rule.d.ts +76 -0
  73. package/dist/src/harness/semantic-errors/rule.js +1 -0
  74. package/dist/src/harness/semantic-errors/rules/gateway.d.ts +11 -0
  75. package/dist/src/harness/semantic-errors/rules/gateway.js +1 -0
  76. package/dist/src/harness/semantic-errors/rules/model-provider.d.ts +11 -0
  77. package/dist/src/harness/semantic-errors/rules/model-provider.js +1 -0
  78. package/dist/src/harness/semantic-errors/rules/sandbox.d.ts +16 -0
  79. package/dist/src/harness/semantic-errors/rules/sandbox.js +1 -0
  80. package/dist/src/harness/semantic-errors/rules/system.d.ts +2 -0
  81. package/dist/src/harness/semantic-errors/rules/system.js +1 -0
  82. package/dist/src/harness/semantic-errors/rules/workflow.d.ts +9 -0
  83. package/dist/src/harness/semantic-errors/rules/workflow.js +1 -0
  84. package/dist/src/harness/semantic-errors/signals.d.ts +28 -0
  85. package/dist/src/harness/semantic-errors/signals.js +1 -0
  86. package/dist/src/harness/tool-loop.js +2 -2
  87. package/dist/src/harness/workflow-sandbox.d.ts +6 -0
  88. package/dist/src/harness/workflow-sandbox.js +2 -2
  89. package/dist/src/internal/application/output-publication-lock.js +1 -1
  90. package/dist/src/internal/application/package.js +1 -1
  91. package/dist/src/internal/logging.d.ts +33 -1
  92. package/dist/src/internal/logging.js +1 -1
  93. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
  94. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +3 -1
  95. package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
  96. package/dist/src/internal/workflow/development-world-client.js +1 -1
  97. package/dist/src/internal/workflow/development-world-server.js +1 -1
  98. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  99. package/dist/src/public/models/openai/chatgpt/model.js +3 -1
  100. package/dist/src/react/use-eve-agent.d.ts +0 -1
  101. package/dist/src/react/use-eve-agent.js +1 -1
  102. package/dist/src/setup/boxes/add-channels.js +1 -1
  103. package/dist/src/setup/boxes/deploy-project.js +1 -1
  104. package/dist/src/setup/boxes/model-capabilities.d.ts +24 -0
  105. package/dist/src/setup/boxes/model-capabilities.js +1 -0
  106. package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
  107. package/dist/src/setup/boxes/select-model.d.ts +30 -8
  108. package/dist/src/setup/boxes/select-model.js +1 -1
  109. package/dist/src/setup/cli/option-row.js +1 -1
  110. package/dist/src/setup/cli/prompt-ui.d.ts +2 -0
  111. package/dist/src/setup/cli/prompt-ui.js +2 -2
  112. package/dist/src/setup/cli/rail-log.d.ts +4 -6
  113. package/dist/src/setup/cli/rail-log.js +3 -2
  114. package/dist/src/setup/connection-connector.js +2 -2
  115. package/dist/src/setup/flows/login.js +1 -1
  116. package/dist/src/setup/flows/model-source-change.d.ts +38 -0
  117. package/dist/src/setup/flows/model-source-change.js +1 -0
  118. package/dist/src/setup/flows/model.d.ts +65 -62
  119. package/dist/src/setup/flows/model.js +1 -1
  120. package/dist/src/setup/flows/provider.d.ts +20 -0
  121. package/dist/src/setup/flows/provider.js +3 -3
  122. package/dist/src/setup/prompter.d.ts +2 -0
  123. package/dist/src/setup/scaffold/create/project.js +1 -1
  124. package/dist/src/setup/slack-connect-lifecycle.js +1 -1
  125. package/dist/src/setup/slackbot.js +1 -1
  126. package/dist/src/setup/vercel-project.d.ts +6 -0
  127. package/dist/src/setup/vercel-project.js +0 -0
  128. package/dist/src/shared/dynamic-tool-definition.d.ts +1 -8
  129. package/dist/src/shared/errors.d.ts +5 -0
  130. package/dist/src/shared/errors.js +1 -1
  131. package/dist/src/shared/gateway-service-tier.d.ts +19 -0
  132. package/dist/src/shared/gateway-service-tier.js +1 -0
  133. package/dist/src/shared/model-summary.d.ts +12 -0
  134. package/dist/src/shared/model-summary.js +1 -0
  135. package/dist/src/shared/workflow-sandbox.d.ts +2 -0
  136. package/dist/src/shared/workflow-sandbox.js +1 -1
  137. package/dist/src/source-change/agent-config-ast.d.ts +54 -0
  138. package/dist/src/source-change/agent-config-ast.js +2 -0
  139. package/dist/src/source-change/agent-config-string-path.d.ts +18 -0
  140. package/dist/src/source-change/agent-config-string-path.js +2 -0
  141. package/dist/src/source-change/apply-agent-model-settings.d.ts +26 -0
  142. package/dist/src/source-change/apply-agent-model-settings.js +1 -0
  143. package/dist/src/source-change/apply-model-name.js +1 -2
  144. package/dist/src/source-change/static-source-change.d.ts +14 -0
  145. package/dist/src/source-change/static-source-change.js +1 -1
  146. package/dist/src/svelte/index.js +1 -1
  147. package/dist/src/svelte/use-eve-agent.d.ts +0 -6
  148. package/dist/src/svelte/use-eve-agent.js +1 -1
  149. package/dist/src/vue/index.js +1 -1
  150. package/dist/src/vue/use-eve-agent.d.ts +0 -2
  151. package/dist/src/vue/use-eve-agent.js +1 -1
  152. package/docs/concepts/execution-model-and-durability.md +1 -1
  153. package/docs/concepts/sessions-runs-and-streaming.md +1 -1
  154. package/docs/getting-started.mdx +1 -1
  155. package/docs/guides/auth-and-route-protection.md +1 -1
  156. package/docs/guides/client/overview.mdx +1 -1
  157. package/docs/guides/client/streaming.mdx +1 -10
  158. package/docs/guides/deployment/meta.json +4 -0
  159. package/docs/guides/deployment/overview.md +61 -0
  160. package/docs/guides/deployment/self-hosting.md +88 -0
  161. package/docs/guides/deployment/vercel.mdx +90 -0
  162. package/docs/guides/dev-tui.md +8 -4
  163. package/docs/guides/dynamic-capabilities.md +2 -0
  164. package/docs/guides/frontend/nextjs.mdx +1 -1
  165. package/docs/guides/frontend/nuxt.mdx +1 -1
  166. package/docs/guides/frontend/overview.mdx +2 -5
  167. package/docs/guides/frontend/sveltekit.mdx +1 -1
  168. package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -4
  169. package/docs/guides/frontend/use-eve-agent-vue.mdx +1 -4
  170. package/docs/guides/instrumentation.md +1 -1
  171. package/docs/reference/cli.md +24 -2
  172. package/docs/tutorial/ship-it.mdx +1 -1
  173. package/package.json +1 -1
  174. package/docs/guides/deployment.md +0 -210
  175. /package/dist/src/cli/{dev/tui → ui}/live-region.d.ts +0 -0
  176. /package/dist/src/cli/{dev/tui → ui}/live-region.js +0 -0
  177. /package/dist/src/cli/{dev/tui → ui}/terminal-text.d.ts +0 -0
  178. /package/dist/src/cli/{dev/tui → ui}/terminal-text.js +0 -0
@@ -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}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{findEnvFileWithKey}from"../boxes/detect-ai-gateway.js";import{fetchGatewayCatalog,selectModel}from"../boxes/select-model.js";import{runInteractive}from"../runner.js";import{inProjectSetupState,prompterSink}from"./in-project.js";import{runProviderFlow}from"./provider.js";import{join}from"node:path";import{discoverAgent}from"#discover/discover-agent.js";import{inspectApplication}from"#services/inspect-application.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{createCompiledRuntimeModelCatalogLoader}from"#compiler/model-catalog.js";import{createStaticSourceChange}from"#source-change/static-source-change.js";var import_picocolors=__toESM(require_picocolors(),1);const MODEL_MENU_MESSAGE=``;function providerStatusHint(e,t=e=>e){return e.kind===`gateway-project`?`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`:`AI Gateway (${e.envKey} in ${e.envFile})`}function modelMenuRows(e,t,n,r){let i;r?(i={value:`model`,label:`Change model`,description:`The model your agent uses`},e!==null&&(i.hint=e)):i={value:`model`,label:`Change model`,disabled:!0,description:`Set via an SDK model call in agent.ts; edit the source to change it`};let a;return a=n?.kind===`external`?{disabled:!0,value:`provider`,label:`Change provider`,description:`Disabled in external endpoint mode`}:t.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(t,import_picocolors.default.bold),description:`How your agent reaches the model provider`},[i,a,{value:`done`,label:`Done`,description:`Return to the prompt`}]}async function detectModelProviderStatus(e,t={}){let[r,a,o]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(r!==void 0){let e={kind:`gateway-project`,projectName:r.projectName};return r.teamName!==void 0&&(e.teamName=r.teamName),e}return a===void 0?o===void 0?{kind:`unset`}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,envFile:o}:{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,envFile:a}}async function runModelFlow(e){let{appRoot:t,prompter:n,signal:r}=e,i={readCurrentModel:readCurrentAgentModel,applyModel:changeAgentModel,detectProviderStatus:detectModelProviderStatus,runProviderFlow,...e.deps},detectProvider=(e=!0)=>i.detectProviderStatus(t,e&&r!==void 0?{signal:r}:{}),[{id:a,routing:s,editable:c},l]=await withSpinner(n,`Checking the project…`,()=>Promise.all([i.readCurrentModel(t),detectProvider()]));r?.throwIfAborted();let u,d,f=s?.kind===`external`?{tone:`warning`,text:"`agent.ts` specifies a model provider directly. In-TUI configuration is restricted to AI Gateway endpoints."}:void 0,m=l.kind===`unset`&&s?.kind!==`external`?`provider`:c?`model`:s?.kind===`external`?`done`:`provider`,h=s?.kind!==`external`&&(e.initialStep===`provider`||l.kind===`unset`);for(;;){let e;if(h)h=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(a,l,s,c),hintLayout:`stacked`,initialValue:m,notices:f===void 0?[]:[f]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;break}if(e===`done`)break;if(e===`model`){let e=await pickModelFromCatalog({appRoot:t,prompter:n,current:a,signal:r,deps:i.selectModel});if(e===void 0){m=`model`;continue}r?.throwIfAborted(),u=await i.applyModel({appRoot:t,slug:e}),r?.throwIfAborted();break}let p=await i.runProviderFlow({appRoot:t,prompter:n,signal:r});if(p.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};m=`provider`;continue}if(p.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};m=`done`;continue}l=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),d={status:l},p.credential!==void 0&&(d.credential=p.credential);break}if(u===void 0&&d===void 0)return{kind:`cancelled`};let g={kind:`done`};return u!==void 0&&(g.modelMessage=formatApplyModelOutcome(u)),d!==void 0&&(g.providerOutcome=d),g}async function pickModelFromCatalog(e){let{appRoot:t,prompter:n,current:i,signal:o}=e,s=e.deps?.fetchModels??fetchGatewayCatalog,p={asker:interactiveAsker(n),deps:{fetchModels:e=>withSpinner(n,`Loading the model catalog...`,()=>s(e))}};i!==null&&(p.defaultModel=i);let m=await runInteractive([selectModel(p)],inProjectSetupState(t,{kind:`unresolved`}),prompterSink(n),{snapshot:snapshotSetupState,signal:o});return m.kind===`cancelled`?void 0:m.state.modelId}function formatApplyModelOutcome(e){switch(e.kind){case`changed`:return`Model changed to ${import_picocolors.default.bold(e.to)}. Live on your next prompt.`;case`unchanged`:return`Model is already \`${e.model}\`.`;case`rejected`:return e.message}}async function changeAgentModel(e){let{appRoot:t,slug:n}=e,r=await validateModelSlug(t,n);if(r!==null)return{kind:`rejected`,message:r};let{manifest:i}=await discoverAgent({agentRoot:join(t,`agent`),appRoot:t}),a=await createStaticSourceChange(i).updateModelName(n);return a.kind===`bail`?{kind:`rejected`,message:`Couldn't edit ${a.at.logicalPath}: ${a.reason}. Change \`model\` by hand.`}:a.from===a.to?{kind:`unchanged`,model:a.to}:{kind:`changed`,to:a.to}}async function validateModelSlug(e,t){if(!t.includes(`/`))return`\`${t}\` isn't a provider/model id (e.g. anthropic/claude-sonnet-5).`;let n=createCompiledRuntimeModelCatalogLoader(e);try{if(await n.getModelLimits(formatLanguageModelGatewayId(t))===null)return`I couldn't confirm \`${t}\` in the AI Gateway model catalog, so I didn't change agent.ts.`}catch{return null}return null}async function readCurrentAgentModel(e){try{let{compiledState:t}=await inspectApplication(e),n=t?.manifest.config.model;return{id:n?.id??null,routing:n?.routing??null,editable:n!==void 0&&n.source===void 0}}catch{return{id:null,routing:null,editable:!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,changeAgentModel,detectModelProviderStatus,formatApplyModelOutcome,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{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{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){return e.kind===`gateway-project`?`AI Gateway (Linked to ${e.teamName===void 0?t(e.projectName):`${t(e.projectName)} in ${t(e.teamName)}`})`:`AI Gateway (${e.envKey} in ${e.envFile})`}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={}){let[i,a,s]=await Promise.all([detectProjectIdentity(e,t),findEnvFileWithKey(e,AI_GATEWAY_API_KEY_ENV_VAR),findEnvFileWithKey(e,`VERCEL_OIDC_TOKEN`)]);if(i!==void 0){let e={kind:`gateway-project`,projectName:i.projectName};return i.teamName!==void 0&&(e.teamName=i.teamName),e}return a===void 0?s===void 0?{kind:`unset`}:{kind:`gateway-key`,envKey:`VERCEL_OIDC_TOKEN`,envFile:s}:{kind:`gateway-key`,envKey:AI_GATEWAY_API_KEY_ENV_VAR,envFile:a}}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,[u,d,f]=await withSpinner(n,`Checking the project…`,()=>Promise.all([o.readCurrentModel(t),detectProvider(),l(r).catch(()=>void 0)]));r?.throwIfAborted();let{id:p,routing:m,serviceTier:h,editable:g,settingsEditable:_}=u,v=u.reasoning===`provider-default`?null:u.reasoning,y=d,b={model:{kind:`keep`},reasoning:{kind:`keep`},gatewayServiceTier:{kind:`keep`}},x,S,C=!1,w=m?.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,T=y.kind===`unset`&&m?.kind!==`external`?`provider`:g||_?`model`:`provider`,E=m?.kind!==`external`&&(e.initialStep===`provider`||y.kind===`unset`);for(;;){let e;if(E)E=!1,e=`provider`;else try{e=await n.select({message:``,options:modelMenuRows(p,v,h,y,m,g,_),hintLayout:`stacked`,initialValue:T,notices:w===void 0?[]:[w]})}catch(e){if(!(e instanceof WizardCancelledError))throw e;if(hasModelSettingsChanges(b))return{kind:`cancelled`,discardedDraft:!0};break}if(e===`done`){C=!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:g?{kind:`pick`,options:modelListRows(f),current:p}:{kind:`fixed`,current:p,reason:`Set via an SDK model call in agent.ts; edit the source to change it`},reasoning:v,serviceTier:h,settingsEditable:_,externalRouting:m?.kind===`external`,capabilitiesFor:e=>gatewayModelCapabilities(f,e)});if(r?.throwIfAborted(),t===void 0){T=`model`;continue}t.model!==void 0&&(p=t.model,m={kind:`gateway`,target:t.model.split(`/`)[0]??``},b.model={kind:`set`,value:t.model}),t.reasoning!==void 0&&(v=t.reasoning==="default"?null:t.reasoning,b.reasoning=v===null?{kind:`remove`}:{kind:`set`,value:v}),t.serviceTier!==void 0&&(h=t.serviceTier===`priority`?{kind:`priority`}:{kind:`standard`},b.gatewayServiceTier=t.serviceTier===`priority`?{kind:`set`,value:`priority`}:{kind:`remove`}),T=`done`;continue}let c=await o.runProviderFlow({appRoot:t,prompter:n,signal:r,currentProvider:y});if(c.kind===`cancelled`){if(r?.aborted)return{kind:`cancelled`};T=`provider`;continue}if(c.kind===`external-provider`){if(r?.aborted)return{kind:`cancelled`};T=`done`;continue}y=await withSpinner(n,`Checking the project…`,()=>detectProvider(!1)),S={status:y},c.credential!==void 0&&(S.credential=c.credential),C=!0;break}if(C&&hasModelSettingsChanges(b)&&(x=await o.applySettings({appRoot:t,patch:b}),r?.throwIfAborted()),x===void 0&&S===void 0)return{kind:`cancelled`};let D={kind:`done`};return x!==void 0&&(D.modelMessage=formatApplyModelSettingsOutcome(x)),S!==void 0&&(D.providerOutcome=S),D}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,9 +1,27 @@
1
1
  import { appendEnv } from "../append-env.js";
2
+ import { AI_GATEWAY_API_KEY_ENV_VAR } from "../ai-gateway-api-key.js";
2
3
  import type { Prompter, SelectOption } from "../prompter.js";
3
4
  import { validateGatewayApiKey, type GatewayKeyValidation } from "../validate-gateway-key.js";
4
5
  import { getVercelAuthStatus } from "../vercel-project.js";
5
6
  import { runLinkFlow, type LinkFlowResult } from "./link.js";
6
7
  export type ProviderConnection = "project" | "own-key" | "external";
8
+ /**
9
+ * How the agent's model is backed right now, as far as the local directory
10
+ * shows: a linked Vercel project, a gateway credential in an env file, or
11
+ * nothing detectable. An external provider (own ANTHROPIC_API_KEY etc.)
12
+ * leaves no marker eve owns, so it reads as `unset`.
13
+ */
14
+ export type ModelProviderStatus = {
15
+ kind: "unset";
16
+ } | {
17
+ kind: "gateway-project";
18
+ projectName: string;
19
+ teamName?: string;
20
+ } | {
21
+ kind: "gateway-key";
22
+ envKey: typeof AI_GATEWAY_API_KEY_ENV_VAR | "VERCEL_OIDC_TOKEN";
23
+ envFile: string;
24
+ };
7
25
  export declare const PROVIDER_QUESTION = "Which model provider do you want to use?";
8
26
  export declare const EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE = "Using another model provider";
9
27
  export declare const EXTERNAL_PROVIDER_INSTRUCTIONS: readonly string[];
@@ -52,6 +70,8 @@ export declare function runProviderFlow(input: {
52
70
  prompter: Prompter;
53
71
  signal?: AbortSignal;
54
72
  picker?: ProviderPicker;
73
+ /** The detected provider, so the chooser can mark and describe the active row. */
74
+ currentProvider?: ModelProviderStatus;
55
75
  deps?: Partial<ProviderFlowDeps>;
56
76
  }): Promise<ProviderFlowResult>;
57
77
  export {};
@@ -1,4 +1,4 @@
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{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
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){return[projectConnectionOption(e),{value:`own-key`,label:`AI Gateway via ${AI_GATEWAY_API_KEY_ENV_VAR}`,hint:`> type your key`},{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider
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=`project`,l;try{for(;;){let n=await selectProvider({picker:e.picker,options:providerOptions(s),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
- `),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.`):r.log.success(`${import_picocolors.default.green(`✓`)} ${import_picocolors.default.bold(`Valid key`)}`);let f=await writeAiGatewayApiKey({projectRoot:t,apiKey:u,appendEnv:o.appendEnv});return r.log.success(`Saved ${f.envKey} to ${f.envFile}.`),{kind:`done`,credential:f.envKey}}export{EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runProviderFlow};
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`};return t?.kind===`gateway-key`&&(r={...r,checked:!0,hint:`${t.envKey} set in ${t.envFile}`}),[n,r,{value:`external`,label:`Other providers`,hint:`Connect directly to a model provider
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
+ `),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`,credential:f.envKey}}export{EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runProviderFlow};
@@ -51,6 +51,8 @@ export interface SelectOption<T extends PrompterValue> {
51
51
  * to the front. Meaningless without `search`.
52
52
  */
53
53
  featured?: boolean;
54
+ /** Marks the currently-active value: renders a green check beside the row. */
55
+ checked?: boolean;
54
56
  }
55
57
  /**
56
58
  * An outcome line from an earlier lap of a looping menu, shown with the
@@ -1,4 +1,4 @@
1
- import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.26`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.25.3`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
1
+ import{pinnedNodeEngineMajor}from"../../node-engine.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{applyPackageManagerWorkspaceConfiguration,isPackageManagerWorkspaceMember,patchWorkspaceRootPackageJson}from"../workspace-root.js";import{WEB_APP_TEMPLATE_FILES}from"./web-template.js";import{basename,join,resolve}from"node:path";import{mkdir,readdir,stat}from"node:fs/promises";const CURRENT_DIRECTORY_PROJECT_NAME=`.`,ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),DEFAULT_AI_PACKAGE_VERSION=`^7.0.26`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.4.0`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.26.0`,nodeEngine:`>=24`};function resolveEvePackageContract(e=DEFAULT_EVE_PACKAGE_CONTRACT){return{version:resolveVersionToken(`evePackage.version`,e.version),nodeEngine:resolveVersionToken(`evePackage.nodeEngine`,e.nodeEngine)}}function modelProviderSlug(e){let t=(e.split(`/`)[0]??``).replaceAll(/[^A-Za-z0-9._-]/gu,``);return t.length>0?t:`anthropic`}function byokProviderEnvVar(e){let t=modelProviderSlug(e).toUpperCase().replaceAll(/[^A-Z0-9]/gu,`_`);return`${/^[0-9]/.test(t)?`_`:``}${t}_API_KEY`}function agentTemplateFiles(e){return{"agent/agent.ts":BASE_AGENT_TEMPLATE.replaceAll(`__EVE_INIT_MODEL__`,e),"agent/channels/eve.ts":WEB_APP_TEMPLATE_FILES[`agent/channels/eve.ts`],"agent/instructions.md":AGENT_INSTRUCTIONS_TEMPLATE}}function renderTemplate(e,t){return e.replaceAll(`__EVE_INIT_APP_NAME__`,t.appName).replaceAll(`__EVE_INIT_MODEL__`,t.model).replaceAll(`__EVE_INIT_BYOK_PROVIDER__`,modelProviderSlug(t.model)).replaceAll(`__EVE_INIT_BYOK_ENV_VAR__`,byokProviderEnvVar(t.model)).replaceAll(`__EVE_INIT_PACKAGE_VERSION__`,formatEveDependencySpecifier(t.eveVersion)).replaceAll(`__EVE_INIT_AI_SDK_VERSION__`,t.aiPackageVersion).replaceAll(`__EVE_INIT_CONNECT_VERSION__`,t.connectPackageVersion).replaceAll(`__EVE_INIT_ZOD_VERSION__`,t.zodPackageVersion).replaceAll(`__EVE_INIT_TYPESCRIPT_VERSION__`,t.typescriptPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.nodeTypesVersion).replaceAll(`__EVE_INIT_NODE_ENGINE__`,t.nodeEngine)}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}const BASE_AGENT_TEMPLATE=`import { defineAgent } from "eve";
2
2
 
3
3
  export default defineAgent({
4
4
  model: "__EVE_INIT_MODEL__",
@@ -1 +1 @@
1
- import{object,string}from"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{parseSlackConnectorDetails,parseSlackConnectors,pickSlackConnector}from"./slack-connect.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{readFile}from"node:fs/promises";import"#setup/cli/index.js";import"#setup/primitives/run-vercel.js";const CONNECT_LOOKUP_TIMEOUT_MS=6e4,CONNECT_MUTATION_TIMEOUT_MS=2*6e4,VercelProjectLinkSchema=object({projectId:string().min(1),orgId:string().min(1)});async function listSlackConnectors(e,t,n,i){let a=await e.captureVercel([`connect`,`list`,`-F`,`json`,`--all-projects`],{cwd:t,onOutput:n,timeoutMs:CONNECT_LOOKUP_TIMEOUT_MS,signal:i});if(!a.ok)return{state:`failed`,message:a.failure.message};try{let e=JSON.parse(a.stdout);if(typeof e!=`object`||!e)return{state:`failed`,message:`Vercel returned a malformed connector list.`};let t=e;return Array.isArray(t.connectors??t.clients)?{state:`ok`,body:e,connectors:parseSlackConnectors(e)}:{state:`failed`,message:`Vercel returned a malformed connector list.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the connector list.`}}}async function readProjectLink(e){try{let t=await readFile(join(e,`.vercel`,`project.json`),`utf8`),n=VercelProjectLinkSchema.safeParse(JSON.parse(t));return n.success?n.data:void 0}catch{return}}async function findSlackConnector(e,t,n,r,a,o){let s=await listSlackConnectors(e,t,a,o);if(s.state===`failed`)return s;let c=new Set(s.connectors.map(e=>e.uid)),l=pickSlackConnector(s.body,n,r);return l===void 0?{state:`not-found`,connectorUids:c}:{state:`found`,connector:l,connectorUids:c}}async function attachSlackConnector(e,t,n,r,i){return await e.runVercel([`connect`,`detach`,n.uid,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS,signal:i})?await e.runVercel([`connect`,`attach`,n.uid,`--triggers`,`--trigger-path`,SLACK_CHANNEL_DEFAULT_ROUTE,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS,signal:i})?{state:`attached`}:{state:`attach-failed`}:{state:`detach-failed`}}async function fetchSlackConnectorDetails(e){let t=e.orgId===void 0?``:`?teamId=${encodeURIComponent(e.orgId)}`,r=[`api`,`/v1/connect/connectors/${encodeURIComponent(e.connectorId)}${t}`];e.orgId!==void 0&&r.push(`--scope`,e.orgId);let i=await e.deps.captureVercel(r,{cwd:e.projectRoot,onOutput:e.onOutput,timeoutMs:e.timeoutMs,signal:e.signal});if(!i.ok)return{state:`failed`,message:i.failure.message};try{let t=parseSlackConnectorDetails(JSON.parse(i.stdout));return t?.ref.id===e.connectorId?{state:`found`,details:t}:{state:`failed`,message:`Vercel returned an invalid Slack connector.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the Slack connector.`}}}async function fetchSlackWorkspace(e){let t=await fetchSlackConnectorDetails(e);return t.state===`failed`?t:t.details.workspace===void 0?{state:`pending`}:{state:`connected`,workspace:t.details.workspace}}async function cleanupConnectorUid(e,t){let{log:n,deps:r,projectRoot:i,onOutput:a}=e;return await r.runVercel([`connect`,`remove`,t,`--disconnect-all`,`--yes`],{cwd:i,onOutput:a,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS})?!0:(n.warning(`Could not remove the abandoned Slack connector. Run \`vercel connect remove ${t} --disconnect-all --yes\` to clean it up.`),!1)}async function cleanupConnectorUids(e,t){let n=[];for(let r of new Set(t))await cleanupConnectorUid(e,r)||n.push(r);return n.length===0?{state:`clean`}:{state:`failed`,connectorUids:n}}async function cleanupCreatedAttempt(e,t){if(t.createdRef)return cleanupConnectorUids(e,[t.createdRef.uid]);e.log.warning(`Vercel returned no connector UID for the abandoned Slack Connect request, so eve cannot prove that request was cancelled. No connector was removed; do not retry until the browser request is no longer usable.`);let n=await listSlackConnectors(e.deps,e.projectRoot,e.onOutput);return n.state===`failed`?{state:`failed`,connectorUids:[]}:{state:`failed`,connectorUids:n.connectors.map(e=>e.uid).filter(e=>(e===t.expectedUid||e.startsWith(`${t.expectedUid}-`))&&!t.baselineConnectorUids.has(e))}}export{CONNECT_LOOKUP_TIMEOUT_MS,CONNECT_MUTATION_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackConnectorDetails,fetchSlackWorkspace,findSlackConnector,listSlackConnectors,readProjectLink};
1
+ import{object,string}from"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js";import"../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js";import{parseSlackConnectorDetails,parseSlackConnectors,pickSlackConnector}from"./slack-connect.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{readFile}from"node:fs/promises";import"#setup/primitives/run-vercel.js";import"#setup/cli/index.js";const CONNECT_LOOKUP_TIMEOUT_MS=6e4,CONNECT_MUTATION_TIMEOUT_MS=2*6e4,VercelProjectLinkSchema=object({projectId:string().min(1),orgId:string().min(1)});async function listSlackConnectors(e,t,n,i){let a=await e.captureVercel([`connect`,`list`,`-F`,`json`,`--all-projects`],{cwd:t,onOutput:n,timeoutMs:CONNECT_LOOKUP_TIMEOUT_MS,signal:i});if(!a.ok)return{state:`failed`,message:a.failure.message};try{let e=JSON.parse(a.stdout);if(typeof e!=`object`||!e)return{state:`failed`,message:`Vercel returned a malformed connector list.`};let t=e;return Array.isArray(t.connectors??t.clients)?{state:`ok`,body:e,connectors:parseSlackConnectors(e)}:{state:`failed`,message:`Vercel returned a malformed connector list.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the connector list.`}}}async function readProjectLink(e){try{let t=await readFile(join(e,`.vercel`,`project.json`),`utf8`),n=VercelProjectLinkSchema.safeParse(JSON.parse(t));return n.success?n.data:void 0}catch{return}}async function findSlackConnector(e,t,n,r,a,o){let s=await listSlackConnectors(e,t,a,o);if(s.state===`failed`)return s;let c=new Set(s.connectors.map(e=>e.uid)),l=pickSlackConnector(s.body,n,r);return l===void 0?{state:`not-found`,connectorUids:c}:{state:`found`,connector:l,connectorUids:c}}async function attachSlackConnector(e,t,n,r,i){return await e.runVercel([`connect`,`detach`,n.uid,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS,signal:i})?await e.runVercel([`connect`,`attach`,n.uid,`--triggers`,`--trigger-path`,SLACK_CHANNEL_DEFAULT_ROUTE,`--yes`],{cwd:t,onOutput:r,nonInteractive:!0,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS,signal:i})?{state:`attached`}:{state:`attach-failed`}:{state:`detach-failed`}}async function fetchSlackConnectorDetails(e){let t=e.orgId===void 0?``:`?teamId=${encodeURIComponent(e.orgId)}`,r=[`api`,`/v1/connect/connectors/${encodeURIComponent(e.connectorId)}${t}`];e.orgId!==void 0&&r.push(`--scope`,e.orgId);let i=await e.deps.captureVercel(r,{cwd:e.projectRoot,onOutput:e.onOutput,timeoutMs:e.timeoutMs,signal:e.signal});if(!i.ok)return{state:`failed`,message:i.failure.message};try{let t=parseSlackConnectorDetails(JSON.parse(i.stdout));return t?.ref.id===e.connectorId?{state:`found`,details:t}:{state:`failed`,message:`Vercel returned an invalid Slack connector.`}}catch{return{state:`failed`,message:`Vercel returned invalid JSON for the Slack connector.`}}}async function fetchSlackWorkspace(e){let t=await fetchSlackConnectorDetails(e);return t.state===`failed`?t:t.details.workspace===void 0?{state:`pending`}:{state:`connected`,workspace:t.details.workspace}}async function cleanupConnectorUid(e,t){let{log:n,deps:r,projectRoot:i,onOutput:a}=e;return await r.runVercel([`connect`,`remove`,t,`--disconnect-all`,`--yes`],{cwd:i,onOutput:a,timeoutMs:CONNECT_MUTATION_TIMEOUT_MS})?!0:(n.warning(`Could not remove the abandoned Slack connector. Run \`vercel connect remove ${t} --disconnect-all --yes\` to clean it up.`),!1)}async function cleanupConnectorUids(e,t){let n=[];for(let r of new Set(t))await cleanupConnectorUid(e,r)||n.push(r);return n.length===0?{state:`clean`}:{state:`failed`,connectorUids:n}}async function cleanupCreatedAttempt(e,t){if(t.createdRef)return cleanupConnectorUids(e,[t.createdRef.uid]);e.log.warning(`Vercel returned no connector UID for the abandoned Slack Connect request, so eve cannot prove that request was cancelled. No connector was removed; do not retry until the browser request is no longer usable.`);let n=await listSlackConnectors(e.deps,e.projectRoot,e.onOutput);return n.state===`failed`?{state:`failed`,connectorUids:[]}:{state:`failed`,connectorUids:n.connectors.map(e=>e.uid).filter(e=>(e===t.expectedUid||e.startsWith(`${t.expectedUid}-`))&&!t.baselineConnectorUids.has(e))}}export{CONNECT_LOOKUP_TIMEOUT_MS,CONNECT_MUTATION_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackConnectorDetails,fetchSlackWorkspace,findSlackConnector,listSlackConnectors,readProjectLink};
@@ -1 +1 @@
1
- import{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector}from"./slack-connect.js";import{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackWorkspace,findSlackConnector,listSlackConnectors,readProjectLink}from"./slack-connect-lifecycle.js";import{createSlackConnector}from"./slack-connect-create.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{performance}from"node:perf_hooks";import{setTimeout}from"node:timers/promises";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{updateSlackChannelConnectorUid}from"#setup/scaffold/update/update-slack-channel.js";const defaultDeps={captureVercel,runVercel,runVercelCaptureStdout},realDelay=(e,t)=>setTimeout(e,void 0,{signal:t}),monotonicNow=()=>performance.now();async function pollSlackWorkspace(e,t,n,i,a,s){let c=e.delay??realDelay,l=e.now??monotonicNow,u=l()+3e5;for(;;){s?.throwIfAborted();let d=u-l();if(d<=0)return{state:`timed-out`};let f=await fetchSlackWorkspace({deps:e,projectRoot:t,connectorId:n,orgId:i,onOutput:a,timeoutMs:Math.min(CONNECT_LOOKUP_TIMEOUT_MS,d),signal:s});if(s?.throwIfAborted(),f.state!==`pending`)return f;let p=u-l();if(p<=0)return{state:`timed-out`};await c(Math.min(3e3,p),s)}}function isAbortFromSignal(e,t){return t?.aborted===!0&&(e===t.reason||e instanceof Error&&e.name===`AbortError`)}function cleanupFailureResult(e){return{state:`cleanup-failed`,connectorUids:e.connectorUids}}async function runAttempt(e){let{log:t,deps:n,projectRoot:r,orgId:a,onOutput:o,signal:s,phase:c}=e,l,d;if(e.source.state===`existing`)l=e.source.ref;else{let i=await createSlackConnector({deps:n,projectRoot:r,orgId:a,slug:e.slug,onOutput:o,signal:s,phase:c,onCreated:e.onCreated,waitForWorkspace:async(e,t)=>{let i=await pollSlackWorkspace(n,r,e.id,a,o,t);return i.state===`connected`?i.workspace:void 0}});if(i.state===`failed`)return{state:`create-failed`};if(i.state===`unresolved`)return t.warning(`Vercel did not return an exact Slack connector UID for this request, so eve cannot attach or remove it safely.`),{state:`unresolved`};l=i.ref,i.via===`workspace`&&(d=i.workspace)}if(e.source.state===`existing`&&d===void 0){let e=await c(`Waiting for the Slack workspace connection...`,()=>pollSlackWorkspace(n,r,l.id,a,o,s));if(e.state===`timed-out`)return{state:`timed-out`,ref:l};if(e.state===`failed`)return{state:`failed`,ref:l,message:e.message};d=e.workspace}let f=await c(`Configuring Slack event delivery for this agent...`,()=>attachSlackConnector(n,r,l,o,s));return s?.throwIfAborted(),f.state===`attached`?d===void 0?{state:`attached`,ref:l}:{state:`attached`,ref:l,workspace:d}:{state:f.state,ref:l}}async function raceAttemptAgainstChoice(e){let t=new AbortController,n=e.outerSignal?AbortSignal.any([e.outerSignal,t.signal]):t.signal,r=e.run(n);try{let i=await Promise.race([r.then(e=>({via:`work`,outcome:e})),e.prompt.choice.then(e=>({via:`choice`,choice:e}))]);if(i.via===`work`)return i;t.abort();let a;try{a=await r}catch(e){if(!isAbortFromSignal(e,n))throw e}return{via:`choice`,choice:i.choice,settled:a}}catch(e){t.abort();try{await r}catch{}throw e}finally{e.prompt.close()}}async function provisionSlackbot(e,t,n,r=defaultDeps,i={}){i.signal?.throwIfAborted();let o=createPromptCommandOutput(e),u={log:e,deps:r,projectRoot:t,onOutput:o},d=await(r.readProjectLink??readProjectLink)(t),p=d?.projectId,m=d?.orgId,h=`slack/${n}`,g=await withPhase(e,`Checking for an existing Slackbot...`,()=>findSlackConnector(r,t,p,h,o,i.signal));if(i.signal?.throwIfAborted(),g.state===`failed`)return e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${g.message}`),{state:`connector-lookup-failed`};if(p===void 0&&g.connectorUids.size>0)return e.warning("Could not verify which Slack connectors belong to this Vercel project, so eve did not create another one. Restore `.vercel/project.json`, then try again."),{state:`connector-lookup-failed`};let finishOutcome=async(t,n,r)=>{let i=n.state===`new`;switch(t.state){case`create-failed`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`unresolved`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`detach-failed`:return e.warning(`Could not remove the connector's existing trigger destination. Run \`vercel connect detach ${t.ref.uid} --yes\`, then \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\`.`),{state:`detach-failed`,connectorUid:t.ref.uid};case`attach-failed`:return e.warning(`Could not register this project as a trigger destination. Run \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\` to enable event delivery.`),{state:`attach-failed`,connectorUid:t.ref.uid};case`attached`:return t.workspace===void 0?{state:`attached`,connectorUid:t.ref.uid}:{state:`attached`,connectorUid:t.ref.uid,chatUrl:t.workspace.workspaceUrl,workspaceName:t.workspace.workspaceName};case`failed`:return e.warning(`Could not verify the Slack workspace connection. ${t.message}`),{state:`installation-check-failed`,connectorUid:t.ref.uid};case`timed-out`:if(e.warning(`The Slackbot did not connect to a Slack workspace in time.`),i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`not-installed`}}},cleanupNewAttempt=async(e,t)=>cleanupCreatedAttempt(u,{expectedUid:h,baselineConnectorUids:e.baselineConnectorUids,createdRef:t});function attemptInput(i,a){return{log:e,deps:r,projectRoot:t,orgId:m,slug:n,source:i,onOutput:o,onCreated:a}}async function runExistingConnector(t){let cleanupCurrentAttempt=async()=>({state:`clean`}),notInstalled=()=>(e.warning(`The existing Slack connector \`${t.ref.uid}\` is not connected to a Slack workspace. eve did not remove it because this run did not create it. If its original browser request is still open, complete it; otherwise run \`vercel connect remove ${t.ref.uid} --disconnect-all --yes\` before trying again.`),{state:`existing-not-installed`,connectorUid:t.ref.uid}),finishExistingOutcome=async e=>e.state===`timed-out`?notInstalled():finishOutcome(e,t,cleanupCurrentAttempt);if(i.awaitChoice!==void 0){let e=await raceAttemptAgainstChoice({prompt:i.awaitChoice({status:`Waiting for the existing Slack workspace connection...`,context:`Complete the original setup in the browser`,actions:[{value:`cancel`,label:`Stop waiting`}]}),outerSignal:i.signal,run:e=>runAttempt({...attemptInput(t,()=>{}),signal:e,phase:(e,t)=>t()})});return e.via===`work`?finishExistingOutcome(e.outcome):e.settled?.state===`attached`?finishExistingOutcome(e.settled):notInstalled()}return finishExistingOutcome(await runAttempt({...attemptInput(t,()=>{}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)}))}async function runUncontrolledAttempt(t){let n,cleanupCurrentAttempt=()=>cleanupNewAttempt(t,n),r=runAttempt({...attemptInput(t,e=>{n=e}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)});try{return await finishOutcome(await r,t,cleanupCurrentAttempt)}catch(e){throw i.signal?.aborted===!0&&await cleanupCurrentAttempt(),e}}async function runInteractiveAttempt(n,a){let s,cleanupCurrentAttempt=()=>cleanupNewAttempt(n,s),l=a({status:`Waiting for Slack setup to finish...`,context:`Complete setup in the browser, then wait while eve verifies the connection`,actions:[{value:`retry`,label:`Did your browser not open? Try again`},{value:`cancel`,label:`Cancel`}]}),u;try{u=await raceAttemptAgainstChoice({prompt:l,outerSignal:i.signal,run:t=>runAttempt({...attemptInput(n,e=>{s=e}),signal:t,phase:e.spinner===void 0?(e,t)=>t():(t,n)=>withPhase(e,t,n)})})}catch(e){throw await cleanupCurrentAttempt(),e}if(u.via===`work`)return{state:`finished`,result:await finishOutcome(u.outcome,n,cleanupCurrentAttempt)};if(u.settled?.state===`attached`)return{state:`finished`,result:await finishOutcome(u.settled,n,cleanupCurrentAttempt)};let d=await cleanupCurrentAttempt();if(d.state===`failed`)return{state:`finished`,result:cleanupFailureResult(d)};if(u.choice===`retry`){let n=await withPhase(e,`Checking existing Slack connectors...`,()=>listSlackConnectors(r,t,o,i.signal));return i.signal?.throwIfAborted(),n.state===`failed`?(e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${n.message}`),{state:`finished`,result:{state:`connector-lookup-failed`}}):{state:`retry`,source:{state:`new`,baselineConnectorUids:new Set(n.connectors.map(e=>e.uid))}}}return{state:`finished`,result:{state:`cancelled`}}}if(g.state===`found`)return runExistingConnector({state:`existing`,ref:g.connector});let _={state:`new`,baselineConnectorUids:g.connectorUids};if(i.awaitChoice===void 0)return runUncontrolledAttempt(_);for(;;){let e=await runInteractiveAttempt(_,i.awaitChoice);if(e.state===`finished`)return e.result;_=e.source}}async function reconcileSlackUid(e,t,n,r){if(n.state!==`attached`||n.connectorUid===r)return!0;let{patched:i}=await updateSlackChannelConnectorUid(join(t,`agent/channels/slack.ts`),n.connectorUid);return i?!0:(e.warning(`Could not patch agent/channels/slack.ts automatically. Update \`connectSlackCredentials("...")\` to \`"${n.connectorUid}"\` and run \`vercel deploy --prod\`.`),!1)}export{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector,provisionSlackbot,reconcileSlackUid};
1
+ import{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector}from"./slack-connect.js";import{CONNECT_LOOKUP_TIMEOUT_MS,attachSlackConnector,cleanupCreatedAttempt,fetchSlackWorkspace,findSlackConnector,listSlackConnectors,readProjectLink}from"./slack-connect-lifecycle.js";import{createSlackConnector}from"./slack-connect-create.js";import{join}from"node:path";import{SLACK_CHANNEL_DEFAULT_ROUTE}from"#setup/scaffold/index.js";import{performance}from"node:perf_hooks";import{captureVercel,runVercel,runVercelCaptureStdout}from"#setup/primitives/run-vercel.js";import{setTimeout}from"node:timers/promises";import{createPromptCommandOutput,withPhase}from"#setup/cli/index.js";import{updateSlackChannelConnectorUid}from"#setup/scaffold/update/update-slack-channel.js";const defaultDeps={captureVercel,runVercel,runVercelCaptureStdout},realDelay=(e,t)=>setTimeout(e,void 0,{signal:t}),monotonicNow=()=>performance.now();async function pollSlackWorkspace(e,t,n,i,a,s){let c=e.delay??realDelay,l=e.now??monotonicNow,u=l()+3e5;for(;;){s?.throwIfAborted();let d=u-l();if(d<=0)return{state:`timed-out`};let f=await fetchSlackWorkspace({deps:e,projectRoot:t,connectorId:n,orgId:i,onOutput:a,timeoutMs:Math.min(CONNECT_LOOKUP_TIMEOUT_MS,d),signal:s});if(s?.throwIfAborted(),f.state!==`pending`)return f;let p=u-l();if(p<=0)return{state:`timed-out`};await c(Math.min(3e3,p),s)}}function isAbortFromSignal(e,t){return t?.aborted===!0&&(e===t.reason||e instanceof Error&&e.name===`AbortError`)}function cleanupFailureResult(e){return{state:`cleanup-failed`,connectorUids:e.connectorUids}}async function runAttempt(e){let{log:t,deps:n,projectRoot:r,orgId:a,onOutput:o,signal:s,phase:c}=e,l,d;if(e.source.state===`existing`)l=e.source.ref;else{let i=await createSlackConnector({deps:n,projectRoot:r,orgId:a,slug:e.slug,onOutput:o,signal:s,phase:c,onCreated:e.onCreated,waitForWorkspace:async(e,t)=>{let i=await pollSlackWorkspace(n,r,e.id,a,o,t);return i.state===`connected`?i.workspace:void 0}});if(i.state===`failed`)return{state:`create-failed`};if(i.state===`unresolved`)return t.warning(`Vercel did not return an exact Slack connector UID for this request, so eve cannot attach or remove it safely.`),{state:`unresolved`};l=i.ref,i.via===`workspace`&&(d=i.workspace)}if(e.source.state===`existing`&&d===void 0){let e=await c(`Waiting for the Slack workspace connection...`,()=>pollSlackWorkspace(n,r,l.id,a,o,s));if(e.state===`timed-out`)return{state:`timed-out`,ref:l};if(e.state===`failed`)return{state:`failed`,ref:l,message:e.message};d=e.workspace}let f=await c(`Configuring Slack event delivery for this agent...`,()=>attachSlackConnector(n,r,l,o,s));return s?.throwIfAborted(),f.state===`attached`?d===void 0?{state:`attached`,ref:l}:{state:`attached`,ref:l,workspace:d}:{state:f.state,ref:l}}async function raceAttemptAgainstChoice(e){let t=new AbortController,n=e.outerSignal?AbortSignal.any([e.outerSignal,t.signal]):t.signal,r=e.run(n);try{let i=await Promise.race([r.then(e=>({via:`work`,outcome:e})),e.prompt.choice.then(e=>({via:`choice`,choice:e}))]);if(i.via===`work`)return i;t.abort();let a;try{a=await r}catch(e){if(!isAbortFromSignal(e,n))throw e}return{via:`choice`,choice:i.choice,settled:a}}catch(e){t.abort();try{await r}catch{}throw e}finally{e.prompt.close()}}async function provisionSlackbot(e,t,n,r=defaultDeps,i={}){i.signal?.throwIfAborted();let o=createPromptCommandOutput(e),u={log:e,deps:r,projectRoot:t,onOutput:o},d=await(r.readProjectLink??readProjectLink)(t),p=d?.projectId,m=d?.orgId,h=`slack/${n}`,g=await withPhase(e,`Checking for an existing Slackbot...`,()=>findSlackConnector(r,t,p,h,o,i.signal));if(i.signal?.throwIfAborted(),g.state===`failed`)return e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${g.message}`),{state:`connector-lookup-failed`};if(p===void 0&&g.connectorUids.size>0)return e.warning("Could not verify which Slack connectors belong to this Vercel project, so eve did not create another one. Restore `.vercel/project.json`, then try again."),{state:`connector-lookup-failed`};let finishOutcome=async(t,n,r)=>{let i=n.state===`new`;switch(t.state){case`create-failed`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`unresolved`:if(i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`create-failed`};case`detach-failed`:return e.warning(`Could not remove the connector's existing trigger destination. Run \`vercel connect detach ${t.ref.uid} --yes\`, then \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\`.`),{state:`detach-failed`,connectorUid:t.ref.uid};case`attach-failed`:return e.warning(`Could not register this project as a trigger destination. Run \`vercel connect attach ${t.ref.uid} --triggers --trigger-path ${SLACK_CHANNEL_DEFAULT_ROUTE} --yes\` to enable event delivery.`),{state:`attach-failed`,connectorUid:t.ref.uid};case`attached`:return t.workspace===void 0?{state:`attached`,connectorUid:t.ref.uid}:{state:`attached`,connectorUid:t.ref.uid,chatUrl:t.workspace.workspaceUrl,workspaceName:t.workspace.workspaceName};case`failed`:return e.warning(`Could not verify the Slack workspace connection. ${t.message}`),{state:`installation-check-failed`,connectorUid:t.ref.uid};case`timed-out`:if(e.warning(`The Slackbot did not connect to a Slack workspace in time.`),i){let e=await r();if(e.state===`failed`)return cleanupFailureResult(e)}return{state:`not-installed`}}},cleanupNewAttempt=async(e,t)=>cleanupCreatedAttempt(u,{expectedUid:h,baselineConnectorUids:e.baselineConnectorUids,createdRef:t});function attemptInput(i,a){return{log:e,deps:r,projectRoot:t,orgId:m,slug:n,source:i,onOutput:o,onCreated:a}}async function runExistingConnector(t){let cleanupCurrentAttempt=async()=>({state:`clean`}),notInstalled=()=>(e.warning(`The existing Slack connector \`${t.ref.uid}\` is not connected to a Slack workspace. eve did not remove it because this run did not create it. If its original browser request is still open, complete it; otherwise run \`vercel connect remove ${t.ref.uid} --disconnect-all --yes\` before trying again.`),{state:`existing-not-installed`,connectorUid:t.ref.uid}),finishExistingOutcome=async e=>e.state===`timed-out`?notInstalled():finishOutcome(e,t,cleanupCurrentAttempt);if(i.awaitChoice!==void 0){let e=await raceAttemptAgainstChoice({prompt:i.awaitChoice({status:`Waiting for the existing Slack workspace connection...`,context:`Complete the original setup in the browser`,actions:[{value:`cancel`,label:`Stop waiting`}]}),outerSignal:i.signal,run:e=>runAttempt({...attemptInput(t,()=>{}),signal:e,phase:(e,t)=>t()})});return e.via===`work`?finishExistingOutcome(e.outcome):e.settled?.state===`attached`?finishExistingOutcome(e.settled):notInstalled()}return finishExistingOutcome(await runAttempt({...attemptInput(t,()=>{}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)}))}async function runUncontrolledAttempt(t){let n,cleanupCurrentAttempt=()=>cleanupNewAttempt(t,n),r=runAttempt({...attemptInput(t,e=>{n=e}),signal:i.signal,phase:(t,n)=>withPhase(e,t,n)});try{return await finishOutcome(await r,t,cleanupCurrentAttempt)}catch(e){throw i.signal?.aborted===!0&&await cleanupCurrentAttempt(),e}}async function runInteractiveAttempt(n,a){let s,cleanupCurrentAttempt=()=>cleanupNewAttempt(n,s),l=a({status:`Waiting for Slack setup to finish...`,context:`Complete setup in the browser, then wait while eve verifies the connection`,actions:[{value:`retry`,label:`Did your browser not open? Try again`},{value:`cancel`,label:`Cancel`}]}),u;try{u=await raceAttemptAgainstChoice({prompt:l,outerSignal:i.signal,run:t=>runAttempt({...attemptInput(n,e=>{s=e}),signal:t,phase:e.spinner===void 0?(e,t)=>t():(t,n)=>withPhase(e,t,n)})})}catch(e){throw await cleanupCurrentAttempt(),e}if(u.via===`work`)return{state:`finished`,result:await finishOutcome(u.outcome,n,cleanupCurrentAttempt)};if(u.settled?.state===`attached`)return{state:`finished`,result:await finishOutcome(u.settled,n,cleanupCurrentAttempt)};let d=await cleanupCurrentAttempt();if(d.state===`failed`)return{state:`finished`,result:cleanupFailureResult(d)};if(u.choice===`retry`){let n=await withPhase(e,`Checking existing Slack connectors...`,()=>listSlackConnectors(r,t,o,i.signal));return i.signal?.throwIfAborted(),n.state===`failed`?(e.warning(`Could not inspect existing Slack connectors, so eve did not create another one. ${n.message}`),{state:`finished`,result:{state:`connector-lookup-failed`}}):{state:`retry`,source:{state:`new`,baselineConnectorUids:new Set(n.connectors.map(e=>e.uid))}}}return{state:`finished`,result:{state:`cancelled`}}}if(g.state===`found`)return runExistingConnector({state:`existing`,ref:g.connector});let _={state:`new`,baselineConnectorUids:g.connectorUids};if(i.awaitChoice===void 0)return runUncontrolledAttempt(_);for(;;){let e=await runInteractiveAttempt(_,i.awaitChoice);if(e.state===`finished`)return e.result;_=e.source}}async function reconcileSlackUid(e,t,n,r){if(n.state!==`attached`||n.connectorUid===r)return!0;let{patched:i}=await updateSlackChannelConnectorUid(join(t,`agent/channels/slack.ts`),n.connectorUid);return i?!0:(e.warning(`Could not patch agent/channels/slack.ts automatically. Update \`connectSlackCredentials("...")\` to \`"${n.connectorUid}"\` and run \`vercel deploy --prod\`.`),!1)}export{parseCreatedSlackConnector,parseSlackConnectorDetails,pickSlackConnector,provisionSlackbot,reconcileSlackUid};
@@ -8,6 +8,12 @@ import { type CreatedProjectFrameworkOptions } from "./vercel-project-framework.
8
8
  export interface PickProjectOptions extends VercelProjectOperationOptions {
9
9
  /** Whether an empty project list may fall back to entering a name to create. */
10
10
  allowCreateWhenEmpty?: boolean;
11
+ /**
12
+ * Searches the team for a project with this name before the list opens and
13
+ * suggests the best match: floated to the top, cursor on it, marked
14
+ * "suggested". Best-effort — a failed lookup falls back to the plain list.
15
+ */
16
+ suggestedName?: string;
11
17
  }
12
18
  export interface PickTeamOptions extends VercelProjectOperationOptions {
13
19
  /** Builds the team selector heading from the current team's display name. */
Binary file
@@ -1,15 +1,9 @@
1
1
  import type { ModelMessage } from "ai";
2
2
  import type { PublicToolInputSchema, PublicToolOutputSchema, ToolModelOutput } from "#shared/tool-definition.js";
3
- import type { SessionContext } from "#public/definitions/callback-context.js";
4
3
  import type { Approval } from "#public/definitions/approval.js";
4
+ import type { ToolContext } from "#public/definitions/tool.js";
5
5
  import type { SessionAuth } from "#context/keys.js";
6
6
  import type { HandleMessageStreamEvent } from "#protocol/message.js";
7
- type ToolContext = SessionContext & {
8
- /** Aborts when the active turn is cancelled. */
9
- readonly abortSignal: AbortSignal;
10
- /** Final runtime name of the current tool. */
11
- readonly toolName: string;
12
- };
13
7
  /**
14
8
  * Stream event types allowed for dynamic tool resolvers. Dispatch
15
9
  * supports any event; this extract restricts the public surface until
@@ -171,4 +165,3 @@ export declare const SKILL_BRAND: unique symbol;
171
165
  * are properly wrapped.
172
166
  */
173
167
  export declare function isBrandedSkillEntry(value: unknown): boolean;
174
- export {};
@@ -15,3 +15,8 @@ export declare function toErrorMessage(error: unknown): string;
15
15
  * `stack`, and `cause` fields onto a fresh Error.
16
16
  */
17
17
  export declare function toError(raw: unknown): Error;
18
+ /**
19
+ * Yields the error itself and every object on its `cause` chain, once
20
+ * each. Cycles terminate the walk instead of looping.
21
+ */
22
+ export declare function walkCauseChain(error: unknown): Generator<unknown>;
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";function toErrorMessage(t){return t instanceof Error?t.message:typeof t==`string`?t:t==null?String(t):isObject(t)?typeof t.message==`string`&&t.message.length>0?t.message:safeJsonStringify(t):String(t)}function toError(t){if(t instanceof Error)return t;let n=Error(toErrorMessage(t));return isObject(t)?(typeof t.name==`string`&&t.name.length>0&&(n.name=t.name),typeof t.stack==`string`&&t.stack.length>0&&(n.stack=t.stack),`cause`in t&&t.cause!==void 0&&t.cause!==t&&(n.cause=t.cause),n):n}function safeJsonStringify(e){try{return JSON.stringify(e)??String(e)}catch{return String(e)}}export{toError,toErrorMessage};
1
+ import{isObject}from"#shared/guards.js";function toErrorMessage(t){return t instanceof Error?t.message:typeof t==`string`?t:t==null?String(t):isObject(t)?typeof t.message==`string`&&t.message.length>0?t.message:safeJsonStringify(t):String(t)}function toError(t){if(t instanceof Error)return t;let n=Error(toErrorMessage(t));return isObject(t)?(typeof t.name==`string`&&t.name.length>0&&(n.name=t.name),typeof t.stack==`string`&&t.stack.length>0&&(n.stack=t.stack),`cause`in t&&t.cause!==void 0&&t.cause!==t&&(n.cause=t.cause),n):n}function*walkCauseChain(t){let n=new Set,r=t;for(;isObject(r)&&!n.has(r);)n.add(r),yield r,r=r.cause}function safeJsonStringify(e){try{return JSON.stringify(e)??String(e)}catch{return String(e)}}export{toError,toErrorMessage,walkCauseChain};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The AI Gateway service tier a model's `providerOptions` requests:
3
+ * `standard` (no tier authored), the `priority` tier eve's Fast mode writes,
4
+ * or any other authored `custom` tier value.
5
+ */
6
+ export type GatewayServiceTierState = {
7
+ kind: "standard";
8
+ } | {
9
+ kind: "priority";
10
+ } | {
11
+ kind: "custom";
12
+ value: string;
13
+ };
14
+ /**
15
+ * Reads `gateway.serviceTier` from an unknown-shaped `providerOptions` value
16
+ * (compiled manifest or `/eve/v1/info` payload). Anything absent or malformed
17
+ * reads as `standard`.
18
+ */
19
+ export declare function readGatewayServiceTier(providerOptions: unknown): GatewayServiceTierState;
@@ -0,0 +1 @@
1
+ function readGatewayServiceTier(e){if(typeof e!=`object`||!e||Array.isArray(e))return{kind:`standard`};let t=e.gateway;if(typeof t!=`object`||!t||Array.isArray(t))return{kind:`standard`};let n=t.serviceTier;return typeof n==`string`?n===`priority`?{kind:`priority`}:{kind:`custom`,value:n}:{kind:`standard`}}export{readGatewayServiceTier};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The one-line model summary grammar shared by the dev TUI's status line and
3
+ * the /model menu's Change model hint: `slug@level ↯`. One implementation so
4
+ * the two surfaces cannot drift.
5
+ */
6
+ export declare function formatModelSummary(input: {
7
+ model: string;
8
+ /** Authored reasoning level; omitted renders the bare slug. */
9
+ reasoning?: string;
10
+ /** The Fast mode marker glyph, present only when the priority tier is on. */
11
+ fastGlyph?: string;
12
+ }): string;
@@ -0,0 +1 @@
1
+ function formatModelSummary(e){let t=e.reasoning===void 0?``:`@${e.reasoning}`,n=e.fastGlyph===void 0?``:` ${e.fastGlyph}`;return`${e.model}${t}${n}`}export{formatModelSummary};
@@ -8,6 +8,7 @@ export type WorkflowSandboxLifecycle = NonNullable<CodeModeModule.CodeModeOption
8
8
  export type WorkflowSandboxContinuationSecurity = CodeModeModule.CodeModeContinuationSecurityOptions;
9
9
  export declare function installWorkflowSandboxModule(module: WorkflowSandboxModule): void;
10
10
  export declare function createWorkflowSandboxTool(input: {
11
+ readonly bridgeRequestLimit: number;
11
12
  readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
12
13
  readonly hostTools: ToolSet;
13
14
  readonly lifecycle?: WorkflowSandboxLifecycle;
@@ -20,6 +21,7 @@ export declare function requestWorkflowSandboxInterrupt(input: {
20
21
  }): Promise<unknown>;
21
22
  export declare function getWorkflowSandboxInterrupt(result: unknown, continuationSecurity: WorkflowSandboxContinuationSecurity): Promise<WorkflowSandboxInterrupt | undefined>;
22
23
  export declare function continueWorkflowSandboxInterrupt(input: {
24
+ readonly bridgeRequestLimit: number;
23
25
  readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
24
26
  readonly interrupt: WorkflowSandboxInterrupt;
25
27
  readonly lifecycle?: WorkflowSandboxLifecycle;
@@ -1 +1 @@
1
- const WORKFLOW_TOOL_NAME=`Workflow`,WORKFLOW_SANDBOX_MODULE_KEY=Symbol.for(`eve.workflowSandbox.module`),WORKFLOW_SANDBOX_MODULE_SPECIFIER=[`#compiled`,`experimental-ai-sdk-code-mode`,`index.js`].join(`/`);let workflowSandboxModulePromise;function installWorkflowSandboxModule(e){globalThis[WORKFLOW_SANDBOX_MODULE_KEY]=e}async function createWorkflowSandboxTool(e){let{createCodeModeTool:t}=await loadWorkflowSandboxModule();return t(e.hostTools,createWorkflowSandboxOptions(e.continuationSecurity,e.lifecycle))}async function requestWorkflowSandboxInterrupt(e){let{requestCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t(e)}async function getWorkflowSandboxInterrupt(e,t){let{getCodeModeInterrupt:n}=await loadWorkflowSandboxModule();return n(e,t)}async function continueWorkflowSandboxInterrupt(e){let{continueCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t({interrupt:e.interrupt,options:createWorkflowSandboxOptions(e.continuationSecurity,e.lifecycle),resolution:e.resolution,tools:e.tools})}async function unwrapWorkflowSandboxResult(e,t){let{unwrapCodeModeResult:n}=await loadWorkflowSandboxModule();return n(e,t)}function readWorkflowSandboxResolution(e){if(typeof e!=`object`||!e)return;let t=e.codeModeInterrupt;if(!(typeof t!=`object`||!t))return t.resolution}function createWorkflowSandboxOptions(e,t){let n={continuationSecurity:e};return t!==void 0&&(n.lifecycle=t),n}async function loadWorkflowSandboxModule(){let e=globalThis[WORKFLOW_SANDBOX_MODULE_KEY];return e===void 0?(workflowSandboxModulePromise??=importWorkflowSandboxModule(WORKFLOW_SANDBOX_MODULE_SPECIFIER),await workflowSandboxModulePromise):e}async function importWorkflowSandboxModule(e){return await import(e)}export{WORKFLOW_TOOL_NAME,continueWorkflowSandboxInterrupt,createWorkflowSandboxTool,getWorkflowSandboxInterrupt,installWorkflowSandboxModule,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult};
1
+ const WORKFLOW_TOOL_NAME=`Workflow`,WORKFLOW_SANDBOX_MODULE_KEY=Symbol.for(`eve.workflowSandbox.module`),WORKFLOW_SANDBOX_MODULE_SPECIFIER=[`#compiled`,`experimental-ai-sdk-code-mode`,`index.js`].join(`/`);let workflowSandboxModulePromise;function installWorkflowSandboxModule(e){globalThis[WORKFLOW_SANDBOX_MODULE_KEY]=e}async function createWorkflowSandboxTool(e){let{createCodeModeTool:t}=await loadWorkflowSandboxModule();return t(e.hostTools,createWorkflowSandboxOptions(e.bridgeRequestLimit,e.continuationSecurity,e.lifecycle))}async function requestWorkflowSandboxInterrupt(e){let{requestCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t(e)}async function getWorkflowSandboxInterrupt(e,t){let{getCodeModeInterrupt:n}=await loadWorkflowSandboxModule();return n(e,t)}async function continueWorkflowSandboxInterrupt(e){let{continueCodeModeInterrupt:t}=await loadWorkflowSandboxModule();return t({interrupt:e.interrupt,options:createWorkflowSandboxOptions(e.bridgeRequestLimit,e.continuationSecurity,e.lifecycle),resolution:e.resolution,tools:e.tools})}async function unwrapWorkflowSandboxResult(e,t){let{unwrapCodeModeResult:n}=await loadWorkflowSandboxModule();return n(e,t)}function readWorkflowSandboxResolution(e){if(typeof e!=`object`||!e)return;let t=e.codeModeInterrupt;if(!(typeof t!=`object`||!t))return t.resolution}function createWorkflowSandboxOptions(e,t,n){let r={continuationSecurity:t,executionPolicy:{maxBridgeRequests:e,maxInFlightBridgeRequests:e}};return n!==void 0&&(r.lifecycle=n),r}async function loadWorkflowSandboxModule(){let e=globalThis[WORKFLOW_SANDBOX_MODULE_KEY];return e===void 0?(workflowSandboxModulePromise??=importWorkflowSandboxModule(WORKFLOW_SANDBOX_MODULE_SPECIFIER),await workflowSandboxModulePromise):e}async function importWorkflowSandboxModule(e){return await import(e)}export{WORKFLOW_TOOL_NAME,continueWorkflowSandboxInterrupt,createWorkflowSandboxTool,getWorkflowSandboxInterrupt,installWorkflowSandboxModule,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult};
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The AST plumbing shared by the agent-config source editors: the loose
3
+ * Rolldown node shapes, the parse-and-locate-`defineAgent({ ... })` pipeline,
4
+ * and the string-splicing helpers. Editors own their edit policies; this
5
+ * module owns how an agent config is read.
6
+ */
7
+ export type Program = {
8
+ readonly body?: readonly AstNode[];
9
+ };
10
+ export type AstNode = {
11
+ readonly arguments?: readonly AstNode[];
12
+ readonly callee?: AstNode;
13
+ readonly computed?: boolean;
14
+ readonly declaration?: AstNode | null;
15
+ readonly end?: number;
16
+ readonly expression?: AstNode | null;
17
+ readonly key?: AstNode;
18
+ readonly name?: string;
19
+ readonly properties?: readonly AstNode[];
20
+ readonly raw?: string;
21
+ readonly start?: number;
22
+ readonly type?: string;
23
+ readonly value?: AstNode | string | number | boolean | null;
24
+ };
25
+ export type ObjectExpression = AstNode & {
26
+ readonly end: number;
27
+ readonly properties: readonly AstNode[];
28
+ readonly start: number;
29
+ readonly type: "ObjectExpression";
30
+ };
31
+ export type ParsedAgentObject = {
32
+ readonly kind: "ok";
33
+ readonly object: ObjectExpression;
34
+ } | {
35
+ readonly kind: "bail";
36
+ readonly reason: string;
37
+ readonly line: number;
38
+ };
39
+ /** Parses a source and locates the `export default defineAgent({ ... })` object. */
40
+ export declare function parseAgentObject(sourceText: string): Promise<ParsedAgentObject>;
41
+ /**
42
+ * The write-guard invariant: an edited source must still parse and still
43
+ * carry the `defineAgent({ ... })` object. Returns the failure reason, or
44
+ * undefined when the source is sound. Callers bail instead of writing, so an
45
+ * editor bug degrades to a "change it by hand" message rather than a broken
46
+ * agent.ts.
47
+ */
48
+ export declare function checkAgentConfigSource(sourceText: string): Promise<string | undefined>;
49
+ /** Strips `as`, `satisfies`, and parentheses to reach the underlying expression. */
50
+ export declare function unwrapExpression(expression: AstNode): AstNode;
51
+ export declare function keyMatches(key: AstNode | undefined, name: string): boolean;
52
+ export declare function isAstNode(value: unknown): value is AstNode;
53
+ export declare function escapeForQuote(value: string, quote: '"' | "'"): string;
54
+ export declare function lineAt(source: string, offset: number): number;
@@ -0,0 +1,2 @@
1
+ import{parseWithNitroRolldownAst}from"#internal/bundler/nitro-rolldown.js";async function parseAgentObject(t){let n;try{n=await parseWithNitroRolldownAst(`agent.ts`,t)}catch(e){let n=e;return{kind:`bail`,reason:`agent.ts does not parse: ${n.message??`unknown parse error`}`,line:parseErrorLine(t,n)}}if((n.errors?.length??0)>0){let e=n.errors?.[0];return{kind:`bail`,reason:`agent.ts does not parse: ${e?.message??`unknown parse error`}`,line:parseErrorLine(t,e)}}let r=findDefineAgentObject(n.program??n);return r===void 0?{kind:`bail`,reason:"no `export default defineAgent({ ... })` call found",line:1}:{kind:`ok`,object:r}}async function checkAgentConfigSource(e){let t=await parseAgentObject(e);return t.kind===`bail`?t.reason:void 0}function findDefineAgentObject(e){for(let t of e.body??[]){if(t.type!==`ExportDefaultDeclaration`||t.declaration==null)continue;let e=unwrapExpression(t.declaration);if(e.type!==`CallExpression`||e.callee?.type!==`Identifier`||e.callee.name!==`defineAgent`)continue;let n=e.arguments?.[0];if(n===void 0||n.type===`SpreadElement`)continue;let r=unwrapExpression(n);if(r.type===`ObjectExpression`&&r.start!==void 0&&r.end!==void 0&&r.properties!==void 0)return r}}function unwrapExpression(e){let t=e;for(;t.type===`ParenthesizedExpression`||t.type===`TSAsExpression`||t.type===`TSSatisfiesExpression`;){if(t.expression==null)return t;t=t.expression}return t}function keyMatches(e,t){return e?.type===`Identifier`?e.name===t:e?.type===`Literal`&&typeof e.value==`string`&&e.value===t}function isAstNode(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function escapeForQuote(e,t){return e.replaceAll(`\\`,`\\\\`).replaceAll(t,`\\${t}`)}function lineAt(e,t){let n=1;for(let r=0;r<t&&r<e.length;r+=1)e[r]===`
2
+ `&&(n+=1);return n}function parseErrorLine(e,t){return typeof t?.loc?.line==`number`?t.loc.line:lineAt(e,t?.labels?.[0]?.start??t?.start??0)}export{checkAgentConfigSource,escapeForQuote,isAstNode,keyMatches,lineAt,parseAgentObject,unwrapExpression};
@@ -0,0 +1,18 @@
1
+ export { checkAgentConfigSource } from "./agent-config-ast.js";
2
+ export type AgentConfigStringPathPatch = {
3
+ readonly kind: "set";
4
+ readonly value: string;
5
+ } | {
6
+ readonly kind: "remove";
7
+ readonly removable?: (value: string) => boolean;
8
+ };
9
+ export type AgentConfigStringPathEdit = {
10
+ readonly kind: "applied";
11
+ readonly nextSource: string;
12
+ } | {
13
+ readonly kind: "bail";
14
+ readonly reason: string;
15
+ readonly line: number;
16
+ };
17
+ /** Safely applies one literal string leaf below `defineAgent({ ... })`. */
18
+ export declare function applyAgentConfigStringPath(sourceText: string, path: readonly [string, ...string[]], patch: AgentConfigStringPathPatch): Promise<AgentConfigStringPathEdit>;
@@ -0,0 +1,2 @@
1
+ import{checkAgentConfigSource,escapeForQuote,isAstNode,keyMatches,lineAt,parseAgentObject,unwrapExpression}from"./agent-config-ast.js";async function applyAgentConfigStringPath(e,n,r){let o=await parseAgentObject(e);if(o.kind===`bail`)return o;let s=[o.object],c=[],l=o.object;for(let[t,a]of n.slice(0,-1).entries()){let o=findProperty(l,a);if(o.kind===`bail`)return{...o,line:lineAt(e,l.start)};if(o.property===void 0){if(r.kind===`remove`)return{kind:`applied`,nextSource:e};let i=nestedObjectSource(n.slice(t+1),r.value);return{kind:`applied`,nextSource:insertProperty(e,l,a,i)}}let u=propertyObjectValue(o.property);if(u===void 0)return{kind:`bail`,reason:`\`${a}\` is not an object literal that eve can edit safely`,line:lineAt(e,o.property.start)};c.push(o.property),s.push(u),l=u}let u=n.at(-1),d=findProperty(l,u);if(d.kind===`bail`)return{...d,line:lineAt(e,l.start)};if(d.property===void 0)return r.kind===`remove`?{kind:`applied`,nextSource:e}:{kind:`applied`,nextSource:insertProperty(e,l,u,JSON.stringify(r.value))};let f=propertyStringValue(d.property);if(f===void 0)return{kind:`bail`,reason:`\`${n.join(`.`)}\` is not a string literal that eve can edit safely`,line:lineAt(e,d.property.start)};if(r.kind===`set`){if(f.value===r.value)return{kind:`applied`,nextSource:e};let n=f.raw?.[0]===`'`?`'`:`"`,i=`${n}${escapeForQuote(r.value,n)}${n}`;return{kind:`applied`,nextSource:e.slice(0,f.start)+i+e.slice(f.end)}}if(r.removable!==void 0&&!r.removable(f.value))return{kind:`bail`,reason:`\`${n.join(`.`)}\` has the custom value ${JSON.stringify(f.value)}`,line:lineAt(e,d.property.start)};let p=d.property,m=l;for(let e=s.length-1;e>0&&m.properties.length===1;--e)p=c[e-1],m=s[e-1];return{kind:`applied`,nextSource:removeProperty(e,m,p)}}function findProperty(e,t){if(e.properties.some(e=>e.type===`SpreadElement`||e.computed===!0))return{kind:`bail`,reason:`\`${t}\` may be supplied by a spread or computed property`};let n=e.properties.filter(e=>e.type===`Property`&&!e.computed&&keyMatches(e.key,t));if(n.length>1)return{kind:`bail`,reason:`\`${t}\` is defined more than once`};let i=n[0];return i!==void 0&&i.start!==void 0&&i.end!==void 0?{kind:`ok`,property:i}:{kind:`ok`}}function propertyObjectValue(e){let t=e.value;if(!isAstNode(t))return;let r=unwrapExpression(t);return r.type===`ObjectExpression`&&r.start!==void 0&&r.end!==void 0&&r.properties!==void 0?r:void 0}function propertyStringValue(e){let t=e.value;if(!isAstNode(t))return;let r=unwrapExpression(t);if(r.type!==`Literal`||typeof r.value!=`string`||r.start===void 0||r.end===void 0)return;let i={start:r.start,end:r.end,value:r.value};return r.raw===void 0?i:{...i,raw:r.raw}}function nestedObjectSource(e,t){let n=JSON.stringify(t);for(let t of[...e].reverse())n=`{ ${t}: ${n} }`;return n}function insertProperty(e,t,n,r){let i=t.end-1,a=t.properties.at(-1);if(a===void 0||a.end===void 0)return e.slice(0,i)+` ${n}: ${r} `+e.slice(i);let o=e.lastIndexOf(`
2
+ `,i-1)+1;if(o>t.start){let t=`${e.slice(o,i)} `,s=e.slice(a.end,o),c=e;s.includes(`,`)||(c=c.slice(0,a.end)+`,`+c.slice(a.end));let l=o+ +!s.includes(`,`);return c.slice(0,l)+`${t}${n}: ${r},\n`+c.slice(l)}let s=e.slice(a.end,i).includes(`,`)?` `:`, `;return e.slice(0,i)+`${s}${n}: ${r}`+e.slice(i)}function removeProperty(e,t,n){let r=t.properties.indexOf(n),i=r>0?t.properties[r-1]:void 0,a=r>=0?t.properties[r+1]:void 0;return a?.start===void 0?i?.end===void 0?e.slice(0,t.start+1)+e.slice(t.end-1):e.slice(0,i.end)+e.slice(n.end):e.slice(0,n.start)+e.slice(a.start)}export{applyAgentConfigStringPath,checkAgentConfigSource};
@@ -0,0 +1,26 @@
1
+ import type { AgentReasoningDefinition } from "#shared/agent-definition.js";
2
+ export type FieldPatch<T> = {
3
+ readonly kind: "keep";
4
+ } | {
5
+ readonly kind: "set";
6
+ readonly value: T;
7
+ } | {
8
+ readonly kind: "remove";
9
+ };
10
+ export interface AgentModelSettingsPatch {
11
+ readonly model: FieldPatch<string>;
12
+ readonly reasoning: FieldPatch<AgentReasoningDefinition>;
13
+ readonly gatewayServiceTier: FieldPatch<"priority">;
14
+ }
15
+ export type AgentModelSetting = "model" | "reasoning" | "fast-mode";
16
+ export type AgentModelSettingsEdit = {
17
+ readonly kind: "applied";
18
+ readonly changed: readonly AgentModelSetting[];
19
+ readonly nextSource: string;
20
+ } | {
21
+ readonly kind: "bail";
22
+ readonly reason: string;
23
+ readonly line: number;
24
+ };
25
+ /** Applies every model-setting change in memory; callers own the atomic write. */
26
+ export declare function applyAgentModelSettingsToSource(sourceText: string, patch: AgentModelSettingsPatch): Promise<AgentModelSettingsEdit>;
@@ -0,0 +1 @@
1
+ import{applyAgentConfigStringPath}from"./agent-config-string-path.js";import{applyModelNameToSource}from"./apply-model-name.js";async function applyAgentModelSettingsToSource(n,r){let i=n,a=[];if(r.model.kind===`remove`)return{kind:`bail`,reason:"the required `model` property cannot be removed",line:1};if(r.model.kind===`set`){let e=await applyModelNameToSource(i,r.model.value);if(e.kind===`bail`)return e;e.nextSource!==i&&a.push(`model`),i=e.nextSource}if(r.reasoning.kind!==`keep`){let t=await applyAgentConfigStringPath(i,[`reasoning`],r.reasoning.kind===`set`?{kind:`set`,value:r.reasoning.value}:{kind:`remove`});if(t.kind===`bail`)return t;t.nextSource!==i&&a.push(`reasoning`),i=t.nextSource}if(r.gatewayServiceTier.kind!==`keep`){let t=await applyAgentConfigStringPath(i,[`modelOptions`,`providerOptions`,`gateway`,`serviceTier`],r.gatewayServiceTier.kind===`set`?{kind:`set`,value:r.gatewayServiceTier.value}:{kind:`remove`,removable:e=>e===`priority`});if(t.kind===`bail`)return t;t.nextSource!==i&&a.push(`fast-mode`),i=t.nextSource}return{kind:`applied`,changed:a,nextSource:i}}export{applyAgentModelSettingsToSource};
@@ -1,2 +1 @@
1
- import{parseWithNitroRolldownAst}from"#internal/bundler/nitro-rolldown.js";const AGENT_FACTORY=`defineAgent`;async function applyModelNameToSource(e,n){let r=await parseAgentSource(e);if(`kind`in r)return r;if((r.errors?.length??0)>0){let t=r.errors?.[0];return{kind:`bail`,reason:`agent.ts does not parse: ${t?.message??`unknown parse error`}`,line:parseErrorLine(e,t)}}let i=findDefineAgentObject(r.program??r,AGENT_FACTORY);if(i===void 0)return{kind:`bail`,reason:`no \`export default ${AGENT_FACTORY}({ ... })\` call found`,line:1};let a=findStringLiteralProperty(i,`model`);if(a===void 0)return{kind:`bail`,reason:"`model` is absent or is not a string literal (e.g. an env reference, a template, an inlined SDK model, or a defineDynamic() dynamic model)",line:lineAt(e,i.start??0)};let o=a.value;if(o===n)return{kind:`applied`,from:o,to:n,nextSource:e};let s=a.raw?.[0]===`'`?`'`:`"`,c=`${s}${escapeForQuote(n,s)}${s}`;return{kind:`applied`,from:o,to:n,nextSource:e.slice(0,a.start)+c+e.slice(a.end)}}async function parseAgentSource(t){try{return await parseWithNitroRolldownAst(`agent.ts`,t)}catch(e){let n=e;return{kind:`bail`,reason:`agent.ts does not parse: ${n.message??`unknown parse error`}`,line:parseErrorLine(t,n)}}}function unwrapExpression(e){let t=e;for(;t.type===`ParenthesizedExpression`||t.type===`TSAsExpression`||t.type===`TSSatisfiesExpression`;){if(t.expression===void 0||t.expression===null)return t;t=t.expression}return t}function findDefineAgentObject(e,t){for(let n of e.body??[]){if(n.type!==`ExportDefaultDeclaration`)continue;let e=n.declaration;if(e==null||e.type!==`CallExpression`&&e.type!==`ParenthesizedExpression`&&e.type!==`TSAsExpression`&&e.type!==`TSSatisfiesExpression`)continue;let r=unwrapExpression(e);if(r.type!==`CallExpression`||!isFactoryCallee(r.callee,t))continue;let i=r.arguments?.[0];if(i===void 0||i.type===`SpreadElement`)continue;let a=unwrapExpression(i);if(a.type===`ObjectExpression`)return a}}function isFactoryCallee(e,t){return e?.type===`Identifier`&&e.name===t}function findStringLiteralProperty(e,t){for(let n of e.properties){if(n.type!==`Property`||n.computed||!keyMatches(n.key,t))continue;let e=n.value;if(!isAstNode(e))continue;let r=unwrapExpression(e);return r.type===`Literal`&&typeof r.value==`string`&&r.start!==void 0&&r.end!==void 0?r:void 0}}function keyMatches(e,t){return e===void 0?!1:e.type===`Identifier`?e.name===t:e.type===`Literal`?typeof e.value==`string`&&e.value===t:!1}function isAstNode(e){return typeof e==`object`&&!!e&&typeof e.type==`string`}function parseErrorLine(e,t){return typeof t?.loc?.line==`number`?t.loc.line:lineAt(e,t?.labels?.[0]?.start??t?.start??0)}function escapeForQuote(e,t){return e.replaceAll(`\\`,`\\\\`).replaceAll(t,`\\${t}`)}function lineAt(e,t){let n=1;for(let r=0;r<t&&r<e.length;r+=1)e[r]===`
2
- `&&(n+=1);return n}export{applyModelNameToSource};
1
+ import{escapeForQuote,isAstNode,keyMatches,lineAt,parseAgentObject,unwrapExpression}from"./agent-config-ast.js";async function applyModelNameToSource(t,n){let a=await parseAgentObject(t);if(a.kind===`bail`)return a;let o=a.object,s=findStringLiteralProperty(o,`model`);if(s===void 0)return{kind:`bail`,reason:"`model` is absent or is not a string literal (e.g. an env reference, a template, an inlined SDK model, or a defineDynamic() dynamic model)",line:lineAt(t,o.start)};let c=s.value;if(c===n)return{kind:`applied`,from:c,to:n,nextSource:t};let l=s.raw?.[0]===`'`?`'`:`"`,u=`${l}${escapeForQuote(n,l)}${l}`;return{kind:`applied`,from:c,to:n,nextSource:t.slice(0,s.start)+u+t.slice(s.end)}}function findStringLiteralProperty(e,r){for(let i of e.properties){if(i.type!==`Property`||i.computed||!keyMatches(i.key,r))continue;let e=i.value;if(!isAstNode(e))continue;let o=unwrapExpression(e);return o.type===`Literal`&&typeof o.value==`string`&&o.start!==void 0&&o.end!==void 0?o:void 0}}export{applyModelNameToSource};
@@ -1,4 +1,5 @@
1
1
  import type { AgentSourceManifest } from "#discover/manifest.js";
2
+ import { type AgentModelSetting, type AgentModelSettingsPatch } from "#source-change/apply-agent-model-settings.js";
2
3
  /**
3
4
  * Outcome of a static source change, returned to upstream callers (CLI, web
4
5
  * setup UI) so they can render success or route the bail to a guided fix.
@@ -15,6 +16,17 @@ export type ApplyResult = {
15
16
  readonly line: number;
16
17
  };
17
18
  };
19
+ export type ApplyModelSettingsResult = {
20
+ readonly kind: "applied";
21
+ readonly changed: readonly AgentModelSetting[];
22
+ } | {
23
+ readonly kind: "bail";
24
+ readonly reason: string;
25
+ readonly at: {
26
+ readonly logicalPath: string;
27
+ readonly line: number;
28
+ };
29
+ };
18
30
  /**
19
31
  * Central, flat API for applying targeted edits to an agent's authored source.
20
32
  *
@@ -29,6 +41,8 @@ export interface StaticSourceChange {
29
41
  * the caller can offer a manual fix.
30
42
  */
31
43
  updateModelName(modelName: string): Promise<ApplyResult>;
44
+ /** Applies the `/model` draft in one source transform and one atomic rename. */
45
+ updateModelSettings(patch: AgentModelSettingsPatch): Promise<ApplyModelSettingsResult>;
32
46
  }
33
47
  /**
34
48
  * Creates the {@link StaticSourceChange} surface bound to one discovered agent.
@@ -1 +1 @@
1
- import{join}from"node:path";import{readFile,rename,writeFile}from"node:fs/promises";import{applyModelNameToSource}from"#source-change/apply-model-name.js";function createStaticSourceChange(e){return{updateModelName:t=>updateAgentModelName(e,t)}}async function updateAgentModelName(n,r){let i=n.configModule;if(i===void 0)return{kind:`bail`,reason:`agent has no agent.ts config module to edit`,at:{logicalPath:`agent.ts`,line:1}};let a=join(n.agentRoot,i.logicalPath),o=await readFile(a,`utf8`),s=await applyModelNameToSource(o,r);if(s.kind===`bail`)return{kind:`bail`,reason:s.reason,at:{logicalPath:i.logicalPath,line:s.line}};if(s.nextSource!==o){let e=`${a}.${process.pid}.eve-tmp`;await writeFile(e,s.nextSource,`utf8`),await rename(e,a)}return{kind:`applied`,from:s.from,to:s.to}}export{createStaticSourceChange};
1
+ import{join}from"node:path";import{readFile,rename,writeFile}from"node:fs/promises";import{checkAgentConfigSource}from"#source-change/agent-config-string-path.js";import{applyAgentModelSettingsToSource}from"#source-change/apply-agent-model-settings.js";import{applyModelNameToSource}from"#source-change/apply-model-name.js";function createStaticSourceChange(e){return{updateModelName:t=>updateAgentModelName(e,t),updateModelSettings:t=>updateAgentModelSettings(e,t)}}async function updateAgentModelSettings(n,r){let i=n.configModule;if(i===void 0)return{kind:`bail`,reason:`agent has no agent.ts config module to edit`,at:{logicalPath:`agent.ts`,line:1}};let o=join(n.agentRoot,i.logicalPath),s=await readFile(o,`utf8`),c=await applyAgentModelSettingsToSource(s,r);if(c.kind===`bail`)return{kind:`bail`,reason:c.reason,at:{logicalPath:i.logicalPath,line:c.line}};let l=await editedSourceBail(s,c.nextSource,i.logicalPath);return l===void 0?(await writeSourceIfChanged(o,s,c.nextSource),{kind:`applied`,changed:c.changed}):l}async function updateAgentModelName(n,r){let i=n.configModule;if(i===void 0)return{kind:`bail`,reason:`agent has no agent.ts config module to edit`,at:{logicalPath:`agent.ts`,line:1}};let a=join(n.agentRoot,i.logicalPath),s=await readFile(a,`utf8`),c=await applyModelNameToSource(s,r);if(c.kind===`bail`)return{kind:`bail`,reason:c.reason,at:{logicalPath:i.logicalPath,line:c.line}};let l=await editedSourceBail(s,c.nextSource,i.logicalPath);return l===void 0?(await writeSourceIfChanged(a,s,c.nextSource),{kind:`applied`,from:c.from,to:c.to}):l}async function writeSourceIfChanged(e,t,i){if(i===t)return;let a=`${e}.${process.pid}.eve-tmp`;await writeFile(a,i,`utf8`),await rename(a,e)}async function editedSourceBail(e,t,n){if(t===e)return;let r=await checkAgentConfigSource(t);if(r!==void 0)return{kind:`bail`,reason:`the edit produced source eve refuses to write (${r})`,at:{logicalPath:n,line:1}}}export{createStaticSourceChange};
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CQIeqmKc.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CruinZmd.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -80,12 +80,6 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
80
80
  readonly initialEvents?: readonly HandleMessageStreamEvent[];
81
81
  /** Seed session identity and stream cursor for resuming a prior conversation. */
82
82
  readonly initialSession?: SessionState;
83
- /**
84
- * Maximum number of stream reconnection attempts per turn.
85
- *
86
- * @default 3
87
- */
88
- readonly maxReconnectAttempts?: number;
89
83
  /**
90
84
  * Project submitted user messages before eve confirms them with a
91
85
  * `message.received` stream event. Optimistic events are reducer-facing
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-CQIeqmKc.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-CruinZmd.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Cy73lgA6.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BkztZA0v.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -79,8 +79,6 @@ export interface UseEveAgentOptions<TData> extends EveAgentStoreCallbacks<TData>
79
79
  readonly initialEvents?: readonly HandleMessageStreamEvent[];
80
80
  /** Prior session cursor to resume from on mount. */
81
81
  readonly initialSession?: SessionState;
82
- /** Maximum SSE reconnection attempts per turn. @default 3 */
83
- readonly maxReconnectAttempts?: number;
84
82
  /**
85
83
  * Project submitted user messages before eve confirms them with a
86
84
  * `message.received` stream event.
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Cy73lgA6.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-BkztZA0v.js";
2
2
 
3
3
  export { useEveAgent };
@@ -36,7 +36,7 @@ export default defineAgent({
36
36
  });
37
37
  ```
38
38
 
39
- The world package backs workflow state, queues, hooks, and streams. Keep secrets and deployment-specific options in runtime environment variables read by that package, not in `agent.ts`. Custom worlds must implement the runtime protocol expected by eve's vendored `@workflow/*` packages (currently the `5.0.0-beta` line); the Workflow SDK rejects incompatible protocol versions during initialization. See the [deployment guide](../guides/deployment#8-deploy-without-vercel) for the install command, plus [agent.ts](../agent-config#workflow-world) and [Workflow Worlds](https://workflow-sdk.dev/worlds).
39
+ The world package backs workflow state, queues, hooks, and streams. Keep secrets and deployment-specific options in runtime environment variables read by that package, not in `agent.ts`. Custom worlds must implement the runtime protocol expected by eve's vendored `@workflow/*` packages (currently the `5.0.0-beta` line); the Workflow SDK rejects incompatible protocol versions during initialization. See [Self-host eve](../guides/deployment/self-hosting#persist-workflow-state), [agent.ts](../agent-config#workflow-world), and [Workflow Worlds](https://workflow-sdk.dev/worlds).
40
40
 
41
41
  ## Resuming after a crash
42
42
 
@@ -110,7 +110,7 @@ Custom channel routes request the same cancellation without knowing the session
110
110
 
111
111
  ## Reconnect and rewind
112
112
 
113
- The stream is durable. Every event is recorded before a step completes, so the whole stream is replayable. A nonnegative `startIndex` is an absolute event count: use it to pick up where you dropped off or pass `0` to rewind to the start.
113
+ The stream is durable. Every event is recorded before a step completes, so consumers can reconnect from their cursor when an HTTP connection ends. A nonnegative `startIndex` is an absolute event count: use it to pick up where you dropped off or pass `0` to rewind to the start.
114
114
 
115
115
  ```bash
116
116
  curl "http://127.0.0.1:3000/eve/v1/session/<sessionId>/stream?startIndex=<count>"
@@ -130,7 +130,7 @@ Other commands the eve binary provides (prefix each with `npx`, or add a matchin
130
130
 
131
131
  In the dev TUI, type a message and watch it happen in order. First the `get_weather` call, then its result, then the reply.
132
132
 
133
- The same CLI can point at a deployment. `npx eve dev https://your-app.vercel.app` drives a deployed app, which is handy for preview and production smoke tests. See [Deployment](./guides/deployment).
133
+ The same CLI can point at a deployment. `npx eve dev https://your-app.vercel.app` drives a deployed app, which is handy for preview and production smoke tests. See [Deployment](./guides/deployment/overview).
134
134
 
135
135
  ## Send a message
136
136
 
@@ -373,4 +373,4 @@ Inline providers derive a stable tool-qualified auth key from Vercel Connect met
373
373
 
374
374
  - [Security model](../concepts/security-model): trust boundaries and the pre-production checklist
375
375
  - [Connections](../connections): connection auth shapes (`connect()` vs static token)
376
- - [Deployment](./deployment): where route-auth secrets live in production
376
+ - [Deployment](./deployment/overview): where route-auth secrets live in production