eve 0.8.2 → 0.8.4

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 (67) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/src/chunks/{use-eve-agent-Dlut2Qzt.js → use-eve-agent-CdETo3qQ.js} +1 -0
  3. package/dist/src/chunks/{use-eve-agent-BSXZSn-R.js → use-eve-agent-ClyM-_UT.js} +1 -0
  4. package/dist/src/cli/banner.d.ts +2 -2
  5. package/dist/src/cli/banner.js +1 -1
  6. package/dist/src/cli/dev/tui/agent-header.d.ts +1 -1
  7. package/dist/src/cli/dev/tui/agent-header.js +1 -1
  8. package/dist/src/cli/dev/tui/log-display-mode.d.ts +13 -0
  9. package/dist/src/cli/dev/tui/log-display-mode.js +1 -0
  10. package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
  11. package/dist/src/cli/dev/tui/runner.js +1 -1
  12. package/dist/src/cli/dev/tui/status-line.d.ts +13 -4
  13. package/dist/src/cli/dev/tui/status-line.js +1 -1
  14. package/dist/src/cli/dev/tui/stream-format.d.ts +1 -2
  15. package/dist/src/cli/dev/tui/stream-format.js +1 -1
  16. package/dist/src/cli/dev/tui/terminal-renderer.js +6 -6
  17. package/dist/src/cli/dev/tui/theme.d.ts +0 -2
  18. package/dist/src/cli/dev/tui/theme.js +1 -1
  19. package/dist/src/cli/dev/tui/types.d.ts +8 -11
  20. package/dist/src/cli/run.js +2 -2
  21. package/dist/src/execution/sandbox/bindings/docker-base-setup.d.ts +3 -5
  22. package/dist/src/execution/sandbox/bindings/docker-base-setup.js +1 -1
  23. package/dist/src/execution/sandbox/bindings/docker.js +1 -1
  24. package/dist/src/execution/sandbox/bindings/microsandbox-platform.d.ts +2 -3
  25. package/dist/src/execution/sandbox/bindings/microsandbox-platform.js +3 -160
  26. package/dist/src/execution/sandbox/bindings/vercel-base-runtime.d.ts +6 -0
  27. package/dist/src/execution/sandbox/bindings/vercel-base-runtime.js +3 -0
  28. package/dist/src/execution/sandbox/bindings/vercel-create-api.js +1 -1
  29. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  30. package/dist/src/execution/sandbox/development-cleanup.d.ts +1 -0
  31. package/dist/src/execution/sandbox/development-cleanup.js +1 -1
  32. package/dist/src/execution/sandbox/development-prewarm.js +1 -1
  33. package/dist/src/execution/sandbox/development-run.d.ts +3 -0
  34. package/dist/src/execution/sandbox/development-run.js +1 -1
  35. package/dist/src/execution/sandbox/ensure.js +1 -1
  36. package/dist/src/execution/sandbox/prewarm.d.ts +4 -0
  37. package/dist/src/execution/sandbox/prewarm.js +2 -1
  38. package/dist/src/execution/sandbox/template-prewarm-lock.js +1 -1
  39. package/dist/src/internal/application/package.js +1 -1
  40. package/dist/src/internal/nitro/host/configure-nitro-routes.js +2 -2
  41. package/dist/src/internal/nitro/host/dev-authored-source-watcher.d.ts +1 -0
  42. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  43. package/dist/src/internal/nitro/host/dev-rebuild-registry.d.ts +5 -0
  44. package/dist/src/internal/nitro/host/dev-rebuild-registry.js +1 -0
  45. package/dist/src/internal/nitro/host/start-development-server.js +1 -1
  46. package/dist/src/internal/nitro/routes/dev-runtime-artifacts.d.ts +3 -0
  47. package/dist/src/internal/nitro/routes/dev-runtime-artifacts.js +1 -1
  48. package/dist/src/protocol/routes.d.ts +5 -0
  49. package/dist/src/protocol/routes.js +1 -1
  50. package/dist/src/public/sandbox/backends/vercel.d.ts +6 -4
  51. package/dist/src/public/sandbox/docker-sandbox.d.ts +3 -3
  52. package/dist/src/public/sandbox/microsandbox-sandbox.d.ts +4 -4
  53. package/dist/src/public/sandbox/vercel-sandbox.d.ts +12 -7
  54. package/dist/src/services/dev-client/runtime-artifacts.d.ts +3 -0
  55. package/dist/src/services/dev-client/runtime-artifacts.js +1 -1
  56. package/dist/src/services/dev-client.js +1 -1
  57. package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
  58. package/dist/src/setup/scaffold/create/project.js +8 -2
  59. package/dist/src/setup/scaffold/update/channels.js +1 -1
  60. package/dist/src/svelte/index.js +1 -1
  61. package/dist/src/svelte/use-eve-agent.js +1 -1
  62. package/dist/src/vue/index.js +1 -1
  63. package/dist/src/vue/use-eve-agent.js +1 -1
  64. package/docs/guides/dev-tui.md +4 -4
  65. package/docs/reference/cli.md +1 -1
  66. package/docs/sandbox.mdx +3 -3
  67. package/package.json +2 -1
