@withtruing/companion 0.13.2 → 0.13.3
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/README.md +1 -1
- package/dist/cli.js +1 -1
- package/dist/codex-binary.js +96 -0
- package/dist/codex-cli-caller.js +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,7 +215,7 @@ truing connect \
|
|
|
215
215
|
the companion's own Codex home. This is separate from your normal Codex login:
|
|
216
216
|
|
|
217
217
|
```powershell
|
|
218
|
-
New-Item -ItemType Directory -Force "$HOME\.product-console-companion\codex-home" | Out-Null; $env:CODEX_HOME="$HOME\.product-console-companion\codex-home"; codex login; Remove-Item Env:CODEX_HOME
|
|
218
|
+
New-Item -ItemType Directory -Force "$HOME\.product-console-companion\codex-home" | Out-Null; $env:CODEX_HOME="$HOME\.product-console-companion\codex-home"; codex.cmd login; Remove-Item Env:CODEX_HOME
|
|
219
219
|
```
|
|
220
220
|
|
|
221
221
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -461,7 +461,7 @@ export function codexReadinessLines(status) {
|
|
|
461
461
|
}
|
|
462
462
|
return [
|
|
463
463
|
'Codex needs a one-time login for the companion\'s own home:',
|
|
464
|
-
' Windows PowerShell: New-Item -ItemType Directory -Force "$HOME\\.product-console-companion\\codex-home" | Out-Null; $env:CODEX_HOME="$HOME\\.product-console-companion\\codex-home"; codex login; Remove-Item Env:CODEX_HOME',
|
|
464
|
+
' Windows PowerShell: New-Item -ItemType Directory -Force "$HOME\\.product-console-companion\\codex-home" | Out-Null; $env:CODEX_HOME="$HOME\\.product-console-companion\\codex-home"; codex.cmd login; Remove-Item Env:CODEX_HOME',
|
|
465
465
|
' macOS/Linux: mkdir -p "$HOME/.product-console-companion/codex-home" && CODEX_HOME="$HOME/.product-console-companion/codex-home" codex login',
|
|
466
466
|
'This separate login keeps your own ~/.codex instructions out of the companion\'s calls.',
|
|
467
467
|
];
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
3
|
+
const defaultFs = { existsSync, readFileSync };
|
|
4
|
+
let cachedCommand = null;
|
|
5
|
+
let cachedPath;
|
|
6
|
+
let cachedPathExt;
|
|
7
|
+
function envValue(env, name) {
|
|
8
|
+
const key = Object.keys(env).find((candidate) => candidate.toLowerCase() === name.toLowerCase());
|
|
9
|
+
return key ? env[key] : undefined;
|
|
10
|
+
}
|
|
11
|
+
function windowsPathEntries(env) {
|
|
12
|
+
return (envValue(env, 'PATH') ?? '')
|
|
13
|
+
.split(';')
|
|
14
|
+
.map((entry) => entry.trim().replace(/^"|"$/g, ''))
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
function windowsExtensions(env) {
|
|
18
|
+
const pathExt = envValue(env, 'PATHEXT') || '.COM;.EXE;.BAT;.CMD';
|
|
19
|
+
return pathExt
|
|
20
|
+
.split(';')
|
|
21
|
+
.map((extension) => extension.trim().toLowerCase())
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.map((extension) => extension.startsWith('.') ? extension : `.${extension}`);
|
|
24
|
+
}
|
|
25
|
+
function existingCandidate(directory, extension, fs) {
|
|
26
|
+
const lowerCaseCandidate = join(directory, `codex${extension.toLowerCase()}`);
|
|
27
|
+
if (fs.existsSync(lowerCaseCandidate))
|
|
28
|
+
return resolve(lowerCaseCandidate);
|
|
29
|
+
const originalCaseCandidate = join(directory, `codex${extension}`);
|
|
30
|
+
return fs.existsSync(originalCaseCandidate) ? resolve(originalCaseCandidate) : null;
|
|
31
|
+
}
|
|
32
|
+
function parsedShimScript(shimPath, fs) {
|
|
33
|
+
let contents;
|
|
34
|
+
try {
|
|
35
|
+
contents = fs.readFileSync(shimPath, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const shimDirectory = dirname(shimPath);
|
|
41
|
+
for (const match of contents.matchAll(/"([^"\r\n]*codex\.js)"/gi)) {
|
|
42
|
+
let target = match[1].replace(/%(?:~dp0|dp0)%?/gi, shimDirectory);
|
|
43
|
+
// Tests inject win32 while running on Linux CI; normalizing both separator forms keeps the
|
|
44
|
+
// resolver testable with a real temporary filesystem and is a no-op for native Windows paths.
|
|
45
|
+
target = target.replace(/[\\/]/g, sep);
|
|
46
|
+
if (!isAbsolute(target))
|
|
47
|
+
target = resolve(shimDirectory, target);
|
|
48
|
+
if (fs.existsSync(target))
|
|
49
|
+
return resolve(target);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function scriptForShim(shimPath, fs) {
|
|
54
|
+
const parsed = parsedShimScript(shimPath, fs);
|
|
55
|
+
if (parsed)
|
|
56
|
+
return parsed;
|
|
57
|
+
const conventional = join(dirname(shimPath), 'node_modules', '@openai', 'codex', 'bin', 'codex.js');
|
|
58
|
+
return fs.existsSync(conventional) ? resolve(conventional) : null;
|
|
59
|
+
}
|
|
60
|
+
function resolveUncached(platform, env, fs) {
|
|
61
|
+
if (platform !== 'win32')
|
|
62
|
+
return { command: 'codex', prefixArgs: [] };
|
|
63
|
+
const extensions = windowsExtensions(env);
|
|
64
|
+
for (const directory of windowsPathEntries(env)) {
|
|
65
|
+
for (const extension of extensions) {
|
|
66
|
+
if (extension !== '.cmd' && extension !== '.exe')
|
|
67
|
+
continue;
|
|
68
|
+
const candidate = existingCandidate(directory, extension, fs);
|
|
69
|
+
if (!candidate)
|
|
70
|
+
continue;
|
|
71
|
+
if (extension === '.exe')
|
|
72
|
+
return { command: candidate, prefixArgs: [] };
|
|
73
|
+
const script = scriptForShim(candidate, fs);
|
|
74
|
+
if (script)
|
|
75
|
+
return { command: process.execPath, prefixArgs: [script] };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { command: 'codex', prefixArgs: [] };
|
|
79
|
+
}
|
|
80
|
+
/** Cache each production environment. Injected dependencies bypass the cache so Linux CI can
|
|
81
|
+
* exercise the Windows lookup rules without mutating process globals or depending on Windows
|
|
82
|
+
* filesystem semantics. */
|
|
83
|
+
export function resolveCodexCommand(options = {}) {
|
|
84
|
+
const injected = options.platform !== undefined || options.env !== undefined || options.fs !== undefined;
|
|
85
|
+
const path = envValue(process.env, 'PATH');
|
|
86
|
+
const pathExt = envValue(process.env, 'PATHEXT');
|
|
87
|
+
if (!injected && cachedCommand && path === cachedPath && pathExt === cachedPathExt)
|
|
88
|
+
return cachedCommand;
|
|
89
|
+
const command = resolveUncached(options.platform ?? process.platform, options.env ?? process.env, options.fs ?? defaultFs);
|
|
90
|
+
if (!injected) {
|
|
91
|
+
cachedCommand = command;
|
|
92
|
+
cachedPath = path;
|
|
93
|
+
cachedPathExt = pathExt;
|
|
94
|
+
}
|
|
95
|
+
return command;
|
|
96
|
+
}
|
package/dist/codex-cli-caller.js
CHANGED
|
@@ -9,6 +9,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:pat
|
|
|
9
9
|
import { createInterface } from 'node:readline';
|
|
10
10
|
import { StringDecoder } from 'node:string_decoder';
|
|
11
11
|
import { assertSingleLineArguments } from './cli-arguments.js';
|
|
12
|
+
import { resolveCodexCommand } from './codex-binary.js';
|
|
12
13
|
import { gitErrorMessage } from './sandbox.js';
|
|
13
14
|
import { stripIntroducedNulls, toCodexStrictSchema } from './strict-schema.js';
|
|
14
15
|
const WALL_CLOCK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
@@ -347,7 +348,8 @@ removeDirectory = rm) {
|
|
|
347
348
|
let firstUnparseableLineFirst = '';
|
|
348
349
|
let firstUnparseableLineLast = '';
|
|
349
350
|
const typeCounts = new Map();
|
|
350
|
-
const
|
|
351
|
+
const { command, prefixArgs } = resolveCodexCommand();
|
|
352
|
+
const child = spawn(command, [...prefixArgs, ...args], {
|
|
351
353
|
cwd: invocationCwd,
|
|
352
354
|
env: buildCodexEnvironment(codexHome),
|
|
353
355
|
windowsHide: true,
|
|
@@ -522,7 +524,8 @@ export async function checkCodexLogin(codexHome) {
|
|
|
522
524
|
throw error;
|
|
523
525
|
}
|
|
524
526
|
return new Promise((resolvePromise) => {
|
|
525
|
-
const
|
|
527
|
+
const { command, prefixArgs } = resolveCodexCommand();
|
|
528
|
+
const child = spawn(command, [...prefixArgs, 'login', 'status'], {
|
|
526
529
|
env: buildCodexEnvironment(validatedHome),
|
|
527
530
|
windowsHide: true,
|
|
528
531
|
});
|