@@ -15,6 +15,7 @@ import type {
1515 ReasoningEffortOption ,
1616 Thread ,
1717 ThreadItem ,
18+ TurnCompletedNotification ,
1819 UserInput
1920} from "./app-server/v2" ;
2021import type { RateLimitsMap } from "./RateLimitsMap" ;
@@ -742,13 +743,20 @@ export class CodexAcpServer implements acp.Agent {
742743 approvalHandler ,
743744 elicitationHandler ) ;
744745
745- if ( await this . availableCommands . tryHandle ( params . prompt , sessionState ) ) {
746+ const commandResult = await this . availableCommands . tryHandle ( params . prompt , sessionState ) ;
747+ if ( commandResult ) {
746748 logger . log ( "Prompt handled by a command" ) ;
747- return {
748- stopReason : "end_turn" ,
749- usage : this . buildPromptUsage ( sessionState . lastTokenUsage ) ,
750- _meta : this . buildQuotaMeta ( sessionState ) ,
751- } ;
749+ if ( commandResult !== true ) {
750+ const interruptedResponse = await this . createInterruptedResponseIfNeeded ( params . sessionId , commandResult , sessionState ) ;
751+ if ( interruptedResponse ) {
752+ return interruptedResponse ;
753+ }
754+ }
755+ const error = eventHandler . getFailure ( ) ;
756+ if ( error ) {
757+ throw error ;
758+ }
759+ return this . createPromptResponse ( "end_turn" , sessionState ) ;
752760 }
753761
754762 const modelId = ModelId . fromString ( sessionState . currentModelId ) ;
@@ -771,22 +779,9 @@ export class CodexAcpServer implements acp.Agent {
771779 ( ) => this . codexAcpClient . sendPrompt ( params , agentMode , modelId , disableSummary , sessionState . cwd ) ) ;
772780
773781 // Check if turn was interrupted (cancelled)
774- if ( turnCompleted . turn . status === "interrupted" ) {
775- await this . connection . sessionUpdate ( {
776- sessionId : params . sessionId ,
777- update : {
778- sessionUpdate : "agent_message_chunk" ,
779- content : {
780- type : "text" ,
781- text : "*Conversation interrupted*"
782- }
783- }
784- } ) ;
785- return {
786- stopReason : "cancelled" ,
787- usage : this . buildPromptUsage ( sessionState . lastTokenUsage ) ,
788- _meta : this . buildQuotaMeta ( sessionState ) ,
789- } ;
782+ const interruptedResponse = await this . createInterruptedResponseIfNeeded ( params . sessionId , turnCompleted , sessionState ) ;
783+ if ( interruptedResponse ) {
784+ return interruptedResponse ;
790785 }
791786
792787 const error = eventHandler . getFailure ( )
@@ -795,11 +790,7 @@ export class CodexAcpServer implements acp.Agent {
795790 throw error ;
796791 }
797792
798- return {
799- stopReason : "end_turn" ,
800- usage : this . buildPromptUsage ( sessionState . lastTokenUsage ) ,
801- _meta : this . buildQuotaMeta ( sessionState ) ,
802- } ;
793+ return this . createPromptResponse ( "end_turn" , sessionState ) ;
803794 } catch ( err ) {
804795 logger . error ( `Prompt for session ${ params . sessionId } failed` , err ) ;
805796 throw err ;
@@ -835,6 +826,35 @@ export class CodexAcpServer implements acp.Agent {
835826 return toPromptUsage ( lastTokenUsage ) ;
836827 }
837828
829+ private async createInterruptedResponseIfNeeded (
830+ sessionId : string ,
831+ turnCompleted : TurnCompletedNotification ,
832+ sessionState : SessionState
833+ ) : Promise < acp . PromptResponse | null > {
834+ if ( turnCompleted . turn . status !== "interrupted" ) {
835+ return null ;
836+ }
837+ await this . connection . sessionUpdate ( {
838+ sessionId,
839+ update : {
840+ sessionUpdate : "agent_message_chunk" ,
841+ content : {
842+ type : "text" ,
843+ text : "*Conversation interrupted*"
844+ }
845+ }
846+ } ) ;
847+ return this . createPromptResponse ( "cancelled" , sessionState ) ;
848+ }
849+
850+ private createPromptResponse ( stopReason : acp . PromptResponse [ "stopReason" ] , sessionState : SessionState ) : acp . PromptResponse {
851+ return {
852+ stopReason,
853+ usage : this . buildPromptUsage ( sessionState . lastTokenUsage ) ,
854+ _meta : this . buildQuotaMeta ( sessionState ) ,
855+ } ;
856+ }
857+
838858 private async runWithProcessCheck < T > ( operation : ( ) => Promise < T > ) : Promise < T > {
839859 try {
840860 return await operation ( ) ;
0 commit comments