import { spawnSync } from "node:child_process";
import {
cpSync,
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { z } from "zod";
const MessageSchema = z.object({
role: z.enum(["system", "user", "assistant"]),
content: z.string(),
});
const RequestSchema = z.object({
version: z.literal("v1"),
model: z.string().min(1),
temperature: z.number().optional(),
maxOutputTokens: z.number().int().positive().optional(),
messages: z.array(MessageSchema).min(1),
metadata: z
.object({
queryId: z.string().optional(),
mode: z.string().optional(),
runKind: z.enum(["cold", "warm"]).optional(),
tokenBudget: z.number().int().positive().optional(),
projectPath: z.string().optional(),
})
.optional(),
});
function readStdin(): string {
return readFileSync(0, "utf-8");
}
function parseBoolEnv(name: string, fallback: boolean): boolean {
const raw = process.env[name];
if (!raw) return fallback;
const normalized = raw.trim().toLowerCase();
if (normalized === "true") return true;
if (normalized === "false") return false;
return fallback;
}
function buildPrompt(
messages: Array<{ role: string; content: string }>,
): string {
return messages
.map((message) => {
const role = message.role.toUpperCase();
return `[${role}]\n${message.content.trim()}`;
})
.join("\n\n");
}
function parseCodexJsonl(stdout: string): {
outputText: string;
inputTokens: number;
outputTokens: number;
} {
const lines = stdout
.split("\n")
.map((line) => line.trim())
.filter(Boolean);
let outputText = "";
let inputTokens = 0;
let outputTokens = 0;
for (const line of lines) {
let parsed: unknown;
try {
parsed = JSON.parse(line) as unknown;
} catch {
continue;
}
if (!parsed || typeof parsed !== "object") continue;
const event = parsed as Record<string, unknown>;
const type = event.type;
if (type === "item.completed") {
const item = event.item;
if (!item || typeof item !== "object") continue;
const itemType = (item as Record<string, unknown>).type;
const text = (item as Record<string, unknown>).text;
if (itemType === "agent_message" && typeof text === "string") {
outputText = text;
}
} else if (type === "turn.completed") {
const usage = event.usage;
if (!usage || typeof usage !== "object") continue;
const inTok = (usage as Record<string, unknown>).input_tokens;
const outTok = (usage as Record<string, unknown>).output_tokens;
if (typeof inTok === "number" && Number.isFinite(inTok)) {
inputTokens = Math.max(0, Math.floor(inTok));
}
if (typeof outTok === "number" && Number.isFinite(outTok)) {
outputTokens = Math.max(0, Math.floor(outTok));
}
}
}
if (!outputText) {
throw new Error("Codex output did not include an agent_message text.");
}
if (inputTokens <= 0 && outputTokens <= 0) {
throw new Error("Codex output did not include usage tokens.");
}
return { outputText, inputTokens, outputTokens };
}
function toTomlString(value: string): string {
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
}
function parseArgsFromEnv(
value: string | undefined,
fallback: string[],
): string[] {
if (!value || !value.trim()) return fallback;
const trimmed = value.trim();
try {
const parsed = JSON.parse(trimmed) as unknown;
if (Array.isArray(parsed)) {
const items = parsed
.map((item) => (typeof item === "string" ? item : String(item ?? "")))
.filter((item) => item.length > 0);
if (items.length > 0) {
return items;
}
}
} catch {
// fall through to CSV parsing
}
const csv = trimmed
.split(",")
.map((item) => item.trim())
.filter(Boolean);
return csv.length > 0 ? csv : fallback;
}
function parseReasoningEffortFromEnv(): string {
const raw = (process.env.DOCLEA_CODEX_REASONING_EFFORT ?? "high")
.trim()
.toLowerCase();
if (raw === "minimal") return "minimal";
if (raw === "low") return "low";
if (raw === "medium") return "medium";
if (raw === "high") return "high";
if (raw === "xhigh") return "xhigh";
return "high";
}
function createIsolatedCodexHome(input: {
model: string;
useDocleaMcp: boolean;
projectPath: string | null;
}): {
rootPath: string;
homePath: string;
} {
const tempRoot = resolve(process.env.DOCLEA_CODEX_TEMP_ROOT ?? tmpdir());
const rootPath = mkdtempSync(join(tempRoot, "codex-bench-"));
const homePath = rootPath;
const codexPath = join(homePath, ".codex");
mkdirSync(codexPath, { recursive: true });
const authHome = resolve(
process.env.DOCLEA_CODEX_AUTH_HOME ?? process.env.HOME ?? "~",
);
const sourceCodexPath = join(authHome, ".codex");
for (const fileName of ["auth.json", ".credentials.json"]) {
const source = join(sourceCodexPath, fileName);
const target = join(codexPath, fileName);
if (existsSync(source)) {
cpSync(source, target);
}
}
const lines: string[] = [
`model = ${toTomlString(input.model)}`,
`model_reasoning_effort = ${toTomlString(parseReasoningEffortFromEnv())}`,
];
if (input.useDocleaMcp) {
const docleaCommand = (
process.env.DOCLEA_CODEX_DOCLEA_SERVER_COMMAND ?? "bun"
).trim();
const docleaArgs = parseArgsFromEnv(
process.env.DOCLEA_CODEX_DOCLEA_SERVER_ARGS,
["run", "/home/pho7on/Work/doclea/mcp/src/index.ts"],
);
const docleaCwd = (
process.env.DOCLEA_CODEX_DOCLEA_SERVER_CWD ??
input.projectPath ??
"/home/pho7on/Work/doclea/mcp"
).trim();
lines.push("", "[mcp_servers.doclea]");
lines.push(`command = ${toTomlString(docleaCommand)}`);
lines.push(`args = [${docleaArgs.map(toTomlString).join(", ")}]`);
lines.push(`cwd = ${toTomlString(docleaCwd)}`);
}
writeFileSync(
join(codexPath, "config.toml"),
`${lines.join("\n")}\n`,
"utf-8",
);
return { rootPath, homePath };
}
function main(): void {
const raw = readStdin();
const request = RequestSchema.parse(JSON.parse(raw));
const prompt = buildPrompt(request.messages);
const model = request.model.trim();
const mode = (request.metadata?.mode ?? "").trim().toLowerCase();
const projectPath = request.metadata?.projectPath?.trim() || null;
const useIsolatedConfig = parseBoolEnv(
"DOCLEA_CODEX_USE_ISOLATED_CONFIG",
false,
);
const forceDocleaMcp = parseBoolEnv("DOCLEA_CODEX_FORCE_DOCLEA_MCP", false);
const disableDocleaMcp = parseBoolEnv(
"DOCLEA_CODEX_DISABLE_DOCLEA_MCP",
false,
);
const modeUsesDoclea = mode === "mcp_full" || mode === "mcp_hybrid_guardrail";
const useDocleaMcp = !disableDocleaMcp && (forceDocleaMcp || modeUsesDoclea);
let isolatedHomeRoot: string | null = null;
let isolatedHomePath: string | null = null;
if (useIsolatedConfig) {
const isolated = createIsolatedCodexHome({
model,
useDocleaMcp,
projectPath,
});
isolatedHomeRoot = isolated.rootPath;
isolatedHomePath = isolated.homePath;
}
try {
const args = [
"exec",
"--json",
"--sandbox",
"read-only",
"--skip-git-repo-check",
"--model",
model,
];
if (projectPath) {
args.push("--cd", projectPath);
}
args.push(prompt);
const run = spawnSync("codex", args, {
encoding: "utf-8",
maxBuffer: 32 * 1024 * 1024,
...(isolatedHomePath
? {
env: {
...process.env,
HOME: isolatedHomePath,
},
}
: {}),
});
if (run.error) {
throw new Error(`Failed to execute codex CLI: ${run.error.message}`);
}
if (run.status !== 0) {
throw new Error(
`codex CLI exited with status ${run.status}.\nstderr:\n${run.stderr ?? ""}\nstdout:\n${run.stdout ?? ""}`,
);
}
const parsed = parseCodexJsonl(run.stdout ?? "");
const response = {
outputText: parsed.outputText,
usage: {
inputTokens: parsed.inputTokens,
outputTokens: parsed.outputTokens,
},
};
process.stdout.write(`${JSON.stringify(response)}\n`);
} finally {
if (isolatedHomeRoot) {
rmSync(isolatedHomeRoot, { recursive: true, force: true });
}
}
}
main();