Skip to content

Commit 07949ce

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(pi): preserve plan exploration timeout
1 parent e948398 commit 07949ce

4 files changed

Lines changed: 22 additions & 7 deletions

File tree

apps/sim/executor/handlers/pi/cloud/plan/backend.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ describe('runCloudPlanPi', () => {
105105
expect(piOptions.envs.GITHUB_TOKEN).toBeUndefined()
106106
expect(piOptions.envs.PI_MODEL).toBe('claude-sonnet-4-6')
107107
expect(piOptions.envs.PI_THINKING).toBe('high')
108+
expect(piOptions.timeoutMs).toBe(30 * 60 * 1000)
108109

109110
expect(mockBuildPrompt).toHaveBeenCalledWith(
110111
expect.objectContaining({

apps/sim/executor/handlers/pi/cloud/plan/backend.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export const runCloudPlanPi: PiBackendRun<PiCloudPlanRunParams> = async (params,
133133
}
134134
: {}),
135135
},
136-
timeoutMs: resolvePiTimeoutMs(lifetimeMs),
136+
timeoutMs: resolvePiTimeoutMs(lifetimeMs, { finalizePhases: 0 }),
137137
onStdout: handleChunk,
138138
}
139139
),

apps/sim/executor/handlers/pi/cloud/shared.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ describe('resolvePiTimeoutMs', () => {
4040
expect(resolvePiTimeoutMs(shortLifetime)).toBeLessThanOrEqual(shortLifetime)
4141
})
4242

43+
it('does not reserve nonexistent finalize phases for Plan', () => {
44+
const timeout = resolvePiTimeoutMs(PI_SANDBOX_MAX_LIFETIME_MS, { finalizePhases: 0 })
45+
46+
expect(timeout).toBeLessThanOrEqual(PI_SANDBOX_MAX_LIFETIME_MS - CLONE_TIMEOUT_MS)
47+
expect(timeout).toBeGreaterThan(resolvePiTimeoutMs(PI_SANDBOX_MAX_LIFETIME_MS))
48+
})
49+
4350
it('falls back to the single-turn floor when the reserves exhaust the lifetime', () => {
4451
// A deadline shorter than the bracketing commands' worst case is legitimate
4552
// (a free-plan sync run). Those ceilings are pessimistic, so leave a short

apps/sim/executor/handlers/pi/cloud/shared.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ export const MIN_PI_TIMEOUT_MS = 60 * 1000
3434
* reaped the sandbox and surface as an opaque SDK error.
3535
*
3636
* The reserve matters as much as the cap. The sandbox clock starts at create,
37-
* and three commands bracket the agent turn: the clone before it, then the
38-
* commit and the push after it, the last two sharing
39-
* {@link FINALIZE_TIMEOUT_MS}. Capping at the bare lifetime would mean the
40-
* sandbox always died first, taking the agent's finished work with it unpushed.
37+
* and authoring has three commands around the agent turn: the clone before it,
38+
* then the commit and push after it, the last two sharing
39+
* {@link FINALIZE_TIMEOUT_MS}. Plan has no finalize phase and sets that reserve
40+
* to zero. Capping at the bare lifetime would mean the sandbox died first.
4141
*
4242
* Takes the lifetime as an argument rather than reading the provider ceiling
4343
* itself, because that ceiling is no longer the only lifetime a run can get: a
@@ -53,10 +53,17 @@ export const MIN_PI_TIMEOUT_MS = 60 * 1000
5353
* through `ttlMinutes`. Reserving the surrounding commands keeps the agent turn
5454
* inside the lifetime the selected provider actually received.
5555
*/
56-
export function resolvePiTimeoutMs(lifetimeMs = resolvePiSandboxLifetimeMs()): number {
56+
export function resolvePiTimeoutMs(
57+
lifetimeMs = resolvePiSandboxLifetimeMs(),
58+
options?: { finalizePhases?: number }
59+
): number {
60+
const finalizePhases = options?.finalizePhases ?? 2
5761
return Math.min(
5862
getMaxExecutionTimeout(),
59-
Math.max(lifetimeMs - CLONE_TIMEOUT_MS - 2 * FINALIZE_TIMEOUT_MS, MIN_PI_TIMEOUT_MS)
63+
Math.max(
64+
lifetimeMs - CLONE_TIMEOUT_MS - finalizePhases * FINALIZE_TIMEOUT_MS,
65+
MIN_PI_TIMEOUT_MS
66+
)
6067
)
6168
}
6269

0 commit comments

Comments
 (0)