
























@@ -1,26 +1,28 @@
11import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry";
22import {
33normalizeModelCompat,
4-type ModelDefinitionConfig,
54type ModelProviderConfig,
65type 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 {
1517type CodexAppServerStartOptions,
1618readCodexPluginConfig,
1719resolveCodexAppServerRuntimeOptions,
1820} from "./src/app-server/config.js";
21+import type {
22+CodexAppServerModel,
23+CodexAppServerModelListResult,
24+} from "./src/app-server/models.js";
192520-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 = {
4244listModels?: CodexModelLister;
4345};
444645-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 {
7348return {
74-id: PROVIDER_ID,
49+id: CODEX_PROVIDER_ID,
7550label: "Codex",
7651docsPath: "/providers/models",
7752auth: [],
@@ -84,9 +59,15 @@ export function buildCodexProvider(options: BuildCodexProviderOptions = {}): Pro
8459listModels: options.listModels,
8560}),
8661},
62+staticCatalog: {
63+order: "late",
64+run: async () => ({
65+provider: buildCodexProviderConfig(FALLBACK_CODEX_MODELS),
66+}),
67+},
8768resolveDynamicModel: (ctx) => resolveCodexDynamicModel(ctx.modelId),
8869resolveSyntheticAuth: () => ({
89-apiKey: "codex-app-server",
70+apiKey: CODEX_APP_SERVER_AUTH_MARKER,
9071source: "codex-app-server",
9172mode: "token",
9273}),
@@ -115,22 +96,13 @@ export async function buildCodexProviderCatalog(
11596let discovered: CodexAppServerModel[] = [];
11697if (config.discovery?.enabled !== false && !shouldSkipLiveDiscovery(options.env)) {
11798discovered = await listModelsBestEffort({
118-listModels: options.listModels ?? listCodexAppServerModels,
99+listModels: options.listModels ?? listCodexAppServerModelsLazy,
119100 timeoutMs,
120101startOptions: appServer.start,
121102});
122103}
123-const models = (discovered.length > 0 ? discovered : FALLBACK_CODEX_MODELS).map(
124-codexModelToDefinition,
125-);
126104return {
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
140112return undefined;
141113}
142114return normalizeModelCompat({
143- ...buildModelDefinition({
115+ ...buildCodexModelDefinition({
144116 id,
145117model: id,
146118inputModalities: ["text", "image"],
147119supportedReasoningEfforts: shouldDefaultToReasoningModel(id) ? ["medium"] : [],
148120}),
149-provider: PROVIDER_ID,
121+provider: CODEX_PROVIDER_ID,
150122baseUrl: CODEX_BASE_URL,
151123} as ProviderRuntimeModel);
152124}
153125154-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: {
183127listModels: CodexModelLister;
184128timeoutMs: number;
@@ -197,6 +141,16 @@ async function listModelsBestEffort(params: {
197141}
198142}
199143144+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 {
201155return typeof value === "number" && Number.isFinite(value) && value > 0
202156 ? value
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。