Files
sub2api/frontend/src/api/codex.ts
T
Long Li 22e1b8144a feat(gateway): expose routed Codex model catalogs
Codex model discovery expects a top-level models manifest, but Composite and other non-OpenAI groups either reached the OpenAI live-manifest handler or had no Codex-specific response at all. API key users also had no supported way to fetch that manifest and reference it from config.toml.

Generate minimal manifests from each group's effective model list while preserving the official OpenAI live path and the ordinary /models response. Add the Use Key flow for authenticated catalog download and model_catalog_json configuration without writing the API key into the downloaded file.
2026-08-22 14:43:40 +09:00

57 lines
1.6 KiB
TypeScript

export interface CodexModelsManifestResult {
content: string
modelCount: number
}
const DEFAULT_CODEX_CLIENT_VERSION = '0.147.0'
function normalizeCodexBaseUrl(baseUrl: string): string {
const fallback = typeof window !== 'undefined' ? window.location.origin : ''
const value = (baseUrl || fallback).trim().replace(/\/+$/, '')
if (!value) return '/v1'
return /\/v1$/i.test(value) ? value : `${value}/v1`
}
export function buildCodexModelsManifestUrl(
baseUrl: string,
clientVersion = DEFAULT_CODEX_CLIENT_VERSION
): string {
const url = normalizeCodexBaseUrl(baseUrl)
const params = new URLSearchParams({ client_version: clientVersion })
return `${url}/models?${params.toString()}`
}
function isCodexModelsManifest(value: unknown): value is { models: unknown[] } {
return typeof value === 'object' && value !== null && Array.isArray((value as { models?: unknown }).models)
}
export async function fetchCodexModelsManifest(
baseUrl: string,
apiKey: string,
signal?: AbortSignal
): Promise<CodexModelsManifestResult> {
const response = await fetch(buildCodexModelsManifestUrl(baseUrl), {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${apiKey}`
},
cache: 'no-store',
signal
})
if (!response.ok) {
throw new Error(`Codex models request failed with status ${response.status}`)
}
const payload: unknown = await response.json()
if (!isCodexModelsManifest(payload)) {
throw new Error('Codex models response is not a valid manifest')
}
return {
content: JSON.stringify(payload, null, 2),
modelCount: payload.models.length
}
}