mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
54ebb24374
The persona resolved at creation is snapshotted into workstream_config (five keys, all-or-none) and applied ONLY from the stamp — the personas table is never read post-create, so edits/archives never touch existing workstreams, and a corrupt stamp fails construction loudly instead of silently reverting to a default envelope. Legacy pre-063 workstreams carry no keys and keep today's behavior byte-for-byte. The four levers (turnstone/core/personas.py holds the codec): 1. Base override — compose_system_message(base_override=...) replaces exactly the BASE module; ENV/CONTEXT/TOOLS/POLICIES keep composing so mandatory prompt policies ride on top of every persona. This also closes the old /creative hole where the fork bypassed composition (no CONTEXT, no DB policies). 2. Tool visibility — the allowlist intersects both the composition name set (TOOLS block self-suppresses, tool-gated policies drop, the memory advisory drops) and the END of _get_active_tools so the wire never advertises hidden tools. tool_search in the set = soft (discovered tools union with the allowlist via the session's expanded-names set); absent = hard (the whole pathway is disabled, covering provider-native defer_loading, which has no synthetic name to filter). Persona sets force client-side tool search. 3. MCP gate (session-wide) — an MCP-off persona drops the client reference at construction: no merge into _tools OR _task_tools, no listeners, refresh callbacks inert, resource/prompt catalogs gone. 4. Memory (own hands only) — no recall injection, memory-directed nudges suppressed (MEMORY_NUDGE_TYPES; behavioural nudges keep firing), memory tool hidden. _task_tools is NOT filtered; compaction spill/markers are never persona-gated, and the post-compaction recall pointer is emitted only when the recall tool is actually visible. Threading: the create handler resolves once (explicit name -> 400 on unknown/disabled/kind-mismatch; empty -> the kind's default; pre-seed DB -> unstamped legacy) and stamps via constructor kwargs + config keys + the workstreams.persona column; SessionManager.open threads the stamp pre-construction exactly like the saved model alias. Non-fork resume adopts the target's stamp so _save_config can't clobber it. spawn / spawn_batch gain a persona arg with prep-time validation (children are interactive-kind; omitted = kind default, never the parent's). Python + TS SDKs, OpenAPI specs, the picker feed GET /v1/api/personas (authed, no perm), and console admin CRUD /api/admin/personas (persona.* perms, archive-only — no DELETE) round out the surface. BREAKING: /creative is removed (the REPL command now points at the writer persona); turnstone --persona <name> is the replacement. Also fixes the CLI session factory, which TypeErrored on the project_id kwarg the shared InteractiveAdapter passes unconditionally.
3923 lines
111 KiB
JSON
3923 lines
111 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "turnstone Server API",
|
|
"version": "1.7.0a6",
|
|
"description": "Single-node workstream management, chat interaction, and real-time streaming."
|
|
},
|
|
"paths": {
|
|
"/v1/api/workstreams": {
|
|
"get": {
|
|
"summary": "List active workstreams",
|
|
"operationId": "v1_api_workstreams_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListWorkstreamsResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/dashboard": {
|
|
"get": {
|
|
"summary": "Dashboard with workstream details and aggregates",
|
|
"operationId": "v1_api_dashboard_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DashboardResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/new": {
|
|
"post": {
|
|
"summary": "Create a new workstream",
|
|
"operationId": "v1_api_workstreams_new_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"description": "Accepts two content types. Default is `application/json` with a `CreateWorkstreamRequest` body. Alternatively, `multipart/form-data` with one `meta` field (JSON-encoded `CreateWorkstreamRequest` shape) plus zero-or-more `file` parts saves each file as an attachment under the new workstream. When `initial_message` is also set, attachments are resolved onto that turn before the worker thread dispatches; otherwise they remain pending for a follow-up `POST /v1/api/workstreams/{ws_id}/send`.",
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateWorkstreamRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CreateWorkstreamResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Error 409",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "Error 413",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/close": {
|
|
"post": {
|
|
"summary": "Close a workstream",
|
|
"operationId": "v1_api_workstreams_{ws_id}_close_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CloseWorkstreamRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/send": {
|
|
"post": {
|
|
"summary": "Send a user message",
|
|
"operationId": "v1_api_workstreams_{ws_id}_send_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SendRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SendResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"summary": "Cancel a queued message",
|
|
"operationId": "v1_api_workstreams_{ws_id}_send_delete",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"description": "Removes a previously-queued message from the workstream's pending queue. Returns ``status: removed`` when the queue had the entry, ``status: not_found`` otherwise.",
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DequeueRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/approve": {
|
|
"post": {
|
|
"summary": "Approve or deny a tool call",
|
|
"operationId": "v1_api_workstreams_{ws_id}_approve_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ApproveRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/command": {
|
|
"post": {
|
|
"summary": "Execute a slash command",
|
|
"operationId": "v1_api_command_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CommandRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/cancel": {
|
|
"post": {
|
|
"summary": "Cancel the active generation in a workstream",
|
|
"operationId": "v1_api_workstreams_{ws_id}_cancel_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/CancelRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/rewind": {
|
|
"post": {
|
|
"summary": "Drop the last N conversation turns (emits clear_ui)",
|
|
"operationId": "v1_api_workstreams_{ws_id}_rewind_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/RewindRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/retry": {
|
|
"post": {
|
|
"summary": "Drop the last response and re-send the last user message",
|
|
"operationId": "v1_api_workstreams_{ws_id}_retry_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/events": {
|
|
"get": {
|
|
"summary": "Per-workstream SSE event stream",
|
|
"operationId": "v1_api_workstreams_{ws_id}_events_get",
|
|
"tags": [
|
|
"Streaming"
|
|
],
|
|
"description": "Opens a Server-Sent Events stream scoped to a single workstream. Returns text/event-stream. See API reference for event types.",
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/events/global": {
|
|
"get": {
|
|
"summary": "Global SSE event stream",
|
|
"operationId": "v1_api_events_global_get",
|
|
"tags": [
|
|
"Streaming"
|
|
],
|
|
"description": "Server-Sent Events stream for node-level state broadcasts. Emits a node_snapshot event on connect (workstreams, health, aggregate), followed by real-time delta events (ws_state, ws_activity, ws_created, ws_closed, ws_rename, health_changed, aggregate). Pass ?expected_node_id=X for identity verification (returns 409 on mismatch).",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/delete": {
|
|
"post": {
|
|
"summary": "Permanently delete a saved workstream",
|
|
"operationId": "v1_api_workstreams_{ws_id}_delete_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Error 500",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/open": {
|
|
"post": {
|
|
"summary": "Load a saved workstream into memory",
|
|
"operationId": "v1_api_workstreams_{ws_id}_open_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Error 500",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/title": {
|
|
"post": {
|
|
"summary": "Set workstream title manually",
|
|
"operationId": "v1_api_workstreams_{ws_id}_title_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Error 409",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/refresh-title": {
|
|
"post": {
|
|
"summary": "Regenerate workstream title via LLM",
|
|
"operationId": "v1_api_workstreams_{ws_id}_refresh-title_post",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}": {
|
|
"get": {
|
|
"summary": "Get workstream detail (rehydrates lazily on miss)",
|
|
"operationId": "v1_api_workstreams_{ws_id}_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"description": "Returns the persisted workstream's display fields. If the session isn't currently in memory the manager rehydrates it before responding; ``500`` on rehydrate failure carries a correlation id matching the server log line. Lifted from the coord-only surface in the Stage 2 history/detail verb lift \u2014 interactive previously had no detail endpoint.",
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WorkstreamDetailResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Error 500",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/history": {
|
|
"get": {
|
|
"summary": "Read the workstream's reconstructed message history",
|
|
"operationId": "v1_api_workstreams_{ws_id}_history_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"description": "Returns the tail of the conversation in OpenAI-like message format. Persisted-but-not-loaded workstreams (closed / evicted) serve history without rehydrating. Lifted from the coord-only surface in the Stage 2 history/detail verb lift \u2014 interactive previously only exposed history through the SSE replay on ``/events``.",
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"default": 100
|
|
},
|
|
"description": "Max conversation rows to fetch from storage (default 100, max 500)."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WorkstreamHistoryResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Error 500",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/export": {
|
|
"get": {
|
|
"summary": "Export the workstream's conversation as OpenAI messages JSON",
|
|
"operationId": "v1_api_workstreams_{ws_id}_export_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"description": "Returns the full conversation as an ``{\"messages\": [...]}`` OpenAI Chat Completions envelope, served as a ``<ws_id>.json`` file download (``Content-Disposition: attachment``). Persisted reasoning is surfaced on assistant messages as a ``reasoning_content`` field. Conversation-only \u2014 the parent + per-child zip bundle is exposed only through the ``turnstone-admin export --children`` CLI.",
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Error 500",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/attachments": {
|
|
"post": {
|
|
"summary": "Upload a file (multipart/form-data, field 'file') and attach it to the caller's next user turn on this workstream. Validates size, MIME, and UTF-8 for text; magic-byte sniff for images. Ownership failures are masked as 404 so non-owners cannot enumerate workstream existence; a 403 indicates a scope/auth failure from the middleware layer.",
|
|
"operationId": "v1_api_workstreams_{ws_id}_attachments_post",
|
|
"tags": [
|
|
"Attachments"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UploadAttachmentResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Error 403",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Error 409",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "Error 413",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"get": {
|
|
"summary": "List the caller's pending (unconsumed) attachments for this workstream. Ownership failures are masked as 404.",
|
|
"operationId": "v1_api_workstreams_{ws_id}_attachments_get",
|
|
"tags": [
|
|
"Attachments"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListAttachmentsResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Error 403",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/attachments/{attachment_id}/content": {
|
|
"get": {
|
|
"summary": "Return raw bytes of an attachment with its stored Content-Type. Ownership failures are masked as 404.",
|
|
"operationId": "v1_api_workstreams_{ws_id}_attachments_{attachment_id}_content_get",
|
|
"tags": [
|
|
"Attachments"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "attachment_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"403": {
|
|
"description": "Error 403",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/attachments/{attachment_id}": {
|
|
"delete": {
|
|
"summary": "Remove a pending attachment (consumed attachments return 404). Ownership failures are also masked as 404.",
|
|
"operationId": "v1_api_workstreams_{ws_id}_attachments_{attachment_id}_delete",
|
|
"tags": [
|
|
"Attachments"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "attachment_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"403": {
|
|
"description": "Error 403",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/{ws_id}/speech-to-text": {
|
|
"post": {
|
|
"summary": "Transcribe a short audio clip (multipart/form-data, field 'audio') using the configured STT model role. Returns the transcript for the client to place into the composer; this endpoint never sends on the user's behalf. Returns 503 when no STT role is configured.",
|
|
"operationId": "v1_api_workstreams_{ws_id}_speech-to-text_post",
|
|
"tags": [
|
|
"Attachments"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "ws_id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SpeechToTextResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Error 403",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"413": {
|
|
"description": "Error 413",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "Error 502",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/tts": {
|
|
"post": {
|
|
"summary": "Synthesize text to speech audio for browser playback using the configured TTS model role. Returns audio bytes; 503 when no TTS role is configured.",
|
|
"operationId": "v1_api_tts_post",
|
|
"tags": [
|
|
"Chat"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TextToSpeechRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "Error 502",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/saved": {
|
|
"get": {
|
|
"summary": "List saved workstreams",
|
|
"operationId": "v1_api_workstreams_saved_get",
|
|
"tags": [
|
|
"Workstreams"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListSavedWorkstreamsResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/skills": {
|
|
"get": {
|
|
"summary": "List available skills (summary)",
|
|
"operationId": "v1_api_skills_get",
|
|
"tags": [
|
|
"Skills"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListSkillSummaryResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/personas": {
|
|
"get": {
|
|
"summary": "List enabled personas for the workstream-creation picker",
|
|
"operationId": "v1_api_personas_get",
|
|
"tags": [
|
|
"Personas"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListPersonaChoicesResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/models": {
|
|
"get": {
|
|
"summary": "List available model aliases",
|
|
"operationId": "v1_api_models_get",
|
|
"tags": [
|
|
"Models"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListAvailableModelsResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/login": {
|
|
"post": {
|
|
"summary": "Authenticate with a token",
|
|
"operationId": "v1_api_auth_login_post",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthLoginRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthLoginResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Error 401",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/setup": {
|
|
"post": {
|
|
"summary": "Create first admin user",
|
|
"operationId": "v1_api_auth_setup_post",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthSetupRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthSetupResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Error 409",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/status": {
|
|
"get": {
|
|
"summary": "Return auth state",
|
|
"operationId": "v1_api_auth_status_get",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthStatusResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/logout": {
|
|
"post": {
|
|
"summary": "Clear auth cookie",
|
|
"operationId": "v1_api_auth_logout_post",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/oidc/authorize": {
|
|
"get": {
|
|
"summary": "Redirect to OIDC provider for SSO login",
|
|
"operationId": "v1_api_auth_oidc_authorize_get",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"302": {
|
|
"description": "Success"
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/oidc/callback": {
|
|
"get": {
|
|
"summary": "OIDC callback \u2014 validates code, provisions user, sets JWT cookie, redirects to app",
|
|
"operationId": "v1_api_auth_oidc_callback_get",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"302": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/auth/whoami": {
|
|
"get": {
|
|
"summary": "Return authenticated user info and permissions",
|
|
"operationId": "v1_api_auth_whoami_get",
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AuthWhoamiResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Error 401",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/memories": {
|
|
"get": {
|
|
"summary": "List structured memories",
|
|
"operationId": "v1_api_memories_get",
|
|
"tags": [
|
|
"Memories"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "type",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Filter by memory type"
|
|
},
|
|
{
|
|
"name": "scope",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Filter by scope"
|
|
},
|
|
{
|
|
"name": "scope_id",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Filter by scope identifier"
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"default": 100
|
|
},
|
|
"description": "Max results (default 100, max 200)"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListMemoriesResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Save (upsert) a structured memory",
|
|
"operationId": "v1_api_memories_post",
|
|
"tags": [
|
|
"Memories"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SaveMemoryRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MemoryInfo"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/memories/search": {
|
|
"post": {
|
|
"summary": "Search structured memories by query",
|
|
"operationId": "v1_api_memories_search_post",
|
|
"tags": [
|
|
"Memories"
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SearchMemoriesRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ListMemoriesResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/memories/{name}": {
|
|
"delete": {
|
|
"summary": "Delete a structured memory by name and scope",
|
|
"operationId": "v1_api_memories_{name}_delete",
|
|
"tags": [
|
|
"Memories"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "name",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "scope",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Scope (default: global)"
|
|
},
|
|
{
|
|
"name": "scope_id",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Scope identifier"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Error 404",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/admin/settings": {
|
|
"get": {
|
|
"summary": "List interface.* settings with values and sources",
|
|
"operationId": "v1_api_admin_settings_get",
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/admin/settings/{key}": {
|
|
"put": {
|
|
"summary": "Update an interface.* setting",
|
|
"operationId": "v1_api_admin_settings_{key}_put",
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "key",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"summary": "Update an interface.* setting (alias for PUT)",
|
|
"operationId": "v1_api_admin_settings_{key}_post",
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "key",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
},
|
|
"400": {
|
|
"description": "Error 400",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"503": {
|
|
"description": "Error 503",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ErrorResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/health": {
|
|
"get": {
|
|
"summary": "Server health check",
|
|
"operationId": "health_get",
|
|
"tags": [
|
|
"Observability"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/HealthResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {
|
|
"ErrorResponse": {
|
|
"description": "Standard error response body.",
|
|
"properties": {
|
|
"error": {
|
|
"description": "Error message",
|
|
"title": "Error",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"error"
|
|
],
|
|
"title": "ErrorResponse",
|
|
"type": "object"
|
|
},
|
|
"StatusResponse": {
|
|
"description": "Generic success response.",
|
|
"properties": {
|
|
"status": {
|
|
"default": "ok",
|
|
"examples": [
|
|
"ok"
|
|
],
|
|
"title": "Status",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"title": "StatusResponse",
|
|
"type": "object"
|
|
},
|
|
"AuthLoginRequest": {
|
|
"description": "POST /v1/api/auth/login request body.\n\nEither username+password or token must be provided.",
|
|
"properties": {
|
|
"username": {
|
|
"default": "",
|
|
"description": "Login username",
|
|
"title": "Username",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"default": "",
|
|
"description": "Login password",
|
|
"title": "Password",
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"default": "",
|
|
"description": "Legacy: bearer token to authenticate",
|
|
"title": "Token",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"title": "AuthLoginRequest",
|
|
"type": "object"
|
|
},
|
|
"AuthLoginResponse": {
|
|
"description": "POST /v1/api/auth/login success response.",
|
|
"properties": {
|
|
"status": {
|
|
"default": "ok",
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"user_id": {
|
|
"default": "",
|
|
"description": "Authenticated user ID",
|
|
"title": "User Id",
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"description": "Legacy role",
|
|
"examples": [
|
|
"full",
|
|
"read"
|
|
],
|
|
"title": "Role",
|
|
"type": "string"
|
|
},
|
|
"scopes": {
|
|
"default": "",
|
|
"description": "Comma-separated scopes",
|
|
"examples": [
|
|
"read,write,approve"
|
|
],
|
|
"title": "Scopes",
|
|
"type": "string"
|
|
},
|
|
"jwt": {
|
|
"default": "",
|
|
"description": "JWT session token (if JWT auth is configured)",
|
|
"title": "Jwt",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"role"
|
|
],
|
|
"title": "AuthLoginResponse",
|
|
"type": "object"
|
|
},
|
|
"AuthSetupRequest": {
|
|
"description": "POST /v1/api/auth/setup request body.",
|
|
"properties": {
|
|
"username": {
|
|
"description": "Login username (1-64 ASCII characters)",
|
|
"title": "Username",
|
|
"type": "string"
|
|
},
|
|
"display_name": {
|
|
"description": "Display name",
|
|
"title": "Display Name",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"description": "Password (minimum 8 characters)",
|
|
"title": "Password",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"username",
|
|
"display_name",
|
|
"password"
|
|
],
|
|
"title": "AuthSetupRequest",
|
|
"type": "object"
|
|
},
|
|
"AuthSetupResponse": {
|
|
"description": "POST /v1/api/auth/setup success response.",
|
|
"properties": {
|
|
"status": {
|
|
"default": "ok",
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"user_id": {
|
|
"title": "User Id",
|
|
"type": "string"
|
|
},
|
|
"username": {
|
|
"title": "Username",
|
|
"type": "string"
|
|
},
|
|
"role": {
|
|
"default": "full",
|
|
"title": "Role",
|
|
"type": "string"
|
|
},
|
|
"scopes": {
|
|
"default": "approve,read,write",
|
|
"title": "Scopes",
|
|
"type": "string"
|
|
},
|
|
"jwt": {
|
|
"default": "",
|
|
"description": "JWT session token",
|
|
"title": "Jwt",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"user_id",
|
|
"username"
|
|
],
|
|
"title": "AuthSetupResponse",
|
|
"type": "object"
|
|
},
|
|
"AuthStatusResponse": {
|
|
"description": "GET /v1/api/auth/status response.",
|
|
"properties": {
|
|
"auth_enabled": {
|
|
"title": "Auth Enabled",
|
|
"type": "boolean"
|
|
},
|
|
"has_users": {
|
|
"title": "Has Users",
|
|
"type": "boolean"
|
|
},
|
|
"setup_required": {
|
|
"title": "Setup Required",
|
|
"type": "boolean"
|
|
},
|
|
"oidc_enabled": {
|
|
"default": false,
|
|
"title": "Oidc Enabled",
|
|
"type": "boolean"
|
|
},
|
|
"oidc_provider_name": {
|
|
"default": "",
|
|
"title": "Oidc Provider Name",
|
|
"type": "string"
|
|
},
|
|
"password_enabled": {
|
|
"default": true,
|
|
"title": "Password Enabled",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"auth_enabled",
|
|
"has_users",
|
|
"setup_required"
|
|
],
|
|
"title": "AuthStatusResponse",
|
|
"type": "object"
|
|
},
|
|
"SendRequest": {
|
|
"properties": {
|
|
"message": {
|
|
"description": "User message text",
|
|
"title": "Message",
|
|
"type": "string"
|
|
},
|
|
"attachment_ids": {
|
|
"anyOf": [
|
|
{
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Explicit list of attachment ids to inject into this turn. When omitted, any pending attachments for the caller on this workstream are auto-consumed. An empty list disables auto-consumption for this send.",
|
|
"title": "Attachment Ids"
|
|
}
|
|
},
|
|
"required": [
|
|
"message"
|
|
],
|
|
"title": "SendRequest",
|
|
"type": "object"
|
|
},
|
|
"SendResponse": {
|
|
"properties": {
|
|
"status": {
|
|
"description": "'ok', 'busy', 'queued', or 'queue_full'",
|
|
"examples": [
|
|
"ok",
|
|
"busy",
|
|
"queued",
|
|
"queue_full"
|
|
],
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"attached_ids": {
|
|
"description": "Attachment ids actually attached to this turn. Subset of the request's `attachment_ids` (or the auto-consumed pending set). Empty when the send carries no attachments.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Attached Ids",
|
|
"type": "array"
|
|
},
|
|
"dropped_attachment_ids": {
|
|
"description": "Attachment ids the caller requested that the server could not reserve (lost a race, already consumed, or cross-scope). The request still proceeds with whatever was reserved; the client can retry uploads or surface a partial-attach warning.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Dropped Attachment Ids",
|
|
"type": "array"
|
|
},
|
|
"priority": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Set on `queued` responses: relative priority of the queued message.",
|
|
"title": "Priority"
|
|
},
|
|
"msg_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Set on `queued` responses: id used to dequeue the message.",
|
|
"title": "Msg Id"
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"title": "SendResponse",
|
|
"type": "object"
|
|
},
|
|
"DequeueRequest": {
|
|
"description": "Body for ``DELETE /v1/api/workstreams/{ws_id}/send``.\n\nRemoves a previously-queued message from the workstream's pending\nqueue. ``msg_id`` is the id returned in a prior ``send`` response\nwhen the workstream was busy and the message was queued.",
|
|
"properties": {
|
|
"msg_id": {
|
|
"description": "Id of the queued message to remove",
|
|
"title": "Msg Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"msg_id"
|
|
],
|
|
"title": "DequeueRequest",
|
|
"type": "object"
|
|
},
|
|
"ApproveRequest": {
|
|
"properties": {
|
|
"approved": {
|
|
"description": "True to approve, false to deny",
|
|
"title": "Approved",
|
|
"type": "boolean"
|
|
},
|
|
"feedback": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional denial reason",
|
|
"title": "Feedback"
|
|
},
|
|
"always": {
|
|
"default": false,
|
|
"description": "Auto-approve the tools in this batch going forward",
|
|
"title": "Always",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"approved"
|
|
],
|
|
"title": "ApproveRequest",
|
|
"type": "object"
|
|
},
|
|
"CommandRequest": {
|
|
"properties": {
|
|
"command": {
|
|
"description": "Slash command (e.g. /clear, /new, /resume)",
|
|
"title": "Command",
|
|
"type": "string"
|
|
},
|
|
"ws_id": {
|
|
"description": "Target workstream ID",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"command",
|
|
"ws_id"
|
|
],
|
|
"title": "CommandRequest",
|
|
"type": "object"
|
|
},
|
|
"CancelRequest": {
|
|
"properties": {
|
|
"force": {
|
|
"default": false,
|
|
"description": "Force cancel: abandon the stuck worker thread immediately. Use when cooperative cancel has not resolved within a few seconds.",
|
|
"title": "Force",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"title": "CancelRequest",
|
|
"type": "object"
|
|
},
|
|
"RewindRequest": {
|
|
"properties": {
|
|
"turns": {
|
|
"description": "Number of conversation turns (user message + its responses) to drop from the end. Clamped to the available turn count.",
|
|
"minimum": 1,
|
|
"title": "Turns",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"turns"
|
|
],
|
|
"title": "RewindRequest",
|
|
"type": "object"
|
|
},
|
|
"CreateWorkstreamRequest": {
|
|
"properties": {
|
|
"name": {
|
|
"default": "",
|
|
"description": "Workstream display name (auto-generated if empty)",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"model": {
|
|
"default": "",
|
|
"description": "Model alias from registry",
|
|
"title": "Model",
|
|
"type": "string"
|
|
},
|
|
"auto_approve": {
|
|
"default": false,
|
|
"description": "Auto-approve all tool calls",
|
|
"title": "Auto Approve",
|
|
"type": "boolean"
|
|
},
|
|
"resume_ws": {
|
|
"default": "",
|
|
"description": "Workstream ID to resume atomically during creation (empty = fresh start)",
|
|
"title": "Resume Ws",
|
|
"type": "string"
|
|
},
|
|
"skill": {
|
|
"default": "",
|
|
"description": "Skill name (replaces default skills)",
|
|
"title": "Skill",
|
|
"type": "string"
|
|
},
|
|
"persona": {
|
|
"default": "",
|
|
"description": "Persona name (slug) to create the workstream with. Resolved and snapshotted at creation \u2014 later persona edits never affect this workstream. Empty selects the kind's default persona; on a database with no personas seeded the workstream is created with legacy (unrestricted) behavior.",
|
|
"title": "Persona",
|
|
"type": "string"
|
|
},
|
|
"notify_targets": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"items": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
}
|
|
],
|
|
"default": "[]",
|
|
"description": "Notification targets, accepted as either a JSON string or a structured array of objects containing channel_type + channel_id/user_id",
|
|
"title": "Notify Targets"
|
|
},
|
|
"client_type": {
|
|
"default": "",
|
|
"description": "Client surface type (web, cli, chat). Defaults to web for server-created sessions.",
|
|
"title": "Client Type",
|
|
"type": "string"
|
|
},
|
|
"initial_message": {
|
|
"default": "",
|
|
"description": "Optional first user message dispatched as a background turn after the workstream is created. When attachments are also provided (via the multipart variant), they are attached to this turn.",
|
|
"title": "Initial Message",
|
|
"type": "string"
|
|
},
|
|
"ws_id": {
|
|
"default": "",
|
|
"description": "Optional caller-supplied workstream id (32-hex). Required when creating with attachments via the cluster routing layer so the console can hash to the owning node before the multipart body lands. Auto-generated when omitted.",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/WorkstreamKind",
|
|
"default": "interactive",
|
|
"description": "Workstream kind \u2014 'interactive' (default) or 'coordinator'. Coordinator workstreams are created by the console's own /v1/api/workstreams/new endpoint; clients hitting /v1/api/workstreams/new should leave this at the default."
|
|
},
|
|
"parent_ws_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional parent workstream id. Populated on children spawned by a coordinator so the parent/child relationship survives restart and appears in audit / list views.",
|
|
"title": "Parent Ws Id"
|
|
},
|
|
"project_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional project to attach this workstream to. Drives the shared 'project' memory scope; coordinator children inherit the parent's project.",
|
|
"title": "Project Id"
|
|
}
|
|
},
|
|
"title": "CreateWorkstreamRequest",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamKind": {
|
|
"description": "Classifier for which manager hosts a workstream.\n\nStrEnum so members are drop-in ``str`` replacements for the DB column,\nJSON payloads, and existing ``==`` comparisons against raw strings.\nNarrow internal annotations to this type; wide boundaries (HTTP body,\nDB row) stay ``str`` and parse via ``WorkstreamKind(raw)`` / ``from_raw``\nat the edge.",
|
|
"enum": [
|
|
"interactive",
|
|
"coordinator"
|
|
],
|
|
"title": "WorkstreamKind",
|
|
"type": "string"
|
|
},
|
|
"CreateWorkstreamResponse": {
|
|
"properties": {
|
|
"ws_id": {
|
|
"description": "Unique ID of the new workstream",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "Assigned workstream name",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"resumed": {
|
|
"default": false,
|
|
"description": "Whether a previous workstream was resumed",
|
|
"title": "Resumed",
|
|
"type": "boolean"
|
|
},
|
|
"message_count": {
|
|
"default": 0,
|
|
"description": "Number of messages in the resumed workstream",
|
|
"title": "Message Count",
|
|
"type": "integer"
|
|
},
|
|
"attachment_ids": {
|
|
"description": "Ids of attachments saved by this request (multipart variant only). Already attached to the initial_message turn when one was provided; otherwise left pending for a follow-up POST /v1/api/workstreams/{ws_id}/send.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Attachment Ids",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id",
|
|
"name"
|
|
],
|
|
"title": "CreateWorkstreamResponse",
|
|
"type": "object"
|
|
},
|
|
"CloseWorkstreamRequest": {
|
|
"description": "Body for ``POST /v1/api/workstreams/{ws_id}/close``.\n\nThe body must be valid JSON; send ``{}`` when omitting all\nfields. Pre-1.5 the model also carried a body-keyed ``ws_id``;\n1.5 moved that to the path so the body shrinks to the optional\n``reason``. Coord ignores the body entirely (its close handler\nis wired ``supports_close_reason=False``).",
|
|
"properties": {
|
|
"reason": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional close reason persisted to ``workstream_config`` for postmortem. Capped at 512 UTF-8 bytes server-side; credential-redaction is applied via the output guard.",
|
|
"title": "Reason"
|
|
}
|
|
},
|
|
"title": "CloseWorkstreamRequest",
|
|
"type": "object"
|
|
},
|
|
"ListWorkstreamsResponse": {
|
|
"description": "Response body for ``GET /v1/api/workstreams`` on either kind.\n\nTop-level key is ``workstreams`` regardless of the kind serving\nthe request \u2014 pre-lift coord returned ``{\"coordinators\": [...]}``;\nconvergence lifted both kinds onto the same shape. Coord SDK /\nfrontend consumers branching on ``data.coordinators`` swap to\n``data.workstreams``.",
|
|
"properties": {
|
|
"workstreams": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/WorkstreamInfo"
|
|
},
|
|
"title": "Workstreams",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"workstreams"
|
|
],
|
|
"title": "ListWorkstreamsResponse",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamInfo": {
|
|
"description": "Active-list row shape, shared across both kinds.\n\nRenamed ``id`` \u2192 ``ws_id`` and added ``user_id`` in the Stage 2\n``list``/``saved`` verb lift so the active-list response shape\nmatches the rest of the v1 surface (every other shared verb's\npayload uses ``ws_id``). ``user_id`` was previously coord-only;\ninteractive now populates it too. SDK consumers reading\n``row.id`` should swap to ``row.ws_id``.",
|
|
"properties": {
|
|
"ws_id": {
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"state": {
|
|
"title": "State",
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/WorkstreamKind",
|
|
"default": "interactive"
|
|
},
|
|
"parent_ws_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Parent Ws Id"
|
|
},
|
|
"user_id": {
|
|
"default": "",
|
|
"title": "User Id",
|
|
"type": "string"
|
|
},
|
|
"project_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Project Id"
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id",
|
|
"name",
|
|
"state"
|
|
],
|
|
"title": "WorkstreamInfo",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamDetailResponse": {
|
|
"description": "Response body for ``GET /v1/api/workstreams/{ws_id}``.\n\nRenamed and relocated from ``CoordinatorDetailResponse`` in the\nStage 2 history/detail verb lift. Both kinds populate every field;\nSDK consumers don't branch on kind to read them. The lift adds the\nendpoint to interactive as a feature gain (pre-lift only coord\nexposed it).",
|
|
"properties": {
|
|
"ws_id": {
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"state": {
|
|
"title": "State",
|
|
"type": "string"
|
|
},
|
|
"user_id": {
|
|
"title": "User Id",
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/WorkstreamKind",
|
|
"default": "interactive"
|
|
},
|
|
"pending_approval": {
|
|
"default": false,
|
|
"description": "True when the workstream is parked on ``_approval_event`` awaiting an operator approve/deny. Mirrors the same field on ``DashboardWorkstream`` / cluster live projections so a freshly-loaded chat tab can render the inline approval gate from the detail snapshot before SSE replay arrives.",
|
|
"title": "Pending Approval",
|
|
"type": "boolean"
|
|
},
|
|
"pending_approval_detail": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/PendingApprovalDetail"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Inline approval payload \u2014 same shape as ``DashboardWorkstream.pending_approval_detail``. ``None`` when no approval is pending. Lets a reload paint the action row + judge verdicts immediately instead of relying on the SSE approve_request replay timing window."
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id",
|
|
"name",
|
|
"state",
|
|
"user_id"
|
|
],
|
|
"title": "WorkstreamDetailResponse",
|
|
"type": "object"
|
|
},
|
|
"PendingApprovalDetail": {
|
|
"description": "Inline approval payload merged into ``DashboardWorkstream``.\n\nSet when a workstream's ``approve_tools`` is parked on\n``_approval_event``; ``None`` (omitted) otherwise. Cross-tenant\nexposure here follows the same trusted-team posture as\n``activity`` / ``tokens`` \u2014 see ``server.py``'s ``dashboard``\nhandler comment.",
|
|
"properties": {
|
|
"call_id": {
|
|
"default": "",
|
|
"description": "Primary call_id \u2014 first non-empty call_id in items list order. Matches the 409 ``current_call_id`` response from ``POST /v1/api/workstreams/{ws_id}/approve`` so the UI can render the same identifier the server reports as current.",
|
|
"title": "Call Id",
|
|
"type": "string"
|
|
},
|
|
"judge_pending": {
|
|
"default": false,
|
|
"description": "LLM judge tier still running; heuristic verdicts may already be present on items.",
|
|
"title": "Judge Pending",
|
|
"type": "boolean"
|
|
},
|
|
"items": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/PendingApprovalItem"
|
|
},
|
|
"title": "Items",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"title": "PendingApprovalDetail",
|
|
"type": "object"
|
|
},
|
|
"PendingApprovalItem": {
|
|
"description": "One pending tool-call inside a ``PendingApprovalDetail`` envelope.\n\nMirrors the dict ``SessionUIBase.serialize_pending_approval_detail``\nemits per item. ``heuristic_verdict`` / ``judge_verdict`` are kept\nloosely-typed because the underlying verdict shape varies by tier;\nconsumers that want the full structure can decode against\n:class:`turnstone.sdk.events.IntentVerdictEvent`.",
|
|
"properties": {
|
|
"call_id": {
|
|
"default": "",
|
|
"title": "Call Id",
|
|
"type": "string"
|
|
},
|
|
"header": {
|
|
"default": "",
|
|
"title": "Header",
|
|
"type": "string"
|
|
},
|
|
"preview": {
|
|
"default": "",
|
|
"title": "Preview",
|
|
"type": "string"
|
|
},
|
|
"func_name": {
|
|
"default": "",
|
|
"title": "Func Name",
|
|
"type": "string"
|
|
},
|
|
"approval_label": {
|
|
"default": "",
|
|
"title": "Approval Label",
|
|
"type": "string"
|
|
},
|
|
"needs_approval": {
|
|
"default": false,
|
|
"title": "Needs Approval",
|
|
"type": "boolean"
|
|
},
|
|
"error": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Error"
|
|
},
|
|
"heuristic_verdict": {
|
|
"anyOf": [
|
|
{
|
|
"additionalProperties": true,
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Heuristic Verdict"
|
|
},
|
|
"judge_verdict": {
|
|
"anyOf": [
|
|
{
|
|
"additionalProperties": true,
|
|
"type": "object"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Judge Verdict"
|
|
}
|
|
},
|
|
"title": "PendingApprovalItem",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamHistoryResponse": {
|
|
"description": "Response body for ``GET /v1/api/workstreams/{ws_id}/history``.\n\nRenamed and relocated from ``CoordinatorHistoryResponse`` in the\nStage 2 history/detail verb lift. Same projected render shape on\nboth kinds; the lift adds the endpoint to interactive as a feature\ngain (pre-lift interactive only exposed history through the SSE\nreplay on ``/events``).",
|
|
"properties": {
|
|
"ws_id": {
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"messages": {
|
|
"description": "Tail of the workstream's message history, projected to the canonical render shape (``role`` may be ``system`` for operator-context turns; flat tool_calls with verdict / output_assessment; top-level source / attachments / reasoning; derived denied / is_error / pending). Bounded by the ``limit`` query parameter (default 100, max 500).",
|
|
"items": {
|
|
"additionalProperties": true,
|
|
"type": "object"
|
|
},
|
|
"title": "Messages",
|
|
"type": "array"
|
|
},
|
|
"cursor": {
|
|
"anyOf": [
|
|
{
|
|
"type": "integer"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "SSE resume cursor (a ``Last-Event-ID`` value). Non-null only when the trailing turn is an executing in-flight tool batch that the live ring buffer can replay: ``messages`` then omits that turn and the client opens its initial SSE with this cursor so the existing delta replay fast-forwards the in-flight turn (tool calls, results, prompts) instead of the lossy synthetic snapshot. Null on every other read \u2014 the client connects fresh.",
|
|
"title": "Cursor"
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id"
|
|
],
|
|
"title": "WorkstreamHistoryResponse",
|
|
"type": "object"
|
|
},
|
|
"DashboardResponse": {
|
|
"properties": {
|
|
"workstreams": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/DashboardWorkstream"
|
|
},
|
|
"title": "Workstreams",
|
|
"type": "array"
|
|
},
|
|
"aggregate": {
|
|
"$ref": "#/components/schemas/DashboardAggregate"
|
|
}
|
|
},
|
|
"required": [
|
|
"workstreams",
|
|
"aggregate"
|
|
],
|
|
"title": "DashboardResponse",
|
|
"type": "object"
|
|
},
|
|
"DashboardAggregate": {
|
|
"properties": {
|
|
"total_tokens": {
|
|
"default": 0,
|
|
"title": "Total Tokens",
|
|
"type": "integer"
|
|
},
|
|
"total_tool_calls": {
|
|
"default": 0,
|
|
"title": "Total Tool Calls",
|
|
"type": "integer"
|
|
},
|
|
"active_count": {
|
|
"default": 0,
|
|
"title": "Active Count",
|
|
"type": "integer"
|
|
},
|
|
"total_count": {
|
|
"default": 0,
|
|
"title": "Total Count",
|
|
"type": "integer"
|
|
},
|
|
"uptime_seconds": {
|
|
"default": 0,
|
|
"title": "Uptime Seconds",
|
|
"type": "integer"
|
|
},
|
|
"node": {
|
|
"default": "local",
|
|
"title": "Node",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"title": "DashboardAggregate",
|
|
"type": "object"
|
|
},
|
|
"DashboardWorkstream": {
|
|
"description": "Dashboard row shape for ``GET /v1/api/dashboard``.\n\nRenamed ``id`` \u2192 ``ws_id`` for v1 row-shape consistency with\nthe rest of the workstream surface (active list, saved list,\nhistory, detail, etc.). Frontend consumers reading\n``dashboard.workstreams[].id`` swap to ``.ws_id``.",
|
|
"properties": {
|
|
"ws_id": {
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"state": {
|
|
"title": "State",
|
|
"type": "string"
|
|
},
|
|
"title": {
|
|
"default": "",
|
|
"title": "Title",
|
|
"type": "string"
|
|
},
|
|
"tokens": {
|
|
"default": 0,
|
|
"title": "Tokens",
|
|
"type": "integer"
|
|
},
|
|
"context_ratio": {
|
|
"default": 0.0,
|
|
"title": "Context Ratio",
|
|
"type": "number"
|
|
},
|
|
"activity": {
|
|
"default": "",
|
|
"title": "Activity",
|
|
"type": "string"
|
|
},
|
|
"activity_state": {
|
|
"default": "",
|
|
"title": "Activity State",
|
|
"type": "string"
|
|
},
|
|
"tool_calls": {
|
|
"default": 0,
|
|
"title": "Tool Calls",
|
|
"type": "integer"
|
|
},
|
|
"node": {
|
|
"default": "",
|
|
"title": "Node",
|
|
"type": "string"
|
|
},
|
|
"model": {
|
|
"default": "",
|
|
"title": "Model",
|
|
"type": "string"
|
|
},
|
|
"model_alias": {
|
|
"default": "",
|
|
"title": "Model Alias",
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/WorkstreamKind",
|
|
"default": "interactive"
|
|
},
|
|
"parent_ws_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Parent Ws Id"
|
|
},
|
|
"user_id": {
|
|
"default": "",
|
|
"title": "User Id",
|
|
"type": "string"
|
|
},
|
|
"project_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Project Id"
|
|
},
|
|
"pending_approval_detail": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/PendingApprovalDetail"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Inline approval payload for the coordinator children-tree UI. Carries the merged ``_pending_approval`` items list + per-call_id LLM verdict cache so a coord can render approve/deny buttons + judge pill without a separate per-child round-trip. ``None`` when no approval is pending. Also surfaced (verbatim) on ``GET /v1/api/cluster/ws/live`` via the ``_CLUSTER_WS_LIVE_KEYS`` projection."
|
|
},
|
|
"recent_auto_approvals": {
|
|
"description": "Per-ws ring buffer (cap 10) of recent tool calls that bypassed the operator approval gate. Surfaces ``WebUI._recent_auto_approvals`` so the coord-tree row can render an 'auto-approved by ...' pill when the child's skill / blanket / admin-policy rules silently let a tool through. Also projected onto ``GET /v1/api/cluster/ws/live`` via ``_CLUSTER_WS_LIVE_KEYS``.",
|
|
"items": {
|
|
"$ref": "#/components/schemas/RecentAutoApproval"
|
|
},
|
|
"title": "Recent Auto Approvals",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id",
|
|
"name",
|
|
"state"
|
|
],
|
|
"title": "DashboardWorkstream",
|
|
"type": "object"
|
|
},
|
|
"RecentAutoApproval": {
|
|
"description": "One ring-buffer entry for ``DashboardWorkstream.recent_auto_approvals``.\n\nRecords a tool call that bypassed the operator approval gate\n(admin tool policy / skill ``allowed_tools`` allowlist / blanket\n``auto_approve`` / \"Approve + Always\" memory). The coord-tree\npill reads this list to surface \"auto-approved by skill X\" so\nthe operator can see WHICH calls bypassed and WHY.",
|
|
"properties": {
|
|
"call_id": {
|
|
"default": "",
|
|
"title": "Call Id",
|
|
"type": "string"
|
|
},
|
|
"func_name": {
|
|
"default": "",
|
|
"title": "Func Name",
|
|
"type": "string"
|
|
},
|
|
"approval_label": {
|
|
"default": "",
|
|
"title": "Approval Label",
|
|
"type": "string"
|
|
},
|
|
"auto_approve_reason": {
|
|
"default": "",
|
|
"description": "Source that fired the bypass. ``skill`` (skill template's ``allowed_tools``), ``always`` (user 'Approve + Always' click), ``policy`` (admin tool-policy ``allow`` rule), ``blanket`` (workstream-level ``auto_approve=True``), ``smart_approval`` (Smart Approvals: high-confidence LLM judge ``approve`` verdict), or ``auto_approve_tools`` (legacy / unknown writer).",
|
|
"title": "Auto Approve Reason",
|
|
"type": "string"
|
|
},
|
|
"ts": {
|
|
"default": 0.0,
|
|
"description": "Unix epoch seconds when the auto-approve fired.",
|
|
"title": "Ts",
|
|
"type": "number"
|
|
}
|
|
},
|
|
"title": "RecentAutoApproval",
|
|
"type": "object"
|
|
},
|
|
"ListSavedWorkstreamsResponse": {
|
|
"properties": {
|
|
"workstreams": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SavedWorkstreamInfo"
|
|
},
|
|
"title": "Workstreams",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"workstreams"
|
|
],
|
|
"title": "ListSavedWorkstreamsResponse",
|
|
"type": "object"
|
|
},
|
|
"SavedWorkstreamInfo": {
|
|
"properties": {
|
|
"ws_id": {
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
},
|
|
"alias": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Alias"
|
|
},
|
|
"title": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Title"
|
|
},
|
|
"created": {
|
|
"title": "Created",
|
|
"type": "string"
|
|
},
|
|
"updated": {
|
|
"title": "Updated",
|
|
"type": "string"
|
|
},
|
|
"message_count": {
|
|
"title": "Message Count",
|
|
"type": "integer"
|
|
},
|
|
"state": {
|
|
"default": "idle",
|
|
"title": "State",
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"$ref": "#/components/schemas/WorkstreamKind",
|
|
"default": "interactive"
|
|
},
|
|
"node_id": {
|
|
"default": "",
|
|
"title": "Node Id",
|
|
"type": "string"
|
|
},
|
|
"model_alias": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Model Alias"
|
|
},
|
|
"launch_skill": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Launch Skill"
|
|
},
|
|
"child_count": {
|
|
"default": 0,
|
|
"title": "Child Count",
|
|
"type": "integer"
|
|
},
|
|
"context_tokens": {
|
|
"default": 0,
|
|
"title": "Context Tokens",
|
|
"type": "integer"
|
|
},
|
|
"context_ratio": {
|
|
"default": 0.0,
|
|
"title": "Context Ratio",
|
|
"type": "number"
|
|
},
|
|
"project_id": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Project Id"
|
|
},
|
|
"persona": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"title": "Persona"
|
|
}
|
|
},
|
|
"required": [
|
|
"ws_id",
|
|
"created",
|
|
"updated",
|
|
"message_count"
|
|
],
|
|
"title": "SavedWorkstreamInfo",
|
|
"type": "object"
|
|
},
|
|
"UploadAttachmentResponse": {
|
|
"description": "Returned after a successful upload.",
|
|
"properties": {
|
|
"attachment_id": {
|
|
"description": "Opaque id for this attachment",
|
|
"title": "Attachment Id",
|
|
"type": "string"
|
|
},
|
|
"filename": {
|
|
"description": "Original upload filename",
|
|
"title": "Filename",
|
|
"type": "string"
|
|
},
|
|
"mime_type": {
|
|
"description": "Canonicalized MIME type",
|
|
"title": "Mime Type",
|
|
"type": "string"
|
|
},
|
|
"size_bytes": {
|
|
"description": "Payload size in bytes",
|
|
"title": "Size Bytes",
|
|
"type": "integer"
|
|
},
|
|
"kind": {
|
|
"description": "'image', 'text', 'pdf', or 'audio'",
|
|
"examples": [
|
|
"image",
|
|
"text",
|
|
"pdf",
|
|
"audio"
|
|
],
|
|
"title": "Kind",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"attachment_id",
|
|
"filename",
|
|
"mime_type",
|
|
"size_bytes",
|
|
"kind"
|
|
],
|
|
"title": "UploadAttachmentResponse",
|
|
"type": "object"
|
|
},
|
|
"ListAttachmentsResponse": {
|
|
"properties": {
|
|
"attachments": {
|
|
"description": "Pending (unconsumed) attachments for caller+workstream",
|
|
"items": {
|
|
"$ref": "#/components/schemas/AttachmentInfo"
|
|
},
|
|
"title": "Attachments",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"attachments"
|
|
],
|
|
"title": "ListAttachmentsResponse",
|
|
"type": "object"
|
|
},
|
|
"AttachmentInfo": {
|
|
"properties": {
|
|
"attachment_id": {
|
|
"description": "Opaque id for this attachment",
|
|
"title": "Attachment Id",
|
|
"type": "string"
|
|
},
|
|
"filename": {
|
|
"description": "Original upload filename",
|
|
"title": "Filename",
|
|
"type": "string"
|
|
},
|
|
"mime_type": {
|
|
"description": "Canonicalized MIME type",
|
|
"title": "Mime Type",
|
|
"type": "string"
|
|
},
|
|
"size_bytes": {
|
|
"description": "Payload size in bytes",
|
|
"title": "Size Bytes",
|
|
"type": "integer"
|
|
},
|
|
"kind": {
|
|
"description": "'image', 'text', 'pdf', or 'audio'",
|
|
"examples": [
|
|
"image",
|
|
"text",
|
|
"pdf",
|
|
"audio"
|
|
],
|
|
"title": "Kind",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"attachment_id",
|
|
"filename",
|
|
"mime_type",
|
|
"size_bytes",
|
|
"kind"
|
|
],
|
|
"title": "AttachmentInfo",
|
|
"type": "object"
|
|
},
|
|
"SpeechToTextResponse": {
|
|
"description": "Transcript returned for the browser to place into the composer.",
|
|
"properties": {
|
|
"status": {
|
|
"default": "ok",
|
|
"description": "Request outcome",
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"transcript": {
|
|
"description": "Transcribed text",
|
|
"title": "Transcript",
|
|
"type": "string"
|
|
},
|
|
"model_alias": {
|
|
"default": "",
|
|
"description": "STT role alias used",
|
|
"title": "Model Alias",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"transcript"
|
|
],
|
|
"title": "SpeechToTextResponse",
|
|
"type": "object"
|
|
},
|
|
"TextToSpeechRequest": {
|
|
"properties": {
|
|
"text": {
|
|
"description": "Text to synthesize",
|
|
"title": "Text",
|
|
"type": "string"
|
|
},
|
|
"voice": {
|
|
"default": "",
|
|
"description": "Optional voice override (else audio.tts_voice setting)",
|
|
"title": "Voice",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"text"
|
|
],
|
|
"title": "TextToSpeechRequest",
|
|
"type": "object"
|
|
},
|
|
"HealthResponse": {
|
|
"properties": {
|
|
"status": {
|
|
"examples": [
|
|
"ok",
|
|
"degraded"
|
|
],
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"version": {
|
|
"default": "",
|
|
"title": "Version",
|
|
"type": "string"
|
|
},
|
|
"node_id": {
|
|
"default": "",
|
|
"title": "Node Id",
|
|
"type": "string"
|
|
},
|
|
"uptime_seconds": {
|
|
"default": 0.0,
|
|
"title": "Uptime Seconds",
|
|
"type": "number"
|
|
},
|
|
"model": {
|
|
"default": "",
|
|
"title": "Model",
|
|
"type": "string"
|
|
},
|
|
"max_ws": {
|
|
"default": 10,
|
|
"description": "Maximum concurrent workstreams",
|
|
"title": "Max Ws",
|
|
"type": "integer"
|
|
},
|
|
"workstreams": {
|
|
"$ref": "#/components/schemas/WorkstreamCounts",
|
|
"default": {
|
|
"total": 0,
|
|
"idle": 0,
|
|
"thinking": 0,
|
|
"running": 0,
|
|
"attention": 0,
|
|
"error": 0
|
|
}
|
|
},
|
|
"backend": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/BackendStatus"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null
|
|
},
|
|
"mcp": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/components/schemas/McpStatus"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"title": "HealthResponse",
|
|
"type": "object"
|
|
},
|
|
"BackendStatus": {
|
|
"properties": {
|
|
"status": {
|
|
"examples": [
|
|
"up",
|
|
"down"
|
|
],
|
|
"title": "Status",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"title": "BackendStatus",
|
|
"type": "object"
|
|
},
|
|
"McpStatus": {
|
|
"properties": {
|
|
"servers": {
|
|
"default": 0,
|
|
"title": "Servers",
|
|
"type": "integer"
|
|
},
|
|
"resources": {
|
|
"default": 0,
|
|
"title": "Resources",
|
|
"type": "integer"
|
|
},
|
|
"prompts": {
|
|
"default": 0,
|
|
"title": "Prompts",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"title": "McpStatus",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamCounts": {
|
|
"properties": {
|
|
"total": {
|
|
"default": 0,
|
|
"title": "Total",
|
|
"type": "integer"
|
|
},
|
|
"idle": {
|
|
"default": 0,
|
|
"title": "Idle",
|
|
"type": "integer"
|
|
},
|
|
"thinking": {
|
|
"default": 0,
|
|
"title": "Thinking",
|
|
"type": "integer"
|
|
},
|
|
"running": {
|
|
"default": 0,
|
|
"title": "Running",
|
|
"type": "integer"
|
|
},
|
|
"attention": {
|
|
"default": 0,
|
|
"title": "Attention",
|
|
"type": "integer"
|
|
},
|
|
"error": {
|
|
"default": 0,
|
|
"title": "Error",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"title": "WorkstreamCounts",
|
|
"type": "object"
|
|
},
|
|
"SaveMemoryRequest": {
|
|
"properties": {
|
|
"name": {
|
|
"description": "Memory identifier (normalized to snake_case)",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"content": {
|
|
"description": "Memory content",
|
|
"maxLength": 65536,
|
|
"title": "Content",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"default": "",
|
|
"description": "Short description for relevance matching",
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"default": "general",
|
|
"description": "Memory type",
|
|
"enum": [
|
|
"user",
|
|
"general",
|
|
"feedback",
|
|
"reference"
|
|
],
|
|
"title": "Type",
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"default": "global",
|
|
"description": "Memory scope",
|
|
"enum": [
|
|
"global",
|
|
"workstream",
|
|
"user"
|
|
],
|
|
"title": "Scope",
|
|
"type": "string"
|
|
},
|
|
"scope_id": {
|
|
"default": "",
|
|
"description": "Scope identifier (ws_id for workstream, user_id for user scope)",
|
|
"title": "Scope Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"name",
|
|
"content"
|
|
],
|
|
"title": "SaveMemoryRequest",
|
|
"type": "object"
|
|
},
|
|
"MemoryInfo": {
|
|
"properties": {
|
|
"memory_id": {
|
|
"title": "Memory Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"default": "",
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"enum": [
|
|
"user",
|
|
"general",
|
|
"feedback",
|
|
"reference"
|
|
],
|
|
"title": "Type",
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"enum": [
|
|
"global",
|
|
"workstream",
|
|
"user"
|
|
],
|
|
"title": "Scope",
|
|
"type": "string"
|
|
},
|
|
"scope_id": {
|
|
"default": "",
|
|
"title": "Scope Id",
|
|
"type": "string"
|
|
},
|
|
"content": {
|
|
"title": "Content",
|
|
"type": "string"
|
|
},
|
|
"created": {
|
|
"title": "Created",
|
|
"type": "string"
|
|
},
|
|
"updated": {
|
|
"title": "Updated",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"memory_id",
|
|
"name",
|
|
"type",
|
|
"scope",
|
|
"content",
|
|
"created",
|
|
"updated"
|
|
],
|
|
"title": "MemoryInfo",
|
|
"type": "object"
|
|
},
|
|
"ListMemoriesResponse": {
|
|
"properties": {
|
|
"memories": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/MemoryInfo"
|
|
},
|
|
"title": "Memories",
|
|
"type": "array"
|
|
},
|
|
"total": {
|
|
"default": 0,
|
|
"title": "Total",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"memories"
|
|
],
|
|
"title": "ListMemoriesResponse",
|
|
"type": "object"
|
|
},
|
|
"SearchMemoriesRequest": {
|
|
"properties": {
|
|
"query": {
|
|
"description": "Search query text",
|
|
"title": "Query",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"default": "",
|
|
"description": "Filter by memory type",
|
|
"enum": [
|
|
"",
|
|
"user",
|
|
"general",
|
|
"feedback",
|
|
"reference"
|
|
],
|
|
"title": "Type",
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"default": "",
|
|
"description": "Filter by scope",
|
|
"enum": [
|
|
"",
|
|
"global",
|
|
"workstream",
|
|
"user"
|
|
],
|
|
"title": "Scope",
|
|
"type": "string"
|
|
},
|
|
"scope_id": {
|
|
"default": "",
|
|
"description": "Filter by scope_id",
|
|
"title": "Scope Id",
|
|
"type": "string"
|
|
},
|
|
"limit": {
|
|
"default": 20,
|
|
"description": "Max results (1-50)",
|
|
"maximum": 50,
|
|
"minimum": 1,
|
|
"title": "Limit",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"query"
|
|
],
|
|
"title": "SearchMemoriesRequest",
|
|
"type": "object"
|
|
},
|
|
"SkillSummary": {
|
|
"properties": {
|
|
"name": {
|
|
"description": "Skill name",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"category": {
|
|
"default": "",
|
|
"description": "Skill category",
|
|
"title": "Category",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"default": "",
|
|
"description": "Skill description for discovery",
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"tags": {
|
|
"description": "Semantic tags",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Tags",
|
|
"type": "array"
|
|
},
|
|
"is_default": {
|
|
"default": false,
|
|
"description": "Whether auto-applied to all sessions",
|
|
"title": "Is Default",
|
|
"type": "boolean"
|
|
},
|
|
"activation": {
|
|
"default": "named",
|
|
"description": "Activation mode: default, named, search",
|
|
"title": "Activation",
|
|
"type": "string"
|
|
},
|
|
"origin": {
|
|
"default": "manual",
|
|
"description": "Source: manual, mcp, skills.sh, github",
|
|
"title": "Origin",
|
|
"type": "string"
|
|
},
|
|
"author": {
|
|
"default": "",
|
|
"description": "Skill author",
|
|
"title": "Author",
|
|
"type": "string"
|
|
},
|
|
"version": {
|
|
"default": "1.0.0",
|
|
"description": "Skill version",
|
|
"title": "Version",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"name"
|
|
],
|
|
"title": "SkillSummary",
|
|
"type": "object"
|
|
},
|
|
"ListSkillSummaryResponse": {
|
|
"properties": {
|
|
"skills": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SkillSummary"
|
|
},
|
|
"title": "Skills",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"skills"
|
|
],
|
|
"title": "ListSkillSummaryResponse",
|
|
"type": "object"
|
|
},
|
|
"PersonaChoice": {
|
|
"description": "Display fields for the creation picker \u2014 the persona's levers\n(prompt / tool set / toggles) deliberately stay server-side.",
|
|
"properties": {
|
|
"name": {
|
|
"description": "Persona slug, the value to pass as CreateWorkstreamRequest.persona",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"display_name": {
|
|
"default": "",
|
|
"description": "Human-readable name",
|
|
"title": "Display Name",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"default": "",
|
|
"description": "What this persona is for",
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"applies_to_kinds": {
|
|
"description": "Workstream kinds this persona can be attached to",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Applies To Kinds",
|
|
"type": "array"
|
|
},
|
|
"is_default": {
|
|
"default": false,
|
|
"description": "Whether an empty persona field resolves to this one",
|
|
"title": "Is Default",
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"required": [
|
|
"name"
|
|
],
|
|
"title": "PersonaChoice",
|
|
"type": "object"
|
|
},
|
|
"ListPersonaChoicesResponse": {
|
|
"properties": {
|
|
"personas": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/PersonaChoice"
|
|
},
|
|
"title": "Personas",
|
|
"type": "array"
|
|
},
|
|
"total": {
|
|
"default": 0,
|
|
"title": "Total",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"title": "ListPersonaChoicesResponse",
|
|
"type": "object"
|
|
},
|
|
"AvailableModelInfo": {
|
|
"properties": {
|
|
"alias": {
|
|
"title": "Alias",
|
|
"type": "string"
|
|
},
|
|
"model": {
|
|
"title": "Model",
|
|
"type": "string"
|
|
},
|
|
"provider": {
|
|
"title": "Provider",
|
|
"type": "string"
|
|
},
|
|
"capabilities": {
|
|
"additionalProperties": true,
|
|
"description": "Operator-set capability flags for this alias (e.g. supports_transcription)",
|
|
"title": "Capabilities",
|
|
"type": "object"
|
|
}
|
|
},
|
|
"required": [
|
|
"alias",
|
|
"model",
|
|
"provider"
|
|
],
|
|
"title": "AvailableModelInfo",
|
|
"type": "object"
|
|
},
|
|
"ListAvailableModelsResponse": {
|
|
"properties": {
|
|
"models": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/AvailableModelInfo"
|
|
},
|
|
"title": "Models",
|
|
"type": "array"
|
|
},
|
|
"default_alias": {
|
|
"default": "",
|
|
"title": "Default Alias",
|
|
"type": "string"
|
|
},
|
|
"channel_default_alias": {
|
|
"default": "",
|
|
"title": "Channel Default Alias",
|
|
"type": "string"
|
|
},
|
|
"judge_default_alias": {
|
|
"default": "",
|
|
"title": "Judge Default Alias",
|
|
"type": "string"
|
|
},
|
|
"stt_default_alias": {
|
|
"default": "",
|
|
"description": "Effective speech-to-text role alias (blank = voice input disabled)",
|
|
"title": "Stt Default Alias",
|
|
"type": "string"
|
|
},
|
|
"tts_default_alias": {
|
|
"default": "",
|
|
"description": "Effective text-to-speech role alias (blank = voice output disabled)",
|
|
"title": "Tts Default Alias",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"title": "ListAvailableModelsResponse",
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|