File size: 2,385 Bytes
e38b699
2c613b3
e38b699
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75b9f57
 
e38b699
 
 
 
 
 
 
 
 
 
 
 
 
 
2c613b3
 
 
 
 
 
 
e38b699
2c613b3
e38b699
 
 
 
 
 
 
 
 
75b9f57
e38b699
 
 
 
 
 
 
75b9f57
e38b699
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { Codex } from "@openai/codex-sdk";
import { spawnSync } from "child_process";

function readStdin() {
  return new Promise((resolve, reject) => {
    let data = "";
    process.stdin.setEncoding("utf8");
    process.stdin.on("data", (chunk) => (data += chunk));
    process.stdin.on("end", () => resolve(data));
    process.stdin.on("error", reject);
  });
}

async function main() {
  const raw = await readStdin();
  const payload = raw ? JSON.parse(raw) : {};

  const message = typeof payload.message === "string" ? payload.message : "";
  const threadId = typeof payload.threadId === "string" ? payload.threadId : null;

  const model = typeof payload.model === "string" ? payload.model : undefined;
  const sandboxMode = payload.sandboxMode || "read-only";
  const approvalPolicy = payload.approvalPolicy || "never";
  const workingDirectory = payload.workingDirectory || process.cwd();
  const modelReasoningEffort =
    payload.modelReasoningEffort || "minimal";

  const apiKey =
    (typeof payload.apiKey === "string" && payload.apiKey) ||
    process.env.CODEX_API_KEY ||
    process.env.OPENAI_API_KEY ||
    process.env.OPENAI_KEY ||
    undefined;

  const baseUrl =
    (typeof payload.baseUrl === "string" && payload.baseUrl) ||
    process.env.OPENAI_BASE_URL ||
    process.env.OPENAI_API_BASE ||
    undefined;

  const codexPathOverride = (() => {
    const override = process.env.CODEX_PATH_OVERRIDE;
    if (override) return override;
    const probe = spawnSync("codex", ["--version"], { stdio: "ignore" });
    return probe.status === 0 ? "codex" : undefined;
  })();

  const codex = new Codex({
    codexPathOverride,
    apiKey,
    baseUrl,
  });

  const thread = threadId
    ? codex.resumeThread(threadId, {
        model,
        sandboxMode,
        approvalPolicy,
        modelReasoningEffort,
        workingDirectory,
        skipGitRepoCheck: true,
      })
    : codex.startThread({
        model,
        sandboxMode,
        approvalPolicy,
        modelReasoningEffort,
        workingDirectory,
        skipGitRepoCheck: true,
      });

  const turn = await thread.run(message);

  process.stdout.write(
    JSON.stringify({
      threadId: thread.id,
      finalResponse: turn.finalResponse,
      usage: turn.usage,
    }),
  );
}

main().catch((err) => {
  process.stderr.write(String(err?.stack || err));
  process.exit(1);
});