diff --git a/package-lock.json b/package-lock.json index aaa3264..a558807 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codebase-cli", - "version": "2.0.0-pre.79", + "version": "2.0.0-pre.80", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codebase-cli", - "version": "2.0.0-pre.79", + "version": "2.0.0-pre.80", "license": "MIT", "dependencies": { "@earendil-works/pi-agent-core": "0.74.0", diff --git a/package.json b/package.json index 56c78b9..d321480 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codebase-cli", - "version": "2.0.0-pre.79", + "version": "2.0.0-pre.80", "description": "Codebase CLI — a TypeScript coding agent on the pi-mono runtime. OAuth-aware, any LLM provider, single install.", "keywords": [ "ai", diff --git a/src/projects/cli.test.ts b/src/projects/cli.test.ts index bcf5d16..631c38c 100644 --- a/src/projects/cli.test.ts +++ b/src/projects/cli.test.ts @@ -100,6 +100,7 @@ describe("runProjectSubcommand", () => { expect(result.code).toBe(0); expect(result.stdout.join("\n")).toContain("alias: codebase web-build"); + expect(result.stdout.join("\n")).toContain("default: 1800"); }); it("prints pull help without treating the flag as a project id", async () => { @@ -267,6 +268,39 @@ describe("runProjectSubcommand", () => { expect(result.stdout.join("\n")).toContain("preview: https://codebase.design/preview/proj-1"); }); + it("keeps the default wait alive beyond ten minutes", async () => { + let now = 0; + const nowSpy = vi.spyOn(Date, "now").mockImplementation(() => now); + const client = fakeClient({ + status: { sessionId: "sess-1", status: "building", projectId: "proj-1" }, + preview: { ok: true, previewPath: "/preview/proj-1" }, + }) as ProjectClient; + client.getBuildStatus = async () => ({ + sessionId: "sess-1", + status: now >= 11 * 60_000 ? "completed" : "building", + projectId: "proj-1", + }); + + try { + const stdout: string[] = []; + const code = await runProjectSubcommand(["project", "build", "--wait", "Build", "a", "demo"], { + client, + stdout: (message) => stdout.push(message), + stderr: () => {}, + sleep: async (ms) => { + now += ms; + }, + handoffStore: null, + }); + + expect(code).toBe(0); + expect(now).toBeGreaterThanOrEqual(11 * 60_000); + expect(stdout.join("\n")).toContain("build sess-1: completed"); + } finally { + nowSpy.mockRestore(); + } + }); + it("fails a terminal build and prints the server reason", async () => { const result = await runProject( ["project", "build", "--wait", "Build", "a", "demo"], diff --git a/src/projects/cli.ts b/src/projects/cli.ts index 1dd1ea9..fb95483 100644 --- a/src/projects/cli.ts +++ b/src/projects/cli.ts @@ -4,7 +4,7 @@ import { BuildHandoffStore } from "./handoff.js"; import type { BuildStatusResponse, PlatformProject } from "./types.js"; const DEFAULT_LIST_LIMIT = 25; -const DEFAULT_BUILD_TIMEOUT_MS = 10 * 60_000; +const DEFAULT_BUILD_TIMEOUT_MS = 30 * 60_000; const DEFAULT_BUILD_POLL_MS = 30_000; export interface ProjectCliOptions { @@ -661,7 +661,7 @@ function printBuildHelp(out: (msg: string) => void): void { out(""); out("Options:"); out(" --wait, -w poll until the build completes, then print preview URL"); - out(" --timeout SECONDS max wait time with --wait (default: 600)"); + out(" --timeout SECONDS max wait time with --wait (default: 1800)"); out(" --model MODEL request a specific web build model"); out(" --scaffold ID request a specific web scaffold"); out(" --project ID continue/build against an existing project when supported by the web API");