From a0263058bff8790d5e817ca1833ef938db2f63f7 Mon Sep 17 00:00:00 2001 From: Winnifred Boehm <88969402+cluic@users.noreply.github.com> Date: Sat, 23 May 2026 18:10:36 +0800 Subject: [PATCH] fix: keep CLI prompts visible before upstream config --- node/.changeset/fix-cli-prompt-warning.md | 5 ++ node/bin/crp.mjs | 2 +- node/src/capture-config.mjs | 4 ++ node/src/capture-store.mjs | 5 +- node/test/crp.test.mjs | 70 +++++++++++++++++++++++ 5 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 node/.changeset/fix-cli-prompt-warning.md create mode 100644 node/src/capture-config.mjs create mode 100644 node/test/crp.test.mjs diff --git a/node/.changeset/fix-cli-prompt-warning.md b/node/.changeset/fix-cli-prompt-warning.md new file mode 100644 index 0000000..5b3619b --- /dev/null +++ b/node/.changeset/fix-cli-prompt-warning.md @@ -0,0 +1,5 @@ +--- +"@cluic/codex-remote-proxy": patch +--- + +Avoid loading SQLite capture support when CLI commands only need default capture settings, so interactive `crp init` and `crp start` prompts stay visible instead of being interrupted by experimental SQLite warnings. diff --git a/node/bin/crp.mjs b/node/bin/crp.mjs index a78e7df..07ed13a 100644 --- a/node/bin/crp.mjs +++ b/node/bin/crp.mjs @@ -7,7 +7,7 @@ import readline from "node:readline/promises"; import os from "node:os"; import { setTimeout as delay } from "node:timers/promises"; -import { DEFAULT_CAPTURE_DB_PATH } from "../src/capture-store.mjs"; +import { DEFAULT_CAPTURE_DB_PATH } from "../src/capture-config.mjs"; const PACKAGE_ROOT = resolve(import.meta.dirname, ".."); const DEFAULT_CODEX_CONFIG_PATH = resolve(os.homedir(), ".codex", "config.toml"); diff --git a/node/src/capture-config.mjs b/node/src/capture-config.mjs new file mode 100644 index 0000000..a00da44 --- /dev/null +++ b/node/src/capture-config.mjs @@ -0,0 +1,4 @@ +import os from "node:os"; +import { resolve } from "node:path"; + +export const DEFAULT_CAPTURE_DB_PATH = resolve(os.homedir(), ".codex-remote-proxy", "traffic.sqlite3"); diff --git a/node/src/capture-store.mjs b/node/src/capture-store.mjs index c7747b9..695dbcd 100644 --- a/node/src/capture-store.mjs +++ b/node/src/capture-store.mjs @@ -1,9 +1,10 @@ import { watchFile, unwatchFile, readFileSync, mkdirSync } from "node:fs"; -import os from "node:os"; import { dirname, isAbsolute, resolve } from "node:path"; import { DatabaseSync } from "node:sqlite"; -export const DEFAULT_CAPTURE_DB_PATH = resolve(os.homedir(), ".codex-remote-proxy", "traffic.sqlite3"); +import { DEFAULT_CAPTURE_DB_PATH } from "./capture-config.mjs"; + +export { DEFAULT_CAPTURE_DB_PATH }; const WATCH_INTERVAL_MS = 500; const WATCH_DEBOUNCE_MS = 100; diff --git a/node/test/crp.test.mjs b/node/test/crp.test.mjs new file mode 100644 index 0000000..4fa57b9 --- /dev/null +++ b/node/test/crp.test.mjs @@ -0,0 +1,70 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; +import { mkdtempSync, rmSync } from "node:fs"; +import os from "node:os"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); + +function makeTempHome() { + return mkdtempSync(join(os.tmpdir(), "crp-home-")); +} + +function makeHomeEnv(homeDir) { + return { + ...process.env, + HOME: homeDir, + USERPROFILE: homeDir + }; +} + +function runCrp(args, env) { + return spawnSync(process.execPath, [join(PACKAGE_ROOT, "bin", "crp.mjs"), ...args], { + cwd: PACKAGE_ROOT, + env, + encoding: "utf8" + }); +} + +test("check does not emit sqlite experimental warnings", () => { + const homeDir = makeTempHome(); + try { + const result = runCrp(["check", "--json"], makeHomeEnv(homeDir)); + const output = `${result.stdout}\n${result.stderr}`; + + assert.equal(result.status, 0); + assert.doesNotMatch(output, /ExperimentalWarning: SQLite/); + } finally { + rmSync(homeDir, { recursive: true, force: true }); + } +}); + +test("init without config fails cleanly without sqlite warnings", () => { + const homeDir = makeTempHome(); + try { + const result = runCrp(["init"], makeHomeEnv(homeDir)); + const output = `${result.stdout}\n${result.stderr}`; + + assert.equal(result.status, 1); + assert.match(output, /Error: Upstream base URL is required/); + assert.doesNotMatch(output, /ExperimentalWarning: SQLite/); + } finally { + rmSync(homeDir, { recursive: true, force: true }); + } +}); + +test("start without config fails cleanly without sqlite warnings", () => { + const homeDir = makeTempHome(); + try { + const result = runCrp(["start"], makeHomeEnv(homeDir)); + const output = `${result.stdout}\n${result.stderr}`; + + assert.equal(result.status, 1); + assert.match(output, /Error: Upstream base URL is required/); + assert.doesNotMatch(output, /ExperimentalWarning: SQLite/); + } finally { + rmSync(homeDir, { recursive: true, force: true }); + } +});