eve 0.11.6 → 0.11.8
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.
- package/CHANGELOG.md +18 -0
- package/README.md +10 -10
- package/bin/eve.d.ts +2 -2
- package/bin/eve.js +9 -9
- package/dist/src/cli/commands/init.d.ts +1 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-create.d.ts +12 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-create.js +1 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox.js +1 -1
- package/dist/src/internal/application/optional-package-install.d.ts +1 -0
- package/dist/src/internal/application/optional-package-install.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/nitro/routes/index.js +1 -1
- package/dist/src/public/channels/slack/defaults.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +2 -2
- package/dist/src/setup/flows/vercel.js +1 -1
- package/dist/src/setup/scaffold/create/project.d.ts +1 -1
- package/dist/src/setup/scaffold/create/project.js +4 -4
- package/dist/src/setup/scaffold/create/web-template.d.ts +2 -1
- package/dist/src/setup/scaffold/create/web-template.js +1 -1
- package/dist/src/setup/scaffold/update/channels.d.ts +0 -1
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/scaffold/version-tokens.d.ts +1 -1
- package/dist/src/setup/scaffold/version-tokens.js +1 -1
- package/docs/channels/slack.mdx +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.11.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4622d94: Point the npm README, runtime landing page, and setup guidance at the canonical eve documentation domain.
|
|
8
|
+
- bfc7191: Use the official TypeScript 7 `tsc` compiler for eve builds, base generated projects, and fixture typechecks. Next.js projects and generated Web Chat apps pin `typescript@6.0.3`, which still provides the JavaScript compiler API Next.js requires.
|
|
9
|
+
|
|
10
|
+
## 0.11.7
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 11a9a3e: Report image-pull and VM-boot progress during microsandbox creation, and include phase and provider-specific recovery guidance when prewarm fails.
|
|
15
|
+
- 7b8df64: Serialize optional sandbox engine auto-installs and reload newly installed engines through their package entrypoint file instead of retrying the cached bare specifier. This prevents first-run `eve dev` sessions from racing microsandbox installation or surfacing Node's stale same-process module-not-found result after Bun installs `microsandbox`.
|
|
16
|
+
|
|
17
|
+
`eve init` also supports `EVE_INIT_PACKAGE_SPEC` so local tarball/source validation can make the generated project install the same eve build under test instead of resolving the published semver range from the registry.
|
|
18
|
+
|
|
19
|
+
- 159d4af: Slack reasoning typing indicators now update progressively when the cumulative status grows by at least four characters, preventing opening fragments from remaining stale without issuing one Slack request per token.
|
|
20
|
+
|
|
3
21
|
## 0.11.6
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -75,7 +75,7 @@ Runtime accessors live on the subpath that owns the concern:
|
|
|
75
75
|
- `getSkill(identifier)` — handle for a named skill visible to the current agent (`eve/skills`)
|
|
76
76
|
- `getContext(key)`, `requireContext(key)`, `hasContext(key)`, `setContext(key)`, `ensureContext(key, factory)` — unified context helpers (`eve/context`)
|
|
77
77
|
|
|
78
|
-
The complete API reference, including types and lower-level runtime primitives, is in [
|
|
78
|
+
The complete API reference, including types and lower-level runtime primitives, is in the [TypeScript API documentation](https://eve.dev/docs/reference/typescript-api).
|
|
79
79
|
|
|
80
80
|
## Tiny Example
|
|
81
81
|
|
|
@@ -138,22 +138,22 @@ CLI commands:
|
|
|
138
138
|
|
|
139
139
|
## Deploying
|
|
140
140
|
|
|
141
|
-
eve is built to be durable. The runtime is Nitro + Workflows. Read [
|
|
141
|
+
eve is built to be durable. The runtime is Nitro + Workflows. Read the [deployment guide](https://eve.dev/docs/guides/deployment) for the deployment path, environment variables, and configuration.
|
|
142
142
|
|
|
143
143
|
## Read Next
|
|
144
144
|
|
|
145
145
|
These files ship inside the installed package at `node_modules/eve/docs/`:
|
|
146
146
|
|
|
147
|
-
- [Full docs index](
|
|
148
|
-
- [Getting Started](
|
|
149
|
-
- [Project Layout](
|
|
150
|
-
- [`agent.ts`](
|
|
151
|
-
- [TypeScript API](
|
|
152
|
-
- [Vercel Deployment](
|
|
147
|
+
- [Full docs index](https://eve.dev/docs) — recommended entry point
|
|
148
|
+
- [Getting Started](https://eve.dev/docs/getting-started) — install, scaffold, and run locally
|
|
149
|
+
- [Project Layout](https://eve.dev/docs/reference/project-layout) — every authored directory in depth
|
|
150
|
+
- [`agent.ts`](https://eve.dev/docs/agent-config) — agent config reference
|
|
151
|
+
- [TypeScript API](https://eve.dev/docs/reference/typescript-api) — complete `define*` and runtime helper reference
|
|
152
|
+
- [Vercel Deployment](https://eve.dev/docs/guides/deployment) — deploy to production
|
|
153
153
|
|
|
154
|
-
By authoring concern: [Tools](
|
|
154
|
+
By authoring concern: [Tools](https://eve.dev/docs/tools) · [Channels](https://eve.dev/docs/channels/overview) · [Hooks](https://eve.dev/docs/guides/hooks) · [Skills](https://eve.dev/docs/skills) · [Sandbox](https://eve.dev/docs/sandbox) · [Connections](https://eve.dev/docs/connections) · [Subagents](https://eve.dev/docs/subagents) · [Schedules](https://eve.dev/docs/schedules) · [Evals](https://eve.dev/docs/evals/overview)
|
|
155
155
|
|
|
156
|
-
By runtime concern: [Sessions and Streaming](
|
|
156
|
+
By runtime concern: [Sessions and Streaming](https://eve.dev/docs/concepts/sessions-runs-and-streaming) · [Session Context](https://eve.dev/docs/guides/session-context) · [Context Control](https://eve.dev/docs/concepts/context-control) · [Auth and Route Protection](https://eve.dev/docs/guides/auth-and-route-protection) · [CLI, Build, and Debugging](https://eve.dev/docs/reference/cli) · [Instrumentation](https://eve.dev/docs/guides/instrumentation)
|
|
157
157
|
|
|
158
158
|
## Architecture (Internals)
|
|
159
159
|
|
package/bin/eve.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export interface BootstrapOptions {
|
|
|
15
15
|
postBuildScriptPaths?: readonly string[];
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Absolute path to the
|
|
18
|
+
* Absolute path to the tsc CLI entrypoint used for bootstrap builds.
|
|
19
19
|
*/
|
|
20
|
-
|
|
20
|
+
tscCliPath?: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export interface BootstrapCommandOptions {
|
package/bin/eve.js
CHANGED
|
@@ -29,7 +29,7 @@ function createBootstrapOptions(overrides = {}) {
|
|
|
29
29
|
resolve(packageRoot, "scripts", "copy-docs.mjs"),
|
|
30
30
|
resolve(packageRoot, "scripts", "stamp-version-tokens.mjs"),
|
|
31
31
|
],
|
|
32
|
-
|
|
32
|
+
tscCliPath: overrides.tscCliPath,
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -198,17 +198,17 @@ async function assertSupportedNodeVersion(
|
|
|
198
198
|
);
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
function
|
|
202
|
-
if (
|
|
203
|
-
return
|
|
201
|
+
function resolveTscCliPath({ tscCliPath }) {
|
|
202
|
+
if (tscCliPath) {
|
|
203
|
+
return tscCliPath;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
// The
|
|
207
|
-
//
|
|
206
|
+
// The `typescript` package only exports `./package.json` in its `exports`
|
|
207
|
+
// map, so `require.resolve("typescript/bin/tsc")`
|
|
208
208
|
// fails with ERR_PACKAGE_PATH_NOT_EXPORTED. Resolve the package.json
|
|
209
209
|
// (which is exported) and join to the binary path manually.
|
|
210
|
-
const packageJsonPath = require.resolve("
|
|
211
|
-
return resolve(dirname(packageJsonPath), "bin", "
|
|
210
|
+
const packageJsonPath = require.resolve("typescript/package.json");
|
|
211
|
+
return resolve(dirname(packageJsonPath), "bin", "tsc");
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
async function runCommand(command, args, options) {
|
|
@@ -276,7 +276,7 @@ export async function ensureBuiltCli(overrides = {}, dependencies = {}) {
|
|
|
276
276
|
|
|
277
277
|
await executeCommand(
|
|
278
278
|
process.execPath,
|
|
279
|
-
[
|
|
279
|
+
[resolveTscCliPath({ tscCliPath: options.tscCliPath }), "-p", "tsconfig.json"],
|
|
280
280
|
{
|
|
281
281
|
cwd: options.packageRoot,
|
|
282
282
|
},
|
|
@@ -23,6 +23,7 @@ export interface InitCommandDependencies {
|
|
|
23
23
|
spawnPackageManager: typeof spawnPackageManager;
|
|
24
24
|
tryInitializeGit: typeof tryInitializeGit;
|
|
25
25
|
}
|
|
26
|
+
export declare const EVE_INIT_PACKAGE_SPEC_ENV = "EVE_INIT_PACKAGE_SPEC";
|
|
26
27
|
/**
|
|
27
28
|
* Creates a new eve agent (`target` is a project name), or adds one to an
|
|
28
29
|
* existing project (`target` is a directory), without prompts or external
|
|
@@ -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{initAgentDevHandoff}from"./agent-instructions.js";import{tryInitializeGit}from"./init-git.js";import{basename,join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,readdir,rename,rm,stat}from"node:fs/promises";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{EVE_WORDMARK}from"#cli/banner.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{SPINNER_FRAMES,SPINNER_FRAME_MS}from"#setup/cli/rail-log.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectInvokingPackageManager,detectPackageManager}from"#setup/package-manager.js";import{pathExists}from"#setup/path-exists.js";import{parseProjectName}from"#setup/project-name.js";import{eveDevArguments,runPackageManagerInstall,spawnPackageManager}from"#setup/primitives/index.js";import{addAgentToProject}from"#setup/scaffold/create/add-to-project.js";var import_picocolors=__toESM(require_picocolors(),1);const defaultDependencies={addAgentToProject,detectInvokingPackageManager,detectPackageManager,ensureChannel,isCodingAgentLaunch,runPackageManagerInstall,scaffoldBaseProject,spawnPackageManager,tryInitializeGit},ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`])
|
|
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{initAgentDevHandoff}from"./agent-instructions.js";import{tryInitializeGit}from"./init-git.js";import{basename,join,resolve}from"node:path";import{ensureChannel,scaffoldBaseProject}from"#setup/scaffold/index.js";import{mkdtemp,readdir,rename,rm,stat}from"node:fs/promises";import{isCodingAgentLaunch}from"#cli/agent-detection.js";import{EVE_WORDMARK}from"#cli/banner.js";import{DEFAULT_AGENT_MODEL_ID}from"#shared/default-agent-model.js";import{SPINNER_FRAMES,SPINNER_FRAME_MS}from"#setup/cli/rail-log.js";import{formatNodeEngineOverrideWarning}from"#setup/node-engine.js";import{detectInvokingPackageManager,detectPackageManager}from"#setup/package-manager.js";import{pathExists}from"#setup/path-exists.js";import{parseProjectName}from"#setup/project-name.js";import{eveDevArguments,runPackageManagerInstall,spawnPackageManager}from"#setup/primitives/index.js";import{addAgentToProject}from"#setup/scaffold/create/add-to-project.js";import{DEFAULT_EVE_PACKAGE_CONTRACT}from"#setup/scaffold/create/project.js";var import_picocolors=__toESM(require_picocolors(),1);const defaultDependencies={addAgentToProject,detectInvokingPackageManager,detectPackageManager,ensureChannel,isCodingAgentLaunch,runPackageManagerInstall,scaffoldBaseProject,spawnPackageManager,tryInitializeGit},ALLOWED_CREATE_IN_PLACE_ENTRIES=new Set([`.DS_Store`,`.git`,`.gitkeep`,`.hg`]),EVE_INIT_PACKAGE_SPEC_ENV=`EVE_INIT_PACKAGE_SPEC`;async function resolveTargetDirectory(e,t){let n=resolve(e,t);return(await stat(n).catch(()=>void 0))?.isDirectory()?n:void 0}function isCurrentDirectoryTarget(e){return/^\.(?:[/\\]+\.?)*$/u.test(e.trim())}async function assertCanScaffoldInPlace(e){let t=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(t.length===0)return;let n=t.slice(0,5).join(`, `),r=t.length>5?`, and ${t.length-5} more`:``;throw Error(`Cannot create project in current directory because it is not empty. Found: ${n}${r}. Use an empty directory.`)}async function moveDirectoryContents(e,t){for(let n of await readdir(e))await rename(join(e,n),join(t,n))}async function addToExistingProject(e,t,n,r){if(t.channelWebNextjs===!0)throw Error("`--channel-web-nextjs` is not supported when adding an agent to an existing project. Run `eve channels add web` from the project afterwards instead.");let i=await n.detectPackageManager(e),a=await n.addAgentToProject({projectRoot:e,model:DEFAULT_AGENT_MODEL_ID,packageManager:i.kind,evePackage:r});return{packageManager:i.kind,nodeEngineOverride:a.nodeEngineOverride}}async function resolveScaffoldPackageManager(e,t){let n=await t.detectPackageManager(e);return n.source==="default"?t.detectInvokingPackageManager()??`pnpm`:n.kind}async function scaffoldProject(e,t,n,r,o,s){let l=resolve(e),f=t===`.`,p=f?l:join(l,t);if(f)await assertCanScaffoldInPlace(p);else if(await pathExists(p))throw Error(`Cannot create project because "${p}" already exists.`);let m=await mkdtemp(join(l,`.eve-init-`));try{let e={projectName:f?basename(p):t,model:DEFAULT_AGENT_MODEL_ID,evePackage:s,targetDirectory:m,packageManager:n},a=await o.scaffoldBaseProject(e);return r.channelWebNextjs===!0&&await o.ensureChannel({projectRoot:a,kind:`web`,packageManager:n,configureVercelServices:!1}),f?await moveDirectoryContents(a,p):await rename(a,p),p}finally{await rm(m,{recursive:!0,force:!0})}}function startSpinner(e,t){if(process.stdout.isTTY!==!0)return e.log(t),{stop(){}};let row=e=>`${import_picocolors.default.green(e)} ${t}`;process.stdout.write(row(SPINNER_FRAMES[0]));let n=0,r=setInterval(()=>{n+=1;let e=SPINNER_FRAMES[n%SPINNER_FRAMES.length]??SPINNER_FRAMES[0];process.stdout.write(`\r\u001B[K${row(e)}`)},SPINNER_FRAME_MS);r.unref?.();let i=!1;return{stop(){i||(i=!0,clearInterval(r),process.stdout.write(`\r\x1B[K`))}}}async function runInitCommand(e,t,r,i,o=defaultDependencies){let s=await o.isCodingAgentLaunch(),c=r??`.`,l=resolveInitEvePackageOverride(),u=isCurrentDirectoryTarget(c),d=u?await pathExists(join(resolve(t),`package.json`))?resolve(t):void 0:await resolveTargetDirectory(t,c),f,p,h;if(d===void 0){let n=u?`.`:parseProjectName(c),r=resolve(t);f=await resolveScaffoldPackageManager(n===`.`?r:join(r,n),o),p=await scaffoldProject(t,n,f,i,o,l),h=!0,e.log(`${import_picocolors.default.green(`✓`)} Created an ${EVE_WORDMARK} agent in ${import_picocolors.default.bold(p)}`)}else{let t=await addToExistingProject(d,i,o,l);f=t.packageManager,p=d,h=!1,e.log(`${import_picocolors.default.green(`✓`)} Added an ${EVE_WORDMARK} agent to ${import_picocolors.default.bold(p)}`),t.nodeEngineOverride!==void 0&&e.log(import_picocolors.default.yellow(`⚠ ${formatNodeEngineOverrideWarning(t.nodeEngineOverride)}`))}let g=[],_=startSpinner(e,`Installing dependencies...`),v;try{v=await o.runPackageManagerInstall(f,p,{bypassMinimumReleaseAge:!0,onOutput:e=>g.push(e.text)})}finally{_.stop()}if(!v){for(let t of g)e.error(t);throw Error(`Failed to install dependencies in "${p}".`)}if(e.log(`${import_picocolors.default.green(`✓`)} Installed dependencies`),h){let t=o.tryInitializeGit(p);t.kind===`failed`&&e.error(import_picocolors.default.yellow(`Git initialization failed: ${t.reason}`))}if(s){e.log(initAgentDevHandoff({projectPath:p,devCommand:[f,...eveDevArguments(f)].join(` `)}));return}let y=h?[...eveDevArguments(f),`--input`,`/model`]:eveDevArguments(f);if(e.log(import_picocolors.default.dim(h?`$ eve dev --input /model`:`$ eve dev`)),!await o.spawnPackageManager(f,p,y))throw Error(`Development server exited unsuccessfully in "${p}".`)}function resolveInitEvePackageOverride(){let e=process.env[EVE_INIT_PACKAGE_SPEC_ENV]?.trim();if(!(e===void 0||e.length===0))return{nodeEngine:DEFAULT_EVE_PACKAGE_CONTRACT.nodeEngine,version:e}}export{EVE_INIT_PACKAGE_SPEC_ENV,runInitCommand};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MicrosandboxError, Sandbox as MicrosandboxSandbox, SandboxBuilder as MicrosandboxSandboxBuilder } from "microsandbox";
|
|
2
|
+
export declare function createMicrosandboxWithProgress(input: {
|
|
3
|
+
readonly builder: MicrosandboxSandboxBuilder;
|
|
4
|
+
readonly errorType: typeof MicrosandboxError;
|
|
5
|
+
readonly log?: (message: string) => void;
|
|
6
|
+
readonly source: string;
|
|
7
|
+
}): Promise<MicrosandboxSandbox>;
|
|
8
|
+
export declare function enrichMicrosandboxError(input: {
|
|
9
|
+
readonly context: string;
|
|
10
|
+
readonly error: unknown;
|
|
11
|
+
readonly errorType?: typeof MicrosandboxError;
|
|
12
|
+
}): Error;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{toErrorMessage}from"#shared/errors.js";async function createMicrosandboxWithProgress(e){let t={phase:`resolving the image`};try{let n=await e.builder.createWithPullProgress(),r=reportMicrosandboxCreateProgress(n,t,e.log);try{return await withHeartbeat(t,e.log,async()=>await n.awaitSandbox())}finally{await r.catch(()=>{})}}catch(n){throw enrichMicrosandboxError({context:`Failed to create microsandbox VM from ${e.source} while ${t.phase}`,error:n,errorType:e.errorType})}}function enrichMicrosandboxError(t){if(t.error instanceof MicrosandboxDiagnosticError)return t.error;let n=readMicrosandboxErrorCode(t.error,t.errorType),r=n===void 0?``:` [${n}]`,i=toErrorMessage(t.error),a=/[.!?]$/u.test(i)?i:`${i}.`,o=microsandboxErrorHint(n),s=o===void 0?``:` ${o}`;return new MicrosandboxDiagnosticError(`${t.context}${r}: ${a}${s}`,{cause:t.error})}var MicrosandboxDiagnosticError=class extends Error{};async function reportMicrosandboxCreateProgress(e,t,n){for await(let r of e){let e=microsandboxCreatePhase(r,t.phase);e!==t.phase&&(t.phase=e,n?.(e))}}function microsandboxCreatePhase(e,t){switch(e.kind){case`resolving`:case`resolved`:return`resolving the image`;case`layerDownloadProgress`:case`layerDownloadComplete`:case`layerDownloadVerifying`:case`layerMaterializeStarted`:case`layerMaterializeProgress`:case`layerMaterializeWriting`:case`layerMaterializeComplete`:return`downloading and materializing image layers`;case`stitchMergingTrees`:case`stitchWritingFsmeta`:case`stitchWritingVmdk`:case`stitchComplete`:return`assembling the image filesystem`;case`complete`:return`image ready; booting microsandbox VM`;default:return t}}async function withHeartbeat(e,t,n){if(t?.(e.phase),t===void 0)return await n();let r=Date.now(),i=setInterval(()=>{let n=Math.round((Date.now()-r)/1e3);t(`${e.phase} (${n}s elapsed)`)},1e4);i.unref?.();try{return await n()}finally{clearInterval(i)}}const MICROSANDBOX_ERROR_HINTS={database:`Check that the microsandbox npm package and installed VM runtime use the same version. If versions changed, use a clean MSB_HOME or migrate the existing database.`,imageNotFound:`Check that the image exists and that the registry credentials can pull it.`,libkrunfwNotFound:"Run `npx microsandbox install` and verify that MSB_PATH points to the installed runtime."};function readMicrosandboxErrorCode(e,n){if(n!==void 0&&e instanceof n||e instanceof Error&&`code`in e&&typeof e.code==`string`&&Object.hasOwn(MICROSANDBOX_ERROR_HINTS,e.code))return e.code}function microsandboxErrorHint(e){return e===void 0?void 0:MICROSANDBOX_ERROR_HINTS[e]}export{createMicrosandboxWithProgress,enrichMicrosandboxError};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{posix}from"node:path";import{access}from"node:fs/promises";import{createHash,randomUUID}from"node:crypto";import{isEveDevEnvironment,loadOptionalEnginePackage}from"#internal/application/optional-package-install.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{assertMicrosandboxPlatformCandidate,ensureMicrosandboxBaseRuntime}from"#execution/sandbox/bindings/microsandbox-platform.js";import{MICROSANDBOX_METADATA_VERSION,writeSessionMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{MICROSANDBOX_USER}from"#execution/sandbox/bindings/microsandbox-options.js";import{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment}from"#execution/sandbox/bindings/microsandbox-network.js";import{adaptMicrosandboxExecToSandboxProcess}from"#execution/sandbox/bindings/microsandbox-process.js";const MICROSANDBOX_STOP_TIMEOUT_MS=1e4;var MicrosandboxVm=class{#e;#t;#n;#r;#i;#a;#o;constructor(e,t,n,r,i,a,o){this.#e=e,this.#i=t,this.#a=n,this.#n=r,this.#t=i,this.#r=a,this.#o=o}get id(){return this.#e.sessionKey}async captureState(e){if(this.#r=e,isEveDevEnvironment())return this.#t!==void 0&&await this.writeMetadata(this.#t,e),{networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION};let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`);return await this.stopAndSnapshot(n),this.#o=n,this.#t!==void 0&&await this.writeMetadata(this.#t,e),t!==void 0&&await removeSnapshotIfExists(this.#e.module,t),{networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:n,version:MICROSANDBOX_METADATA_VERSION}}async detach(){await this.#i.detach().catch(()=>{})}async readFileBytes(e){try{let t=this.#i.fs();return await t.exists(e)?Buffer.from(await t.read(e)):null}catch{return null}}async removePath(e){let t=`${e.force===!0?`f`:``}${e.recursive===!0?`r`:``}`,n=`${t.length>0?`rm -${t}`:`rm`} -- ${shellQuote(e.path)}`;await this.runInternalCommand({abortSignal:e.abortSignal,command:n,user:MICROSANDBOX_USER})}async removePersisted(){await removeSandboxIfExists(this.#e.module,this.#a),this.#o!==void 0&&await removeSnapshotIfExists(this.#e.module,this.#o)}async setNetworkPolicy(e){let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`),i=this.#a;await this.stopAndSnapshot(n),await removeSandboxIfExists(this.#e.module,i);let a=createProviderName(`eve-sbx-ses`,`${this.#e.sessionKey}:${randomUUID()}`);this.#i=await createMicrosandbox({fromSnapshot:n,module:this.#e.module,name:a,networkPolicy:e,options:this.#e.options,tags:this.#e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT}),this.#a=a,this.#n=e,this.#o=void 0,this.#t!==void 0&&this.#r!==void 0&&await this.writeMetadata(this.#t,this.#r),await removeSnapshotIfExists(this.#e.module,n),t!==void 0&&await removeSnapshotIfExists(this.#e.module,t)}async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t={...this.#e.options.env,...createTransformBrokerEnvironment(createMicrosandboxNetworkPlan(this.#n)),...e.env},n=await this.#i.execStreamWith(`bash`,n=>n.args([`-lc`,e.command]).cwd(e.workingDirectory??WORKSPACE_ROOT).envs(t).user(MICROSANDBOX_USER));return e.abortSignal!==void 0&&e.abortSignal.addEventListener(`abort`,()=>{n.kill().catch(()=>{})},{once:!0}),adaptMicrosandboxExecToSandboxProcess(n)}async stopAndSnapshot(e){await this.#i.stop().catch(()=>{}),await stopAndSnapshotMicrosandboxSandbox(this.#e.module,this.#a,e)}async writeFiles(t){let n=this.#i.fs();for(let r of t){let t=posix.dirname(r.path);await this.runInternalCommand({command:`mkdir -p ${shellQuote(t)}`,user:MICROSANDBOX_USER}),await n.write(r.path,r.content),await this.runInternalCommand({command:`chown ${MICROSANDBOX_USER}:${MICROSANDBOX_USER} ${shellQuote(r.path)}`,user:`root`})}}async writeMetadata(e,t){this.#t=e,this.#r=t,await writeSessionMetadata(e,{networkPolicy:this.#n,optionsHash:t,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION})}async runInternalCommand(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=await this.#i.execWith(`bash`,t=>t.args([`-lc`,e.command]).cwd(WORKSPACE_ROOT).user(e.user));if(t.code!==0){let n=e.failureMessage??`Microsandbox command failed.`;throw Error(`${n} ${t.stderr()}`.trim())}}};async function createPreparedMicrosandbox(e){let t=e.setupBaseRuntime?`allow-all`:e.networkPolicy,n=await createMicrosandbox({fromSnapshot:e.fromSnapshot,module:e.module,name:e.name,networkPolicy:t,options:e.options,tags:e.tags,user:e.setupBaseRuntime?void 0:MICROSANDBOX_USER,workdir:e.setupBaseRuntime?`/`:WORKSPACE_ROOT}),r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.name,t);return e.setupBaseRuntime&&(await withProgressHeartbeat(`preparing base runtime inside VM`,e.log,async()=>{await ensureMicrosandboxBaseRuntime(n,{log:e.log})}),e.networkPolicy!==void 0&&e.networkPolicy!==`allow-all`&&(e.log?.(`applying network policy`),await r.setNetworkPolicy(e.networkPolicy))),r}async function connectMicrosandbox(e){let t;try{t=await e.module.Sandbox.get(e.metadata.sandboxName)}catch(t){if(!isMicrosandboxNotFoundError(t))throw t;return e.metadata.stateSnapshotName===void 0?null:await restoreMicrosandboxSessionSnapshot(e)}if(t.status!==`running`&&t.status!==`draining`&&e.metadata.stateSnapshotName!==void 0)return await restoreMicrosandboxSessionSnapshot(e);let n=t.status===`running`||t.status===`draining`?await t.connectWithTimeout(1e4):await t.startDetached();return new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.metadata.sandboxName,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName)}async function restoreMicrosandboxSessionSnapshot(e){if(e.metadata.stateSnapshotName===void 0||!await snapshotExists(e.module,e.metadata.stateSnapshotName))return null;let t=createProviderName(`eve-sbx-ses`,`${e.sessionKey}:${randomUUID()}`),n=await createMicrosandbox({fromSnapshot:e.metadata.stateSnapshotName,module:e.module,name:t,networkPolicy:e.metadata.networkPolicy,options:e.options,tags:e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT});await removeSandboxIfExists(e.module,e.metadata.sandboxName);let i=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,t,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName);return await i.writeMetadata(e.metadataPath,e.metadata.optionsHash),i}async function loadMicrosandboxModule(e){e.log?.(`checking microsandbox platform support`),await assertMicrosandboxPlatformCandidate();let t=await withProgressHeartbeat(`loading microsandbox npm package`,e.log,()=>loadOptionalEnginePackage({appRoot:e.appRoot,autoInstall:e.options.setup.autoInstall,importModule:async()=>await import(`microsandbox`),missingMessage:"The microsandbox sandbox backend requires the `microsandbox` package, which is not bundled with eve. Install it in your application (for example `pnpm add -D microsandbox`), or use docker() / vercel() instead.",packageName:`microsandbox`}));if(e.log?.(`checking microsandbox VM runtime`),!t.isInstalled()){if(!e.options.setup.autoInstall||!isEveDevEnvironment())throw Error("The microsandbox VM runtime is not installed. Run `npx microsandbox install`, set MSB_PATH for a custom install, or let `eve dev` install it automatically with microsandbox({ setup: { autoInstall: true } }).");await withProgressHeartbeat(`installing microsandbox VM runtime`,e.log,async()=>{await t.setup().skipVerify(e.options.setup.skipVerify).install()})}return e.log?.(`microsandbox runtime ready`),t}async function withProgressHeartbeat(e,t,n){if(t?.(e),t===void 0)return await n();let r=Date.now(),i=setInterval(()=>{t(`${e} (${Math.round((Date.now()-r)/1e3)}s elapsed)`)},1e4);i.unref?.();try{return await n()}finally{clearInterval(i)}}async function loadMicrosandboxWithoutInstall(){try{let e=await import(`microsandbox`);return e.isInstalled()?e:null}catch{return null}}async function stopAndSnapshotMicrosandboxSandbox(e,t,n){for(let r=0;r<3;r+=1){let i=await e.Sandbox.get(t);await i.stopWithTimeout(r===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{});try{await i.snapshot(n);return}catch(e){if(!isMicrosandboxSnapshotSourceRunningError(e)||r===2)throw e;await i.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250))}}}async function snapshotExists(e,t){try{return await e.Snapshot.get(t),!0}catch{return!1}}async function sandboxExists(e,t){try{return await e.Sandbox.get(t),!0}catch(e){if(isMicrosandboxNotFoundError(e))return!1;throw e}}async function removeSnapshotIfExists(e,t){try{await e.Snapshot.remove(t,{force:!0})}catch(e){if(!isMicrosandboxNotFoundError(e))throw e}}function createProviderName(e,t,n=``){return`${e}-${createStableHash(`${t}:${n}`).slice(0,32)}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}async function doesPathExist(e){try{return await access(e),!0}catch{return!1}}async function createMicrosandbox(e){let t=e.module.Sandbox.builder(e.name).cpus(e.options.cpus).detached(!0).envs(e.options.env).labels(resolveMicrosandboxLabels(e.tags)).memory(e.options.memoryMiB).pullPolicy(e.options.pullPolicy).replace().workdir(e.workdir);return t=e.fromSnapshot===void 0?t.image(e.options.image):t.fromSnapshot(e.fromSnapshot),e.user!==void 0&&(t=t.user(e.user)),await applyMicrosandboxNetwork(t,e.networkPolicy).create()}async function removeSandboxIfExists(e,t){for(let n=0;n<3;n+=1)try{let r=await e.Sandbox.get(t);await r.stopWithTimeout(n===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{}),await r.remove();return}catch(r){if(isMicrosandboxNotFoundError(r))return;if(isMicrosandboxStillRunningError(r)&&n<2){await(await e.Sandbox.get(t).catch(()=>null))?.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250));continue}throw r}}function isMicrosandboxNotFoundError(e){return e instanceof Error?/not found|not exist|no such/i.test(e.message):!1}function isMicrosandboxStillRunningError(e){return e instanceof Error?/still running/i.test(e.message):!1}function isMicrosandboxSnapshotSourceRunningError(e){return e instanceof Error?/snapshot source sandbox .*not stopped|SnapshotSandboxRunning/i.test(e.message):!1}function resolveMicrosandboxLabels(e){return{"eve.backend":`microsandbox`,...withDevelopmentSandboxTags(e)}}export{MicrosandboxVm,connectMicrosandbox,createPreparedMicrosandbox,createProviderName,createStableHash,doesPathExist,isMicrosandboxNotFoundError,loadMicrosandboxModule,loadMicrosandboxWithoutInstall,removeSnapshotIfExists,sandboxExists,snapshotExists,stopAndSnapshotMicrosandboxSandbox};
|
|
1
|
+
import{posix}from"node:path";import{access}from"node:fs/promises";import{createHash,randomUUID}from"node:crypto";import{isEveDevEnvironment,loadOptionalEnginePackage}from"#internal/application/optional-package-install.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{assertMicrosandboxPlatformCandidate,ensureMicrosandboxBaseRuntime}from"#execution/sandbox/bindings/microsandbox-platform.js";import{MICROSANDBOX_METADATA_VERSION,writeSessionMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{MICROSANDBOX_USER}from"#execution/sandbox/bindings/microsandbox-options.js";import{createMicrosandboxWithProgress}from"#execution/sandbox/bindings/microsandbox-create.js";import{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment}from"#execution/sandbox/bindings/microsandbox-network.js";import{adaptMicrosandboxExecToSandboxProcess}from"#execution/sandbox/bindings/microsandbox-process.js";const MICROSANDBOX_STOP_TIMEOUT_MS=1e4;var MicrosandboxVm=class{#e;#t;#n;#r;#i;#a;#o;constructor(e,t,n,r,i,a,o){this.#e=e,this.#i=t,this.#a=n,this.#n=r,this.#t=i,this.#r=a,this.#o=o}get id(){return this.#e.sessionKey}async captureState(e){if(this.#r=e,isEveDevEnvironment())return this.#t!==void 0&&await this.writeMetadata(this.#t,e),{networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION};let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`);return await this.stopAndSnapshot(n),this.#o=n,this.#t!==void 0&&await this.writeMetadata(this.#t,e),t!==void 0&&await removeSnapshotIfExists(this.#e.module,t),{networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:n,version:MICROSANDBOX_METADATA_VERSION}}async detach(){await this.#i.detach().catch(()=>{})}async readFileBytes(e){try{let t=this.#i.fs();return await t.exists(e)?Buffer.from(await t.read(e)):null}catch{return null}}async removePath(e){let t=`${e.force===!0?`f`:``}${e.recursive===!0?`r`:``}`,n=`${t.length>0?`rm -${t}`:`rm`} -- ${shellQuote(e.path)}`;await this.runInternalCommand({abortSignal:e.abortSignal,command:n,user:MICROSANDBOX_USER})}async removePersisted(){await removeSandboxIfExists(this.#e.module,this.#a),this.#o!==void 0&&await removeSnapshotIfExists(this.#e.module,this.#o)}async setNetworkPolicy(e){let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`),i=this.#a;await this.stopAndSnapshot(n),await removeSandboxIfExists(this.#e.module,i);let a=createProviderName(`eve-sbx-ses`,`${this.#e.sessionKey}:${randomUUID()}`);this.#i=await createMicrosandbox({fromSnapshot:n,module:this.#e.module,name:a,networkPolicy:e,options:this.#e.options,tags:this.#e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT}),this.#a=a,this.#n=e,this.#o=void 0,this.#t!==void 0&&this.#r!==void 0&&await this.writeMetadata(this.#t,this.#r),await removeSnapshotIfExists(this.#e.module,n),t!==void 0&&await removeSnapshotIfExists(this.#e.module,t)}async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t={...this.#e.options.env,...createTransformBrokerEnvironment(createMicrosandboxNetworkPlan(this.#n)),...e.env},n=await this.#i.execStreamWith(`bash`,n=>n.args([`-lc`,e.command]).cwd(e.workingDirectory??WORKSPACE_ROOT).envs(t).user(MICROSANDBOX_USER));return e.abortSignal!==void 0&&e.abortSignal.addEventListener(`abort`,()=>{n.kill().catch(()=>{})},{once:!0}),adaptMicrosandboxExecToSandboxProcess(n)}async stopAndSnapshot(e){await this.#i.stop().catch(()=>{}),await stopAndSnapshotMicrosandboxSandbox(this.#e.module,this.#a,e)}async writeFiles(t){let n=this.#i.fs();for(let r of t){let t=posix.dirname(r.path);await this.runInternalCommand({command:`mkdir -p ${shellQuote(t)}`,user:MICROSANDBOX_USER}),await n.write(r.path,r.content),await this.runInternalCommand({command:`chown ${MICROSANDBOX_USER}:${MICROSANDBOX_USER} ${shellQuote(r.path)}`,user:`root`})}}async writeMetadata(e,t){this.#t=e,this.#r=t,await writeSessionMetadata(e,{networkPolicy:this.#n,optionsHash:t,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION})}async runInternalCommand(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=await this.#i.execWith(`bash`,t=>t.args([`-lc`,e.command]).cwd(WORKSPACE_ROOT).user(e.user));if(t.code!==0){let n=e.failureMessage??`Microsandbox command failed.`;throw Error(`${n} ${t.stderr()}`.trim())}}};async function createPreparedMicrosandbox(e){let t=e.setupBaseRuntime?`allow-all`:e.networkPolicy,n=await createMicrosandbox({fromSnapshot:e.fromSnapshot,log:e.log,module:e.module,name:e.name,networkPolicy:t,options:e.options,tags:e.tags,user:e.setupBaseRuntime?void 0:MICROSANDBOX_USER,workdir:e.setupBaseRuntime?`/`:WORKSPACE_ROOT}),r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.name,t);return e.setupBaseRuntime&&(await withProgressHeartbeat(`preparing base runtime inside VM`,e.log,async()=>{await ensureMicrosandboxBaseRuntime(n,{log:e.log})}),e.networkPolicy!==void 0&&e.networkPolicy!==`allow-all`&&(e.log?.(`applying network policy`),await r.setNetworkPolicy(e.networkPolicy))),r}async function connectMicrosandbox(e){let t;try{t=await e.module.Sandbox.get(e.metadata.sandboxName)}catch(t){if(!isMicrosandboxNotFoundError(t))throw t;return e.metadata.stateSnapshotName===void 0?null:await restoreMicrosandboxSessionSnapshot(e)}if(t.status!==`running`&&t.status!==`draining`&&e.metadata.stateSnapshotName!==void 0)return await restoreMicrosandboxSessionSnapshot(e);let n=t.status===`running`||t.status===`draining`?await t.connectWithTimeout(1e4):await t.startDetached();return new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.metadata.sandboxName,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName)}async function restoreMicrosandboxSessionSnapshot(e){if(e.metadata.stateSnapshotName===void 0||!await snapshotExists(e.module,e.metadata.stateSnapshotName))return null;let t=createProviderName(`eve-sbx-ses`,`${e.sessionKey}:${randomUUID()}`),n=await createMicrosandbox({fromSnapshot:e.metadata.stateSnapshotName,module:e.module,name:t,networkPolicy:e.metadata.networkPolicy,options:e.options,tags:e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT});await removeSandboxIfExists(e.module,e.metadata.sandboxName);let i=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,t,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName);return await i.writeMetadata(e.metadataPath,e.metadata.optionsHash),i}async function loadMicrosandboxModule(e){e.log?.(`checking microsandbox platform support`),await assertMicrosandboxPlatformCandidate();let t=await withProgressHeartbeat(`loading microsandbox npm package`,e.log,()=>loadOptionalEnginePackage({appRoot:e.appRoot,autoInstall:e.options.setup.autoInstall,importModule:async()=>await import(`microsandbox`),missingMessage:"The microsandbox sandbox backend requires the `microsandbox` package, which is not bundled with eve. Install it in your application (for example `pnpm add -D microsandbox`), or use docker() / vercel() instead.",packageName:`microsandbox`}));if(e.log?.(`checking microsandbox VM runtime`),!t.isInstalled()){if(!e.options.setup.autoInstall||!isEveDevEnvironment())throw Error("The microsandbox VM runtime is not installed. Run `npx microsandbox install`, set MSB_PATH for a custom install, or let `eve dev` install it automatically with microsandbox({ setup: { autoInstall: true } }).");await withProgressHeartbeat(`installing microsandbox VM runtime`,e.log,async()=>{await t.setup().skipVerify(e.options.setup.skipVerify).install()})}return e.log?.(`microsandbox runtime ready`),t}async function withProgressHeartbeat(e,t,n){if(t?.(e),t===void 0)return await n();let r=Date.now(),i=setInterval(()=>{t(`${e} (${Math.round((Date.now()-r)/1e3)}s elapsed)`)},1e4);i.unref?.();try{return await n()}finally{clearInterval(i)}}async function loadMicrosandboxWithoutInstall(){try{let e=await import(`microsandbox`);return e.isInstalled()?e:null}catch{return null}}async function stopAndSnapshotMicrosandboxSandbox(e,t,n){for(let r=0;r<3;r+=1){let i=await e.Sandbox.get(t);await i.stopWithTimeout(r===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{});try{await i.snapshot(n);return}catch(e){if(!isMicrosandboxSnapshotSourceRunningError(e)||r===2)throw e;await i.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250))}}}async function snapshotExists(e,t){try{return await e.Snapshot.get(t),!0}catch{return!1}}async function sandboxExists(e,t){try{return await e.Sandbox.get(t),!0}catch(e){if(isMicrosandboxNotFoundError(e))return!1;throw e}}async function removeSnapshotIfExists(e,t){try{await e.Snapshot.remove(t,{force:!0})}catch(e){if(!isMicrosandboxNotFoundError(e))throw e}}function createProviderName(e,t,n=``){return`${e}-${createStableHash(`${t}:${n}`).slice(0,32)}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}async function doesPathExist(e){try{return await access(e),!0}catch{return!1}}async function createMicrosandbox(e){let t=e.module.Sandbox.builder(e.name).cpus(e.options.cpus).detached(!0).envs(e.options.env).labels(resolveMicrosandboxLabels(e.tags)).memory(e.options.memoryMiB).pullPolicy(e.options.pullPolicy).replace().workdir(e.workdir);t=e.fromSnapshot===void 0?t.image(e.options.image):t.fromSnapshot(e.fromSnapshot),e.user!==void 0&&(t=t.user(e.user));let n=e.fromSnapshot===void 0?`image "${e.options.image}"`:`snapshot "${e.fromSnapshot}"`;return await createMicrosandboxWithProgress({builder:applyMicrosandboxNetwork(t,e.networkPolicy),errorType:e.module.MicrosandboxError,log:e.log,source:n})}async function removeSandboxIfExists(e,t){for(let n=0;n<3;n+=1)try{let r=await e.Sandbox.get(t);await r.stopWithTimeout(n===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{}),await r.remove();return}catch(r){if(isMicrosandboxNotFoundError(r))return;if(isMicrosandboxStillRunningError(r)&&n<2){await(await e.Sandbox.get(t).catch(()=>null))?.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250));continue}throw r}}function isMicrosandboxNotFoundError(e){return e instanceof Error?/not found|not exist|no such/i.test(e.message):!1}function isMicrosandboxStillRunningError(e){return e instanceof Error?/still running/i.test(e.message):!1}function isMicrosandboxSnapshotSourceRunningError(e){return e instanceof Error?/snapshot source sandbox .*not stopped|SnapshotSandboxRunning/i.test(e.message):!1}function resolveMicrosandboxLabels(e){return{"eve.backend":`microsandbox`,...withDevelopmentSandboxTags(e)}}export{MicrosandboxVm,connectMicrosandbox,createPreparedMicrosandbox,createProviderName,createStableHash,doesPathExist,isMicrosandboxNotFoundError,loadMicrosandboxModule,loadMicrosandboxWithoutInstall,removeSnapshotIfExists,sandboxExists,snapshotExists,stopAndSnapshotMicrosandboxSandbox};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createStableHash}from"#execution/sandbox/bindings/microsandbox-runtime.js";import{pruneMicrosandboxTemplates}from"#execution/sandbox/bindings/microsandbox-templates.js";import{microsandboxOptionsForHash,resolveMicrosandboxOptions}from"#execution/sandbox/bindings/microsandbox-options.js";import{createMicrosandboxHandle,prewarmMicrosandboxTemplate}from"#execution/sandbox/bindings/microsandbox-lifecycle.js";const MICROSANDBOX_BACKEND_NAME=`microsandbox`;function createMicrosandboxSandboxBackend(t={}){let n=resolveMicrosandboxOptions(t.createOptions),r=createStableHash(JSON.stringify(microsandboxOptionsForHash(n))).slice(0,20);return{name:MICROSANDBOX_BACKEND_NAME,async prewarm(e){return await prewarmMicrosandboxTemplate({backendName:MICROSANDBOX_BACKEND_NAME,options:n,optionsHash:r,prewarmInput:e})},async create(e){return await createMicrosandboxHandle({backendName:MICROSANDBOX_BACKEND_NAME,createInput:e,options:n,optionsHash:r})}}}export{MICROSANDBOX_BACKEND_NAME,createMicrosandboxSandboxBackend,pruneMicrosandboxTemplates};
|
|
1
|
+
import{createStableHash}from"#execution/sandbox/bindings/microsandbox-runtime.js";import{pruneMicrosandboxTemplates}from"#execution/sandbox/bindings/microsandbox-templates.js";import{microsandboxOptionsForHash,resolveMicrosandboxOptions}from"#execution/sandbox/bindings/microsandbox-options.js";import{enrichMicrosandboxError}from"#execution/sandbox/bindings/microsandbox-create.js";import{createMicrosandboxHandle,prewarmMicrosandboxTemplate}from"#execution/sandbox/bindings/microsandbox-lifecycle.js";const MICROSANDBOX_BACKEND_NAME=`microsandbox`;function createMicrosandboxSandboxBackend(t={}){let n=resolveMicrosandboxOptions(t.createOptions),r=createStableHash(JSON.stringify(microsandboxOptionsForHash(n))).slice(0,20);return{name:MICROSANDBOX_BACKEND_NAME,async prewarm(e){try{return await prewarmMicrosandboxTemplate({backendName:MICROSANDBOX_BACKEND_NAME,options:n,optionsHash:r,prewarmInput:e})}catch(t){throw enrichMicrosandboxError({context:`Failed to prewarm microsandbox template "${e.templateKey}"`,error:t})}},async create(e){return await createMicrosandboxHandle({backendName:MICROSANDBOX_BACKEND_NAME,createInput:e,options:n,optionsHash:r})}}}export{MICROSANDBOX_BACKEND_NAME,createMicrosandboxSandboxBackend,pruneMicrosandboxTemplates};
|
|
@@ -34,6 +34,7 @@ export declare function installPackageIntoProject(input: {
|
|
|
34
34
|
export declare function loadOptionalEnginePackage<T>(input: {
|
|
35
35
|
readonly appRoot: string;
|
|
36
36
|
readonly autoInstall: boolean;
|
|
37
|
+
readonly importInstalledModule?: () => Promise<T>;
|
|
37
38
|
readonly importModule: () => Promise<T>;
|
|
38
39
|
readonly missingMessage: string;
|
|
39
40
|
readonly packageName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync}from"node:fs";import{dirname,join}from"node:path";import{spawn}from"node:child_process";const EVE_DEV_ENV_FLAG=`EVE_DEV`;function isEveDevEnvironment(){return process.env[EVE_DEV_ENV_FLAG]===`1`}function detectProjectPackageManager(r){let i=r;for(;;){if(existsSync(join(i,`pnpm-lock.yaml`))||existsSync(join(i,`pnpm-workspace.yaml`)))return`pnpm`;if(existsSync(join(i,`yarn.lock`)))return`yarn`;if(existsSync(join(i,`bun.lock`))||existsSync(join(i,`bun.lockb`)))return`bun`;if(existsSync(join(i,`package-lock.json`)))return`npm`;let r=dirname(i);if(r===i)return`npm`;i=r}}const INSTALL_ARGUMENTS={bun:[`add`,`--dev`],npm:[`install`,`--save-dev`],pnpm:[`add`,`-D`],yarn:[`add`,`-D`]};async function installPackageIntoProject(e){let t=detectProjectPackageManager(e.appRoot),n=[...INSTALL_ARGUMENTS[t],e.packageName];console.info(`[eve:dev] installing optional dependency "${e.packageName}" via \`${t} ${n.join(` `)}\`...`);let i=spawn(t,n,{cwd:e.appRoot,shell:shouldSpawnPackageManagerWithShell(),stdio:[`ignore`,`pipe`,`pipe`]}),a=[];i.stdout?.on(`data`,e=>a.push(e)),i.stderr?.on(`data`,e=>a.push(e));let o=await new Promise((e,t)=>{i.on(`error`,t),i.on(`close`,t=>e(t??1))});if(o!==0){let n=Buffer.concat(a).toString(`utf8`).trim();throw Error(`Failed to install "${e.packageName}" with ${t} (exit ${o}).`+(n.length>0?`\n${n.slice(-2e3)}`:``))}console.info(`[eve:dev] installed "${e.packageName}".`)}async function loadOptionalEnginePackage(e){try{return await e.importModule()}catch(t){if(!e.autoInstall||!isEveDevEnvironment())throw Error(e.missingMessage,{cause:t});try{await installPackageIntoProject({appRoot:e.appRoot,packageName:e.packageName})}catch(t){throw Error(`${e.missingMessage} Automatic installation failed: ${toMessage(t)}`,{cause:t})}return await e.
|
|
1
|
+
import{existsSync}from"node:fs";import{dirname,join}from"node:path";import{spawn}from"node:child_process";import{mkdir,readFile,rm,stat,writeFile}from"node:fs/promises";import{pathToFileURL}from"node:url";const EVE_DEV_ENV_FLAG=`EVE_DEV`;function isEveDevEnvironment(){return process.env[EVE_DEV_ENV_FLAG]===`1`}function detectProjectPackageManager(r){let i=r;for(;;){if(existsSync(join(i,`pnpm-lock.yaml`))||existsSync(join(i,`pnpm-workspace.yaml`)))return`pnpm`;if(existsSync(join(i,`yarn.lock`)))return`yarn`;if(existsSync(join(i,`bun.lock`))||existsSync(join(i,`bun.lockb`)))return`bun`;if(existsSync(join(i,`package-lock.json`)))return`npm`;let r=dirname(i);if(r===i)return`npm`;i=r}}const INSTALL_ARGUMENTS={bun:[`add`,`--dev`],npm:[`install`,`--save-dev`],pnpm:[`add`,`-D`],yarn:[`add`,`-D`]},OPTIONAL_PACKAGE_LOCK_TIMEOUT_MS=600*1e3,pendingOptionalPackageInstalls=new Map;async function installPackageIntoProject(e){let t=detectProjectPackageManager(e.appRoot),n=[...INSTALL_ARGUMENTS[t],e.packageName];console.info(`[eve:dev] installing optional dependency "${e.packageName}" via \`${t} ${n.join(` `)}\`...`);let i=spawn(t,n,{cwd:e.appRoot,shell:shouldSpawnPackageManagerWithShell(),stdio:[`ignore`,`pipe`,`pipe`]}),a=[];i.stdout?.on(`data`,e=>a.push(e)),i.stderr?.on(`data`,e=>a.push(e));let o=await new Promise((e,t)=>{i.on(`error`,t),i.on(`close`,t=>e(t??1))});if(o!==0){let n=Buffer.concat(a).toString(`utf8`).trim();throw Error(`Failed to install "${e.packageName}" with ${t} (exit ${o}).`+(n.length>0?`\n${n.slice(-2e3)}`:``))}console.info(`[eve:dev] installed "${e.packageName}".`)}async function loadOptionalEnginePackage(e){try{return await e.importModule()}catch(t){if(!e.autoInstall||!isEveDevEnvironment())throw Error(e.missingMessage,{cause:t});let n=e.importInstalledModule??(async()=>await importInstalledEnginePackage({appRoot:e.appRoot,packageName:e.packageName}));try{await withOptionalPackageInstallLock(e,async()=>{try{await n();return}catch{}await installPackageIntoProject({appRoot:e.appRoot,packageName:e.packageName})})}catch(t){throw Error(`${e.missingMessage} Automatic installation failed: ${toMessage(t)}`,{cause:t})}return await n()}}async function importInstalledEnginePackage(e){let t=join(e.appRoot,`node_modules`,...e.packageName.split(`/`)),r=join(t,`package.json`),i=resolvePackageEntryPoint(JSON.parse(await readFile(r,`utf8`)));if(i.startsWith(`/`))throw Error(`Invalid absolute entrypoint for optional package "${e.packageName}".`);return await import(pathToFileURL(join(t,i)).href)}function resolvePackageEntryPoint(e){let t=readDotExport(e.exports);return t===void 0?typeof e.module==`string`&&e.module.length>0?e.module:typeof e.main==`string`&&e.main.length>0?e.main:`index.js`:t}function readDotExport(e){if(typeof e==`string`&&e.length>0)return e;if(typeof e!=`object`||!e)return;let t=`.`in e?e[`.`]:e;if(typeof t==`string`&&t.length>0)return t;if(typeof t!=`object`||!t)return;let n=t;if(typeof n.import==`string`&&n.import.length>0)return n.import;if(typeof n.default==`string`&&n.default.length>0)return n.default}async function withOptionalPackageInstallLock(e,t){let n=`${e.appRoot}:${e.packageName}`,r=pendingOptionalPackageInstalls.get(n);if(r!==void 0){await r;return}let i=withOptionalPackageInstallFileLock(e,t).finally(()=>{pendingOptionalPackageInstalls.delete(n)});pendingOptionalPackageInstalls.set(n,i),await i}async function withOptionalPackageInstallFileLock(e,t){let r=join(e.appRoot,`.eve`,`optional-package-locks`,`${sanitizeLockName(e.packageName)}.lock`);await acquireLock(r);try{await t()}finally{await rm(r,{force:!0,recursive:!0}).catch(()=>{})}}async function acquireLock(e){let r=Date.now();for(;;){await mkdir(dirname(e),{recursive:!0});try{await mkdir(e),await writeFile(join(e,`owner.json`),`${JSON.stringify({createdAt:new Date().toISOString(),pid:process.pid})}\n`);return}catch(t){if(!isFileExistsError(t))throw t;await waitForExistingLock(e,r)}}}async function waitForExistingLock(e,t){let n=await stat(e).catch(e=>{if(isNotFoundError(e))return null;throw e});if(n!==null){if(Date.now()-n.mtimeMs>18e5){await rm(e,{force:!0,recursive:!0}).catch(()=>{});return}if(Date.now()-t>OPTIONAL_PACKAGE_LOCK_TIMEOUT_MS)throw Error(`Timed out waiting for optional package install lock "${e}" after ${OPTIONAL_PACKAGE_LOCK_TIMEOUT_MS}ms.`);await new Promise(e=>setTimeout(e,250))}}function sanitizeLockName(e){return e.replaceAll(/[^a-zA-Z0-9._-]+/g,`-`)}function shouldSpawnPackageManagerWithShell(e=process.platform){return e===`win32`}function isFileExistsError(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`EEXIST`}function isNotFoundError(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function toMessage(e){return e instanceof Error?e.message:String(e)}export{EVE_DEV_ENV_FLAG,detectProjectPackageManager,installPackageIntoProject,isEveDevEnvironment,loadOptionalEnginePackage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.11.
|
|
1
|
+
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.11.8`,WORKFLOW_MODULE_ALIASES={"workflow/api":`src/compiled/@workflow/core/runtime.js`,"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`,"workflow/runtime":`src/compiled/@workflow/core/runtime.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -140,7 +140,7 @@ const DEPLOYMENT_URL_PLACEHOLDER=`{{DEPLOYMENT_URL}}`,HOME_PAGE_HTML_TEMPLATE=`<
|
|
|
140
140
|
running
|
|
141
141
|
</span>
|
|
142
142
|
<h1 class="mono">eve</h1>
|
|
143
|
-
<p class="lede">The agent is up and accepting messages. <a href="https://
|
|
143
|
+
<p class="lede">The agent is up and accepting messages. <a href="https://eve.dev/docs">Read the docs<span class="lede-arrow" aria-hidden="true"> →</span></a></p>
|
|
144
144
|
<div class="terminal mono" role="group" aria-label="Send a message from your terminal">
|
|
145
145
|
<span class="terminal-prompt" aria-hidden="true">$</span>
|
|
146
146
|
<span class="terminal-cmd">eve dev ${DEPLOYMENT_URL_PLACEHOLDER}</span>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{createLogger,extractErrorId,formatErrorHint}from"#internal/logging.js";import{truncateMessageText,truncateTypingStatus}from"#public/channels/slack/limits.js";import{buildSlackAuthContext}from"#public/channels/slack/auth.js";import{buildAuthCompletedText,buildAuthEphemeralBlocks,buildAuthRequiredPublicText,formatConnectionDisplayName}from"#public/channels/slack/connections.js";import{renderInputRequestBlocks}from"#public/channels/slack/hitl.js";const log=createLogger(`slack.defaults`);function defaultSlackAuth(e,t){let n=e.author;return n?buildSlackAuthContext({channelId:t.slack.channelId,fullName:n.fullName,isBot:n.isBot,teamId:e.teamId,threadTs:t.slack.threadTs,userId:n.userId,userName:n.userName}):null}async function defaultOnAppMention(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}async function defaultOnDirectMessage(e,t){return await e.thread.startTyping(`Thinking...`),{auth:defaultSlackAuth(t,e)}}function firstNonEmptyLine(e){for(let t of e.split(/\r?\n/u)){let e=t.trim();if(e.length>0)return e}}function defaultInputRequestedHandler(){return async(e,t,n)=>{if(e.requests.length===0)return;let i=truncateMessageText(e.requests.map(e=>e.prompt).join(`
|
|
2
|
-
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:i})}}const defaultEvents={async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let a=Date.now(),
|
|
2
|
+
`));await t.thread.post({blocks:e.requests.flatMap(renderInputRequestBlocks),text:i})}}const defaultEvents={async"turn.started"(e,t,n){t.state.pendingToolCallMessage=null,t.state.lastReasoningTypingAtMs=null,t.state.lastReasoningTypingStatus=null,await t.thread.startTyping(`Working...`)},async"reasoning.appended"(e,t,n){let r=firstNonEmptyLine(e.reasoningSoFar);if(r===void 0)return;let a=truncateTypingStatus(r),o=t.state.lastReasoningTypingStatus,s=o!=null&&a.startsWith(o)&&a.length>=o.length+4,c=Date.now(),l=t.state.lastReasoningTypingAtMs;if(!s&&l!=null){let e=c-l;if(e>=0&&e<5e3)return}await t.thread.startTyping(a),t.state.lastReasoningTypingAtMs=c,t.state.lastReasoningTypingStatus=a},async"actions.requested"(e,t,n){let r=t.state.pendingToolCallMessage;if(t.state.pendingToolCallMessage=null,r){await t.thread.startTyping(truncateTypingStatus(r));return}let a=e.actions.map(e=>e.kind===`tool-call`?e.toolName:e.kind);await t.thread.startTyping(truncateTypingStatus(`Running ${a.join(`, `)}...`))},async"message.completed"(e,t,n){if(e.finishReason===`tool-calls`){t.state.pendingToolCallMessage=e.message?firstNonEmptyLine(e.message)??null:null;return}t.state.pendingToolCallMessage=null,e.message&&await t.thread.post(e.message)},async"turn.failed"(e,r,i){let a=formatErrorHint(e),o=extractErrorId(e.details);await r.thread.post([`I hit an error while handling your request${a}.`,``,`Please try again, rephrase, or reach out if it keeps failing.`,...o?[``,`_Error id: \`${o}\`_`]:[]].join(`
|
|
3
3
|
`))},async"session.failed"(e,r){let i=formatErrorHint(e),a=extractErrorId(e.details);await r.thread.post([`This session couldn't recover from an error${i}.`,``,`Start a new thread to continue — I can't pick this one back up.`,...a?[``,`_Error id: \`${a}\`_`]:[]].join(`
|
|
4
4
|
`))},async"authorization.required"(e,t,n){let r=e.authorization?.displayName??formatConnectionDisplayName(e.name),i=t.state.triggeringUserId??null,a=e.authorization?.url;if(i&&a){let n=e.authorization?.userCode;try{await t.thread.postEphemeral(i,{blocks:buildAuthEphemeralBlocks({displayName:r,url:a,userCode:n}),text:n?`Sign in with ${r}: ${a} (code: ${n})`:`Sign in with ${r}: ${a}`});return}catch(t){log.error(`Slack auth ephemeral delivery failed`,{name:e.name,error:t})}}let o=buildAuthRequiredPublicText({displayName:r,hasUser:i!==null});try{let n=await t.thread.post(o);n.id&&(t.state.pendingAuthMessageTs={...t.state.pendingAuthMessageTs,[e.name]:n.id})}catch(t){log.error(`Slack auth public message delivery failed`,{name:e.name,error:t})}},async"authorization.completed"(e,t,n){let r=t.state.pendingAuthMessageTs??{},i=r[e.name];if(i===void 0)return;let a=buildAuthCompletedText({displayName:e.authorization?.displayName??formatConnectionDisplayName(e.name),outcome:e.outcome,reason:e.reason});try{await t.slack.request(`chat.update`,{channel:t.slack.channelId,ts:i,text:a})}catch(t){log.error(`Slack auth status edit failed`,{name:e.name,error:t})}let s={...r};delete s[e.name],t.state.pendingAuthMessageTs=s}};export{defaultEvents,defaultInputRequestedHandler,defaultOnAppMention,defaultOnDirectMessage,defaultSlackAuth};
|
|
@@ -109,8 +109,8 @@ export interface SlackChannelState {
|
|
|
109
109
|
pendingToolCallMessage?: string | null;
|
|
110
110
|
/**
|
|
111
111
|
* Last reasoning-derived typing indicator sent by the default
|
|
112
|
-
* `reasoning.appended` handler. Used to
|
|
113
|
-
*
|
|
112
|
+
* `reasoning.appended` handler. Used to surface substantial progressive
|
|
113
|
+
* extensions immediately while throttling smaller streamed deltas.
|
|
114
114
|
*/
|
|
115
115
|
lastReasoningTypingAtMs?: number | null;
|
|
116
116
|
lastReasoningTypingStatus?: string | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
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{WizardCancelledError}from"../step.js";import{getVercelAuthStatus}from"../vercel-project.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";import{join}from"node:path";var import_picocolors=__toESM(require_picocolors(),1);const AI_GATEWAY_ENV_KEY=`AI_GATEWAY_API_KEY`,ENV_FILE_NAME=`.env.local`,PROVIDER_QUESTION=`Which model provider do you want to use?`,CONNECTION_QUESTION=`How do you want to connect to AI Gateway?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${ENV_FILE_NAME} — 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://
|
|
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{WizardCancelledError}from"../step.js";import{getVercelAuthStatus}from"../vercel-project.js";import{runLinkFlow}from"./link.js";import{validateGatewayApiKey}from"../validate-gateway-key.js";import{join}from"node:path";var import_picocolors=__toESM(require_picocolors(),1);const AI_GATEWAY_ENV_KEY=`AI_GATEWAY_API_KEY`,ENV_FILE_NAME=`.env.local`,PROVIDER_QUESTION=`Which model provider do you want to use?`,CONNECTION_QUESTION=`How do you want to connect to AI Gateway?`,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE=`Using another model provider`,EXTERNAL_PROVIDER_INSTRUCTIONS=[`Set your provider's API key in ${ENV_FILE_NAME} — 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:`Connect via a project`,hint:`vercel link + env pull`};switch(e){case`authenticated`:return t;case`cli-missing`:return{...t,disabled:!0,disabledReason:`Vercel CLI not found, see /vc`,disabledReasonTone:`warning`};case`logged-out`:return{...t,disabled:!0,disabledReason:`Log in to Vercel first, see /login`,disabledReasonTone:`warning`};case`unavailable`:return{...t,disabled:!0,disabledReason:`Couldn't reach Vercel, check your connection`,disabledReasonTone:`warning`};default:return e}}async function runVercelFlow(e){let{appRoot:t,prompter:a,signal:o}=e,s={getVercelAuthStatus,runLinkFlow,appendEnv,validateGatewayApiKey,...e.deps},c,l;try{if(c=await a.select({message:PROVIDER_QUESTION,options:[{value:`gateway`,label:`Vercel AI Gateway`,hint:`one key, every model`},{value:`other`,label:`Something else`,hint:`use your own provider credentials`}],hintLayout:`stacked`}),c===`gateway`){let e=a.log.spinner?.(`Checking your Vercel login…`),n;try{n=await s.getVercelAuthStatus(t,{signal:o}),o?.throwIfAborted()}finally{e?.stop()}l=await a.select({message:CONNECTION_QUESTION,options:[projectConnectionOption(n),{value:`own-key`,label:`Use my own key`,hint:`paste an ${AI_GATEWAY_ENV_KEY}`}],hintLayout:`stacked`})}}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}if(c===`other`)return a.acknowledge?await a.acknowledge({message:EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,lines:EXTERNAL_PROVIDER_INSTRUCTIONS}):a.note(EXTERNAL_PROVIDER_INSTRUCTIONS.join(`
|
|
2
2
|
`),EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE),{kind:`done`,outcome:`external-provider`};if(l===`own-key`)for(;;){let e;try{e=await a.password({message:`Enter your ${AI_GATEWAY_ENV_KEY}`,validate:e=>e.trim().length===0?`API key cannot be empty.`:void 0})}catch(e){if(e instanceof WizardCancelledError)return{kind:`cancelled`};throw e}o?.throwIfAborted();let n=e.trim(),r=a.log.spinner?.(`Validating…`),i;try{i=await s.validateGatewayApiKey(n,o)}finally{r?.stop()}if(o?.throwIfAborted(),i.kind===`invalid`){a.log.error(`${i.message} Check the key and try again, or Esc to cancel.`);continue}return i.kind===`inconclusive`?a.log.warning(`Couldn't reach the gateway to validate (${i.message}). Saving the key anyway.`):a.log.success(`${import_picocolors.default.green(`✓`)} ${import_picocolors.default.bold(`Valid key`)}`),await s.appendEnv(join(t,ENV_FILE_NAME),{[AI_GATEWAY_ENV_KEY]:n},{force:!0}),o?.throwIfAborted(),a.log.success(`Saved ${AI_GATEWAY_ENV_KEY} to ${ENV_FILE_NAME}.`),{kind:`done`,credential:AI_GATEWAY_ENV_KEY}}else return await s.runLinkFlow({appRoot:t,prompter:a,signal:o,projectSelection:`create-or-link`})}export{CONNECTION_QUESTION,EXTERNAL_PROVIDER_INSTRUCTIONS,EXTERNAL_PROVIDER_INSTRUCTIONS_TITLE,PROVIDER_QUESTION,runVercelFlow};
|
|
@@ -57,7 +57,7 @@ export interface ScaffoldBaseProjectOptions {
|
|
|
57
57
|
aiPackageVersion?: string;
|
|
58
58
|
connectPackageVersion?: string;
|
|
59
59
|
zodPackageVersion?: string;
|
|
60
|
-
|
|
60
|
+
typescriptPackageVersion?: string;
|
|
61
61
|
/**
|
|
62
62
|
* Scaffold an inline provider `byok` block in `agent.ts` that reads the
|
|
63
63
|
* provider key from `process.env` instead of relying on the managed Vercel
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pinnedNodeEngineMajor}from"../../node-engine.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_AI_PACKAGE_VERSION=`7.0.0-beta.178`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.11.
|
|
1
|
+
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pinnedNodeEngineMajor}from"../../node-engine.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_AI_PACKAGE_VERSION=`7.0.0-beta.178`,DEFAULT_CONNECT_PACKAGE_VERSION=`0.2.2`,DEFAULT_ZOD_PACKAGE_VERSION=`4.4.3`,DEFAULT_EVE_PACKAGE_CONTRACT={version:`0.11.8`,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__",
|
|
@@ -15,7 +15,7 @@ export default defineAgent({
|
|
|
15
15
|
"build": "eve build",
|
|
16
16
|
"dev": "eve dev",
|
|
17
17
|
"start": "eve start",
|
|
18
|
-
"typecheck": "
|
|
18
|
+
"typecheck": "tsc"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@vercel/connect": "__EVE_INIT_CONNECT_VERSION__",
|
|
@@ -25,7 +25,7 @@ export default defineAgent({
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "__EVE_INIT_TYPES_NODE_VERSION__",
|
|
28
|
-
"
|
|
28
|
+
"typescript": "__EVE_INIT_TYPESCRIPT_VERSION__"
|
|
29
29
|
},
|
|
30
30
|
"overrides": {
|
|
31
31
|
"ai": "__EVE_INIT_AI_SDK_VERSION__"
|
|
@@ -90,4 +90,4 @@ export default defineAgent({
|
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
|
-
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(),...getPackageManagerStrategy(n).scaffoldFiles}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!t){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 a=resolve(e.targetDirectory??process.cwd(),e.projectName),o=e.projectName===`.`,c=e.overwriteExisting??!1,u=e.byokProvider??!1,d=e.packageManager??`pnpm`,f=resolveEvePackageContract(e.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine);if(o)await assertCanCreateInPlace(a,c);else if(await pathExists(a))throw Error(`Cannot create project because "${a}" already exists.`);let m={appName:basename(a),model:e.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`7.0.0-beta.178`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.4.3`),
|
|
93
|
+
`:BASE_AGENT_TEMPLATE,...SHARED_TEMPLATE_FILES,"package.json":packageJsonTemplate(),...getPackageManagerStrategy(n).scaffoldFiles}}async function assertCanCreateInPlace(e,t){if(!await pathExists(e))return;let r=(await readdir(e)).filter(e=>!ALLOWED_CREATE_IN_PLACE_ENTRIES.has(e));if(r.length>0&&!t){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 a=resolve(e.targetDirectory??process.cwd(),e.projectName),o=e.projectName===`.`,c=e.overwriteExisting??!1,u=e.byokProvider??!1,d=e.packageManager??`pnpm`,f=resolveEvePackageContract(e.evePackage),p=pinnedNodeEngineMajor(f.nodeEngine);if(o)await assertCanCreateInPlace(a,c);else if(await pathExists(a))throw Error(`Cannot create project because "${a}" already exists.`);let m={appName:basename(a),model:e.model,eveVersion:f.version,aiPackageVersion:resolveVersionToken(`aiPackageVersion`,e.aiPackageVersion??`7.0.0-beta.178`),connectPackageVersion:resolveVersionToken(`connectPackageVersion`,e.connectPackageVersion??`0.2.2`),zodPackageVersion:resolveVersionToken(`zodPackageVersion`,e.zodPackageVersion??`4.4.3`),typescriptPackageVersion:resolveVersionToken(`typescriptPackageVersion`,e.typescriptPackageVersion??`7.0.1-rc`),nodeTypesVersion:p,nodeEngine:p};await mkdir(a,{recursive:!0});for(let[t,i]of Object.entries(templateFiles(u,d))){let s=`${a}/${t}`,l=await pathExists(s);await writeTextFile(s,renderTemplate(i,m),{force:o&&c}),l&&await e.onOverwriteFile?.(s)}return a}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_CONTRACT,DEFAULT_ZOD_PACKAGE_VERSION,agentTemplateFiles,byokProviderEnvVar,formatEveDependencySpecifier,isEveProject,modelProviderSlug,resolveEvePackageContract,scaffoldBaseProject};
|
|
@@ -41,7 +41,7 @@ export declare const WEB_APP_TEMPLATE_PACKAGE_JSON: {
|
|
|
41
41
|
readonly build: "next build";
|
|
42
42
|
readonly dev: "next dev";
|
|
43
43
|
readonly start: "next start";
|
|
44
|
-
readonly typecheck: "
|
|
44
|
+
readonly typecheck: "tsc --noEmit -p tsconfig.json";
|
|
45
45
|
};
|
|
46
46
|
readonly dependencies: {
|
|
47
47
|
readonly "@radix-ui/react-use-controllable-state": "1.2.2";
|
|
@@ -76,5 +76,6 @@ export declare const WEB_APP_TEMPLATE_PACKAGE_JSON: {
|
|
|
76
76
|
readonly "@types/node": "catalog:";
|
|
77
77
|
readonly "@types/react": "catalog:";
|
|
78
78
|
readonly "@types/react-dom": "catalog:";
|
|
79
|
+
readonly typescript: "6.0.3";
|
|
79
80
|
};
|
|
80
81
|
};
|
|
@@ -4711,4 +4711,4 @@ export default config;
|
|
|
4711
4711
|
],
|
|
4712
4712
|
"exclude": ["node_modules"]
|
|
4713
4713
|
}
|
|
4714
|
-
`},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,dev:`next dev`,start:`next start`,typecheck:`
|
|
4714
|
+
`},WEB_APP_TEMPLATE_PACKAGE_JSON={scripts:{build:`next build`,dev:`next dev`,start:`next start`,typecheck:`tsc --noEmit -p tsconfig.json`},dependencies:{"@radix-ui/react-use-controllable-state":`1.2.2`,"@shikijs/core":`4.1.0`,"@shikijs/engine-javascript":`4.1.0`,"@shikijs/engine-oniguruma":`4.1.0`,"@streamdown/cjk":`1.0.3`,"@streamdown/code":`1.1.1`,"@streamdown/math":`1.0.2`,"@streamdown/mermaid":`1.0.2`,"@tailwindcss/postcss":`4.3.0`,ai:`catalog:`,"class-variance-authority":`0.7.1`,clsx:`2.1.1`,cmdk:`1.1.1`,eve:`workspace:*`,"lucide-react":`1.16.0`,motion:`12.40.0`,nanoid:`5.1.11`,next:`catalog:`,"radix-ui":`1.4.3`,react:`catalog:`,"react-dom":`catalog:`,shiki:`4.1.0`,streamdown:`catalog:`,"tailwind-merge":`3.6.0`,tailwindcss:`4.3.0`,"use-stick-to-bottom":`1.1.4`,zod:`catalog:`},devDependencies:{"@types/node":`catalog:`,"@types/react":`catalog:`,"@types/react-dom":`catalog:`,typescript:`6.0.3`}};export{WEB_APP_TEMPLATE_FILES,WEB_APP_TEMPLATE_PACKAGE_JSON};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pinnedNodeEngineMajor}from"../../node-engine.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{DEFAULT_EVE_PACKAGE_CONTRACT,resolveEvePackageContract}from"../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,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),`next`)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`7.0.0-beta.178`,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`,
|
|
1
|
+
import{getPackageManagerStrategy}from"../../primitives/pm/index.js";import{pinnedNodeEngineMajor}from"../../node-engine.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{DEFAULT_EVE_PACKAGE_CONTRACT,resolveEvePackageContract}from"../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,t){if(!await pathExists(e))return!1;let r=JSON.parse(await readFile(e,`utf8`));return isJsonObject(r)&&packageJsonHasDependency(r,t)}async function isNextJsProject(e){return hasPackageDependency(join(e,`package.json`),`next`)}async function ensurePackageDependency(e,t,r){return!await pathExists(e)||await readDependencyVersion(e,t)===r?[]:(await patchPackageJson(e,{dependencies:{[t]:r}}),[{path:e,dependencies:[t],devDependencies:[],scripts:[]}])}function resolveWebPackageVersions(e){return{evePackage:e?.evePackage??DEFAULT_EVE_PACKAGE_CONTRACT,aiPackageVersion:e?.aiPackageVersion??`7.0.0-beta.178`,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`,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,r){if(!await pathExists(e))return{mutations:[]};let o=resolveEvePackageContract(r.evePackage),s=pinnedNodeEngineMajor(o.nodeEngine),c={...WEB_APP_TEMPLATE_PACKAGE_JSON.dependencies,ai:resolveVersionToken(`aiPackageVersion`,r.aiPackageVersion),eve:formatEveDependencySpecifier(o.version),next:resolveVersionToken(`nextPackageVersion`,r.nextPackageVersion),react:resolveVersionToken(`reactPackageVersion`,r.reactPackageVersion),"react-dom":resolveVersionToken(`reactDomPackageVersion`,r.reactDomPackageVersion),streamdown:resolveVersionToken(`streamdownPackageVersion`,r.streamdownPackageVersion),zod:resolveVersionToken(`zodPackageVersion`,r.zodPackageVersion)},u={...WEB_APP_TEMPLATE_PACKAGE_JSON.devDependencies,"@types/node":s,"@types/react":resolveVersionToken(`typesReactPackageVersion`,r.typesReactPackageVersion),"@types/react-dom":resolveVersionToken(`typesReactDomPackageVersion`,r.typesReactDomPackageVersion),typescript:`6.0.3`},f=WEB_APP_TEMPLATE_PACKAGE_JSON.scripts,p=await patchPackageJson(e,{dependencies:c,devDependencies:u,scripts:f,nodeEngineRequirement:o.nodeEngine});return{mutations:[{path:e,dependencies:Object.keys(c),devDependencies:Object.keys(u),scripts:Object.keys(f)}],nodeEngineOverride:p.nodeEngineOverride}}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({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Returns a scaffold version value, resolving a build-stamp token at the point
|
|
3
3
|
* of need when the running code is unstamped. The published package is stamped
|
|
4
4
|
* by the build (`scripts/stamp-version-tokens.mjs`), so the fallback only ever
|
|
5
|
-
* fires in a dev tree —
|
|
5
|
+
* fires in a dev tree — tsc watch emits and tests running from `src` — where
|
|
6
6
|
* the live workspace catalog *is* the truth the stamp would have captured.
|
|
7
7
|
* Outside a dev tree an unstamped token still throws, because writing the
|
|
8
8
|
* literal token into a scaffolded package.json would break the generated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`
|
|
1
|
+
import{existsSync,readFileSync,realpathSync}from"node:fs";import{dirname,join}from"node:path";import{fileURLToPath}from"node:url";function versionToken(e){return`__${e}_VERSION__`}function bareToken(e){return`__${e}__`}const NODE_ENGINE_TOKEN=bareToken(`NODE_ENGINE`),TOKEN_SOURCES={[versionToken(`EVE_PACKAGE`)]:{kind:`eve-version`},[NODE_ENGINE_TOKEN]:{kind:`eve-node-engine`},[versionToken(`AI_SDK`)]:{kind:`catalog`,packageName:`ai`},[versionToken(`VERCEL_CONNECT`)]:{kind:`catalog`,packageName:`@vercel/connect`},[versionToken(`NEXT`)]:{kind:`catalog`,packageName:`next`},[versionToken(`REACT`)]:{kind:`catalog`,packageName:`react`},[versionToken(`REACT_DOM`)]:{kind:`catalog`,packageName:`react-dom`},[versionToken(`STREAMDOWN`)]:{kind:`catalog`,packageName:`streamdown`},[versionToken(`ZOD`)]:{kind:`catalog`,packageName:`zod`},[versionToken(`TYPESCRIPT`)]:{kind:`catalog`,packageName:`typescript`},[versionToken(`TYPES_REACT`)]:{kind:`catalog`,packageName:`@types/react`},[versionToken(`TYPES_REACT_DOM`)]:{kind:`catalog`,packageName:`@types/react-dom`}},resolvedTokens=new Map;function findEvePackageRoot(){let o=dirname(realpathSync(fileURLToPath(import.meta.url)));for(;;){let n=join(o,`package.json`);if(existsSync(n)&&JSON.parse(readFileSync(n,`utf8`)).name===`eve`)return o;let a=dirname(o);if(a===o)return;o=a}}function findWorkspaceManifest(t){let n=t;for(;;){let t=join(n,`pnpm-workspace.yaml`);if(existsSync(t))return t;let a=dirname(n);if(a===n)return;n=a}}function readCatalogVersion(e,n){let r=readFileSync(e,`utf8`).split(/\r?\n/),i=!1;for(let e of r){if(/^catalog:\s*$/.test(e)){i=!0;continue}if(!i)continue;if(/^\S/.test(e))break;let t=e.match(/^\s+(?:"([^"]+)"|([\w@/.-]+)):\s*"([^"]+)"/);if(t&&(t[1]??t[2])===n)return t[3]}}function resolveTokenFromDevTree(n){let r=TOKEN_SOURCES[n];if(r!==void 0)try{let n=findEvePackageRoot();if(n===void 0||!existsSync(join(n,`scripts/stamp-version-tokens.mjs`)))return;if(r.kind===`eve-version`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`));return typeof e.version==`string`?e.version:void 0}if(r.kind===`eve-node-engine`){let e=JSON.parse(readFileSync(join(n,`package.json`),`utf8`)).engines?.node;return typeof e==`string`?e:void 0}let a=findWorkspaceManifest(n);return a===void 0?void 0:readCatalogVersion(a,r.packageName)}catch{return}}function resolveVersionToken(e,t){if(!t.startsWith(`__`))return t;let n=resolvedTokens.get(t);if(n!==void 0)return n;let r=resolveTokenFromDevTree(t);if(r===void 0)throw Error(`Scaffold received unstamped version token (${e}=${t}). Build eve before using its dist entrypoint.`);return resolvedTokens.set(t,r),r}export{resolveVersionToken};
|
package/docs/channels/slack.mdx
CHANGED
|
@@ -78,7 +78,7 @@ export default slackChannel({
|
|
|
78
78
|
|
|
79
79
|
### Delivery
|
|
80
80
|
|
|
81
|
-
The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and tool status on `actions.requested`. Reasoning snippets
|
|
81
|
+
The default handlers reply in-thread and show progress. Typing indicators post automatically: `Thinking…` on inbound, `Working…` on `turn.started`, a truncated reasoning snippet on `reasoning.appended`, and tool status on `actions.requested`. Reasoning snippets build progressively: extensions of at least four characters appear immediately, while smaller streamed deltas use the five-second refresh interval to avoid one Slack request per token. Override `events["reasoning.appended"]` if you prefer generic wording. Override `onAppMention` or the `events` handlers to customize.
|
|
82
82
|
|
|
83
83
|
When a session starts without a `threadTs` (say, from a schedule or `receive(slack, ...)`), it anchors on the first agent post, and later posts and mentions resume that same session. Pass `initialMessage` with a `Card` to land a structured anchor first instead. `threadTs` and `initialMessage` are mutually exclusive.
|
|
84
84
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eve",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Filesystem-first framework for durable backend AI agents that run anywhere.",
|
|
6
6
|
"keywords": [
|
|
@@ -372,18 +372,18 @@
|
|
|
372
372
|
"build": "pnpm run check:bin-runtime-dependencies && pnpm run build:js && node ./scripts/copy-docs.mjs && node ./scripts/stamp-version-tokens.mjs",
|
|
373
373
|
"build:compiled": "node ./scripts/vendor-compiled.mjs",
|
|
374
374
|
"build:js": "pnpm run build:compiled && pnpm run clean && pnpm run build:types && node ./scripts/copy-compiled-assets.mjs && node ./scripts/build-rolldown.mjs && node ./scripts/copy-runtime-assets.mjs",
|
|
375
|
-
"build:types": "pnpm run build:compiled &&
|
|
375
|
+
"build:types": "pnpm run build:compiled && tsc -p tsconfig.build.json",
|
|
376
376
|
"check:bin-runtime-dependencies": "node ./scripts/check-bin-runtime-dependencies.mjs",
|
|
377
|
-
"dev": "pnpm run build:compiled && node ./scripts/copy-runtime-assets.mjs &&
|
|
377
|
+
"dev": "pnpm run build:compiled && node ./scripts/copy-runtime-assets.mjs && tsc -p tsconfig.dev.json --watch --preserveWatchOutput",
|
|
378
378
|
"test": "pnpm run test:unit && pnpm run test:integration",
|
|
379
379
|
"test:integration": "pnpm run build:js && vitest run --config vitest.integration.config.ts",
|
|
380
380
|
"test:scenario": "pnpm run build:compiled && vitest run --config vitest.scenario.config.ts",
|
|
381
381
|
"test:unit": "pnpm run build:compiled && vitest run --config vitest.unit.config.ts",
|
|
382
382
|
"test:watch": "pnpm run build:compiled && vitest --config vitest.unit.config.ts",
|
|
383
|
-
"typecheck": "pnpm run check:web-template && pnpm run build:compiled &&
|
|
383
|
+
"typecheck": "pnpm run check:web-template && pnpm run build:compiled && tsc -p tsconfig.json --noEmit",
|
|
384
384
|
"generate:web-template": "node src/setup/build.ts --write",
|
|
385
385
|
"check:web-template": "node src/setup/build.ts --check",
|
|
386
|
-
"test:tui": "pnpm run build:js &&
|
|
386
|
+
"test:tui": "pnpm run build:js && tsc -p tsconfig.tui.json --noEmit && node test/tui-client/run-all.mjs",
|
|
387
387
|
"test:vercel": "vitest run --config vitest.vercel.config.ts"
|
|
388
388
|
}
|
|
389
389
|
}
|