@fulldivevr/workcord-cli 3.0.3 → 3.0.5
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/commands/machine.js
CHANGED
|
@@ -88,7 +88,8 @@ export function registerMachine(program) {
|
|
|
88
88
|
const detected = await detectAdapters();
|
|
89
89
|
pickAdapters(detected, opts.adapter, home);
|
|
90
90
|
// checkAdapters already narrowed the set to the chosen adapter.
|
|
91
|
-
const
|
|
91
|
+
const usable = await checkAdapters(detected, opts.adapter, home);
|
|
92
|
+
const adapters = pickAdapters(usable, "auto", home);
|
|
92
93
|
const baseUrl = credential.baseUrl || (await getBaseUrl());
|
|
93
94
|
const installationId = await readOrCreateInstallationId();
|
|
94
95
|
const release = await acquireMachineLock(getMachineLockPath());
|
|
@@ -183,8 +184,8 @@ function collect(value, previous) {
|
|
|
183
184
|
}
|
|
184
185
|
const RUNNERS = { claude: runClaude, codex: runCodex };
|
|
185
186
|
/**
|
|
186
|
-
* Prints the binary each adapter uses
|
|
187
|
-
*
|
|
187
|
+
* Prints the binary each adapter uses. A Codex that cannot answer `app-server`
|
|
188
|
+
* fails the start, since a legacy Codex CLI cannot run tasks at all.
|
|
188
189
|
*/
|
|
189
190
|
export async function checkAdapters(installed, choice, home, log = (line) => process.stderr.write(line + "\n"), env = process.env) {
|
|
190
191
|
const usable = {};
|
|
@@ -197,10 +198,13 @@ export async function checkAdapters(installed, choice, home, log = (line) => pro
|
|
|
197
198
|
log(`ERROR: ${probe.message}`);
|
|
198
199
|
if (probe.stderr)
|
|
199
200
|
log(`machine: codex said: ${probe.stderr.replace(/\s+/g, " ").slice(-300)}`);
|
|
200
|
-
|
|
201
|
+
throw new Error("codex cannot run tasks, see the ERROR line above.");
|
|
201
202
|
}
|
|
203
|
+
usable.codex = binary;
|
|
204
|
+
log(`machine: codex at ${usable.codex}`);
|
|
205
|
+
continue;
|
|
202
206
|
}
|
|
203
|
-
|
|
207
|
+
if (name === "claude" && (await binaryVersion(binary, childEnv(env, home))) === "unknown") {
|
|
204
208
|
log(`ERROR: claude at ${binary} does not answer "claude --version". Reinstall it: npm i -g @anthropic-ai/claude-code@latest`);
|
|
205
209
|
continue;
|
|
206
210
|
}
|
|
@@ -52,7 +52,7 @@ export function binaryVersion(binary, env) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
export function codexUnusableMessage(binary, version) {
|
|
55
|
-
return `codex at ${binary} (version ${version}) cannot run "codex app-server". Update it: npm i -g @openai/codex@latest`;
|
|
55
|
+
return `codex at ${binary} (version ${version}) cannot run "codex app-server". Update it: npm i -g @openai/codex@latest, or install the Codex desktop app (it bundles a current codex)`;
|
|
56
56
|
}
|
|
57
57
|
/** Starts `codex app-server` and accepts it once it answers `initialize`; a legacy Codex CLI never does. */
|
|
58
58
|
export async function probeCodex(binary, env, home, timeoutMs = PROBE_TIMEOUT_MS) {
|
package/dist/machine/agents.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { access, constants } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
2
3
|
import { delimiter, join } from "node:path";
|
|
3
4
|
export const ADAPTER_NAMES = ["claude", "codex"];
|
|
4
5
|
/**
|
|
@@ -12,17 +13,32 @@ export function childEnv(env = process.env, home) {
|
|
|
12
13
|
return inherited;
|
|
13
14
|
return { ...inherited, HOME: home, CODEX_HOME: join(home, ".codex"), CLAUDE_CONFIG_DIR: join(home, ".claude") };
|
|
14
15
|
}
|
|
16
|
+
/** Codex desktop bundles a current codex that is not on PATH; when one exists it is the codex, ahead of PATH. */
|
|
17
|
+
export function codexDesktopPaths(platform = process.platform, home = homedir()) {
|
|
18
|
+
if (platform !== "darwin")
|
|
19
|
+
return [];
|
|
20
|
+
return ["/Applications", join(home, "Applications")].flatMap((dir) => [
|
|
21
|
+
join(dir, "ChatGPT.app/Contents/Resources/codex-cli/bin/codex"),
|
|
22
|
+
join(dir, "Codex.app/Contents/Resources/codex"),
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
const isExecutable = (path) => access(path, constants.X_OK).then(() => true, () => false);
|
|
26
|
+
function onPath(name, env) {
|
|
27
|
+
return String(env.PATH || "").split(delimiter).filter(Boolean).map((dir) => join(dir, name));
|
|
28
|
+
}
|
|
15
29
|
/** Absolute path of each installed agent CLI, found the way a shell would find it. */
|
|
16
|
-
export async function detectAdapters(env = process.env) {
|
|
30
|
+
export async function detectAdapters(env = process.env, codexDesktop = codexDesktopPaths()) {
|
|
17
31
|
const found = {};
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
for (const candidate of onPath("claude", env)) {
|
|
33
|
+
if (await isExecutable(candidate)) {
|
|
34
|
+
found.claude = candidate;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const candidate of [...codexDesktop, ...onPath("codex", env)]) {
|
|
39
|
+
if (await isExecutable(candidate)) {
|
|
40
|
+
found.codex = candidate;
|
|
41
|
+
break;
|
|
26
42
|
}
|
|
27
43
|
}
|
|
28
44
|
return found;
|