@@ -213,6 +213,13 @@ export class Task extends EventEmitter<ClineEvents> {
213213 didAlreadyUseTool = false
214214 didCompleteReadingStream = false
215215
216+ // Temperature management for tool failure retries
217+ private currentTemperature ?: number
218+ private originalTemperature ?: number
219+ private temperatureReductionAttempts = 0
220+ private readonly maxTemperatureReductions = 3
221+ private readonly temperatureReductionFactor = 0.5
222+
216223 constructor ( {
217224 provider,
218225 apiConfiguration,
@@ -1361,7 +1368,7 @@ export class Task extends EventEmitter<ClineEvents> {
13611368 // Yields only if the first chunk is successful, otherwise will
13621369 // allow the user to retry the request (most likely due to rate
13631370 // limit error, which gets thrown on the first chunk).
1364- const stream = this . attemptApiRequest ( )
1371+ const stream = this . attemptApiRequest ( 0 , this . currentTemperature )
13651372 let assistantMessage = ""
13661373 let reasoningMessage = ""
13671374 this . isStreaming = true
@@ -1565,8 +1572,29 @@ export class Task extends EventEmitter<ClineEvents> {
15651572 this . consecutiveMistakeCount ++
15661573 }
15671574
1568- const recDidEndLoop = await this . recursivelyMakeClineRequests ( this . userMessageContent )
1569- didEndLoop = recDidEndLoop
1575+ // Check if we should retry with reduced temperature due to tool failure
1576+ if ( this . shouldReduceTemperature ) {
1577+ const canRetry = await this . retryWithReducedTemperature ( )
1578+ if ( canRetry ) {
1579+ // Retry the request with reduced temperature
1580+ const retryUserContent = [
1581+ ...this . userMessageContent ,
1582+ {
1583+ type : "text" as const ,
1584+ text : "I've reduced the temperature to help avoid tool errors. Please try again with the same approach." ,
1585+ } ,
1586+ ]
1587+ const recDidEndLoop = await this . recursivelyMakeClineRequests ( retryUserContent )
1588+ didEndLoop = recDidEndLoop
1589+ } else {
1590+ // Can't reduce temperature further, proceed normally
1591+ const recDidEndLoop = await this . recursivelyMakeClineRequests ( this . userMessageContent )
1592+ didEndLoop = recDidEndLoop
1593+ }
1594+ } else {
1595+ const recDidEndLoop = await this . recursivelyMakeClineRequests ( this . userMessageContent )
1596+ didEndLoop = recDidEndLoop
1597+ }
15701598 } else {
15711599 // If there's no assistant_responses, that means we got no text
15721600 // or tool_use content blocks from API which we should assume is
@@ -1669,7 +1697,7 @@ export class Task extends EventEmitter<ClineEvents> {
16691697 } ) ( )
16701698 }
16711699
1672- public async * attemptApiRequest ( retryAttempt : number = 0 ) : ApiStream {
1700+ public async * attemptApiRequest ( retryAttempt : number = 0 , temperatureOverride ?: number ) : ApiStream {
16731701 const state = await this . providerRef . deref ( ) ?. getState ( )
16741702 const {
16751703 apiConfiguration,
@@ -1682,6 +1710,22 @@ export class Task extends EventEmitter<ClineEvents> {
16821710 profileThresholds = { } ,
16831711 } = state ?? { }
16841712
1713+ // Store original temperature on first attempt
1714+ if ( this . originalTemperature === undefined && apiConfiguration ) {
1715+ this . originalTemperature = apiConfiguration . modelTemperature ?? undefined
1716+ }
1717+
1718+ // Apply temperature override if provided
1719+ if ( temperatureOverride !== undefined && apiConfiguration ) {
1720+ this . currentTemperature = temperatureOverride
1721+ // Create a modified API configuration with the new temperature
1722+ const modifiedApiConfig = { ...apiConfiguration , modelTemperature : temperatureOverride }
1723+ // Rebuild the API handler with the modified configuration
1724+ this . api = buildApiHandler ( modifiedApiConfig )
1725+ } else {
1726+ this . currentTemperature = this . originalTemperature
1727+ }
1728+
16851729 // Get condensing configuration for automatic triggers
16861730 const customCondensingPrompt = state ?. customCondensingPrompt
16871731 const condensingApiConfigId = state ?. condensingApiConfigId
@@ -1947,6 +1991,43 @@ export class Task extends EventEmitter<ClineEvents> {
19471991 if ( error ) {
19481992 this . emit ( "taskToolFailed" , this . taskId , toolName , error )
19491993 }
1994+
1995+ // Trigger temperature reduction for retry
1996+ this . shouldReduceTemperature = true
1997+ }
1998+
1999+ private shouldReduceTemperature = false
2000+
2001+ public async retryWithReducedTemperature ( ) : Promise < boolean > {
2002+ // Check if we've exceeded max temperature reductions
2003+ if ( this . temperatureReductionAttempts >= this . maxTemperatureReductions ) {
2004+ await this . say (
2005+ "error" ,
2006+ `Maximum temperature reduction attempts (${ this . maxTemperatureReductions } ) reached. Cannot reduce temperature further.` ,
2007+ )
2008+ return false
2009+ }
2010+
2011+ // Calculate new temperature
2012+ const currentTemp = this . currentTemperature ?? this . originalTemperature ?? 1.0
2013+ const newTemperature = Math . max ( 0 , currentTemp * this . temperatureReductionFactor )
2014+
2015+ // Increment attempt counter
2016+ this . temperatureReductionAttempts ++
2017+
2018+ // Log the temperature reduction
2019+ await this . say (
2020+ "text" ,
2021+ `Reducing temperature from ${ currentTemp . toFixed ( 2 ) } to ${ newTemperature . toFixed ( 2 ) } due to tool failure (attempt ${ this . temperatureReductionAttempts } /${ this . maxTemperatureReductions } )` ,
2022+ )
2023+
2024+ // Store the new temperature for the next API request
2025+ this . currentTemperature = newTemperature
2026+
2027+ // Reset the flag
2028+ this . shouldReduceTemperature = false
2029+
2030+ return true
19502031 }
19512032
19522033 // Getters
0 commit comments