11import * as acp from "@agentclientprotocol/sdk" ;
2- import type { MessageConnection } from "vscode-jsonrpc/node" ;
3- import { CodexClient } from "./CodexClient" ;
42import { CodexEventHandler } from "./CodexEventHandler" ;
5- import type { JsonValue } from "./app-server/serde_json/JsonValue" ;
6- import { CodexAuthMethods , type CodexAuthRequest , isCodexAuthRequest } from "./CodexAuthMethod" ;
3+ import { CodexAuthMethods , type CodexAuthRequest } from "./CodexAuthMethod" ;
74import { RequestError } from "@agentclientprotocol/sdk" ;
5+ import { CodexAcpClient } from "./CodexAcpClient" ;
86
97
108export interface SessionState {
119 sessionId : string ,
12- seenReasoningDeltas : boolean ;
1310 pendingPrompt : AbortController | null ;
1411}
1512
1613export class CodexACPAgent implements acp . Agent {
17- private readonly name : string = "codex-appserver-acp" ;
18- private readonly version : string = "0.1.0" ;
19- private readonly title : string = "Codex ACP" ;
20-
21- private readonly codexClient : CodexClient ;
14+ private readonly codexAcpClient : CodexAcpClient ;
2215 private readonly connection : acp . AgentSideConnection ;
23- private readonly config : JsonObject | null ;
24- private readonly modelProvider : string | null ;
2516 private readonly defaultAuthRequest : CodexAuthRequest | null ;
2617
2718 private readonly sessions : Map < string , SessionState > ;
2819
2920 constructor (
3021 connection : acp . AgentSideConnection ,
31- codexConnection : MessageConnection ,
32- codexConfig ?: JsonObject ,
33- modelProvider ?: string ,
22+ codexAcpClient : CodexAcpClient ,
3423 defaultAuthRequest ?: CodexAuthRequest ,
3524 ) {
3625 this . sessions = new Map ( ) ;
37- this . codexClient = new CodexClient ( codexConnection ) ;
3826 this . connection = connection ;
39- this . config = codexConfig ?? null ;
40- this . modelProvider = modelProvider ?? null ;
4127 this . defaultAuthRequest = defaultAuthRequest ?? null ;
28+ this . codexAcpClient = codexAcpClient ;
4229 }
4330
4431 async initialize (
4532 _params : acp . InitializeRequest ,
4633 ) : Promise < acp . InitializeResponse > {
47- await this . codexClient . initialize ( {
48- clientInfo : {
49- name : _params . clientInfo ?. name ?? this . name ,
50- version : _params . clientInfo ?. version ?? this . version ,
51- title : _params . clientInfo ?. title ?? this . title ,
52- }
53- } ) ;
34+ await this . codexAcpClient . initialize ( _params ) ;
5435 return {
5536 protocolVersion : acp . PROTOCOL_VERSION ,
5637 agentCapabilities : {
@@ -63,53 +44,30 @@ export class CodexACPAgent implements acp.Agent {
6344 async newSession (
6445 _params : acp . NewSessionRequest ,
6546 ) : Promise < acp . NewSessionResponse > {
66- if ( ! await this . codexClient . loginStatus ( ) ) {
47+ if ( await this . codexAcpClient . authRequired ( ) ) {
6748 if ( this . defaultAuthRequest ) {
6849 await this . authenticate ( this . defaultAuthRequest )
6950 } else {
7051 throw RequestError . authRequired ( ) ;
7152 }
7253 }
7354
74- const threadStartResponse = await this . codexClient . threadStart ( {
75- config : this . config ,
76- modelProvider : this . modelProvider ,
77- model : null ,
78- cwd : _params . cwd ,
79- approvalPolicy : "never" ,
80- sandbox : null ,
81- baseInstructions : null ,
82- developerInstructions : null ,
83- } )
84-
85- const sessionId = threadStartResponse . thread . id ;
55+ const sessionId = await this . codexAcpClient . newSession ( _params ) ;
8656 this . sessions . set ( sessionId , {
8757 sessionId : sessionId ,
88- seenReasoningDeltas : false ,
8958 pendingPrompt : null ,
9059 } ) ;
9160
9261 return {
93- sessionId,
62+ sessionId : sessionId ,
9463 } ;
9564 }
9665
9766 async authenticate (
9867 _params : acp . AuthenticateRequest ,
9968 ) : Promise < acp . AuthenticateResponse > {
100- if ( ! isCodexAuthRequest ( _params ) ) {
101- throw RequestError . invalidRequest ( ) ;
102- }
103- let authResult : Boolean ;
104- switch ( _params . methodId ) {
105- case "api-key" :
106- authResult = await this . codexClient . loginWithApiKey ( _params . _meta . apiKey ) ;
107- break ;
108- case "chat-gpt" :
109- authResult = await this . codexClient . loginWithChatGpt ( ) ;
110- break ;
111- }
112- if ( ! authResult ) {
69+ const isAuthenticated = await this . codexAcpClient . authenticate ( _params ) ;
70+ if ( ! isAuthenticated ) {
11371 throw RequestError . invalidParams ( ) ;
11472 }
11573 return { } ;
@@ -131,12 +89,9 @@ export class CodexACPAgent implements acp.Agent {
13189 sessionState . pendingPrompt ?. abort ( ) ;
13290 sessionState . pendingPrompt = new AbortController ( ) ;
13391
134- const prompt = params . prompt . filter ( b => b . type === "text" )
135- . map ( b => b . text )
136- . join ( " " ) ;
137-
13892 try {
139- await this . processMessage ( sessionState , prompt ) ;
93+ const messageHandler = new CodexEventHandler ( this . connection , sessionState ) ;
94+ await this . codexAcpClient . sendPrompt ( params , ( event ) => messageHandler . handleNotification ( event ) ) ;
14095 } catch ( err ) {
14196 if ( sessionState . pendingPrompt . signal . aborted ) {
14297 return { stopReason : "cancelled" } ;
@@ -152,35 +107,8 @@ export class CodexACPAgent implements acp.Agent {
152107 } ;
153108 }
154109
155- private async processMessage (
156- sessionState : SessionState ,
157- prompt : string
158- ) : Promise < void > {
159- const messageHandler = new CodexEventHandler ( this . connection , sessionState ) ;
160-
161- this . codexClient . onServerNotification ( notification => {
162- messageHandler . handleNotification ( notification ) ;
163- } ) ;
164-
165- await this . codexClient . turnStart ( {
166- threadId : sessionState . sessionId ,
167- input : [ { type : "text" , text : prompt } ] ,
168- approvalPolicy : null ,
169- sandboxPolicy : null ,
170- summary : null ,
171- cwd : null ,
172- effort : null ,
173- model : null ,
174- } )
175-
176- await this . codexClient . waitForCompletion ( )
177- }
178-
179110 async cancel ( params : acp . CancelNotification ) : Promise < void > {
180111 //TODO not supported yet
181- await this . codexClient . close ( )
182112 this . sessions . get ( params . sessionId ) ?. pendingPrompt ?. abort ( ) ;
183113 }
184- }
185-
186- export type JsonObject = { [ key in string ] ?: JsonValue }
114+ }
0 commit comments