/** * Codex adapter: reads `~/.codex/config.toml` ([mcp_servers]) and `~/.codex/prompts`. */ import * as path from "node:path"; import { TOML } from "bun"; import type { AdapterResult, McpCandidate, SourceDiagnostic } from "../types"; import { type Adapter, type AdapterOptions, collectMarkdownPrompts, readSourceText } from "./index"; const SOURCE = "codex" as const; function parseToml( text: string, filePath: string, ): { data: Record } | { diagnostic: SourceDiagnostic } { try { const data = TOML.parse(text) as unknown; if (typeof data !== "object" || data === null) { return { diagnostic: { source: SOURCE, type: "mcp", status: "failed_invalid_source", message: `${filePath} is not a TOML table`, }, }; } return { data: data as Record }; } catch (error) { return { diagnostic: { source: SOURCE, type: "mcp", status: "failed_invalid_source", message: `invalid TOML in ${filePath}: ${(error as Error).message}`, }, }; } } export const codexAdapter: Adapter = { source: SOURCE, async collect({ homeDir }: AdapterOptions): Promise { const result: AdapterResult = { mcpCandidates: [], skillCandidates: [], diagnostics: [] }; const configPath = path.join(homeDir, ".codex", "config.toml"); const read = await readSourceText(configPath, SOURCE, "mcp"); if ("diagnostic" in read) { result.diagnostics.push(read.diagnostic); } else { const parsed = parseToml(read.text, configPath); if ("diagnostic" in parsed) { result.diagnostics.push(parsed.diagnostic); } else { const servers = parsed.data.mcp_servers; if (servers && typeof servers === "object" && !Array.isArray(servers)) { for (const [name, raw] of Object.entries(servers as Record)) { result.mcpCandidates.push({ source: SOURCE, name, raw } satisfies McpCandidate); } } } } const prompts = await collectMarkdownPrompts(path.join(homeDir, ".codex", "prompts"), SOURCE); result.skillCandidates.push(...prompts.candidates); result.diagnostics.push(...prompts.diagnostics); return result; }, };