Changeset 0.33.0 (#207)

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit is contained in:
2026-03-19 21:37:32 +00:00
committed by xcaliber
parent b1266b0d7c
commit ed3e9363f2
42 changed files with 2527 additions and 129 deletions

643
server/static/openapi.yaml Normal file
View File

@@ -0,0 +1,643 @@
openapi: 3.0.3
info:
title: Chat Switchboard API
description: |
Multi-provider AI chat platform with team workspaces, workflow automation,
and extensibility via Starlark packages.
**Authentication:** Most endpoints require a Bearer JWT token obtained via
`POST /api/v1/auth/login`. Include it as `Authorization: Bearer <token>`.
**WebSocket:** Real-time events are delivered over WebSocket at `/ws`.
Obtain a ticket via `POST /api/v1/ws/ticket` and connect with `?ticket=<id>`.
version: "${VERSION}"
contact:
name: Chat Switchboard
servers:
- url: /
description: Current instance
tags:
- name: Auth
description: Authentication and session management
- name: Channels
description: Chat channel CRUD and messaging
- name: Completions
description: AI completion requests (streaming and non-streaming)
- name: Health
description: System health and readiness probes
- name: Admin
description: Platform administration (requires admin role)
- name: Usage
description: Token usage and cost tracking
- name: WebSocket
description: Real-time event delivery
paths:
# ── Auth ───────────────────────────────────
/api/v1/auth/register:
post:
tags: [Auth]
summary: Register a new user
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [username, password]
properties:
username:
type: string
minLength: 3
password:
type: string
minLength: 8
email:
type: string
format: email
display_name:
type: string
responses:
"201":
description: User created
content:
application/json:
schema:
$ref: "#/components/schemas/AuthResponse"
"400":
$ref: "#/components/responses/BadRequest"
"409":
description: Username already taken
/api/v1/auth/login:
post:
tags: [Auth]
summary: Authenticate and obtain JWT tokens
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [username, password]
properties:
username:
type: string
password:
type: string
responses:
"200":
description: Login successful
content:
application/json:
schema:
$ref: "#/components/schemas/AuthResponse"
"401":
description: Invalid credentials
"429":
description: Rate limited
/api/v1/auth/refresh:
post:
tags: [Auth]
summary: Refresh an expired access token
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [refresh_token]
properties:
refresh_token:
type: string
responses:
"200":
description: New token pair
content:
application/json:
schema:
$ref: "#/components/schemas/AuthResponse"
"401":
description: Invalid or expired refresh token
/api/v1/auth/logout:
post:
tags: [Auth]
summary: Invalidate the current session
security:
- bearerAuth: []
responses:
"200":
description: Logged out
# ── Channels ───────────────────────────────
/api/v1/channels:
get:
tags: [Channels]
summary: List channels accessible to the current user
security:
- bearerAuth: []
parameters:
- name: type
in: query
schema:
type: string
enum: [direct, group, workflow]
- name: page
in: query
schema:
type: integer
default: 1
- name: per_page
in: query
schema:
type: integer
default: 50
responses:
"200":
description: Channel list
content:
application/json:
schema:
type: object
properties:
channels:
type: array
items:
$ref: "#/components/schemas/Channel"
total:
type: integer
post:
tags: [Channels]
summary: Create a new channel
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
title:
type: string
type:
type: string
enum: [direct, group]
default: direct
system_prompt:
type: string
responses:
"201":
description: Channel created
content:
application/json:
schema:
$ref: "#/components/schemas/Channel"
/api/v1/channels/{id}:
get:
tags: [Channels]
summary: Get channel details
security:
- bearerAuth: []
parameters:
- $ref: "#/components/parameters/ChannelID"
responses:
"200":
description: Channel details
content:
application/json:
schema:
$ref: "#/components/schemas/Channel"
"404":
$ref: "#/components/responses/NotFound"
put:
tags: [Channels]
summary: Update channel settings
security:
- bearerAuth: []
parameters:
- $ref: "#/components/parameters/ChannelID"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
title:
type: string
system_prompt:
type: string
ai_mode:
type: string
enum: [auto, off, mention_only]
responses:
"200":
description: Updated
delete:
tags: [Channels]
summary: Archive a channel
security:
- bearerAuth: []
parameters:
- $ref: "#/components/parameters/ChannelID"
responses:
"200":
description: Archived
# ── Completions ────────────────────────────
/api/v1/chat/completions:
post:
tags: [Completions]
summary: Send a message and get an AI completion
description: |
Streams SSE events by default. Set `stream: false` for a single JSON response.
Supports tool calling, @mentions, multi-model routing, and workflow integration.
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [content, channel_id]
properties:
channel_id:
type: string
format: uuid
content:
type: string
model:
type: string
description: Override the default model
persona_id:
type: string
format: uuid
provider_config_id:
type: string
format: uuid
max_tokens:
type: integer
temperature:
type: number
minimum: 0
maximum: 2
top_p:
type: number
minimum: 0
maximum: 1
stream:
type: boolean
default: true
file_ids:
type: array
items:
type: string
format: uuid
disabled_tools:
type: array
items:
type: string
responses:
"200":
description: |
**Streaming:** SSE events (`data: {"content":"..."}`, `data: [DONE]`).
**Non-streaming:** OpenAI-compatible JSON response.
content:
text/event-stream:
schema:
type: string
application/json:
schema:
type: object
properties:
model:
type: string
choices:
type: array
items:
type: object
properties:
message:
type: object
properties:
role:
type: string
content:
type: string
finish_reason:
type: string
usage:
type: object
properties:
prompt_tokens:
type: integer
completion_tokens:
type: integer
total_tokens:
type: integer
"400":
$ref: "#/components/responses/BadRequest"
"429":
description: Token budget exceeded
# ── Health ─────────────────────────────────
/health:
get:
tags: [Health]
summary: Basic health check
responses:
"200":
description: System status
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: ok
version:
type: string
database:
type: boolean
schema_version:
type: integer
/healthz/live:
get:
tags: [Health]
summary: Kubernetes liveness probe
responses:
"200":
description: Process alive
/healthz/ready:
get:
tags: [Health]
summary: Kubernetes readiness probe
description: Returns 503 if the database is unreachable (2s timeout).
responses:
"200":
description: Ready to serve traffic
"503":
description: Database unavailable
/metrics:
get:
tags: [Health]
summary: Prometheus metrics endpoint
description: |
Returns all `switchboard_*` metrics in Prometheus text exposition format.
Includes HTTP request latency, WebSocket connections, completion tokens,
DB pool stats, and provider health gauges.
responses:
"200":
description: Prometheus text format
content:
text/plain:
schema:
type: string
# ── WebSocket ──────────────────────────────
/api/v1/ws/ticket:
post:
tags: [WebSocket]
summary: Obtain a WebSocket connection ticket
description: |
Returns a single-use ticket (30s TTL) for authenticating the WebSocket
upgrade at `/ws?ticket=<id>`. Cross-pod safe (v0.32.0).
security:
- bearerAuth: []
responses:
"200":
description: Ticket issued
content:
application/json:
schema:
type: object
properties:
ticket:
type: string
# ── Admin: Stats ───────────────────────────
/api/v1/admin/stats:
get:
tags: [Admin]
summary: Platform statistics
security:
- bearerAuth: []
responses:
"200":
description: Aggregate counts
content:
application/json:
schema:
type: object
properties:
users:
type: integer
channels:
type: integer
messages:
type: integer
# ── Admin: Provider Health ─────────────────
/api/v1/admin/providers/health:
get:
tags: [Admin]
summary: Current health status for all providers
security:
- bearerAuth: []
responses:
"200":
description: Provider health summaries
content:
application/json:
schema:
type: object
properties:
providers:
type: array
items:
$ref: "#/components/schemas/ProviderHealth"
# ── Admin: Usage ───────────────────────────
/api/v1/admin/usage:
get:
tags: [Admin, Usage]
summary: Aggregated token usage
security:
- bearerAuth: []
parameters:
- name: since
in: query
schema:
type: string
format: date-time
- name: until
in: query
schema:
type: string
format: date-time
- name: period
in: query
schema:
type: string
enum: [7d, 30d, 90d]
- name: group_by
in: query
schema:
type: string
enum: [model, user, provider, day]
responses:
"200":
description: Usage data
# ── Admin: Dashboard ───────────────────────
/api/v1/admin/dashboard:
get:
tags: [Admin]
summary: Real-time observability dashboard data
description: |
Aggregates provider health, 24h usage, DB pool stats, WebSocket count,
recent errors, and uptime into a single response. Designed for the
built-in admin dashboard (v0.33.0).
security:
- bearerAuth: []
responses:
"200":
description: Dashboard snapshot
content:
application/json:
schema:
type: object
properties:
providers:
type: array
items:
$ref: "#/components/schemas/ProviderHealth"
usage_24h:
type: object
db_pool:
type: object
properties:
open_connections:
type: integer
in_use:
type: integer
idle:
type: integer
ws_connections:
type: integer
uptime_seconds:
type: number
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
ChannelID:
name: id
in: path
required: true
schema:
type: string
format: uuid
responses:
BadRequest:
description: Invalid request
content:
application/json:
schema:
type: object
properties:
error:
type: string
NotFound:
description: Resource not found
content:
application/json:
schema:
type: object
properties:
error:
type: string
schemas:
AuthResponse:
type: object
properties:
token:
type: string
refresh_token:
type: string
user:
type: object
properties:
id:
type: string
format: uuid
username:
type: string
role:
type: string
enum: [admin, user]
Channel:
type: object
properties:
id:
type: string
format: uuid
title:
type: string
type:
type: string
enum: [direct, group, workflow]
user_id:
type: string
format: uuid
team_id:
type: string
format: uuid
ai_mode:
type: string
enum: [auto, off, mention_only]
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
ProviderHealth:
type: object
properties:
provider_config_id:
type: string
format: uuid
status:
type: string
enum: [healthy, degraded, down, unknown]
request_count:
type: integer
error_count:
type: integer
error_rate:
type: number
avg_latency_ms:
type: number
max_latency_ms:
type: integer