Skip to content

Commit afa65d2

Browse files
committed
debugging opencode failures on gpt-5-codex
1 parent d202c29 commit afa65d2

1 file changed

Lines changed: 117 additions & 0 deletions

File tree

agents/opencode.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,109 @@ const DEFAULT_PERMISSION_CONFIG: NonNullable<OpencodeConfig["permission"]> = {
2222
webfetch: "allow",
2323
};
2424

25+
// Custom fetch with extended timeout and better error handling
26+
const customFetch: typeof fetch = async (input, init) => {
27+
const url = typeof input === "string" ? input : input.url;
28+
const method = init?.method || "GET";
29+
const startTime = Date.now();
30+
31+
// Log request details
32+
console.error(`[opencode] ============ FETCH REQUEST START ============`);
33+
console.error(`[opencode] ${method} ${url}`);
34+
console.error(`[opencode] Timeout: 600000ms (10 minutes)`);
35+
36+
if (init?.headers) {
37+
console.error(`[opencode] Request Headers:`);
38+
const headers = init.headers;
39+
if (headers instanceof Headers) {
40+
headers.forEach((value, key) => {
41+
console.error(`[opencode] ${key}: ${key.toLowerCase().includes('auth') || key.toLowerCase().includes('key') ? '***REDACTED***' : value}`);
42+
});
43+
} else if (typeof headers === "object") {
44+
Object.entries(headers).forEach(([key, value]) => {
45+
console.error(`[opencode] ${key}: ${key.toLowerCase().includes('auth') || key.toLowerCase().includes('key') ? '***REDACTED***' : value}`);
46+
});
47+
}
48+
} else {
49+
console.error(`[opencode] Request Headers: none`);
50+
}
51+
52+
if (init?.body) {
53+
const bodyStr = typeof init.body === "string" ? init.body : String(init.body);
54+
console.error(`[opencode] Request Body Length: ${bodyStr.length} bytes`);
55+
// Don't log full body to avoid sensitive data, but show a preview
56+
if (bodyStr.length < 500) {
57+
console.error(`[opencode] Request Body Preview: ${bodyStr.substring(0, 200)}...`);
58+
}
59+
}
60+
61+
try {
62+
// Extend timeout to 10 minutes for long-running LLM requests
63+
const controller = new AbortController();
64+
const timeoutId = setTimeout(() => {
65+
const duration = Date.now() - startTime;
66+
console.error(`[opencode] ⏱️ REQUEST TIMEOUT after ${duration}ms`);
67+
controller.abort();
68+
}, 600_000); // 10 minutes
69+
70+
const response = await fetch(input, {
71+
...init,
72+
signal: controller.signal,
73+
});
74+
75+
clearTimeout(timeoutId);
76+
const duration = Date.now() - startTime;
77+
78+
console.error(`[opencode] ============ FETCH RESPONSE ============`);
79+
console.error(`[opencode] Status: ${response.status} ${response.statusText}`);
80+
console.error(`[opencode] Duration: ${duration}ms`);
81+
82+
// Log response headers
83+
console.error(`[opencode] Response Headers:`);
84+
response.headers.forEach((value, key) => {
85+
console.error(`[opencode] ${key}: ${value}`);
86+
});
87+
88+
if (!response.ok) {
89+
const responseText = await response.clone().text().catch(() => "Unable to read body");
90+
console.error(`[opencode] ❌ HTTP ${response.status} Response Body:`);
91+
console.error(responseText.substring(0, 1000));
92+
} else {
93+
console.error(`[opencode] ✅ Request successful`);
94+
}
95+
96+
console.error(`[opencode] ============ FETCH REQUEST END ============`);
97+
return response;
98+
} catch (error) {
99+
const duration = Date.now() - startTime;
100+
console.error(`[opencode] ============ FETCH ERROR ============`);
101+
console.error(`[opencode] ❌ Fetch failed for ${method} ${url}`);
102+
console.error(`[opencode] Duration: ${duration}ms`);
103+
console.error(`[opencode] Error Type: ${error instanceof Error ? error.name : typeof error}`);
104+
console.error(`[opencode] Error Message: ${error instanceof Error ? error.message : String(error)}`);
105+
106+
if (error instanceof Error && error.stack) {
107+
console.error(`[opencode] Error Stack:`);
108+
console.error(error.stack);
109+
}
110+
111+
if (error && typeof error === "object" && "cause" in error) {
112+
console.error(`[opencode] Error Cause:`, error.cause);
113+
}
114+
115+
console.error(`[opencode] ============ FETCH ERROR END ============`);
116+
throw error;
117+
}
118+
};
119+
25120
const opencodePort = await detectPort(4096);
26121

27122
const opencode = await createOpencode({
28123
port: opencodePort,
29124
config: {
30125
permission: DEFAULT_PERMISSION_CONFIG,
31126
},
127+
fetch: customFetch,
32128
});
33129
process.once("beforeExit", () => opencode.server.close());
34130

@@ -162,12 +258,18 @@ const opencodeAgent: AgentDefinition = {
162258

163259
let sessionID = sessionCache.get(cacheKey);
164260
if (!sessionID) {
261+
console.error(`[opencode] Creating new session for ${cacheKey} in directory ${cwd}`);
262+
const sessionStartTime = Date.now();
165263
const { data: session } = await opencode.client.session.create({
166264
query: { directory: cwd },
167265
throwOnError: true,
168266
});
267+
const sessionDuration = Date.now() - sessionStartTime;
169268
sessionID = session.id;
170269
sessionCache.set(cacheKey, sessionID);
270+
console.error(`[opencode] Session created with ID ${sessionID} in ${sessionDuration}ms`);
271+
} else {
272+
console.error(`[opencode] Reusing cached session ${sessionID} for ${cacheKey}`);
171273
}
172274

173275
const actions: string[] = [];
@@ -177,6 +279,11 @@ const opencodeAgent: AgentDefinition = {
177279
};
178280
try {
179281
const [providerID, modelID] = model.split("/");
282+
console.error(`[opencode] Sending prompt to session ${sessionID} with model ${providerID}/${modelID}`);
283+
console.error(`[opencode] Prompt length: ${prompt.length} characters`);
284+
console.error(`[opencode] Working directory: ${cwd}`);
285+
286+
const promptStartTime = Date.now();
180287
const { data } = await opencode.client.session.prompt({
181288
path: { id: sessionID! },
182289
query: { directory: cwd },
@@ -189,6 +296,11 @@ const opencodeAgent: AgentDefinition = {
189296
},
190297
throwOnError: true,
191298
});
299+
const promptDuration = Date.now() - promptStartTime;
300+
301+
console.error(`[opencode] Prompt completed in ${promptDuration}ms`);
302+
console.error(`[opencode] Response parts count: ${Array.isArray(data.parts) ? data.parts.length : 'invalid'}`);
303+
console.error(`[opencode] Token usage: input=${data.info.tokens.input}, output=${data.info.tokens.output}`);
192304

193305
usage.input = data.info.tokens.input;
194306
usage.output = data.info.tokens.output;
@@ -200,6 +312,11 @@ const opencodeAgent: AgentDefinition = {
200312

201313
logPromptResult(data, options);
202314
} catch (error) {
315+
console.error(`[opencode] Error occurred during prompt execution for session ${sessionID}`);
316+
console.error(`[opencode] Model: ${model}, CWD: ${cwd}`);
317+
console.error(`[opencode] Error details:`, serializeError(error));
318+
console.error(`[opencode] Clearing session cache for ${cacheKey}`);
319+
203320
sessionCache.delete(cacheKey);
204321
logError(
205322
{

0 commit comments

Comments
 (0)