@@ -1 +1 @@
1
- import{startDevelopmentSandboxPrewarmInBackground}from"#execution/sandbox/development-prewarm.js";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{EVE_DEV_ENV_FLAG}from"#internal/application/optional-package-install.js";import{EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV,createDevelopmentSandboxRunId}from"#execution/sandbox/development-run.js";import{pruneDevelopmentRuntimeArtifactsSnapshotsInBackground}from"#internal/nitro/dev-runtime-artifacts.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{pruneLocalSandboxTemplatesInBackground,stopDevelopmentSandboxResources}from"#execution/sandbox/bindings/local.js";import{DEFAULT_DEVELOPMENT_SERVER_PORT,MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS}from"#internal/nitro/host/ports.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`127.0.0.1`,t.toString()):e}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??DEFAULT_DEVELOPMENT_SERVER_PORT;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startDevelopmentServer(o,s={}){process.env[EVE_DEV_ENV_FLAG]??=`1`,loadDevelopmentEnvironmentFiles(o);let c=process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV],l=createDevelopmentSandboxRunId();process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=l;let u,d,f,p;try{let t=await prepareApplicationHost(o,{dev:!0});pruneDevelopmentRuntimeArtifactsSnapshotsInBackground(t.appRoot);let n=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:t.appRoot,dev:!0}));startDevelopmentSandboxPrewarmInBackground({appRoot:t.appRoot,compiledArtifactsSource:n}),pruneLocalSandboxTemplatesInBackground(t.appRoot),u=await createApplicationNitro(t,!0),d=createDevServer(u),guardDevelopmentServerWebSocketUpgrades(u,d);let r=s.host??u.options.devServer.hostname,i=s.port??readEnvironmentPort(),m=i??u.options.devServer.port,h=await listenForDevelopmentServer({devServer:d,host:r,port:m,retryOnAddressInUse:i===void 0});if(!h.url)throw Error(`Nitro dev server did not expose a URL.`);f=installWorkflowLocalQueueEnvironment(h.url),await prepare(u),await build(u);let{startAuthoredSourceWatcher:g}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);p=await g({nitro:u,preparedHost:t});let _=f;if(_===void 0)throw Error(`Workflow local queue environment was not initialized.`);let v=p,y=d,b=u;return{async close(){try{await v.close(),await y.close(),await b.close(),await stopDevelopmentSandboxResources({devRunId:l,log:e=>console.warn(`[eve:dev] ${e}`)})}finally{_(),restoreDevelopmentSandboxRunId(c)}},url:normalizeDevelopmentServerClientUrl(h.url)}}catch(e){throw await p?.close().catch(()=>{}),f?.(),await d?.close().catch(()=>{}),await u?.close().catch(()=>{}),await stopDevelopmentSandboxResources({devRunId:l,log:e=>console.warn(`[eve:dev] ${e}`)}).catch(()=>{}),restoreDevelopmentSandboxRunId(c),e}}function restoreDevelopmentSandboxRunId(e){if(e===void 0){delete process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV];return}process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=e}export{normalizeDevelopmentServerClientUrl,startDevelopmentServer};
1
+ import{startDevelopmentSandboxPrewarmInBackground}from"#execution/sandbox/development-prewarm.js";import{loadDevelopmentEnvironmentFiles}from"#cli/dev/environment.js";import{EVE_DEV_ENV_FLAG}from"#internal/application/optional-package-install.js";import{EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV,clearInitializedDevelopmentSandboxBackendNames,createDevelopmentSandboxRunId,getInitializedDevelopmentSandboxBackendNames}from"#execution/sandbox/development-run.js";import{pruneDevelopmentRuntimeArtifactsSnapshotsInBackground}from"#internal/nitro/dev-runtime-artifacts.js";import{build,createDevServer,prepare}from"nitro/builder";import{createApplicationNitro}from"#internal/nitro/host/create-application-nitro.js";import{prepareApplicationHost}from"#internal/nitro/host/prepare-application-host.js";import{createNitroArtifactsConfig}from"#internal/nitro/host/artifacts-config.js";import{resolveNitroCompiledArtifactsSource}from"#internal/nitro/routes/runtime-artifacts.js";import{pruneLocalSandboxTemplatesInBackground,stopDevelopmentSandboxResources}from"#execution/sandbox/bindings/local.js";import{DEFAULT_DEVELOPMENT_SERVER_PORT,MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS}from"#internal/nitro/host/ports.js";const MAX_ALLOWED_DEVELOPMENT_SERVER_PORT=65535,WORKFLOW_LOCAL_BASE_URL_ENV=`WORKFLOW_LOCAL_BASE_URL`,PORT_ENV=`PORT`,WILDCARD_LISTEN_HOSTNAMES=new Set([`[::]`,`::`,`0.0.0.0`]);function normalizeDevelopmentServerClientUrl(e){let t=new URL(e);return WILDCARD_LISTEN_HOSTNAMES.has(t.hostname)?(t.hostname=`127.0.0.1`,t.toString()):e}function isAddressInUseError(e){return e instanceof Error&&`code`in e&&e.code===`EADDRINUSE`}function resolveDevelopmentServerPort(e){let t=typeof e==`string`?Number(e):e??DEFAULT_DEVELOPMENT_SERVER_PORT;if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid development server port "${String(e)}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function readEnvironmentPort(){let e=process.env[PORT_ENV];if(e===void 0||e.trim()===``)return;let t=Number(e);if(!Number.isInteger(t)||t<0||t>MAX_ALLOWED_DEVELOPMENT_SERVER_PORT)throw Error(`Invalid ${PORT_ENV} environment variable "${e}". Expected an integer between 0 and ${MAX_ALLOWED_DEVELOPMENT_SERVER_PORT}.`);return t}function resolveDevelopmentServerPorts(e){let t=resolveDevelopmentServerPort(e.port);if(t===0||!e.retryOnAddressInUse)return[t];let n=[];for(let e=0;e<MAX_DEVELOPMENT_SERVER_PORT_ATTEMPTS;e+=1){let r=t+e;if(r>65535)break;n.push(r)}return n}function installWorkflowLocalQueueEnvironment(e){let t=process.env[WORKFLOW_LOCAL_BASE_URL_ENV],n=process.env[PORT_ENV],r=new URL(normalizeDevelopmentServerClientUrl(e));return process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=r.origin,r.port&&(process.env[PORT_ENV]=r.port),()=>{t===void 0?delete process.env[WORKFLOW_LOCAL_BASE_URL_ENV]:process.env[WORKFLOW_LOCAL_BASE_URL_ENV]=t,n===void 0?delete process.env[PORT_ENV]:process.env[PORT_ENV]=n}}function attachTemporarySocketErrorHandler(e){let onSocketError=()=>{};return e.once(`error`,onSocketError),()=>{e.off(`error`,onSocketError)}}function shouldProxyDevelopmentServerWebSocketUpgrades(e){return e.options.features.websocket===!0||e.options.experimental.websocket===!0}function guardDevelopmentServerWebSocketUpgrades(e,t){let n=t.upgrade.bind(t),r=shouldProxyDevelopmentServerWebSocketUpgrades(e);t.upgrade=async(e,t,i)=>{if(!r){t.destroyed||t.destroy();return}let a=attachTemporarySocketErrorHandler(t);try{await n(e,t,i)}catch{t.destroyed||t.destroy()}finally{a()}}}async function listenForDevelopmentServer(e){let t=resolveDevelopmentServerPorts({port:e.port,retryOnAddressInUse:e.retryOnAddressInUse}),n;for(let r of t){let t=e.devServer.listen({hostname:e.host,port:r,silent:!0});try{return await t.ready(),t}catch(r){if(n=r,await t.close().catch(()=>{}),!isAddressInUseError(r)||!e.retryOnAddressInUse)throw r}}throw Error(`Failed to start Nitro dev server after ${t.length} attempts. Tried ports ${t.join(`, `)}.`,{cause:n})}async function startDevelopmentServer(o,s={}){process.env[EVE_DEV_ENV_FLAG]??=`1`,loadDevelopmentEnvironmentFiles(o);let c=process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV],l=createDevelopmentSandboxRunId();process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=l;let u,d,f,p;try{let t=await prepareApplicationHost(o,{dev:!0});pruneDevelopmentRuntimeArtifactsSnapshotsInBackground(t.appRoot);let n=resolveNitroCompiledArtifactsSource(createNitroArtifactsConfig({appRoot:t.appRoot,dev:!0}));startDevelopmentSandboxPrewarmInBackground({appRoot:t.appRoot,compiledArtifactsSource:n}),pruneLocalSandboxTemplatesInBackground(t.appRoot),u=await createApplicationNitro(t,!0),d=createDevServer(u),guardDevelopmentServerWebSocketUpgrades(u,d);let r=s.host??u.options.devServer.hostname,a=s.port??readEnvironmentPort(),m=a??u.options.devServer.port,h=await listenForDevelopmentServer({devServer:d,host:r,port:m,retryOnAddressInUse:a===void 0});if(!h.url)throw Error(`Nitro dev server did not expose a URL.`);f=installWorkflowLocalQueueEnvironment(h.url),await prepare(u),await build(u);let{startAuthoredSourceWatcher:g}=await import(`#internal/nitro/host/dev-authored-source-watcher.js`);p=await g({nitro:u,preparedHost:t});let _=f;if(_===void 0)throw Error(`Workflow local queue environment was not initialized.`);let v=p,y=d,b=u;return{async close(){try{await v.close(),await y.close(),await b.close(),await stopDevelopmentSandboxResources({backendNames:getInitializedDevelopmentSandboxBackendNames(l),devRunId:l,log:e=>console.warn(`[eve:dev] ${e}`)})}finally{clearInitializedDevelopmentSandboxBackendNames(l),_(),restoreDevelopmentSandboxRunId(c)}},url:normalizeDevelopmentServerClientUrl(h.url)}}catch(e){throw await p?.close().catch(()=>{}),f?.(),await d?.close().catch(()=>{}),await u?.close().catch(()=>{}),await stopDevelopmentSandboxResources({backendNames:getInitializedDevelopmentSandboxBackendNames(l),devRunId:l,log:e=>console.warn(`[eve:dev] ${e}`)}).catch(()=>{}),clearInitializedDevelopmentSandboxBackendNames(l),restoreDevelopmentSandboxRunId(c),e}}function restoreDevelopmentSandboxRunId(e){if(e===void 0){delete process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV];return}process.env[EVE_DEVELOPMENT_SANDBOX_RUN_ID_ENV]=e}export{normalizeDevelopmentServerClientUrl,startDevelopmentServer};
@@ -8,3 +8,6 @@
8
8
  export declare function handleDevRuntimeArtifactsRequest(input: {
9
9
  appRoot: string;
10
10
  }): Response;
11
+ export declare function handleDevRuntimeArtifactsRebuildRequest(input: {
12
+ appRoot: string;
13
+ }): Promise<Response>;
@@ -1 +1 @@
1
- import{readDevelopmentRuntimeArtifactsRevision}from"#internal/nitro/dev-runtime-artifacts.js";function handleDevRuntimeArtifactsRequest(e){return Response.json(readDevelopmentRuntimeArtifactsRevision(e.appRoot),{headers:{"cache-control":`no-store`}})}export{handleDevRuntimeArtifactsRequest};
1
+ import{readDevelopmentRuntimeArtifactsRevision}from"#internal/nitro/dev-runtime-artifacts.js";import{flushDevelopmentRebuild}from"#internal/nitro/host/dev-rebuild-registry.js";function handleDevRuntimeArtifactsRequest(t){return Response.json(readDevelopmentRuntimeArtifactsRevision(t.appRoot),{headers:{"cache-control":`no-store`}})}async function handleDevRuntimeArtifactsRebuildRequest(e){return await flushDevelopmentRebuild(e.appRoot),handleDevRuntimeArtifactsRequest(e)}export{handleDevRuntimeArtifactsRebuildRequest,handleDevRuntimeArtifactsRequest};
@@ -51,6 +51,11 @@ export declare const EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = "/eve/v1/dev/sche
51
51
  * snapshot.
52
52
  */
53
53
  export declare const EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = "/eve/v1/dev/runtime-artifacts";
54
+ /**
55
+ * Dev-only route that flushes queued runtime artifact rebuilds before
56
+ * returning the current revision.
57
+ */
58
+ export declare const EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH = "/eve/v1/dev/runtime-artifacts/rebuild";
54
59
  /**
55
60
  * Builds the dev-only schedule dispatch URL for one named authored
56
61
  * schedule. The path encodes the schedule id so reserved characters in
@@ -1 +1 @@
1
- const EVE_ROUTE_PREFIX=`/eve/v1`,EVE_HEALTH_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/health`,EVE_INFO_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/info`,EVE_CREATE_SESSION_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/session`,EVE_CONTINUE_SESSION_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId`,EVE_MESSAGE_STREAM_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId/stream`,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`;function createEveDevDispatchSchedulePath(e){return`${EVE_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,EVE_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/callback/:token`;function createEveMessageStreamRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createEveContinueSessionRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createEveConnectionCallbackRoutePath(e,t){return`${EVE_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createEveCallbackRoutePath(e){return`${EVE_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{EVE_CALLBACK_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,EVE_ROUTE_PREFIX,createEveCallbackRoutePath,createEveConnectionCallbackRoutePath,createEveContinueSessionRoutePath,createEveDevDispatchSchedulePath,createEveMessageStreamRoutePath};
1
+ const EVE_ROUTE_PREFIX=`/eve/v1`,EVE_HEALTH_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/health`,EVE_INFO_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/info`,EVE_CREATE_SESSION_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/session`,EVE_CONTINUE_SESSION_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId`,EVE_MESSAGE_STREAM_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/session/:sessionId/stream`,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH=`${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH=`${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;function createEveDevDispatchSchedulePath(e){return`${EVE_ROUTE_PREFIX}/dev/schedules/${encodeURIComponent(e)}`}const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`,EVE_CALLBACK_ROUTE_PATTERN=`${EVE_ROUTE_PREFIX}/callback/:token`;function createEveMessageStreamRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}/stream`}function createEveContinueSessionRoutePath(e){return`${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(e)}`}function createEveConnectionCallbackRoutePath(e,t){return`${EVE_ROUTE_PREFIX}/connections/${encodeURIComponent(e)}/callback/${encodeURIComponent(t)}`}function createEveCallbackRoutePath(e){return`${EVE_ROUTE_PREFIX}/callback/${encodeURIComponent(e)}`}export{EVE_CALLBACK_ROUTE_PATTERN,EVE_CONNECTION_CALLBACK_ROUTE_PATTERN,EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN,EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,EVE_HEALTH_ROUTE_PATH,EVE_INFO_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,EVE_ROUTE_PREFIX,createEveCallbackRoutePath,createEveConnectionCallbackRoutePath,createEveContinueSessionRoutePath,createEveDevDispatchSchedulePath,createEveMessageStreamRoutePath};
@@ -6,10 +6,12 @@ import type { VercelSandboxBootstrapUseOptions, VercelSandboxCreateOptions, Verc
6
6
  * including for local development, where it creates real hosted
7
7
  * sandboxes (requires Vercel credentials).
8
8
  *
9
- * The optional `opts` parameter is forwarded to the Vercel SDK's
10
- * `Sandbox.create(...)` for every fresh sandbox the framework creates
11
- * (template at prewarm, session at first-time create). On resume
12
- * (`Sandbox.get`), no create happens, so opts are not re-applied.
9
+ * The optional `opts` parameter is forwarded to Vercel Sandbox creation
10
+ * for every fresh sandbox the framework creates (template at prewarm,
11
+ * session at first-time create). On resume (`Sandbox.get`), no create
12
+ * happens, so opts are not re-applied. `networkPolicy` is applied after
13
+ * framework-owned base setup for fresh templates and template-less
14
+ * sessions, before authored bootstrap code runs.
13
15
  *
14
16
  * `opts.source`, if supplied, is used only on the template create:
15
17
  * the author's snapshot, git revision, or tarball becomes the base
@@ -23,9 +23,9 @@ export interface DockerSandboxCreateOptions {
23
23
  /**
24
24
  * Base container image for templates and sessions. Defaults to
25
25
  * `ubuntu:26.04` — the official Ubuntu 26.04 image. Framework setup
26
- * installs Node 24 and baseline tools. Custom images must provide
27
- * Bash, Node 24, and npm, or a package manager and setup network
28
- * access that can install them.
26
+ * creates `/workspace` and verifies Bash. Install any authored runtime
27
+ * tools (Node, Python, ripgrep, etc.) in sandbox bootstrap or provide
28
+ * them through a custom image.
29
29
  */
30
30
  readonly image?: string;
31
31
  /**
@@ -11,10 +11,10 @@ import type { SandboxNetworkPolicy } from "#shared/sandbox-network-policy.js";
11
11
  export interface MicrosandboxCreateOptions {
12
12
  /**
13
13
  * OCI image used as the base runtime. Eve prepares this image with
14
- * the framework workspace, Node 24, pnpm, git, ripgrep, sudo, and
15
- * other baseline tools before authored bootstrap code runs. Custom
16
- * images must provide Bash and either Node 24/npm or a package
17
- * manager capable of installing them.
14
+ * Bash, the framework workspace, and the sandbox user before authored
15
+ * bootstrap code runs. Install authored runtime tools such as Node,
16
+ * Python, or ripgrep in sandbox bootstrap or provide them through a
17
+ * custom Ubuntu image.
18
18
  *
19
19
  * @default "ubuntu:26.04"
20
20
  */
@@ -1,10 +1,15 @@
1
1
  import type { Sandbox as SdkSandbox, SandboxUpdateParams } from "#compiled/@vercel/sandbox/index.js";
2
2
  /**
3
- * Options accepted by `vercelSandboxBackend(opts)`. Forwarded directly to the
4
- * Vercel SDK's `Sandbox.create(...)` for every fresh sandbox the
5
- * framework creates (template at prewarm time, session at first-time
6
- * session-create). Skipped on resume (`Sandbox.get`) since no create
7
- * happens there.
3
+ * Options accepted by `vercelSandboxBackend(opts)`. Forwarded to Vercel
4
+ * Sandbox creation for every fresh sandbox the framework creates
5
+ * (template at prewarm time, session at first-time session-create).
6
+ * Skipped on resume (`Sandbox.get`) since no create happens there.
7
+ *
8
+ * `networkPolicy` is deferred until after framework-owned base setup
9
+ * for fresh templates and template-less sessions, so Eve can install
10
+ * required packages before authored bootstrap code runs. Template-backed
11
+ * session creates receive it at creation time because the template
12
+ * already contains the prepared base runtime.
8
13
  *
9
14
  * Framework-injected fields (`name`, `onResume`, `persistent`, `signal`)
10
15
  * are excluded: the framework owns those and overrides any
@@ -12,8 +17,8 @@ import type { Sandbox as SdkSandbox, SandboxUpdateParams } from "#compiled/@verc
12
17
  *
13
18
  * `source` is honored only on the template create at prewarm time, so
14
19
  * an author-supplied snapshot, git revision, or tarball becomes the
15
- * base layer for the template. Bootstrap, seed files, and framework
16
- * setup (workspace dir, ripgrep) all run on top, and the resulting
20
+ * base layer for the template. Framework setup, bootstrap, and seed
21
+ * files all run on top, and the resulting
17
22
  * framework-owned snapshot is what every later session derives from,
18
23
  * so `source` is stripped from the session-create path. Eve does not
19
24
  * detect external snapshot changes; to pick up a rebuilt external
@@ -11,3 +11,6 @@
11
11
  export declare function readDevelopmentRuntimeArtifactsRevision(input: {
12
12
  readonly serverUrl: string;
13
13
  }): Promise<string | undefined>;
14
+ export declare function rebuildDevelopmentRuntimeArtifacts(input: {
15
+ readonly serverUrl: string;
16
+ }): Promise<string | undefined>;
@@ -1 +1 @@
1
- import{resolveDevelopmentClientHeaders}from"./request-headers.js";import{EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(e){try{let t=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,e.serverUrl),n=await fetch(t,{headers:await resolveDevelopmentClientHeaders({serverUrl:e.serverUrl})});if(!n.ok)return;let r=await n.json();return typeof r.revision==`string`&&r.revision.length>0?r.revision:void 0}catch{return}}export{readDevelopmentRuntimeArtifactsRevision};
1
+ import{resolveDevelopmentClientHeaders}from"./request-headers.js";import{EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}from"#protocol/routes.js";async function readDevelopmentRuntimeArtifactsRevision(t){try{let r=new URL(EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH,t.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(r,{headers:await resolveDevelopmentClientHeaders({serverUrl:t.serverUrl})}))}catch{return}}async function rebuildDevelopmentRuntimeArtifacts(n){try{let r=new URL(EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH,n.serverUrl);return await parseDevelopmentRuntimeArtifactsRevision(await fetch(r,{headers:await resolveDevelopmentClientHeaders({serverUrl:n.serverUrl}),method:`POST`}))}catch{return}}async function parseDevelopmentRuntimeArtifactsRevision(e){if(!e.ok)return;let t=await e.json();return typeof t.revision==`string`&&t.revision.length>0?t.revision:void 0}export{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts};
@@ -1 +1 @@
1
- import{isLocalDevelopmentServerUrl}from"#services/dev-client/request-headers.js";import{readDevelopmentRuntimeArtifactsRevision}from"#services/dev-client/runtime-artifacts.js";var LocalDevelopmentRuntimeArtifactSessionRefresher=class{#e;#t;#n;constructor(t){this.#e=isLocalDevelopmentServerUrl(t.serverUrl),this.#t=t.serverUrl}clear(){this.#n=void 0}async refresh(e){return shouldRefreshRuntimeArtifactsForTurn(e)?await this.#r(e):e.session}async refreshIdle(e){return await this.#r(e)}async#r(e){if(!this.#e)return e.session;let n=await readDevelopmentRuntimeArtifactsRevision({serverUrl:this.#t});if(n===void 0)return e.session;let r=e.session,i=this.#n;return i!==void 0&&i!==n&&(r.state.continuationToken!==void 0&&(r=e.createSession()),await e.onRuntimeArtifactsChanged?.({previousRevision:i,revision:n})),this.#n=n,r}};function shouldRefreshRuntimeArtifactsForTurn(e){return e.message!==void 0&&(e.inputResponses?.length??0)===0}function createDevelopmentRuntimeArtifactSessionRefresher(e){return new LocalDevelopmentRuntimeArtifactSessionRefresher(e)}export{createDevelopmentRuntimeArtifactSessionRefresher};
1
+ import{isLocalDevelopmentServerUrl}from"#services/dev-client/request-headers.js";import{readDevelopmentRuntimeArtifactsRevision,rebuildDevelopmentRuntimeArtifacts}from"#services/dev-client/runtime-artifacts.js";var LocalDevelopmentRuntimeArtifactSessionRefresher=class{#e;#t;#n;constructor(t){this.#e=isLocalDevelopmentServerUrl(t.serverUrl),this.#t=t.serverUrl}clear(){this.#n=void 0}async refresh(e){return shouldRefreshRuntimeArtifactsForTurn(e)?await this.#r({...e,rebuild:!0}):e.session}async refreshIdle(e){return await this.#r({...e,rebuild:!1})}async#r(e){if(!this.#e)return e.session;let n=(e.rebuild?await rebuildDevelopmentRuntimeArtifacts({serverUrl:this.#t}):void 0)??await readDevelopmentRuntimeArtifactsRevision({serverUrl:this.#t});if(n===void 0)return e.session;let r=e.session,i=this.#n;return i!==void 0&&i!==n&&(r.state.continuationToken!==void 0&&(r=e.createSession()),await e.onRuntimeArtifactsChanged?.({previousRevision:i,revision:n})),this.#n=n,r}};function shouldRefreshRuntimeArtifactsForTurn(e){return e.message!==void 0&&(e.inputResponses?.length??0)===0}function createDevelopmentRuntimeArtifactSessionRefresher(e){return new LocalDevelopmentRuntimeArtifactSessionRefresher(e)}export{createDevelopmentRuntimeArtifactSessionRefresher};
@@ -1 +1 @@
1
- import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"../update/package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{agentTemplateFiles,formatEveDependencySpecifier}from"./project.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=join(i.projectRoot,`package.json`);if(!await pathExists(a))throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let o=agentTemplateFiles(i.model),s=[];for(let e of Object.keys(o))await pathExists(join(i.projectRoot,e))&&s.push(e);if(s.length===0&&await pathExists(join(i.projectRoot,`agent`))&&s.push(`agent/`),s.length>0)throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it already has: ${s.join(`, `)}. Move them aside first.`);let c=resolveVersionToken(`evePackageVersion`,i.evePackageVersion??`0.8.2`),l=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`7.0.0-canary.171`),u=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.2.2`),d=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),f=[];for(let[e,t]of Object.entries(o)){let r=join(i.projectRoot,e);await writeTextFile(r,t),f.push(r)}let p=JSON.parse(await readFile(a,`utf8`)),m={"@vercel/connect":u,ai:l,eve:formatEveDependencySpecifier(c),zod:d},h={};for(let[e,t]of Object.entries(m))hasDeclaredDependency(p,e)||(h[e]=t);return Object.keys(h).length>0&&await patchPackageJson(a,{dependencies:h}),await getPackageManagerStrategy(i.packageManager??`pnpm`).applyProjectConfiguration(i.projectRoot),{filesWritten:f,dependenciesAdded:Object.keys(h).sort()}}export{addAgentToProject};
1
+ import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"../update/package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{agentTemplateFiles,formatEveDependencySpecifier}from"./project.js";import{join}from"node:path";import{readFile}from"node:fs/promises";const DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`optionalDependencies`,`peerDependencies`];function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function hasDeclaredDependency(e,t){if(!isJsonObject(e))return!1;for(let n of DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function addAgentToProject(i){let a=join(i.projectRoot,`package.json`);if(!await pathExists(a))throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it has no package.json. Run \`eve init <name>\` to create a new project instead.`);let o=agentTemplateFiles(i.model),s=[];for(let e of Object.keys(o))await pathExists(join(i.projectRoot,e))&&s.push(e);if(s.length===0&&await pathExists(join(i.projectRoot,`agent`))&&s.push(`agent/`),s.length>0)throw Error(`Cannot add an Eve agent to "${i.projectRoot}" because it already has: ${s.join(`, `)}. Move them aside first.`);let c=resolveVersionToken(`evePackageVersion`,i.evePackageVersion??`0.8.4`),l=resolveVersionToken(`aiPackageVersion`,i.aiPackageVersion??`7.0.0-canary.171`),u=resolveVersionToken(`connectPackageVersion`,i.connectPackageVersion??`0.2.2`),d=resolveVersionToken(`zodPackageVersion`,i.zodPackageVersion??`4.4.3`),f=[];for(let[e,t]of Object.entries(o)){let r=join(i.projectRoot,e);await writeTextFile(r,t),f.push(r)}let p=JSON.parse(await readFile(a,`utf8`)),m={"@vercel/connect":u,ai:l,eve:formatEveDependencySpecifier(c),zod:d},h={};for(let[e,t]of Object.entries(m))hasDeclaredDependency(p,e)||(h[e]=t);return Object.keys(h).length>0&&await patchPackageJson(a,{dependencies:h}),await getPackageManagerStrategy(i.packageManager??`pnpm`).applyProjectConfiguration(i.projectRoot),{filesWritten:f,dependenciesAdded:Object.keys(h).sort()}}export{addAgentToProject};
@@ -1,4 +1,4 @@
1
- import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.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_EVE_PACKAGE_VERSION=`0.8.2`,DEFAULT_AI_PACKAGE_VERSION=`7.0.0-canary.171`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`;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.evePackageVersion)).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_TSGO_VERSION__`,t.tsgoPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.typesNodePackageVersion)}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{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{resolveVersionToken}from"../version-tokens.js";import{SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS}from"../update/module-files.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_EVE_PACKAGE_VERSION=`0.8.4`,DEFAULT_AI_PACKAGE_VERSION=`7.0.0-canary.171`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`;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.evePackageVersion)).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_TSGO_VERSION__`,t.tsgoPackageVersion).replaceAll(`__EVE_INIT_TYPES_NODE_VERSION__`,t.typesNodePackageVersion)}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__",
@@ -26,6 +26,12 @@ export default defineAgent({
26
26
  "devDependencies": {
27
27
  ${e?` "@types/node": "__EVE_INIT_TYPES_NODE_VERSION__",
28
28
  "@typescript/native-preview": "__EVE_INIT_TSGO_VERSION__"`:` "@typescript/native-preview": "__EVE_INIT_TSGO_VERSION__"`}
29
+ },
30
+ "overrides": {
31
+ "ai": "__EVE_INIT_AI_SDK_VERSION__"
32
+ },
33
+ "resolutions": {
34
+ "ai": "__EVE_INIT_AI_SDK_VERSION__"
29
35
  }
30
36
  }
31
37
  `}const AGENT_INSTRUCTIONS_TEMPLATE=`# Identity
@@ -80,4 +86,4 @@ export default defineAgent({
80
86
  },
81
87
  },
82
88
  });
83
- `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(t),...getPackageManagerStrategy(n).scaffoldFiles}}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(e){let i=resolve(e.targetDirectory??process.cwd(),e.projectName),a=e.projectName===`.`,s=e.overwriteExisting??!1,u=e.byokProvider??!1,d=e.packageManager??`pnpm`;if(a)await assertCanCreateInPlace(i,s);else if(await pathExists(i))throw Error(`Cannot create project because "${i}" already exists.`);let f=e.typesNodePackageVersion??`25.9.1`,p={appName:basename(i),model:e.model,evePackageVersion:resolveVersionToken(`evePackageVersion`,e.evePackageVersion??`0.8.2`),aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`7.0.0-canary.171`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.4.3`),tsgoPackageVersion:resolveVersionToken(`tsgoPackageVersion`,e.tsgoPackageVersion??`7.0.0-dev.20260523.1`),typesNodePackageVersion:u?resolveVersionToken(`typesNodePackageVersion`,f):f};await mkdir(i,{recursive:!0});for(let[r,o]of Object.entries(templateFiles(u,d))){let c=`${i}/${r}`,l=await pathExists(c);await writeTextFile(c,renderTemplate(o,p),{force:a&&s}),l&&await e.onOverwriteFile?.(c)}return i}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_VERSION,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,scaffoldBaseProject};
89
+ `:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(t),...getPackageManagerStrategy(n).scaffoldFiles}}async function assertCanCreateInPlace(e,n){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!n){let e=r.slice(0,5).join(`, `),t=r.length>5?`, and ${r.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${e}${t}. Use an empty directory.`)}}async function scaffoldBaseProject(e){let i=resolve(e.targetDirectory??process.cwd(),e.projectName),a=e.projectName===`.`,s=e.overwriteExisting??!1,u=e.byokProvider??!1,d=e.packageManager??`pnpm`;if(a)await assertCanCreateInPlace(i,s);else if(await pathExists(i))throw Error(`Cannot create project because "${i}" already exists.`);let f=e.typesNodePackageVersion??`25.9.1`,p={appName:basename(i),model:e.model,evePackageVersion:resolveVersionToken(`evePackageVersion`,e.evePackageVersion??`0.8.4`),aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`7.0.0-canary.171`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.4.3`),tsgoPackageVersion:resolveVersionToken(`tsgoPackageVersion`,e.tsgoPackageVersion??`7.0.0-dev.20260523.1`),typesNodePackageVersion:u?resolveVersionToken(`typesNodePackageVersion`,f):f};await mkdir(i,{recursive:!0});for(let[r,o]of Object.entries(templateFiles(u,d))){let c=`${i}/${r}`,l=await pathExists(c);await writeTextFile(c,renderTemplate(o,p),{force:a&&s}),l&&await e.onOverwriteFile?.(c)}return i}async function isEveProject(e){for(let t of SUPPORTED_AUTHORED_MODULE_FILE_EXTENSIONS)try{return await stat(join(e,`agent`,`agent${t}`)),!0}catch{}return!1}export{CURRENT_DIRECTORY_PROJECT_NAME,DEFAULT_AI_PACKAGE_VERSION,DEFAULT_CONNECT_PACKAGE_VERSION,DEFAULT_EVE_PACKAGE_VERSION,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,scaffoldBaseProject};
@@ -1,4 +1,4 @@
1
- import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"./package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import"../create/project.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},eve:{buildCommand:`eve build`,entrypoint:`.`,framework:`eve`,routePrefix:`/_eve_internal/eve`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,n){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,n)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),`next`)}async function ensurePackageDependency(e,n,i){return!await pathExists(e)||await readDependencyVersion(e,n)===i?[]:(await patchPackageJson(e,{dependencies:{[n]:i}}),[{path:e,dependencies:[n],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackageVersion:e?.evePackageVersion??`0.8.2`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.171`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n){if(!await pathExists(e))return[];let a={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,n.aiPackageVersion),eve:formatEveDependencySpecifier(resolveVersionToken(`evePackageVersion`,n.evePackageVersion)),next:resolveVersionToken(`nextPackageVersion`,n.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,n.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,n.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,n.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,n.zodPackageVersion)},o={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":resolveVersionToken(`typesNodePackageVersion`,n.typesNodePackageVersion),"@types/react":resolveVersionToken(`typesReactPackageVersion`,n.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,n.typesReactDomPackageVersion),"@typescript/native-preview":resolveVersionToken(`tsgoPackageVersion`,n.tsgoPackageVersion)},s=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:a,devDependencies:o,scripts:s}),[{path:e,dependencies:Object.keys(a),devDependencies:Object.keys(o),scripts:Object.keys(s)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
1
+ import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pathExists,writeTextFile}from"../files.js";import{patchPackageJson}from"./package-json.js";import{resolveVersionToken}from"../version-tokens.js";import{getSupportedModuleBaseName,matchesSupportedModuleBaseName}from"./module-files.js";import{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON}from"../create/web-template.js";import"../create/project.js";import{basename,join,resolve}from"node:path";import{readFile,readdir,writeFile}from"node:fs/promises";const SLACK_CHANNEL_DEFAULT_ROUTE=`/eve/v1/slack`,DEFAULT_SLACK_CONNECTOR_SLUG=`my-agent`,PACKAGE_DEPENDENCY_FIELDS=[`dependencies`,`devDependencies`,`peerDependencies`,`optionalDependencies`],WEB_NEXT_CONFIG_PATH=`next.config.ts`,WEB_VERCEL_JSON_PATH=`vercel.json`,WEB_VERCEL_JSON_SCHEMA=`https://openapi.vercel.sh/vercel.json`,WEB_COMPETING_NEXT_CONFIG_PATHS=[`next.config.js`,`next.config.mjs`,WEB_NEXT_CONFIG_PATH,`next.config.mts`].filter(e=>e!==WEB_NEXT_CONFIG_PATH),WEB_DEFAULT_VERCEL_SERVICES={web:{entrypoint:`.`,framework:`nextjs`,routePrefix:`/`},eve:{buildCommand:`eve build`,entrypoint:`.`,framework:`eve`,routePrefix:`/_eve_internal/eve`}};function toSlackConnectorSlug(e){return e}function isJsonObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function readDependencyVersion(e,t){let n=JSON.parse(await readFile(e,`utf8`));if(!isJsonObject(n)||!isJsonObject(n.dependencies))return;let r=n.dependencies[t];return typeof r==`string`?r:void 0}function packageJsonHasDependency(e,t){for(let n of PACKAGE_DEPENDENCY_FIELDS){let r=e[n];if(isJsonObject(r)&&typeof r[t]==`string`)return!0}return!1}async function hasPackageDependency(e,n){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,n)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),`next`)}async function ensurePackageDependency(e,n,i){return!await pathExists(e)||await readDependencyVersion(e,n)===i?[]:(await patchPackageJson(e,{dependencies:{[n]:i}}),[{path:e,dependencies:[n],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackageVersion:e?.evePackageVersion??`0.8.4`,aiPackageVersion:e?.aiPackageVersion??`7.0.0-canary.171`,nextPackageVersion:e?.nextPackageVersion??`16.2.6`,reactPackageVersion:e?.reactPackageVersion??`19.2.6`,reactDomPackageVersion:e?.reactDomPackageVersion??`19.2.6`,streamdownPackageVersion:e?.streamdownPackageVersion??`2.5.0`,zodPackageVersion:e?.zodPackageVersion??`4.4.3`,tsgoPackageVersion:e?.tsgoPackageVersion??`7.0.0-dev.20260523.1`,typesNodePackageVersion:e?.typesNodePackageVersion??`25.9.1`,typesReactPackageVersion:e?.typesReactPackageVersion??`19.2.15`,typesReactDomPackageVersion:e?.typesReactDomPackageVersion??`19.2.3`}}function formatEveDependencySpecifier(e){return/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z-.]+)?$/.test(e)?`^${e}`:e}async function patchWebPackageJson(e,n){if(!await pathExists(e))return[];let a={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,n.aiPackageVersion),eve:formatEveDependencySpecifier(resolveVersionToken(`evePackageVersion`,n.evePackageVersion)),next:resolveVersionToken(`nextPackageVersion`,n.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,n.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,n.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,n.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,n.zodPackageVersion)},o={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":resolveVersionToken(`typesNodePackageVersion`,n.typesNodePackageVersion),"@types/react":resolveVersionToken(`typesReactPackageVersion`,n.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,n.typesReactDomPackageVersion),"@typescript/native-preview":resolveVersionToken(`tsgoPackageVersion`,n.tsgoPackageVersion)},s=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts;return await patchPackageJson(e,{dependencies:a,devDependencies:o,scripts:s}),[{path:e,dependencies:Object.keys(a),devDependencies:Object.keys(o),scripts:Object.keys(s)}]}function normalizeSlackConnectorSlug(e){return toSlackConnectorSlug((e.trim().replace(/^@/,``).split(`/`).at(-1)??``).toLowerCase().replace(/[^a-z0-9_-]+/g,`-`).replace(/^[^a-z0-9]+/,``).replace(/[^a-z0-9]+$/,``).slice(0,100).replace(/[^a-z0-9]+$/,``)||`my-agent`)}async function deriveSlackConnectorSlug(e,t){if(t!==void 0&&t.length>0&&t!==`.`)return normalizeSlackConnectorSlug(t);try{let t=await readFile(join(e,`package.json`),`utf8`),n=JSON.parse(t);if(typeof n.name==`string`&&n.name.length>0)return normalizeSlackConnectorSlug(n.name)}catch{}return normalizeSlackConnectorSlug(basename(resolve(e))||`my-agent`)}function buildSlackTemplate(e){if(!e.startsWith(`slack/`)||e.length===6)throw Error(`Invalid Slack connector UID "${e}".`);return`import { connectSlackCredentials } from "@vercel/connect/eve";
2
2
  import { slackChannel } from "eve/channels/slack";
3
3
 
4
4
  export default slackChannel({
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-Dlut2Qzt.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-CdETo3qQ.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-Dlut2Qzt.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-CdETo3qQ.js";
2
2
 
3
3
  export { useEveAgent };
@@ -1,3 +1,3 @@
1
- import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-BSXZSn-R.js";
1
+ import { n as defaultMessageReducer, t as useEveAgent } from "../chunks/use-eve-agent-ClyM-_UT.js";
2
2
 
3
3
  export { defaultMessageReducer, useEveAgent };
@@ -1,3 +1,3 @@
1
- import { t as useEveAgent } from "../chunks/use-eve-agent-BSXZSn-R.js";
1
+ import { t as useEveAgent } from "../chunks/use-eve-agent-ClyM-_UT.js";
2
2
 
3
3
  export { useEveAgent };
@@ -12,17 +12,17 @@ eve dev
12
12
  On startup the TUI prints a brand line with your agent's name, plus a rotating tip (local sessions only):
13
13
 
14
14
  ```text
15
- eve weather-agent
15
+ eve weather-agent
16
16
  Use /channels to add more ways to reach your agent.
17
17
  ```
18
18
 
19
19
  If agent discovery reported problems, an error/warning count renders between the two lines. Instructions, tools, skills, and subagents are one `eve info` away, and `/help` lists every command.
20
20
 
21
- From there the conversation streams straight into your terminal's normal scrollback — your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`/`stderr` — so you keep native scrolling, copy/paste, and a transcript that persists after you exit. Each turn is rendered without boxes: a colored gutter glyph marks who's speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`), and a subagent's work is indented beneath its `◆` header. A sticky footer keeps you oriented. When input is ready, the prompt shows a dim `Type to chat · / for commands` placeholder while empty; while a turn or setup action owns the terminal, only its live status is shown. Beneath the prompt or status, a persistent line shows the model, the session's token flow (`⁕ 394.4K ↓ 4.3K`), the linked Vercel project and team (`▲ my-agent (acme)`), and a yellow `/deploy pending` marker once a channel added this session still needs `/deploy`. The Vercel segment stays hidden until the directory is linked. Press `Enter` to send; `Ctrl+C` interrupts a running turn or quits at the prompt. Slash commands: `/new` starts a fresh session and `/exit` quits.
21
+ From there the conversation streams straight into your terminal's normal scrollback — your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`, `stderr`, or sandbox lifecycle lines — so you keep native scrolling, copy/paste, and a transcript that persists after you exit. Each turn is rendered without boxes: a colored gutter glyph marks who's speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`), and a subagent's work is indented beneath its `◆` header. A sticky footer keeps you oriented. When input is ready, the prompt stays bare until you type; while a turn or setup action owns the terminal, only its live status is shown. Beneath the prompt or status, a persistent line shows the model, the session's token flow (`↑ 394.4K ↓ 4.3K`), the linked Vercel project and team (`▲ my-agent (acme)`), and a yellow `/deploy pending` marker once a channel added this session still needs `/deploy`. The Vercel segment stays hidden until the directory is linked. Press `Enter` to send; `Ctrl+C` interrupts a running turn or quits at the prompt. Slash commands: `/new` starts a fresh session and `/exit` quits.
22
22
 
23
23
  When `eve dev` runs the server locally, three more slash commands manage the project without leaving the session. Bare `/model` opens a configure menu that loops until Done (or Esc). "Change model" runs the same searchable model picker setup uses (the AI Gateway catalog, pre-selected on the model the runtime is serving); a model change is written into your agent's authored source, and the command reports success only after Eve confirms the new id (`/model <provider/model-id>` applies one directly, skipping the menu). The provider row opens the provider questions: which model provider to use (picking something other than AI Gateway shows wiring instructions for your own provider and stops there, leaving any existing setup untouched) and how to connect to AI Gateway — paste your own `AI_GATEWAY_API_KEY`, saved straight to `.env.local`, or connect via a project, which asks for a Vercel team and then opens that team's existing-project list (picking again re-links) before pulling the project's environment so an AI Gateway credential lands in `.env.local`; the dev server reloads env files automatically, no restart needed. The row demands attention (a bold yellow "Configure provider" with "Required to enable the agent") until a link or gateway credential is detected, then names the connection (e.g. "AI Gateway (Linked to my-project in my-team)") after, and each action's latest outcome stays visible beneath the menu (e.g. "✓ Model changed to openai/gpt-5.5"). `/channels` shows the agent's channel list — already-registered channels render as checked, focusable rows with an "Already installed" hint — and adds the one you pick, including the Slack Connect provisioning, then installs the dependencies the scaffold added so the dev server can load the new channels right away; after each addition the list repaints with the channel checked, until Done (or Esc) leaves the flow. `/deploy` ships the agent to Vercel production, linking first when the directory is unlinked. Each command echoes as an invocation line, asks through a bordered panel that takes the input area's place — one question at a time, clearly separate from the chat transcript — and finishes with a one-line `⎿` result; loading states stay on the ephemeral status line instead of piling into the transcript. These commands are not available when connected to a remote server with `--url`, and when a turn fails because AI Gateway authentication is missing or stale, the error points you at `/model` directly. The TUI also checks at startup: a missing model-provider setup surfaces as an attention line — `⚠ 1 setup issue: model provider not linked · /model` — so the fix is visible before the first message fails, and each command's outcome hangs under it with the `⎿` connector.
24
24
 
25
- The prompt input behaves like a shell line editor: `↑`/`↓` cycle through the messages you've sent this session, `←`/`→`, Home/End, and `Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line, the rest of the line, or the previous word. If a turn fails terminally — the server session dies or the connection drops — the TUI starts a fresh session and notes it inline so you can keep going (server-side context resets with the old session). Errors render compactly, with docs links highlighted, and a code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Captured server `stdout`/`stderr` renders as dim, indented log runs behind a `│` rule — consecutive lines from the same source share one label. Dev-server rebuilds condense further, into one status row that updates in place: `tui/setup-panel.ts changed · rebuilding…`, then `· rebuilt`. Only the latest rebuild shows, and paths shrink to their last two components. The TUI hides logs by default. `/loglevel <all|stderr|none>` switches what the transcript shows, and because logs stay buffered either way, the switch is retroactive: `/loglevel all` brings back everything captured so far, in its original order. Bare `/loglevel` reports the current mode; the `--logs` flag sets the starting one.
25
+ The prompt input behaves like a shell line editor: `↑`/`↓` cycle through the messages you've sent this session, `←`/`→`, Home/End, and `Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line, the rest of the line, or the previous word. If a turn fails terminally — the server session dies or the connection drops — the TUI starts a fresh session and notes it inline so you can keep going (server-side context resets with the old session). Errors render compactly, with docs links highlighted, and a code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Captured server `stdout`/`stderr` renders as dim, indented log runs behind a `│` rule — consecutive lines from the same source share one label — while sandbox lifecycle lines use their own label. Dev-server rebuilds condense further, into one status row that updates in place: `tui/setup-panel.ts changed · rebuilding…`, then `· rebuilt`. Only the latest rebuild shows, and paths shrink to their last two components. By default, `eve dev` shows `stderr` and keeps stdout and sandbox lines buffered but hidden. `/loglevel <all|stderr|sandbox|none>` switches what the transcript shows retroactively, and `--logs` sets the starting mode. Bare `/loglevel` reports the current mode. At the idle prompt, `Ctrl+L` cycles `none all → stderr → sandbox → none` and briefly shows the selected mode in the status line; `Ctrl+R` redraws.
26
26
 
27
27
  The agent will sometimes need something from you, and the TUI asks inline. Tool approvals are a `y`/`n`. Option questions let you pick with `↑`/`↓` and `Enter`, or you can type a freeform answer. If a tool needs an authorized [connection](../connections), the URL shows up right in the transcript, and the turn picks back up once you've finished the flow.
28
28
 
@@ -32,7 +32,7 @@ Density flags accept `full` / `collapsed` / `auto-collapsed` / `hidden`:
32
32
  eve dev --tools full --assistant-response-stats tokens --context-size 200000
33
33
  ```
34
34
 
35
- Other useful flags: `--subagents`, `--reasoning`, `--logs <all|stderr|none>`, `--host`/`--port`, and `--no-ui` (headless, also the automatic fallback when stdout isn't a TTY).
35
+ Other useful flags: `--subagents`, `--reasoning`, `--logs <all|stderr|sandbox|none>`, `--host`/`--port`, and `--no-ui` (headless, also the automatic fallback when stdout isn't a TTY).
36
36
 
37
37
  ## Remote: `eve dev <url>`
38
38
 
@@ -88,7 +88,7 @@ Pass a bare URL as the only argument and the UI connects to that server instead
88
88
  | `--connection-auth <mode>` | Connection-authorization rendering: `full` \| `collapsed` \| `auto-collapsed` \| `hidden` |
89
89
  | `--assistant-response-stats <mode>` | Assistant header statistic: `tokens` \| `tokensPerSecond` |
90
90
  | `--context-size <tokens>` | Model context window size, shown as a usage percentage |
91
- | `--logs <mode>` | Server/agent logs to show: `all` \| `stderr` \| `none` |
91
+ | `--logs <mode>` | Server/agent logs to show: `all` \| `stderr` \| `sandbox` \| `none` |
92
92
 
93
93
  Local dev keeps immutable runtime source snapshots under `.eve/dev-runtime/snapshots/` so in-flight sessions keep a consistent code revision while new prompts pick up rebuilds. `eve dev` prunes stale runtime snapshots and old local sandbox templates in the background on startup; stopping `eve dev` and deleting `.eve/dev-runtime/snapshots/` or `.eve/sandbox-cache/local/templates/` is safe when you want a manual cleanup.
94
94
 
package/docs/sandbox.mdx CHANGED
@@ -144,11 +144,11 @@ export default defineSandbox({
144
144
 
145
145
  ### Docker
146
146
 
147
- `dockerBackend()` drives the Docker CLI directly. The default base image is `ubuntu:26.04`, the official Ubuntu 26.04 image from Docker Hub; Eve installs Node 24, npm, Bash, and baseline tools during framework setup before authored bootstrap code runs. Configure it through `dockerBackend({ image, env, pullPolicy, networkPolicy })`; custom images must provide Bash, Node 24, and npm, or a package manager and setup network access that can install them. Templates are committed as local Docker images and reused across sessions when the sandbox source, seed files, `revalidationKey`, and Docker backend options still match; sessions run as long-lived containers whose filesystems persist `/workspace` changes across turns for the same durable session. `eve dev` prunes stale template images in the background.
147
+ `dockerBackend()` drives the Docker CLI directly. The default base image is `ubuntu:26.04`, the official Ubuntu 26.04 image from Docker Hub; Eve creates `/workspace` and verifies Bash during framework setup before authored bootstrap code runs. Configure it through `dockerBackend({ image, env, pullPolicy, networkPolicy })`; install authored runtime tools such as Node, Python, or ripgrep in sandbox bootstrap or provide them through a custom image. Templates are committed as local Docker images and reused across sessions when the sandbox source, seed files, `revalidationKey`, and Docker backend options still match; sessions run as long-lived containers whose filesystems persist `/workspace` changes across turns for the same durable session. `eve dev` prunes stale template images in the background.
148
148
 
149
149
  ### microsandbox
150
150
 
151
- `microsandboxBackend()` runs each sandbox in a lightweight local VM with snapshot-backed templates, a `vercel-sandbox` user, and a firewall capable of domain-level network policies and credential brokering — the closest local match to hosted Vercel Sandbox. Supported hosts: macOS on Apple Silicon, or Linux (glibc) with KVM. The `microsandbox` npm package and its VM runtime are not bundled with Eve: `eve dev` installs both automatically when missing (disable with `setup: { autoInstall: false }`); production processes fail with actionable install errors instead.
151
+ `microsandboxBackend()` runs each sandbox in a lightweight local VM with snapshot-backed templates, a `vercel-sandbox` user, and a firewall capable of domain-level network policies and credential brokering — the closest local match to hosted Vercel Sandbox. The default base image is `ubuntu:26.04`; Eve verifies Bash, creates `/workspace`, and creates the sandbox user during framework setup before authored bootstrap code runs. Install authored runtime tools such as Node, Python, or ripgrep in sandbox bootstrap or provide them through a custom Ubuntu image. Supported hosts: macOS on Apple Silicon, or Linux (glibc) with KVM. The `microsandbox` npm package and its VM runtime are not bundled with Eve: `eve dev` installs both automatically when missing (disable with `setup: { autoInstall: false }`); production processes fail with actionable install errors instead.
152
152
 
153
153
  ### just-bash
154
154
 
@@ -193,7 +193,7 @@ networkPolicy: {
193
193
  };
194
194
  ```
195
195
 
196
- Set it on the factory (`vercelSandboxBackend({ networkPolicy: "deny-all" })`) and it applies from creation, including during `bootstrap`. Set it in `onSession`'s `use()` to override per-session. The common pattern combines both: leave the factory open so `bootstrap` can `git clone`, then lock down in `onSession`. And to change the policy mid-turn, call `sandbox.setNetworkPolicy(...)` on the live handle.
196
+ Set it on the factory (`vercelSandboxBackend({ networkPolicy: "deny-all" })`) and it applies before authored `bootstrap` code runs; framework-owned base setup may briefly keep egress open to install required packages. Set it in `onSession`'s `use()` to override per-session. The common pattern combines both: leave the factory open so `bootstrap` can `git clone`, then lock down in `onSession`. And to change the policy mid-turn, call `sandbox.setNetworkPolicy(...)` on the live handle.
197
197
 
198
198
  Domain-level allow-lists and credential brokering are supported by `vercelSandboxBackend()` and `microsandboxBackend()`. The Docker backend honors only `"allow-all"` and `"deny-all"` (at creation and via `setNetworkPolicy`); the just-bash backend rejects `setNetworkPolicy` entirely.
199
199
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "private": false,
5
5
  "description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
6
6
  "keywords": [
@@ -288,6 +288,7 @@
288
288
  "svelte": "^5.0.0",
289
289
  "turndown": "7.2.4",
290
290
  "vite": "^8.0.0",
291
+ "vitest": "4.1.7",
291
292
  "vue": "^3.5.0",
292
293
  "zod": "4.4.3",
293
294
  "zod-validation-error": "5.0.0",