From d6aae751a011b6624b68f66dfe9cac666f6c268d Mon Sep 17 00:00:00 2001 From: serhiizghama Date: Thu, 25 Jun 2026 03:40:18 +0700 Subject: [PATCH 1/2] fix(vercel): honor author-supplied runtime instead of forcing eve image Signed-off-by: serhiizghama --- .changeset/vercel-honor-runtime.md | 5 +++++ .../sandbox/bindings/vercel-create-sdk.ts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .changeset/vercel-honor-runtime.md diff --git a/.changeset/vercel-honor-runtime.md b/.changeset/vercel-honor-runtime.md new file mode 100644 index 000000000..51d4fd9a0 --- /dev/null +++ b/.changeset/vercel-honor-runtime.md @@ -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. diff --git a/packages/eve/src/execution/sandbox/bindings/vercel-create-sdk.ts b/packages/eve/src/execution/sandbox/bindings/vercel-create-sdk.ts index 80a6933b2..d8c6edc71 100644 --- a/packages/eve/src/execution/sandbox/bindings/vercel-create-sdk.ts +++ b/packages/eve/src/execution/sandbox/bindings/vercel-create-sdk.ts @@ -24,11 +24,17 @@ export async function createVercelEveImageSandbox(input: { readonly createOptions: VercelSandboxCreateParams; readonly sandboxModule: VercelModule; }): Promise { - 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"; From 7a98362416316010a45a1b04ca08e5b9d376da5f Mon Sep 17 00:00:00 2001 From: serhiizghama Date: Thu, 25 Jun 2026 03:40:23 +0700 Subject: [PATCH 2/2] test(vercel): cover runtime forwarding through the eve image binding Signed-off-by: serhiizghama --- .../execution/sandbox/bindings/vercel.test.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/packages/eve/src/execution/sandbox/bindings/vercel.test.ts b/packages/eve/src/execution/sandbox/bindings/vercel.test.ts index 9404c096d..041aca220 100644 --- a/packages/eve/src/execution/sandbox/bindings/vercel.test.ts +++ b/packages/eve/src/execution/sandbox/bindings/vercel.test.ts @@ -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",