fix delegate timeout (#284)

* pin all CLI installations to explicit versions and use pro models by default

- codex: pin @openai/codex to 0.101.0 (was "latest")
- opencode: pin opencode-ai to 1.1.56 (was "latest")
- gemini: pin gemini-cli to v0.28.2 via new tag param on installFromGithub
- cursor: pin to 2026.01.28-fd13201 via direct tarball download (replaces curl install script)
- add installFromDirectTarball to install.ts for versioned tarball URLs
- gemini auto effort now uses pro-preview instead of flash-preview
- test runner model overrides updated to use pro-preview consistently

Co-authored-by: Cursor <cursoragent@cursor.com>

* increase activity timeout

* fix delegation timeout

* fix delegate timeouts

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
David Blass
2026-02-12 23:46:28 +00:00
committed by pullfrog[bot]
parent ceadb3120a
commit a8dde34531
8 changed files with 121 additions and 27 deletions
+1
View File
@@ -142,6 +142,7 @@ export const claude = agent({
activityTimeout: 0, // disabled: process-level timeout in main.ts handles this (subprocess timeout would kill orchestrator during delegation)
onStdout: async (chunk) => {
finalOutput += chunk;
markActivity(); // reset activity timeout on any CLI output
// buffer incomplete lines across chunks (NDJSON format)
stdoutBuffer += chunk;
+1
View File
@@ -232,6 +232,7 @@ export const codex = agent({
activityTimeout: 0, // disabled: process-level timeout in main.ts handles this (subprocess timeout would kill orchestrator during delegation)
onStdout: async (chunk) => {
finalOutput += chunk;
markActivity(); // reset activity timeout on any CLI output
// buffer incomplete lines across chunks (NDJSON format)
stdoutBuffer += chunk;
+28 -16
View File
@@ -274,6 +274,7 @@ export const cursor = agent({
let stdout = "";
let stderr = "";
let stdoutBuffer = "";
child.on("spawn", () => {
log.debug("Cursor CLI process spawned");
@@ -282,25 +283,36 @@ export const cursor = agent({
child.stdout?.on("data", async (data) => {
const text = data.toString();
stdout += text;
markActivity(); // reset activity timeout on any CLI output
try {
const event = JSON.parse(text) as CursorEvent;
markActivity(); // reset activity timeout on every event
log.debug(JSON.stringify(event, null, 2));
// buffer incomplete lines across chunks (NDJSON format)
stdoutBuffer += text;
const lines = stdoutBuffer.split("\n");
// skip empty thinking deltas
if (event.type === "thinking" && event.subtype === "delta" && !event.text) {
return;
// keep the last element (may be incomplete) in the buffer
stdoutBuffer = lines.pop() || "";
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
try {
const event = JSON.parse(trimmed) as CursorEvent;
log.debug(JSON.stringify(event, null, 2));
// skip empty thinking deltas
if (event.type === "thinking" && event.subtype === "delta" && !event.text) {
continue;
}
// route to appropriate handler
const handler = messageHandlers[event.type as keyof typeof messageHandlers];
if (handler) {
await handler(event as never);
}
} catch {
// ignore parse errors - might be formatted tool call logs from cursor cli
}
// route to appropriate handler
const handler = messageHandlers[event.type as keyof typeof messageHandlers];
if (handler) {
await handler(event as never);
}
} catch {
// ignore parse errors - might be formatted tool call logs from cursor cli
// our handlers log tool calls instead, so we don't need to display these
}
});
+1
View File
@@ -239,6 +239,7 @@ export const gemini = agent({
onStdout: async (chunk) => {
const text = chunk.toString();
finalOutput += text;
markActivity(); // reset activity timeout on any CLI output
// buffer incomplete lines across chunks (NDJSON format)
stdoutBuffer += text;
+1
View File
@@ -123,6 +123,7 @@ export const opencode = agent({
onStdout: async (chunk) => {
const text = chunk.toString();
output += text;
markActivity(); // reset activity timeout on any CLI output
// buffer incomplete lines across chunks (NDJSON format)
stdoutBuffer += text;