@@ -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+
25120const opencodePort = await detectPort ( 4096 ) ;
26121
27122const opencode = await createOpencode ( {
28123 port : opencodePort ,
29124 config : {
30125 permission : DEFAULT_PERMISSION_CONFIG ,
31126 } ,
127+ fetch : customFetch ,
32128} ) ;
33129process . 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