import type { BackendProfile, JsonRecord } from "./types.js"; export interface BackendProfileSpec { profile: BackendProfile; backendKind: "codex-app-server-stdio"; protocol: "codex-app-server-jsonrpc-stdio"; transport: "stdio"; command: "codex app-server --listen stdio://"; status: "registered"; requiredSecretKeys: ["auth.json", "config.toml"]; defaultSecretName: string; profileIsolation: "profile-scoped-codex-home"; description: string; } export const backendProfileSpecs: readonly BackendProfileSpec[] = [ { profile: "codex", backendKind: "codex-app-server-stdio", protocol: "codex-app-server-jsonrpc-stdio", transport: "stdio", command: "codex app-server --listen stdio://", status: "registered", requiredSecretKeys: ["auth.json", "config.toml"], defaultSecretName: "agentrun-v01-provider-codex", profileIsolation: "profile-scoped-codex-home", description: "Default Codex-compatible profile", }, { profile: "deepseek", backendKind: "codex-app-server-stdio", protocol: "codex-app-server-jsonrpc-stdio", transport: "stdio", command: "codex app-server --listen stdio://", status: "registered", requiredSecretKeys: ["auth.json", "config.toml"], defaultSecretName: "agentrun-v01-provider-deepseek", profileIsolation: "profile-scoped-codex-home", description: "DeepSeek-compatible profile through Codex app-server stdio", }, { profile: "minimax-m3", backendKind: "codex-app-server-stdio", protocol: "codex-app-server-jsonrpc-stdio", transport: "stdio", command: "codex app-server --listen stdio://", status: "registered", requiredSecretKeys: ["auth.json", "config.toml"], defaultSecretName: "agentrun-v01-provider-minimax-m3", profileIsolation: "profile-scoped-codex-home", description: "MiniMax M3 OpenAI-compatible profile through Codex app-server stdio", }, ]; export const backendProfiles = backendProfileSpecs.map((item) => item.profile) as readonly BackendProfile[]; export function backendProfileSpec(profile: string): BackendProfileSpec | null { return backendProfileSpecs.find((item) => item.profile === profile) ?? null; } export function isBackendProfile(value: string): value is BackendProfile { return backendProfileSpec(value) !== null; } export function backendCapability(spec: BackendProfileSpec): JsonRecord { const defaultSecretRef = { name: spec.defaultSecretName, keys: [...spec.requiredSecretKeys], valuesPrinted: false }; return { profile: spec.profile, backendKind: spec.backendKind, protocol: spec.protocol, transport: spec.transport, command: spec.command, status: spec.status, requiredSecretKeys: [...spec.requiredSecretKeys], defaultSecretRef, preflight: { readiness: "requires-profile-secret-ref", defaultSecretRef, requiredSecretKeys: [...spec.requiredSecretKeys], profileIsolation: spec.profileIsolation, credentialValuesPrinted: false, valuesPrinted: false, }, profileIsolation: spec.profileIsolation, description: spec.description, }; } export function mergeBackendCapability(profile: string, storedCapabilities: JsonRecord): JsonRecord { const spec = backendProfileSpec(profile); if (!spec) return { profile, ...storedCapabilities, valuesPrinted: false }; const base = backendCapability(spec); return { ...base, ...storedCapabilities, defaultSecretRef: base.defaultSecretRef, preflight: base.preflight, }; } export function backendCapabilities(): JsonRecord[] { return backendProfileSpecs.map(backendCapability); } export function backendCapabilitiesSqlValues(profiles?: readonly BackendProfile[]): string { const specs = profiles ? profiles.map((profile) => { const spec = backendProfileSpec(profile); if (!spec) throw new Error(`unknown backend profile for SQL seed: ${profile}`); return spec; }) : backendProfileSpecs; return specs.map((spec) => { const capabilities = JSON.stringify({ backendKind: spec.backendKind, protocol: spec.protocol, transport: spec.transport, command: spec.command, requiredSecretKeys: spec.requiredSecretKeys, defaultSecretRef: { name: spec.defaultSecretName, keys: spec.requiredSecretKeys }, profileIsolation: spec.profileIsolation, description: spec.description, }); return `('${sqlString(spec.profile)}', '${sqlString(capabilities)}'::jsonb, '{"mode":"manual-runner-v0.1"}'::jsonb, '{"status":"${sqlString(spec.status)}"}'::jsonb, now())`; }).join(",\n"); } function sqlString(value: string): string { return value.replace(/'/gu, "''"); }