codex-openai-proxy 0.1.0-rc.0
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/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/app-server/app-server.d.ts +39 -0
- package/dist/app-server/app-server.js +261 -0
- package/dist/app-server/app-server.js.map +1 -0
- package/dist/app-server/auth.d.ts +16 -0
- package/dist/app-server/auth.js +102 -0
- package/dist/app-server/auth.js.map +1 -0
- package/dist/app-server/json-rpc.d.ts +29 -0
- package/dist/app-server/json-rpc.js +141 -0
- package/dist/app-server/json-rpc.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +11 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/cli.d.ts +6 -0
- package/dist/cli/cli.js +319 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/continuation/state.d.ts +71 -0
- package/dist/continuation/state.js +460 -0
- package/dist/continuation/state.js.map +1 -0
- package/dist/core/abort.d.ts +13 -0
- package/dist/core/abort.js +74 -0
- package/dist/core/abort.js.map +1 -0
- package/dist/core/canonical.d.ts +6 -0
- package/dist/core/canonical.js +22 -0
- package/dist/core/canonical.js.map +1 -0
- package/dist/core/config.d.ts +33 -0
- package/dist/core/config.js +139 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/logger.d.ts +17 -0
- package/dist/core/logger.js +44 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/policy.d.ts +98 -0
- package/dist/core/policy.js +242 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/redact.d.ts +2 -0
- package/dist/core/redact.js +35 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/http/chat-execute.d.ts +24 -0
- package/dist/http/chat-execute.js +491 -0
- package/dist/http/chat-execute.js.map +1 -0
- package/dist/http/chat-normalize.d.ts +100 -0
- package/dist/http/chat-normalize.js +379 -0
- package/dist/http/chat-normalize.js.map +1 -0
- package/dist/http/chat-sse.d.ts +14 -0
- package/dist/http/chat-sse.js +52 -0
- package/dist/http/chat-sse.js.map +1 -0
- package/dist/http/chat-validate.d.ts +37 -0
- package/dist/http/chat-validate.js +190 -0
- package/dist/http/chat-validate.js.map +1 -0
- package/dist/http/chat.d.ts +8 -0
- package/dist/http/chat.js +137 -0
- package/dist/http/chat.js.map +1 -0
- package/dist/http/errors.d.ts +19 -0
- package/dist/http/errors.js +56 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/server.d.ts +19 -0
- package/dist/http/server.js +254 -0
- package/dist/http/server.js.map +1 -0
- package/package.json +67 -0
- package/protocol/VERSION.json +10 -0
- package/protocol/schemas/response-mapping.schema.json +38 -0
- package/protocol/schemas/x-codex.schema.json +12 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { listenForAbort, withDeadline } from "../core/abort.js";
|
|
4
|
+
/** Ensures app-server has an authenticated OpenAI account. */
|
|
5
|
+
export async function ensureAuthenticated(options) {
|
|
6
|
+
const account = (await options.rpc.request("account/read", { refreshToken: false }, options.signal));
|
|
7
|
+
if (typeof account.requiresOpenaiAuth !== "boolean")
|
|
8
|
+
throw new Error("account/read returned an invalid requiresOpenaiAuth value.");
|
|
9
|
+
if (!account.requiresOpenaiAuth || account.account != null)
|
|
10
|
+
return;
|
|
11
|
+
const useDeviceCode = !options.interactive;
|
|
12
|
+
await startAndWaitForLogin(options, useDeviceCode);
|
|
13
|
+
}
|
|
14
|
+
/** Starts a browser or device-code login and waits for its notification. */
|
|
15
|
+
async function startAndWaitForLogin(options, useDeviceCode) {
|
|
16
|
+
let loginId;
|
|
17
|
+
let earlyCompletion;
|
|
18
|
+
let settle;
|
|
19
|
+
const completion = new Promise((resolve, reject) => {
|
|
20
|
+
settle = (error) => (error ? reject(error) : resolve());
|
|
21
|
+
});
|
|
22
|
+
void completion.catch(() => undefined);
|
|
23
|
+
const notification = (method, raw) => {
|
|
24
|
+
if (method !== "account/login/completed" ||
|
|
25
|
+
typeof raw !== "object" ||
|
|
26
|
+
raw === null)
|
|
27
|
+
return;
|
|
28
|
+
const result = raw;
|
|
29
|
+
if (loginId === undefined) {
|
|
30
|
+
earlyCompletion = result;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (result.loginId != null && result.loginId !== loginId)
|
|
34
|
+
return;
|
|
35
|
+
settle(result.success
|
|
36
|
+
? undefined
|
|
37
|
+
: new Error(result.error ?? "ChatGPT login failed."));
|
|
38
|
+
};
|
|
39
|
+
options.rpc.on("notification", notification);
|
|
40
|
+
try {
|
|
41
|
+
await withDeadline(options.signal, {
|
|
42
|
+
milliseconds: options.timeoutMs,
|
|
43
|
+
timeoutReason: new Error("ChatGPT login timed out."),
|
|
44
|
+
abortReason: (signal) => signal.reason instanceof Error
|
|
45
|
+
? signal.reason
|
|
46
|
+
: new Error("ChatGPT login cancelled."),
|
|
47
|
+
}, async (deadlineSignal) => {
|
|
48
|
+
const disposeDeadline = listenForAbort(deadlineSignal, (abortedSignal) => settle(abortedSignal.reason instanceof Error
|
|
49
|
+
? abortedSignal.reason
|
|
50
|
+
: new Error("ChatGPT login cancelled.")));
|
|
51
|
+
try {
|
|
52
|
+
const login = (await options.rpc.request("account/login/start", { type: useDeviceCode ? "chatgptDeviceCode" : "chatgpt" }, options.signal));
|
|
53
|
+
loginId = login.loginId;
|
|
54
|
+
if (earlyCompletion !== undefined)
|
|
55
|
+
notification("account/login/completed", earlyCompletion);
|
|
56
|
+
if (login.type === "chatgpt") {
|
|
57
|
+
const launched = await (options.launch ?? launchBrowser)(login.authUrl);
|
|
58
|
+
if (!launched) {
|
|
59
|
+
options.terminal(`Open this URL to sign in to ChatGPT:\n${login.authUrl}\n`);
|
|
60
|
+
options.log("warn", "browser_launch_failed", {
|
|
61
|
+
login_url: "[REDACTED]",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
options.log("info", "browser_launch_succeeded");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
options.terminal(`Open ${login.verificationUrl} and enter code ${login.userCode}.\n`);
|
|
69
|
+
options.log("info", "device_code_login_started", {
|
|
70
|
+
verification_url: "[REDACTED]",
|
|
71
|
+
user_code: "[REDACTED]",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
await completion;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
disposeDeadline();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
options.rpc.off("notification", notification);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Opens a login URL with the platform browser without invoking a shell. */
|
|
86
|
+
export async function launchBrowser(url) {
|
|
87
|
+
const command = process.platform === "darwin"
|
|
88
|
+
? "open"
|
|
89
|
+
: process.platform === "win32"
|
|
90
|
+
? "cmd"
|
|
91
|
+
: "xdg-open";
|
|
92
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
93
|
+
try {
|
|
94
|
+
const child = spawn(command, args, { shell: false, stdio: "ignore" });
|
|
95
|
+
const [code] = await once(child, "exit");
|
|
96
|
+
return code === 0;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/app-server/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { Writable, Readable } from "node:stream";
|
|
3
|
+
/** JSON-RPC error object accepted by respondError. */
|
|
4
|
+
export interface RpcErrorData {
|
|
5
|
+
code: number;
|
|
6
|
+
message: string;
|
|
7
|
+
data?: unknown;
|
|
8
|
+
}
|
|
9
|
+
/** Represents an error response received over JSON-RPC. */
|
|
10
|
+
export declare class RpcError extends Error {
|
|
11
|
+
readonly rpcCode: number;
|
|
12
|
+
constructor(rpcCode: number, message: string);
|
|
13
|
+
}
|
|
14
|
+
/** Request initiated by app-server toward the proxy. */
|
|
15
|
+
export interface ServerRequest {
|
|
16
|
+
id: string | number;
|
|
17
|
+
method: string;
|
|
18
|
+
params: unknown;
|
|
19
|
+
}
|
|
20
|
+
/** Exchanges newline-delimited JSON-RPC messages with app-server. */
|
|
21
|
+
export declare class JsonRpcTransport extends EventEmitter {
|
|
22
|
+
#private;
|
|
23
|
+
constructor(input: Readable, output: Writable, maxPending?: number);
|
|
24
|
+
request(method: string, params: unknown, signal?: AbortSignal): Promise<unknown>;
|
|
25
|
+
notify(method: string, params?: unknown): void;
|
|
26
|
+
respond(id: string | number, result: unknown): void;
|
|
27
|
+
respondError(id: string | number, error: RpcErrorData): void;
|
|
28
|
+
close(reason?: Error): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import { record } from "../core/canonical.js";
|
|
4
|
+
import { listenForAbort } from "../core/abort.js";
|
|
5
|
+
/** Represents an error response received over JSON-RPC. */
|
|
6
|
+
export class RpcError extends Error {
|
|
7
|
+
rpcCode;
|
|
8
|
+
constructor(rpcCode, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.rpcCode = rpcCode;
|
|
11
|
+
this.name = "RpcError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** Exchanges newline-delimited JSON-RPC messages with app-server. */
|
|
15
|
+
export class JsonRpcTransport extends EventEmitter {
|
|
16
|
+
#pending = new Map();
|
|
17
|
+
#output;
|
|
18
|
+
#maxPending;
|
|
19
|
+
#nextId = 1;
|
|
20
|
+
#closed = false;
|
|
21
|
+
constructor(input, output, maxPending = 256) {
|
|
22
|
+
super();
|
|
23
|
+
this.#output = output;
|
|
24
|
+
this.#maxPending = maxPending;
|
|
25
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
26
|
+
lines.on("line", (line) => this.#receive(line));
|
|
27
|
+
lines.on("close", () => this.close(new Error("app-server transport closed")));
|
|
28
|
+
input.on("error", (error) => this.close(error));
|
|
29
|
+
output.on("error", (error) => this.close(error));
|
|
30
|
+
}
|
|
31
|
+
request(method, params, signal) {
|
|
32
|
+
if (this.#closed)
|
|
33
|
+
return Promise.reject(new Error("app-server transport is closed"));
|
|
34
|
+
if (signal?.aborted)
|
|
35
|
+
return Promise.reject(signal.reason ?? new Error("request cancelled"));
|
|
36
|
+
if (this.#pending.size >= this.#maxPending)
|
|
37
|
+
return Promise.reject(new RpcError(-32001, "app-server request queue is full"));
|
|
38
|
+
const id = this.#nextId++;
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
let disposeAbort = () => undefined;
|
|
41
|
+
const abort = (abortedSignal) => {
|
|
42
|
+
if (!this.#pending.delete(id))
|
|
43
|
+
return;
|
|
44
|
+
reject(abortedSignal.reason ?? new Error("request cancelled"));
|
|
45
|
+
};
|
|
46
|
+
const pending = {
|
|
47
|
+
resolve: (value) => {
|
|
48
|
+
disposeAbort();
|
|
49
|
+
resolve(value);
|
|
50
|
+
},
|
|
51
|
+
reject: (reason) => {
|
|
52
|
+
disposeAbort();
|
|
53
|
+
reject(reason);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
this.#pending.set(id, pending);
|
|
57
|
+
disposeAbort = listenForAbort(signal, abort);
|
|
58
|
+
if (!this.#pending.has(id))
|
|
59
|
+
return;
|
|
60
|
+
try {
|
|
61
|
+
this.#write({ id, method, params });
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (this.#pending.delete(id))
|
|
65
|
+
pending.reject(error);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
notify(method, params) {
|
|
70
|
+
this.#write(params === undefined ? { method } : { method, params });
|
|
71
|
+
}
|
|
72
|
+
respond(id, result) {
|
|
73
|
+
this.#write({ id, result });
|
|
74
|
+
}
|
|
75
|
+
respondError(id, error) {
|
|
76
|
+
this.#write({ id, error });
|
|
77
|
+
}
|
|
78
|
+
close(reason = new Error("app-server transport closed")) {
|
|
79
|
+
if (this.#closed)
|
|
80
|
+
return;
|
|
81
|
+
this.#closed = true;
|
|
82
|
+
for (const pending of this.#pending.values())
|
|
83
|
+
pending.reject(reason);
|
|
84
|
+
this.#pending.clear();
|
|
85
|
+
this.emit("close", reason);
|
|
86
|
+
}
|
|
87
|
+
#write(message) {
|
|
88
|
+
if (this.#closed)
|
|
89
|
+
throw new Error("app-server transport is closed");
|
|
90
|
+
this.#output.write(`${JSON.stringify(message)}\n`);
|
|
91
|
+
}
|
|
92
|
+
#receive(line) {
|
|
93
|
+
// Buffered frames may arrive after close; logical closure is authoritative.
|
|
94
|
+
if (this.#closed)
|
|
95
|
+
return;
|
|
96
|
+
if (line.trim() === "")
|
|
97
|
+
return;
|
|
98
|
+
let value;
|
|
99
|
+
try {
|
|
100
|
+
value = JSON.parse(line);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
this.emit("malformed", line);
|
|
104
|
+
this.close(new Error("app-server emitted malformed JSON"));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const message = record(value);
|
|
108
|
+
if (!message) {
|
|
109
|
+
this.emit("malformed", line);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if ((typeof message.id === "number" || typeof message.id === "string") &&
|
|
113
|
+
("result" in message || "error" in message)) {
|
|
114
|
+
const pending = typeof message.id === "number"
|
|
115
|
+
? this.#pending.get(message.id)
|
|
116
|
+
: undefined;
|
|
117
|
+
if (!pending)
|
|
118
|
+
return;
|
|
119
|
+
this.#pending.delete(message.id);
|
|
120
|
+
const error = record(message.error);
|
|
121
|
+
if (error && typeof error.code === "number")
|
|
122
|
+
pending.reject(new RpcError(error.code, String(error.message ?? "JSON-RPC error")));
|
|
123
|
+
else
|
|
124
|
+
pending.resolve(message.result);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (typeof message.method !== "string") {
|
|
128
|
+
this.emit("malformed", line);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (typeof message.id === "number" || typeof message.id === "string")
|
|
132
|
+
this.emit("request", {
|
|
133
|
+
id: message.id,
|
|
134
|
+
method: message.method,
|
|
135
|
+
params: message.params,
|
|
136
|
+
});
|
|
137
|
+
else
|
|
138
|
+
this.emit("notification", message.method, message.params);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=json-rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-rpc.js","sourceRoot":"","sources":["../../src/app-server/json-rpc.ts"],"names":[],"mappings":"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"}
|
package/dist/bin.d.ts
ADDED
package/dist/bin.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { run } from "./cli/cli.js";
|
|
3
|
+
import { writeStartupError } from "./core/logger.js";
|
|
4
|
+
try {
|
|
5
|
+
process.exitCode = await run(process.argv.slice(2));
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
writeStartupError(error);
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,IAAI,CAAC;IACH,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Delays before bounded app-server restart attempts after an unexpected exit. */
|
|
2
|
+
export declare const APP_SERVER_RECOVERY_DELAYS_MS: readonly [1000, 3000, 5000, 10000];
|
|
3
|
+
/** Documents the CLI's supported command and options. */
|
|
4
|
+
export declare const usage = "Usage: codex-openai-proxy serve [options]\n\nOptions:\n --version Print the proxy version\n --help Print this help\n --host <host> Loopback host (default: 127.0.0.1)\n --port <port> TCP port, or 0 for an ephemeral port (default: 8787)\n --root <directory> Allowed working-directory root (default: launch directory)\n --codex-path <path> Override the package-owned Codex executable\n --tool-timeout <duration> Dynamic tool deadline (default: 5m)\n --implicit-tool-continuation <true|false>\n Resolve tool results by tool_call_id (default: true)\n --request-timeout <duration> HTTP request deadline (default: 30s)\n --shutdown-timeout <duration> Graceful shutdown deadline (default: 10s)\n --body-limit <bytes> Maximum request body (default: 1048576)\n --max-requests <count> Maximum concurrent requests (default: 100)\n --log-level <level> debug, info, warn, or error (default: info)\n --state-dir <directory> State directory (default: per-root under ~/.codex-openai-proxy)";
|
|
5
|
+
/** Runs the CLI lifecycle and returns its eventual process exit code. */
|
|
6
|
+
export declare function run(argv: readonly string[]): Promise<number>;
|
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { DEFAULT_STATE_DIR_DESCRIPTION, parseServeOptions, resolveServeOptions, } from "../core/config.js";
|
|
2
|
+
import { createLogger, } from "../core/logger.js";
|
|
3
|
+
import { createProxyServer } from "../http/server.js";
|
|
4
|
+
import { CLIENT_VERSION, PINNED_CODEX_VERSION, startAppServer, } from "../app-server/app-server.js";
|
|
5
|
+
import { ensureAuthenticated } from "../app-server/auth.js";
|
|
6
|
+
import { abortableDelay } from "../core/abort.js";
|
|
7
|
+
/** Delays before bounded app-server restart attempts after an unexpected exit. */
|
|
8
|
+
export const APP_SERVER_RECOVERY_DELAYS_MS = [
|
|
9
|
+
1_000, 3_000, 5_000, 10_000,
|
|
10
|
+
];
|
|
11
|
+
/** Documents the CLI's supported command and options. */
|
|
12
|
+
export const usage = `Usage: codex-openai-proxy serve [options]
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--version Print the proxy version
|
|
16
|
+
--help Print this help
|
|
17
|
+
--host <host> Loopback host (default: 127.0.0.1)
|
|
18
|
+
--port <port> TCP port, or 0 for an ephemeral port (default: 8787)
|
|
19
|
+
--root <directory> Allowed working-directory root (default: launch directory)
|
|
20
|
+
--codex-path <path> Override the package-owned Codex executable
|
|
21
|
+
--tool-timeout <duration> Dynamic tool deadline (default: 5m)
|
|
22
|
+
--implicit-tool-continuation <true|false>
|
|
23
|
+
Resolve tool results by tool_call_id (default: true)
|
|
24
|
+
--request-timeout <duration> HTTP request deadline (default: 30s)
|
|
25
|
+
--shutdown-timeout <duration> Graceful shutdown deadline (default: 10s)
|
|
26
|
+
--body-limit <bytes> Maximum request body (default: 1048576)
|
|
27
|
+
--max-requests <count> Maximum concurrent requests (default: 100)
|
|
28
|
+
--log-level <level> debug, info, warn, or error (default: info)
|
|
29
|
+
--state-dir <directory> State directory (default: ${DEFAULT_STATE_DIR_DESCRIPTION})`;
|
|
30
|
+
/** Runs the CLI lifecycle and returns its eventual process exit code. */
|
|
31
|
+
export async function run(argv) {
|
|
32
|
+
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
|
|
33
|
+
process.stdout.write(`${usage}\n`);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (argv.includes("--version")) {
|
|
37
|
+
process.stdout.write(`${CLIENT_VERSION}\n`);
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
if (argv[0] !== "serve")
|
|
41
|
+
throw new Error(`Unknown command: ${argv[0]}\n\n${usage}`);
|
|
42
|
+
const parsed = parseServeOptions(argv.slice(1));
|
|
43
|
+
let log = createLogger(parsed.logLevel, undefined, redactionContext(parsed));
|
|
44
|
+
try {
|
|
45
|
+
const options = await resolveServeOptions(parsed);
|
|
46
|
+
log = createLogger(options.logLevel, undefined, redactionContext(options));
|
|
47
|
+
return await runServer(options, log);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
log.failure("startup_failed", {}, error);
|
|
51
|
+
return 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Derives one redaction context from parsed or finalized configuration. */
|
|
55
|
+
function redactionContext(options) {
|
|
56
|
+
return {
|
|
57
|
+
root: options.root,
|
|
58
|
+
sensitivePaths: [options.stateDir, options.codexPath].filter((path) => path !== undefined),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Installs one-shot process signal handlers and returns an idempotent disposer. */
|
|
62
|
+
function installSignalHandlers(stop) {
|
|
63
|
+
const onSigint = () => stop("SIGINT");
|
|
64
|
+
const onSigterm = () => stop("SIGTERM");
|
|
65
|
+
process.once("SIGINT", onSigint);
|
|
66
|
+
process.once("SIGTERM", onSigterm);
|
|
67
|
+
let disposed = false;
|
|
68
|
+
return () => {
|
|
69
|
+
if (disposed)
|
|
70
|
+
return;
|
|
71
|
+
disposed = true;
|
|
72
|
+
process.off("SIGINT", onSigint);
|
|
73
|
+
process.off("SIGTERM", onSigterm);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** Owns app-server startup, authentication, transport installation, and recovery. */
|
|
77
|
+
class AppServerSupervisor {
|
|
78
|
+
#options;
|
|
79
|
+
#log;
|
|
80
|
+
#proxy;
|
|
81
|
+
#lifecycle;
|
|
82
|
+
#active;
|
|
83
|
+
#starting;
|
|
84
|
+
#initializing;
|
|
85
|
+
#cleanupFailures = new Set();
|
|
86
|
+
#recovering = false;
|
|
87
|
+
constructor({ options, log, proxy, lifecycle }) {
|
|
88
|
+
this.#options = options;
|
|
89
|
+
this.#log = log;
|
|
90
|
+
this.#proxy = proxy;
|
|
91
|
+
this.#lifecycle = lifecycle;
|
|
92
|
+
}
|
|
93
|
+
/** Starts the initial child and installs its transport before returning. */
|
|
94
|
+
async start() {
|
|
95
|
+
await this.#startAndInstall();
|
|
96
|
+
}
|
|
97
|
+
/** Waits for initialization to settle, then stops every current child. */
|
|
98
|
+
async stop() {
|
|
99
|
+
// startAppServer owns cancellation before it can expose an AppServer. Await
|
|
100
|
+
// that task so shutdown cannot complete while a recovery child is still
|
|
101
|
+
// being verified, initialized, or authenticated.
|
|
102
|
+
let initialized;
|
|
103
|
+
try {
|
|
104
|
+
initialized = await this.#initializing;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// The initialization observer below classifies failures at rejection
|
|
108
|
+
// time, while normal startup and recovery errors remain with callers.
|
|
109
|
+
}
|
|
110
|
+
const children = [
|
|
111
|
+
...new Set([this.#active, this.#starting, initialized]),
|
|
112
|
+
].filter((child) => child !== undefined);
|
|
113
|
+
// AppServer.stop() memoizes its own shutdown, so repeated calls are safe.
|
|
114
|
+
const results = await Promise.allSettled(children.map(async (child) => await child.stop()));
|
|
115
|
+
for (const result of results)
|
|
116
|
+
if (result.status === "rejected")
|
|
117
|
+
this.#cleanupFailures.add(result.reason);
|
|
118
|
+
const failures = [...this.#cleanupFailures];
|
|
119
|
+
if (failures.length === 1)
|
|
120
|
+
throw failures[0];
|
|
121
|
+
if (failures.length > 1)
|
|
122
|
+
throw new AggregateError(failures, "app-server cleanup failed");
|
|
123
|
+
}
|
|
124
|
+
/** Stops one partial child while retaining cleanup failure for shutdown. */
|
|
125
|
+
async #stopPartial(next) {
|
|
126
|
+
try {
|
|
127
|
+
await next.stop();
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
this.#cleanupFailures.add(error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Starts and authenticates one child without exposing a partial transport. */
|
|
134
|
+
async #initialize() {
|
|
135
|
+
const next = await startAppServer({
|
|
136
|
+
codexPath: this.#options.codexPath,
|
|
137
|
+
root: this.#options.root,
|
|
138
|
+
startupTimeoutMs: this.#options.toolTimeoutMs,
|
|
139
|
+
shutdownTimeoutMs: this.#options.shutdownTimeoutMs,
|
|
140
|
+
log: this.#log,
|
|
141
|
+
diagnosticLogging: this.#options.logLevel === "debug",
|
|
142
|
+
signal: this.#lifecycle.signal,
|
|
143
|
+
});
|
|
144
|
+
this.#starting = next;
|
|
145
|
+
let exited = false;
|
|
146
|
+
next.child.once("exit", () => {
|
|
147
|
+
exited = true;
|
|
148
|
+
if (!this.#lifecycle.signal.aborted && this.#active === next) {
|
|
149
|
+
this.#active = undefined;
|
|
150
|
+
this.#proxy.setReady(false);
|
|
151
|
+
this.#proxy.setTransport(undefined);
|
|
152
|
+
void this.#recover();
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
try {
|
|
156
|
+
await ensureAuthenticated({
|
|
157
|
+
rpc: next.rpc,
|
|
158
|
+
log: this.#log,
|
|
159
|
+
timeoutMs: this.#options.toolTimeoutMs,
|
|
160
|
+
interactive: Boolean(process.stderr.isTTY),
|
|
161
|
+
terminal: (message) => process.stderr.write(message),
|
|
162
|
+
signal: this.#lifecycle.signal,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
await this.#stopPartial(next);
|
|
167
|
+
if (this.#starting === next)
|
|
168
|
+
this.#starting = undefined;
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
if (this.#lifecycle.signal.aborted || exited) {
|
|
172
|
+
await this.#stopPartial(next);
|
|
173
|
+
if (this.#starting === next)
|
|
174
|
+
this.#starting = undefined;
|
|
175
|
+
throw (this.#lifecycle.signal.reason ??
|
|
176
|
+
new Error("app-server exited during startup"));
|
|
177
|
+
}
|
|
178
|
+
this.#starting = undefined;
|
|
179
|
+
return next;
|
|
180
|
+
}
|
|
181
|
+
/** Atomically promotes one initialized child into the live proxy transport. */
|
|
182
|
+
async #startAndInstall() {
|
|
183
|
+
const initializing = this.#initialize();
|
|
184
|
+
this.#initializing = initializing;
|
|
185
|
+
void initializing.catch((error) => {
|
|
186
|
+
// An ordinary failure that preceded shutdown remains an operational
|
|
187
|
+
// startup/recovery error. Once aborted, only the exact lifecycle reason
|
|
188
|
+
// is expected; a different rejection can be abort cleanup failing.
|
|
189
|
+
if (this.#lifecycle.signal.aborted &&
|
|
190
|
+
error !== this.#lifecycle.signal.reason)
|
|
191
|
+
this.#cleanupFailures.add(error);
|
|
192
|
+
});
|
|
193
|
+
try {
|
|
194
|
+
const next = await initializing;
|
|
195
|
+
if (this.#lifecycle.signal.aborted) {
|
|
196
|
+
await this.#stopPartial(next);
|
|
197
|
+
throw this.#lifecycle.signal.reason;
|
|
198
|
+
}
|
|
199
|
+
this.#active = next;
|
|
200
|
+
this.#proxy.setTransport(next.rpc, next.requirements);
|
|
201
|
+
this.#proxy.setReady(true);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
if (this.#initializing === initializing)
|
|
205
|
+
this.#initializing = undefined;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/** Runs the single bounded recovery loop while leaving HTTP listening. */
|
|
209
|
+
async #recover() {
|
|
210
|
+
if (this.#recovering || this.#lifecycle.signal.aborted)
|
|
211
|
+
return;
|
|
212
|
+
this.#recovering = true;
|
|
213
|
+
this.#proxy.setReady(false);
|
|
214
|
+
try {
|
|
215
|
+
for (const [index, delayMs] of APP_SERVER_RECOVERY_DELAYS_MS.entries()) {
|
|
216
|
+
if (this.#lifecycle.signal.aborted)
|
|
217
|
+
return;
|
|
218
|
+
const attempt = index + 1;
|
|
219
|
+
try {
|
|
220
|
+
await abortableDelay(delayMs, this.#lifecycle.signal);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
if (this.#lifecycle.signal.aborted)
|
|
224
|
+
return;
|
|
225
|
+
throw new Error("App-server recovery delay failed.");
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
await this.#startAndInstall();
|
|
229
|
+
this.#log("info", "app_server_restarted", { attempt });
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
if (this.#lifecycle.signal.aborted)
|
|
234
|
+
return;
|
|
235
|
+
this.#log.failure("app_server_restart_failed", { attempt }, error);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
this.#log("error", "app_server_restart_exhausted");
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
this.#recovering = false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/** Runs the proxy lifecycle after configuration has been fully resolved. */
|
|
246
|
+
async function runServer(options, log) {
|
|
247
|
+
const proxy = createProxyServer(options, log);
|
|
248
|
+
const address = await proxy.listen();
|
|
249
|
+
log("info", "server_listening", {
|
|
250
|
+
proxy_version: CLIENT_VERSION,
|
|
251
|
+
codex_version: PINNED_CODEX_VERSION,
|
|
252
|
+
host: address.address,
|
|
253
|
+
port: address.port,
|
|
254
|
+
default_sandbox: "read-only",
|
|
255
|
+
default_web_search: "disabled",
|
|
256
|
+
ready: false,
|
|
257
|
+
});
|
|
258
|
+
log("debug", "server_root", { root: options.root });
|
|
259
|
+
const lifecycle = new AbortController();
|
|
260
|
+
const supervisor = new AppServerSupervisor({
|
|
261
|
+
options,
|
|
262
|
+
log,
|
|
263
|
+
proxy,
|
|
264
|
+
lifecycle,
|
|
265
|
+
});
|
|
266
|
+
let settleShutdown;
|
|
267
|
+
const shutdown = new Promise((resolve) => {
|
|
268
|
+
settleShutdown = resolve;
|
|
269
|
+
});
|
|
270
|
+
let stopping;
|
|
271
|
+
const stop = (signal) => {
|
|
272
|
+
if (stopping)
|
|
273
|
+
return;
|
|
274
|
+
lifecycle.abort(new Error(`proxy received ${signal}`));
|
|
275
|
+
log("info", "shutdown_started", { signal });
|
|
276
|
+
proxy.setReady(false);
|
|
277
|
+
// Disposing the coordinator first rejects suspended dynamic tool calls
|
|
278
|
+
// before the child transport is terminated.
|
|
279
|
+
proxy.setTransport(undefined);
|
|
280
|
+
stopping = (async () => {
|
|
281
|
+
try {
|
|
282
|
+
await supervisor.stop();
|
|
283
|
+
await proxy.close();
|
|
284
|
+
log("info", "shutdown_complete");
|
|
285
|
+
settleShutdown(0);
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
await proxy.close().catch(() => undefined);
|
|
289
|
+
log.failure("shutdown_failed", {}, error);
|
|
290
|
+
settleShutdown(1);
|
|
291
|
+
}
|
|
292
|
+
})();
|
|
293
|
+
};
|
|
294
|
+
// Install lifecycle handlers before authentication so login is cancellable.
|
|
295
|
+
const disposeSignals = installSignalHandlers(stop);
|
|
296
|
+
try {
|
|
297
|
+
// Authentication must finish before readiness admits proxy traffic.
|
|
298
|
+
await supervisor.start();
|
|
299
|
+
if (lifecycle.signal.aborted)
|
|
300
|
+
return await shutdown;
|
|
301
|
+
// Announce readiness only after shutdown handlers can observe an immediate signal.
|
|
302
|
+
log("info", "app_server_ready", {
|
|
303
|
+
proxy_version: CLIENT_VERSION,
|
|
304
|
+
codex_version: PINNED_CODEX_VERSION,
|
|
305
|
+
});
|
|
306
|
+
return await shutdown;
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
if (lifecycle.signal.aborted)
|
|
310
|
+
return await shutdown;
|
|
311
|
+
await supervisor.stop().catch(() => undefined);
|
|
312
|
+
await proxy.close().catch(() => undefined);
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
disposeSignals();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"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"}
|