mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
be165c1971
* feat: MCP resource and prompt discovery with read_resource tool Extends MCPClientManager with resource and prompt discovery alongside existing tool support. Resources and prompts are discovered on connect, cached per-server with copy-on-write rebuilds, and refreshed via push notifications, periodic polling, or manual /mcp refresh. New read_resource built-in tool reads MCP resources by URI. Requires user approval (same as MCP tool calls) since resources are served by external MCP servers. Resource catalog injected into system message with XML delimiters. Error messages sanitized to prevent leaking server internals to the model. Prompt discovery stores prefixed names (mcp__server__prompt) and exposes get_prompt_sync() for future use_prompt tool (Chunk D). /mcp command now shows tools, resources, and prompts. Docs and diagrams updated. * feat: MCP prompt governance sync with origin tracking and readonly guards Migration 009 adds origin, mcp_server, and readonly columns to prompt_templates. MCP prompts discovered by MCPClientManager are automatically synced into the governance table as read-only templates with origin="mcp". Sync engine handles: create on connect, update on prompt refresh, delete when prompts are removed from server. Manual templates take precedence on name collision (MCP prompt skipped with warning). Admin API returns 403 on update/delete of readonly templates. Console UI shows MCP origin badge and disables edit/delete buttons. Storage backends gain get_prompt_template_by_name, list_prompt_templates_by_origin, and delete_prompt_templates_by_server methods. Also addresses PR #44 review feedback: concurrent.futures.TimeoutError handling in sync dispatch, XML-escape resource catalog descriptions, resource template entries excluded from _resource_map, URI collision warnings, needs_periodic capability-aware computation, malformed JSON primary key fallback for read_resource. * feat: use_prompt tool, prompt catalog, and PR review hardening New use_prompt built-in tool invokes MCP prompt templates by name, expanding them into messages. Requires user approval (external MCP servers). Prompt catalog injected into system message with XML delimiters (up to 30 prompts, HTML-escaped). Prompt listener registered in session for catalog rebuild on changes. Addresses PR #44 review feedback: - _init_system_messages() now uses copy-on-write (build locally, assign atomically) so background thread callbacks never see partial system messages - sync_prompts_to_storage() serialized behind _sync_lock to prevent races between set_storage() (main thread) and MCP background thread - shutdown() clears listener lists to release callback references Docs and diagrams updated for 18 built-in tools. * feat: granular tool policies for MCP resources, prompts, and tools Policy evaluation now uses approval_label (falling back to func_name) for fnmatch pattern matching, enabling fine-grained per-URI and per-server policies: - read_resource: mcp_resource__{normalized_uri} - use_prompt: mcp__{server}__{prompt} (prefixed name) - MCP tools: mcp__{server}__{tool} (was static "mcp_tool") URI normalization resolves .. path segments to prevent traversal bypasses in policy matching. Resource templates filtered from system message catalog (not directly readable). use_prompt arguments validated as dict with string coercion. TypeScript SDK PromptTemplateInfo gains origin, mcp_server, readonly fields. Governance docs updated with MCP policy patterns. * feat: MCP visibility in server and console UIs Server health endpoint includes mcp.servers, mcp.resources, mcp.prompts counts. Server UI status bar shows magenta MCP indicator with tooltip. Console cluster status bar shows MCP metrics with magenta LED dot. Console node detail view shows per-node MCP summary. Console collector aggregates MCP counts across nodes in overview. Uses var(--magenta) design token with new --magenta-glow for theme adaptation. ARIA roles on MCP status elements. Tooltips on console MCP metric labels. Node MCP summary hidden on mobile (< 700px). New diagram: 20-mcp-architecture.puml covering full MCP lifecycle (connection, discovery, refresh, governance sync, policy, UI). * fix: McpStatus in health schema, count properties, catalog name fidelity Adds McpStatus model to HealthResponse (Python + TypeScript SDKs) so typed clients see the mcp field from /health. Addresses Copilot review feedback: - resource_count/prompt_count properties avoid list allocation on /health and /metrics polls - get_tools/resources/prompts return shallow-copied dicts to prevent callers from mutating internal cache - Prompt names and arg names in system message catalog are NOT HTML-escaped (model must use exact strings in use_prompt calls); only descriptions are escaped * fix: OpenAPI spec McpStatus + diagram approval column accuracy Adds McpStatus schema and optional mcp field to HealthResponse in openapi-server.json, matching the Python schema and TypeScript types. Fixes tool pipeline diagram: math, web_fetch, web_search correctly shown as auto-approve (not "Yes" for approval).
1274 lines
33 KiB
JSON
1274 lines
33 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "turnstone Server API",
|
|
"version": "0.4.2",
|
|
"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"],
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/workstreams/close": {
|
|
"post": {
|
|
"summary": "Close a workstream",
|
|
"operationId": "v1_api_workstreams_close_post",
|
|
"tags": ["Workstreams"],
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/send": {
|
|
"post": {
|
|
"summary": "Send a user message",
|
|
"operationId": "v1_api_send_post",
|
|
"tags": ["Chat"],
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/v1/api/approve": {
|
|
"post": {
|
|
"summary": "Approve or deny a tool call",
|
|
"operationId": "v1_api_approve_post",
|
|
"tags": ["Chat"],
|
|
"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/plan": {
|
|
"post": {
|
|
"summary": "Respond to a plan review",
|
|
"operationId": "v1_api_plan_post",
|
|
"tags": ["Chat"],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PlanFeedbackRequest"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"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/cancel": {
|
|
"post": {
|
|
"summary": "Cancel the active generation in a workstream",
|
|
"operationId": "v1_api_cancel_post",
|
|
"tags": ["Chat"],
|
|
"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/events": {
|
|
"get": {
|
|
"summary": "Per-workstream SSE event stream",
|
|
"operationId": "v1_api_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": "query",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Workstream identifier"
|
|
}
|
|
],
|
|
"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": "Global Server-Sent Events stream for state-change broadcasts across all workstreams. Returns text/event-stream.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/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/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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/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"
|
|
}
|
|
},
|
|
"required": ["auth_enabled", "has_users", "setup_required"],
|
|
"title": "AuthStatusResponse",
|
|
"type": "object"
|
|
},
|
|
"SendRequest": {
|
|
"properties": {
|
|
"message": {
|
|
"description": "User message text",
|
|
"title": "Message",
|
|
"type": "string"
|
|
},
|
|
"ws_id": {
|
|
"description": "Target workstream ID",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["message", "ws_id"],
|
|
"title": "SendRequest",
|
|
"type": "object"
|
|
},
|
|
"SendResponse": {
|
|
"properties": {
|
|
"status": {
|
|
"description": "'ok' or 'busy'",
|
|
"examples": ["ok", "busy"],
|
|
"title": "Status",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["status"],
|
|
"title": "SendResponse",
|
|
"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": "Enable auto-approve for this tool",
|
|
"title": "Always",
|
|
"type": "boolean"
|
|
},
|
|
"ws_id": {
|
|
"description": "Target workstream ID",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["approved", "ws_id"],
|
|
"title": "ApproveRequest",
|
|
"type": "object"
|
|
},
|
|
"PlanFeedbackRequest": {
|
|
"properties": {
|
|
"feedback": {
|
|
"description": "Feedback text; empty string means approval",
|
|
"title": "Feedback",
|
|
"type": "string"
|
|
},
|
|
"ws_id": {
|
|
"description": "Target workstream ID",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["feedback", "ws_id"],
|
|
"title": "PlanFeedbackRequest",
|
|
"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": {
|
|
"ws_id": {
|
|
"description": "Target workstream ID",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["ws_id"],
|
|
"title": "CancelRequest",
|
|
"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"
|
|
}
|
|
},
|
|
"title": "CreateWorkstreamRequest",
|
|
"type": "object"
|
|
},
|
|
"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"
|
|
}
|
|
},
|
|
"required": ["ws_id", "name"],
|
|
"title": "CreateWorkstreamResponse",
|
|
"type": "object"
|
|
},
|
|
"CloseWorkstreamRequest": {
|
|
"properties": {
|
|
"ws_id": {
|
|
"description": "Workstream ID to close",
|
|
"title": "Ws Id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["ws_id"],
|
|
"title": "CloseWorkstreamRequest",
|
|
"type": "object"
|
|
},
|
|
"ListWorkstreamsResponse": {
|
|
"properties": {
|
|
"workstreams": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/WorkstreamInfo"
|
|
},
|
|
"title": "Workstreams",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": ["workstreams"],
|
|
"title": "ListWorkstreamsResponse",
|
|
"type": "object"
|
|
},
|
|
"WorkstreamInfo": {
|
|
"properties": {
|
|
"id": {
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"state": {
|
|
"title": "State",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["id", "name", "state"],
|
|
"title": "WorkstreamInfo",
|
|
"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": {
|
|
"properties": {
|
|
"id": {
|
|
"title": "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"
|
|
}
|
|
},
|
|
"required": ["id", "name", "state"],
|
|
"title": "DashboardWorkstream",
|
|
"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"
|
|
}
|
|
},
|
|
"required": ["ws_id", "created", "updated", "message_count"],
|
|
"title": "SavedWorkstreamInfo",
|
|
"type": "object"
|
|
},
|
|
"HealthResponse": {
|
|
"properties": {
|
|
"status": {
|
|
"examples": ["ok", "degraded"],
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"version": {
|
|
"default": "",
|
|
"title": "Version",
|
|
"type": "string"
|
|
},
|
|
"uptime_seconds": {
|
|
"default": 0.0,
|
|
"title": "Uptime Seconds",
|
|
"type": "number"
|
|
},
|
|
"model": {
|
|
"default": "",
|
|
"title": "Model",
|
|
"type": "string"
|
|
},
|
|
"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"
|
|
},
|
|
"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"
|
|
},
|
|
"BackendStatus": {
|
|
"properties": {
|
|
"status": {
|
|
"examples": ["up", "down"],
|
|
"title": "Status",
|
|
"type": "string"
|
|
},
|
|
"circuit_state": {
|
|
"examples": ["closed", "open", "half_open"],
|
|
"title": "Circuit State",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": ["status", "circuit_state"],
|
|
"title": "BackendStatus",
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|