Skip to content

Commit 14fa8a5

Browse files
authored
perf: show project progress before sandbox preparation (#267)
## Summary - publishes the durable project-created event immediately after the database materialization commits - removes a redundant Python `print('ready')` call after workspace creation has already started and verified Daytona - reduces first-run app-builder latency without changing sandbox recovery or readiness guarantees ## Decision `ensureWorkspaceDirectory` remains the real readiness boundary. It is a sandbox operation backed by `ensureSandbox`, so a second synthetic code execution adds a control-plane and toolbox round trip but proves no additional invariant. ## Verification - `pnpm lint` - `pnpm typecheck` - `pnpm turbo build --force` - `pnpm deadcode` - `pnpm architecture:check` - `pnpm turbo skills:build` A fresh ordinary-user production app-builder run will measure project-visible latency after merge/deploy.
1 parent 7d0bc46 commit 14fa8a5

4 files changed

Lines changed: 8 additions & 20 deletions

File tree

apps/agent-worker/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ the Daytona adapter normalizes the provider's structured `503` response to an in
105105
then the lifecycle verifies the active-run lease and canonical volume mount before replacing the
106106
stopped container on the same isolated workspace-volume subpath. This preserves user files while
107107
avoiding an indefinite dependency on one unhealthy runner.
108+
Project materialization publishes its durable project-created event immediately after the database
109+
commit, before waiting on Daytona workspace preparation. The workspace directory operation is
110+
itself the sandbox readiness boundary; app-builder preparation does not issue a second synthetic
111+
code-execution probe after that operation succeeds.
108112
Provider output-length termination is nonterminal: the Workflow checkpoints the partial model turn,
109113
adds an internal continuation message, and resumes from that durable state. A tool-free turn completes
110114
the run only when the model reports an actual stop; content filtering, provider errors, and invalid

apps/agent-worker/src/durable-objects/agent-run-app-builder.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ import {
2929
projectLocalSourceDir,
3030
} from "./project-sandbox-package-runtime";
3131

32-
export type ProjectSandboxStub = CodeRuntimeContext["sandbox"];
33-
export type AgentRunLogger = ReturnType<typeof createLogger>;
32+
type ProjectSandboxStub = CodeRuntimeContext["sandbox"];
33+
type AgentRunLogger = ReturnType<typeof createLogger>;
3434

3535
interface AgentRunAppBuilderEnv extends AnalyticsBindings {
3636
HYPERDRIVE: Hyperdrive;
@@ -491,21 +491,6 @@ function repoImportError(message: string): APIError {
491491
});
492492
}
493493

494-
export async function warmSandbox(
495-
sandbox: ProjectSandboxStub,
496-
logger: AgentRunLogger,
497-
): Promise<void> {
498-
const result = await sandbox.runCode({
499-
code: "print('ready')",
500-
language: "python",
501-
});
502-
const stdout = result.stdout;
503-
logger.info("sandbox_warmed", {
504-
success: result.success,
505-
stdoutBytes: stdout.length,
506-
});
507-
}
508-
509494
async function startExpoDevServer(
510495
sandbox: ProjectSandboxStub,
511496
logger: AgentRunLogger,

apps/agent-worker/src/durable-objects/agent-run-path.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { createLogger } from "@cheatcode/observability";
22
import type { CodeRuntimeContext, WorkspaceResolver } from "@cheatcode/sandbox-contracts";
33
import type { UIMessageChunk } from "ai";
4-
import { runAppBuilder, warmSandbox } from "./agent-run-app-builder";
4+
import { runAppBuilder } from "./agent-run-app-builder";
55
import type { AgentRunEnv } from "./agent-run-env";
66
import type { StartRunInput } from "./agent-run-schemas";
77

@@ -43,7 +43,6 @@ export async function prepareAppBuilderRun(
4343
options.input.projectMode = appBuilderMode;
4444
await options.workspaceResolver();
4545
const boundOptions = { ...options, input: requireProjectBinding(options.input) };
46-
await warmSandbox(boundOptions.sandbox, boundOptions.logger);
4746
if (boundOptions.isCanceled()) {
4847
return { options: boundOptions, usesManagedPreview: false, waitsForGeneratedPreview: false };
4948
}

apps/agent-worker/src/durable-objects/agent-run-workspace.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ async function resolveWorkspace(input: WorkspaceResolverInput): Promise<Workspac
5656
const project = result.project;
5757
input.input.projectId = project.id;
5858
input.input.workspaceSlug = project.workspaceSlug;
59-
await ensureWorkspaceDirectory(input, project.workspaceSlug);
6059
if (result.kind === "created") {
6160
await input.append({
6261
data: { projectId: project.id, projectName: project.name, v: 1 },
6362
type: "data-project-created",
6463
});
6564
}
65+
await ensureWorkspaceDirectory(input, project.workspaceSlug);
6666
input.logger.info("agent_workspace_materialized", {
6767
projectId: project.id,
6868
workspaceSlug: project.workspaceSlug,

0 commit comments

Comments
 (0)