UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

155 lines (154 loc) 4.74 kB
import { c as isRecord } from "../../record-coerce-DItp3I4t.js"; import { l as normalizeOptionalString } from "../../string-coerce-CIXf7egm.js"; import { n as signalProcessTree } from "../../kill-tree-CR2oLt9D.js"; import { a as resolveWindowsSpawnProgram, r as materializeWindowsSpawnProgram } from "../../windows-spawn-oyE-2b7Z.js"; import "../../string-coerce-runtime-GQa0ehRA.js"; import "../../process-runtime-pcN9RjT8.js"; import { spawn } from "node:child_process"; //#region extensions/openai/package.json var version = "2026.9.2"; //#endregion //#region extensions/openai/cli-auth-api.ts function projectCodexCliAccount(response) { const account = response.account; if (account === null && typeof response.requiresOpenaiAuth === "boolean") return { type: "none", requiresOpenaiAuth: response.requiresOpenaiAuth }; if (!isRecord(account) || typeof account.type !== "string") return null; if (account.type === "apiKey") return { type: "apiKey" }; if (account.type !== "chatgpt") return { type: "unknown" }; const email = normalizeOptionalString(account.email); return { type: "chatgpt", ...email && email.length <= 320 && !/[\r\n]/u.test(email) ? { email } : {} }; } /** Reads the native account before setup has installed a harness or configured an agent. */ async function readCodexCliAccount(params) { const env = params.env ?? process.env; if (env !== process.env && !env.CODEX_HOME?.trim() && (process.platform === "win32" || !env.HOME?.trim())) return null; try { const program = resolveWindowsSpawnProgram({ command: params.command, env, packageName: "@openai/codex" }); const invocation = materializeWindowsSpawnProgram(program, [ "app-server", "--listen", "stdio://" ]); const detached = process.platform !== "win32"; const child = spawn(invocation.command, invocation.argv, { env, detached, stdio: [ "pipe", "pipe", "ignore" ], shell: invocation.shell, windowsHide: invocation.windowsHide ?? true }); return await new Promise((resolve) => { let phase = "initialize"; let result = null; let output = ""; let outputBytes = 0; let cleanupTimer; const finish = () => { if (phase === "closed") return; phase = "closed"; clearTimeout(timer); clearTimeout(cleanupTimer); const complete = () => { if (!detached && child.exitCode === null && child.signalCode === null) child.kill("SIGKILL"); child.stdin.destroy(); child.stdout.destroy(); child.unref(); resolve(result); }; if (child.pid && (detached || child.exitCode === null && child.signalCode === null)) signalProcessTree(child.pid, "SIGKILL", { detached, onComplete: complete }); else complete(); }; const stop = (account) => { if (phase === "closing" || phase === "closed") return; phase = "closing"; result = account; output = ""; if (!detached || !child.pid) { finish(); return; } signalProcessTree(child.pid, "SIGTERM", { detached }); cleanupTimer = setTimeout(finish, 200); }; const timer = setTimeout(finish, 3e3); const send = (messages) => { try { child.stdin.write(`${messages.map((message) => JSON.stringify(message)).join("\n")}\n`); } catch { stop(null); } }; child.once("error", () => stop(null)); child.once("close", finish); child.stdin.on("error", () => stop(null)); child.stdout.on("error", () => stop(null)); child.stdout.setEncoding("utf8"); child.stdout.on("data", (chunk) => { if (phase === "closing" || phase === "closed") return; outputBytes += Buffer.byteLength(chunk); if (outputBytes > 65536) { stop(null); return; } output += chunk; let newline; while ((newline = output.indexOf("\n")) !== -1) { const line = output.slice(0, newline); output = output.slice(newline + 1); try { const message = JSON.parse(line); if (!isRecord(message) || "method" in message || message.id !== (phase === "initialize" ? 1 : 2)) continue; if (message.error || !isRecord(message.result)) { stop(null); return; } if (phase === "initialize") { phase = "account"; send([{ method: "initialized" }, { id: 2, method: "account/read", params: { refreshToken: false } }]); } else { stop(projectCodexCliAccount(message.result)); return; } } catch { stop(null); return; } } }); send([{ id: 1, method: "initialize", params: { clientInfo: { name: "openclaw", title: "OpenClaw", version } } }]); }); } catch { return null; } } //#endregion export { readCodexCliAccount };