@@ -405,10 +405,16 @@ export class Cline extends EventEmitter<ClineEvents> {
405405 if ( ! provider ) {
406406 throw new Error ( "[Cline.ts ask] Cannot wait for input, provider reference lost." )
407407 }
408- await provider . postMessageToWebview ( { type : "enableChatInput" } ) // <<< Use the new dedicated message type
408+ await provider . postMessageToWebview ( { type : "enableChatInput" } )
409409
410- // Wait for handleWebviewAskResponse to set this.askResponse
411- await pWaitFor ( ( ) => this . askResponse !== undefined , { interval : 100 } )
410+ // abort is crusial here to prevent blocking user input on switch mode
411+ await pWaitFor ( ( ) => this . askResponse !== undefined || this . abort , { interval : 100 } )
412+
413+ if ( this . abort ) {
414+ throw new Error (
415+ `[Cline#ask chat_input_wait] Task ${ this . taskId } .${ this . instanceId } aborted while waiting for user input.` ,
416+ )
417+ }
412418
413419 console . log ( "[Cline.ts ask] Resuming after chat input received." )
414420 const result = { response : this . askResponse ! , text : this . askResponseText , images : this . askResponseImages }
@@ -1064,18 +1070,16 @@ export class Cline extends EventEmitter<ClineEvents> {
10641070 console . log ( `Model: ${ this . api . getModel ( ) . id } , Context window: ${ modelInfo . contextWindow } tokens` )
10651071
10661072 // Detailed debug info on each message
1067- if ( mode === "chat" ) {
1068- console . log ( `\n======= MINIMAL MODE DEBUG INFO =======` )
1069- console . log ( `System prompt: ${ systemPrompt } ...` )
1070- console . log (
1071- `\nLast user message content: ${
1072- this . apiConversationHistory . length > 0 &&
1073- this . apiConversationHistory [ this . apiConversationHistory . length - 1 ] . role === "user"
1074- ? JSON . stringify ( this . apiConversationHistory [ this . apiConversationHistory . length - 1 ] . content )
1075- : "No user message"
1076- } ...`,
1077- )
1078- }
1073+ console . log ( `\n======= MINIMAL MODE DEBUG INFO =======` )
1074+ console . log ( `System prompt: ${ systemPrompt } ...` )
1075+ console . log (
1076+ `\nLast user message content: ${
1077+ this . apiConversationHistory . length > 0 &&
1078+ this . apiConversationHistory [ this . apiConversationHistory . length - 1 ] . role === "user"
1079+ ? JSON . stringify ( this . apiConversationHistory [ this . apiConversationHistory . length - 1 ] . content )
1080+ : "No user message"
1081+ } ...`,
1082+ )
10791083
10801084 // If the previous API request's total token usage is close to the context window, truncate the conversation history to free up space for the new request
10811085 if ( previousApiReqIndex >= 0 ) {
@@ -1955,57 +1959,34 @@ export class Cline extends EventEmitter<ClineEvents> {
19551959
19561960 await pWaitFor ( ( ) => this . userMessageContentReady )
19571961
1958- // if the model did not tool use, then we need to tell it to either use a tool or attempt_completion
1959- const didToolUse = this . assistantMessageContent . some ( ( block ) => block . type === "tool_use" )
1960- if ( ! didToolUse ) {
1961- // --- Get provider and mode ---
1962- const provider = this . providerRef . deref ( )
1963- const { mode } = ( await provider ?. getState ( ) ) ?? { }
1962+ // --- Get provider and mode ---
1963+ const provider = this . providerRef . deref ( )
1964+ const { mode } = ( await provider ?. getState ( ) ) ?? { }
19641965
1965- if ( mode !== "chat" ) {
1966- // Non-chat mode, no tool use: Add feedback and recurse internally
1966+ if ( mode === "chat" ) {
1967+ // Handle chat mode continuation/termination
1968+ const nextUserContent = await this . _handleChatResponse ( )
1969+ if ( nextUserContent ) {
1970+ return await this . recursivelyMakeClineRequests ( nextUserContent , false )
1971+ } else {
1972+ didEndLoop = true
1973+ }
1974+ } else {
1975+ // Original logic for non-chat modes
1976+ const didToolUse = this . assistantMessageContent . some ( ( block ) => block . type === "tool_use" )
1977+ if ( ! didToolUse ) {
1978+ // if the model did not tool use, then we need to tell it to either use a tool or attempt_completion
19671979 this . userMessageContent . push ( {
19681980 type : "text" ,
19691981 text : formatResponse . noToolsUsed ( ) ,
19701982 } )
19711983 this . consecutiveMistakeCount ++
1972- // Continue the loop by recursing with the feedback message
1973- // Return the boolean result of this recursive call
1974- return await this . recursivelyMakeClineRequests ( this . userMessageContent , false )
1975- } else {
1976- // Chat mode, no tool use: Use ask('chat_input_wait') to pause and get input
1977- console . log ( "[Cline.ts] Chat mode, no tool use. Waiting for next user input via ask." )
1978- const { response, text, images } = await this . ask ( "chat_input_wait" )
1979-
1980- if ( response === "messageResponse" ) {
1981- // User provided input
1982- const nextUserContent : UserContent = [ ]
1983- if ( text ) nextUserContent . push ( { type : "text" , text } )
1984- if ( images ) nextUserContent . push ( ...formatResponse . imageBlocks ( images ) )
1985-
1986- if ( nextUserContent . length > 0 ) {
1987- // Add user input to UI (ask doesn't add messages for chat_input_wait)
1988- await this . say ( "user_feedback" , text , images )
1989- // Recurse with the new user input
1990- return await this . recursivelyMakeClineRequests ( nextUserContent , false )
1991- } else {
1992- // Resumed but no content? End the loop.
1993- console . warn ( "[Cline.ts] Resumed chat wait but received no content." )
1994- return true
1995- }
1996- } else {
1997- // User likely cancelled or something went wrong during the ask wait. End the loop.
1998- console . log ( "[Cline.ts] Chat input wait did not receive messageResponse." )
1999- return true
2000- }
20011984 }
2002- } else {
2003- // Tool use detected: tool results are already prepared in this.userMessageContent
2004- // by presentAssistantMessage. Continue the loop by recursing.
2005- return await this . recursivelyMakeClineRequests ( this . userMessageContent , false )
1985+ const recDidEndLoop = await this . recursivelyMakeClineRequests ( this . userMessageContent )
1986+ didEndLoop = recDidEndLoop
20061987 }
20071988 } else {
2008- // if there's no assistant_responses, that means we got no text or tool_use content blocks from API which we should assume is an error
1989+ // if there's no assistant_responses, that means we got no text or tool_use content blocks from API
20091990 await this . say (
20101991 "error" ,
20111992 "Unexpected API Response: The language model did not provide any assistant messages. This may indicate an issue with the API or the model's output." ,
@@ -2014,9 +1995,10 @@ export class Cline extends EventEmitter<ClineEvents> {
20141995 role : "assistant" ,
20151996 content : [ { type : "text" , text : "Failure: I did not provide a response." } ] ,
20161997 } )
1998+ didEndLoop = true
20171999 }
20182000
2019- return didEndLoop // will always be false for now
2001+ return didEndLoop
20202002 } catch ( error ) {
20212003 // This should never happen since the only thing that can throw an
20222004 // error is the attemptApiRequest, which is wrapped in a try catch
@@ -2673,4 +2655,33 @@ export class Cline extends EventEmitter<ClineEvents> {
26732655 public getToolUsage ( ) {
26742656 return this . toolUsage
26752657 }
2658+
2659+ // --- Add the new private method here ---
2660+ private async _handleChatResponse ( ) : Promise < UserContent | null > {
2661+ // Chat mode: Always wait for user input after assistant's turn.
2662+ console . log ( "[Cline.ts] Chat mode. Waiting for next user input via ask." )
2663+ const { response, text, images } = await this . ask ( "chat_input_wait" )
2664+
2665+ if ( response === "messageResponse" ) {
2666+ // User provided input
2667+ const nextUserContent : UserContent = [ ]
2668+ if ( text ) nextUserContent . push ( { type : "text" , text } )
2669+ if ( images ) nextUserContent . push ( ...formatResponse . imageBlocks ( images ) )
2670+
2671+ if ( nextUserContent . length > 0 ) {
2672+ // Add user input to UI (ask doesn't add messages for chat_input_wait)
2673+ await this . say ( "user_feedback" , text , images )
2674+ // Return content for next recursion
2675+ return nextUserContent
2676+ } else {
2677+ // Resumed but no content? End the loop.
2678+ console . warn ( "[Cline.ts] Resumed chat wait but received no content." )
2679+ return null // Signal loop termination
2680+ }
2681+ } else {
2682+ // User likely cancelled or something went wrong during the ask wait. End the loop.
2683+ console . log ( "[Cline.ts] Chat input wait did not receive messageResponse." )
2684+ return null // Signal loop termination
2685+ }
2686+ }
26762687}
0 commit comments