feat: agent roleUniversalIdentifier for manifest-driven role assignment (#23206)
## Summary - Adds optional `roleUniversalIdentifier` on `AgentManifest` / `defineAgent` so apps can declaratively assign a role to an agent (same config shape as `defaultRoleUniversalIdentifier`). - Wires `agentUniversalIdentifier` as a sync many-to-one FK on `roleTarget`, and emits a deterministic `roleTarget` from the agent during app sync (create / update / delete). - Enables app agents (e.g. Slack assistant) to get a role on install without postInstall hooks or manual admin assignment. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23206?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+29
-17
@@ -7,6 +7,7 @@ import { IsNull, Not, Repository } from 'typeorm';
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
|
||||
import { FlatRoleTargetByAgentIdMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-role-target-by-agent-id-maps.type';
|
||||
import { fromRoleTargetEntityToFlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/utils/from-role-target-entity-to-flat-role-target.util';
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
@@ -26,6 +27,8 @@ export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvi
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
@InjectWorkspaceScopedRepository(RoleEntity)
|
||||
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
|
||||
@InjectWorkspaceScopedRepository(AgentEntity)
|
||||
private readonly agentRepository: WorkspaceScopedRepository<AgentEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -33,28 +36,36 @@ export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvi
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<FlatRoleTargetByAgentIdMaps> {
|
||||
const [roleTargetEntities, applications, roles] = await Promise.all([
|
||||
this.roleTargetRepository.find(workspaceId, {
|
||||
where: {
|
||||
agentId: Not(IsNull()),
|
||||
},
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.roleRepository.find(workspaceId, {
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
]);
|
||||
const [roleTargetEntities, applications, roles, agents] = await Promise.all(
|
||||
[
|
||||
this.roleTargetRepository.find(workspaceId, {
|
||||
where: {
|
||||
agentId: Not(IsNull()),
|
||||
},
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.roleRepository.find(workspaceId, {
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.agentRepository.find(workspaceId, {
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
const applicationIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(applications);
|
||||
const roleIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(roles);
|
||||
const agentIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(agents);
|
||||
|
||||
const flatRoleTargetByAgentIdMaps: FlatRoleTargetByAgentIdMaps = {};
|
||||
|
||||
@@ -66,6 +77,7 @@ export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvi
|
||||
entity: roleTargetEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
roleIdToUniversalIdentifierMap,
|
||||
agentIdToUniversalIdentifierMap,
|
||||
});
|
||||
|
||||
flatRoleTargetByAgentIdMaps[roleTargetEntity.agentId] = flatRoleTarget;
|
||||
|
||||
Reference in New Issue
Block a user