Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/vercel-honor-runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eve": patch
---

The Vercel sandbox backend now honors an author-supplied `runtime` (e.g. `vercel({ runtime: "python3.13" })`) instead of always forcing the `vercel/eve:latest` image. The default eve image is still used when no runtime is requested.
14 changes: 10 additions & 4 deletions packages/eve/src/execution/sandbox/bindings/vercel-create-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,17 @@ export async function createVercelEveImageSandbox(input: {
readonly createOptions: VercelSandboxCreateParams;
readonly sandboxModule: VercelModule;
}): Promise<VercelSandbox> {
const createOptions: VercelSandboxCreateParams = {
...input.createOptions,
__image: VERCEL_EVE_SANDBOX_IMAGE,
};
// The eve base image is only a default. `__image` takes precedence over
// `runtime` in the SDK, so forcing it unconditionally silently drops an
// author-supplied runtime — apply it only when no runtime was requested.
const createOptions: VercelSandboxCreateParams = hasAuthorRuntime(input.createOptions)
? input.createOptions
: { ...input.createOptions, __image: VERCEL_EVE_SANDBOX_IMAGE };
return await input.sandboxModule.Sandbox.create(createOptions);
}

function hasAuthorRuntime(createOptions: VercelSandboxCreateParams): boolean {
return (createOptions as VercelSandboxCreateParams & { runtime?: unknown }).runtime !== undefined;
}

const VERCEL_EVE_SANDBOX_IMAGE = "vercel/eve:latest";
25 changes: 25 additions & 0 deletions packages/eve/src/execution/sandbox/bindings/vercel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,31 @@ describe("createVercelSandbox", () => {
);
});

it("honors an author-supplied runtime instead of forcing the eve image", async () => {
const templateSandbox = createMockSandbox({ name: "template-key" });
const sandboxModule = {
Sandbox: {
create: vi.fn().mockResolvedValueOnce(templateSandbox),
get: vi.fn().mockResolvedValueOnce(null),
},
};

const backend = createVercelSandbox({
createOptions: { runtime: "python3.13" } as never,
loadSandboxModule: async () => sandboxModule as never,
});

await backend.prewarm({
runtimeContext: { appRoot: "/tmp/test-app-root" },
seedFiles: [],
templateKey: "template-key",
});

const createArgs = sandboxModule.Sandbox.create.mock.calls[0]?.[0];
expect(createArgs).toMatchObject({ runtime: "python3.13" });
expect(createArgs).not.toHaveProperty("__image");
});

it("passes resolved credentials to Vercel sandbox lookups instead of inferring scope", async () => {
const existingTemplate = createMockSandbox({
name: "template-key",
Expand Down
Loading