niahere 0.4.0 → 0.4.1
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/package.json +1 -1
- package/src/agent/backends/codex.ts +34 -1
package/package.json
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join, dirname } from "path";
|
|
1
4
|
import type { AgentBackend, AgentSession, AgentSessionContext, AgentEvent } from "../types";
|
|
2
5
|
import type { Attachment } from "../../types/attachment";
|
|
3
6
|
import type { McpSourceContext } from "../../mcp";
|
|
4
7
|
import { CodexNormalizer } from "./codex-normalize";
|
|
5
8
|
import { mintRun, revokeRun } from "../mcp-endpoint";
|
|
6
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the codex binary's absolute path. The daemon runs under launchd with a
|
|
12
|
+
* minimal PATH (`/usr/bin:/bin:...`) that excludes nvm/homebrew bins, so a bare
|
|
13
|
+
* `codex` spawn would fail. Search the likely install locations (env override,
|
|
14
|
+
* the runtime's own bin, homebrew, every nvm node bin, bun) and fall back to
|
|
15
|
+
* PATH only as a last resort. Cached after first resolution.
|
|
16
|
+
*/
|
|
17
|
+
let cachedCodexBin: string | null = null;
|
|
18
|
+
export function resolveCodexBin(): string {
|
|
19
|
+
if (cachedCodexBin) return cachedCodexBin;
|
|
20
|
+
const candidates: string[] = [];
|
|
21
|
+
if (process.env.CODEX_PATH) candidates.push(process.env.CODEX_PATH);
|
|
22
|
+
candidates.push(join(dirname(process.execPath), "codex")); // sibling of bun/node
|
|
23
|
+
candidates.push("/opt/homebrew/bin/codex", "/usr/local/bin/codex");
|
|
24
|
+
try {
|
|
25
|
+
const nvm = join(homedir(), ".nvm", "versions", "node");
|
|
26
|
+
for (const v of readdirSync(nvm)) candidates.push(join(nvm, v, "bin", "codex"));
|
|
27
|
+
} catch {
|
|
28
|
+
/* no nvm */
|
|
29
|
+
}
|
|
30
|
+
candidates.push(join(homedir(), ".bun", "bin", "codex"));
|
|
31
|
+
cachedCodexBin = candidates.find((p) => existsSync(p)) ?? "codex";
|
|
32
|
+
return cachedCodexBin;
|
|
33
|
+
}
|
|
34
|
+
|
|
7
35
|
/** Minimal spawned-process surface, injectable so the session is unit-testable. */
|
|
8
36
|
export interface CliProc {
|
|
9
37
|
stdout: ReadableStream<Uint8Array>;
|
|
@@ -33,7 +61,12 @@ function scrubbedEnv(extra: Record<string, string>): Record<string, string> {
|
|
|
33
61
|
}
|
|
34
62
|
|
|
35
63
|
function defaultSpawn(args: string[], opts: { cwd: string; env: Record<string, string> }): CliProc {
|
|
36
|
-
const proc = Bun.spawn([
|
|
64
|
+
const proc = Bun.spawn([resolveCodexBin(), ...args], {
|
|
65
|
+
cwd: opts.cwd,
|
|
66
|
+
env: opts.env,
|
|
67
|
+
stdout: "pipe",
|
|
68
|
+
stderr: "pipe",
|
|
69
|
+
});
|
|
37
70
|
return {
|
|
38
71
|
stdout: proc.stdout as ReadableStream<Uint8Array>,
|
|
39
72
|
stderr: proc.stderr as ReadableStream<Uint8Array>,
|