Files
twenty/packages/twenty-front/src/modules/settings/components/SettingsListItemCardContent.tsx
T
Félix Malfait 4f20fd35c5 feat: Add Agent Evaluation System and Refactor AI Modules (#16111)
## Summary

This PR introduces a comprehensive agent evaluation system and refactors
the AI module structure for better organization.

## Key Changes

### 🎯 Agent Evaluation System
- Added **Agent Turn Evaluation** entities, DTOs, and database schema
- New GraphQL mutations: `evaluateAgentTurn` and `runEvaluationInput`
- Added `evaluationInputs` field to Agent entity for storing test inputs
- New `AgentTurnGraderService` for automatic turn evaluation
- Added evaluation UI with new **Evals** and **Logs** tabs in agent
detail pages

### 🏗️ Entity & Module Refactoring
- Renamed `AgentChatMessage` → `AgentMessage` for clarity
- Consolidated chat entities: `AgentMessage`, `AgentTurn`, and
`AgentChatThread`
- Reorganized AI modules under `ai/` subdirectory structure
- Updated imports across codebase to reflect new module paths

### 🤖 New Agents & Roles
- Added **Dashboard Builder Agent** for dashboard creation and
management
- Added **Dashboard Manager Role** with appropriate permissions
- Updated role permissions to be more granular (users vs agents vs API
keys)

### 🔐 Permission System Updates
- Added `HTTP_REQUEST_TOOL` permission flag
- Updated Workflow Manager role permissions (restricted tool access)
- Enhanced permission flag types to differentiate between user/agent/API
key contexts
- Added `isRelevantForAgents`, `isRelevantForApiKeys`,
`isRelevantForUsers` to permission flags

### 📨 Message Role Enhancement
- Added `system` role to `AgentMessageRole` enum (alongside
user/assistant)
- Updated message handling to support system prompts

### 🎨 UI/UX Improvements
- New tabs in agent detail: **Evals** and **Logs**
- Added turn detail page: `/ai/agents/:agentId/turns/:turnId`
- Fixed text overflow in `SettingsListItemCardContent`
- Updated role applicability labels ("Assignable to Workspace Members")

### 🛠️ Technical Improvements
- Fixed Zod schema validation for UUID and Date fields (use string
validators)
- Updated `ToolRegistryService` to properly register HTTP tool with
permission flag
- Enhanced error handling in agent execution services
- Updated database migrations for new entity schema

## Database Migrations
- `1764210000000-add-system-role-to-agent-message.ts`
- `1764220000000-add-evaluation-inputs-to-agent.ts`
- `1764200000000-add-agent-turn-evaluation.ts`
- `1764100000000-refactor-agent-chat-entities.ts`

## Testing
- [ ] Agent evaluation flow tested
- [ ] Dashboard Builder agent tested
- [ ] Permission system validated
- [ ] UI tabs and navigation tested
- [ ] Database migrations run successfully

## Breaking Changes
⚠️ **Entity Rename**: `AgentChatMessage` renamed to `AgentMessage` -
GraphQL queries need updating

## Related Issues
<!-- Link any related issues here -->

## Screenshots
<!-- Add screenshots if applicable -->
2025-11-27 08:25:40 +01:00

113 lines
2.9 KiB
TypeScript

import isPropValid from '@emotion/is-prop-valid';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { type ReactNode } from 'react';
import { Link } from 'react-router-dom';
import { isDefined } from 'twenty-shared/utils';
import { IconChevronRight, type IconComponent } from 'twenty-ui/display';
import { CardContent } from 'twenty-ui/layout';
const StyledRow = styled(CardContent, {
shouldForwardProp: (prop) => prop !== 'to' && isPropValid(prop),
})<{ to?: boolean }>`
align-items: center;
cursor: ${({ onClick, to }) => (onClick || to ? 'pointer' : 'default')};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};
padding-left: ${({ theme }) => theme.spacing(3)};
min-height: ${({ theme }) => theme.spacing(6)};
&:hover {
${({ to, theme }) =>
to && `background: ${theme.background.transparent.light};`}
}
`;
const StyledRightContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
`;
const StyledContent = styled.div`
flex: 1 1 0;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
min-width: 0;
overflow: hidden;
`;
const StyledLabel = styled.span`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledDescription = styled.span`
color: ${({ theme }) => theme.font.color.light};
font-weight: ${({ theme }) => theme.font.weight.regular};
padding-left: ${({ theme }) => theme.spacing(1)};
`;
const StyledLink = styled(Link)`
color: ${({ theme }) => theme.font.color.secondary};
text-decoration: none;
`;
type SettingsListItemCardContentProps = {
label: string;
description?: string;
divider?: boolean;
LeftIcon?: IconComponent;
LeftIconColor?: string;
onClick?: () => void;
rightComponent: ReactNode;
to?: string;
};
export const SettingsListItemCardContent = ({
label,
description,
divider,
LeftIcon,
LeftIconColor,
onClick,
rightComponent,
to,
}: SettingsListItemCardContentProps) => {
const theme = useTheme();
const content = (
<StyledRow onClick={onClick} divider={divider} to={!!to}>
{!!LeftIcon && (
<LeftIcon
size={theme.icon.size.md}
color={LeftIconColor ?? 'currentColor'}
/>
)}
<StyledContent>
<StyledLabel>{label}</StyledLabel>
{!!description && <StyledDescription>{description}</StyledDescription>}
</StyledContent>
<StyledRightContainer>
{rightComponent}
{!!to && (
<IconChevronRight
size={theme.icon.size.md}
color={theme.font.color.tertiary}
/>
)}
</StyledRightContainer>
</StyledRow>
);
if (isDefined(to)) {
return <StyledLink to={to}>{content}</StyledLink>;
}
return content;
};