@bitkyc08/opencodex 2.6.13 → 2.6.14
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/gui/dist/assets/{index-BTTqyZ-C.js → index-B64_jgH-.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic.ts +8 -3
- package/src/adapters/client-fingerprint.ts +4 -0
- package/src/adapters/google.ts +0 -3
- package/src/adapters/kiro-wire.ts +2 -2
- package/src/adapters/kiro.ts +1 -1
- package/src/adapters/openai-chat.ts +104 -69
- package/src/adapters/openai-responses.ts +36 -1
- package/src/oauth/anthropic.ts +2 -2
- package/src/oauth/google-antigravity.ts +4 -3
- package/src/oauth/kimi.ts +2 -2
- package/src/server/adapter-resolve.ts +43 -0
- package/src/server/gui-static.ts +98 -0
- package/src/server.ts +8 -125
package/src/server.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { timingSafeEqual } from "node:crypto";
|
|
3
|
-
import { extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
|
-
import { createAnthropicAdapter } from "./adapters/anthropic";
|
|
5
|
-
import { createAzureAdapter } from "./adapters/azure";
|
|
6
|
-
import { createGoogleAdapter } from "./adapters/google";
|
|
7
|
-
import { createKiroAdapter } from "./adapters/kiro";
|
|
8
|
-
import { createOpenAIChatAdapter } from "./adapters/openai-chat";
|
|
9
|
-
import { createResponsesPassthroughAdapter } from "./adapters/openai-responses";
|
|
10
3
|
import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse, type ResponsesTerminalStatus } from "./bridge";
|
|
11
4
|
import { markActivity } from "./sidecar-tracker";
|
|
12
5
|
import {
|
|
@@ -87,6 +80,10 @@ import {
|
|
|
87
80
|
type CodexUpstreamOutcome,
|
|
88
81
|
} from "./codex-routing";
|
|
89
82
|
import { registerCodexWebSocket, unregisterCodexWebSocket, updateCodexWebSocketAuthContext } from "./codex-websocket-registry";
|
|
83
|
+
import { resolveGuiFilePath, rootFallbackPayload, serveGuiFile } from "./server/gui-static";
|
|
84
|
+
export { resolveGuiFilePath, rootFallbackPayload } from "./server/gui-static";
|
|
85
|
+
import { resolveAdapter, resolveWireProtocolOverride } from "./server/adapter-resolve";
|
|
86
|
+
export { resolveAdapter } from "./server/adapter-resolve";
|
|
90
87
|
|
|
91
88
|
// ---------------------------------------------------------------------------
|
|
92
89
|
// Active turn tracking + graceful shutdown drain
|
|
@@ -188,124 +185,10 @@ const VERSION = (() => {
|
|
|
188
185
|
}
|
|
189
186
|
})();
|
|
190
187
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
".json": "application/json", ".svg": "image/svg+xml", ".png": "image/png",
|
|
194
|
-
".ico": "image/x-icon",
|
|
195
|
-
};
|
|
188
|
+
// GUI static serving extracted to ./server/gui-static. Re-exported below to keep the
|
|
189
|
+
// "../src/server" import surface stable for tests/callers.
|
|
196
190
|
|
|
197
|
-
|
|
198
|
-
const candidates = [
|
|
199
|
-
join(import.meta.dir, "..", "gui", "dist"),
|
|
200
|
-
join(import.meta.dir, "..", "..", "gui", "dist"),
|
|
201
|
-
];
|
|
202
|
-
for (const c of candidates) {
|
|
203
|
-
if (existsSync(join(c, "index.html"))) return c;
|
|
204
|
-
}
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function resolveGuiFilePath(guiDist: string, pathname: string): string | null {
|
|
209
|
-
let decodedPath: string;
|
|
210
|
-
try {
|
|
211
|
-
decodedPath = decodeURIComponent(pathname);
|
|
212
|
-
} catch {
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
if (decodedPath.includes("\0")) return null;
|
|
216
|
-
|
|
217
|
-
const relativePath = decodedPath === "/" || decodedPath === ""
|
|
218
|
-
? "index.html"
|
|
219
|
-
: decodedPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
220
|
-
const root = resolve(guiDist);
|
|
221
|
-
const filePath = resolve(root, relativePath);
|
|
222
|
-
const rel = relative(root, filePath);
|
|
223
|
-
if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) return null;
|
|
224
|
-
return filePath;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
function isFile(path: string): boolean {
|
|
228
|
-
try {
|
|
229
|
-
return statSync(path).isFile();
|
|
230
|
-
} catch {
|
|
231
|
-
return false;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function serveGuiFile(pathname: string): Response | null {
|
|
236
|
-
const guiDist = findGuiDist();
|
|
237
|
-
if (!guiDist) return null;
|
|
238
|
-
const filePath = resolveGuiFilePath(guiDist, pathname);
|
|
239
|
-
if (!filePath) return null;
|
|
240
|
-
|
|
241
|
-
if (!isFile(filePath)) {
|
|
242
|
-
if (!extname(pathname)) {
|
|
243
|
-
const indexPath = join(guiDist, "index.html");
|
|
244
|
-
if (isFile(indexPath)) {
|
|
245
|
-
return new Response(Bun.file(indexPath), {
|
|
246
|
-
headers: { "Content-Type": "text/html" },
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const ext = extname(filePath);
|
|
254
|
-
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
255
|
-
return new Response(Bun.file(filePath), {
|
|
256
|
-
headers: { "Content-Type": contentType },
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export function rootFallbackPayload() {
|
|
261
|
-
return {
|
|
262
|
-
status: "ok",
|
|
263
|
-
service: "opencodex",
|
|
264
|
-
version: VERSION,
|
|
265
|
-
dashboard: {
|
|
266
|
-
available: false,
|
|
267
|
-
reason: "GUI build not found. Run `bun run build:gui` from the opencodex repo, or use `ocx gui` from a packaged install.",
|
|
268
|
-
},
|
|
269
|
-
endpoints: {
|
|
270
|
-
health: "/healthz",
|
|
271
|
-
models: "/v1/models",
|
|
272
|
-
responses: "/v1/responses",
|
|
273
|
-
management: "/api/*",
|
|
274
|
-
},
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const ANTHROPIC_WIRE_MODELS: Record<string, Set<string>> = {
|
|
279
|
-
"opencode-go": new Set(["minimax-m2.5", "minimax-m2.7", "minimax-m3", "qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus"]),
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
function resolveWireProtocolOverride(providerName: string, modelId: string, providerConfig: OcxProviderConfig): OcxProviderConfig {
|
|
283
|
-
const overrideSet = ANTHROPIC_WIRE_MODELS[providerName];
|
|
284
|
-
if (overrideSet?.has(modelId) && providerConfig.adapter !== "anthropic") {
|
|
285
|
-
return { ...providerConfig, adapter: "anthropic" };
|
|
286
|
-
}
|
|
287
|
-
return providerConfig;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export function resolveAdapter(providerConfig: OcxProviderConfig) {
|
|
291
|
-
switch (providerConfig.adapter) {
|
|
292
|
-
case "openai-chat":
|
|
293
|
-
return createOpenAIChatAdapter(providerConfig);
|
|
294
|
-
case "anthropic":
|
|
295
|
-
return createAnthropicAdapter(providerConfig);
|
|
296
|
-
case "openai-responses":
|
|
297
|
-
return createResponsesPassthroughAdapter(providerConfig);
|
|
298
|
-
case "google":
|
|
299
|
-
return createGoogleAdapter(providerConfig);
|
|
300
|
-
case "kiro":
|
|
301
|
-
return createKiroAdapter(providerConfig);
|
|
302
|
-
case "azure":
|
|
303
|
-
case "azure-openai":
|
|
304
|
-
return createAzureAdapter(providerConfig);
|
|
305
|
-
default:
|
|
306
|
-
throw new Error(`Unknown adapter: ${providerConfig.adapter}`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
191
|
+
// Adapter resolution + wire-protocol override extracted to ./server/adapter-resolve.
|
|
309
192
|
|
|
310
193
|
function sidecarOutcomeRecorder(config: OcxConfig, authCtx: CodexAuthContext): ((outcome: CodexUpstreamOutcome) => void) | undefined {
|
|
311
194
|
return authCtx.kind === "pool" || authCtx.kind === "main-pool"
|