Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ workflows:
- develop
- feat/ai-workflows
- pm-1793
- pm-1794

- 'build-prod':
context: org-global
Expand Down
44 changes: 42 additions & 2 deletions src/api/ai-workflow/ai-workflow.controller.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import { Controller, Post, Body, Get, Param } from '@nestjs/common';
import {
Controller,
Post,
Body,
Get,
Param,
Patch,
ValidationPipe,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiTags,
ApiOperation,
ApiResponse,
ApiParam,
ApiBody,
} from '@nestjs/swagger';
import { AiWorkflowService } from './ai-workflow.service';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import path for AiWorkflowService has been changed from ./aiWorkflow.service to ./ai-workflow.service. Ensure that the file name has been updated accordingly in the file system to prevent import errors.

import { CreateAiWorkflowDto } from '../../dto/aiWorkflow.dto';
import {
CreateAiWorkflowDto,
UpdateAiWorkflowDto,
} from '../../dto/aiWorkflow.dto';
import { Scopes } from 'src/shared/decorators/scopes.decorator';
import { UserRole } from 'src/shared/enums/userRole.enum';
import { Scope } from 'src/shared/enums/scopes.enum';
import { Roles } from 'src/shared/guards/tokenRoles.guard';
import { User } from 'src/shared/decorators/user.decorator';
import { JwtUser } from 'src/shared/modules/global/jwt.service';

@ApiTags('ai_workflow')
@ApiBearerAuth()
Expand Down Expand Up @@ -40,4 +55,29 @@ export class AiWorkflowController {
async getById(@Param('id') id: string) {
return this.aiWorkflowService.getWorkflowById(id);
}

@Patch('/:id')
@Scopes(Scope.UpdateWorkflow)
@Roles(UserRole.Admin)
@ApiOperation({ summary: 'Update an existing AI workflow' })
@ApiParam({
name: 'id',
description: 'The ID of the AI workflow',
example: '229c5PnhSKqsSu',
})
@ApiBody({ description: 'AI workflow data', type: UpdateAiWorkflowDto })
@ApiResponse({
status: 200,
description: 'AI workflow updated successfully.',
})
@ApiResponse({ status: 403, description: 'Forbidden.' })
@ApiResponse({ status: 404, description: 'AI workflow not found.' })
async update(
@Param('id') id: string,
@Body(new ValidationPipe({ whitelist: true, transform: true }))
updateDto: UpdateAiWorkflowDto,
@User() user: JwtUser,
) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user parameter has been removed from the method signature, but it is still being used in the updateWorkflow method call. Ensure that the updateWorkflow method does not require the userId parameter anymore, or update the method implementation accordingly.

return this.aiWorkflowService.updateWorkflow(id, updateDto, user.userId);
}
}
67 changes: 64 additions & 3 deletions src/api/ai-workflow/ai-workflow.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Injectable, BadRequestException } from '@nestjs/common';
import {
Injectable,
BadRequestException,
Logger,
NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '../../shared/modules/global/prisma.service';
import { CreateAiWorkflowDto } from '../../dto/aiWorkflow.dto';
import {
CreateAiWorkflowDto,
UpdateAiWorkflowDto,
} from '../../dto/aiWorkflow.dto';
import { ScorecardStatus } from 'src/dto/scorecard.dto';

@Injectable()
export class AiWorkflowService {
private readonly logger: Logger = new Logger(AiWorkflowService.name);
constructor(private readonly prisma: PrismaService) {}

async scorecardExists(scorecardId: string): Promise<boolean> {
Expand All @@ -26,13 +35,17 @@ export class AiWorkflowService {

const scorecardExists = await this.scorecardExists(scorecardId);
if (!scorecardExists) {
this.logger.error(
`Active scorecard with id ${scorecardId} does not exist.`,
);
throw new BadRequestException(
`Scorecard with id ${scorecardId} does not exist or is not active.`,
);
}

const llmExists = await this.llmModelExists(llmId);
if (!llmExists) {
this.logger.error(`LLM model with id ${llmId} does not exist.`);
throw new BadRequestException(
`LLM model with id ${llmId} does not exist.`,
);
Expand Down Expand Up @@ -60,8 +73,56 @@ export class AiWorkflowService {
},
});
if (!workflow) {
throw new Error(`AI workflow with id ${id} not found.`);
this.logger.error(`AI workflow with id ${id} not found.`);
throw new NotFoundException(`AI workflow with id ${id} not found.`);
}
return workflow;
}

async updateWorkflow(
id: string,
updateDto: UpdateAiWorkflowDto,
updatedBy?: string,
) {
const existingWorkflow = await this.prisma.aiWorkflow.findUnique({
where: { id },
});
if (!existingWorkflow) {
this.logger.error(`AI workflow with id ${id} not found.`);
throw new NotFoundException(`AI workflow with id ${id} not found.`);
}

if (updateDto.scorecardId) {
const scorecardExists = await this.scorecardExists(updateDto.scorecardId);
if (!scorecardExists) {
this.logger.error(
`Active scorecard with id ${updateDto.scorecardId} does not exist.`,
);
throw new BadRequestException(
`Active scorecard with id ${updateDto.scorecardId} does not exist.`,
);
}
}

if (updateDto.llmId) {
const llmExists = await this.llmModelExists(updateDto.llmId);
if (!llmExists) {
this.logger.error(
`LLM model with id ${updateDto.llmId} does not exist.`,
);
throw new BadRequestException(
`LLM model with id ${updateDto.llmId} does not exist.`,
);
}
}

return this.prisma.aiWorkflow.update({
where: { id },
data: {
...updateDto,
updatedBy,
updatedAt: new Date(),
},
});
}
}
4 changes: 3 additions & 1 deletion src/dto/aiWorkflow.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApiProperty } from '@nestjs/swagger';
import { ApiProperty, PartialType } from '@nestjs/swagger';
import { IsString, IsNotEmpty } from 'class-validator';

export class CreateAiWorkflowDto {
Expand Down Expand Up @@ -42,3 +42,5 @@ export class CreateAiWorkflowDto {
@IsNotEmpty()
createdBy: string;
}

export class UpdateAiWorkflowDto extends PartialType(CreateAiWorkflowDto) {}
1 change: 1 addition & 0 deletions src/shared/enums/scopes.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export enum Scope {
// AI workflow scopes
CreateWorkflow = 'create:workflow',
ReadWorkflow = 'read:workflow',
UpdateWorkflow = 'update:workflow',
}

/**
Expand Down