Files

1376 lines
34 KiB
JSON

{
"openapi": "3.1.0",
"info": {
"title": "ComfyUI-Doctor API",
"version": "1.8.4",
"summary": "HTTP API contract for the ComfyUI-Doctor custom node.",
"description": "ComfyUI-Doctor registers canonical /doctor/... and /debugger/... routes on the ComfyUI PromptServer. Current ComfyUI route duplication may expose /api/doctor/... as a host-provided alias for Doctor routes. Doctor does not currently queue host prompts directly; future prompt queueing should use non-secret usage-source identifier comfyui-doctor and must not include secrets, raw prompts, private paths, cookies, or credentials. Write-sensitive endpoints use the Doctor admin guard; shared servers should configure DOCTOR_ADMIN_TOKEN and DOCTOR_REQUIRE_ADMIN_TOKEN=1."
},
"servers": [
{
"url": "http://127.0.0.1:8188",
"description": "Local ComfyUI PromptServer"
}
],
"tags": [
{
"name": "Debugger",
"description": "Current error analysis, history, and language state."
},
{
"name": "LLM",
"description": "LLM analysis, chat, provider defaults, key verification, and model listing."
},
{
"name": "Secrets",
"description": "Admin-gated server-side provider credential metadata and storage."
},
{
"name": "Statistics",
"description": "Error statistics and resolution workflow."
},
{
"name": "Feedback",
"description": "Sanitized community feedback preview and admin-gated submission."
},
{
"name": "Health",
"description": "Runtime health and proactive diagnostics."
},
{
"name": "Telemetry",
"description": "Local telemetry buffer controls."
},
{
"name": "Plugins",
"description": "Scan-only community plugin trust reporting."
},
{
"name": "Jobs",
"description": "Resumable job state and mutation controls."
},
{
"name": "Providers",
"description": "External provider capability status."
}
],
"paths": {
"/debugger/last_analysis": {
"get": {
"tags": [
"Debugger"
],
"operationId": "getLastAnalysis",
"summary": "Return the latest error analysis state.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/debugger/history": {
"get": {
"tags": [
"Debugger"
],
"operationId": "getAnalysisHistory",
"summary": "Return recent error-analysis history.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
}
}
}
},
"/debugger/set_language": {
"post": {
"tags": [
"Debugger"
],
"operationId": "setDebuggerLanguage",
"summary": "Change the suggestion language.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LanguageRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/debugger/clear_history": {
"post": {
"tags": [
"Debugger"
],
"operationId": "clearAnalysisHistory",
"summary": "Clear recorded error-analysis history.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/ui_text": {
"get": {
"tags": [
"LLM"
],
"operationId": "getDoctorUiText",
"summary": "Return localized UI text and public package metadata.",
"parameters": [
{
"name": "lang",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/analyze": {
"post": {
"tags": [
"LLM"
],
"operationId": "analyzeError",
"summary": "Run single-shot LLM analysis for an error context.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AnalyzeRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/Error"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/chat": {
"post": {
"tags": [
"LLM"
],
"operationId": "chat",
"summary": "Run the interactive chat flow with JSON or SSE streaming output.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChatRequest"
}
}
}
},
"responses": {
"200": {
"description": "Chat completion response. Streaming requests return Server-Sent Events.",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
},
"text/event-stream": {
"schema": {
"type": "string",
"description": "SSE stream with data events containing JSON fragments."
}
}
}
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/Error"
},
"503": {
"$ref": "#/components/responses/Error"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/provider_defaults": {
"get": {
"tags": [
"LLM"
],
"operationId": "getProviderDefaults",
"summary": "Return default base URLs for supported LLM providers.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
}
}
}
},
"/doctor/verify_key": {
"post": {
"tags": [
"LLM"
],
"operationId": "verifyProviderKey",
"summary": "Validate provider connectivity and credential availability.",
"requestBody": {
"$ref": "#/components/requestBodies/ProviderCredentialRequest"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
}
}
}
},
"/doctor/list_models": {
"post": {
"tags": [
"LLM"
],
"operationId": "listProviderModels",
"summary": "List models from the selected provider when supported.",
"requestBody": {
"$ref": "#/components/requestBodies/ProviderCredentialRequest"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
}
}
}
},
"/doctor/secrets/status": {
"get": {
"tags": [
"Secrets"
],
"operationId": "getSecretStatus",
"summary": "Return provider credential source status without exposing secret values.",
"security": [
{
"AdminTokenAuth": []
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
}
}
}
},
"/doctor/secrets": {
"put": {
"tags": [
"Secrets"
],
"operationId": "saveProviderSecret",
"summary": "Save a provider credential to the optional server-side store.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SecretWriteRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
}
}
}
},
"/doctor/secrets/{provider}": {
"delete": {
"tags": [
"Secrets"
],
"operationId": "deleteProviderSecret",
"summary": "Delete a stored provider credential.",
"security": [
{
"AdminTokenAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/ProviderPath"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/OptionalAdminPayload"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/statistics": {
"get": {
"tags": [
"Statistics"
],
"operationId": "getStatistics",
"summary": "Return error statistics for the dashboard.",
"parameters": [
{
"name": "time_range_days",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"default": 30
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/statistics/reset": {
"post": {
"tags": [
"Statistics"
],
"operationId": "resetStatistics",
"summary": "Clear statistics and history data.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"$ref": "#/components/requestBodies/OptionalAdminPayload"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/mark_resolved": {
"post": {
"tags": [
"Statistics"
],
"operationId": "markErrorResolved",
"summary": "Mark an error as resolved, unresolved, or ignored.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResolutionRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/feedback/preview": {
"post": {
"tags": [
"Feedback"
],
"operationId": "previewFeedback",
"summary": "Build and sanitize a community feedback preview.",
"requestBody": {
"$ref": "#/components/requestBodies/GenericJson"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/feedback/submit": {
"post": {
"tags": [
"Feedback"
],
"operationId": "submitFeedback",
"summary": "Submit sanitized feedback through the configured GitHub flow.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"$ref": "#/components/requestBodies/GenericJson"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/health": {
"get": {
"tags": [
"Health"
],
"operationId": "getRuntimeHealth",
"summary": "Return Doctor runtime health and path diagnostics.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/plugins": {
"get": {
"tags": [
"Plugins"
],
"operationId": "getPluginTrustReport",
"summary": "Return scan-only plugin trust information.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/status": {
"get": {
"tags": [
"Telemetry"
],
"operationId": "getTelemetryStatus",
"summary": "Return telemetry enabled state and buffer stats.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/buffer": {
"get": {
"tags": [
"Telemetry"
],
"operationId": "getTelemetryBuffer",
"summary": "Return local telemetry buffer contents.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/track": {
"post": {
"tags": [
"Telemetry"
],
"operationId": "trackTelemetryEvent",
"summary": "Add a telemetry event when telemetry is enabled.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TelemetryTrackRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"403": {
"$ref": "#/components/responses/Error"
},
"413": {
"$ref": "#/components/responses/Error"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/clear": {
"post": {
"tags": [
"Telemetry"
],
"operationId": "clearTelemetryBuffer",
"summary": "Clear the local telemetry buffer.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"$ref": "#/components/requestBodies/OptionalAdminPayload"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/export": {
"get": {
"tags": [
"Telemetry"
],
"operationId": "exportTelemetryBuffer",
"summary": "Export local telemetry buffer as JSON.",
"responses": {
"200": {
"description": "Telemetry export JSON.",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/telemetry/toggle": {
"post": {
"tags": [
"Telemetry"
],
"operationId": "toggleTelemetry",
"summary": "Enable or disable telemetry.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TelemetryToggleRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/jobs/{job_id}": {
"get": {
"tags": [
"Jobs"
],
"operationId": "getJob",
"summary": "Return resumable job state.",
"parameters": [
{
"$ref": "#/components/parameters/JobIdPath"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/jobs/{job_id}/resume": {
"post": {
"tags": [
"Jobs"
],
"operationId": "resumeJob",
"summary": "Resume an eligible failed, cancelled, or pending job.",
"security": [
{
"AdminTokenAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/JobIdPath"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/OptionalAdminPayload"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/jobs/{job_id}/cancel": {
"post": {
"tags": [
"Jobs"
],
"operationId": "cancelJob",
"summary": "Cancel an eligible job.",
"security": [
{
"AdminTokenAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/JobIdPath"
}
],
"requestBody": {
"$ref": "#/components/requestBodies/OptionalAdminPayload"
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/providers/{provider_id}/status": {
"get": {
"tags": [
"Providers"
],
"operationId": "getProviderStatus",
"summary": "Return external enrichment provider capability status.",
"parameters": [
{
"$ref": "#/components/parameters/ProviderIdPath"
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"404": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/health_check": {
"post": {
"tags": [
"Health"
],
"operationId": "runHealthCheck",
"summary": "Run local diagnostics for a workflow or context payload.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthCheckRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/health_report": {
"get": {
"tags": [
"Health"
],
"operationId": "getHealthReport",
"summary": "Return the latest diagnostics report.",
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/health_history": {
"get": {
"tags": [
"Health"
],
"operationId": "getHealthHistory",
"summary": "Return diagnostics report history metadata.",
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
},
{
"name": "offset",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 0,
"default": 0
}
}
],
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/doctor/health_ack": {
"post": {
"tags": [
"Health"
],
"operationId": "acknowledgeHealthIssue",
"summary": "Acknowledge, ignore, or resolve a diagnostics issue.",
"security": [
{
"AdminTokenAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthAckRequest"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/JsonObject"
},
"400": {
"$ref": "#/components/responses/Error"
},
"401": {
"$ref": "#/components/responses/AdminDenied"
},
"403": {
"$ref": "#/components/responses/AdminDenied"
},
"500": {
"$ref": "#/components/responses/Error"
}
}
}
}
},
"components": {
"securitySchemes": {
"AdminTokenAuth": {
"type": "apiKey",
"in": "header",
"name": "X-Doctor-Admin-Token",
"description": "Doctor admin token. Some existing handlers also accept an admin_token field in JSON payloads for UI compatibility."
}
},
"parameters": {
"ProviderPath": {
"name": "provider",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
"ProviderIdPath": {
"name": "provider_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
"JobIdPath": {
"name": "job_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
},
"requestBodies": {
"GenericJson": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"OptionalAdminPayload": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdminPayload"
}
}
}
},
"ProviderCredentialRequest": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProviderCredentialRequest"
}
}
}
}
},
"responses": {
"JsonObject": {
"description": "JSON object response.",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"Error": {
"description": "Standard error envelope.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorEnvelope"
}
}
}
},
"AdminDenied": {
"description": "Admin authorization denied.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorEnvelope"
}
}
}
}
},
"schemas": {
"AdminPayload": {
"type": "object",
"properties": {
"admin_token": {
"type": "string",
"writeOnly": true
}
},
"additionalProperties": true
},
"AnalyzeRequest": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string"
},
"node_context": {
"type": "object",
"additionalProperties": true
},
"workflow": {
"type": "object",
"additionalProperties": true
},
"api_key": {
"type": "string",
"writeOnly": true
},
"base_url": {
"type": "string",
"format": "uri"
},
"provider": {
"type": "string"
},
"model": {
"type": "string"
},
"language": {
"type": "string"
},
"privacy_mode": {
"type": "string",
"enum": [
"off",
"basic",
"strict"
]
}
},
"additionalProperties": true
},
"ChatRequest": {
"allOf": [
{
"$ref": "#/components/schemas/AnalyzeRequest"
},
{
"type": "object",
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"stream": {
"type": "boolean"
}
},
"additionalProperties": true
}
]
},
"ErrorEnvelope": {
"type": "object",
"required": [
"success",
"error",
"message"
],
"properties": {
"success": {
"type": "boolean",
"const": false
},
"error": {
"type": "string"
},
"message": {
"type": "string"
}
},
"additionalProperties": true
},
"HealthAckRequest": {
"type": "object",
"required": [
"report_id",
"issue_id",
"status"
],
"properties": {
"report_id": {
"type": "string"
},
"issue_id": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"acknowledged",
"ignored",
"resolved"
]
},
"admin_token": {
"type": "string",
"writeOnly": true
}
},
"additionalProperties": false
},
"HealthCheckRequest": {
"type": "object",
"properties": {
"workflow": {
"type": "object",
"additionalProperties": true
},
"scope": {
"type": "string",
"enum": [
"manual",
"schedule",
"pre_exec",
"workflow_change"
]
},
"options": {
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": true
},
"LanguageRequest": {
"type": "object",
"required": [
"language"
],
"properties": {
"language": {
"type": "string"
}
},
"additionalProperties": false
},
"ProviderCredentialRequest": {
"type": "object",
"properties": {
"base_url": {
"type": "string",
"format": "uri"
},
"api_key": {
"type": "string",
"writeOnly": true
},
"provider": {
"type": "string"
}
},
"additionalProperties": true
},
"ResolutionRequest": {
"type": "object",
"required": [
"timestamp",
"status"
],
"properties": {
"timestamp": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"resolved",
"unresolved",
"ignored"
]
},
"admin_token": {
"type": "string",
"writeOnly": true
}
},
"additionalProperties": false
},
"SecretWriteRequest": {
"type": "object",
"required": [
"provider",
"api_key"
],
"properties": {
"provider": {
"type": "string",
"enum": [
"openai",
"anthropic",
"deepseek",
"groq",
"gemini",
"xai",
"openrouter",
"generic"
]
},
"api_key": {
"type": "string",
"writeOnly": true
},
"admin_token": {
"type": "string",
"writeOnly": true
}
},
"additionalProperties": false
},
"TelemetryToggleRequest": {
"type": "object",
"required": [
"enabled"
],
"properties": {
"enabled": {
"type": "boolean"
},
"admin_token": {
"type": "string",
"writeOnly": true
}
},
"additionalProperties": false
},
"TelemetryTrackRequest": {
"type": "object",
"required": [
"category",
"action"
],
"properties": {
"category": {
"type": "string"
},
"action": {
"type": "string"
},
"label": {
"type": "string"
},
"value": {
"type": "integer"
}
},
"additionalProperties": false
}
}
}
}