import type { AdapterEnvironmentCheck, AdapterEnvironmentTestContext, AdapterEnvironmentTestResult, } from "@paperclip/adapter-utils"; import { asString, parseObject, ensureAbsoluteDirectory, ensureCommandResolvable, ensurePathInEnv, } from "@paperclip/adapter-utils/server-utils"; function summarizeStatus(checks: AdapterEnvironmentCheck[]): AdapterEnvironmentTestResult["status"] { if (checks.some((check) => check.level === "error")) return "fail"; if (checks.some((check) => check.level === "warn")) return "warn"; return "pass"; } function isNonEmpty(value: unknown): value is string { return typeof value === "string" && value.trim().length > 0; } export async function testEnvironment( ctx: AdapterEnvironmentTestContext, ): Promise { const checks: AdapterEnvironmentCheck[] = []; const config = parseObject(ctx.config); const command = asString(config.command, "codex"); const cwd = asString(config.cwd, process.cwd()); try { await ensureAbsoluteDirectory(cwd); checks.push({ code: "codex_cwd_valid", level: "info", message: `Working directory is valid: ${cwd}`, }); } catch (err) { checks.push({ code: "codex_cwd_invalid", level: "error", message: err instanceof Error ? err.message : "Invalid working directory", detail: cwd, }); } const envConfig = parseObject(config.env); const env: Record = {}; for (const [key, value] of Object.entries(envConfig)) { if (typeof value === "string") env[key] = value; } const runtimeEnv = ensurePathInEnv({ ...process.env, ...env }); try { await ensureCommandResolvable(command, cwd, runtimeEnv); checks.push({ code: "codex_command_resolvable", level: "info", message: `Command is executable: ${command}`, }); } catch (err) { checks.push({ code: "codex_command_unresolvable", level: "error", message: err instanceof Error ? err.message : "Command is not executable", detail: command, }); } const configOpenAiKey = env.OPENAI_API_KEY; const hostOpenAiKey = process.env.OPENAI_API_KEY; if (isNonEmpty(configOpenAiKey) || isNonEmpty(hostOpenAiKey)) { const source = isNonEmpty(configOpenAiKey) ? "adapter config env" : "server environment"; checks.push({ code: "codex_openai_api_key_present", level: "info", message: "OPENAI_API_KEY is set for Codex authentication.", detail: `Detected in ${source}.`, }); } else { checks.push({ code: "codex_openai_api_key_missing", level: "warn", message: "OPENAI_API_KEY is not set. Codex runs may fail until authentication is configured.", hint: "Set OPENAI_API_KEY in adapter env, shell environment, or Codex auth configuration.", }); } return { adapterType: ctx.adapterType, status: summarizeStatus(checks), checks, testedAt: new Date().toISOString(), }; }