feat(ai): add mcp integration (#13004)
This commit is contained in:
@ -1,251 +1,170 @@
|
||||
import gql from 'graphql-tag';
|
||||
import { AGENT_GQL_FIELDS } from 'test/integration/constants/agent-gql-fields.constants';
|
||||
import { createAgentOperation } from 'test/integration/graphql/utils/create-agent-operation-factory.util';
|
||||
import { deleteAgentOperation } from 'test/integration/graphql/utils/delete-agent-operation-factory.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { updateAgentOperation } from 'test/integration/graphql/utils/update-agent-operation-factory.util';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { AgentService } from 'src/engine/metadata-modules/agent/agent.service';
|
||||
import { AgentResolver } from 'src/engine/metadata-modules/agent/agent.resolver';
|
||||
import {
|
||||
AgentException,
|
||||
AgentExceptionCode,
|
||||
} from 'src/engine/metadata-modules/agent/agent.exception';
|
||||
|
||||
// Mock the agent service
|
||||
jest.mock('../../../../../src/engine/metadata-modules/agent/agent.service');
|
||||
|
||||
// Mock the guards and decorators
|
||||
jest.mock('../../../../../src/engine/guards/feature-flag.guard', () => ({
|
||||
FeatureFlagGuard: jest.fn().mockImplementation(() => ({
|
||||
canActivate: jest.fn().mockReturnValue(true),
|
||||
})),
|
||||
RequireFeatureFlag: () => jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../src/engine/guards/workspace-auth.guard', () => ({
|
||||
WorkspaceAuthGuard: jest.fn().mockImplementation(() => ({
|
||||
canActivate: jest.fn().mockReturnValue(true),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('agentResolver', () => {
|
||||
describe('createOneAgent', () => {
|
||||
it('should create an agent successfully', async () => {
|
||||
const operation = createAgentOperation({
|
||||
name: 'Test AI Agent Admin',
|
||||
description: 'A test AI agent created by admin',
|
||||
prompt: 'You are a helpful AI assistant for testing.',
|
||||
modelId: 'gpt-4o',
|
||||
responseFormat: { type: 'json_object' },
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
let agentService: AgentService;
|
||||
let agentResolver: AgentResolver;
|
||||
let module: TestingModule;
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.createOneAgent).toBeDefined();
|
||||
expect(response.body.data.createOneAgent.id).toBeDefined();
|
||||
expect(response.body.data.createOneAgent.name).toBe(
|
||||
'Test AI Agent Admin',
|
||||
);
|
||||
expect(response.body.data.createOneAgent.description).toBe(
|
||||
'A test AI agent created by admin',
|
||||
);
|
||||
expect(response.body.data.createOneAgent.prompt).toBe(
|
||||
'You are a helpful AI assistant for testing.',
|
||||
);
|
||||
expect(response.body.data.createOneAgent.modelId).toBe('gpt-4o');
|
||||
expect(response.body.data.createOneAgent.responseFormat).toEqual({
|
||||
type: 'json_object',
|
||||
});
|
||||
await makeGraphqlAPIRequest(
|
||||
deleteAgentOperation(response.body.data.createOneAgent.id),
|
||||
);
|
||||
});
|
||||
beforeAll(async () => {
|
||||
// Create a testing module with mocked dependencies
|
||||
module = await Test.createTestingModule({
|
||||
providers: [
|
||||
AgentResolver,
|
||||
{
|
||||
provide: AgentService,
|
||||
useValue: {
|
||||
findOneAgent: jest.fn(),
|
||||
updateOneAgent: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
it('should validate required fields and return error', async () => {
|
||||
const operation = createAgentOperation({
|
||||
name: undefined as any,
|
||||
description: 'Agent without required fields',
|
||||
prompt: undefined as any,
|
||||
modelId: undefined as any,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
expect(response.body.errors).toBeDefined();
|
||||
expect(response.body.errors[0].message).toContain(
|
||||
'Field "name" of required type "String!" was not provided',
|
||||
);
|
||||
});
|
||||
// Get the mocked services from the module
|
||||
agentService = module.get<AgentService>(AgentService);
|
||||
agentResolver = module.get<AgentResolver>(AgentResolver);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (module) {
|
||||
await module.close();
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('findOneAgent', () => {
|
||||
let testAgentId: string;
|
||||
const testAgentId = 'test-agent-id';
|
||||
const workspaceId = 'test-workspace-id';
|
||||
const mockAgent = {
|
||||
id: testAgentId,
|
||||
name: 'Test Agent for Find',
|
||||
description: 'A test agent for find operations',
|
||||
prompt: 'You are a test agent for finding.',
|
||||
modelId: 'gpt-4o',
|
||||
roleId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
const operation = createAgentOperation({
|
||||
name: 'Test Agent for Find',
|
||||
description: 'A test agent for find operations',
|
||||
prompt: 'You are a test agent for finding.',
|
||||
modelId: 'gpt-4o',
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
testAgentId = response.body.data.createOneAgent.id;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await makeGraphqlAPIRequest(deleteAgentOperation(testAgentId));
|
||||
});
|
||||
it('should find agent by ID successfully', async () => {
|
||||
const queryData = {
|
||||
query: gql`
|
||||
query FindOneAgent($input: AgentIdInput!) {
|
||||
findOneAgent(input: $input) {
|
||||
${AGENT_GQL_FIELDS}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { input: { id: testAgentId } },
|
||||
};
|
||||
const response = await makeGraphqlAPIRequest(queryData);
|
||||
// Mock the findOneAgent method to return a mock agent
|
||||
(agentService.findOneAgent as jest.Mock).mockResolvedValueOnce(mockAgent);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.errors).toBeUndefined();
|
||||
expect(response.body.data.findOneAgent).toBeDefined();
|
||||
expect(response.body.data.findOneAgent.id).toBe(testAgentId);
|
||||
expect(response.body.data.findOneAgent.name).toBe('Test Agent for Find');
|
||||
});
|
||||
it('should return 404 error for non-existent agent', async () => {
|
||||
const nonExistentId = '00000000-0000-0000-0000-000000000000';
|
||||
const queryData = {
|
||||
query: gql`
|
||||
query FindOneAgent($input: AgentIdInput!) {
|
||||
findOneAgent(input: $input) {
|
||||
${AGENT_GQL_FIELDS}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { input: { id: nonExistentId } },
|
||||
};
|
||||
const response = await makeGraphqlAPIRequest(queryData);
|
||||
// Call the resolver directly
|
||||
const result = await agentResolver.findOneAgent({ id: testAgentId }, {
|
||||
id: workspaceId,
|
||||
} as any);
|
||||
|
||||
expect(response.body.errors).toBeDefined();
|
||||
expect(response.body.errors[0].message).toContain('not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('findManyAgents', () => {
|
||||
const testAgentIds: string[] = [];
|
||||
|
||||
beforeAll(async () => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const operation = createAgentOperation({
|
||||
name: `Test Agent ${i + 1}`,
|
||||
description: `A test agent ${i + 1} for find many operations`,
|
||||
prompt: `You are test agent ${i + 1}.`,
|
||||
modelId: 'gpt-4o',
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
testAgentIds.push(response.body.data.createOneAgent.id);
|
||||
}
|
||||
});
|
||||
afterAll(async () => {
|
||||
for (const agentId of testAgentIds) {
|
||||
await makeGraphqlAPIRequest(deleteAgentOperation(agentId));
|
||||
}
|
||||
});
|
||||
it('should find all agents successfully', async () => {
|
||||
const queryData = {
|
||||
query: gql`
|
||||
query FindManyAgents {
|
||||
findManyAgents {
|
||||
${AGENT_GQL_FIELDS}
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
const response = await makeGraphqlAPIRequest(queryData);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.errors).toBeUndefined();
|
||||
expect(response.body.data.findManyAgents).toBeDefined();
|
||||
expect(Array.isArray(response.body.data.findManyAgents)).toBe(true);
|
||||
expect(response.body.data.findManyAgents.length).toBeGreaterThanOrEqual(
|
||||
3,
|
||||
// Verify the service was called with the correct parameters
|
||||
expect(agentService.findOneAgent).toHaveBeenCalledWith(
|
||||
testAgentId,
|
||||
workspaceId,
|
||||
);
|
||||
const testAgentNames = response.body.data.findManyAgents
|
||||
.filter((agent: any) => testAgentIds.includes(agent.id))
|
||||
.map((agent: any) => agent.name);
|
||||
|
||||
expect(testAgentNames).toContain('Test Agent 1');
|
||||
expect(testAgentNames).toContain('Test Agent 2');
|
||||
expect(testAgentNames).toContain('Test Agent 3');
|
||||
// Verify the result matches our expectations
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe(testAgentId);
|
||||
expect(result.name).toBe('Test Agent for Find');
|
||||
});
|
||||
|
||||
it('should throw an error for non-existent agent', async () => {
|
||||
const nonExistentId = '00000000-0000-0000-0000-000000000000';
|
||||
|
||||
// Mock the findOneAgent method to throw an exception
|
||||
(agentService.findOneAgent as jest.Mock).mockRejectedValueOnce(
|
||||
new AgentException(
|
||||
`Agent with id ${nonExistentId} not found`,
|
||||
AgentExceptionCode.AGENT_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
|
||||
// Call the resolver and expect it to throw
|
||||
await expect(
|
||||
agentResolver.findOneAgent({ id: nonExistentId }, {
|
||||
id: workspaceId,
|
||||
} as any),
|
||||
).rejects.toThrow(AgentException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateOneAgent', () => {
|
||||
let testAgentId: string;
|
||||
const testAgentId = 'test-agent-id';
|
||||
const workspaceId = 'test-workspace-id';
|
||||
|
||||
beforeAll(async () => {
|
||||
const operation = createAgentOperation({
|
||||
name: 'Original Test Agent',
|
||||
description: 'Original description',
|
||||
prompt: 'Original prompt',
|
||||
modelId: 'gpt-4o',
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
const updatedAgent = {
|
||||
id: testAgentId,
|
||||
name: 'Updated Test Agent Admin',
|
||||
description: 'Updated description',
|
||||
prompt: 'Updated prompt for admin',
|
||||
modelId: 'gpt-4o-mini',
|
||||
roleId: null,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
testAgentId = response.body.data.createOneAgent.id;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await makeGraphqlAPIRequest(deleteAgentOperation(testAgentId));
|
||||
});
|
||||
it('should update an agent successfully', async () => {
|
||||
const operation = updateAgentOperation({
|
||||
id: testAgentId,
|
||||
name: 'Updated Test Agent Admin',
|
||||
description: 'Updated description',
|
||||
prompt: 'Updated prompt for admin',
|
||||
modelId: 'gpt-4o-mini',
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.updateOneAgent).toBeDefined();
|
||||
expect(response.body.data.updateOneAgent.id).toBe(testAgentId);
|
||||
expect(response.body.data.updateOneAgent.name).toBe(
|
||||
'Updated Test Agent Admin',
|
||||
// Mock the updateOneAgent method to return the updated agent
|
||||
(agentService.updateOneAgent as jest.Mock).mockResolvedValueOnce(
|
||||
updatedAgent,
|
||||
);
|
||||
expect(response.body.data.updateOneAgent.description).toBe(
|
||||
'Updated description',
|
||||
|
||||
// Call the resolver directly
|
||||
const result = await agentResolver.updateOneAgent(
|
||||
{
|
||||
id: testAgentId,
|
||||
name: 'Updated Test Agent Admin',
|
||||
description: 'Updated description',
|
||||
prompt: 'Updated prompt for admin',
|
||||
modelId: 'gpt-4o-mini',
|
||||
},
|
||||
{ id: workspaceId } as any,
|
||||
);
|
||||
expect(response.body.data.updateOneAgent.prompt).toBe(
|
||||
'Updated prompt for admin',
|
||||
|
||||
// Verify the service was called with the correct parameters
|
||||
expect(agentService.updateOneAgent).toHaveBeenCalledWith(
|
||||
{
|
||||
id: testAgentId,
|
||||
name: 'Updated Test Agent Admin',
|
||||
description: 'Updated description',
|
||||
prompt: 'Updated prompt for admin',
|
||||
modelId: 'gpt-4o-mini',
|
||||
},
|
||||
workspaceId,
|
||||
);
|
||||
expect(response.body.data.updateOneAgent.modelId).toBe('gpt-4o-mini');
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteOneAgent', () => {
|
||||
let testAgentId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const operation = createAgentOperation({
|
||||
name: 'Agent to Delete',
|
||||
description: 'This agent will be deleted',
|
||||
prompt: 'You are an agent that will be deleted.',
|
||||
modelId: 'gpt-4o',
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
testAgentId = response.body.data.createOneAgent.id;
|
||||
});
|
||||
it('should delete an agent successfully', async () => {
|
||||
const operation = deleteAgentOperation(testAgentId);
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.deleteOneAgent).toBeDefined();
|
||||
expect(response.body.data.deleteOneAgent.id).toBe(testAgentId);
|
||||
expect(response.body.data.deleteOneAgent.name).toBe('Agent to Delete');
|
||||
const findQueryData = {
|
||||
query: gql`
|
||||
query FindOneAgent($input: AgentIdInput!) {
|
||||
findOneAgent(input: $input) {
|
||||
${AGENT_GQL_FIELDS}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { input: { id: testAgentId } },
|
||||
};
|
||||
const findResponse = await makeGraphqlAPIRequest(findQueryData);
|
||||
|
||||
expect(findResponse.body.errors).toBeDefined();
|
||||
expect(findResponse.body.errors[0].message).toContain('not found');
|
||||
});
|
||||
it('should return 404 error for non-existent agent', async () => {
|
||||
const nonExistentId = '00000000-0000-0000-0000-000000000000';
|
||||
const operation = deleteAgentOperation(nonExistentId);
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
expect(response.body.errors).toBeDefined();
|
||||
expect(response.body.errors[0].message).toContain('not found');
|
||||
// Verify the result matches our expectations
|
||||
expect(result).toBeDefined();
|
||||
expect(result.id).toBe(testAgentId);
|
||||
expect(result.name).toBe('Updated Test Agent Admin');
|
||||
expect(result.description).toBe('Updated description');
|
||||
expect(result.prompt).toBe('Updated prompt for admin');
|
||||
expect(result.modelId).toBe('gpt-4o-mini');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const updateFeatureFlagFactory = (
|
||||
workspaceId: string,
|
||||
featureFlag: string,
|
||||
value: boolean,
|
||||
) => ({
|
||||
query: gql`
|
||||
mutation UpdateWorkspaceFeatureFlag(
|
||||
$workspaceId: String!
|
||||
$featureFlag: String!
|
||||
$value: Boolean!
|
||||
) {
|
||||
updateWorkspaceFeatureFlag(
|
||||
workspaceId: $workspaceId
|
||||
featureFlag: $featureFlag
|
||||
value: $value
|
||||
)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
workspaceId,
|
||||
featureFlag,
|
||||
value,
|
||||
},
|
||||
});
|
||||
@ -62,15 +62,13 @@ describe('AgentToolService Integration', () => {
|
||||
);
|
||||
|
||||
expect(tools).toBeDefined();
|
||||
expect(Object.keys(tools)).toHaveLength(8);
|
||||
expect(Object.keys(tools)).toHaveLength(6);
|
||||
expect(Object.keys(tools)).toContain('create_testObject');
|
||||
expect(Object.keys(tools)).toContain('update_testObject');
|
||||
expect(Object.keys(tools)).toContain('find_testObject');
|
||||
expect(Object.keys(tools)).toContain('find_one_testObject');
|
||||
expect(Object.keys(tools)).toContain('soft_delete_testObject');
|
||||
expect(Object.keys(tools)).toContain('soft_delete_many_testObject');
|
||||
expect(Object.keys(tools)).toContain('destroy_testObject');
|
||||
expect(Object.keys(tools)).toContain('destroy_many_testObject');
|
||||
});
|
||||
|
||||
it('should generate read-only tools for agent with read permissions only', async () => {
|
||||
@ -646,156 +644,6 @@ describe('AgentToolService Integration', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Destroy Operations', () => {
|
||||
it('should destroy a single record', async () => {
|
||||
const roleWithDestroyPermission = {
|
||||
...context.testRole,
|
||||
canDestroyAllObjectRecords: true,
|
||||
};
|
||||
const mockRepository = createMockRepository();
|
||||
const existingRecord = createTestRecord('test-record-id', {
|
||||
name: 'Test Record',
|
||||
});
|
||||
|
||||
jest
|
||||
.spyOn(context.agentService, 'findOneAgent')
|
||||
.mockResolvedValue(context.testAgent as any);
|
||||
jest
|
||||
.spyOn(context.roleRepository, 'findOne')
|
||||
.mockResolvedValue(roleWithDestroyPermission);
|
||||
jest
|
||||
.spyOn(
|
||||
context.workspacePermissionsCacheService,
|
||||
'getRolesPermissionsFromCache',
|
||||
)
|
||||
.mockResolvedValue({
|
||||
data: {
|
||||
[context.testRoleId]: {
|
||||
[context.testObjectMetadata.id]: {
|
||||
canRead: true,
|
||||
canUpdate: true,
|
||||
canSoftDelete: true,
|
||||
canDestroy: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
version: '1.0',
|
||||
});
|
||||
jest
|
||||
.spyOn(context.objectMetadataService, 'findManyWithinWorkspace')
|
||||
.mockResolvedValue([context.testObjectMetadata]);
|
||||
|
||||
setupRepositoryMock(context, mockRepository);
|
||||
mockRepository.findOne.mockResolvedValue(existingRecord);
|
||||
mockRepository.remove.mockResolvedValue(existingRecord);
|
||||
|
||||
const tools = await context.agentToolService.generateToolsForAgent(
|
||||
context.testAgentId,
|
||||
context.testWorkspaceId,
|
||||
);
|
||||
const destroyTool = tools['destroy_testObject'];
|
||||
|
||||
expect(destroyTool).toBeDefined();
|
||||
|
||||
if (!destroyTool.execute) {
|
||||
throw new Error(
|
||||
'Destroy tool is missing or does not have an execute method',
|
||||
);
|
||||
}
|
||||
|
||||
const result = await destroyTool.execute(
|
||||
{ id: 'test-record-id' },
|
||||
{
|
||||
toolCallId: 'test-tool-call-id',
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Destroy record',
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
expectSuccessResult(result, 'Successfully destroyed testObject');
|
||||
expect(mockRepository.remove).toHaveBeenCalledWith(existingRecord);
|
||||
});
|
||||
|
||||
it('should destroy multiple records', async () => {
|
||||
const roleWithDestroyPermission = {
|
||||
...context.testRole,
|
||||
canDestroyAllObjectRecords: true,
|
||||
};
|
||||
const mockRepository = createMockRepository();
|
||||
const existingRecords = createTestRecords(3);
|
||||
|
||||
jest
|
||||
.spyOn(context.agentService, 'findOneAgent')
|
||||
.mockResolvedValue(context.testAgent as any);
|
||||
jest
|
||||
.spyOn(context.roleRepository, 'findOne')
|
||||
.mockResolvedValue(roleWithDestroyPermission);
|
||||
jest
|
||||
.spyOn(
|
||||
context.workspacePermissionsCacheService,
|
||||
'getRolesPermissionsFromCache',
|
||||
)
|
||||
.mockResolvedValue({
|
||||
data: {
|
||||
[context.testRoleId]: {
|
||||
[context.testObjectMetadata.id]: {
|
||||
canRead: true,
|
||||
canUpdate: true,
|
||||
canSoftDelete: true,
|
||||
canDestroy: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
version: '1.0',
|
||||
});
|
||||
jest
|
||||
.spyOn(context.objectMetadataService, 'findManyWithinWorkspace')
|
||||
.mockResolvedValue([context.testObjectMetadata]);
|
||||
|
||||
setupRepositoryMock(context, mockRepository);
|
||||
mockRepository.find.mockResolvedValue(existingRecords);
|
||||
mockRepository.remove.mockResolvedValue(existingRecords);
|
||||
|
||||
const tools = await context.agentToolService.generateToolsForAgent(
|
||||
context.testAgentId,
|
||||
context.testWorkspaceId,
|
||||
);
|
||||
const destroyManyTool = tools['destroy_many_testObject'];
|
||||
|
||||
expect(destroyManyTool).toBeDefined();
|
||||
|
||||
if (!destroyManyTool.execute) {
|
||||
throw new Error(
|
||||
'Destroy many tool is missing or does not have an execute method',
|
||||
);
|
||||
}
|
||||
|
||||
const result = await destroyManyTool.execute(
|
||||
{
|
||||
filter: { id: { in: ['record-1', 'record-2', 'record-3'] } },
|
||||
},
|
||||
{
|
||||
toolCallId: 'test-tool-call-id',
|
||||
messages: [
|
||||
{
|
||||
role: 'user',
|
||||
content: 'Destroy many records',
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
expectSuccessResult(
|
||||
result,
|
||||
'Successfully destroyed 3 testObject records',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle empty search criteria in find records', async () => {
|
||||
const mockRepository = createMockRepository();
|
||||
|
||||
@ -12,6 +12,7 @@ import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
import { ToolService } from 'src/engine/core-modules/ai/services/tool.service';
|
||||
|
||||
export interface AgentToolTestContext {
|
||||
module: TestingModule;
|
||||
@ -77,6 +78,10 @@ export const createAgentToolTestModule =
|
||||
getRolesPermissionsFromCache: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: ToolService,
|
||||
useClass: ToolService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user