Skip to content

Commit a1d165c

Browse files
committed
Add CodexEnvConfig: auto-configure gateway from env vars
1 parent ac324e6 commit a1d165c

5 files changed

Lines changed: 129 additions & 5 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"publishConfig": {
44
"access": "public"
55
},
6-
"version": "1.1.7-beta.3",
6+
"version": "1.1.7-beta.4",
77
"description": "",
88
"main": "dist/index.js",
99
"bin": {

src/CodexAcpClient.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {CODEX_API_KEY_ENV_VAR, GatewayAuthMethod, isCodexAuthRequest, OPENAI_API_KEY_ENV_VAR} from "./CodexAuthMethod";
2+
import {readGatewayConfigFromEnv} from "./CodexEnvConfig";
23
import type {EmbeddedResourceResource} from "@agentclientprotocol/sdk";
34
import * as acp from "@agentclientprotocol/sdk";
45
import {type McpServer, RequestError} from "@agentclientprotocol/sdk";
@@ -80,7 +81,7 @@ export class CodexAcpClient {
8081
this.codexClient = codexClient;
8182
this.config = codexConfig ?? {};
8283
this.modelProvider = modelProvider ?? null;
83-
this.gatewayConfig = null;
84+
this.gatewayConfig = readGatewayConfigFromEnv();
8485
}
8586

8687
private readonly defaultClientInfo: ClientInfo = {
@@ -976,7 +977,7 @@ function shouldDeduplicateMcpConflicts(): boolean {
976977
return !disabledByEnv;
977978
}
978979

979-
type WireApi = "responses";
980+
type WireApi = "responses" | "chat";
980981

981982
interface GatewayConfig {
982983
modelProvider: string;

src/CodexEnvConfig.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* Environment-driven auto-configuration for the Nuwax Codex bridge.
3+
*
4+
* Reads custom env vars (CODEX_BASE_URL, CODEX_WIRE_API, CODEX_MODEL,
5+
* CODEX_LOG_DIR) and translates them into Codex gateway config or system
6+
* env overrides. All custom logic lives here to keep merge conflicts with
7+
* upstream codex-acp to a minimum.
8+
*/
9+
import {CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR} from "./CodexAuthMethod";
10+
import {logger} from "./Logger";
11+
12+
// ---------------------------------------------------------------------------
13+
// Public env var names
14+
// ---------------------------------------------------------------------------
15+
16+
export const CODEX_BASE_URL_ENV_VAR = "CODEX_BASE_URL";
17+
export const CODEX_WIRE_API_ENV_VAR = "CODEX_WIRE_API";
18+
export const CODEX_MODEL_ENV_VAR = "CODEX_MODEL";
19+
export const CODEX_LOG_DIR_ENV_VAR = "CODEX_LOG_DIR";
20+
21+
// ---------------------------------------------------------------------------
22+
// Types
23+
// ---------------------------------------------------------------------------
24+
25+
/** Codex wire-protocol variant. */
26+
export type EnvWireApi = "responses" | "chat";
27+
28+
/** Well-known provider id used by the auto-configured gateway. */
29+
export const CUSTOM_GATEWAY_ID = "custom-gateway";
30+
31+
/** Shape of the gateway config stored in CodexAcpClient. */
32+
export interface EnvGatewayConfig {
33+
modelProvider: string;
34+
config: {
35+
name: string;
36+
base_url: string;
37+
http_headers: Record<string, string>;
38+
wire_api: EnvWireApi;
39+
};
40+
}
41+
42+
// ---------------------------------------------------------------------------
43+
// Gateway auto-config from env
44+
// ---------------------------------------------------------------------------
45+
46+
/**
47+
* If `CODEX_BASE_URL` is set, build a gateway config from environment
48+
* variables. Returns `null` when no env-driven gateway is requested (so
49+
* the ACP `authenticate` / `providers/set` flow remains the authority).
50+
*/
51+
export function readGatewayConfigFromEnv(): EnvGatewayConfig | null {
52+
const baseUrl = process.env[CODEX_BASE_URL_ENV_VAR]?.trim();
53+
if (!baseUrl) {
54+
return null;
55+
}
56+
57+
const rawWireApi = process.env[CODEX_WIRE_API_ENV_VAR]?.trim();
58+
const wireApi: EnvWireApi =
59+
rawWireApi === "chat" || rawWireApi === "responses" ? rawWireApi : "responses";
60+
61+
const providerName =
62+
process.env[CODEX_MODEL_ENV_VAR]?.trim() || "Custom Gateway";
63+
64+
const headers: Record<string, string> = {"X-Client-Feature-ID": "codex"};
65+
66+
const apiKey = readAnyApiKey();
67+
if (apiKey) {
68+
headers["Authorization"] = `Bearer ${apiKey}`;
69+
}
70+
71+
logger.log("Auto-configured gateway from env", {
72+
baseUrl,
73+
wireApi,
74+
providerName,
75+
hasApiKey: !!apiKey,
76+
});
77+
78+
return {
79+
modelProvider: CUSTOM_GATEWAY_ID,
80+
config: {
81+
name: providerName,
82+
base_url: baseUrl,
83+
http_headers: headers,
84+
wire_api: wireApi,
85+
},
86+
};
87+
}
88+
89+
// ---------------------------------------------------------------------------
90+
// Log directory mapping
91+
// ---------------------------------------------------------------------------
92+
93+
/**
94+
* Map `CODEX_LOG_DIR` → `APP_SERVER_LOGS` if the former is set and the
95+
* latter is not. Must be called **before** the Logger singleton is first
96+
* accessed (i.e. at the very top of `startAcpServer`).
97+
*/
98+
export function applyCodexLogDir(): void {
99+
const dir = process.env[CODEX_LOG_DIR_ENV_VAR];
100+
if (dir && !process.env["APP_SERVER_LOGS"]) {
101+
process.env["APP_SERVER_LOGS"] = dir;
102+
}
103+
}
104+
105+
// ---------------------------------------------------------------------------
106+
// Helpers
107+
// ---------------------------------------------------------------------------
108+
109+
/**
110+
* Try `CODEX_API_KEY` first, then fall back to `OPENAI_API_KEY`. Returns
111+
* `undefined` when neither is set (callers decide whether this is fatal).
112+
*/
113+
function readAnyApiKey(): string | undefined {
114+
for (const envVar of [CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR]) {
115+
const value = process.env[envVar]?.trim();
116+
if (value) {
117+
return value;
118+
}
119+
}
120+
return undefined;
121+
}

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import packageJson from "../package.json";
1212
import {logger} from "./Logger";
1313
import {runLoginCommand} from "./login";
1414
import {runCodexCli} from "./CodexCli";
15+
import {applyCodexLogDir} from "./CodexEnvConfig";
1516
import {
1617
GOAL_CONTROL_METHOD, LEGACY_SET_SESSION_MODEL_METHOD,
1718
SESSION_STEERING_METHOD,
@@ -63,6 +64,7 @@ if (process.argv[2] === "login") {
6364
}
6465

6566
function startAcpServer() {
67+
applyCodexLogDir();
6668
const codexPath = process.env["CODEX_PATH"];
6769
const configString = process.env["CODEX_CONFIG"];
6870
const authRequestString = process.env["DEFAULT_AUTH_REQUEST"];

0 commit comments

Comments
 (0)