@childclm/codexx 0.1.2 → 0.1.4
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/bin/codexx.js +0 -0
- package/package.json +1 -1
- package/src/index.js +113 -48
package/bin/codexx.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -144,50 +144,46 @@ function resolveWindowsCodexCandidates() {
|
|
|
144
144
|
const candidates = [];
|
|
145
145
|
const appData = process.env.APPDATA || path.join(HOME, "AppData", "Roaming");
|
|
146
146
|
const npmRoot = path.join(appData, "npm");
|
|
147
|
-
const localShims = [
|
|
148
|
-
path.join(npmRoot, "codex.exe"),
|
|
149
|
-
path.join(npmRoot, "codex.cmd"),
|
|
150
|
-
path.join(npmRoot, "codex"),
|
|
151
|
-
];
|
|
152
|
-
candidates.push(...localShims);
|
|
153
147
|
|
|
154
|
-
const
|
|
155
|
-
const foundExe = (finder.stdout || "")
|
|
156
|
-
.trim()
|
|
157
|
-
.split(/\r?\n/)
|
|
158
|
-
.filter(Boolean);
|
|
159
|
-
candidates.push(...foundExe);
|
|
160
|
-
|
|
161
|
-
const foundCmd = spawnSync("where", ["codex.cmd"], { encoding: "utf8" });
|
|
162
|
-
const cmdHits = (foundCmd.stdout || "")
|
|
163
|
-
.trim()
|
|
164
|
-
.split(/\r?\n/)
|
|
165
|
-
.filter(Boolean);
|
|
166
|
-
candidates.push(...cmdHits);
|
|
167
|
-
|
|
168
|
-
const directVendorParent = path.join(
|
|
148
|
+
const nativePackageScope = path.join(
|
|
169
149
|
npmRoot,
|
|
170
150
|
"node_modules",
|
|
171
151
|
"@openai",
|
|
172
152
|
"codex",
|
|
173
153
|
"node_modules",
|
|
154
|
+
"@openai",
|
|
174
155
|
);
|
|
175
|
-
if (fileExists(
|
|
156
|
+
if (fileExists(nativePackageScope)) {
|
|
176
157
|
try {
|
|
177
|
-
const dirs = fs.readdirSync(
|
|
158
|
+
const dirs = fs.readdirSync(nativePackageScope);
|
|
178
159
|
for (const dir of dirs) {
|
|
179
|
-
if (!dir.
|
|
180
|
-
const vendorRoot = path.join(
|
|
160
|
+
if (!dir.startsWith("codex-win32-")) continue;
|
|
161
|
+
const vendorRoot = path.join(nativePackageScope, dir, "vendor");
|
|
181
162
|
if (!fileExists(vendorRoot)) continue;
|
|
182
163
|
const vendorDirs = fs.readdirSync(vendorRoot);
|
|
183
164
|
for (const vendorDir of vendorDirs) {
|
|
184
|
-
|
|
185
|
-
candidates.push(exePath);
|
|
165
|
+
candidates.push(path.join(vendorRoot, vendorDir, "bin", "codex.exe"));
|
|
186
166
|
}
|
|
187
167
|
}
|
|
188
168
|
} catch {}
|
|
189
169
|
}
|
|
190
170
|
|
|
171
|
+
candidates.push(path.join(npmRoot, "codex.cmd"), path.join(npmRoot, "codex"));
|
|
172
|
+
|
|
173
|
+
const finder = spawnSync("where", ["codex.exe"], { encoding: "utf8" });
|
|
174
|
+
const foundExe = (finder.stdout || "")
|
|
175
|
+
.trim()
|
|
176
|
+
.split(/\r?\n/)
|
|
177
|
+
.filter(Boolean);
|
|
178
|
+
candidates.push(...foundExe);
|
|
179
|
+
|
|
180
|
+
const foundCmd = spawnSync("where", ["codex.cmd"], { encoding: "utf8" });
|
|
181
|
+
const cmdHits = (foundCmd.stdout || "")
|
|
182
|
+
.trim()
|
|
183
|
+
.split(/\r?\n/)
|
|
184
|
+
.filter(Boolean);
|
|
185
|
+
candidates.push(...cmdHits);
|
|
186
|
+
|
|
191
187
|
return [...new Set(candidates)].filter(Boolean);
|
|
192
188
|
}
|
|
193
189
|
|
|
@@ -268,6 +264,30 @@ function clearScreen() {
|
|
|
268
264
|
process.stdout.write("\x1b[2J\x1b[0f");
|
|
269
265
|
}
|
|
270
266
|
|
|
267
|
+
function resetTerminalForChild() {
|
|
268
|
+
process.stdout.write("\x1b[0m\x1b[2J\x1b[3J\x1b[H");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function suspendTerminalForChild(rl) {
|
|
272
|
+
setRawMode(false);
|
|
273
|
+
if (rl && typeof rl.pause === "function") {
|
|
274
|
+
rl.pause();
|
|
275
|
+
}
|
|
276
|
+
if (typeof process.stdin.pause === "function") {
|
|
277
|
+
process.stdin.pause();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function resumeTerminalAfterChild(rl) {
|
|
282
|
+
if (typeof process.stdin.resume === "function") {
|
|
283
|
+
process.stdin.resume();
|
|
284
|
+
}
|
|
285
|
+
if (rl && typeof rl.resume === "function") {
|
|
286
|
+
rl.resume();
|
|
287
|
+
}
|
|
288
|
+
setRawMode(true);
|
|
289
|
+
}
|
|
290
|
+
|
|
271
291
|
function prompt(rl, text) {
|
|
272
292
|
return new Promise((resolve) => rl.question(text, resolve));
|
|
273
293
|
}
|
|
@@ -472,23 +492,63 @@ function hasOfficialSession(sessionId, projectRoot) {
|
|
|
472
492
|
|
|
473
493
|
function buildCodexEnv(provider) {
|
|
474
494
|
return {
|
|
495
|
+
CODEXX_PROVIDER_API_KEY: provider.apiKey,
|
|
475
496
|
OPENAI_API_KEY: provider.apiKey,
|
|
476
497
|
OPENAI_BASE_URL: provider.baseUrl || process.env.OPENAI_BASE_URL,
|
|
477
498
|
};
|
|
478
499
|
}
|
|
479
500
|
|
|
480
|
-
function
|
|
501
|
+
function tomlString(value) {
|
|
502
|
+
return JSON.stringify(String(value));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function buildCodexProviderArgs(provider) {
|
|
506
|
+
if (!provider || !provider.baseUrl) return [];
|
|
507
|
+
|
|
508
|
+
const providerKey = "codexx";
|
|
509
|
+
const providerDisplayName = provider.modelProvider || "OpenAI";
|
|
510
|
+
return [
|
|
511
|
+
"-c",
|
|
512
|
+
`model_provider=${tomlString(providerKey)}`,
|
|
513
|
+
"-c",
|
|
514
|
+
`model_providers.${providerKey}.name=${tomlString(providerDisplayName)}`,
|
|
515
|
+
"-c",
|
|
516
|
+
`model_providers.${providerKey}.base_url=${tomlString(provider.baseUrl)}`,
|
|
517
|
+
"-c",
|
|
518
|
+
`model_providers.${providerKey}.wire_api=${tomlString("responses")}`,
|
|
519
|
+
"-c",
|
|
520
|
+
`model_providers.${providerKey}.requires_openai_auth=false`,
|
|
521
|
+
"-c",
|
|
522
|
+
`model_providers.${providerKey}.env_key=${tomlString("CODEXX_PROVIDER_API_KEY")}`,
|
|
523
|
+
];
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function runCodex(args, env, cwd = process.cwd(), rl = null, provider = null) {
|
|
481
527
|
return new Promise((resolve, reject) => {
|
|
482
528
|
const cmd = resolveCodexCommand();
|
|
483
|
-
const launch = buildCodexLaunch(
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
529
|
+
const launch = buildCodexLaunch(
|
|
530
|
+
cmd,
|
|
531
|
+
[...buildCodexProviderArgs(provider), ...args],
|
|
532
|
+
);
|
|
533
|
+
const settle = (done, value) => {
|
|
534
|
+
resumeTerminalAfterChild(rl);
|
|
535
|
+
done(value);
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
try {
|
|
539
|
+
suspendTerminalForChild(rl);
|
|
540
|
+
resetTerminalForChild();
|
|
541
|
+
const child = spawn(launch.command, launch.args, {
|
|
542
|
+
cwd,
|
|
543
|
+
stdio: "inherit",
|
|
544
|
+
env: { ...process.env, ...env },
|
|
545
|
+
shell: launch.shell,
|
|
546
|
+
});
|
|
547
|
+
child.on("error", (error) => settle(reject, error));
|
|
548
|
+
child.on("exit", (code) => settle(resolve, code ?? 0));
|
|
549
|
+
} catch (error) {
|
|
550
|
+
settle(reject, error);
|
|
551
|
+
}
|
|
492
552
|
});
|
|
493
553
|
}
|
|
494
554
|
|
|
@@ -848,10 +908,8 @@ async function launchNewSession(rl, cwd = process.cwd()) {
|
|
|
848
908
|
console.log(`准备启动新主线会话 · provider=${provider.name}`);
|
|
849
909
|
await pause(rl, "按回车进入 Codex...");
|
|
850
910
|
|
|
851
|
-
setRawMode(false);
|
|
852
911
|
const startedAtMs = Date.now();
|
|
853
|
-
await runCodex([], buildCodexEnv(provider), projectState.root);
|
|
854
|
-
setRawMode(true);
|
|
912
|
+
await runCodex([], buildCodexEnv(provider), projectState.root, rl, provider);
|
|
855
913
|
|
|
856
914
|
const linkedSessionId = await maybeLinkLatestSession(
|
|
857
915
|
projectState.root,
|
|
@@ -939,9 +997,13 @@ async function resumeSpecificSession(rl, sessionId, cwd = process.cwd()) {
|
|
|
939
997
|
console.log(`provider=${provider.name}`);
|
|
940
998
|
await pause(rl, "按回车进入 Codex...");
|
|
941
999
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1000
|
+
await runCodex(
|
|
1001
|
+
["resume", sessionId],
|
|
1002
|
+
buildCodexEnv(provider),
|
|
1003
|
+
projectState.root,
|
|
1004
|
+
rl,
|
|
1005
|
+
provider,
|
|
1006
|
+
);
|
|
945
1007
|
}
|
|
946
1008
|
|
|
947
1009
|
async function pickSessionAndResume(rl, cwd = process.cwd()) {
|
|
@@ -1087,10 +1149,14 @@ async function forkFromSession(rl, source, cwd = process.cwd()) {
|
|
|
1087
1149
|
console.log(`provider=${provider.name}`);
|
|
1088
1150
|
await pause(rl, "按回车进入 Codex...");
|
|
1089
1151
|
|
|
1090
|
-
setRawMode(false);
|
|
1091
1152
|
const startedAtMs = Date.now();
|
|
1092
|
-
await runCodex(
|
|
1093
|
-
|
|
1153
|
+
await runCodex(
|
|
1154
|
+
["fork", source.sessionId],
|
|
1155
|
+
buildCodexEnv(provider),
|
|
1156
|
+
projectState.root,
|
|
1157
|
+
rl,
|
|
1158
|
+
provider,
|
|
1159
|
+
);
|
|
1094
1160
|
|
|
1095
1161
|
const linkedSessionId = await maybeLinkLatestSession(
|
|
1096
1162
|
projectState.root,
|
|
@@ -1143,13 +1209,12 @@ async function deleteSpecificSession(rl, target, cwd = process.cwd()) {
|
|
|
1143
1209
|
};
|
|
1144
1210
|
}
|
|
1145
1211
|
|
|
1146
|
-
setRawMode(false);
|
|
1147
1212
|
const exitCode = await runCodex(
|
|
1148
1213
|
["delete", "--force", target.sessionId],
|
|
1149
1214
|
{},
|
|
1150
1215
|
projectState.root,
|
|
1216
|
+
rl,
|
|
1151
1217
|
);
|
|
1152
|
-
setRawMode(true);
|
|
1153
1218
|
|
|
1154
1219
|
const stillExists = hasOfficialSession(target.sessionId, projectState.root);
|
|
1155
1220
|
if (exitCode !== 0 || stillExists) {
|