refactor(codex): give the CODEX_HOME lookup its own module

This commit is contained in:
2026-09-08 16:24:17 +07:00
parent aef7ec130b
commit 57849d2f75
3 changed files with 92 additions and 5 deletions
+41
View File
@@ -0,0 +1,41 @@
/**
* @file Tests for codex-home.js: CODEX_HOME resolution and related path
* resolutions for Codex project and surface directories.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const path = require("node:path");
const os = require("node:os");
const { describe, it, beforeEach } = require("node:test");
const assert = require("node:assert/strict");
describe("codex-home", () => {
beforeEach(() => {
// Clear the require cache so getCodexHome() reads the fresh env var
delete require.cache[require.resolve("../lib/codex-home")];
});
it("honours CODEX_HOME over the home directory", () => {
process.env.CODEX_HOME = "/tmp/injected-codex";
delete require.cache[require.resolve("../lib/codex-home")];
assert.equal(require("../lib/codex-home").getCodexHome(), "/tmp/injected-codex");
});
it("puts the project surfaces under <cwd>/.codex", () => {
const { getProjectCodexDir } = require("../lib/codex-home");
assert.equal(getProjectCodexDir("/repo"), path.join("/repo", ".codex"));
});
it("returns the cwd as the project root", () => {
const { getProjectRoot } = require("../lib/codex-home");
assert.equal(getProjectRoot("/repo"), "/repo");
});
it("defaults to ~/.codex when CODEX_HOME is not set", () => {
delete process.env.CODEX_HOME;
delete require.cache[require.resolve("../lib/codex-home")];
const { getCodexHome } = require("../lib/codex-home");
assert.equal(getCodexHome(), path.join(os.homedir(), ".codex"));
});
});
+49
View File
@@ -0,0 +1,49 @@
/**
* @file Centralized Codex home directory path management. Resolves the Codex
* home directory, project-level Codex surfaces, and project roots. Supports a
* custom root via the CODEX_HOME environment variable so the dashboard can
* track non-standard Codex installations.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const path = require("node:path");
const os = require("node:os");
/**
* The Codex home directory. Resolves to $CODEX_HOME if set, else
* ~/.codex. Always reads process.env at call time so tests can inject.
*
* @returns {string} Absolute path to the Codex home directory.
*/
function getCodexHome() {
return process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
}
/**
* The directory where Codex stores per-project surfaces (rollout journals,
* SQLite mirrors, etc.) for a project at the given working directory.
*
* @param {string} cwd Absolute path to a project root.
* @returns {string} Absolute path to <cwd>/.codex.
*/
function getProjectCodexDir(cwd) {
return path.join(cwd, ".codex");
}
/**
* The project root. For now, this is just an identity function — cwd is
* the project root. Exists as a contract for consistency with claude-home.js
* and to anchor the path-resolution hierarchy.
*
* @param {string} cwd Absolute path to a project root (where AGENTS.md lives).
* @returns {string} The same cwd.
*/
function getProjectRoot(cwd) {
return cwd;
}
module.exports = {
getCodexHome,
getProjectCodexDir,
getProjectRoot,
};
+2 -5
View File
@@ -33,6 +33,7 @@
const fs = require("node:fs");
const path = require("node:path");
const os = require("node:os");
const { getCodexHome } = require("./codex-home");
// `*** Update File: <path>` lines inside an apply_patch heredoc.
const PATCH_FILE_RE = /^\*\*\* (Add|Update|Delete) File: (.+)$/gm;
@@ -98,10 +99,6 @@ function eventsFromPayload(payload) {
return [{ tool_name: "Bash", tool_input: { command: commandFromPayload(payload, text) } }];
}
function codexHome() {
return process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
}
/** Every rollout journal under sessions/, newest mtime first, capped at MAX_FILES. */
function rolloutFiles() {
const out = [];
@@ -126,7 +123,7 @@ function rolloutFiles() {
}
}
};
walk(path.join(codexHome(), "sessions"), 0);
walk(path.join(getCodexHome(), "sessions"), 0);
return out.sort((a, b) => b.mtime - a.mtime).slice(0, MAX_FILES);
}