Skip to content

api web api

Zachary BENSALEM edited this page Aug 15, 2026 · 1 revision

Web API

Purpose

The web HTTP API is the browser-facing wire surface for the Qredence web chat UI. Routes live under web/app/src/routes/api/ as thin TanStack Start wrappers that delegate to handler functions in web/server/src/handlers/. The browser talks HTTP only: NDJSON over POST /api/chat for streaming a turn, and Server-Sent Events over GET /api/chat/events for out-of-turn pushes. The contract is defined in web/protocol/src/chat-protocol.ts, validated by zod schemas in web/protocol/src/chat-protocol.zod.ts.

The server binds to 127.0.0.1 with no tokens, so there is no multi-user authentication on this surface. All handlers are process-agnostic Request -> Response functions coordinated by a single PrimeBridge per Node process (web/server/src/prime-bridge.ts).

Endpoint reference

Routes are declared under web/app/src/routes/api/. Each row lists the route file, the method and path, the underlying handler, and its purpose. The route wrappers are one-line delegations to @prime-agent/web-server.

Method Path Route file Handler Purpose
POST /api/chat web/app/src/routes/api/chat.ts handleChatPost Run a turn; returns NDJSON ChatStreamEvent frames
POST /api/chat/abort web/app/src/routes/api/chat/abort.ts handleChatAbortPost Abort the active turn and cancel pending dialogs
POST /api/chat/question web/app/src/routes/api/chat/question.ts handleChatQuestionPost Answer a pending tool question
POST /api/chat/new web/app/src/routes/api/chat/new.ts handleChatNewPost Create a session ({cwd, model?, thinkingLevel?})
POST /api/chat/resume web/app/src/routes/api/chat/resume.ts handleChatResumePost Resume by sessionId or sessionFile
POST /api/chat/model web/app/src/routes/api/chat/model.ts handleChatModelPost session.setModel({provider, id})
GET /api/chat/session web/app/src/routes/api/chat/session.ts handleChatSessionGet One session plus its messages
GET /api/chat/sessions web/app/src/routes/api/chat/sessions.ts handleChatSessionsGet Session picker list (?cwd= optional)
GET /api/chat/models web/app/src/routes/api/chat/models.ts handleChatModelsGet Model registry (`?scope=enabled
POST /api/chat/models/discover web/app/src/routes/api/chat/models/discover.ts handleChatModelsDiscoverPost Probe an OpenAI-compatible base URL /v1/models
GET /api/chat/settings web/app/src/routes/api/chat/settings.ts handleChatSettingsGet Resolved settings
PATCH /api/chat/settings web/app/src/routes/api/chat/settings.ts handleChatSettingsPatch Persist settings via SettingsManager
GET /api/chat/providers web/app/src/routes/api/chat/providers.ts handleChatProvidersGet Provider catalog plus credentials
POST /api/chat/providers web/app/src/routes/api/chat/providers.ts handleChatProvidersPost Store a provider API key
DELETE /api/chat/providers web/app/src/routes/api/chat/providers.ts handleChatProvidersDelete Remove a provider credential
POST /api/chat/providers/oauth web/app/src/routes/api/chat/providers/oauth.ts handleChatProvidersOAuth Start/poll/continue/cancel an interactive OAuth login
GET /api/chat/resources web/app/src/routes/api/chat/resources.ts handleChatResourcesGet Skills, prompts, extensions, themes
GET /api/chat/commands web/app/src/routes/api/chat/commands.ts handleChatCommandsGet Slash command autocomplete
POST /api/chat/command web/app/src/routes/api/chat/command.ts handleChatCommandPost Run a slash command on a session
GET /api/chat/events web/app/src/routes/api/chat/events.ts handleChatEventsGet SSE stream with ring-buffer replay
GET /api/workspace/tree web/app/src/routes/api/workspace/tree.ts handleWorkspaceTreeGet Workspace file tree
GET /api/workspace/file web/app/src/routes/api/workspace/file.ts handleWorkspaceFileGet File preview
GET /api/workspace/browse web/app/src/routes/api/workspace/browse.ts handleWorkspaceBrowseGet Directory picker
POST /api/workspace/root web/app/src/routes/api/workspace/root.ts handleWorkspaceRootPost Rebind the default cwd
GET /api/health web/app/src/routes/api/health.ts handleHealthGet Liveness plus kernel readiness

Request and response shapes

The wire types are defined in web/protocol/src/chat-protocol.ts and validated by zod in web/protocol/src/chat-protocol.zod.ts (ChatRequestSchema, ChatStreamEventSchema, ChatQuestionAnswerRequestSchema, the workspace schemas, and so on).

ChatRequest

Body of POST /api/chat. It extends ChatSessionMetadata (one of sessionId/sessionFile, plus optional cwd). Optional fields: message, model (ChatModelSelection, either a string key or {provider, id, thinkingLevel?}), mode, planAction, streamingBehavior, userId, and userEmail.

userId and userEmail may appear on the wire for OpenAPI documentation, but client-supplied values are stripped after validation; the server sets them only from the authenticated session (see the post-chat handler). Do not treat them as client-controllable identity.

ChatStreamEvent

A single NDJSON frame on the turn stream, discriminated by type. A turn begins with start, then a mix of delta/tool/thinking content and plan/state/queue lifecycle signals, optional compaction/retry progress, and ends with done (success) or error. Validated by ChatStreamEventSchema.

Frame type Shape
start {type, id, runId, sessionId, sessionFile?, sessionReset?, diagnostics?}
delta {type, text, messageId?}
tool {type, part, messageId?} (a ChatToolPart)
thinking {type, text, messageId?}
plan {type, mode, executing, completed, total, state, message?}
state {type, state} (a ChatStateEvent, e.g. agent_start/agent_end)
queue {type, steering, followUp}
compaction `{type, phase: "start"
retry `{type, phase: "start"
done {type, runId, message, sessionId, sessionFile?, sessionReset?}
error {type, message, runId?}

ChatSessionMetadata

Identifies the target session. At least one of sessionFile/sessionId is typically provided to continue an existing session; omitting both starts a new one. Includes an optional cwd.

Health response

GET /api/health returns { ok: true, kernel, uptimeMs }, where kernel is { ok: boolean, reason?: string } from PrimeBridge.kernelReadyState(). The client hook web/app/src/lib/pi/use-kernel-health.ts polls this endpoint (default 15 s) to drive the kernel status chip.

NDJSON framing for POST /api/chat

handleChatPost (web/server/src/handlers/chat.ts) validates the body with ChatRequestSchema, resolves the session, then returns a ReadableStream with Content-Type: application/x-ndjson; charset=utf-8. Each frame is a single JSON object followed by a newline:

  • The handler writes a leading start frame, then subscribes to the bridge and forwards every matching session frame.
  • The stream closes after a done or error frame.
  • The response headers disable caching (Cache-Control: no-cache, no-store) and set X-Accel-Buffering: no.

SSE semantics for GET /api/chat/events

handleChatEventsGet (web/server/src/handlers/chat-events.ts) returns a text/event-stream response for out-of-turn pushes for a session. The client passes the session in ?sessionId= and an optional Last-Event-ID header (or ?lastEventId=) to resume replay.

  • On connect the server writes a synthetic { type: "connected", sessionId } frame.
  • Events carry an id equal to the ring-buffer sequence number; the frame is event: message with the ChatStreamEvent as data.
  • Ring-buffer replay: with a nonzero Last-Event-ID, RingBuffer.replaySince returns every retained frame with a higher sequence. If the client is behind the oldest retained frame, the buffer reports overflow and the server emits a state frame with name: "agent_settled" and message: "resync-required", telling the UI to fall back to GET /api/chat/session.
  • For first-time clients (Last-Event-ID absent), only still-pending tool-question frames are replayed (web/server/src/sse-replay.ts).
  • A heartbeat comment is sent every 15 s to keep the connection alive.
  • Headers: Content-Type: text/event-stream; charset=utf-8, Cache-Control: no-cache, no-store, Connection: keep-alive, X-Accel-Buffering: no.

The turn stream (POST /api/chat) remains authoritative during an active turn; the SSE handler skips frames while the session is streaming/submitted. Out-of-turn pushes such as tool-Question requests, state frames for notify/setStatus, and agent messages are applied through the same reducer.

Validation and trust

All request bodies pass through zod schemas in web/protocol/src/chat-protocol.zod.ts before handlers act on them. Schemas are organized per-domain under web/protocol/src/schemas/ (chat, catalog, settings, shared, misc) and registered with zod-to-openapi for documentation. userId/userEmail are server-set only; they are stripped from client input after validation.

Related pages

Clone this wiki locally