mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
fix(eve): store local Workflow data under .eve (#806)
Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"eve": patch
|
||||
---
|
||||
|
||||
Store local Workflow World data under `.eve/.workflow-data` for both `eve dev` and `eve start`.
|
||||
@@ -50,7 +50,6 @@ Thumbs.db
|
||||
# Vercel/Temp build output
|
||||
.output/
|
||||
.eve/
|
||||
.workflow-data/
|
||||
|
||||
# Geist
|
||||
.source
|
||||
|
||||
@@ -9,7 +9,6 @@ node_modules
|
||||
.output
|
||||
.turbo
|
||||
.vercel
|
||||
.workflow-data
|
||||
.workflow-vitest
|
||||
coverage
|
||||
dist
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -37,7 +37,6 @@ yarn-error.log*
|
||||
.eve
|
||||
.swc
|
||||
.output
|
||||
.workflow-data
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
.turbo
|
||||
.agents
|
||||
.github
|
||||
.workflow-data
|
||||
dist
|
||||
research
|
||||
node_modules
|
||||
|
||||
@@ -8,7 +8,6 @@ dist
|
||||
|
||||
# eve runtime data
|
||||
.eve
|
||||
.workflow-data
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
@@ -3,4 +3,3 @@ node_modules
|
||||
tsconfig.tsbuildinfo
|
||||
.eve
|
||||
.output
|
||||
.workflow-data
|
||||
|
||||
@@ -15,7 +15,7 @@ Work nests in three levels:
|
||||
|
||||
Every turn runs as a durable workflow, built on the open-source [Workflow SDK](https://workflow-sdk.dev/) (Vercel Workflow when you deploy on Vercel). eve checkpoints progress and serializes durable state at each step boundary. Your code runs inside a managed step, so tools, the sandbox, and subagents feel synchronous even though the session underneath them is durable.
|
||||
|
||||
The Workflow SDK is not inherently tied to Vercel. In local development and in a self-deployed `eve start` process, eve uses the SDK's local world by default; that world persists workflow runs on disk under `.workflow-data` and dispatches through the same Nitro-hosted workflow routes. On Vercel, the same workflow code runs against Vercel Workflow instead, which adds platform features such as latest production deployment routing and dashboard run metadata.
|
||||
The Workflow SDK is not inherently tied to Vercel. In local development and in a self-deployed `eve start` process, eve uses the SDK's local world by default; that world persists workflow runs on disk under `.eve/.workflow-data` and dispatches through the same Nitro-hosted workflow routes. On Vercel, the same workflow code runs against Vercel Workflow instead, which adds platform features such as latest production deployment routing and dashboard run metadata.
|
||||
|
||||
When a Vercel production deployment changes, the next model turn in an existing session uses that deployment's current instructions, model, and tools. The durable session keeps its conversation history and authored state, so identity-based channels such as Telegram private chats and Twilio phone-number conversations adopt agent updates without requiring a new session.
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ Eve writes the standard Nitro output under `.output/` instead of Vercel Build Ou
|
||||
|
||||
Self-deployed agents should make the Vercel-specific choices explicit:
|
||||
|
||||
- Let the Workflow SDK use its default local world, which stores workflow state under `.workflow-data`, configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. The Workflow SDK rejects worlds with an incompatible runtime protocol during initialization.
|
||||
- Let the Workflow SDK use its default local world, which stores workflow state under `.eve/.workflow-data`; configure your host so that directory is on persistent storage, or select another world with `experimental.workflow.world` in the root `agent.ts`. When you select a custom world, install a world package built against the same `@workflow/*` line as your eve release (currently the `5.0.0-beta` line). The npm `latest` tag may lag, so pin the version explicitly, for example `pnpm add @workflow/world-postgres@5.0.0-beta.x`. The Workflow SDK rejects worlds with an incompatible runtime protocol during initialization.
|
||||
- If you put a reverse proxy or ingress in front of eve, forward **both** `/eve/` and `/.well-known/workflow/`. The workflow world delivers run callbacks to `/.well-known/workflow/v1/flow`; a proxy restricted to `/eve/` lets sessions start but silently stalls runs forever, because the callbacks never reach eve.
|
||||
- Install the AI SDK package for your provider, then use a direct provider model object and `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` when you want no Gateway dependency.
|
||||
- Use `AI_GATEWAY_API_KEY` if you still want Gateway routing from a non-Vercel host.
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -2,7 +2,6 @@ node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -473,7 +473,7 @@ describe("discoverAgent (memory)", () => {
|
||||
|
||||
it("silently ignores generated runtime directories", async () => {
|
||||
const project = buildMemoryAgentProject({
|
||||
agentDirectories: [".eve", ".next", ".output", ".vercel", ".workflow-data", "node_modules"],
|
||||
agentDirectories: [".eve", ".next", ".output", ".vercel", "node_modules"],
|
||||
agentFiles: {
|
||||
"instructions.md": "You are a precise assistant.",
|
||||
},
|
||||
|
||||
@@ -25,7 +25,6 @@ const GENERATED_AGENT_DIRECTORY_NAMES = new Set<string>([
|
||||
".next",
|
||||
".output",
|
||||
".vercel",
|
||||
".workflow-data",
|
||||
"node_modules",
|
||||
]);
|
||||
|
||||
|
||||
@@ -22,19 +22,25 @@ describe("createWorkflowWorldPluginSource", () => {
|
||||
expect(source).toContain(
|
||||
'validateWorkflowWorld({ packageName: "@acme/eve-world", world: workflowWorld });',
|
||||
);
|
||||
expect(source).not.toContain("resolveLocalWorkflowWorldDataDirectory");
|
||||
expect(source).toContain("setWorld(workflowWorld);");
|
||||
expect(source).toContain("await getWorld();");
|
||||
expect(source).toContain("await workflowWorld.start?.();");
|
||||
});
|
||||
|
||||
it("selects vendored local and Vercel world packages with Workflow's selector", () => {
|
||||
expect(
|
||||
createWorkflowWorldPluginSource({
|
||||
compiledArtifactsBootstrapPath: "/app/.eve/compile/bootstrap.mjs",
|
||||
configuredWorld: undefined,
|
||||
defaultWorld: "local",
|
||||
}),
|
||||
).toContain("/compiled/@workflow/world-local/index.js");
|
||||
it("configures the vendored local World with eve's app-local data resolver", () => {
|
||||
const source = createWorkflowWorldPluginSource({
|
||||
compiledArtifactsBootstrapPath: "/app/.eve/compile/bootstrap.mjs",
|
||||
configuredWorld: undefined,
|
||||
defaultWorld: "local",
|
||||
});
|
||||
|
||||
expect(source).toContain("/compiled/@workflow/world-local/index.js");
|
||||
expect(source).toContain("resolveLocalWorkflowWorldDataDirectory(process.cwd())");
|
||||
expect(source).not.toContain("createWorldFromModule(workflowWorldModule)");
|
||||
});
|
||||
|
||||
it("selects the vendored Vercel World with Workflow's selector", () => {
|
||||
expect(
|
||||
createWorkflowWorldPluginSource({
|
||||
compiledArtifactsBootstrapPath: "/app/.eve/compile/bootstrap.mjs",
|
||||
|
||||
@@ -260,15 +260,36 @@ export function createWorkflowWorldPluginSource(input: {
|
||||
const workflowWorldValidationImportSpecifier = resolvePackageSourceFilePath(
|
||||
"src/internal/workflow/validate-world.ts",
|
||||
);
|
||||
const localWorldDataDirectoryResolverImportSpecifier =
|
||||
packageName === "@workflow/world-local"
|
||||
? resolvePackageSourceFilePath("src/internal/workflow/local-world-data-directory.ts")
|
||||
: undefined;
|
||||
const createWorkflowWorldSource =
|
||||
localWorldDataDirectoryResolverImportSpecifier === undefined
|
||||
? "const workflowWorld = await createWorldFromModule(workflowWorldModule);"
|
||||
: [
|
||||
"const workflowWorld = await workflowWorldModule.createWorld({",
|
||||
" dataDir: resolveLocalWorkflowWorldDataDirectory(process.cwd()),",
|
||||
"});",
|
||||
].join("\n");
|
||||
const workflowRuntimeImports =
|
||||
localWorldDataDirectoryResolverImportSpecifier === undefined
|
||||
? "createWorldFromModule, getWorld, setWorld"
|
||||
: "getWorld, setWorld";
|
||||
|
||||
return [
|
||||
"// Generated by eve. Do not edit by hand.",
|
||||
`import ${stringifyEsmImportSpecifier(input.compiledArtifactsBootstrapPath)};`,
|
||||
`import * as workflowWorldModule from ${stringifyEsmImportSpecifier(importSpecifier)};`,
|
||||
`import { createWorldFromModule, getWorld, setWorld } from ${stringifyEsmImportSpecifier(workflowRuntimeImportSpecifier)};`,
|
||||
...(localWorldDataDirectoryResolverImportSpecifier === undefined
|
||||
? []
|
||||
: [
|
||||
`import { resolveLocalWorkflowWorldDataDirectory } from ${stringifyEsmImportSpecifier(localWorldDataDirectoryResolverImportSpecifier)};`,
|
||||
]),
|
||||
`import { ${workflowRuntimeImports} } from ${stringifyEsmImportSpecifier(workflowRuntimeImportSpecifier)};`,
|
||||
`import { validateWorkflowWorld } from ${stringifyEsmImportSpecifier(workflowWorldValidationImportSpecifier)};`,
|
||||
"",
|
||||
"const workflowWorld = await createWorldFromModule(workflowWorldModule);",
|
||||
createWorkflowWorldSource,
|
||||
`validateWorkflowWorld({ packageName: ${JSON.stringify(input.configuredWorld)}, world: workflowWorld });`,
|
||||
"setWorld(workflowWorld);",
|
||||
"await getWorld();",
|
||||
|
||||
@@ -14,6 +14,7 @@ import { getCompiledRuntimeAgentBundle } from "#runtime/sessions/compiled-agent-
|
||||
import { createRuntimeSession, withRuntimeSession } from "#runtime/sessions/runtime-session.js";
|
||||
import { createDevelopmentNitroArtifactsConfig } from "#internal/nitro/host/artifacts-config.js";
|
||||
import { publishDevelopmentGeneration } from "#internal/nitro/development-generation.js";
|
||||
import { resolveLocalWorkflowWorldDataDirectory } from "#internal/workflow/local-world-data-directory.js";
|
||||
import {
|
||||
activateDevelopmentRuntimeArtifactsSnapshot,
|
||||
activateDevelopmentRuntimeArtifactsSnapshotTransaction,
|
||||
@@ -499,7 +500,7 @@ describe("development runtime artifact snapshots", () => {
|
||||
sourceRoot: appRoot,
|
||||
},
|
||||
});
|
||||
const runsDirectory = join(appRoot, ".workflow-data", "default", "runs");
|
||||
const runsDirectory = join(resolveLocalWorkflowWorldDataDirectory(appRoot), "default", "runs");
|
||||
await mkdir(runsDirectory, { recursive: true });
|
||||
await writeFile(
|
||||
join(runsDirectory, "active-turn.json"),
|
||||
|
||||
@@ -24,7 +24,6 @@ const SNAPSHOT_SKIP_NAMES = new Set([
|
||||
".output",
|
||||
".turbo",
|
||||
".vercel",
|
||||
".workflow-data",
|
||||
"node_modules",
|
||||
]);
|
||||
const SNAPSHOT_APP_ROOT_SKIP_NAMES = new Set(["build", "dist"]);
|
||||
|
||||
@@ -32,7 +32,6 @@ const WATCHER_IGNORED_DIRECTORY_NAMES = new Set([
|
||||
".output",
|
||||
".turbo",
|
||||
".vercel",
|
||||
".workflow-data",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
|
||||
@@ -56,7 +56,6 @@ const IGNORED_INPUT_DIRECTORIES = new Set([
|
||||
".nuxt",
|
||||
".output",
|
||||
".vercel",
|
||||
".workflow-data",
|
||||
".workflow-vitest",
|
||||
".well-known",
|
||||
".svelte-kit",
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
getDevelopmentWorkflowGeneration,
|
||||
withDevelopmentWorkflowGeneration,
|
||||
} from "#internal/workflow/development-generation-context.js";
|
||||
import { LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH } from "#internal/workflow/local-world-data-directory.js";
|
||||
import {
|
||||
DEVELOPMENT_WORKER_APP_ROOT_ENV,
|
||||
DEVELOPMENT_WORKFLOW_DELIVERY_HEADER,
|
||||
@@ -46,7 +47,7 @@ export class MissingDevelopmentGenerationError extends Error {
|
||||
constructor(generationId: string, cause?: unknown) {
|
||||
super(
|
||||
`Workflow run references missing development generation "${generationId}". ` +
|
||||
`Remove ".workflow-data" to discard the app's active local Workflow runs.`,
|
||||
`Remove "${LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH}" to discard the app's active local Workflow runs.`,
|
||||
cause === undefined ? undefined : { cause },
|
||||
);
|
||||
this.name = "MissingDevelopmentGenerationError";
|
||||
|
||||
@@ -16,6 +16,10 @@ import {
|
||||
createParentDevelopmentWorkflowWorld,
|
||||
type ParentDevelopmentWorkflowWorld,
|
||||
} from "#internal/workflow/development-world-server.js";
|
||||
import {
|
||||
LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH,
|
||||
resolveLocalWorkflowWorldDataDirectory,
|
||||
} from "#internal/workflow/local-world-data-directory.js";
|
||||
import {
|
||||
DEVELOPMENT_WORKER_APP_ROOT_ENV,
|
||||
DEVELOPMENT_WORKFLOW_DELIVERY_HEADER,
|
||||
@@ -41,14 +45,16 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("parent development Workflow World", () => {
|
||||
it("stores local Workflow state under the app's top-level .workflow-data directory", async () => {
|
||||
it("stores local Workflow state under .eve/.workflow-data", async () => {
|
||||
const appRoot = await createScratchDirectory("eve-parent-workflow-data-dir-");
|
||||
const world = createWorld({ activeGenerationId: () => "generation-a", appRoot });
|
||||
|
||||
try {
|
||||
await world.start();
|
||||
await expect(access(join(appRoot, ".workflow-data", "version.txt"))).resolves.toBeUndefined();
|
||||
await expect(access(join(appRoot, ".eve", "workflow-data"))).rejects.toMatchObject({
|
||||
await expect(
|
||||
access(join(resolveLocalWorkflowWorldDataDirectory(appRoot), "version.txt")),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(access(join(appRoot, ".workflow-data"))).rejects.toMatchObject({
|
||||
code: "ENOENT",
|
||||
});
|
||||
} finally {
|
||||
@@ -153,7 +159,9 @@ describe("parent development Workflow World", () => {
|
||||
// the failure is reported explicitly.
|
||||
await expect(restarted.start()).resolves.toBeUndefined();
|
||||
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining("generation-a"));
|
||||
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining(".workflow-data"));
|
||||
expect(errorSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining(LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH),
|
||||
);
|
||||
} finally {
|
||||
errorSpy.mockRestore();
|
||||
await restarted.close();
|
||||
|
||||
@@ -5,6 +5,10 @@ import type { ValidQueueName, World } from "#compiled/@workflow/world/index.js";
|
||||
import { createWorld } from "#compiled/@workflow/world-local/index.js";
|
||||
import { turnWorkflowReference } from "#execution/workflow-runtime.js";
|
||||
import { deriveEveWorkflowQueuePrefix } from "#internal/workflow/queue-namespace.js";
|
||||
import {
|
||||
LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH,
|
||||
resolveLocalWorkflowWorldDataDirectory,
|
||||
} from "#internal/workflow/local-world-data-directory.js";
|
||||
import {
|
||||
decodeDevelopmentWorldValue,
|
||||
encodeDevelopmentWorldValue,
|
||||
@@ -74,7 +78,7 @@ class LocalParentDevelopmentWorkflowWorld implements ParentDevelopmentWorkflowWo
|
||||
this.#resolveActiveGenerationId = input.resolveActiveGenerationId;
|
||||
this.#transportSecret = input.transportSecret;
|
||||
this.#world = createWorld({
|
||||
dataDir: join(input.appRoot, ".workflow-data"),
|
||||
dataDir: resolveLocalWorkflowWorldDataDirectory(input.appRoot),
|
||||
recoverActiveRuns: false,
|
||||
});
|
||||
}
|
||||
@@ -96,7 +100,7 @@ class LocalParentDevelopmentWorkflowWorld implements ParentDevelopmentWorkflowWo
|
||||
console.error(
|
||||
`[eve:dev] ${String(missingGenerationIds.size)} active local Workflow run(s) reference development generations that no longer exist ` +
|
||||
`(${[...missingGenerationIds].join(", ")}). Their deliveries are quarantined; ` +
|
||||
`remove ".workflow-data" to discard the app's active local Workflow runs.`,
|
||||
`remove "${LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH}" to discard the app's active local Workflow runs.`,
|
||||
);
|
||||
}
|
||||
await this.#world.start?.();
|
||||
@@ -144,7 +148,7 @@ class LocalParentDevelopmentWorkflowWorld implements ParentDevelopmentWorkflowWo
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to read the app's active local Workflow runs. ` +
|
||||
`Remove ".workflow-data" to discard them.`,
|
||||
`Remove "${LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH}" to discard them.`,
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
@@ -301,7 +305,7 @@ async function reenqueueActiveDevelopmentRuns(input: {
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to read the app's active local Workflow runs. ` +
|
||||
`Remove ".workflow-data" to discard them.`,
|
||||
`Remove "${LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH}" to discard them.`,
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { join } from "node:path";
|
||||
|
||||
export const LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH = ".eve/.workflow-data";
|
||||
|
||||
export function resolveLocalWorkflowWorldDataDirectory(appRoot: string): string {
|
||||
return join(appRoot, LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH);
|
||||
}
|
||||
@@ -113,7 +113,6 @@ const GITIGNORE_TEMPLATE = `node_modules
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.output
|
||||
.nitro
|
||||
dist
|
||||
|
||||
@@ -245,7 +245,6 @@ const SHARED_TEMPLATE_FILES: Record<string, string> = {
|
||||
.env*
|
||||
.eve
|
||||
.vercel
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
@@ -258,7 +257,6 @@ dist
|
||||
".vercelignore": `node_modules
|
||||
.env*
|
||||
.eve
|
||||
.workflow-data
|
||||
.next
|
||||
.output
|
||||
.nitro
|
||||
|
||||
@@ -821,7 +821,7 @@ describe("scaffoldBaseProject", () => {
|
||||
// artifacts and a bare .env must be excluded here or a source deploy
|
||||
// ships them (and `.eve` alone can blow the upload size limit).
|
||||
const vercelignore = await readFile(join(projectRoot, ".vercelignore"), "utf8");
|
||||
for (const entry of [".env*", ".eve", ".workflow-data", ".output", ".nitro", "dist"]) {
|
||||
for (const entry of [".env*", ".eve", ".output", ".nitro", "dist"]) {
|
||||
expect(vercelignore.split("\n")).toContain(entry);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { spawn, type ChildProcess } from "node:child_process";
|
||||
import { mkdir, realpath, writeFile } from "node:fs/promises";
|
||||
import { access, mkdir, realpath, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
@@ -9,6 +9,7 @@ import { runCli } from "../../src/cli/run.js";
|
||||
import { resolveInstalledPackageInfo } from "../../src/internal/application/package.js";
|
||||
import { useScenarioApp } from "../../src/internal/testing/scenario-app.js";
|
||||
import { WEATHER_AGENT_DESCRIPTOR } from "../../src/internal/testing/scenario-apps/weather-agent.js";
|
||||
import { resolveLocalWorkflowWorldDataDirectory } from "../../src/internal/workflow/local-world-data-directory.js";
|
||||
import {
|
||||
EVE_CONTINUE_SESSION_ROUTE_PATTERN,
|
||||
EVE_CREATE_SESSION_ROUTE_PATH,
|
||||
@@ -396,7 +397,7 @@ describe("runCli", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("starts an existing built app and serves the health route", async () => {
|
||||
it("starts an existing built app with local Workflow data under .eve", async () => {
|
||||
const { buildApplication } = await import("../../src/internal/nitro/host.js");
|
||||
const appRoot = await createMinimalAppRoot("eve-cli-start-health-");
|
||||
|
||||
@@ -413,6 +414,12 @@ describe("runCli", () => {
|
||||
expect(response.status).toBe(200);
|
||||
expect(responseJson).toMatchObject({ ok: true, status: "ready" });
|
||||
expect(server.stdout()).toContain("[START] server listening at");
|
||||
await expect(
|
||||
access(join(resolveLocalWorkflowWorldDataDirectory(appRoot), "version.txt")),
|
||||
).resolves.toBeUndefined();
|
||||
await expect(access(join(appRoot, ".workflow-data"))).rejects.toMatchObject({
|
||||
code: "ENOENT",
|
||||
});
|
||||
} finally {
|
||||
await server.stop();
|
||||
}
|
||||
|
||||
@@ -8,11 +8,7 @@ import { fileURLToPath } from "node:url";
|
||||
*/
|
||||
export default async function clearWorkflowCache(): Promise<void> {
|
||||
const packageRoot = fileURLToPath(new URL("../../", import.meta.url));
|
||||
const cacheDirectories = [
|
||||
join(packageRoot, ".workflow-data"),
|
||||
join(packageRoot, ".workflow-vitest"),
|
||||
join(packageRoot, ".eve"),
|
||||
];
|
||||
const cacheDirectories = [join(packageRoot, ".workflow-vitest"), join(packageRoot, ".eve")];
|
||||
|
||||
await Promise.all(
|
||||
cacheDirectories.map((directory) => rm(directory, { force: true, recursive: true })),
|
||||
|
||||
@@ -12,7 +12,6 @@ const IGNORED_DIRECTORY_NAMES = new Set([
|
||||
".output",
|
||||
".swc",
|
||||
".turbo",
|
||||
".workflow-data",
|
||||
"coverage",
|
||||
"dist",
|
||||
"node_modules",
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
} from "#internal/workflow-bundle/builder-support.js";
|
||||
import { detectWorkflowPatterns } from "#internal/workflow-bundle/workflow-builders.js";
|
||||
import { installEveWorkflowQueueNamespace } from "#internal/workflow/queue-namespace.js";
|
||||
import { resolveLocalWorkflowWorldDataDirectory } from "#internal/workflow/local-world-data-directory.js";
|
||||
|
||||
export const WORKFLOW_TEST_AGENT_NAME = "eve-test";
|
||||
|
||||
@@ -48,7 +49,7 @@ export default async function setupWorkflowTests(): Promise<void> {
|
||||
tsconfigPath: join(packageRoot, "tsconfig.json"),
|
||||
workingDir: packageRoot,
|
||||
});
|
||||
await initDataDir(join(packageRoot, ".workflow-data"));
|
||||
await initDataDir(resolveLocalWorkflowWorldDataDirectory(packageRoot));
|
||||
}
|
||||
|
||||
async function discoverWorkflowEntries(): Promise<WorkflowBundleDiscoveredEntries> {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
deriveEveWorkflowQueuePrefix,
|
||||
installEveWorkflowQueueNamespace,
|
||||
} from "#internal/workflow/queue-namespace.js";
|
||||
import { resolveLocalWorkflowWorldDataDirectory } from "#internal/workflow/local-world-data-directory.js";
|
||||
import { setWorld } from "#internal/workflow/runtime.js";
|
||||
|
||||
import { WORKFLOW_TEST_AGENT_NAME } from "./workflow-global-setup.js";
|
||||
@@ -19,7 +20,7 @@ const outDir = resolveWorkflowTestOutputDirectory(packageRoot);
|
||||
const poolId = process.env.VITEST_POOL_ID ?? "0";
|
||||
installEveWorkflowQueueNamespace(WORKFLOW_TEST_AGENT_NAME);
|
||||
const world = createLocalWorld({
|
||||
dataDir: join(packageRoot, ".workflow-data", `vitest-${poolId}`),
|
||||
dataDir: join(resolveLocalWorkflowWorldDataDirectory(packageRoot), `vitest-${poolId}`),
|
||||
tag: `vitest-${poolId}`,
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**", ".output/**", ".vercel/output/**"]
|
||||
@@ -35,7 +34,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": ["dist/**/*.d.ts", "dist/**/*.d.ts.map"]
|
||||
@@ -54,7 +52,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
@@ -69,7 +66,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
@@ -84,7 +80,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
@@ -99,7 +94,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
@@ -114,7 +108,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
@@ -139,7 +132,6 @@
|
||||
"!.output/**",
|
||||
"!.svelte-kit/**",
|
||||
"!.turbo/**",
|
||||
"!.workflow-data/**",
|
||||
"!node_modules/**"
|
||||
],
|
||||
"outputs": []
|
||||
|
||||
Reference in New Issue
Block a user