feat(gateway): add config toggle for chat completions endpoint

This commit is contained in:
Peter Steinberger
2026-01-10 22:34:25 +01:00
parent 050c1c5391
commit 1110d96769
8 changed files with 88 additions and 3 deletions

View File

@@ -9,12 +9,16 @@ import {
installGatewayTestHooks();
async function startServer(port: number) {
async function startServer(
port: number,
opts?: { openAiChatCompletionsEnabled?: boolean },
) {
const { startGatewayServer } = await import("./server.js");
return await startGatewayServer(port, {
host: "127.0.0.1",
auth: { mode: "token", token: "secret" },
controlUiEnabled: false,
openAiChatCompletionsEnabled: opts?.openAiChatCompletionsEnabled,
});
}
@@ -44,6 +48,22 @@ function parseSseDataLines(text: string): string[] {
}
describe("OpenAI-compatible HTTP API (e2e)", () => {
it("can be disabled via config (404)", async () => {
const port = await getFreePort();
const server = await startServer(port, {
openAiChatCompletionsEnabled: false,
});
try {
const res = await postChatCompletions(port, {
model: "clawdbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(404);
} finally {
await server.close({ reason: "test done" });
}
});
it("rejects non-POST", async () => {
const port = await getFreePort();
const server = await startServer(port);

View File

@@ -206,6 +206,7 @@ export function createGatewayHttpServer(opts: {
canvasHost: CanvasHostHandler | null;
controlUiEnabled: boolean;
controlUiBasePath: string;
openAiChatCompletionsEnabled: boolean;
handleHooksRequest: HooksRequestHandler;
resolvedAuth: import("./auth.js").ResolvedGatewayAuth;
}): HttpServer {
@@ -213,6 +214,7 @@ export function createGatewayHttpServer(opts: {
canvasHost,
controlUiEnabled,
controlUiBasePath,
openAiChatCompletionsEnabled,
handleHooksRequest,
resolvedAuth,
} = opts;
@@ -222,8 +224,10 @@ export function createGatewayHttpServer(opts: {
void (async () => {
if (await handleHooksRequest(req, res)) return;
if (await handleOpenAiHttpRequest(req, res, { auth: resolvedAuth }))
return;
if (openAiChatCompletionsEnabled) {
if (await handleOpenAiHttpRequest(req, res, { auth: resolvedAuth }))
return;
}
if (canvasHost) {
if (await handleA2uiHttpRequest(req, res)) return;
if (await canvasHost.handleHttpRequest(req, res)) return;

View File

@@ -328,6 +328,11 @@ export type GatewayServerOptions = {
* Default: config `gateway.controlUi.enabled` (or true when absent).
*/
controlUiEnabled?: boolean;
/**
* If false, do not serve `POST /v1/chat/completions`.
* Default: config `gateway.http.endpoints.chatCompletions.enabled` (or true when absent).
*/
openAiChatCompletionsEnabled?: boolean;
/**
* Override gateway auth configuration (merges with config).
*/
@@ -432,6 +437,10 @@ export async function startGatewayServer(
}
const controlUiEnabled =
opts.controlUiEnabled ?? cfgAtStart.gateway?.controlUi?.enabled ?? true;
const openAiChatCompletionsEnabled =
opts.openAiChatCompletionsEnabled ??
cfgAtStart.gateway?.http?.endpoints?.chatCompletions?.enabled ??
true;
const controlUiBasePath = normalizeControlUiBasePath(
cfgAtStart.gateway?.controlUi?.basePath,
);
@@ -615,6 +624,7 @@ export async function startGatewayServer(
canvasHost,
controlUiEnabled,
controlUiBasePath,
openAiChatCompletionsEnabled,
handleHooksRequest,
resolvedAuth,
});