import test from "node:test"; import assert from "node:assert/strict"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { spawn } from "node:child_process"; import { detectCodexDesktopIntegration } from "../scripts/codex-desktop-integration-probe.mjs"; const repoRoot = path.resolve(import.meta.dirname, ".."); async function makeFakeCodexApp() { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "boss-codex-app-")); const appPath = path.join(tempDir, "Codex.app"); const contentsDir = path.join(appPath, "Contents"); const resourcesDir = path.join(contentsDir, "Resources"); await fs.mkdir(resourcesDir, { recursive: true }); await fs.writeFile( path.join(contentsDir, "Info.plist"), ` CFBundleIdentifier com.openai.codex CFBundleShortVersionString 26.429.30905 CFBundleVersion 2345 CFBundleURLTypes CFBundleURLName Codex CFBundleURLSchemes codex `, "utf8", ); await fs.writeFile( path.join(resourcesDir, "app.asar"), "function copyThreadLink(id){return `codex://threads/${id}`} // no plugin host export", "utf8", ); return { tempDir, appPath }; } test("detectCodexDesktopIntegration reports stable deeplink and bridge capabilities without patching app", async () => { const { tempDir, appPath } = await makeFakeCodexApp(); try { const result = await detectCodexDesktopIntegration({ appPath, bridgeEventsUrl: "http://127.0.0.1:4318/api/v1/codex-desktop/events", }); assert.equal(result.ok, true); assert.equal(result.app.bundleIdentifier, "com.openai.codex"); assert.equal(result.app.shortVersion, "26.429.30905"); assert.deepEqual(result.app.urlSchemes, ["codex"]); assert.deepEqual(result.capabilities.threadDeepLink, { supported: true, template: "codex://threads/{threadId}", evidence: "CFBundleURLSchemes contains codex and app resources contain codex://threads/", }); assert.equal(result.capabilities.desktopBridgeSse.supported, true); assert.equal(result.capabilities.desktopBridgeSse.url, "http://127.0.0.1:4318/api/v1/codex-desktop/events"); assert.equal(result.capabilities.inAppSubscription.supported, false); assert.equal(result.capabilities.packagePatch.supported, false); } finally { await fs.rm(tempDir, { recursive: true, force: true }); } }); test("codex desktop refresh bridge daemon exposes capabilities from the integration probe", async () => { const { tempDir, appPath } = await makeFakeCodexApp(); const child = spawn(process.execPath, [path.join(repoRoot, "scripts/codex-desktop-refresh-bridge-daemon.mjs")], { cwd: repoRoot, env: { ...process.env, BOSS_CODEX_DESKTOP_BRIDGE_HOST: "127.0.0.1", BOSS_CODEX_DESKTOP_BRIDGE_PORT: "0", BOSS_CODEX_DESKTOP_APP_PATH: appPath, BOSS_CODEX_DESKTOP_REFRESH_DRY_RUN: "true", }, stdio: ["ignore", "pipe", "pipe"], }); try { const ready = await new Promise((resolve, reject) => { let buffer = ""; const timer = setTimeout(() => reject(new Error("daemon not ready")), 4000); child.stdout.setEncoding("utf8"); child.stdout.on("data", (chunk) => { buffer += chunk; const line = buffer.trim().split(/\r?\n/).at(-1); if (line) { try { clearTimeout(timer); resolve(JSON.parse(line)); } catch { // wait } } }); child.on("error", reject); }); const response = await fetch(`http://${ready.host}:${ready.port}/api/v1/codex-desktop/capabilities`); const result = await response.json(); assert.equal(response.status, 200); assert.equal(result.ok, true); assert.equal(result.capabilities.threadDeepLink.supported, true); assert.equal(result.capabilities.packagePatch.supported, false); } finally { child.kill("SIGTERM"); await fs.rm(tempDir, { recursive: true, force: true }); } });