Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import { Controller, Get, Post, Patch, Body, Query, UseGuards, HttpCode, HttpStatus, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery, } from '@nestjs/swagger'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; import { AIService } from './services'; import { ChatRequestDto, ChatResponseDto, UpdateAIConfigDto, AIConfigResponseDto, UsageStatsDto, AIModelDto, } from './dto'; interface RequestUser { id: string; tenant_id: string; email: string; role: string; } @ApiTags('ai') @Controller('ai') @UseGuards(JwtAuthGuard) @ApiBearerAuth() export class AIController { constructor(private readonly aiService: AIService) {} // ==================== Chat ==================== @Post('chat') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Send chat completion request' }) @ApiResponse({ status: 200, description: 'Chat response', type: ChatResponseDto }) @ApiResponse({ status: 400, description: 'Bad request or AI disabled' }) async chat( @CurrentUser() user: RequestUser, @Body() dto: ChatRequestDto, ): Promise<ChatResponseDto> { return this.aiService.chat(user.tenant_id, user.id, dto); } // ==================== Models ==================== @Get('models') @ApiOperation({ summary: 'List available AI models' }) @ApiResponse({ status: 200, description: 'List of models', type: [AIModelDto] }) async getModels(): Promise<AIModelDto[]> { return this.aiService.getModels(); } // ==================== Configuration ==================== @Get('config') @ApiOperation({ summary: 'Get AI configuration for tenant' }) @ApiResponse({ status: 200, description: 'AI configuration', type: AIConfigResponseDto }) async getConfig(@CurrentUser() user: RequestUser): Promise<AIConfigResponseDto> { const config = await this.aiService.getConfig(user.tenant_id); return config as AIConfigResponseDto; } @Patch('config') @ApiOperation({ summary: 'Update AI configuration' }) @ApiResponse({ status: 200, description: 'Updated configuration', type: AIConfigResponseDto }) async updateConfig( @CurrentUser() user: RequestUser, @Body() dto: UpdateAIConfigDto, ): Promise<AIConfigResponseDto> { const config = await this.aiService.updateConfig(user.tenant_id, dto); return config as AIConfigResponseDto; } // ==================== Usage ==================== @Get('usage') @ApiOperation({ summary: 'Get usage history' }) @ApiQuery({ name: 'page', required: false, type: Number }) @ApiQuery({ name: 'limit', required: false, type: Number }) async getUsage( @CurrentUser() user: RequestUser, @Query('page') page = 1, @Query('limit') limit = 20, ) { return this.aiService.getUsageHistory(user.tenant_id, page, limit); } @Get('usage/current') @ApiOperation({ summary: 'Get current month usage stats' }) @ApiResponse({ status: 200, description: 'Usage statistics', type: UsageStatsDto }) async getCurrentUsage(@CurrentUser() user: RequestUser): Promise<UsageStatsDto> { return this.aiService.getCurrentMonthUsage(user.tenant_id); } // ==================== Health ==================== @Get('health') @ApiOperation({ summary: 'Check AI service health' }) async health() { return { status: this.aiService.isServiceReady() ? 'ready' : 'not_configured', timestamp: new Date().toISOString(), }; } } |