refactor(eval): changed timeout from inactivity to wall-clock budget
- Only bridge heartbeats (`agent()`/`llm()`) now re-arm the watchdog; compute, stdout, `log()`/`phase()`, and ordinary tool calls count against the budget. - Emitted an immediate heartbeat at bridge call start to avoid early abort near budget edge. - Removed `idle` flag and "of inactivity" suffix from timeout annotation strings. - Updated docs, prompts, and comments to reflect the new wall-clock semantics.
This commit is contained in:
@@ -232,20 +232,18 @@ async function waitForPromiseWithCancellation<T>(
|
||||
// Result formatting
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function formatTimeoutAnnotation(timeoutMs?: number, idle = false): string | undefined {
|
||||
const suffix = idle ? " of inactivity" : "";
|
||||
function formatTimeoutAnnotation(timeoutMs?: number): string | undefined {
|
||||
if (timeoutMs === undefined) return "Command timed out";
|
||||
const secs = Math.max(1, Math.round(timeoutMs / 1000));
|
||||
return `Command timed out after ${secs} seconds${suffix}`;
|
||||
return `Command timed out after ${secs} seconds`;
|
||||
}
|
||||
|
||||
function formatKernelTimeoutAnnotation(timeoutMs: number | undefined, kernelKilled: boolean, idle = false): string {
|
||||
function formatKernelTimeoutAnnotation(timeoutMs: number | undefined, kernelKilled: boolean): string {
|
||||
const secs = timeoutMs === undefined ? undefined : Math.max(1, Math.round(timeoutMs / 1000));
|
||||
const suffix = idle ? " of inactivity" : "";
|
||||
if (kernelKilled) {
|
||||
return `eval cell timed out${suffix} and the kernel was unresponsive to interrupt; the kernel has been killed and will be recreated on the next call.`;
|
||||
return "eval cell timed out and the kernel was unresponsive to interrupt; the kernel has been killed and will be recreated on the next call.";
|
||||
}
|
||||
const duration = secs === undefined ? "the configured timeout" : `${secs}s${suffix}`;
|
||||
const duration = secs === undefined ? "the configured timeout" : `${secs}s`;
|
||||
return `eval cell timed out after ${duration}; kernel interrupted but remains running. Reset the kernel via { reset: true } if state appears corrupted.`;
|
||||
}
|
||||
|
||||
@@ -489,10 +487,6 @@ async function executeWithKernel(
|
||||
const displayOutputs: KernelDisplayOutput[] = [];
|
||||
const deadlineMs = getExecutionDeadlineMs(options);
|
||||
let executionTimeoutMs: number | undefined;
|
||||
// Idle mode: the caller (eval tool) drives cancellation via an idle-aware
|
||||
// signal and passes no wall-clock deadline, so annotate timeouts with the
|
||||
// configured inactivity budget rather than a remaining-deadline figure.
|
||||
const idleMode = deadlineMs === undefined && options?.idleTimeoutMs !== undefined;
|
||||
|
||||
// Collect every display output and, for status events, stream them live so
|
||||
// long-running bridge helpers (e.g. `agent()`) surface progress mid-cell.
|
||||
@@ -530,11 +524,7 @@ async function executeWithKernel(
|
||||
|
||||
if (result.cancelled) {
|
||||
const annotation = result.timedOut
|
||||
? formatKernelTimeoutAnnotation(
|
||||
executionTimeoutMs ?? options?.idleTimeoutMs,
|
||||
result.kernelKilled ?? false,
|
||||
idleMode,
|
||||
)
|
||||
? formatKernelTimeoutAnnotation(executionTimeoutMs ?? options?.idleTimeoutMs, result.kernelKilled ?? false)
|
||||
: undefined;
|
||||
return {
|
||||
exitCode: undefined,
|
||||
@@ -572,7 +562,7 @@ async function executeWithKernel(
|
||||
displayOutputs,
|
||||
stdinRequested: false,
|
||||
...(await sink.dump(
|
||||
timedOut ? formatTimeoutAnnotation(executionTimeoutMs ?? options?.idleTimeoutMs, idleMode) : undefined,
|
||||
timedOut ? formatTimeoutAnnotation(executionTimeoutMs ?? options?.idleTimeoutMs) : undefined,
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user