{"openapi":"3.1.0","info":{"title":"nfrax-api • v1","version":"0.1.0"},"servers":[{"url":"/v1"}],"paths":{"/chat/reset-cache":{"post":{"summary":"Reset Mcp Cache","description":"Reset MCP tool cache (development/debugging only).\n\nThis clears the cached MCP tools, forcing a fresh load on the next request.\nUseful for debugging MCP server connection issues or testing cache behavior.","operationId":"reset_mcp_cache","responses":{"200":{"description":"Reset Mcp Cache success","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"security":[],"tags":["chat"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/chat/reset-cache'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/chat/reset-cache'"}]}},"/chat/stop/{stream_id}":{"post":{"summary":"Stop Stream","description":"Stop an active chat stream.\n\nThis allows the client to cancel an ongoing streaming response.\nThe stream will stop gracefully after the current chunk.","operationId":"stop_stream","parameters":[{"name":"stream_id","in":"path","required":true,"schema":{"type":"string","title":"Stream Id"},"description":"stream_id parameter."},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Stop Stream success","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"tags":["chat"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/chat/stop/{stream_id}'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/chat/stop/{stream_id}'"}]}},"/chat/cache-stats":{"get":{"summary":"Get Cache Stats","description":"Get MCP tool cache statistics for monitoring.\n\nReturns information about the current cache state, useful for:\n- Monitoring cache hit rate\n- Debugging cache behavior\n- Understanding tool loading performance\n\nNote: Cache statistics depend on ai-infra implementation details.\nIf the function is not available, returns basic status only.","operationId":"get_cache_stats","responses":{"200":{"description":"Get Cache Stats success","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"parameters":[{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"security":[],"tags":["chat"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/chat/cache-stats'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/chat/cache-stats'"}]}},"/chat":{"post":{"summary":"Chat","description":"Chat with the nfrax documentation assistant.\n\nUsers must provide their own API key (BYOK - Bring Your Own Key).\nThe API key is used directly with the provider and is not stored.\n\nThe assistant has access to RAG-based tools for searching documentation\nand code across svc-infra, ai-infra, and fin-infra packages.\n\nSet stream=true to receive Server-Sent Events (SSE) for streaming responses.\n\n**Rolling Summary Support:**\n\nFor long conversations, this endpoint supports token-efficient rolling summaries:\n\n1. **First request**: Don't send `summary` (or send null)\n2. **Check response**: If `summary` and `summary_through_index` are returned,\n   store them client-side\n3. **Next request**: Send the stored `summary` and only messages after\n   `summary_through_index` in the history\n4. **Repeat**: As conversation grows, summary is extended automatically\n\nThis allows unlimited conversation length while keeping token costs low.\n\n**Agent Visibility (streaming only):**\n\nControl how much detail about agent activity appears in the SSE stream:\n\n- `minimal`: Only response tokens (cleanest UX)\n- `standard`: Tokens + tool names + timing (shows what's happening)\n- `detailed`: + tool arguments + full results for parsing (default, enables clickable links)\n- `debug`: + result previews for UI display (development only)\n\n**SSE Event Types (when streaming):**\n\n```\n{\"type\": \"thinking\", \"model\": \"gpt-4o-mini\"}     // Agent starting\n{\"type\": \"tool_start\", \"tool\": \"search_docs\", \"tool_id\": \"call_abc\", \"arguments\"?: {...}}   // Tool execution begins\n{\"type\": \"tool_results\", \"tool\": \"search_docs\", \"docs\": [{\"package\": \"svc-infra\", \"path\": \"auth.md\"}], \"latency_ms\": 234}  // Parsed tool results (clickable links)\n{\"type\": \"token\", \"content\": \"Based on...\"}     // Response tokens\n{\"type\": \"done\", \"tools_called\": 2}             // Stream complete\n{\"type\": \"error\", \"message\": \"...\"}             // Error occurred\n```\n\n**Request fields:**\n- `summary`: Rolling summary from previous response (null for first message)\n- `max_context_tokens`: Token budget before summarization triggers (default: 4000)\n- `visibility`: Agent activity visibility level (default: \"standard\")\n\n**Response fields (when summarization occurs):**\n- `summary`: New/extended summary to store for next request\n- `summary_through_index`: Number of messages covered by summary","operationId":"chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}},"required":true,"description":"Request body for POST /chat."},"responses":{"200":{"description":"Chat success","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"security":[],"tags":["chat"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/chat'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/chat'"}]}},"/chat-feedback":{"post":{"summary":"Submit chat quality feedback","description":"Submit feedback on an AI chat response quality.\n\n**Important**: Only the specific user message and assistant response being rated\nare stored. No chat history is persisted.\n\n**Rate Limit**: 10 requests per minute per session.\n\n**Session ID**: Required header for rate limiting and grouping feedback.\nGenerate a UUID on first visit and store in localStorage.","operationId":"create_chat_feedback","parameters":[{"name":"X-Session-Id","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":100,"description":"Browser session ID for rate limiting","title":"X-Session-Id"},"description":"Browser session ID for rate limiting"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackCreate"}}},"description":"Request body for POST /chat-feedback."},"responses":{"201":{"description":"Chat feedback created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackRead"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until next allowed request."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"tags":["chat-feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/chat-feedback'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/chat-feedback'"}]},"get":{"summary":"List chat feedback","description":"List chat feedback entries with optional filters and pagination.","operationId":"list_chat_feedback","parameters":[{"name":"rating","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/Rating"},{"type":"null"}],"description":"Filter by rating","title":"Rating","type":"string"},"description":"Filter by rating"},{"name":"issue_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/ChatIssueType"},{"type":"null"}],"description":"Filter by issue type","title":"Issue Type","type":"string"},"description":"Filter by issue type"},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by model","title":"Model","type":"string"},"description":"Filter by model"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"responses":{"200":{"description":"List chat feedback success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackListResponse"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"security":[],"tags":["chat-feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/chat-feedback'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/chat-feedback'"}]}},"/chat-feedback/{feedback_id}":{"get":{"summary":"Get chat feedback by ID","description":"Get a specific chat feedback entry by ID.","operationId":"get_chat_feedback","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Feedback Id"},"description":"feedback_id parameter."},{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"responses":{"200":{"description":"Chat feedback found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackRead"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"404":{"description":"Chat feedback not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"security":[],"tags":["chat-feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/chat-feedback/{feedback_id}'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/chat-feedback/{feedback_id}'"}]}},"/feedback":{"post":{"summary":"Submit general feedback","description":"Submit feedback for docs, feature requests, bug reports, or general comments.\n\n**Rate Limit**: 10 requests per minute per session.\n\n**Session ID**: Required header for rate limiting and grouping feedback.\nGenerate a UUID on first visit and store in localStorage.","operationId":"create_feedback","parameters":[{"name":"X-Session-Id","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":100,"description":"Browser session ID for rate limiting","title":"X-Session-Id"},"description":"Browser session ID for rate limiting"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackCreate"}}},"description":"Request body for POST /feedback."},"responses":{"201":{"description":"Feedback created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRead"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until next allowed request."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"tags":["feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/feedback'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/feedback'"}]},"get":{"summary":"List feedback","description":"List feedback entries with optional filters and pagination.","operationId":"list_feedback","parameters":[{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/FeedbackType"},{"type":"null"}],"description":"Filter by feedback type","title":"Type","type":"string"},"description":"Filter by feedback type"},{"name":"package","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/Package"},{"type":"null"}],"description":"Filter by package","title":"Package","type":"string"},"description":"Filter by package"},{"name":"rating","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/Rating"},{"type":"null"}],"description":"Filter by rating","title":"Rating","type":"string"},"description":"Filter by rating"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"responses":{"200":{"description":"List feedback success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackListResponse"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"security":[],"tags":["feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/feedback'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/feedback'"}]}},"/feedback/{feedback_id}":{"get":{"summary":"Get feedback by ID","description":"Get a specific feedback entry by ID.","operationId":"get_feedback","parameters":[{"name":"feedback_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Feedback Id"},"description":"feedback_id parameter."},{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"responses":{"200":{"description":"Feedback found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRead"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"404":{"description":"Feedback not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"security":[],"tags":["feedback"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/feedback/{feedback_id}'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/feedback/{feedback_id}'"}]}},"/providers":{"get":{"summary":"List Providers","description":"List all supported LLM providers.\n\nReturns the list of providers that can be used with the chat endpoint.","operationId":"list_providers","responses":{"200":{"description":"List Providers success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvidersResponse"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"parameters":[{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"security":[],"tags":["providers"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/providers'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/providers'"}]}},"/capabilities":{"get":{"summary":"List Capabilities","description":"List all supported model capabilities.\n\nReturns the list of capabilities that can be used to filter models.","operationId":"list_capabilities","responses":{"200":{"description":"List Capabilities success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesResponse"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/ValidationError"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"},"304":{"description":"Not Modified","headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"}}}},"parameters":[{"$ref":"#/components/parameters/IfNoneMatch"},{"$ref":"#/components/parameters/IfModifiedSince"}],"security":[],"tags":["capabilities"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X GET '/v1/capabilities'"},{"lang":"bash","label":"httpie","source":"http GET '/v1/capabilities'"}]}},"/models":{"post":{"summary":"List Models","description":"List available models for a specific provider.\n\nRequires the user's API key to fetch models from the provider's API.\nModels can be filtered by capability (default: chat).","operationId":"list_models","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListModelsRequest"}}},"required":true,"description":"Request body for POST /models."},"responses":{"200":{"description":"List Models success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListModelsResponse"}}},"headers":{"ETag":{"$ref":"#/components/headers/ETag"},"Last-Modified":{"$ref":"#/components/headers/LastModified"},"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"X-RateLimit-Limit":{"$ref":"#/components/headers/XRateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/XRateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/XRateLimitReset"}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}},"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"security":[],"tags":["models"],"x-codeSamples":[{"lang":"bash","label":"curl","source":"curl -X POST '/v1/models'"},{"lang":"bash","label":"httpie","source":"http POST '/v1/models'"}]}}},"components":{"schemas":{"CapabilitiesResponse":{"properties":{"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities","description":"List of supported capability names"}},"type":"object","required":["capabilities"],"title":"CapabilitiesResponse","description":"Response with list of supported model capabilities."},"ChatFeedbackCreate":{"properties":{"user_message":{"type":"string","maxLength":50000,"minLength":1,"title":"User Message"},"assistant_message":{"type":"string","maxLength":50000,"minLength":1,"title":"Assistant Message"},"model":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Model"},"rating":{"$ref":"#/components/schemas/Rating"},"issue_type":{"anyOf":[{"$ref":"#/components/schemas/ChatIssueType"},{"type":"null"}]},"comment":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Comment"}},"type":"object","required":["user_message","assistant_message","rating"],"title":"ChatFeedbackCreate","description":"Schema for creating chat feedback.\n\nThe user_message and assistant_message are the single exchange\nbeing rated - no chat history is stored."},"ChatFeedbackListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ChatFeedbackRead"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page","default":1},"per_page":{"type":"integer","title":"Per Page","default":20}},"type":"object","required":["items","total"],"title":"ChatFeedbackListResponse","description":"Paginated list response for chat feedback."},"ChatFeedbackRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","title":"Session Id"},"user_message":{"type":"string","title":"User Message"},"assistant_message":{"type":"string","title":"Assistant Message"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"rating":{"$ref":"#/components/schemas/Rating"},"issue_type":{"anyOf":[{"$ref":"#/components/schemas/ChatIssueType"},{"type":"null"}]},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","session_id","user_message","assistant_message","rating","created_at"],"title":"ChatFeedbackRead","description":"Schema for reading chat feedback (API response)."},"ChatIssueType":{"type":"string","enum":["wrong_info","incomplete","unclear","off_topic","other"],"title":"ChatIssueType","description":"Issue type for negative chat feedback."},"ChatMessage":{"properties":{"role":{"type":"string","enum":["user","assistant"],"title":"Role"},"content":{"type":"string","title":"Content"}},"type":"object","required":["role","content"],"title":"ChatMessage","description":"A message in the chat history."},"ChatRequest":{"properties":{"message":{"type":"string","maxLength":4000,"minLength":1,"title":"Message","description":"User message"},"provider":{"type":"string","enum":["openai","anthropic","google","xai"],"title":"Provider","description":"LLM provider to use","default":"openai"},"api_key":{"type":"string","minLength":1,"title":"Api Key","description":"API key for the provider"},"history":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","title":"History","description":"Previous conversation messages"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Specific model to use (optional)"},"stream":{"type":"boolean","title":"Stream","description":"Whether to stream the response","default":false},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Rolling summary of earlier conversation (from previous response)"},"max_context_tokens":{"type":"integer","title":"Max Context Tokens","description":"Token budget for context (summary + messages). Triggers summarization when exceeded.","default":4000},"visibility":{"type":"string","enum":["minimal","standard","detailed","debug"],"title":"Visibility","description":"Controls visibility of agent activity in SSE stream. 'minimal': tokens only. 'standard': tokens + tool names + timing. 'detailed': + tool arguments + full results for parsing (default). 'debug': + result previews for UI.","default":"detailed"}},"type":"object","required":["message","api_key"],"title":"ChatRequest","description":"Request body for the chat endpoint."},"FeedbackCreate":{"properties":{"type":{"$ref":"#/components/schemas/FeedbackType"},"package":{"anyOf":[{"$ref":"#/components/schemas/Package"},{"type":"null"}]},"rating":{"anyOf":[{"$ref":"#/components/schemas/Rating"},{"type":"null"}]},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email","description":"Optional email for follow-up"},"content":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Content"},"page_url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Page Url"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["type"],"title":"FeedbackCreate","description":"Schema for creating new feedback."},"FeedbackListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/FeedbackRead"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page","default":1},"per_page":{"type":"integer","title":"Per Page","default":20}},"type":"object","required":["items","total"],"title":"FeedbackListResponse","description":"Paginated list response for feedback."},"FeedbackRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"type":{"$ref":"#/components/schemas/FeedbackType"},"package":{"anyOf":[{"$ref":"#/components/schemas/Package"},{"type":"null"}]},"rating":{"anyOf":[{"$ref":"#/components/schemas/Rating"},{"type":"null"}]},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"page_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Url"},"session_id":{"type":"string","title":"Session Id"},"metadata_":{"additionalProperties":true,"type":"object","title":"Metadata"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","type","session_id","created_at"],"title":"FeedbackRead","description":"Schema for reading feedback (API response)."},"FeedbackType":{"type":"string","enum":["feature_request","docs","bug","general"],"title":"FeedbackType","description":"Type of feedback being submitted."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ListModelsRequest":{"properties":{"provider":{"type":"string","enum":["openai","anthropic","google","xai"],"title":"Provider","description":"LLM provider to list models for"},"api_key":{"type":"string","minLength":1,"title":"Api Key","description":"API key for the provider"},"capability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Capability","description":"Filter models by capability: chat, embedding, audio, image, vision, etc.","default":"chat"}},"type":"object","required":["provider","api_key"],"title":"ListModelsRequest","description":"Request body for listing models."},"ListModelsResponse":{"properties":{"provider":{"type":"string","title":"Provider","description":"Provider name"},"models":{"items":{"type":"string"},"type":"array","title":"Models","description":"List of available model IDs"}},"type":"object","required":["provider","models"],"title":"ListModelsResponse","description":"Response with available models for a provider."},"Package":{"type":"string","enum":["svc-infra","ai-infra","fin-infra"],"title":"Package","description":"Package that feedback relates to."},"ProvidersResponse":{"properties":{"providers":{"items":{"type":"string"},"type":"array","title":"Providers","description":"List of supported provider names"}},"type":"object","required":["providers"],"title":"ProvidersResponse","description":"Response with list of supported providers."},"Rating":{"type":"string","enum":["positive","negative"],"title":"Rating","description":"User sentiment rating."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"Problem":{"type":"object","properties":{"type":{"type":"string","format":"uri","description":"URI identifying the error type"},"title":{"type":"string","description":"Short, human-readable summary"},"status":{"type":"integer","format":"int32","description":"HTTP status code"},"detail":{"type":"string","description":"Human-readable explanation"},"instance":{"type":"string","format":"uri-reference","description":"URI reference for this occurrence"},"code":{"type":"string","description":"Stable application error code"},"errors":{"type":"array","description":"Optional list of field/validation errors","items":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}},"trace_id":{"type":"string","description":"Correlation/trace id (if available)"}},"required":["title","status"]}},"responses":{"BadRequest":{"description":"The request is malformed or missing required fields","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Bad Request","status":400,"detail":"Invalid request payload.","instance":"https://api.example.com/request/abc123","code":"BAD_REQUEST","trace_id":"00000000000000000000000000000000"}}}}}},"Unauthorized":{"description":"Authentication required or failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Unauthorized","status":401,"detail":"Missing or invalid credentials.","instance":"https://api.example.com/request/abc123","code":"UNAUTHORIZED","trace_id":"00000000000000000000000000000000"}}}}}},"Forbidden":{"description":"The authenticated principal does not have access","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Forbidden","status":403,"detail":"You do not have permission to perform this action.","instance":"https://api.example.com/request/abc123","code":"FORBIDDEN","trace_id":"00000000000000000000000000000000"}}}}}},"NotFound":{"description":"The requested resource was not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Not Found","status":404,"detail":"Resource not found.","instance":"https://api.example.com/request/abc123","code":"NOT_FOUND","trace_id":"00000000000000000000000000000000"}}}}}},"Conflict":{"description":"A conflicting resource already exists or constraints were violated","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Conflict","status":409,"detail":"Record already exists.","instance":"https://api.example.com/request/abc123","code":"CONFLICT","trace_id":"00000000000000000000000000000000"}}}}}},"ValidationError":{"description":"Request failed validation","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Unprocessable Entity","status":422,"detail":"Validation failed.","instance":"https://api.example.com/request/abc123","code":"VALIDATION_ERROR","trace_id":"00000000000000000000000000000000","errors":[{"loc":["body","email"],"msg":"value is not a valid email address","type":"value_error.email"}]}}}}}},"TooManyRequests":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Too Many Requests","status":429,"detail":"Rate limit exceeded. Try again later.","instance":"https://api.example.com/request/abc123","code":"RATE_LIMITED","trace_id":"00000000000000000000000000000000"}}}}}},"ServerError":{"description":"Unexpected server error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"default":{"value":{"type":"about:blank","title":"Internal Server Error","status":500,"detail":"Something went wrong. Please contact support.","instance":"https://api.example.com/request/abc123","code":"INTERNAL_ERROR","trace_id":"00000000000000000000000000000000"}}}}}}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Provide to make the request idempotent for 24h."},"IfNoneMatch":{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"Conditional GET (ETag)."},"IfModifiedSince":{"name":"If-Modified-Since","in":"header","required":false,"schema":{"type":"string"},"description":"Conditional GET. HTTP-date per RFC 9110 (e.g. 'Wed, 01 Jan 2025 00:00:00 GMT')."},"IfMatch":{"name":"If-Match","in":"header","required":false,"schema":{"type":"string"},"description":"Optimistic concurrency for updates."}},"headers":{"ETag":{"schema":{"type":"string"},"description":"Opaque entity tag."},"LastModified":{"schema":{"type":"string"},"description":"Last modification time, HTTP-date per RFC 9110."},"XRateLimitLimit":{"schema":{"type":"integer"},"description":"Tokens in window."},"XRateLimitRemaining":{"schema":{"type":"integer"},"description":"Remaining tokens."},"XRateLimitReset":{"schema":{"type":"integer"},"description":"Unix reset time."},"XRequestId":{"schema":{"type":"string"},"description":"Correlation id."}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"tokenUrl":"/users/login","scopes":{}}}}}},"tags":[{"name":"capabilities","description":"Operations related to capabilities."},{"name":"chat","description":"Operations related to chat."},{"name":"chat-feedback","description":"Operations related to chat-feedback."},{"name":"feedback","description":"Operations related to feedback."},{"name":"models","description":"Operations related to models."},{"name":"providers","description":"Operations related to providers."}]}