11import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry" ;
22import {
33 normalizeModelCompat ,
4- type ModelDefinitionConfig ,
54 type ModelProviderConfig ,
65 type ProviderPlugin ,
76} from "openclaw/plugin-sdk/provider-model-shared" ;
8- import {
9- listCodexAppServerModels ,
10- type CodexAppServerModel ,
11- type CodexAppServerModelListResult ,
12- } from "./harness.js" ;
137import { resolveCodexSystemPromptContribution } from "./prompt-overlay.js" ;
8+ import {
9+ buildCodexModelDefinition ,
10+ buildCodexProviderConfig ,
11+ CODEX_APP_SERVER_AUTH_MARKER ,
12+ CODEX_BASE_URL ,
13+ CODEX_PROVIDER_ID ,
14+ FALLBACK_CODEX_MODELS ,
15+ } from "./provider-catalog.js" ;
1416import {
1517 type CodexAppServerStartOptions ,
1618 readCodexPluginConfig ,
1719 resolveCodexAppServerRuntimeOptions ,
1820} from "./src/app-server/config.js" ;
21+ import type {
22+ CodexAppServerModel ,
23+ CodexAppServerModelListResult ,
24+ } from "./src/app-server/models.js" ;
1925
20- const PROVIDER_ID = "codex" ;
21- const CODEX_BASE_URL = "https://chatgpt.com/backend-api" ;
22- const DEFAULT_CONTEXT_WINDOW = 272_000 ;
23- const DEFAULT_MAX_TOKENS = 128_000 ;
2426const DEFAULT_DISCOVERY_TIMEOUT_MS = 2500 ;
2527const LIVE_DISCOVERY_ENV = "OPENCLAW_CODEX_DISCOVERY_LIVE" ;
2628
@@ -42,36 +44,9 @@ type BuildCatalogOptions = {
4244 listModels ?: CodexModelLister ;
4345} ;
4446
45- const FALLBACK_CODEX_MODELS = [
46- {
47- id : "gpt-5.4" ,
48- model : "gpt-5.4" ,
49- displayName : "gpt-5.4" ,
50- description : "Latest frontier agentic coding model." ,
51- isDefault : true ,
52- inputModalities : [ "text" , "image" ] ,
53- supportedReasoningEfforts : [ "low" , "medium" , "high" , "xhigh" ] ,
54- } ,
55- {
56- id : "gpt-5.4-mini" ,
57- model : "gpt-5.4-mini" ,
58- displayName : "GPT-5.4-Mini" ,
59- description : "Smaller frontier agentic coding model." ,
60- inputModalities : [ "text" , "image" ] ,
61- supportedReasoningEfforts : [ "low" , "medium" , "high" , "xhigh" ] ,
62- } ,
63- {
64- id : "gpt-5.2" ,
65- model : "gpt-5.2" ,
66- displayName : "gpt-5.2" ,
67- inputModalities : [ "text" , "image" ] ,
68- supportedReasoningEfforts : [ "low" , "medium" , "high" , "xhigh" ] ,
69- } ,
70- ] satisfies CodexAppServerModel [ ] ;
71-
7247export function buildCodexProvider ( options : BuildCodexProviderOptions = { } ) : ProviderPlugin {
7348 return {
74- id : PROVIDER_ID ,
49+ id : CODEX_PROVIDER_ID ,
7550 label : "Codex" ,
7651 docsPath : "/providers/models" ,
7752 auth : [ ] ,
@@ -84,9 +59,15 @@ export function buildCodexProvider(options: BuildCodexProviderOptions = {}): Pro
8459 listModels : options . listModels ,
8560 } ) ,
8661 } ,
62+ staticCatalog : {
63+ order : "late" ,
64+ run : async ( ) => ( {
65+ provider : buildCodexProviderConfig ( FALLBACK_CODEX_MODELS ) ,
66+ } ) ,
67+ } ,
8768 resolveDynamicModel : ( ctx ) => resolveCodexDynamicModel ( ctx . modelId ) ,
8869 resolveSyntheticAuth : ( ) => ( {
89- apiKey : "codex-app-server" ,
70+ apiKey : CODEX_APP_SERVER_AUTH_MARKER ,
9071 source : "codex-app-server" ,
9172 mode : "token" ,
9273 } ) ,
@@ -115,22 +96,13 @@ export async function buildCodexProviderCatalog(
11596 let discovered : CodexAppServerModel [ ] = [ ] ;
11697 if ( config . discovery ?. enabled !== false && ! shouldSkipLiveDiscovery ( options . env ) ) {
11798 discovered = await listModelsBestEffort ( {
118- listModels : options . listModels ?? listCodexAppServerModels ,
99+ listModels : options . listModels ?? listCodexAppServerModelsLazy ,
119100 timeoutMs,
120101 startOptions : appServer . start ,
121102 } ) ;
122103 }
123- const models = ( discovered . length > 0 ? discovered : FALLBACK_CODEX_MODELS ) . map (
124- codexModelToDefinition ,
125- ) ;
126104 return {
127- provider : {
128- baseUrl : CODEX_BASE_URL ,
129- apiKey : "codex-app-server" ,
130- auth : "token" ,
131- api : "openai-codex-responses" ,
132- models,
133- } ,
105+ provider : buildCodexProviderConfig ( discovered . length > 0 ? discovered : FALLBACK_CODEX_MODELS ) ,
134106 } ;
135107}
136108
@@ -140,45 +112,17 @@ function resolveCodexDynamicModel(modelId: string): ProviderRuntimeModel | undef
140112 return undefined ;
141113 }
142114 return normalizeModelCompat ( {
143- ...buildModelDefinition ( {
115+ ...buildCodexModelDefinition ( {
144116 id,
145117 model : id ,
146118 inputModalities : [ "text" , "image" ] ,
147119 supportedReasoningEfforts : shouldDefaultToReasoningModel ( id ) ? [ "medium" ] : [ ] ,
148120 } ) ,
149- provider : PROVIDER_ID ,
121+ provider : CODEX_PROVIDER_ID ,
150122 baseUrl : CODEX_BASE_URL ,
151123 } as ProviderRuntimeModel ) ;
152124}
153125
154- function codexModelToDefinition ( model : CodexAppServerModel ) : ModelDefinitionConfig {
155- return buildModelDefinition ( model ) ;
156- }
157-
158- function buildModelDefinition ( model : {
159- id : string ;
160- model : string ;
161- displayName ?: string ;
162- inputModalities : string [ ] ;
163- supportedReasoningEfforts : string [ ] ;
164- } ) : ModelDefinitionConfig {
165- const id = model . id . trim ( ) || model . model . trim ( ) ;
166- return {
167- id,
168- name : model . displayName ?. trim ( ) || id ,
169- api : "openai-codex-responses" ,
170- reasoning : model . supportedReasoningEfforts . length > 0 || shouldDefaultToReasoningModel ( id ) ,
171- input : model . inputModalities . includes ( "image" ) ? [ "text" , "image" ] : [ "text" ] ,
172- cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
173- contextWindow : DEFAULT_CONTEXT_WINDOW ,
174- maxTokens : DEFAULT_MAX_TOKENS ,
175- compat : {
176- supportsReasoningEffort : model . supportedReasoningEfforts . length > 0 ,
177- supportsUsageInStreaming : true ,
178- } ,
179- } ;
180- }
181-
182126async function listModelsBestEffort ( params : {
183127 listModels : CodexModelLister ;
184128 timeoutMs : number ;
@@ -197,6 +141,16 @@ async function listModelsBestEffort(params: {
197141 }
198142}
199143
144+ async function listCodexAppServerModelsLazy ( options : {
145+ timeoutMs : number ;
146+ limit ?: number ;
147+ startOptions ?: CodexAppServerStartOptions ;
148+ sharedClient ?: boolean ;
149+ } ) : Promise < CodexAppServerModelListResult > {
150+ const { listCodexAppServerModels } = await import ( "./src/app-server/models.js" ) ;
151+ return listCodexAppServerModels ( options ) ;
152+ }
153+
200154function normalizeTimeoutMs ( value : unknown ) : number {
201155 return typeof value === "number" && Number . isFinite ( value ) && value > 0
202156 ? value
0 commit comments