codexapp 0.1.47 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/index-C55jtDWV.css +1 -0
- package/dist/assets/index-DhcIXLYw.js +1428 -0
- package/dist/index.html +2 -2
- package/dist-cli/index.js +130 -71
- package/dist-cli/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/index-DGYijDgu.css +0 -1
- package/dist/assets/index-dkC99kKB.js +0 -1442
package/dist/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Codex Web Local</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DhcIXLYw.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C55jtDWV.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body class="bg-slate-950">
|
|
11
11
|
<div id="app"></div>
|
package/dist-cli/index.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
4
|
import { createServer as createServer2 } from "http";
|
|
5
|
-
import { chmodSync, createWriteStream, existsSync as
|
|
5
|
+
import { chmodSync, createWriteStream, existsSync as existsSync5, mkdirSync } from "fs";
|
|
6
6
|
import { readFile as readFile4, stat as stat5, writeFile as writeFile4 } from "fs/promises";
|
|
7
|
-
import { homedir as
|
|
8
|
-
import { isAbsolute as isAbsolute3, join as
|
|
9
|
-
import { spawn as spawn3
|
|
7
|
+
import { homedir as homedir4, networkInterfaces } from "os";
|
|
8
|
+
import { isAbsolute as isAbsolute3, join as join6, resolve as resolve2 } from "path";
|
|
9
|
+
import { spawn as spawn3 } from "child_process";
|
|
10
10
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
11
11
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12
12
|
import { dirname as dirname3 } from "path";
|
|
@@ -16,8 +16,8 @@ import qrcode from "qrcode-terminal";
|
|
|
16
16
|
|
|
17
17
|
// src/server/httpServer.ts
|
|
18
18
|
import { fileURLToPath } from "url";
|
|
19
|
-
import { dirname as dirname2, extname as
|
|
20
|
-
import { existsSync as
|
|
19
|
+
import { dirname as dirname2, extname as extname3, isAbsolute as isAbsolute2, join as join5 } from "path";
|
|
20
|
+
import { existsSync as existsSync4 } from "fs";
|
|
21
21
|
import { writeFile as writeFile3, stat as stat4 } from "fs/promises";
|
|
22
22
|
import express from "express";
|
|
23
23
|
|
|
@@ -28,9 +28,9 @@ import { mkdtemp as mkdtemp2, readFile as readFile2, mkdir as mkdir2, stat as st
|
|
|
28
28
|
import { createReadStream } from "fs";
|
|
29
29
|
import { request as httpRequest } from "http";
|
|
30
30
|
import { request as httpsRequest } from "https";
|
|
31
|
-
import { homedir as
|
|
31
|
+
import { homedir as homedir3 } from "os";
|
|
32
32
|
import { tmpdir as tmpdir2 } from "os";
|
|
33
|
-
import { basename, isAbsolute, join as
|
|
33
|
+
import { basename as basename2, isAbsolute, join as join3, resolve } from "path";
|
|
34
34
|
import { createInterface } from "readline";
|
|
35
35
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
36
36
|
|
|
@@ -1120,6 +1120,84 @@ async function handleSkillsRoutes(req, res, url, context) {
|
|
|
1120
1120
|
return false;
|
|
1121
1121
|
}
|
|
1122
1122
|
|
|
1123
|
+
// src/utils/commandInvocation.ts
|
|
1124
|
+
import { spawnSync } from "child_process";
|
|
1125
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1126
|
+
import { homedir as homedir2 } from "os";
|
|
1127
|
+
import { basename, extname, join as join2 } from "path";
|
|
1128
|
+
var WINDOWS_CMD_NAMES = /* @__PURE__ */ new Set(["codex", "npm", "npx"]);
|
|
1129
|
+
function quoteCmdExeArg(value) {
|
|
1130
|
+
const normalized = value.replace(/"/g, '""');
|
|
1131
|
+
if (!/[\s"]/u.test(normalized)) {
|
|
1132
|
+
return normalized;
|
|
1133
|
+
}
|
|
1134
|
+
return `"${normalized}"`;
|
|
1135
|
+
}
|
|
1136
|
+
function needsCmdExeWrapper(command) {
|
|
1137
|
+
if (process.platform !== "win32") {
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
const lowerCommand = command.toLowerCase();
|
|
1141
|
+
const baseName = basename(lowerCommand);
|
|
1142
|
+
if (/\.(cmd|bat)$/i.test(baseName)) {
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1145
|
+
if (extname(baseName)) {
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
return WINDOWS_CMD_NAMES.has(baseName);
|
|
1149
|
+
}
|
|
1150
|
+
function getSpawnInvocation(command, args = []) {
|
|
1151
|
+
if (needsCmdExeWrapper(command)) {
|
|
1152
|
+
return {
|
|
1153
|
+
command: "cmd.exe",
|
|
1154
|
+
args: ["/d", "/s", "/c", [quoteCmdExeArg(command), ...args.map((arg) => quoteCmdExeArg(arg))].join(" ")]
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
return { command, args };
|
|
1158
|
+
}
|
|
1159
|
+
function spawnSyncCommand(command, args = [], options = {}) {
|
|
1160
|
+
const invocation = getSpawnInvocation(command, args);
|
|
1161
|
+
return spawnSync(invocation.command, invocation.args, options);
|
|
1162
|
+
}
|
|
1163
|
+
function canRunCommand(command, args = []) {
|
|
1164
|
+
const result = spawnSyncCommand(command, args, { stdio: "ignore" });
|
|
1165
|
+
return result.status === 0;
|
|
1166
|
+
}
|
|
1167
|
+
function getUserNpmPrefix() {
|
|
1168
|
+
return join2(homedir2(), ".npm-global");
|
|
1169
|
+
}
|
|
1170
|
+
function resolveCodexCommand() {
|
|
1171
|
+
if (canRunCommand("codex", ["--version"])) {
|
|
1172
|
+
return "codex";
|
|
1173
|
+
}
|
|
1174
|
+
if (process.platform === "win32") {
|
|
1175
|
+
const windowsCandidates = [
|
|
1176
|
+
process.env.APPDATA ? join2(process.env.APPDATA, "npm", "codex.cmd") : "",
|
|
1177
|
+
join2(homedir2(), ".local", "bin", "codex.cmd"),
|
|
1178
|
+
join2(getUserNpmPrefix(), "bin", "codex.cmd")
|
|
1179
|
+
].filter(Boolean);
|
|
1180
|
+
for (const candidate2 of windowsCandidates) {
|
|
1181
|
+
if (existsSync2(candidate2) && canRunCommand(candidate2, ["--version"])) {
|
|
1182
|
+
return candidate2;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
const userCandidate = join2(getUserNpmPrefix(), "bin", "codex");
|
|
1187
|
+
if (existsSync2(userCandidate) && canRunCommand(userCandidate, ["--version"])) {
|
|
1188
|
+
return userCandidate;
|
|
1189
|
+
}
|
|
1190
|
+
const prefix = process.env.PREFIX?.trim();
|
|
1191
|
+
if (!prefix) {
|
|
1192
|
+
return null;
|
|
1193
|
+
}
|
|
1194
|
+
const candidate = join2(prefix, "bin", "codex");
|
|
1195
|
+
if (existsSync2(candidate) && canRunCommand(candidate, ["--version"])) {
|
|
1196
|
+
return candidate;
|
|
1197
|
+
}
|
|
1198
|
+
return null;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1123
1201
|
// src/server/codexAppServerBridge.ts
|
|
1124
1202
|
function asRecord2(value) {
|
|
1125
1203
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -1224,7 +1302,7 @@ async function listFilesWithRipgrep(cwd) {
|
|
|
1224
1302
|
}
|
|
1225
1303
|
function getCodexHomeDir2() {
|
|
1226
1304
|
const codexHome = process.env.CODEX_HOME?.trim();
|
|
1227
|
-
return codexHome && codexHome.length > 0 ? codexHome :
|
|
1305
|
+
return codexHome && codexHome.length > 0 ? codexHome : join3(homedir3(), ".codex");
|
|
1228
1306
|
}
|
|
1229
1307
|
async function runCommand2(command, args, options = {}) {
|
|
1230
1308
|
await new Promise((resolve3, reject) => {
|
|
@@ -1262,7 +1340,7 @@ function isNotGitRepositoryError(error) {
|
|
|
1262
1340
|
return message.includes("not a git repository") || message.includes("fatal: not a git repository");
|
|
1263
1341
|
}
|
|
1264
1342
|
async function ensureRepoHasInitialCommit(repoRoot) {
|
|
1265
|
-
const agentsPath =
|
|
1343
|
+
const agentsPath = join3(repoRoot, "AGENTS.md");
|
|
1266
1344
|
try {
|
|
1267
1345
|
await stat2(agentsPath);
|
|
1268
1346
|
} catch {
|
|
@@ -1323,7 +1401,7 @@ function normalizeStringRecord(value) {
|
|
|
1323
1401
|
return next;
|
|
1324
1402
|
}
|
|
1325
1403
|
function getCodexAuthPath() {
|
|
1326
|
-
return
|
|
1404
|
+
return join3(getCodexHomeDir2(), "auth.json");
|
|
1327
1405
|
}
|
|
1328
1406
|
async function readCodexAuth() {
|
|
1329
1407
|
try {
|
|
@@ -1337,10 +1415,10 @@ async function readCodexAuth() {
|
|
|
1337
1415
|
}
|
|
1338
1416
|
}
|
|
1339
1417
|
function getCodexGlobalStatePath() {
|
|
1340
|
-
return
|
|
1418
|
+
return join3(getCodexHomeDir2(), ".codex-global-state.json");
|
|
1341
1419
|
}
|
|
1342
1420
|
function getCodexSessionIndexPath() {
|
|
1343
|
-
return
|
|
1421
|
+
return join3(getCodexHomeDir2(), "session_index.jsonl");
|
|
1344
1422
|
}
|
|
1345
1423
|
var MAX_THREAD_TITLES = 500;
|
|
1346
1424
|
var EMPTY_THREAD_TITLE_CACHE = { titles: {}, order: [] };
|
|
@@ -1599,10 +1677,10 @@ function handleFileUpload(req, res) {
|
|
|
1599
1677
|
setJson2(res, 400, { error: "No file in request" });
|
|
1600
1678
|
return;
|
|
1601
1679
|
}
|
|
1602
|
-
const uploadDir =
|
|
1680
|
+
const uploadDir = join3(tmpdir2(), "codex-web-uploads");
|
|
1603
1681
|
await mkdir2(uploadDir, { recursive: true });
|
|
1604
|
-
const destDir = await mkdtemp2(
|
|
1605
|
-
const destPath =
|
|
1682
|
+
const destDir = await mkdtemp2(join3(uploadDir, "f-"));
|
|
1683
|
+
const destPath = join3(destDir, fileName);
|
|
1606
1684
|
await writeFile2(destPath, fileData);
|
|
1607
1685
|
setJson2(res, 200, { path: destPath });
|
|
1608
1686
|
} catch (err) {
|
|
@@ -1709,7 +1787,8 @@ var AppServerProcess = class {
|
|
|
1709
1787
|
start() {
|
|
1710
1788
|
if (this.process) return;
|
|
1711
1789
|
this.stopping = false;
|
|
1712
|
-
const
|
|
1790
|
+
const invocation = getSpawnInvocation(resolveCodexCommand() ?? "codex", this.appServerArgs);
|
|
1791
|
+
const proc = spawn2(invocation.command, invocation.args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
1713
1792
|
this.process = proc;
|
|
1714
1793
|
proc.stdout.setEncoding("utf8");
|
|
1715
1794
|
proc.stdout.on("data", (chunk) => {
|
|
@@ -1935,7 +2014,8 @@ var MethodCatalog = class {
|
|
|
1935
2014
|
}
|
|
1936
2015
|
async runGenerateSchemaCommand(outDir) {
|
|
1937
2016
|
await new Promise((resolve3, reject) => {
|
|
1938
|
-
const
|
|
2017
|
+
const invocation = getSpawnInvocation(resolveCodexCommand() ?? "codex", ["app-server", "generate-json-schema", "--out", outDir]);
|
|
2018
|
+
const process2 = spawn2(invocation.command, invocation.args, {
|
|
1939
2019
|
stdio: ["ignore", "ignore", "pipe"]
|
|
1940
2020
|
});
|
|
1941
2021
|
let stderr = "";
|
|
@@ -1991,9 +2071,9 @@ var MethodCatalog = class {
|
|
|
1991
2071
|
if (this.methodCache) {
|
|
1992
2072
|
return this.methodCache;
|
|
1993
2073
|
}
|
|
1994
|
-
const outDir = await mkdtemp2(
|
|
2074
|
+
const outDir = await mkdtemp2(join3(tmpdir2(), "codex-web-local-schema-"));
|
|
1995
2075
|
await this.runGenerateSchemaCommand(outDir);
|
|
1996
|
-
const clientRequestPath =
|
|
2076
|
+
const clientRequestPath = join3(outDir, "ClientRequest.json");
|
|
1997
2077
|
const raw = await readFile2(clientRequestPath, "utf8");
|
|
1998
2078
|
const parsed = JSON.parse(raw);
|
|
1999
2079
|
const methods = this.extractMethodsFromClientRequest(parsed);
|
|
@@ -2004,9 +2084,9 @@ var MethodCatalog = class {
|
|
|
2004
2084
|
if (this.notificationCache) {
|
|
2005
2085
|
return this.notificationCache;
|
|
2006
2086
|
}
|
|
2007
|
-
const outDir = await mkdtemp2(
|
|
2087
|
+
const outDir = await mkdtemp2(join3(tmpdir2(), "codex-web-local-schema-"));
|
|
2008
2088
|
await this.runGenerateSchemaCommand(outDir);
|
|
2009
|
-
const serverNotificationPath =
|
|
2089
|
+
const serverNotificationPath = join3(outDir, "ServerNotification.json");
|
|
2010
2090
|
const raw = await readFile2(serverNotificationPath, "utf8");
|
|
2011
2091
|
const parsed = JSON.parse(raw);
|
|
2012
2092
|
const methods = this.extractMethodsFromServerNotification(parsed);
|
|
@@ -2168,7 +2248,7 @@ function createCodexBridgeMiddleware() {
|
|
|
2168
2248
|
return;
|
|
2169
2249
|
}
|
|
2170
2250
|
if (req.method === "GET" && url.pathname === "/codex-api/home-directory") {
|
|
2171
|
-
setJson2(res, 200, { data: { path:
|
|
2251
|
+
setJson2(res, 200, { data: { path: homedir3() } });
|
|
2172
2252
|
return;
|
|
2173
2253
|
}
|
|
2174
2254
|
if (req.method === "POST" && url.pathname === "/codex-api/worktree/create") {
|
|
@@ -2198,22 +2278,22 @@ function createCodexBridgeMiddleware() {
|
|
|
2198
2278
|
await runCommand2("git", ["init"], { cwd: sourceCwd });
|
|
2199
2279
|
gitRoot = await runCommandCapture("git", ["rev-parse", "--show-toplevel"], { cwd: sourceCwd });
|
|
2200
2280
|
}
|
|
2201
|
-
const repoName =
|
|
2202
|
-
const worktreesRoot =
|
|
2281
|
+
const repoName = basename2(gitRoot) || "repo";
|
|
2282
|
+
const worktreesRoot = join3(getCodexHomeDir2(), "worktrees");
|
|
2203
2283
|
await mkdir2(worktreesRoot, { recursive: true });
|
|
2204
2284
|
let worktreeId = "";
|
|
2205
2285
|
let worktreeParent = "";
|
|
2206
2286
|
let worktreeCwd = "";
|
|
2207
2287
|
for (let attempt = 0; attempt < 12; attempt += 1) {
|
|
2208
2288
|
const candidate = randomBytes(2).toString("hex");
|
|
2209
|
-
const parent =
|
|
2289
|
+
const parent = join3(worktreesRoot, candidate);
|
|
2210
2290
|
try {
|
|
2211
2291
|
await stat2(parent);
|
|
2212
2292
|
continue;
|
|
2213
2293
|
} catch {
|
|
2214
2294
|
worktreeId = candidate;
|
|
2215
2295
|
worktreeParent = parent;
|
|
2216
|
-
worktreeCwd =
|
|
2296
|
+
worktreeCwd = join3(parent, repoName);
|
|
2217
2297
|
break;
|
|
2218
2298
|
}
|
|
2219
2299
|
}
|
|
@@ -2318,7 +2398,7 @@ function createCodexBridgeMiddleware() {
|
|
|
2318
2398
|
let index = 1;
|
|
2319
2399
|
while (index < 1e5) {
|
|
2320
2400
|
const candidateName = `New Project (${String(index)})`;
|
|
2321
|
-
const candidatePath =
|
|
2401
|
+
const candidatePath = join3(normalizedBasePath, candidateName);
|
|
2322
2402
|
try {
|
|
2323
2403
|
await stat2(candidatePath);
|
|
2324
2404
|
index += 1;
|
|
@@ -2564,7 +2644,7 @@ function createAuthSession(password) {
|
|
|
2564
2644
|
}
|
|
2565
2645
|
|
|
2566
2646
|
// src/server/localBrowseUi.ts
|
|
2567
|
-
import { dirname, extname, join as
|
|
2647
|
+
import { dirname, extname as extname2, join as join4 } from "path";
|
|
2568
2648
|
import { open, readFile as readFile3, readdir as readdir3, stat as stat3 } from "fs/promises";
|
|
2569
2649
|
var TEXT_EDITABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2570
2650
|
".txt",
|
|
@@ -2595,7 +2675,7 @@ var TEXT_EDITABLE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
2595
2675
|
".ps1"
|
|
2596
2676
|
]);
|
|
2597
2677
|
function languageForPath(pathValue) {
|
|
2598
|
-
const extension =
|
|
2678
|
+
const extension = extname2(pathValue).toLowerCase();
|
|
2599
2679
|
switch (extension) {
|
|
2600
2680
|
case ".js":
|
|
2601
2681
|
return "javascript";
|
|
@@ -2656,7 +2736,7 @@ function decodeBrowsePath(rawPath) {
|
|
|
2656
2736
|
}
|
|
2657
2737
|
}
|
|
2658
2738
|
function isTextEditablePath(pathValue) {
|
|
2659
|
-
return TEXT_EDITABLE_EXTENSIONS.has(
|
|
2739
|
+
return TEXT_EDITABLE_EXTENSIONS.has(extname2(pathValue).toLowerCase());
|
|
2660
2740
|
}
|
|
2661
2741
|
function looksLikeTextBuffer(buffer) {
|
|
2662
2742
|
if (buffer.length === 0) return true;
|
|
@@ -2702,7 +2782,7 @@ function escapeForInlineScriptString(value) {
|
|
|
2702
2782
|
async function getDirectoryItems(localPath) {
|
|
2703
2783
|
const entries = await readdir3(localPath, { withFileTypes: true });
|
|
2704
2784
|
const withMeta = await Promise.all(entries.map(async (entry) => {
|
|
2705
|
-
const entryPath =
|
|
2785
|
+
const entryPath = join4(localPath, entry.name);
|
|
2706
2786
|
const entryStat = await stat3(entryPath);
|
|
2707
2787
|
const editable = !entry.isDirectory() && await isTextEditableFile(entryPath);
|
|
2708
2788
|
return {
|
|
@@ -2889,8 +2969,8 @@ async function createTextEditorHtml(localPath) {
|
|
|
2889
2969
|
// src/server/httpServer.ts
|
|
2890
2970
|
import { WebSocketServer } from "ws";
|
|
2891
2971
|
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
2892
|
-
var distDir =
|
|
2893
|
-
var spaEntryFile =
|
|
2972
|
+
var distDir = join5(__dirname, "..", "dist");
|
|
2973
|
+
var spaEntryFile = join5(distDir, "index.html");
|
|
2894
2974
|
var IMAGE_CONTENT_TYPES = {
|
|
2895
2975
|
".avif": "image/avif",
|
|
2896
2976
|
".bmp": "image/bmp",
|
|
@@ -2947,7 +3027,7 @@ function createServer(options = {}) {
|
|
|
2947
3027
|
res.status(400).json({ error: "Expected absolute local file path." });
|
|
2948
3028
|
return;
|
|
2949
3029
|
}
|
|
2950
|
-
const contentType = IMAGE_CONTENT_TYPES[
|
|
3030
|
+
const contentType = IMAGE_CONTENT_TYPES[extname3(localPath).toLowerCase()];
|
|
2951
3031
|
if (!contentType) {
|
|
2952
3032
|
res.status(415).json({ error: "Unsupported image type." });
|
|
2953
3033
|
return;
|
|
@@ -3034,7 +3114,7 @@ function createServer(options = {}) {
|
|
|
3034
3114
|
res.status(404).json({ error: "File not found." });
|
|
3035
3115
|
}
|
|
3036
3116
|
});
|
|
3037
|
-
const hasFrontendAssets =
|
|
3117
|
+
const hasFrontendAssets = existsSync4(spaEntryFile);
|
|
3038
3118
|
if (hasFrontendAssets) {
|
|
3039
3119
|
app.use(express.static(distDir));
|
|
3040
3120
|
}
|
|
@@ -3107,7 +3187,7 @@ var program = new Command().name("codexui").description("Web interface for Codex
|
|
|
3107
3187
|
var __dirname2 = dirname3(fileURLToPath2(import.meta.url));
|
|
3108
3188
|
async function readCliVersion() {
|
|
3109
3189
|
try {
|
|
3110
|
-
const packageJsonPath =
|
|
3190
|
+
const packageJsonPath = join6(__dirname2, "..", "package.json");
|
|
3111
3191
|
const raw = await readFile4(packageJsonPath, "utf8");
|
|
3112
3192
|
const parsed = JSON.parse(raw);
|
|
3113
3193
|
return typeof parsed.version === "string" ? parsed.version : "unknown";
|
|
@@ -3119,46 +3199,25 @@ function isTermuxRuntime() {
|
|
|
3119
3199
|
return Boolean(process.env.TERMUX_VERSION || process.env.PREFIX?.includes("/com.termux/"));
|
|
3120
3200
|
}
|
|
3121
3201
|
function canRun(command, args = []) {
|
|
3122
|
-
const result =
|
|
3123
|
-
return result
|
|
3202
|
+
const result = canRunCommand(command, args);
|
|
3203
|
+
return result;
|
|
3124
3204
|
}
|
|
3125
3205
|
function runOrFail(command, args, label) {
|
|
3126
|
-
const result =
|
|
3206
|
+
const result = spawnSyncCommand(command, args, { stdio: "inherit" });
|
|
3127
3207
|
if (result.status !== 0) {
|
|
3128
3208
|
throw new Error(`${label} failed with exit code ${String(result.status ?? -1)}`);
|
|
3129
3209
|
}
|
|
3130
3210
|
}
|
|
3131
3211
|
function runWithStatus(command, args) {
|
|
3132
|
-
const result =
|
|
3212
|
+
const result = spawnSyncCommand(command, args, { stdio: "inherit" });
|
|
3133
3213
|
return result.status ?? -1;
|
|
3134
3214
|
}
|
|
3135
|
-
function getUserNpmPrefix() {
|
|
3136
|
-
return join5(homedir3(), ".npm-global");
|
|
3137
|
-
}
|
|
3138
|
-
function resolveCodexCommand() {
|
|
3139
|
-
if (canRun("codex", ["--version"])) {
|
|
3140
|
-
return "codex";
|
|
3141
|
-
}
|
|
3142
|
-
const userCandidate = join5(getUserNpmPrefix(), "bin", "codex");
|
|
3143
|
-
if (existsSync4(userCandidate) && canRun(userCandidate, ["--version"])) {
|
|
3144
|
-
return userCandidate;
|
|
3145
|
-
}
|
|
3146
|
-
const prefix = process.env.PREFIX?.trim();
|
|
3147
|
-
if (!prefix) {
|
|
3148
|
-
return null;
|
|
3149
|
-
}
|
|
3150
|
-
const candidate = join5(prefix, "bin", "codex");
|
|
3151
|
-
if (existsSync4(candidate) && canRun(candidate, ["--version"])) {
|
|
3152
|
-
return candidate;
|
|
3153
|
-
}
|
|
3154
|
-
return null;
|
|
3155
|
-
}
|
|
3156
3215
|
function resolveCloudflaredCommand() {
|
|
3157
3216
|
if (canRun("cloudflared", ["--version"])) {
|
|
3158
3217
|
return "cloudflared";
|
|
3159
3218
|
}
|
|
3160
|
-
const localCandidate =
|
|
3161
|
-
if (
|
|
3219
|
+
const localCandidate = join6(homedir4(), ".local", "bin", "cloudflared");
|
|
3220
|
+
if (existsSync5(localCandidate) && canRun(localCandidate, ["--version"])) {
|
|
3162
3221
|
return localCandidate;
|
|
3163
3222
|
}
|
|
3164
3223
|
return null;
|
|
@@ -3211,9 +3270,9 @@ async function ensureCloudflaredInstalledLinux() {
|
|
|
3211
3270
|
if (!mappedArch) {
|
|
3212
3271
|
throw new Error(`cloudflared auto-install is not supported for Linux architecture: ${process.arch}`);
|
|
3213
3272
|
}
|
|
3214
|
-
const userBinDir =
|
|
3273
|
+
const userBinDir = join6(homedir4(), ".local", "bin");
|
|
3215
3274
|
mkdirSync(userBinDir, { recursive: true });
|
|
3216
|
-
const destination =
|
|
3275
|
+
const destination = join6(userBinDir, "cloudflared");
|
|
3217
3276
|
const downloadUrl = `https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${mappedArch}`;
|
|
3218
3277
|
console.log("\ncloudflared not found. Installing to ~/.local/bin...\n");
|
|
3219
3278
|
await downloadFile(downloadUrl, destination);
|
|
@@ -3252,8 +3311,8 @@ async function resolveCloudflaredForTunnel() {
|
|
|
3252
3311
|
return ensureCloudflaredInstalledLinux();
|
|
3253
3312
|
}
|
|
3254
3313
|
function hasCodexAuth() {
|
|
3255
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
3256
|
-
return
|
|
3314
|
+
const codexHome = process.env.CODEX_HOME?.trim() || join6(homedir4(), ".codex");
|
|
3315
|
+
return existsSync5(join6(codexHome, "auth.json"));
|
|
3257
3316
|
}
|
|
3258
3317
|
function ensureCodexInstalled() {
|
|
3259
3318
|
let codexCommand = resolveCodexCommand();
|
|
@@ -3271,7 +3330,7 @@ function ensureCodexInstalled() {
|
|
|
3271
3330
|
Global npm install requires elevated permissions. Retrying with --prefix ${userPrefix}...
|
|
3272
3331
|
`);
|
|
3273
3332
|
runOrFail("npm", ["install", "-g", "--prefix", userPrefix, pkg], `${label} (user prefix)`);
|
|
3274
|
-
process.env.PATH = `${
|
|
3333
|
+
process.env.PATH = `${join6(userPrefix, "bin")}:${process.env.PATH ?? ""}`;
|
|
3275
3334
|
};
|
|
3276
3335
|
if (isTermuxRuntime()) {
|
|
3277
3336
|
console.log("\nCodex CLI not found. Installing Termux-compatible Codex CLI from npm...\n");
|
|
@@ -3412,8 +3471,8 @@ function listenWithFallback(server, startPort) {
|
|
|
3412
3471
|
});
|
|
3413
3472
|
}
|
|
3414
3473
|
function getCodexGlobalStatePath2() {
|
|
3415
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
3416
|
-
return
|
|
3474
|
+
const codexHome = process.env.CODEX_HOME?.trim() || join6(homedir4(), ".codex");
|
|
3475
|
+
return join6(codexHome, ".codex-global-state.json");
|
|
3417
3476
|
}
|
|
3418
3477
|
function normalizeUniqueStrings(value) {
|
|
3419
3478
|
if (!Array.isArray(value)) return [];
|