From 0c669b389b7bb235c8092e0e6882e13f13620ebe Mon Sep 17 00:00:00 2001 From: CTO Agent Date: Sun, 29 Mar 2026 00:37:45 +0000 Subject: [PATCH] feat: replace snapshotId with name-based sandbox persistence With Vercel's new sandbox names feature, sandbox state persists automatically by name. This removes explicit snapshot-taking and snapshotId passing throughout the tasks codebase. - Remove snapshot() calls from codingAgentTask, updatePRTask, setupSandboxTask - Remove snapshotId from schemas, callbacks, and return types - Use Sandbox.get({ name }) instead of Sandbox.get({ sandboxId }) - snapshotAndPersist now only persists github_repo metadata - Update all related tests Co-Authored-By: Paperclip --- src/recoup/updateAccountSnapshot.ts | 21 +++++------- .../__tests__/getOrCreateSandbox.test.ts | 6 ++-- .../notifyCodingAgentCallback.test.ts | 1 - .../__tests__/snapshotAndPersist.test.ts | 29 +++++++++-------- src/sandboxes/ensureGithubRepo.ts | 3 +- src/sandboxes/getOrCreateSandbox.ts | 2 +- src/sandboxes/notifyCodingAgentCallback.ts | 1 - src/sandboxes/snapshotAndPersist.ts | 30 ++++++----------- src/schemas/codingAgentSchema.ts | 1 - src/schemas/sandboxSchema.ts | 8 ----- src/schemas/updatePRSchema.ts | 1 - src/tasks/__tests__/codingAgentTask.test.ts | 4 +-- src/tasks/__tests__/setupSandboxTask.test.ts | 8 ++--- src/tasks/__tests__/updatePRTask.test.ts | 32 +++++-------------- src/tasks/codingAgentTask.ts | 8 ++--- src/tasks/runSandboxCommandTask.ts | 14 ++------ src/tasks/setupSandboxTask.ts | 14 +++----- src/tasks/updatePRTask.ts | 21 ++++-------- 18 files changed, 66 insertions(+), 138 deletions(-) diff --git a/src/recoup/updateAccountSnapshot.ts b/src/recoup/updateAccountSnapshot.ts index 8be278a..054cebb 100644 --- a/src/recoup/updateAccountSnapshot.ts +++ b/src/recoup/updateAccountSnapshot.ts @@ -5,24 +5,21 @@ import { NEW_API_BASE_URL, RECOUP_API_KEY } from "../consts"; * Updates sandbox config for an account via PATCH /api/sandboxes. * * @param accountId - The account ID to update - * @param snapshotId - Optional snapshot ID to set + * @param _snapshotId - Deprecated, unused. Kept for call-site compat during migration. * @param githubRepo - Optional GitHub repo URL to persist - * @returns The updated snapshot data or undefined on error + * @returns The updated data or undefined on error */ export async function updateAccountSnapshot( accountId: string, - snapshotId?: string, + _snapshotId?: string, githubRepo?: string -): Promise<{ success: boolean; snapshotId: string } | undefined> { +): Promise<{ success: boolean } | undefined> { const url = `${NEW_API_BASE_URL}/api/sandboxes`; - logger.log("Updating account snapshot", { accountId, snapshotId, githubRepo, url }); + logger.log("Updating account sandbox metadata", { accountId, githubRepo, url }); try { const body: Record = { account_id: accountId }; - if (snapshotId) { - body.snapshotId = snapshotId; - } if (githubRepo) { body.github_repo = githubRepo; } @@ -38,7 +35,7 @@ export async function updateAccountSnapshot( if (!response.ok) { const errorText = await response.text(); - logger.error("Failed to update account snapshot", { + logger.error("Failed to update account sandbox metadata", { status: response.status, statusText: response.statusText, error: errorText, @@ -48,16 +45,14 @@ export async function updateAccountSnapshot( const data = await response.json(); - logger.log("Account snapshot updated successfully", { + logger.log("Account sandbox metadata updated successfully", { accountId, - snapshotId: data.snapshotId, }); return data; } catch (error) { - logger.error("Error updating account snapshot", { + logger.error("Error updating account sandbox metadata", { accountId, - snapshotId, error: error instanceof Error ? error.message : String(error), }); return undefined; diff --git a/src/sandboxes/__tests__/getOrCreateSandbox.test.ts b/src/sandboxes/__tests__/getOrCreateSandbox.test.ts index eabcd2a..c2dab3a 100644 --- a/src/sandboxes/__tests__/getOrCreateSandbox.test.ts +++ b/src/sandboxes/__tests__/getOrCreateSandbox.test.ts @@ -8,7 +8,7 @@ vi.mock("@trigger.dev/sdk/v3", () => ({ vi.mock("@vercel/sandbox", () => ({ Sandbox: { get: vi.fn().mockResolvedValue({ - sandboxId: "sbx_123", + name: "sbx_123", status: "running", }), }, @@ -53,7 +53,7 @@ describe("getOrCreateSandbox", () => { await getOrCreateSandbox("acc_1"); expect(Sandbox.get).toHaveBeenCalledWith( - expect.objectContaining({ sandboxId: "sbx_123" }), + expect.objectContaining({ name: "sbx_123" }), ); }); @@ -62,7 +62,7 @@ describe("getOrCreateSandbox", () => { expect(result.sandboxId).toBe("sbx_123"); expect(result.sandbox).toEqual( - expect.objectContaining({ sandboxId: "sbx_123" }), + expect.objectContaining({ name: "sbx_123" }), ); }); diff --git a/src/sandboxes/__tests__/notifyCodingAgentCallback.test.ts b/src/sandboxes/__tests__/notifyCodingAgentCallback.test.ts index aff093c..9e711a0 100644 --- a/src/sandboxes/__tests__/notifyCodingAgentCallback.test.ts +++ b/src/sandboxes/__tests__/notifyCodingAgentCallback.test.ts @@ -23,7 +23,6 @@ describe("notifyCodingAgentCallback", () => { threadId: "slack:C123:123", status: "pr_created", branch: "agent/fix-123", - snapshotId: "snap_abc", prs: [{ repo: "recoupable/api", number: 42, url: "url", baseBranch: "test" }], }); diff --git a/src/sandboxes/__tests__/snapshotAndPersist.test.ts b/src/sandboxes/__tests__/snapshotAndPersist.test.ts index 8876697..5ced26a 100644 --- a/src/sandboxes/__tests__/snapshotAndPersist.test.ts +++ b/src/sandboxes/__tests__/snapshotAndPersist.test.ts @@ -5,13 +5,11 @@ vi.mock("@trigger.dev/sdk/v3", () => ({ })); vi.mock("../../recoup/updateAccountSnapshot", () => ({ - updateAccountSnapshot: vi.fn().mockResolvedValue({ success: true, snapshotId: "snap_123" }), + updateAccountSnapshot: vi.fn().mockResolvedValue({ success: true }), })); const { snapshotAndPersist } = await import("../snapshotAndPersist"); -const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000; - function createMockSandbox() { return { snapshot: vi.fn().mockResolvedValue({ @@ -26,26 +24,31 @@ beforeEach(() => { }); describe("snapshotAndPersist", () => { - it("passes 7-day expiration to sandbox.snapshot()", async () => { + it("persists github repo without snapshotId", async () => { const sandbox = createMockSandbox(); - await snapshotAndPersist(sandbox, "acc_456"); - expect(sandbox.snapshot).toHaveBeenCalledWith({ expiration: SEVEN_DAYS_MS }); + const { updateAccountSnapshot } = await import("../../recoup/updateAccountSnapshot"); + await snapshotAndPersist(sandbox, "acc_456", "https://github.com/org/repo"); + expect(updateAccountSnapshot).toHaveBeenCalledWith( + "acc_456", + undefined, + "https://github.com/org/repo", + ); }); - it("returns the snapshot result", async () => { + it("does not take a sandbox snapshot", async () => { const sandbox = createMockSandbox(); - const result = await snapshotAndPersist(sandbox, "acc_456"); - expect(result.snapshotId).toBe("snap_123"); + await snapshotAndPersist(sandbox, "acc_456"); + expect(sandbox.snapshot).not.toHaveBeenCalled(); }); - it("persists snapshot with github repo when provided", async () => { + it("persists without snapshotId when no github repo", async () => { const sandbox = createMockSandbox(); const { updateAccountSnapshot } = await import("../../recoup/updateAccountSnapshot"); - await snapshotAndPersist(sandbox, "acc_456", "https://github.com/org/repo"); + await snapshotAndPersist(sandbox, "acc_456"); expect(updateAccountSnapshot).toHaveBeenCalledWith( "acc_456", - "snap_123", - "https://github.com/org/repo", + undefined, + undefined, ); }); }); diff --git a/src/sandboxes/ensureGithubRepo.ts b/src/sandboxes/ensureGithubRepo.ts index 73b9f27..82f26c0 100644 --- a/src/sandboxes/ensureGithubRepo.ts +++ b/src/sandboxes/ensureGithubRepo.ts @@ -54,8 +54,7 @@ export async function ensureGithubRepo( // Persist the repo URL via PATCH /api/sandboxes logger.log("Persisting GitHub repo URL", { accountId, repoUrl }); - const snapshotId = sandboxesInfo?.snapshotId ?? undefined; - await updateAccountSnapshot(accountId, snapshotId, repoUrl); + await updateAccountSnapshot(accountId, undefined, repoUrl); githubRepo = repoUrl; } diff --git a/src/sandboxes/getOrCreateSandbox.ts b/src/sandboxes/getOrCreateSandbox.ts index 8eb716b..d90f438 100644 --- a/src/sandboxes/getOrCreateSandbox.ts +++ b/src/sandboxes/getOrCreateSandbox.ts @@ -28,7 +28,7 @@ export async function getOrCreateSandbox( } const sandbox = await Sandbox.get({ - sandboxId: created.sandboxId, + name: created.sandboxId, token, teamId, projectId, diff --git a/src/sandboxes/notifyCodingAgentCallback.ts b/src/sandboxes/notifyCodingAgentCallback.ts index b676780..7c6ee16 100644 --- a/src/sandboxes/notifyCodingAgentCallback.ts +++ b/src/sandboxes/notifyCodingAgentCallback.ts @@ -4,7 +4,6 @@ interface CallbackPayload { threadId: string; status: "pr_created" | "no_changes" | "failed" | "updated"; branch?: string; - snapshotId?: string; prs?: { repo: string; number: number; url: string; baseBranch: string }[]; message?: string; stdout?: string; diff --git a/src/sandboxes/snapshotAndPersist.ts b/src/sandboxes/snapshotAndPersist.ts index 56b36b3..4ae8bf8 100644 --- a/src/sandboxes/snapshotAndPersist.ts +++ b/src/sandboxes/snapshotAndPersist.ts @@ -3,34 +3,24 @@ import { logger } from "@trigger.dev/sdk/v3"; import { updateAccountSnapshot } from "../recoup/updateAccountSnapshot"; /** - * Takes a sandbox snapshot and persists the snapshotId (and optional - * github_repo) via the API. + * Persists sandbox metadata (github_repo) via the API. * - * @param sandbox - The Vercel Sandbox instance + * With the Vercel Sandbox names feature, sandbox state persists automatically + * by name — explicit snapshots are no longer required for sandbox resumption. + * + * @param _sandbox - The Vercel Sandbox instance (unused with name-based persistence) * @param accountId - The account ID to update - * @param githubRepo - Optional GitHub repo URL to persist alongside the snapshot - * @returns The snapshot result with snapshotId and expiresAt + * @param githubRepo - Optional GitHub repo URL to persist */ export async function snapshotAndPersist( - sandbox: Sandbox, + _sandbox: Sandbox, accountId: string, githubRepo?: string ) { - const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000; - - logger.log("Taking sandbox snapshot"); - const snapshotResult = await sandbox.snapshot({ expiration: SEVEN_DAYS_MS }); - - logger.log("Snapshot created", { - snapshotId: snapshotResult.snapshotId, - expiresAt: snapshotResult.expiresAt, - }); - - logger.log("Persisting snapshot ID", { + logger.log("Persisting sandbox metadata (names replace snapshots)", { accountId, - snapshotId: snapshotResult.snapshotId, + githubRepo, }); - await updateAccountSnapshot(accountId, snapshotResult.snapshotId, githubRepo); - return snapshotResult; + await updateAccountSnapshot(accountId, undefined, githubRepo); } diff --git a/src/schemas/codingAgentSchema.ts b/src/schemas/codingAgentSchema.ts index 150289f..a2206eb 100644 --- a/src/schemas/codingAgentSchema.ts +++ b/src/schemas/codingAgentSchema.ts @@ -9,7 +9,6 @@ export type CodingAgentPayload = z.infer; export interface CodingAgentResult { branch: string; - snapshotId: string; prs: { repo: string; number: number; url: string; baseBranch: string }[]; stdout: string; stderr: string; diff --git a/src/schemas/sandboxSchema.ts b/src/schemas/sandboxSchema.ts index 943eeea..dc246b1 100644 --- a/src/schemas/sandboxSchema.ts +++ b/src/schemas/sandboxSchema.ts @@ -12,18 +12,10 @@ export type RunSandboxCommandPayload = z.infer< typeof runSandboxCommandPayloadSchema >; -export const snapshotSchema = z.object({ - id: z.string(), - expiresAt: z.string(), -}); - -export type Snapshot = z.infer; - export const sandboxResultSchema = z.object({ stdout: z.string(), stderr: z.string(), exitCode: z.number(), - snapshot: snapshotSchema, }); export type SandboxResult = z.infer; diff --git a/src/schemas/updatePRSchema.ts b/src/schemas/updatePRSchema.ts index 50484f9..e07856f 100644 --- a/src/schemas/updatePRSchema.ts +++ b/src/schemas/updatePRSchema.ts @@ -2,7 +2,6 @@ import { z } from "zod"; export const updatePRPayloadSchema = z.object({ feedback: z.string().min(1, "feedback is required"), - snapshotId: z.string().min(1, "snapshotId is required"), branch: z.string().min(1, "branch is required"), repo: z.string().min(1, "repo is required"), callbackThreadId: z.string().min(1, "callbackThreadId is required"), diff --git a/src/tasks/__tests__/codingAgentTask.test.ts b/src/tasks/__tests__/codingAgentTask.test.ts index c2f991a..e86ddc1 100644 --- a/src/tasks/__tests__/codingAgentTask.test.ts +++ b/src/tasks/__tests__/codingAgentTask.test.ts @@ -12,7 +12,6 @@ vi.mock("@trigger.dev/sdk/v3", () => ({ })); const mockSandboxStop = vi.fn(); -const mockSandboxSnapshot = vi.fn().mockResolvedValue({ snapshotId: "snap_123" }); const mockGetOrCreateSandbox = vi.fn(); vi.mock("../../sandboxes/getOrCreateSandbox", () => ({ @@ -60,9 +59,8 @@ beforeEach(() => { mockGetOrCreateSandbox.mockResolvedValue({ sandboxId: "sbx-123", sandbox: { - sandboxId: "sbx-123", + name: "sbx-123", stop: mockSandboxStop, - snapshot: mockSandboxSnapshot, }, }); }); diff --git a/src/tasks/__tests__/setupSandboxTask.test.ts b/src/tasks/__tests__/setupSandboxTask.test.ts index f9baed5..b3dfd8b 100644 --- a/src/tasks/__tests__/setupSandboxTask.test.ts +++ b/src/tasks/__tests__/setupSandboxTask.test.ts @@ -29,10 +29,7 @@ vi.mock("../../sandboxes/provisionSandbox", () => ({ })); vi.mock("../../sandboxes/snapshotAndPersist", () => ({ - snapshotAndPersist: vi.fn().mockResolvedValue({ - snapshotId: "snap_abc", - expiresAt: new Date("2026-03-12"), - }), + snapshotAndPersist: vi.fn().mockResolvedValue(undefined), })); const { setupSandboxTask } = await import("../setupSandboxTask"); @@ -79,12 +76,11 @@ describe("setupSandboxTask", () => { ); }); - it("returns snapshotId and githubRepo on success", async () => { + it("returns githubRepo on success", async () => { const result = await run({ accountId: "acc_1" }); expect(result).toEqual({ githubRepo: "https://github.com/org/repo", - snapshotId: "snap_abc", }); }); diff --git a/src/tasks/__tests__/updatePRTask.test.ts b/src/tasks/__tests__/updatePRTask.test.ts index bef8f84..672f24b 100644 --- a/src/tasks/__tests__/updatePRTask.test.ts +++ b/src/tasks/__tests__/updatePRTask.test.ts @@ -12,13 +12,12 @@ vi.mock("@trigger.dev/sdk/v3", () => ({ }, })); -const mockSandboxCreate = vi.fn(); +const mockSandboxGet = vi.fn(); const mockSandboxStop = vi.fn(); -const mockSandboxSnapshot = vi.fn().mockResolvedValue({ snapshotId: "snap_new" }); vi.mock("@vercel/sandbox", () => ({ Sandbox: { - create: (...args: unknown[]) => mockSandboxCreate(...args), + get: (...args: unknown[]) => mockSandboxGet(...args), }, })); @@ -57,28 +56,26 @@ await import("../updatePRTask"); beforeEach(() => { vi.clearAllMocks(); - mockSandboxCreate.mockResolvedValue({ - sandboxId: "sbx-456", + mockSandboxGet.mockResolvedValue({ + name: CODING_AGENT_ACCOUNT_ID, stop: mockSandboxStop, - snapshot: mockSandboxSnapshot, }); }); describe("updatePRTask", () => { const basePayload = { feedback: "Make the button blue instead", - snapshotId: "snap_old", branch: "agent/fix-bug-123", repo: "recoupable/api", callbackThreadId: "slack:C123:123.456", }; - it("resumes sandbox from snapshot", async () => { + it("resumes sandbox by name", async () => { await mockRun(basePayload); - expect(mockSandboxCreate).toHaveBeenCalledWith( + expect(mockSandboxGet).toHaveBeenCalledWith( expect.objectContaining({ - source: { type: "snapshot", snapshotId: "snap_old" }, + name: CODING_AGENT_ACCOUNT_ID, }), ); }); @@ -112,7 +109,7 @@ describe("updatePRTask", () => { ); }); - it("notifies callback with updated status and new snapshot", async () => { + it("notifies callback with updated status", async () => { const { notifyCodingAgentCallback } = await import("../../sandboxes/notifyCodingAgentCallback"); await mockRun(basePayload); @@ -121,7 +118,6 @@ describe("updatePRTask", () => { expect.objectContaining({ threadId: "slack:C123:123.456", status: "updated", - snapshotId: "snap_new", stdout: "done", stderr: "", }), @@ -141,18 +137,6 @@ describe("updatePRTask", () => { expect(configureGitAuth).toHaveBeenCalledOnce(); }); - it("creates sandbox with correct timeout param", async () => { - await mockRun(basePayload); - - expect(mockSandboxCreate).toHaveBeenCalledWith( - expect.objectContaining({ - timeout: 30 * 60 * 1000, - }), - ); - const callArgs = mockSandboxCreate.mock.calls[0][0]; - expect(callArgs).not.toHaveProperty("timeoutMs"); - }); - it("passes sandbox env to both agent calls", async () => { const { runClaudeCodeAgent } = await import("../../sandboxes/runClaudeCodeAgent"); const { getSandboxEnv } = await import("../../sandboxes/getSandboxEnv"); diff --git a/src/tasks/codingAgentTask.ts b/src/tasks/codingAgentTask.ts index 18e1f92..4c8367c 100644 --- a/src/tasks/codingAgentTask.ts +++ b/src/tasks/codingAgentTask.ts @@ -61,14 +61,10 @@ export const codingAgentTask = schemaTask({ const prs = await pushAndCreatePRsViaAgent(sandbox, { prompt, branch, agentStdout: agentResult.stdout }); - logStep("Taking snapshot"); - const { snapshotId } = await sandbox.snapshot(); - const callbackPayload = { threadId: callbackThreadId, status: (prs.length > 0 ? "pr_created" : "no_changes") as "pr_created" | "no_changes", branch, - snapshotId, prs, stdout: agentResult.stdout, stderr: agentResult.stderr, @@ -78,9 +74,9 @@ export const codingAgentTask = schemaTask({ metadata.set("currentStep", "Complete"); - return { branch, snapshotId, prs, stdout: agentResult.stdout, stderr: agentResult.stderr }; + return { branch, prs, stdout: agentResult.stdout, stderr: agentResult.stderr }; } finally { - logStep("Stopping sandbox", false, { sandboxId: sandbox.sandboxId }); + logStep("Stopping sandbox", false, { sandboxId: sandbox.name }); await sandbox.stop(); } }, diff --git a/src/tasks/runSandboxCommandTask.ts b/src/tasks/runSandboxCommandTask.ts index 857df73..55e534e 100644 --- a/src/tasks/runSandboxCommandTask.ts +++ b/src/tasks/runSandboxCommandTask.ts @@ -20,7 +20,7 @@ import { /** * Background task that connects to an existing Vercel Sandbox, ensures OpenClaw * is installed with AI Gateway, runs a command with arguments, captures - * output, takes a snapshot, and updates the account's snapshot ID. + * output, persists metadata, and pushes to GitHub. */ export const runSandboxCommandTask = schemaTask({ id: "run-sandbox-command", @@ -42,7 +42,7 @@ export const runSandboxCommandTask = schemaTask({ accountId, }); - const sandbox = await Sandbox.get({ sandboxId, token, teamId, projectId }); + const sandbox = await Sandbox.get({ name: sandboxId, token, teamId, projectId }); logStep("Connected to sandbox"); @@ -91,20 +91,12 @@ export const runSandboxCommandTask = schemaTask({ logStep("Pushing to GitHub"); await pushSandboxToGithub(sandbox); - const snapshotResult = await snapshotAndPersist( - sandbox, - accountId, - githubRepo ?? undefined - ); + await snapshotAndPersist(sandbox, accountId, githubRepo ?? undefined); const result: SandboxResult = { stdout, stderr, exitCode, - snapshot: { - id: snapshotResult.snapshotId, - expiresAt: snapshotResult.expiresAt.toISOString(), - }, }; logStep("Sandbox command completed successfully"); diff --git a/src/tasks/setupSandboxTask.ts b/src/tasks/setupSandboxTask.ts index 71e0d65..d08f718 100644 --- a/src/tasks/setupSandboxTask.ts +++ b/src/tasks/setupSandboxTask.ts @@ -29,25 +29,19 @@ export const setupSandboxTask = schemaTask({ const { githubRepo } = await provisionSandbox(sandbox, sandboxId, accountId); logStep("Provisioning complete", false); - logStep("Taking snapshot"); - const snapshotResult = await snapshotAndPersist( - sandbox, - accountId, - githubRepo, - ); + logStep("Persisting sandbox metadata"); + await snapshotAndPersist(sandbox, accountId, githubRepo); logStep("Sandbox setup complete", true, { - sandboxId: sandbox.sandboxId, + sandboxId: sandbox.name, githubRepo: githubRepo ?? null, - snapshotId: snapshotResult.snapshotId, }); return { githubRepo: githubRepo ?? null, - snapshotId: snapshotResult.snapshotId, }; } finally { - logStep("Stopping sandbox", false, { sandboxId: sandbox.sandboxId }); + logStep("Stopping sandbox", false, { sandboxId: sandbox.name }); await sandbox.stop(); } }, diff --git a/src/tasks/updatePRTask.ts b/src/tasks/updatePRTask.ts index 8aa1464..d1fbe8c 100644 --- a/src/tasks/updatePRTask.ts +++ b/src/tasks/updatePRTask.ts @@ -11,7 +11,7 @@ import { CODING_AGENT_ACCOUNT_ID } from "../consts"; import { PROGRESS_PROMPT_PREFIX, PROGRESS_PROMPT_SUFFIX } from "./promptPrefixes"; /** - * Background task that resumes a sandbox from a snapshot, applies feedback + * Background task that resumes a named sandbox, applies feedback * via the Claude Code agent, and pushes the updates to the existing PR branch. */ export const updatePRTask = schemaTask({ @@ -22,20 +22,19 @@ export const updatePRTask = schemaTask({ maxAttempts: 0, }, run: async (payload) => { - const { feedback, snapshotId, branch, repo, callbackThreadId } = payload; + const { feedback, branch, repo, callbackThreadId } = payload; const { token, teamId, projectId } = getVercelSandboxCredentials(); - logStep("Resuming sandbox from snapshot"); + logStep("Resuming sandbox by name"); - const sandbox = await Sandbox.create({ + const sandbox = await Sandbox.get({ + name: CODING_AGENT_ACCOUNT_ID, token, teamId, projectId, - source: { type: "snapshot", snapshotId }, - timeout: 30 * 60 * 1000, }); - logStep("Sandbox resumed", false, { sandboxId: sandbox.sandboxId, snapshotId }); + logStep("Sandbox resumed", false, { sandboxId: sandbox.name }); try { await configureGitAuth(sandbox); @@ -66,13 +65,9 @@ export const updatePRTask = schemaTask({ ].join("\n"), }); - logStep("Taking new snapshot"); - const newSnapshot = await sandbox.snapshot(); - const callbackPayload = { threadId: callbackThreadId, status: "updated" as const, - snapshotId: newSnapshot.snapshotId, stdout: agentResult.stdout, stderr: agentResult.stderr, }; @@ -80,10 +75,8 @@ export const updatePRTask = schemaTask({ await notifyCodingAgentCallback(callbackPayload); metadata.set("currentStep", "Complete"); - - return { snapshotId: newSnapshot.snapshotId }; } finally { - logStep("Stopping sandbox", false, { sandboxId: sandbox.sandboxId }); + logStep("Stopping sandbox", false, { sandboxId: sandbox.name }); await sandbox.stop(); } },