test(omo-codex): batch 84 (10 files)

This commit is contained in:
YeonGyu-Kim
2026-05-30 19:12:14 +09:00
parent c990dd92c1
commit b7ed2a9484
10 changed files with 1357 additions and 0 deletions
@@ -0,0 +1,104 @@
import assert from "node:assert/strict";
import { lstat, mkdir, readFile, readlink, rm, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import test from "node:test";
import { installMarketplaceLocally } from "./install-local.mjs";
import { makeTempDir, writeJson, writePluginAt } from "./install-test-fixtures.mjs";
const legacyCodexPluginMarketplace = ["code", "yeongyu", "codex", "plugins"].join("-");
test(
"#given bundled agent roles and stale legacy links #when installing locally #then relinks Codex agents to marketplace snapshot",
{ skip: process.platform === "win32" ? "Windows copies agent files instead of symlinking them" : false },
async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
const pluginRoot = join(codexPackageRoot, "plugin");
const agentsRoot = join(pluginRoot, "components", "ultrawork", "agents");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "sisyphuslabs",
plugins: [{ name: "omo", source: "./plugins/omo" }],
});
await writePluginAt(pluginRoot, "omo", "0.1.0");
await mkdir(agentsRoot, { recursive: true });
for (const agentName of ["explorer", "librarian", "plan"]) {
await writeFile(join(agentsRoot, `${agentName}.toml`), `name = "${agentName}"\n`);
}
await mkdir(join(codexHome, "agents"), { recursive: true });
await symlink(
join(codexHome, "plugins", "cache", legacyCodexPluginMarketplace, "omo", "0.1.0", "components", "ultrawork", "agents", "explorer.toml"),
join(codexHome, "agents", "explorer.toml"),
);
const result = await installMarketplaceLocally({
repoRoot,
codexHome,
platform: "linux",
runCommand: async () => {},
log: () => {},
});
assert.equal(result.installed.length, 1);
const snapshotPluginPath = join(codexHome, ".tmp", "marketplaces", "sisyphuslabs", "plugins", "omo");
for (const agentName of ["explorer", "librarian", "plan"]) {
const agentPath = join(codexHome, "agents", `${agentName}.toml`);
assert.equal((await lstat(agentPath)).isSymbolicLink(), true);
assert.equal(await readlink(agentPath), join(snapshotPluginPath, "components", "ultrawork", "agents", `${agentName}.toml`));
assert.equal(await readFile(agentPath, "utf8"), `name = "${agentName}"\n`);
}
const installedAgents = JSON.parse(await readFile(join(snapshotPluginPath, ".installed-agents.json"), "utf8"));
assert.deepEqual(installedAgents.agents.sort(), [
join(codexHome, "agents", "explorer.toml"),
join(codexHome, "agents", "librarian.toml"),
join(codexHome, "agents", "plan.toml"),
]);
},
);
test(
"#given local sisyphuslabs install #when plugin cache is pruned #then agent links still resolve through marketplace snapshot",
{ skip: process.platform === "win32" ? "Windows copies agent files instead of symlinking them" : false },
async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
const pluginRoot = join(codexPackageRoot, "plugin");
const agentsRoot = join(pluginRoot, "components", "ultrawork", "agents");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "sisyphuslabs",
plugins: [{ name: "omo", source: "./plugins/omo" }],
});
await writePluginAt(pluginRoot, "omo", "0.1.0");
await mkdir(agentsRoot, { recursive: true });
await writeFile(join(agentsRoot, "explorer.toml"), 'name = "explorer"\n');
const snapshotRoot = join(codexHome, ".tmp", "marketplaces", "sisyphuslabs");
await mkdir(join(snapshotRoot, ".git"), { recursive: true });
await writeFile(join(snapshotRoot, ".git", "config"), "[remote \"origin\"]\n");
await writeFile(join(snapshotRoot, ".codex-marketplace-install.json"), '{"source_type":"git"}\n');
const result = await installMarketplaceLocally({
repoRoot,
codexHome,
platform: "linux",
runCommand: async () => {},
log: () => {},
});
const pluginPath = result.installed[0].path;
await rm(pluginPath, { recursive: true, force: true });
const agentPath = join(codexHome, "agents", "explorer.toml");
assert.equal(
await readlink(agentPath),
join(codexHome, ".tmp", "marketplaces", "sisyphuslabs", "plugins", "omo", "components", "ultrawork", "agents", "explorer.toml"),
);
assert.equal(await readFile(agentPath, "utf8"), 'name = "explorer"\n');
assert.equal(await readFile(join(snapshotRoot, ".git", "config"), "utf8"), "[remote \"origin\"]\n");
assert.equal(await readFile(join(snapshotRoot, ".codex-marketplace-install.json"), "utf8"), '{"source_type":"git"}\n');
},
);
@@ -0,0 +1,123 @@
import assert from "node:assert/strict";
import { mkdir, readFile, readlink, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import test from "node:test";
import { linkCachedPluginBins } from "./install/cache.mjs";
import { makeTempDir, writeJson } from "./install-test-fixtures.mjs";
test("#given Windows platform #when linking cached plugin bins #then writes command shims", async () => {
const root = await makeTempDir();
const pluginRoot = join(root, "plugin");
const binDir = join(root, "bin");
await mkdir(pluginRoot, { recursive: true });
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/alpha",
bin: {
alpha: "./dist/cli.js",
},
});
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await writeFile(join(pluginRoot, "dist", "cli.js"), "#!/usr/bin/env node\n");
const linked = await linkCachedPluginBins({ binDir, pluginRoot, platform: "win32" });
assert.deepEqual(linked, [{ name: "alpha", path: join(binDir, "alpha.cmd"), target: join(pluginRoot, "dist", "cli.js") }]);
const shim = await readFile(join(binDir, "alpha.cmd"), "utf8");
assert.match(shim, /@echo off/);
assert.match(shim, new RegExp(`node "${join(pluginRoot, "dist", "cli.js").replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}" %\\*`));
});
test("#given existing custom Windows command shim #when linking bins #then rejects without overwriting", async () => {
const root = await makeTempDir();
const pluginRoot = join(root, "plugin");
const binDir = join(root, "bin");
await mkdir(pluginRoot, { recursive: true });
await mkdir(binDir, { recursive: true });
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/alpha",
bin: {
alpha: "./dist/cli.js",
},
});
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await writeFile(join(pluginRoot, "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeFile(join(binDir, "alpha.cmd"), "@echo off\r\necho custom\r\n");
await assert.rejects(
linkCachedPluginBins({ binDir, pluginRoot, platform: "win32" }),
/already exists and is not a generated command shim/,
);
assert.match(await readFile(join(binDir, "alpha.cmd"), "utf8"), /echo custom/);
});
test("#given managed legacy Codex component symlink #when linking bins #then removes stale symlink and writes OMO bin", async () => {
const root = await makeTempDir();
const pluginRoot = join(root, "plugin");
const binDir = join(root, "bin");
const oldTarget = join(root, "codex-home", "plugins", "cache", "legacy-market", "omo", "0.0.1", "components", "rules", "dist", "cli.js");
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await mkdir(join(root, "codex-home", "plugins", "cache", "legacy-market", "omo", "0.0.1", "components", "rules", "dist"), { recursive: true });
await mkdir(binDir, { recursive: true });
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/omo",
bin: { "omo-rules": "./dist/cli.js" },
});
await writeFile(join(pluginRoot, "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeFile(oldTarget, "#!/usr/bin/env node\n");
await symlink(oldTarget, join(binDir, "codex-rules"));
await linkCachedPluginBins({ binDir, pluginRoot, platform: "linux" });
await assert.rejects(readlink(join(binDir, "codex-rules")));
assert.equal(await readlink(join(binDir, "omo-rules")), join(pluginRoot, "dist", "cli.js"));
});
test("#given user-owned legacy Codex symlink #when linking bins #then preserves the user symlink", async () => {
const root = await makeTempDir();
const pluginRoot = join(root, "plugin");
const binDir = join(root, "bin");
const userTarget = join(root, "user-tools", "codex-rules");
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await mkdir(join(root, "user-tools"), { recursive: true });
await mkdir(binDir, { recursive: true });
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/omo",
bin: { "omo-rules": "./dist/cli.js" },
});
await writeFile(join(pluginRoot, "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeFile(userTarget, "#!/usr/bin/env node\n");
await symlink(userTarget, join(binDir, "codex-rules"));
await linkCachedPluginBins({ binDir, pluginRoot, platform: "linux" });
assert.equal(await readlink(join(binDir, "codex-rules")), userTarget);
assert.equal(await readlink(join(binDir, "omo-rules")), join(pluginRoot, "dist", "cli.js"));
});
test("#given user-owned legacy Codex symlink with component-like target #when linking bins #then preserves it", async () => {
const root = await makeTempDir();
const pluginRoot = join(root, "plugin");
const binDir = join(root, "bin");
const userTarget = join(root, "workspace", "components", "rules", "dist", "cli.js");
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await mkdir(join(root, "workspace", "components", "rules", "dist"), { recursive: true });
await mkdir(binDir, { recursive: true });
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/omo",
bin: { "omo-rules": "./dist/cli.js" },
});
await writeFile(join(pluginRoot, "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeFile(userTarget, "#!/usr/bin/env node\n");
await symlink(userTarget, join(binDir, "codex-rules"));
await linkCachedPluginBins({ binDir, pluginRoot, platform: "linux" });
assert.equal(await readlink(join(binDir, "codex-rules")), userTarget);
assert.equal(await readlink(join(binDir, "omo-rules")), join(pluginRoot, "dist", "cli.js"));
});
@@ -0,0 +1,30 @@
import assert from "node:assert/strict";
import { mkdir, stat, writeFile } from "node:fs/promises";
import { join } from "node:path";
import test from "node:test";
import { installCachedPlugin } from "./install/cache.mjs";
import { makeTempDir } from "./install-test-fixtures.mjs";
test("#given source plugin has a stale npm lockfile #when caching plugin #then lockfile is regenerated rather than copied", async () => {
// given
const root = await makeTempDir();
const codexHome = join(root, "codex-home");
const sourceRoot = join(root, "plugin");
await mkdir(sourceRoot, { recursive: true });
await writeFile(join(sourceRoot, "package.json"), JSON.stringify({ name: "@scope/omo", version: "0.1.0" }));
await writeFile(join(sourceRoot, "package-lock.json"), '{"packages":{"components/ulw-loop":{}}}\n');
// when
const installed = await installCachedPlugin({
codexHome,
marketplaceName: "debug",
name: "omo",
sourcePath: sourceRoot,
version: "0.1.0",
runCommand: async () => {},
});
// then
await assert.rejects(stat(join(installed.path, "package-lock.json")));
});
@@ -0,0 +1,118 @@
import assert from "node:assert/strict";
import { mkdtemp, readFile, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { updateCodexConfig } from "./install/config.mjs";
test("#given empty Codex config #when script installer updates config #then enables MultiAgentV2 with ten thousand session threads", async () => {
// given
const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-"));
const configPath = join(root, "config.toml");
// when
await updateCodexConfig({
configPath,
repoRoot: "/repo/packages/omo-codex",
marketplaceName: "debug",
marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex" },
pluginNames: ["omo"],
});
// then
const config = await readFile(configPath, "utf8");
assert.match(config, /\[features\.multi_agent_v2\]/);
assert.match(config, /enabled = true/);
assert.match(config, /max_concurrent_threads_per_session = 10000/);
});
test("#given sisyphuslabs config without explicit source #when script installer updates config #then uses local marketplace", async () => {
// given
const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-sisyphuslabs-"));
const configPath = join(root, "config.toml");
// when
await updateCodexConfig({
configPath,
repoRoot: "/repo/packages/omo-codex",
marketplaceName: "sisyphuslabs",
pluginNames: ["omo"],
});
// then
const config = await readFile(configPath, "utf8");
assert.match(config, /\[marketplaces\.sisyphuslabs\]/);
assert.match(config, /source_type = "local"/);
assert.match(config, /source = "\/repo\/packages\/omo-codex"/);
assert.doesNotMatch(config, /lazycodex\.git/);
assert.doesNotMatch(config, /ref = "main"/);
});
test("#given existing MultiAgentV2 table #when script installer updates config #then preserves unrelated tuning while setting ten thousand session threads", async () => {
// given
const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-existing-"));
const configPath = join(root, "config.toml");
await writeFile(
configPath,
[
"[features.multi_agent_v2]",
"enabled = false",
"usage_hint_enabled = false",
"max_concurrent_threads_per_session = 4",
"",
].join("\n"),
);
// when
await updateCodexConfig({
configPath,
repoRoot: "/repo/packages/omo-codex",
marketplaceName: "debug",
marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex" },
pluginNames: ["omo"],
});
// then
const config = await readFile(configPath, "utf8");
assert.match(config, /\[features\.multi_agent_v2\]/);
assert.match(config, /enabled = true/);
assert.match(config, /usage_hint_enabled = false/);
assert.match(config, /max_concurrent_threads_per_session = 10000/);
assert.doesNotMatch(config, /max_concurrent_threads_per_session = 4/);
});
test("#given legacy boolean MultiAgentV2 flag and table #when script installer updates config #then normalizes to table config", async () => {
// given
const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-legacy-"));
const configPath = join(root, "config.toml");
await writeFile(
configPath,
[
"[features]",
"multi_agent_v2 = true",
"plugins = false",
"",
"[features.multi_agent_v2]",
"usage_hint_enabled = false",
"",
].join("\n"),
);
// when
await updateCodexConfig({
configPath,
repoRoot: "/repo/packages/omo-codex",
marketplaceName: "debug",
marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex" },
pluginNames: ["omo"],
});
// then
const config = await readFile(configPath, "utf8");
assert.doesNotMatch(config, /^multi_agent_v2\s*=/m);
assert.match(config, /\[features\.multi_agent_v2\]/);
assert.match(config, /enabled = true/);
assert.match(config, /usage_hint_enabled = false/);
assert.match(config, /max_concurrent_threads_per_session = 10000/);
});
@@ -0,0 +1,192 @@
#!/usr/bin/env node
import { mkdir, writeFile } from "node:fs/promises";
import { homedir } from "node:os";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import {
installCachedPlugin,
linkCachedPluginBins,
pruneMarketplaceCache,
pruneMarketplacePluginCaches,
} from "./install/cache.mjs";
import { linkCachedPluginAgents } from "./install/agents.mjs";
import { updateCodexConfig } from "./install/config.mjs";
import { trustedHookStatesForPlugin } from "./install/hook-trust.mjs";
import { defaultRunCommand } from "./install/process.mjs";
import { writeInstalledMarketplaceSnapshot } from "./install/snapshot.mjs";
import {
readMarketplace,
readPluginManifest,
resolvePluginSource,
validatePathSegment,
} from "./install/marketplace.mjs";
const LEGACY_CODEX_PLUGIN_MARKETPLACE = ["code", "yeongyu", "codex", "plugins"].join("-");
const SISYPHUS_LEGACY_CACHE_MARKETPLACES = ["lazycodex", LEGACY_CODEX_PLUGIN_MARKETPLACE];
export function resolveCodexInstallerBinDir(options = {}) {
const homeDir = resolve(options.homeDir ?? homedir());
const env = options.env ?? process.env;
const explicitBinDir = nonEmptyEnvValue(env, "CODEX_LOCAL_BIN_DIR");
if (explicitBinDir !== undefined) return explicitBinDir;
const codexHome = resolve(options.codexHome ?? nonEmptyEnvValue(env, "CODEX_HOME") ?? join(homeDir, ".codex"));
const defaultCodexHome = resolve(join(homeDir, ".codex"));
return codexHome === defaultCodexHome ? join(homeDir, ".local", "bin") : join(codexHome, "bin");
}
export async function installMarketplaceLocally(options = {}) {
const repoRoot = resolve(options.repoRoot ?? process.cwd());
const env = options.env ?? process.env;
const homeDir = resolve(options.homeDir ?? homedir());
const codexHome = resolve(options.codexHome ?? nonEmptyEnvValue(env, "CODEX_HOME") ?? join(homeDir, ".codex"));
const binDir = resolve(options.binDir ?? resolveCodexInstallerBinDir({ codexHome, env, homeDir }));
const platform = options.platform ?? process.platform;
const runCommand = options.runCommand ?? defaultRunCommand;
const log = options.log ?? console.log;
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
const marketplace = await readMarketplace(repoRoot, {
marketplacePath: join(codexPackageRoot, "marketplace.json"),
});
const installed = [];
const pluginSources = [];
const agentConfigs = new Map();
for (const entry of marketplace.plugins) {
const sourcePath = resolvePluginSource(codexPackageRoot, entry, { pathOverride: "./plugin" });
const manifest = await readPluginManifest(sourcePath);
if (manifest.name !== entry.name) {
throw new Error(
`plugin manifest name ${JSON.stringify(manifest.name)} does not match marketplace name ${JSON.stringify(entry.name)}`,
);
}
const version = manifest.version ?? "local";
validatePathSegment(version, "plugin version");
log(`Building ${entry.name}@${version}`);
const plugin = await installCachedPlugin({
codexHome,
marketplaceName: marketplace.name,
name: entry.name,
runCommand,
sourcePath,
version,
});
const binLinks = await linkCachedPluginBins({ binDir, pluginRoot: plugin.path, platform });
for (const link of binLinks) {
log(`Linked ${link.name} -> ${link.target}`);
}
pluginSources.push({ name: entry.name, sourcePath });
installed.push(plugin);
}
const agentSourceRoots = await agentSourceRootsForInstall({ codexHome, marketplace, installed, pluginSources });
for (const plugin of installed) {
const pluginRoot = agentSourceRoots.get(plugin.name) ?? plugin.path;
const agentLinks = await linkCachedPluginAgents({ codexHome, pluginRoot, platform });
for (const link of agentLinks) {
log(`Linked agent ${link.name} -> ${link.target}`);
const agentName = agentNameFromToml(link.name);
agentConfigs.set(agentName, { name: agentName, configFile: `./agents/${link.name}` });
}
}
const pluginNames = marketplace.plugins.map((plugin) => plugin.name);
const trustedHookStates = (
await Promise.all(
installed.map((plugin) =>
trustedHookStatesForPlugin({
marketplaceName: marketplace.name,
pluginName: plugin.name,
pluginRoot: plugin.path,
}),
),
)
).flat();
await pruneMarketplaceCache({ codexHome, marketplaceName: marketplace.name, keepPluginNames: pluginNames });
for (const legacyMarketplaceName of legacyCacheMarketplaces(marketplace.name)) {
await pruneMarketplacePluginCaches({ codexHome, marketplaceName: legacyMarketplaceName, pluginNames });
}
const marketplaceRoot = join(codexHome, "plugins", "cache", marketplace.name);
await writeCachedMarketplaceManifest({
marketplaceName: marketplace.name,
marketplaceRoot,
plugins: installed,
});
await updateCodexConfig({
configPath: join(codexHome, "config.toml"),
repoRoot: codexPackageRoot,
marketplaceName: marketplace.name,
marketplaceSource: { sourceType: "local", source: marketplaceRoot },
pluginNames,
trustedHookStates,
agentConfigs: [...agentConfigs.values()].sort((left, right) => left.name.localeCompare(right.name)),
});
for (const plugin of installed) {
log(`Installed ${plugin.name}@${marketplace.name} -> ${plugin.path}`);
}
return { marketplaceName: marketplace.name, installed };
}
function agentNameFromToml(fileName) {
return fileName.endsWith(".toml") ? fileName.slice(0, -".toml".length) : fileName;
}
async function agentSourceRootsForInstall({ codexHome, marketplace, installed, pluginSources }) {
if (marketplace.name !== "sisyphuslabs") {
return new Map(installed.map((plugin) => [plugin.name, plugin.path]));
}
const snapshotPlugins = await writeInstalledMarketplaceSnapshot({
codexHome,
marketplace,
plugins: pluginSources,
});
return new Map(snapshotPlugins.map((plugin) => [plugin.name, plugin.path]));
}
async function writeCachedMarketplaceManifest({ marketplaceName, marketplaceRoot, plugins }) {
const marketplaceDir = join(marketplaceRoot, ".agents", "plugins");
await mkdir(marketplaceDir, { recursive: true });
await writeFile(
join(marketplaceDir, "marketplace.json"),
`${JSON.stringify(
{
name: marketplaceName,
plugins: plugins.map((plugin) => ({
name: plugin.name,
source: { source: "local", path: `./${plugin.name}/${plugin.version}` },
})),
},
null,
"\t",
)}\n`,
);
}
function nonEmptyEnvValue(env, key) {
const value = env[key];
if (typeof value !== "string") return undefined;
const trimmed = value.trim();
return trimmed.length === 0 ? undefined : value;
}
function legacyCacheMarketplaces(marketplaceName) {
return marketplaceName === "sisyphuslabs" ? SISYPHUS_LEGACY_CACHE_MARKETPLACES : [];
}
async function main() {
const repoRoot = process.argv[2] ? resolve(process.argv[2]) : process.cwd();
const result = await installMarketplaceLocally({ repoRoot });
console.log(`Installed ${result.installed.length} plugin(s) from ${result.marketplaceName}.`);
}
const invokedPath = process.argv[1] ? resolve(process.argv[1]) : "";
if (invokedPath === fileURLToPath(import.meta.url)) {
main().catch((error) => {
console.error(error instanceof Error ? error.message : error);
process.exitCode = 1;
});
}
@@ -0,0 +1,378 @@
import assert from "node:assert/strict";
import { mkdir, readFile, readlink, stat, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
import { installMarketplaceLocally, resolveCodexInstallerBinDir } from "./install-local.mjs";
import { makeTempDir, writeJson, writePluginAt } from "./install-test-fixtures.mjs";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const legacyCodexPluginMarketplace = ["code", "yeongyu", "codex", "plugins"].join("-");
test("#given default CODEX_HOME #when resolving local installer bin dir without override #then preserves user local bin precedence", () => {
const homeDir = join("/tmp", "omo-codex-home-default");
const codexHome = join(homeDir, ".codex");
assert.equal(resolveCodexInstallerBinDir({ codexHome, env: {}, homeDir }), join(homeDir, ".local", "bin"));
});
test("#given custom CODEX_HOME #when resolving local installer bin dir without override #then keeps generated omo inside that Codex home", () => {
const homeDir = join("/tmp", "omo-codex-home-custom");
const codexHome = join("/tmp", "omo-codex-install-custom");
assert.equal(resolveCodexInstallerBinDir({ codexHome, env: {}, homeDir }), join(codexHome, "bin"));
});
test("#given custom CODEX_HOME and PATH without omo #when installing locally without bin override #then bootstraps via local CLI when omo is absent", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const homeDir = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
const pluginRoot = join(codexPackageRoot, "plugin");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "sisyphuslabs",
plugins: [{ name: "omo", source: "./plugins/omo" }],
});
await writePluginAt(pluginRoot, "omo", "0.1.0");
const result = await installMarketplaceLocally({
repoRoot,
codexHome,
env: { PATH: "/usr/bin:/bin" },
homeDir,
platform: "linux",
runCommand: async () => {},
log: () => {},
});
assert.equal(result.installed.length, 1);
assert.equal(await readlink(join(codexHome, "bin", "omo")), join(result.installed[0].path, "dist", "cli.js"));
});
test("#given explicit CODEX_LOCAL_BIN_DIR #when resolving local installer bin dir #then preserves installed omo precedence", () => {
const homeDir = join("/tmp", "omo-codex-home-explicit");
const codexHome = join("/tmp", "omo-codex-install-explicit");
const explicitBinDir = join("/tmp", "omo-codex-explicit-bin");
assert.equal(
resolveCodexInstallerBinDir({
codexHome,
env: { CODEX_LOCAL_BIN_DIR: explicitBinDir },
homeDir,
}),
explicitBinDir,
);
});
test("#given omo plugin source #when inspecting identity #then uses sisyphuslabs omo metadata", async () => {
const pluginRoot = join(scriptDir, "..", "plugin");
const manifest = JSON.parse(await readFile(join(pluginRoot, ".codex-plugin", "plugin.json"), "utf8"));
const packageJson = JSON.parse(await readFile(join(pluginRoot, "package.json"), "utf8"));
assert.equal(packageJson.name, "@sisyphuslabs/omo-codex-plugin");
assert.equal(manifest.homepage, "https://github.com/sisyphuslabs/omo");
assert.equal(manifest.repository, "https://github.com/sisyphuslabs/omo");
assert.equal(manifest.interface.websiteURL, "https://github.com/sisyphuslabs/omo");
assert.equal(manifest.interface.privacyPolicyURL, "https://github.com/sisyphuslabs/omo#privacy");
assert.equal(manifest.interface.termsOfServiceURL, "https://github.com/sisyphuslabs/omo#license");
});
test("#given local marketplace #when installing #then copies versioned plugins and enables config", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const binDir = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
const pluginRoot = join(codexPackageRoot, "plugin");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "debug-marketplace",
plugins: [
{
name: "alpha",
source: "./plugins/alpha",
},
],
});
await writePluginAt(pluginRoot, "alpha", "1.2.3");
await mkdir(join(codexPackageRoot, "shared-lsp", "dist"), { recursive: true });
await writeJson(join(codexPackageRoot, "shared-lsp", "package.json"), {
name: "@example/shared-lsp",
version: "0.0.0",
type: "module",
bin: { "shared-lsp": "./dist/cli.js" },
});
await writeFile(join(codexPackageRoot, "shared-lsp", "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/alpha",
version: "1.2.3",
bin: {
alpha: "./dist/cli.js",
},
scripts: {
build: "node -e \"require('fs').writeFileSync('dist/cli.js', 'console.log(1)')\"",
},
dependencies: {
"@example/shared-lsp": "file:../shared-lsp",
},
});
await writeJson(join(pluginRoot, ".mcp.json"), {
mcpServers: {
alpha: {
command: "node",
args: ["./dist/cli.js", "mcp"],
cwd: ".",
},
shared: {
command: "node",
args: ["../shared-lsp/dist/cli.js", "mcp"],
cwd: ".",
},
},
});
await mkdir(join(pluginRoot, "node_modules"), { recursive: true });
await writeFile(join(pluginRoot, "node_modules", "skip.txt"), "skip");
await mkdir(join(codexHome, "plugins", "cache", "debug-marketplace", "stale", "0.1.0"), { recursive: true });
await writeFile(
join(codexHome, "config.toml"),
[
'[plugins."stale@debug-marketplace"]',
"enabled = true",
"",
'[hooks.state."stale@debug-marketplace:hooks/hooks.json:user_prompt_submit:0:0"]',
'trusted_hash = "sha256:old"',
"",
].join("\n"),
);
const commands = [];
const result = await installMarketplaceLocally({
repoRoot,
codexHome,
binDir,
platform: "linux",
runCommand: async (command, args, options) => {
commands.push([command, args, options.cwd]);
if (command === "npm" && args.join(" ") === "run build") {
await mkdir(join(options.cwd, "dist"), { recursive: true });
await writeFile(join(options.cwd, "dist", "cli.js"), "#!/usr/bin/env node\nconsole.log(1)\n");
}
},
log: () => {},
});
assert.deepEqual(
result.installed.map((plugin) => `${plugin.name}@${plugin.version}`),
["alpha@1.2.3"],
);
const alphaCacheRoot = join(codexHome, "plugins", "cache", "debug-marketplace", "alpha", "1.2.3");
assert.equal((await stat(join(alphaCacheRoot, "dist", "cli.js"))).isFile(), true);
assert.equal((await stat(join(alphaCacheRoot, ".mcp.json"))).isFile(), true);
assert.equal(await readlink(join(binDir, "alpha")), join(alphaCacheRoot, "dist", "cli.js"));
const alphaMcp = JSON.parse(await readFile(join(alphaCacheRoot, ".mcp.json"), "utf8"));
const sharedMcpCli = join(alphaCacheRoot, "mcp", "shared", "dist", "cli.js");
assert.deepEqual(alphaMcp.mcpServers.alpha.args, [join(alphaCacheRoot, "dist", "cli.js"), "mcp"]);
assert.deepEqual(alphaMcp.mcpServers.shared.args, [sharedMcpCli, "mcp"]);
assert.equal((await stat(sharedMcpCli)).isFile(), true);
assert.equal(
Object.hasOwn(alphaMcp.mcpServers.alpha, "cwd"),
false,
"`cwd: \".\"` must be stripped so the spawned MCP server inherits the caller's workspace cwd",
);
assert.equal(Object.hasOwn(alphaMcp.mcpServers.shared, "cwd"), false);
assert.equal(alphaMcp.mcpServers.alpha.command, "node");
const alphaPackageJson = JSON.parse(await readFile(join(alphaCacheRoot, "package.json"), "utf8"));
assert.equal(alphaPackageJson.dependencies["@example/shared-lsp"], `file:${join(codexPackageRoot, "shared-lsp")}`);
await assert.rejects(
stat(join(codexHome, "plugins", "cache", "debug-marketplace", "alpha", "1.2.3", "node_modules")),
/code: 'ENOENT'|ENOENT/,
);
await assert.rejects(
stat(join(codexHome, "plugins", "cache", "debug-marketplace", "stale")),
/code: 'ENOENT'|ENOENT/,
);
assert.deepEqual(
commands.map(([command, args, cwd]) => [command, args.join(" "), cwd]),
[
["npm", "install", pluginRoot],
["npm", "run build", pluginRoot],
["npm", "install --omit=dev", join(codexHome, "plugins", "cache", "debug-marketplace", "alpha", "1.2.3")],
],
);
const config = await readFile(join(codexHome, "config.toml"), "utf8");
assert.match(config, /\[features\]\n(?:plugin_hooks = true\n)?plugins = true/);
assert.match(config, /\[marketplaces\.debug-marketplace\]/);
assert.match(config, /source_type = "local"/);
assert.match(config, /\[plugins\."alpha@debug-marketplace"\]\nenabled = true/);
assert.match(config, /\[agents\.explorer\]\nconfig_file = "\.\/agents\/explorer\.toml"/);
assert.match(config, /\[agents\.librarian\]\nconfig_file = "\.\/agents\/librarian\.toml"/);
assert.match(config, /\[agents\.plan\]\nconfig_file = "\.\/agents\/plan\.toml"/);
assert.doesNotMatch(config, /stale@debug-marketplace/);
});
test("#given sisyphuslabs marketplace #when installing #then registers the local built marketplace cache", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "sisyphuslabs",
plugins: [{ name: "omo", source: "./plugins/omo" }],
});
await writePluginAt(join(codexPackageRoot, "plugin"), "omo", "0.1.0");
await mkdir(join(repoRoot, "packages", "lsp-tools-mcp", "dist"), { recursive: true });
await writeJson(join(repoRoot, "packages", "lsp-tools-mcp", "package.json"), {
name: "@example/lsp-tools-mcp",
version: "0.1.0",
type: "module",
bin: { "omo-lsp": "./dist/cli.js" },
});
await writeFile(join(repoRoot, "packages", "lsp-tools-mcp", "dist", "cli.js"), "#!/usr/bin/env node\n");
await writeJson(join(codexPackageRoot, "plugin", ".mcp.json"), {
mcpServers: {
lsp: {
command: "node",
args: ["../../lsp-tools-mcp/dist/cli.js", "mcp"],
cwd: ".",
},
},
});
await mkdir(join(codexHome, "plugins", "cache", legacyCodexPluginMarketplace, "omo", "0.1.0"), {
recursive: true,
});
await writeJson(join(codexHome, "plugins", "cache", legacyCodexPluginMarketplace, "omo", "0.1.0", ".mcp.json"), {
mcpServers: {
lsp: {
command: "node",
args: ["old/components/lsp/packages/lsp-tools-mcp/dist/cli.js", "mcp"],
},
},
});
const legacyPluginKey = `omo@${legacyCodexPluginMarketplace}`;
await writeFile(
join(codexHome, "config.toml"),
[
`[marketplaces.${legacyCodexPluginMarketplace}]`,
'last_updated = "2026-05-01T00:00:00Z"',
'source_type = "git"',
'source = "https://github.com/code-yeongyu/codex-plugins.git"',
"",
`[plugins.${JSON.stringify(legacyPluginKey)}]`,
"enabled = true",
"",
`[plugins.${JSON.stringify(legacyPluginKey)}.mcp_servers.lsp]`,
'enabled = true',
"",
`[hooks.state.${JSON.stringify(`${legacyPluginKey}:hooks/hooks.json:post_tool_use:0:0`)}]`,
'trusted_hash = "sha256:old"',
"",
].join("\n"),
);
await installMarketplaceLocally({
repoRoot,
codexHome,
runCommand: async () => {},
log: () => {},
});
const config = await readFile(join(codexHome, "config.toml"), "utf8");
assert.match(config, /\[marketplaces\.sisyphuslabs\]/);
assert.match(config, /source_type = "local"/);
assert.match(config, new RegExp(`source = ${JSON.stringify(join(codexHome, "plugins", "cache", "sisyphuslabs")).replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
assert.doesNotMatch(config, /ref = "main"/);
assert.match(config, /\[plugins\."omo@sisyphuslabs"\]\nenabled = true/);
assert.doesNotMatch(config, /\[marketplaces\.lazycodex\]/);
assert.doesNotMatch(config, new RegExp(legacyCodexPluginMarketplace));
assert.doesNotMatch(config, /lazycodex\.git/);
const marketplace = JSON.parse(
await readFile(join(codexHome, "plugins", "cache", "sisyphuslabs", ".agents", "plugins", "marketplace.json"), "utf8"),
);
assert.deepEqual(marketplace.plugins, [{ name: "omo", source: { source: "local", path: "./omo/0.1.0" } }]);
const cachedMcp = JSON.parse(
await readFile(join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "0.1.0", ".mcp.json"), "utf8"),
);
assert.equal(
cachedMcp.mcpServers.lsp.args[0],
join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "0.1.0", "mcp", "lsp", "dist", "cli.js"),
);
assert.doesNotMatch(cachedMcp.mcpServers.lsp.args[0], /components\/lsp\/packages/);
assert.equal((await stat(cachedMcp.mcpServers.lsp.args[0])).isFile(), true);
const snapshotPluginRoot = join(codexHome, ".tmp", "marketplaces", "sisyphuslabs", "plugins", "omo");
const snapshotMcp = JSON.parse(await readFile(join(snapshotPluginRoot, ".mcp.json"), "utf8"));
assert.equal(
snapshotMcp.mcpServers.lsp.args[0],
join(snapshotPluginRoot, "mcp", "lsp", "dist", "cli.js"),
);
assert.doesNotMatch(snapshotMcp.mcpServers.lsp.args[0], /\.\.\/\.\.\/lsp-tools-mcp/);
assert.doesNotMatch(snapshotMcp.mcpServers.lsp.args[0], /components\/lsp\/packages/);
assert.equal((await stat(snapshotMcp.mcpServers.lsp.args[0])).isFile(), true);
await assert.rejects(
stat(join(codexHome, "plugins", "cache", legacyCodexPluginMarketplace, "omo")),
/code: 'ENOENT'|ENOENT/,
);
});
test("#given plugin hooks #when installing #then records trusted hook hashes", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "debug-marketplace",
plugins: [{ name: "alpha", source: "./plugins/alpha" }],
});
const pluginRoot = join(codexPackageRoot, "plugin");
await writePluginAt(pluginRoot, "alpha", "1.2.3");
await writeJson(join(pluginRoot, "hooks", "hooks.json"), {
hooks: {
UserPromptSubmit: [
{
hooks: [
{
type: "command",
command: "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
timeout: 10,
statusMessage: "checking alpha",
},
],
},
],
},
});
await installMarketplaceLocally({
repoRoot,
codexHome,
runCommand: async () => {},
log: () => {},
});
const config = await readFile(join(codexHome, "config.toml"), "utf8");
assert.match(config, /\[hooks\.state\."alpha@debug-marketplace:hooks\/hooks\.json:user_prompt_submit:0:0"\]/);
assert.match(config, /trusted_hash = "sha256:[a-f0-9]{64}"/);
});
test("#given bad plugin source path #when installing #then rejects traversal", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const codexPackageRoot = join(repoRoot, "packages", "omo-codex");
await writeJson(join(codexPackageRoot, "marketplace.json"), {
name: "debug-marketplace",
plugins: [
{
name: "escape",
source: "../escape",
},
],
});
await assert.rejects(
installMarketplaceLocally({ repoRoot, codexHome, log: () => {} }),
/local plugin source path must start with \.\//,
);
});
@@ -0,0 +1,173 @@
import assert from "node:assert/strict";
import { readFile, stat } from "node:fs/promises";
import { join } from "node:path";
import test from "node:test";
import { installCachedPlugin } from "./install/cache.mjs";
import { createCachedMcpRuntimeArgRewriter } from "./install/mcp-runtime-cache.mjs";
import { makeTempDir, writeJson } from "./install-test-fixtures.mjs";
test("#given external MCP package runtime #when installing cached plugin #then runtime is copied into the plugin cache", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const sourceRoot = join(repoRoot, "packages", "omo-codex", "plugin");
const astGrepPackageRoot = join(repoRoot, "packages", "ast-grep-mcp");
const lspPackageRoot = join(repoRoot, "packages", "lsp-tools-mcp");
await writeJson(join(astGrepPackageRoot, "package.json"), {
name: "@example/does-not-matter-either",
version: "0.1.0",
type: "module",
bin: { "omo-ast-grep": "./dist/cli.js" },
});
await writeJson(join(lspPackageRoot, "package.json"), {
name: "@example/does-not-matter",
version: "0.1.0",
type: "module",
bin: { "omo-lsp": "./dist/cli.js" },
});
await writeJson(join(sourceRoot, "package.json"), {
name: "@example/omo",
version: "0.1.0",
});
await writeJson(join(sourceRoot, ".mcp.json"), {
mcpServers: {
ast_grep: {
command: "node",
args: ["../../ast-grep-mcp/dist/cli.js", "mcp"],
cwd: ".",
},
lsp: {
command: "node",
args: ["../../lsp-tools-mcp/dist/cli.js", "mcp"],
cwd: ".",
},
},
});
await writeJson(join(astGrepPackageRoot, "dist", "cli.js"), { executable: true });
await writeJson(join(lspPackageRoot, "dist", "cli.js"), { executable: true });
await writeJson(join(lspPackageRoot, "dist", "lsp", "manager.js"), { copied: true });
const result = await installCachedPlugin({
codexHome,
marketplaceName: "sisyphuslabs",
name: "omo",
runCommand: async () => {},
sourcePath: sourceRoot,
version: "0.1.0",
});
const cachedMcp = JSON.parse(await readFile(join(result.path, ".mcp.json"), "utf8"));
const copiedAstGrepCli = join(result.path, "mcp", "ast_grep", "dist", "cli.js");
const copiedCli = join(result.path, "mcp", "lsp", "dist", "cli.js");
assert.deepEqual(cachedMcp.mcpServers.ast_grep.args, [copiedAstGrepCli, "mcp"]);
assert.deepEqual(cachedMcp.mcpServers.lsp.args, [copiedCli, "mcp"]);
assert.equal(Object.hasOwn(cachedMcp.mcpServers.ast_grep, "cwd"), false);
assert.equal(Object.hasOwn(cachedMcp.mcpServers.lsp, "cwd"), false);
assert.equal((await stat(copiedAstGrepCli)).isFile(), true);
assert.equal((await stat(copiedCli)).isFile(), true);
assert.equal((await stat(join(result.path, "mcp", "lsp", "dist", "lsp", "manager.js"))).isFile(), true);
});
test("#given multiple args from one external MCP package #when rewriting #then copies the dist tree once and rewrites each runtime arg", async () => {
const repoRoot = await makeTempDir();
const pluginRoot = join(repoRoot, "packages", "omo-codex", "plugin");
const sourceRoot = pluginRoot;
const packageRoot = join(repoRoot, "packages", "multi-tool-mcp");
const copiedRoots = [];
await writeJson(join(packageRoot, "package.json"), {
name: "@example/multi-tool-mcp",
version: "0.1.0",
bin: { "multi-tool": "./dist/cli.js" },
});
await writeJson(join(packageRoot, "dist", "cli.js"), { executable: true });
await writeJson(join(packageRoot, "dist", "worker.js"), { worker: true });
const rewrite = createCachedMcpRuntimeArgRewriter({
copyDist: async (_source, target) => {
copiedRoots.push(target);
},
});
const first = await rewrite({ arg: "../../multi-tool-mcp/dist/cli.js", pluginRoot, serverName: "multi", sourceRoot });
const second = await rewrite({ arg: "../../multi-tool-mcp/dist/worker.js", pluginRoot, serverName: "multi", sourceRoot });
assert.equal(copiedRoots.length, 1);
assert.deepEqual([first, second], [
join(pluginRoot, "mcp", "multi", "dist", "cli.js"),
join(pluginRoot, "mcp", "multi", "dist", "worker.js"),
]);
});
test("#given plugin-local MCP runtime #when rewriting cached manifest args #then keeps the cached plugin dist path", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const sourceRoot = join(repoRoot, "packages", "omo-codex", "plugin");
const pluginRoot = join(codexHome, "plugins", "cache", "sisyphuslabs", "omo", "0.1.0");
const copiedRoots = [];
await writeJson(join(sourceRoot, "package.json"), {
name: "@example/source-plugin",
version: "0.1.0",
});
await writeJson(join(pluginRoot, "package.json"), {
name: "@example/cached-plugin",
version: "0.1.0",
});
await writeJson(join(pluginRoot, "dist", "cli.js"), { executable: true });
const rewrite = createCachedMcpRuntimeArgRewriter({
copyDist: async (_source, target) => {
copiedRoots.push(target);
},
});
const runtimeArg = await rewrite({ arg: "./dist/cli.js", pluginRoot, serverName: "omo", sourceRoot });
assert.equal(runtimeArg, join(pluginRoot, "dist", "cli.js"));
assert.equal(copiedRoots.length, 0);
});
test("#given structurally valid external MCP package without mcp suffix #when installing cached plugin #then runtime is copied into the plugin cache", async () => {
const repoRoot = await makeTempDir();
const codexHome = await makeTempDir();
const sourceRoot = join(repoRoot, "packages", "omo-codex", "plugin");
const runtimePackageRoot = join(repoRoot, "packages", "language-tools");
await writeJson(join(runtimePackageRoot, "package.json"), {
name: "@example/language-tools",
version: "0.1.0",
type: "module",
bin: { "omo-language-tools": "./dist/cli.js" },
});
await writeJson(join(runtimePackageRoot, "dist", "cli.js"), { executable: true });
await writeJson(join(sourceRoot, "package.json"), {
name: "@example/omo",
version: "0.1.0",
});
await writeJson(join(sourceRoot, ".mcp.json"), {
mcpServers: {
language_tools: {
command: "node",
args: ["../../language-tools/dist/cli.js", "mcp", "../local-config.json"],
cwd: ".",
},
},
});
const result = await installCachedPlugin({
codexHome,
marketplaceName: "sisyphuslabs",
name: "omo",
runCommand: async () => {},
sourcePath: sourceRoot,
version: "0.1.0",
});
const cachedMcp = JSON.parse(await readFile(join(result.path, ".mcp.json"), "utf8"));
const copiedCli = join(result.path, "mcp", "language_tools", "dist", "cli.js");
assert.deepEqual(cachedMcp.mcpServers.language_tools.args, [copiedCli, "mcp", join(sourceRoot, "..", "local-config.json")]);
assert.equal((await stat(copiedCli)).isFile(), true);
});
@@ -0,0 +1,58 @@
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
export async function makeTempDir() {
return mkdtemp(join(tmpdir(), "omo-codex-install-"));
}
export async function writeJson(path, value) {
await mkdir(dirname(path), { recursive: true });
await writeFile(path, `${JSON.stringify(value, null, 2)}\n`);
}
export async function writePlugin(root, name, version) {
const pluginRoot = join(root, "plugins", name);
await writePluginAt(pluginRoot, name, version);
}
export async function writePluginAt(pluginRoot, name, version) {
await mkdir(join(pluginRoot, ".codex-plugin"), { recursive: true });
await mkdir(join(pluginRoot, "dist"), { recursive: true });
await mkdir(join(pluginRoot, "hooks"), { recursive: true });
await mkdir(join(pluginRoot, "skills", name), { recursive: true });
await mkdir(join(pluginRoot, "components", "ultrawork", "agents"), { recursive: true });
await writeJson(join(pluginRoot, ".codex-plugin", "plugin.json"), {
name,
version,
description: `${name} test plugin`,
mcpServers: "./.mcp.json",
hooks: "./hooks/hooks.json",
skills: "./skills/",
});
await writeJson(join(pluginRoot, ".mcp.json"), {
mcpServers: {
[name]: {
command: "node",
args: ["./dist/cli.js", "mcp"],
cwd: ".",
},
},
});
await writeJson(join(pluginRoot, "hooks", "hooks.json"), { hooks: {} });
await writeFile(join(pluginRoot, "skills", name, "SKILL.md"), "---\nname: test\n---\n");
await writeFile(join(pluginRoot, "components", "ultrawork", "agents", "explorer.toml"), 'name = "explorer"\n');
await writeFile(join(pluginRoot, "components", "ultrawork", "agents", "librarian.toml"), 'name = "librarian"\n');
await writeFile(join(pluginRoot, "components", "ultrawork", "agents", "plan.toml"), 'name = "plan"\n');
await writeJson(join(pluginRoot, "package.json"), {
name: `@example/${name}`,
version,
bin: {
[name]: "./dist/cli.js",
},
scripts: {
build: "node -e \"require('fs').writeFileSync('dist/cli.js', 'console.log(1)')\"",
},
dependencies: {},
});
}
@@ -0,0 +1,111 @@
#!/usr/bin/env node
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
export const TELEMETRY_SYNC_FILES = [
"atomic-write.ts",
"data-path.ts",
"env-flags.ts",
"posthog-activity-state.ts",
];
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
const PACKAGE_ROOT = dirname(SCRIPT_DIR);
const DEFAULT_SOURCE_DIR = join(PACKAGE_ROOT, "src", "telemetry");
const DEFAULT_COMPONENT_DIR = join(PACKAGE_ROOT, "plugin", "components", "telemetry", "src");
export async function syncTelemetryComponent(options = {}) {
const sourceDir = resolve(options.sourceDir ?? DEFAULT_SOURCE_DIR);
const componentDir = resolve(options.componentDir ?? DEFAULT_COMPONENT_DIR);
const files = options.files ?? TELEMETRY_SYNC_FILES;
const check = options.check ?? false;
const changed = [];
for (const fileName of files) {
const sourcePath = join(sourceDir, fileName);
const componentPath = join(componentDir, fileName);
const sourceText = await readFile(sourcePath, "utf8");
const componentText = await readOptionalText(componentPath);
const nextText = toComponentSource(sourceText);
if (componentText === nextText) continue;
changed.push(fileName);
if (!check) {
await mkdir(dirname(componentPath), { recursive: true });
await writeFile(componentPath, nextText);
}
}
if (check && changed.length > 0) {
throw new Error(`telemetry component out of sync: ${changed.join(", ")}`);
}
return { checked: check, changed };
}
function toComponentSource(sourceText) {
return sourceText
.replaceAll(/\bprocess\.env\.([A-Z0-9_]+)/g, 'process.env["$1"]')
.replaceAll(/from "(\.\/[^"]+)"/g, 'from "$1.js"');
}
async function readOptionalText(path) {
try {
return await readFile(path, "utf8");
} catch (error) {
if (isNodeError(error) && error.code === "ENOENT") return null;
throw error;
}
}
function isNodeError(error) {
return error instanceof Error && "code" in error;
}
function parseArgs(args) {
const parsed = {
check: false,
sourceDir: DEFAULT_SOURCE_DIR,
componentDir: DEFAULT_COMPONENT_DIR,
};
for (let index = 0; index < args.length; index += 1) {
const arg = args[index];
if (arg === "--check") {
parsed.check = true;
continue;
}
if (arg === "--source-dir") {
const value = args[index + 1];
if (value === undefined) throw new Error("--source-dir requires a value");
parsed.sourceDir = value;
index += 1;
continue;
}
if (arg === "--component-dir") {
const value = args[index + 1];
if (value === undefined) throw new Error("--component-dir requires a value");
parsed.componentDir = value;
index += 1;
continue;
}
throw new Error(`unknown argument: ${arg}`);
}
return parsed;
}
async function main() {
const result = await syncTelemetryComponent(parseArgs(process.argv.slice(2)));
if (result.changed.length === 0) {
console.log("telemetry component in sync");
return;
}
console.log(`synced telemetry component: ${result.changed.join(", ")}`);
}
const invokedPath = process.argv[1] ? resolve(process.argv[1]) : "";
if (invokedPath === fileURLToPath(import.meta.url)) {
main().catch((error) => {
console.error(error instanceof Error ? error.message : error);
process.exitCode = 1;
});
}
@@ -0,0 +1,70 @@
import assert from "node:assert/strict";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
const SCRIPT_PATH = new URL("./sync-telemetry-component.mjs", import.meta.url);
async function makeTempDir() {
return mkdtemp(join(tmpdir(), "omo-codex-telemetry-sync-"));
}
async function runSync(args) {
const { syncTelemetryComponent } = await import(SCRIPT_PATH);
return syncTelemetryComponent(args);
}
test("#given stale telemetry component files #when sync runs #then pure package telemetry source rewrites the component copy", async () => {
// given
const root = await makeTempDir();
const sourceDir = join(root, "source");
const componentDir = join(root, "component");
await mkdir(sourceDir);
await mkdir(componentDir);
await writeFile(join(sourceDir, "atomic-write.ts"), "export const source = true\n", { flush: true });
await writeFile(join(componentDir, "atomic-write.ts"), "export const stale = true\n", { flush: true });
try {
// when
const result = await runSync({
sourceDir,
componentDir,
files: ["atomic-write.ts"],
check: false,
});
// then
assert.deepEqual(result, {
checked: false,
changed: ["atomic-write.ts"],
});
assert.equal(await readFile(join(componentDir, "atomic-write.ts"), "utf8"), "export const source = true\n");
} finally {
await rm(root, { recursive: true, force: true });
}
});
test("#given a missing pure telemetry source file #when sync runs #then it fails with the missing source path", async () => {
// given
const root = await makeTempDir();
const sourceDir = join(root, "source");
const componentDir = join(root, "component");
await mkdir(componentDir);
await writeFile(join(componentDir, "atomic-write.ts"), "export const stale = true\n", { flush: true });
try {
// when / then
await assert.rejects(
runSync({
sourceDir,
componentDir,
files: ["atomic-write.ts"],
check: false,
}),
(error) => error instanceof Error && error.message.includes(join(sourceDir, "atomic-write.ts")),
);
} finally {
await rm(root, { recursive: true, force: true });
}
});