11import * as acp from "@agentclientprotocol/sdk" ;
22import { CodexEventHandler } from "./CodexEventHandler" ;
33import { CodexAuthMethods , type CodexAuthRequest } from "./CodexAuthMethod" ;
4- import { RequestError } from "@agentclientprotocol/sdk" ;
5- import { CodexAcpClient } from "./CodexAcpClient" ;
4+ import { type ModelInfo , RequestError , type SessionModelState } from "@agentclientprotocol/sdk" ;
5+ import { CodexAcpClient , type SessionMetadata } from "./CodexAcpClient" ;
6+ import type { Model } from "./app-server/v2" ;
7+ import type { ReasoningEffort } from "./app-server" ;
8+ import { ModelId } from "./ModelId" ;
69
710
811export interface SessionState {
9- sessionId : string ,
12+ sessionMetadata : SessionMetadata ;
1013 pendingPrompt : AbortController | null ;
1114}
1215
@@ -52,14 +55,21 @@ export class CodexAcpServer implements acp.Agent {
5255 }
5356 }
5457
55- const sessionId = await this . codexAcpClient . newSession ( _params ) ;
58+ const sessionMetadata = await this . codexAcpClient . newSession ( _params ) ;
59+ const { sessionId, currentModelId, models} = sessionMetadata ;
5660 this . sessions . set ( sessionId , {
57- sessionId : sessionId ,
58- pendingPrompt : null ,
61+ sessionMetadata : sessionMetadata ,
62+ pendingPrompt : null
5963 } ) ;
6064
65+ const availableModels = this . buildAvailableModels ( models ) ;
66+ const sessionModelState : SessionModelState = {
67+ availableModels : availableModels ,
68+ currentModelId : currentModelId ,
69+ }
6170 return {
6271 sessionId : sessionId ,
72+ models : sessionModelState ,
6373 } ;
6474 }
6575
@@ -80,6 +90,55 @@ export class CodexAcpServer implements acp.Agent {
8090 return { } ;
8191 }
8292
93+ async setSessionModel ( params : acp . SetSessionModelRequest ) : Promise < acp . SetSessionModelResponse > {
94+ const sessionState = this . sessions . get ( params . sessionId ) ;
95+ if ( ! sessionState ) throw new Error ( `Session ${ params . sessionId } not found` ) ;
96+
97+ const requestedModelId = ModelId . fromString ( params . modelId ) ;
98+ const requestedModelName = requestedModelId . model ;
99+ const requestedEffort = requestedModelId . effort ;
100+
101+ const model = sessionState . sessionMetadata . models . find ( m => m . id === requestedModelName ) ;
102+ if ( ! model ) throw new Error ( `Unknown model ${ params . modelId } ` ) ;
103+
104+ const requestedEffortValue = requestedEffort as ReasoningEffort | undefined ;
105+ let reasoningEffort : ReasoningEffort ;
106+ if ( requestedEffortValue ) {
107+ const matchedEffort = model . supportedReasoningEfforts . find (
108+ ( option ) => option . reasoningEffort === requestedEffortValue
109+ ) ?. reasoningEffort ;
110+
111+ if ( ! matchedEffort ) {
112+ throw new Error ( `Unsupported reasoning effort ${ requestedEffortValue } for model ${ requestedModelName } ` ) ;
113+ }
114+
115+ reasoningEffort = matchedEffort ;
116+ } else {
117+ reasoningEffort = model . defaultReasoningEffort ;
118+ }
119+
120+
121+ await this . codexAcpClient . setModel ( {
122+ model : model . model ,
123+ reasoningEffort,
124+ } ) ;
125+ sessionState . sessionMetadata . currentModelId = ModelId . fromComponents ( model , reasoningEffort ) . toString ( ) ;
126+
127+ return { } ;
128+ }
129+
130+
131+
132+ private buildAvailableModels ( models : Model [ ] ) : ModelInfo [ ] {
133+ return models . flatMap ( ( model ) =>
134+ model . supportedReasoningEfforts . map ( ( effort ) => ( {
135+ modelId : ModelId . fromComponents ( model , effort . reasoningEffort ) . toString ( ) ,
136+ name : `${ model . displayName } (${ effort . reasoningEffort } )` ,
137+ description : `${ model . description } ${ effort . description } ` ,
138+ } ) )
139+ ) ;
140+ }
141+
83142 getSessionState ( sessionId : string ) : SessionState {
84143 const sessionState = this . sessions . get ( sessionId ) ;
85144 if ( ! sessionState ) {
0 commit comments