docs(api): document /api/v1/ws chat WebSocket endpoint in openapi.yaml (#4215)

Integrated into release/v3.8.29 (round 8)
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-18 20:50:12 -03:00
committed by GitHub
parent 1cdbf73925
commit fe548212a4
2 changed files with 68 additions and 0 deletions

View File

@@ -1104,6 +1104,42 @@ paths:
"502":
description: All upstream providers failed
/api/v1/ws:
get:
tags: [Chat]
summary: Chat completion over WebSocket (handshake + upgrade)
description: >-
OpenAI-compatible chat over a WebSocket connection. `GET` with
`?handshake=1` returns the connection descriptor (auth path, message
protocol and live-event channels) as JSON; a plain `GET` without an
Upgrade returns `426 Upgrade Required`. After upgrading, the client
exchanges JSON frames — `{type:"request", id, payload:{model, messages}}`
to start a completion and `{type:"cancel", id}` to abort it. A separate
live channel (default port `LIVE_WS_PORT=20129`, path `/live`) streams
dashboard events on the `requests`, `combo` and `credentials` topics with
a 15s heartbeat. Requires an API key.
security:
- BearerAuth: []
parameters:
- name: handshake
in: query
description: Set to `1` to receive the JSON connection descriptor instead of upgrading.
required: false
schema:
type: string
enum: ["1"]
responses:
"101":
description: WebSocket upgrade successful
"200":
description: Handshake descriptor (auth path, message protocol, live channels)
"401":
description: WebSocket auth required (no credential supplied)
"403":
description: Invalid WebSocket credential
"426":
description: Upgrade Required — connect via WebSocket or use `?handshake=1`
/api/v1/providers/{provider}/chat/completions:
post:
tags: [Chat]

View File

@@ -0,0 +1,32 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import yaml from "js-yaml";
// Regression guard: the OpenAI-compatible chat WebSocket endpoint (/api/v1/ws)
// must be documented in openapi.yaml so it shows up on the dashboard's
// "API Endpoints" page (which renders /api/openapi/spec, parsed from this file).
// The route (src/app/api/v1/ws/route.ts) shipped in v3.6.6 but was never listed
// in the spec, so it was invisible in the endpoints reference.
const ROOT = fileURLToPath(new URL("../../", import.meta.url));
const spec = yaml.load(readFileSync(ROOT + "docs/reference/openapi.yaml", "utf8")) as {
paths: Record<string, Record<string, { tags?: string[]; security?: unknown[]; responses?: Record<string, unknown> }>>;
};
test("openapi.yaml documents the /api/v1/ws chat WebSocket endpoint", () => {
const entry = spec.paths["/api/v1/ws"];
assert.ok(entry, "/api/v1/ws must be present in openapi.yaml paths");
assert.ok(entry.get, "/api/v1/ws must document the GET (handshake/upgrade) operation");
});
test("/api/v1/ws is tagged, authenticated and documents the WS upgrade responses", () => {
const op = spec.paths["/api/v1/ws"].get;
assert.ok((op.tags ?? []).length > 0, "should be tagged so it groups on the endpoints page");
assert.ok(Array.isArray(op.security) && op.security.length > 0, "should require auth (BearerAuth)");
const responses = op.responses ?? {};
for (const code of ["101", "426"]) {
assert.ok(code in responses, `should document the ${code} WebSocket response`);
}
});