Feat: role applicability controls (#14239)

Closes [#1404](https://github.com/twentyhq/core-team-issues/issues/1404)

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
Abdul Rahman
2025-09-04 08:58:50 +05:30
committed by GitHub
parent 052f91cff1
commit 79bcd90d8d
72 changed files with 1889 additions and 344 deletions
@@ -49,6 +49,7 @@ export class AgentToolGeneratorService {
id: roleId,
workspaceId,
},
relations: ['permissionFlags'],
});
if (!role) {
@@ -9,4 +9,5 @@ export enum AgentExceptionCode {
USER_WORKSPACE_ID_NOT_FOUND = 'USER_WORKSPACE_ID_NOT_FOUND',
ROLE_NOT_FOUND = 'ROLE_NOT_FOUND',
HANDOFF_ALREADY_EXISTS = 'HANDOFF_ALREADY_EXISTS',
ROLE_CANNOT_BE_ASSIGNED_TO_AGENTS = 'ROLE_CANNOT_BE_ASSIGNED_TO_AGENTS',
}
@@ -38,10 +38,7 @@ export class AgentResolver {
@Query(() => [AgentDTO])
@RequireFeatureFlag(FeatureFlagKey.IS_AI_ENABLED)
async findManyAgents(@AuthWorkspace() { id: workspaceId }: Workspace) {
return this.agentRepository.find({
where: { workspaceId },
order: { createdAt: 'DESC' },
});
return this.agentService.findManyAgents(workspaceId);
}
@Query(() => AgentDTO)
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { In, Repository } from 'typeorm';
import { AgentRoleService } from 'src/engine/metadata-modules/agent-role/agent-role.service';
import { type CreateAgentInput } from 'src/engine/metadata-modules/agent/dtos/create-agent.input';
@@ -23,6 +23,37 @@ export class AgentService {
private readonly agentRoleService: AgentRoleService,
) {}
async findManyAgents(workspaceId: string) {
const agents = await this.agentRepository.find({
where: { workspaceId },
order: { createdAt: 'DESC' },
});
if (agents.length === 0) {
return [];
}
const roleTargets = await this.roleTargetsRepository.find({
where: {
workspaceId,
agentId: In(agents.map((agent) => agent.id)),
},
});
const agentRoleMap = new Map<string, string>();
roleTargets.forEach((roleTarget) => {
if (roleTarget.agentId) {
agentRoleMap.set(roleTarget.agentId, roleTarget.roleId);
}
});
return agents.map((agent) => ({
...agent,
roleId: agentRoleMap.get(agent.id) || null,
}));
}
async findOneAgent(id: string, workspaceId: string) {
const agent = await this.agentRepository.findOne({
where: { id, workspaceId },