@@ -11,6 +11,13 @@ import {
1111 BadRequestException ,
1212 NotFoundException ,
1313} from '@nestjs/common' ;
14+ import {
15+ ApiTags ,
16+ ApiOperation ,
17+ ApiResponse ,
18+ ApiBearerAuth ,
19+ ApiBody ,
20+ } from '@nestjs/swagger' ;
1421import { AIService , AIConfig , ChatMessage } from './ai.service' ;
1522import { AuthGuard } from '../auth/auth.guard' ;
1623import { PrismaService } from '../prisma/prisma.service' ;
@@ -33,6 +40,8 @@ interface ChatDto {
3340 messages : ChatMessage [ ] ;
3441}
3542
43+ @ApiTags ( 'AI' )
44+ @ApiBearerAuth ( 'bearer' )
3645@Controller ( 'v1/ai' )
3746@UseGuards ( AuthGuard )
3847export class AIController {
@@ -45,6 +54,13 @@ export class AIController {
4554 * Get AI configuration for workspace
4655 */
4756 @Get ( 'config' )
57+ @ApiOperation ( {
58+ summary : 'Get AI configuration' ,
59+ description : 'Returns AI configuration for the workspace; the API key is masked in the response.' ,
60+ } )
61+ @ApiResponse ( { status : 200 , description : 'AI configuration (masked API key)' } )
62+ @ApiResponse ( { status : 400 , description : 'Workspace context required' } )
63+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
4864 async getConfig ( @Req ( ) req : any ) {
4965 const workspaceId = req . workspaceId ;
5066 if ( ! workspaceId ) {
@@ -65,6 +81,30 @@ export class AIController {
6581 * Update AI configuration
6682 */
6783 @Put ( 'config' )
84+ @ApiOperation ( {
85+ summary : 'Update AI configuration' ,
86+ description : 'Updates provider, model, API key, Ollama URL, and auto-analyze settings.' ,
87+ } )
88+ @ApiBody ( {
89+ schema : {
90+ type : 'object' ,
91+ required : [ 'provider' ] ,
92+ properties : {
93+ provider : {
94+ type : 'string' ,
95+ enum : [ 'ollama' , 'openai' , 'anthropic' ] ,
96+ example : 'ollama' ,
97+ } ,
98+ model : { type : 'string' } ,
99+ apiKey : { type : 'string' } ,
100+ ollamaUrl : { type : 'string' } ,
101+ autoAnalyze : { type : 'boolean' } ,
102+ } ,
103+ } ,
104+ } )
105+ @ApiResponse ( { status : 200 , description : 'Configuration updated' } )
106+ @ApiResponse ( { status : 400 , description : 'Invalid input or workspace context' } )
107+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
68108 async updateConfig (
69109 @Req ( ) req : any ,
70110 @Body ( ) body : UpdateConfigDto ,
@@ -100,6 +140,13 @@ export class AIController {
100140 * Test AI configuration
101141 */
102142 @Post ( 'test' )
143+ @ApiOperation ( {
144+ summary : 'Test AI configuration' ,
145+ description : 'Runs a simple prompt against the configured provider to verify connectivity.' ,
146+ } )
147+ @ApiResponse ( { status : 200 , description : 'Test result with success flag and response or error message' } )
148+ @ApiResponse ( { status : 400 , description : 'Workspace context or AI configuration missing' } )
149+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
103150 async testConfig ( @Req ( ) req : any ) {
104151 const workspaceId = req . workspaceId ;
105152 if ( ! workspaceId ) {
@@ -134,6 +181,24 @@ export class AIController {
134181 * Analyze traffic from a debug session
135182 */
136183 @Post ( 'analyze' )
184+ @ApiOperation ( {
185+ summary : 'Analyze debug session traffic' ,
186+ description : 'Sends recent session traffic to the AI for analysis with an optional follow-up question.' ,
187+ } )
188+ @ApiBody ( {
189+ schema : {
190+ type : 'object' ,
191+ required : [ 'sessionId' ] ,
192+ properties : {
193+ sessionId : { type : 'string' } ,
194+ question : { type : 'string' } ,
195+ } ,
196+ } ,
197+ } )
198+ @ApiResponse ( { status : 200 , description : 'Traffic analysis result' } )
199+ @ApiResponse ( { status : 400 , description : 'Invalid request, workspace mismatch, or AI not configured' } )
200+ @ApiResponse ( { status : 404 , description : 'Debug session not found' } )
201+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
137202 async analyze (
138203 @Req ( ) req : any ,
139204 @Body ( ) body : AnalyzeDto ,
@@ -210,6 +275,34 @@ export class AIController {
210275 * Chat with AI about a debug session
211276 */
212277 @Post ( 'chat' )
278+ @ApiOperation ( {
279+ summary : 'Chat about a debug session' ,
280+ description : 'Sends messages with session traffic context and returns the assistant reply.' ,
281+ } )
282+ @ApiBody ( {
283+ schema : {
284+ type : 'object' ,
285+ required : [ 'sessionId' , 'messages' ] ,
286+ properties : {
287+ sessionId : { type : 'string' } ,
288+ messages : {
289+ type : 'array' ,
290+ items : {
291+ type : 'object' ,
292+ required : [ 'role' , 'content' ] ,
293+ properties : {
294+ role : { type : 'string' , enum : [ 'user' , 'assistant' , 'system' ] } ,
295+ content : { type : 'string' } ,
296+ } ,
297+ } ,
298+ } ,
299+ } ,
300+ } ,
301+ } )
302+ @ApiResponse ( { status : 200 , description : 'Assistant message and token usage' } )
303+ @ApiResponse ( { status : 400 , description : 'Invalid request, workspace mismatch, or AI not configured' } )
304+ @ApiResponse ( { status : 404 , description : 'Debug session not found' } )
305+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
213306 async chat (
214307 @Req ( ) req : any ,
215308 @Body ( ) body : ChatDto ,
@@ -290,6 +383,14 @@ export class AIController {
290383 * Get chat history for a session
291384 */
292385 @Get ( 'sessions/:sessionId/messages' )
386+ @ApiOperation ( {
387+ summary : 'Get AI chat history' ,
388+ description : 'Returns stored AI messages for a debug session in chronological order.' ,
389+ } )
390+ @ApiResponse ( { status : 200 , description : 'List of AI messages for the session' } )
391+ @ApiResponse ( { status : 400 , description : 'Workspace context required' } )
392+ @ApiResponse ( { status : 404 , description : 'Session not found' } )
393+ @ApiResponse ( { status : 401 , description : 'Unauthorized' } )
293394 async getMessages (
294395 @Req ( ) req : any ,
295396 @Param ( 'sessionId' ) sessionId : string ,
0 commit comments