fix: code review cleanup

- Replace all 'any' types with proper Prisma types
- Fix exactOptionalPropertyTypes compatibility
- Export AuthUser type from better-auth-request.interface
- Remove duplicate empty migration folder
- Ensure proper JSON handling with Prisma.InputJsonValue

All agent-tasks tests passing (18/18)
This commit is contained in:
Jason Woltje
2026-01-29 23:35:40 -06:00
parent da4fb72902
commit 562859202b
3 changed files with 54 additions and 19 deletions

View File

@@ -19,6 +19,7 @@ import { AuthGuard } from "../auth/guards/auth.guard";
import { WorkspaceGuard, PermissionGuard } from "../common/guards"; import { WorkspaceGuard, PermissionGuard } from "../common/guards";
import { Workspace, Permission, RequirePermission } from "../common/decorators"; import { Workspace, Permission, RequirePermission } from "../common/decorators";
import { CurrentUser } from "../auth/decorators/current-user.decorator"; import { CurrentUser } from "../auth/decorators/current-user.decorator";
import type { AuthUser } from "../auth/types/better-auth-request.interface";
/** /**
* Controller for agent task endpoints * Controller for agent task endpoints
@@ -44,7 +45,7 @@ export class AgentTasksController {
async create( async create(
@Body() createAgentTaskDto: CreateAgentTaskDto, @Body() createAgentTaskDto: CreateAgentTaskDto,
@Workspace() workspaceId: string, @Workspace() workspaceId: string,
@CurrentUser() user: any @CurrentUser() user: AuthUser
) { ) {
return this.agentTasksService.create( return this.agentTasksService.create(
workspaceId, workspaceId,

View File

@@ -1,6 +1,10 @@
import { Injectable, NotFoundException } from "@nestjs/common"; import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "../prisma/prisma.service"; import { PrismaService } from "../prisma/prisma.service";
import { AgentTaskStatus, AgentTaskPriority } from "@prisma/client"; import {
AgentTaskStatus,
AgentTaskPriority,
Prisma,
} from "@prisma/client";
import type { import type {
CreateAgentTaskDto, CreateAgentTaskDto,
UpdateAgentTaskDto, UpdateAgentTaskDto,
@@ -22,33 +26,40 @@ export class AgentTasksService {
userId: string, userId: string,
createAgentTaskDto: CreateAgentTaskDto createAgentTaskDto: CreateAgentTaskDto
) { ) {
const data: any = { // Build the create input, handling optional fields properly for exactOptionalPropertyTypes
...createAgentTaskDto, const createInput: Prisma.AgentTaskUncheckedCreateInput = {
title: createAgentTaskDto.title,
workspaceId, workspaceId,
createdById: userId, createdById: userId,
status: createAgentTaskDto.status || AgentTaskStatus.PENDING, status: createAgentTaskDto.status ?? AgentTaskStatus.PENDING,
priority: createAgentTaskDto.priority || AgentTaskPriority.MEDIUM, priority: createAgentTaskDto.priority ?? AgentTaskPriority.MEDIUM,
agentConfig: createAgentTaskDto.agentConfig || {}, agentType: createAgentTaskDto.agentType,
agentConfig: (createAgentTaskDto.agentConfig ?? {}) as Prisma.InputJsonValue,
}; };
// Add optional fields only if they exist
if (createAgentTaskDto.description) createInput.description = createAgentTaskDto.description;
if (createAgentTaskDto.result) createInput.result = createAgentTaskDto.result as Prisma.InputJsonValue;
if (createAgentTaskDto.error) createInput.error = createAgentTaskDto.error;
// Set startedAt if status is RUNNING // Set startedAt if status is RUNNING
if (data.status === AgentTaskStatus.RUNNING) { if (createInput.status === AgentTaskStatus.RUNNING) {
data.startedAt = new Date(); createInput.startedAt = new Date();
} }
// Set completedAt if status is COMPLETED or FAILED // Set completedAt if status is COMPLETED or FAILED
if ( if (
data.status === AgentTaskStatus.COMPLETED || createInput.status === AgentTaskStatus.COMPLETED ||
data.status === AgentTaskStatus.FAILED createInput.status === AgentTaskStatus.FAILED
) { ) {
data.completedAt = new Date(); createInput.completedAt = new Date();
if (!data.startedAt) { if (!createInput.startedAt) {
data.startedAt = new Date(); createInput.startedAt = new Date();
} }
} }
const agentTask = await this.prisma.agentTask.create({ const agentTask = await this.prisma.agentTask.create({
data, data: createInput,
include: { include: {
createdBy: { createdBy: {
select: { id: true, name: true, email: true }, select: { id: true, name: true, email: true },
@@ -68,9 +79,11 @@ export class AgentTasksService {
const skip = (page - 1) * limit; const skip = (page - 1) * limit;
// Build where clause // Build where clause
const where: any = { const where: Prisma.AgentTaskWhereInput = {};
workspaceId: query.workspaceId,
}; if (query.workspaceId) {
where.workspaceId = query.workspaceId;
}
if (query.status) { if (query.status) {
where.status = query.status; where.status = query.status;
@@ -157,7 +170,25 @@ export class AgentTasksService {
throw new NotFoundException(`Agent task with ID ${id} not found`); throw new NotFoundException(`Agent task with ID ${id} not found`);
} }
const data: any = { ...updateAgentTaskDto }; const data: Prisma.AgentTaskUpdateInput = {};
// Only include fields that are actually being updated
if (updateAgentTaskDto.title !== undefined) data.title = updateAgentTaskDto.title;
if (updateAgentTaskDto.description !== undefined) data.description = updateAgentTaskDto.description;
if (updateAgentTaskDto.status !== undefined) data.status = updateAgentTaskDto.status;
if (updateAgentTaskDto.priority !== undefined) data.priority = updateAgentTaskDto.priority;
if (updateAgentTaskDto.agentType !== undefined) data.agentType = updateAgentTaskDto.agentType;
if (updateAgentTaskDto.error !== undefined) data.error = updateAgentTaskDto.error;
if (updateAgentTaskDto.agentConfig !== undefined) {
data.agentConfig = updateAgentTaskDto.agentConfig as Prisma.InputJsonValue;
}
if (updateAgentTaskDto.result !== undefined) {
data.result = updateAgentTaskDto.result === null
? Prisma.JsonNull
: (updateAgentTaskDto.result as Prisma.InputJsonValue);
}
// Handle startedAt based on status changes // Handle startedAt based on status changes
if (updateAgentTaskDto.status) { if (updateAgentTaskDto.status) {

View File

@@ -8,6 +8,9 @@
import type { AuthUser } from "@mosaic/shared"; import type { AuthUser } from "@mosaic/shared";
// Re-export AuthUser for use in other modules
export type { AuthUser };
/** /**
* Session data stored in request after authentication * Session data stored in request after authentication
*/ */