Open History to see the last commit
1import { tokenizeCliArgs } from "@t3tools/shared/cliArgs";
2
3const T3CODE_CODEX_LAUNCH_ARGS_ENV = "T3CODE_CODEX_LAUNCH_ARGS";
4
5export const resolveCodexLaunchArgs = (
6 launchArgs?: string,
7 environment: NodeJS.ProcessEnv = process.env,
8) => environment[T3CODE_CODEX_LAUNCH_ARGS_ENV]?.trim() || launchArgs?.trim() || "";
9
10const codexLaunchArgv = (launchArgs?: string): ReadonlyArray<string> => tokenizeCliArgs(launchArgs);
11
12// T3 unsubscribes only when it unloads a thread; Codex's own unload delay would stack on that.
13export const codexAppServerArgs = (launchArgs?: string) => [
14 "app-server",
15 "-c",
16 "thread_unload_delay_secs=0",
17 ...codexLaunchArgv(launchArgs),
18];
19
20interface LaunchArgFilter {
21 readonly switches: ReadonlySet<string>;
22 readonly valueFlags: ReadonlySet<string>;
23 readonly inlinePrefixes: ReadonlyArray<string>;
24}
25
26const SHARED_VALUE_FLAGS = ["--config", "-c", "--enable", "--disable"];
27const SHARED_INLINE_PREFIXES = ["--config=", "-c=", "--enable=", "--disable="];
28
29const MCP_LIST_FILTER: LaunchArgFilter = {
30 switches: new Set(),
31 valueFlags: new Set([...SHARED_VALUE_FLAGS, "--profile", "-p"]),
32 inlinePrefixes: [...SHARED_INLINE_PREFIXES, "--profile=", "-p="],
33};
34
35const EXEC_FILTER: LaunchArgFilter = {
36 switches: new Set(["--strict-config", "--oss"]),
37 valueFlags: new Set([...SHARED_VALUE_FLAGS, "--local-provider", "--profile", "-p"]),
38 inlinePrefixes: [...SHARED_INLINE_PREFIXES, "--local-provider=", "--profile=", "-p="],
39};
40
41const filterLaunchArgs = (launchArgs: string | undefined, allowed: LaunchArgFilter) => {
42 const args = codexLaunchArgv(launchArgs);
43 const kept: Array<string> = [];
44
45 for (let index = 0; index < args.length; index++) {
46 const arg = args[index];
47 if (arg === undefined) continue;
48
49 if (allowed.switches.has(arg)) {
50 kept.push(arg);
51 } else if (allowed.valueFlags.has(arg)) {
52 const value = args[index + 1];
53 if (value !== undefined && !value.startsWith("-")) {
54 kept.push(arg, value);
55 index++;
56 }
57 } else if (allowed.inlinePrefixes.some((prefix) => arg.startsWith(prefix))) {
58 kept.push(arg);
59 }
60 }
61
62 return kept;
63};
64
65export const codexExecLaunchArgs = (launchArgs?: string) =>
66 filterLaunchArgs(launchArgs, EXEC_FILTER);
67
68export const codexMcpListLaunchArgs = (launchArgs?: string) =>
69 filterLaunchArgs(launchArgs, MCP_LIST_FILTER);