feat(eve): convert standalone agents to workspaces - #3349
OwenKephart wants to merge 2 commits into
Conversation
Signed-off-by: owenkephart <owen.kephart@vercel.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
||
| const oldRoot = join(root, "agents", oldName); | ||
| await mkdir(oldRoot, { recursive: true }); | ||
| await moveIfPresent(root, oldName, "agent"); |
There was a problem hiding this comment.
[P1] Preserve flat standalone agents
findEveProjectContext also classifies flat roots containing agent.ts, instructions.md, tools/, and similar entries as standalone. This path only renames a root agent/ directory, so converting a valid flat project leaves the original files at the workspace root. Once agents/<new> exists, project resolution selects the workspace and the original agent disappears from dev, build, and deploy. Detect the flat layout and move its complete agent surface into agents/${oldName}, or reject it before the first write.
| const oldRoot = join(root, "agents", oldName); | ||
| await mkdir(oldRoot, { recursive: true }); | ||
| await moveIfPresent(root, oldName, "agent"); | ||
| await moveIfPresent(root, oldName, "evals"); |
There was a problem hiding this comment.
[P1] Preserve app-scoped local state
The original agent's app root changes from root to agents/${oldName}, but its .eve/ state stays at root. The converted agent therefore starts with a new .eve/.workflow-data store and can no longer resume its existing local sessions; traces, logs, eval artifacts, and dev runtime generations are stranded too. Migrate the app-scoped state needed under the new app root, or stop with explicit guidance instead of reporting a complete conversion.
| `Cannot convert this standalone eve project because ${tsconfigPath} is not a generated eve TypeScript configuration.`, | ||
| ); | ||
| } | ||
| const packageUpdated = packageSource |
There was a problem hiding this comment.
[P1] Make package imports workspace-safe
These two literal replacements leave any additional import target rooted in ./agent or ./evals pointing at a removed path. They also make the root #* map resolve to the original member for every nested agent, so a later #tools/foo import from agents/research resolves to agents/${oldName}/agent/tools/foo. Please provide member-correct import resolution, or reject package configurations that cannot be migrated safely before moving files.
| "Cannot convert this standalone eve project because agents/ already exists. Complete the migration manually to avoid overwriting an existing workspace.", | ||
| ); | ||
| } | ||
| if (entries.has("vercel.ts") || entries.has("vercel.json")) { |
There was a problem hiding this comment.
[P1] Preserve the original agent's public route
For a plain standalone project, this conversion changes the root build into an inferred workspace build. The old agent then moves from /eve/v1/* to /${oldName}/eve/v1/*, breaking existing clients and webhooks on the next deployment. The preflight only blocks authored service graphs, and the confirmation mentions filesystem moves but not this API break. Preserve a compatibility route for the original agent, or block automatic conversion when that compatibility cannot be guaranteed.
| const GENERATED_WEB_CHAT_NEXT_CONFIG = | ||
| 'import type { NextConfig } from "next";\nimport { withEve } from "eve/next";\n\nconst nextConfig: NextConfig = {};\n\nexport default withEve(nextConfig);\n'; | ||
|
|
||
| interface StandaloneMigrationOptions { |
There was a problem hiding this comment.
[P1] Reject init options this path ignores
The caller passes the full InitCommandOptions, but this narrowed type drops agents and channelWebNextjs. As a result, eve init research --agents=a,b --yes converts the project and creates only research, while --channel-web-nextjs converts without adding Web Chat. The existing project and workspace paths reject these incompatible combinations. Include them in migration preflight and fail before confirmation or mutation, rather than silently changing the requested operation.
b358bae to
71ea0a9
Compare
Signed-off-by: owenkephart <owen.kephart@vercel.com>
71ea0a9 to
33ca973
Compare
| } | ||
| const choice = await dependencies.createPrompter().select<"convert" | "cancel">({ | ||
| message: "Convert this eve project to an agents workspace?", | ||
| description: `The existing agent will move to agents/${oldName}/ and ${name} will be added.`, |
There was a problem hiding this comment.
| description: `The existing agent will move to agents/${oldName}/ and ${name} will be added.`, | |
| description: | |
| `The existing agent will move to agents/${oldName}/ and ${name} will be added. ` + | |
| `Its public route changes from /eve/v1/* to /eve/agents/${oldName}/eve/v1/*, ` + | |
| `so update any external clients, webhooks, or channel callbacks that target the old path.`, |
Confirmation prompt for converting a standalone eve project to a workspace omits that the existing agent's public HTTP route changes from /eve/v1/* to /eve/agents/<oldName>/eve/v1/*, so users can't make an informed decision and existing clients/webhooks silently break.
| await rename(join(root, path), join(root, "agents", oldName, path)); | ||
| } catch (error) { | ||
| if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; | ||
| } |
| import { prepareWebChatMigration, type WebChatMigration } from "./web-chat.js"; | ||
| import type { InitCliLogger } from "../init-agent-workspace.js"; | ||
| import { hasInteractiveTerminal } from "../preconditions.js"; | ||
|
|
Summary
Standalone eve projects currently reject
eve init <name>, so authors cannot grow a single-agent project into a workspace through the CLI. This adds an explicit conversion flow that moves the existing agent and evals intoagents/<project-name>/and adds the requested agent, with confirmation by default and--yesfor non-interactive use. Generated Web Chat projects retain their root app and are rewired to the moved agent; custom Next.js apps and Vercel service graphs stop before writing and explain the manual migration boundary.Validation
pnpm fmtpnpm lint(passes with pre-existing workspace warnings)pnpm --filter eve exec tsc --noEmit --pretty falsepnpm --filter eve exec vitest run --config vitest.integration.config.ts src/cli/commands/migrate/standalone.integration.test.ts src/cli/commands/init.integration.test.ts(72 passed)pnpm --filter eve exec vitest run --config vitest.unit.config.ts src/cli/run.test.ts(67 passed)pnpm guard:invariantspnpm docs:checkgit diff --checkChecklist
CONTRIBUTING.mdevepackagegit commit --signoff)