@@ -288,6 +288,8 @@ export function initializeAgent(
288288 const gatewayUrl = getLlmGatewayUrlFromHost ( config . posthogApiHost ) ;
289289 process . env . ANTHROPIC_BASE_URL = gatewayUrl ;
290290 process . env . ANTHROPIC_AUTH_TOKEN = config . posthogApiKey ;
291+ // Use CLAUDE_CODE_OAUTH_TOKEN to override any stored /login credentials
292+ process . env . CLAUDE_CODE_OAUTH_TOKEN = config . posthogApiKey ;
291293 // Disable experimental betas (like input_examples) that the LLM gateway doesn't support
292294 process . env . CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true' ;
293295
@@ -377,6 +379,8 @@ export async function runAgent(
377379
378380 const startTime = Date . now ( ) ;
379381 const collectedText : string [ ] = [ ] ;
382+ // Track if we received a successful result (before any cleanup errors)
383+ let receivedSuccessResult = false ;
380384
381385 // Workaround for SDK bug: stdin closes before canUseTool responses can be sent.
382386 // The fix is to use an async generator for the prompt that stays open until
@@ -398,6 +402,31 @@ export async function runAgent(
398402 await resultReceived ;
399403 } ;
400404
405+ // Helper to handle successful completion (used in normal path and race condition recovery)
406+ const completeWithSuccess = (
407+ suppressedError ?: Error ,
408+ ) : { error ?: AgentErrorType ; message ?: string } => {
409+ const durationMs = Date . now ( ) - startTime ;
410+ const durationSeconds = Math . round ( durationMs / 1000 ) ;
411+
412+ if ( suppressedError ) {
413+ logToFile (
414+ `Ignoring post-completion error, agent completed successfully in ${ durationSeconds } s` ,
415+ ) ;
416+ logToFile ( 'Suppressed error:' , suppressedError . message ) ;
417+ } else {
418+ logToFile ( `Agent run completed in ${ durationSeconds } s` ) ;
419+ }
420+
421+ analytics . capture ( WIZARD_INTERACTION_EVENT_NAME , {
422+ action : 'agent integration completed' ,
423+ duration_ms : durationMs ,
424+ duration_seconds : durationSeconds ,
425+ } ) ;
426+ spinner . stop ( successMessage ) ;
427+ return { } ;
428+ } ;
429+
401430 try {
402431 // Tools needed for the wizard:
403432 // - File operations: Read, Write, Edit
@@ -428,7 +457,11 @@ export async function runAgent(
428457 settingSources : [ 'project' ] ,
429458 // Explicitly enable required tools including Skill
430459 allowedTools,
431- env : { ...process . env } ,
460+ env : {
461+ ...process . env ,
462+ // Prevent user's Anthropic API key from overriding the wizard's OAuth token
463+ ANTHROPIC_API_KEY : undefined ,
464+ } ,
432465 canUseTool : ( toolName : string , input : unknown ) => {
433466 logToFile ( 'canUseTool called:' , { toolName, input } ) ;
434467 const result = wizardCanUseTool (
@@ -454,11 +487,15 @@ export async function runAgent(
454487 handleSDKMessage ( message , options , spinner , collectedText ) ;
455488 // Signal completion when result received
456489 if ( message . type === 'result' ) {
490+ // Track successful results before any potential cleanup errors
491+ // The SDK may emit a second error result during cleanup due to a race condition
492+ if ( message . subtype === 'success' && ! message . is_error ) {
493+ receivedSuccessResult = true ;
494+ }
457495 signalDone ! ( ) ;
458496 }
459497 }
460498
461- const durationMs = Date . now ( ) - startTime ;
462499 const outputText = collectedText . join ( '\n' ) ;
463500
464501 // Check for error markers in the agent's output
@@ -487,19 +524,19 @@ export async function runAgent(
487524 return { error : AgentErrorType . API_ERROR , message : outputText } ;
488525 }
489526
490- logToFile ( `Agent run completed in ${ Math . round ( durationMs / 1000 ) } s` ) ;
491- analytics . capture ( WIZARD_INTERACTION_EVENT_NAME , {
492- action : 'agent integration completed' ,
493- duration_ms : durationMs ,
494- duration_seconds : Math . round ( durationMs / 1000 ) ,
495- } ) ;
496-
497- spinner . stop ( successMessage ) ;
498- return { } ;
527+ return completeWithSuccess ( ) ;
499528 } catch ( error ) {
500529 // Signal done to unblock the async generator
501530 signalDone ! ( ) ;
502531
532+ // If we already received a successful result, the error is from SDK cleanup
533+ // This happens due to a race condition: the SDK tries to send a cleanup command
534+ // after the prompt stream closes, but streaming mode is still active.
535+ // See: https://github.com/anthropics/claude-agent-sdk-typescript/issues/41
536+ if ( receivedSuccessResult ) {
537+ return completeWithSuccess ( error as Error ) ;
538+ }
539+
503540 // Check if we collected an API error before the exception was thrown
504541 const outputText = collectedText . join ( '\n' ) ;
505542
0 commit comments