Skip to content

Commit 3e34a57

Browse files
committed
fix: target official Codex plugin install paths
1 parent 8c22ddd commit 3e34a57

3 files changed

Lines changed: 196 additions & 173 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
},
7474
"files": [
7575
"dist/",
76+
"codex-plugin/",
77+
".agents/",
7678
"assets/",
7779
"config/",
7880
"scripts/",

scripts/install-codex-auth-utils.js

Lines changed: 111 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,137 @@
1-
import { join } from "node:path";
1+
import { dirname, join } from "node:path";
22
import { homedir } from "node:os";
33
import { rename as fsRename } from "node:fs/promises";
44

5-
const PLUGIN_NAME = "codex-multi-auth";
5+
export const PLUGIN_NAME = "codex-multi-auth";
6+
export const PLUGIN_MARKETPLACE = "ndycode";
7+
export const PLUGIN_VERSION = "local";
68
export const FILE_RETRY_CODES = new Set(["EBUSY", "EPERM", "EAGAIN", "ENOTEMPTY", "EACCES"]);
79
export const FILE_RETRY_MAX_ATTEMPTS = 6;
810
export const FILE_RETRY_BASE_DELAY_MS = 25;
911
export const FILE_RETRY_JITTER_MS = 20;
1012

13+
function firstNonEmpty(values) {
14+
for (const value of values) {
15+
const trimmed = (value ?? "").trim();
16+
if (trimmed.length > 0) {
17+
return trimmed;
18+
}
19+
}
20+
return null;
21+
}
22+
23+
export function resolveCodexHomeDir(
24+
platform = process.platform,
25+
env = process.env,
26+
home = homedir(),
27+
) {
28+
const override = (env.CODEX_HOME ?? "").trim();
29+
if (override.length > 0) {
30+
return override;
31+
}
32+
if (platform === "win32") {
33+
const homeDrive = (env.HOMEDRIVE ?? "").trim();
34+
const homePath = (env.HOMEPATH ?? "").trim();
35+
const drivePathHome =
36+
homeDrive.length > 0 && homePath.length > 0
37+
? `${homeDrive}${homePath}`
38+
: undefined;
39+
return join(
40+
firstNonEmpty([env.USERPROFILE, env.HOME, drivePathHome, home]) ?? home,
41+
".codex",
42+
);
43+
}
44+
return join(firstNonEmpty([env.HOME, home]) ?? home, ".codex");
45+
}
46+
47+
export function makePluginKey(
48+
pluginName = PLUGIN_NAME,
49+
marketplaceName = PLUGIN_MARKETPLACE,
50+
) {
51+
return `${pluginName}@${marketplaceName}`;
52+
}
53+
1154
export function resolveInstallPaths(
1255
platform = process.platform,
1356
env = process.env,
1457
home = homedir(),
58+
pluginName = PLUGIN_NAME,
59+
marketplaceName = PLUGIN_MARKETPLACE,
60+
pluginVersion = PLUGIN_VERSION,
1561
) {
16-
const isWindows = platform === "win32";
17-
const appData = (env.APPDATA ?? "").trim();
18-
const localAppData = (env.LOCALAPPDATA ?? appData).trim();
19-
const configBase = isWindows
20-
? appData || join(home, "AppData", "Roaming")
21-
: join(home, ".config");
22-
const cacheBase = isWindows
23-
? localAppData || join(home, "AppData", "Local")
24-
: join(home, ".cache");
25-
const configDir = join(configBase, "Codex");
26-
const configPath = join(configDir, "Codex.json");
27-
const cacheDir = join(cacheBase, "Codex");
62+
const codexHomeDir = resolveCodexHomeDir(platform, env, home);
63+
const configPathOverride = (env.CODEX_CLI_CONFIG_PATH ?? "").trim();
64+
const configPath = configPathOverride.length > 0
65+
? configPathOverride
66+
: join(codexHomeDir, "config.toml");
67+
const configDir = dirname(configPath);
68+
const pluginsCacheDir = join(codexHomeDir, "plugins", "cache");
69+
const pluginBaseDir = join(pluginsCacheDir, marketplaceName, pluginName);
70+
const pluginInstallDir = join(pluginBaseDir, pluginVersion);
2871
return {
72+
codexHomeDir,
2973
configDir,
3074
configPath,
31-
cacheDir,
32-
cacheNodeModules: join(cacheDir, "node_modules", PLUGIN_NAME),
33-
cacheBunLock: join(cacheDir, "bun.lock"),
34-
cachePackageJson: join(cacheDir, "package.json"),
75+
pluginsCacheDir,
76+
pluginBaseDir,
77+
pluginInstallDir,
78+
pluginKey: makePluginKey(pluginName, marketplaceName),
79+
pluginName,
80+
marketplaceName,
81+
pluginVersion,
3582
};
3683
}
3784

38-
export function normalizePluginList(list) {
39-
const entries = Array.isArray(list) ? list.filter(Boolean) : [];
40-
const filtered = entries.filter((entry) => {
41-
if (typeof entry !== "string") return true;
42-
return entry !== PLUGIN_NAME && !entry.startsWith(`${PLUGIN_NAME}@`);
43-
});
44-
const deduped = [];
45-
const seen = new Set();
46-
for (const entry of filtered) {
47-
const key = typeof entry === "string" ? `s:${entry}` : `j:${JSON.stringify(entry)}`;
48-
if (seen.has(key)) continue;
49-
seen.add(key);
50-
deduped.push(entry);
85+
function splitLines(content) {
86+
return content.replace(/\r\n/g, "\n").split("\n");
87+
}
88+
89+
function findSectionRange(lines, sectionHeader) {
90+
const headerIndex = lines.findIndex((line) => line.trim() === sectionHeader);
91+
if (headerIndex === -1) {
92+
return null;
93+
}
94+
let endIndex = lines.length;
95+
for (let index = headerIndex + 1; index < lines.length; index += 1) {
96+
if (/^\s*\[[^\]]+\]\s*$/.test(lines[index])) {
97+
endIndex = index;
98+
break;
99+
}
100+
}
101+
return { headerIndex, endIndex };
102+
}
103+
104+
function upsertTomlBoolean(content, sectionHeader, key, enabled) {
105+
const lines = splitLines(content.trim());
106+
const normalized = lines.length === 1 && lines[0] === "" ? [] : lines;
107+
const keyLine = `${key} = ${enabled ? "true" : "false"}`;
108+
const range = findSectionRange(normalized, sectionHeader);
109+
110+
if (!range) {
111+
if (normalized.length > 0 && normalized[normalized.length - 1] !== "") {
112+
normalized.push("");
113+
}
114+
normalized.push(sectionHeader, keyLine);
115+
return `${normalized.join("\n")}\n`;
116+
}
117+
118+
for (let index = range.headerIndex + 1; index < range.endIndex; index += 1) {
119+
if (new RegExp(`^\\s*${key}\\s*=`).test(normalized[index])) {
120+
normalized[index] = keyLine;
121+
return `${normalized.join("\n")}\n`;
122+
}
51123
}
52-
return [...deduped, PLUGIN_NAME];
124+
125+
normalized.splice(range.endIndex, 0, keyLine);
126+
return `${normalized.join("\n")}\n`;
127+
}
128+
129+
export function mergePluginConfigToml(content, pluginKey) {
130+
const withFeatures = upsertTomlBoolean(content, "[features]", "plugins", true);
131+
return upsertTomlBoolean(withFeatures, `[plugins."${pluginKey}"]`, "enabled", true);
53132
}
54133

55134
function sleep(ms) {
56-
// Keep this helper local so installer scripts remain standalone and do not depend on lib/.
57135
return new Promise((resolve) => {
58136
setTimeout(resolve, ms);
59137
});

0 commit comments

Comments
 (0)