UNPKG

@vfarcic/dot-ai

Version:

AI-powered development productivity platform that enhances software development workflows through intelligent automation and AI-driven assistance

470 lines (469 loc) 17.2 kB
"use strict"; /** * REST API Route Definitions * * Central registration of all REST API routes with their Zod schemas. * This is the single source of truth for routing, OpenAPI generation, and fixture validation. * * PRD #354: REST API Route Registry with Auto-Generated OpenAPI and Test Fixtures */ Object.defineProperty(exports, "__esModule", { value: true }); exports.routeDefinitions = void 0; exports.registerAllRoutes = registerAllRoutes; exports.getRouteCount = getRouteCount; const zod_1 = require("zod"); const schemas_1 = require("../schemas"); /** * Query parameter schemas for various endpoints */ const ToolDiscoveryQuerySchema = zod_1.z.object({ category: zod_1.z.string().optional().describe('Filter tools by category'), tag: zod_1.z.string().optional().describe('Filter tools by tag'), search: zod_1.z.string().optional().describe('Search tools by name or description'), }); const ResourceSearchQuerySchema = zod_1.z.object({ q: zod_1.z.string().describe('Search query'), limit: zod_1.z.coerce .number() .optional() .default(20) .describe('Maximum results to return'), offset: zod_1.z.coerce .number() .optional() .default(0) .describe('Offset for pagination'), }); const ResourceListQuerySchema = zod_1.z.object({ kind: zod_1.z.string().describe('Resource kind (e.g., Pod, Deployment)'), apiVersion: zod_1.z.string().describe('API version (e.g., v1, apps/v1)'), namespace: zod_1.z.string().optional().describe('Filter by namespace'), limit: zod_1.z.coerce.number().optional().describe('Maximum results to return'), offset: zod_1.z.coerce.number().optional().describe('Offset for pagination'), }); const SingleResourceQuerySchema = zod_1.z.object({ kind: zod_1.z.string().describe('Resource kind'), apiVersion: zod_1.z.string().describe('API version'), name: zod_1.z.string().describe('Resource name'), namespace: zod_1.z .string() .optional() .describe('Namespace (for namespaced resources)'), }); const ResourceKindsQuerySchema = zod_1.z.object({ namespace: zod_1.z.string().optional().describe('Filter kinds by namespace'), }); const EventsQuerySchema = zod_1.z.object({ name: zod_1.z.string().describe('Resource name'), kind: zod_1.z.string().describe('Resource kind'), namespace: zod_1.z.string().optional().describe('Resource namespace'), }); const LogsQuerySchema = zod_1.z.object({ name: zod_1.z.string().describe('Pod name'), namespace: zod_1.z.string().describe('Pod namespace'), container: zod_1.z .string() .optional() .describe('Container name (defaults to first container)'), tailLines: zod_1.z.coerce.number().optional().describe('Number of lines from end'), previous: zod_1.z.coerce .boolean() .optional() .describe('Get logs from previous container instance'), }); const VisualizationQuerySchema = zod_1.z.object({ reload: zod_1.z.coerce .boolean() .optional() .describe('Force regeneration of visualization'), }); /** * Path parameter schemas */ const ToolNameParamsSchema = zod_1.z.object({ toolName: zod_1.z.string().describe('Name of the tool to execute'), }); const PromptNameParamsSchema = zod_1.z.object({ promptName: zod_1.z.string().describe('Name of the prompt'), }); const SessionIdParamsSchema = zod_1.z.object({ sessionId: zod_1.z.string().describe('Session ID'), }); const SourceIdentifierParamsSchema = zod_1.z.object({ sourceIdentifier: zod_1.z .string() .describe('Source identifier (e.g., namespace/name of GitKnowledgeSource CR)'), }); const KnowledgeAskBodySchema = zod_1.z.object({ query: zod_1.z .string() .min(1) .describe('The question to answer from the knowledge base'), limit: zod_1.z.coerce .number() .optional() .default(20) .describe('Maximum chunks to retrieve per search (default: 20)'), uriFilter: zod_1.z .string() .optional() .describe('Optional: filter searches to specific document URI'), }); /** * OpenAPI schema placeholder - returns raw OpenAPI spec object */ const OpenApiResponseSchema = zod_1.z .object({ openapi: zod_1.z.string(), info: zod_1.z.object({ title: zod_1.z.string(), description: zod_1.z.string(), version: zod_1.z.string(), }), paths: zod_1.z.record(zod_1.z.string(), zod_1.z.any()), }) .passthrough(); /** * All route definitions for the REST API */ exports.routeDefinitions = [ // ============================================ // Tool Endpoints // ============================================ { path: '/api/v1/tools', method: 'GET', description: 'Discover available tools with optional filtering by category, tag, or search term', tags: ['Tools'], query: ToolDiscoveryQuerySchema, response: schemas_1.ToolDiscoveryResponseSchema, errorResponses: { 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/tools/:toolName', method: 'POST', description: 'Execute a tool with the provided parameters', tags: ['Tools'], params: ToolNameParamsSchema, body: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).describe('Tool execution parameters'), response: schemas_1.ToolExecutionResponseSchema, errorResponses: { 400: schemas_1.InvalidToolRequestErrorSchema, 404: schemas_1.ToolNotFoundErrorSchema, 500: schemas_1.ToolExecutionErrorSchema, }, }, // ============================================ // OpenAPI Endpoint // ============================================ { path: '/api/v1/openapi', method: 'GET', description: 'Get the OpenAPI 3.0 specification for this API', tags: ['Documentation'], response: OpenApiResponseSchema, errorResponses: { 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Resource Endpoints // ============================================ { path: '/api/v1/resources', method: 'GET', description: 'List resources filtered by kind and optional namespace', tags: ['Resources'], query: ResourceListQuerySchema, response: schemas_1.ResourceListResponseSchema, errorResponses: { 400: schemas_1.ResourceBadRequestErrorSchema, 503: schemas_1.ResourcePluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/resources/kinds', method: 'GET', description: 'List all resource kinds available in the cluster with counts', tags: ['Resources'], query: ResourceKindsQuerySchema, response: schemas_1.ResourceKindsResponseSchema, errorResponses: { 503: schemas_1.ResourcePluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/resources/search', method: 'GET', description: 'Search for resources using semantic search', tags: ['Resources'], query: ResourceSearchQuerySchema, response: schemas_1.ResourceSearchResponseSchema, errorResponses: { 400: schemas_1.ResourceBadRequestErrorSchema, 503: schemas_1.ResourcePluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/resources/sync', method: 'POST', description: 'Sync resources from the Kubernetes controller', tags: ['Resources'], body: schemas_1.ResourceSyncRequestSchema, response: schemas_1.ResourceSyncResponseSchema, errorResponses: { 400: schemas_1.ResourceBadRequestErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/resource', method: 'GET', description: 'Get a single resource with full details including live status', tags: ['Resources'], query: SingleResourceQuerySchema, response: schemas_1.SingleResourceResponseSchema, errorResponses: { 400: schemas_1.ResourceBadRequestErrorSchema, 404: schemas_1.NotFoundErrorSchema, 503: schemas_1.ResourcePluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/namespaces', method: 'GET', description: 'List all namespaces in the cluster', tags: ['Resources'], response: schemas_1.NamespacesResponseSchema, errorResponses: { 503: schemas_1.ResourcePluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Events Endpoint // ============================================ { path: '/api/v1/events', method: 'GET', description: 'Get Kubernetes events for a specific resource', tags: ['Observability'], query: EventsQuerySchema, response: schemas_1.EventsResponseSchema, errorResponses: { 400: schemas_1.EventsBadRequestErrorSchema, 503: schemas_1.EventsPluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Logs Endpoint // ============================================ { path: '/api/v1/logs', method: 'GET', description: 'Get container logs from a pod', tags: ['Observability'], query: LogsQuerySchema, response: schemas_1.LogsResponseSchema, errorResponses: { 400: schemas_1.LogsBadRequestErrorSchema, 503: schemas_1.LogsPluginUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Prompts Endpoints // ============================================ { path: '/api/v1/prompts', method: 'GET', description: 'List all available prompts', tags: ['Prompts'], response: schemas_1.PromptsListResponseSchema, errorResponses: { 500: schemas_1.InternalServerErrorSchema, }, }, { path: '/api/v1/prompts/refresh', method: 'POST', description: 'Force-refresh the prompts cache by pulling latest from the git repository', tags: ['Prompts'], response: schemas_1.PromptsCacheRefreshResponseSchema, errorResponses: { 500: schemas_1.PromptsCacheRefreshErrorSchema, }, }, { path: '/api/v1/prompts/:promptName', method: 'POST', description: 'Get a prompt with rendered template arguments', tags: ['Prompts'], params: PromptNameParamsSchema, body: schemas_1.PromptGetRequestSchema, response: schemas_1.PromptGetResponseSchema, errorResponses: { 404: schemas_1.PromptNotFoundErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Visualization Endpoint // ============================================ { path: '/api/v1/visualize/:sessionId', method: 'GET', description: 'Get structured visualization data for a session', tags: ['Visualization'], params: SessionIdParamsSchema, query: VisualizationQuerySchema, response: schemas_1.VisualizationResponseSchema, errorResponses: { 404: schemas_1.VisualizationNotFoundErrorSchema, 503: schemas_1.VisualizationServiceUnavailableErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Sessions Endpoints // ============================================ { path: '/api/v1/sessions', method: 'GET', description: 'List sessions with optional status filtering and pagination', tags: ['Sessions'], query: schemas_1.SessionListQuerySchema, response: schemas_1.SessionListResponseSchema, errorResponses: { 500: schemas_1.SessionListErrorSchema, }, }, { path: '/api/v1/sessions/:sessionId', method: 'GET', description: 'Get raw session data for any tool type (remediate, query, recommend, etc.)', tags: ['Sessions'], params: SessionIdParamsSchema, response: schemas_1.SessionResponseSchema, errorResponses: { 404: schemas_1.SessionNotFoundErrorSchema, 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // SSE Streaming Endpoints (PRD #425) // ============================================ { path: '/api/v1/events/remediations', method: 'GET', description: 'SSE stream for real-time remediation session events. Returns text/event-stream.', tags: ['Sessions'], response: schemas_1.RemediationSSEEventSchema, errorResponses: { 500: schemas_1.InternalServerErrorSchema, }, }, // ============================================ // Knowledge Base Endpoints (PRD #356) // ============================================ { path: '/api/v1/knowledge/source/:sourceIdentifier', method: 'DELETE', description: 'Delete all knowledge base chunks for a source identifier. Used by controller for GitKnowledgeSource cleanup.', tags: ['Knowledge'], params: SourceIdentifierParamsSchema, response: schemas_1.DeleteBySourceResponseSchema, errorResponses: { 503: schemas_1.DeleteBySourcePluginUnavailableErrorSchema, 500: schemas_1.DeleteBySourceErrorSchema, }, }, { path: '/api/v1/knowledge/ask', method: 'POST', description: 'Ask a question and receive an AI-synthesized answer from the knowledge base. Uses an agentic approach that can search multiple times with different phrasings for comprehensive answers.', tags: ['Knowledge'], body: KnowledgeAskBodySchema, response: schemas_1.KnowledgeAskResponseSchema, errorResponses: { 400: schemas_1.KnowledgeAskBadRequestErrorSchema, 503: schemas_1.ServiceUnavailableErrorSchema, 500: schemas_1.KnowledgeAskErrorSchema, }, }, // ============================================ // Embeddings Endpoint (PRD #384) // ============================================ { path: '/api/v1/embeddings/migrate', method: 'POST', description: 'Migrate embedding vectors when switching between embedding providers. Re-embeds all data using the current provider.', tags: ['Embeddings'], body: schemas_1.EmbeddingMigrationRequestSchema, response: schemas_1.EmbeddingMigrationResponseSchema, errorResponses: { 400: schemas_1.EmbeddingMigrationBadRequestErrorSchema, 503: schemas_1.EmbeddingMigrationServiceUnavailableErrorSchema, 500: schemas_1.EmbeddingMigrationErrorSchema, }, }, // ============================================ // User Management Endpoints (PRD #380 Task 2.5) // ============================================ { path: '/api/v1/users', method: 'POST', description: 'Create a new Dex static user', tags: ['Users'], body: schemas_1.UserCreateRequestSchema, response: schemas_1.UserCreateResponseSchema, errorResponses: { 400: schemas_1.UserBadRequestErrorSchema, 409: schemas_1.UserConflictErrorSchema, 500: schemas_1.UserManagementErrorSchema, }, }, { path: '/api/v1/users', method: 'GET', description: 'List all Dex static users (emails only)', tags: ['Users'], response: schemas_1.UserListResponseSchema, errorResponses: { 500: schemas_1.UserManagementErrorSchema, }, }, { path: '/api/v1/users/:email', method: 'DELETE', description: 'Delete a Dex static user by email', tags: ['Users'], params: schemas_1.UserEmailParamsSchema, response: schemas_1.UserDeleteResponseSchema, errorResponses: { 404: schemas_1.UserNotFoundErrorSchema, 500: schemas_1.UserManagementErrorSchema, }, }, ]; /** * Register all routes with the provided registry */ function registerAllRoutes(registry) { for (const route of exports.routeDefinitions) { registry.register(route); } } /** * Get route count - useful for validation */ function getRouteCount() { return exports.routeDefinitions.length; }