@@ -101,6 +101,7 @@ import {
101101 resolveBootstrapPromptTruncationWarningMode ,
102102 resolveBootstrapTotalMaxChars ,
103103} from "../../pi-embedded-helpers.js" ;
104+ import { countActiveToolExecutions } from "../../pi-embedded-subscribe.handlers.tools.js" ;
104105import { subscribeEmbeddedPiSession } from "../../pi-embedded-subscribe.js" ;
105106import { createPreparedEmbeddedPiSettingsManager } from "../../pi-project-settings.js" ;
106107import {
@@ -782,6 +783,7 @@ export async function runEmbeddedAttempt(
782783 let timedOut = false ;
783784 let idleTimedOut = false ;
784785 let timedOutDuringCompaction = false ;
786+ let timedOutDuringToolExecution = false ;
785787 let promptError : unknown = null ;
786788 let emitDiagnosticRunCompleted :
787789 | ( ( outcome : "completed" | "aborted" | "error" , err ?: unknown ) => void )
@@ -2250,6 +2252,14 @@ export async function runEmbeddedAttempt(
22502252 aborted = true ;
22512253 if ( isTimeout ) {
22522254 timedOut = true ;
2255+ // Distinguish run-timer fires that occur while tool execution is in
2256+ // flight (LLM already responded; primary model is not at fault) from
2257+ // LLM-phase timeouts. Mirrors the `timedOutDuringCompaction` precedent
2258+ // (#46889) so the failover policy can skip pointless model fallback.
2259+ // Closes #52147.
2260+ if ( ! timedOutDuringCompaction && countActiveToolExecutions ( params . runId ) > 0 ) {
2261+ timedOutDuringToolExecution = true ;
2262+ }
22532263 }
22542264 if ( isTimeout ) {
22552265 runAbortController . abort ( reason ?? makeTimeoutAbortReason ( ) ) ;
@@ -3456,6 +3466,7 @@ export async function runEmbeddedAttempt(
34563466 timedOut,
34573467 idleTimedOut,
34583468 timedOutDuringCompaction,
3469+ timedOutDuringToolExecution,
34593470 promptError : promptError ? formatErrorMessage ( promptError ) : undefined ,
34603471 promptErrorSource,
34613472 usage : attemptUsage ,
@@ -3474,6 +3485,7 @@ export async function runEmbeddedAttempt(
34743485 timedOut,
34753486 idleTimedOut,
34763487 timedOutDuringCompaction,
3488+ timedOutDuringToolExecution,
34773489 promptError : promptError ? formatErrorMessage ( promptError ) : undefined ,
34783490 promptErrorSource,
34793491 usage : attemptUsage ,
@@ -3498,6 +3510,7 @@ export async function runEmbeddedAttempt(
34983510 timedOut,
34993511 idleTimedOut,
35003512 timedOutDuringCompaction,
3513+ timedOutDuringToolExecution,
35013514 promptError : promptError ? formatErrorMessage ( promptError ) : undefined ,
35023515 } ) ;
35033516 trajectoryEndRecorded = true ;
@@ -3511,6 +3524,7 @@ export async function runEmbeddedAttempt(
35113524 timedOut,
35123525 idleTimedOut,
35133526 timedOutDuringCompaction,
3527+ timedOutDuringToolExecution,
35143528 promptError,
35153529 promptErrorSource,
35163530 preflightRecovery,
@@ -3555,6 +3569,7 @@ export async function runEmbeddedAttempt(
35553569 timedOut,
35563570 idleTimedOut,
35573571 timedOutDuringCompaction,
3572+ timedOutDuringToolExecution,
35583573 promptError : promptError ? formatErrorMessage ( promptError ) : undefined ,
35593574 } ) ;
35603575 }
0 commit comments