snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,295 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Agent creation should fail when computed name already exists 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "AGENT_ALREADY_EXISTS",
"message": "Agent with name "existingTestAgent" already exists",
"userFriendlyMessage": "An agent with this name already exists",
},
],
"flatEntityMinimalInformation": {
"name": "existingTestAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "An agent with this name already exists",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when label is empty string 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Label cannot be empty",
"userFriendlyMessage": "Label cannot be empty",
},
],
"flatEntityMinimalInformation": {
"name": "",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Label cannot be empty",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when label is missing 1`] = `
{
"extensions": {
"code": "BAD_USER_INPUT",
"http": {
"status": 400,
},
"userFriendlyMessage": "An error occurred.",
},
"message": "Field "label" of required type "String!" was not provided.",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when modelId is empty string 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Model ID cannot be empty",
"userFriendlyMessage": "Model ID cannot be empty",
},
],
"flatEntityMinimalInformation": {
"name": "emptyModelidAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Model ID cannot be empty",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when modelId is missing 1`] = `
{
"extensions": {
"code": "BAD_USER_INPUT",
"http": {
"status": 400,
},
"userFriendlyMessage": "An error occurred.",
},
"message": "Field "modelId" of required type "String!" was not provided.",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when prompt is empty string 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Prompt cannot be empty",
"userFriendlyMessage": "Prompt cannot be empty",
},
],
"flatEntityMinimalInformation": {
"name": "emptyPromptAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Prompt cannot be empty",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when prompt is missing 1`] = `
{
"extensions": {
"code": "BAD_USER_INPUT",
"http": {
"status": 400,
},
"userFriendlyMessage": "An error occurred.",
},
"message": "Field "prompt" of required type "String!" was not provided.",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when responseFormat has invalid type 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format type must be either "text" or "json"",
"userFriendlyMessage": "Invalid response format type",
},
],
"flatEntityMinimalInformation": {
"name": "invalidResponseFormatAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Invalid response format type",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when responseFormat type is json but schema is missing 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format with type "json" must include a schema",
"userFriendlyMessage": "JSON response format requires a schema",
},
],
"flatEntityMinimalInformation": {
"name": "jsonWithoutSchemaAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "JSON response format requires a schema",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;
exports[`Agent creation should fail when responseFormat type is text but schema is present 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format with type "text" should not include a schema",
"userFriendlyMessage": "Text response format should not have a schema",
},
],
"flatEntityMinimalInformation": {
"name": "textWithSchemaAgent",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "create",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Text response format should not have a schema",
},
"message": "Multiple validation errors occurred while creating agent",
"name": "GraphQLError",
}
`;

View File

@@ -0,0 +1,49 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Agent deletion should fail should fail when attempting to delete a standard agent 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "AGENT_IS_STANDARD",
"message": "Cannot delete standard agent",
"userFriendlyMessage": "Cannot delete standard agent",
},
],
"flatEntityMinimalInformation": {
"name": "helper",
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "delete",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Cannot delete standard agent",
},
"message": "Multiple validation errors occurred while deleting agent",
"name": "GraphQLError",
}
`;
exports[`Agent deletion should fail when deleting a non-existent agent 1`] = `
{
"extensions": {
"code": "NOT_FOUND",
"subCode": "AGENT_NOT_FOUND",
"userFriendlyMessage": "Agent not found.",
},
"message": "Could not retrieve deleted agent",
"name": "NotFoundError",
}
`;

View File

@@ -0,0 +1,338 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Agent update should fail should fail when attempting to update a standard agent 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "AGENT_IS_STANDARD",
"message": "Cannot update standard agent",
"userFriendlyMessage": "Cannot update standard agent",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Cannot update standard agent",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail should fail when updating a non-existent agent 1`] = `
{
"extensions": {
"code": "NOT_FOUND",
"subCode": "AGENT_NOT_FOUND",
"userFriendlyMessage": "The agent you are looking for could not be found. It may have been deleted or you may not have access to it.",
},
"message": "Agent not found",
"name": "NotFoundError",
}
`;
exports[`Agent update should fail when settings null required properties 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Label cannot be empty",
"userFriendlyMessage": "Label cannot be empty",
},
{
"code": "INVALID_AGENT_INPUT",
"message": "Prompt cannot be empty",
"userFriendlyMessage": "Prompt cannot be empty",
},
{
"code": "INVALID_AGENT_INPUT",
"message": "Model ID cannot be empty",
"userFriendlyMessage": "Model ID cannot be empty",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Label cannot be empty",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating label to one that already exists 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "AGENT_ALREADY_EXISTS",
"message": "Agent with name "existingAgentForDuplicateTest" already exists",
"userFriendlyMessage": "An agent with this name already exists",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "An agent with this name already exists",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating responseFormat type to json without schema 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format with type "json" must include a schema",
"userFriendlyMessage": "JSON response format requires a schema",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "JSON response format requires a schema",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating responseFormat type to text with schema 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format with type "text" should not include a schema",
"userFriendlyMessage": "Text response format should not have a schema",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Text response format should not have a schema",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating responseFormat with invalid type 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Response format type must be either "text" or "json"",
"userFriendlyMessage": "Invalid response format type",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Invalid response format type",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating with empty label 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Label cannot be empty",
"userFriendlyMessage": "Label cannot be empty",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Label cannot be empty",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating with empty modelId 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Model ID cannot be empty",
"userFriendlyMessage": "Model ID cannot be empty",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Model ID cannot be empty",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;
exports[`Agent update should fail when updating with empty prompt 1`] = `
{
"extensions": {
"code": "METADATA_VALIDATION_FAILED",
"errors": {
"agent": [
{
"errors": [
{
"code": "INVALID_AGENT_INPUT",
"message": "Prompt cannot be empty",
"userFriendlyMessage": "Prompt cannot be empty",
},
],
"flatEntityMinimalInformation": {
"universalIdentifier": Any<String>,
},
"metadataName": "agent",
"status": "fail",
"type": "update",
},
],
},
"message": "Validation failed for 1 agent",
"summary": {
"agent": 1,
"totalErrors": 1,
},
"userFriendlyMessage": "Prompt cannot be empty",
},
"message": "Multiple validation errors occurred while updating agent",
"name": "GraphQLError",
}
`;

View File

@@ -0,0 +1,175 @@
import { TEST_AI_MODEL_ID } from 'test/integration/constants/test-ai-model-ids.constants';
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import {
eachTestingContextFilter,
type EachTestingContext,
} from 'twenty-shared/testing';
import { isDefined } from 'twenty-shared/utils';
import { type CreateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/create-agent.input';
type TestContext = {
input: CreateAgentInput;
};
type GlobalTestContext = {
existingAgentLabel: string;
};
const globalTestContext: GlobalTestContext = {
existingAgentLabel: 'Existing Test Agent',
};
type CreateOneAgentTestingContext = EachTestingContext<TestContext>[];
describe('Agent creation should fail', () => {
let existingAgentId: string | undefined;
beforeAll(async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: globalTestContext.existingAgentLabel,
prompt: 'Existing agent for testing',
modelId: TEST_AI_MODEL_ID,
},
});
existingAgentId = data.createOneAgent.id;
});
afterAll(async () => {
if (isDefined(existingAgentId)) {
await deleteOneAgent({
expectToFail: false,
input: { id: existingAgentId },
});
}
});
const failingAgentCreationTestCases: CreateOneAgentTestingContext = [
{
title: 'when label is missing',
context: {
input: {
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
} as CreateAgentInput,
},
},
{
title: 'when prompt is missing',
context: {
input: {
label: 'Test Agent Missing Prompt',
modelId: TEST_AI_MODEL_ID,
} as CreateAgentInput,
},
},
{
title: 'when modelId is missing',
context: {
input: {
label: 'Test Agent Missing ModelId',
prompt: 'Test prompt',
} as CreateAgentInput,
},
},
{
title: 'when label is empty string',
context: {
input: {
label: '',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
},
},
},
{
title: 'when prompt is empty string',
context: {
input: {
label: 'Empty Prompt Agent',
prompt: '',
modelId: TEST_AI_MODEL_ID,
},
},
},
{
title: 'when modelId is empty string',
context: {
input: {
label: 'Empty ModelId Agent',
prompt: 'Test prompt',
modelId: '' as any,
},
},
},
{
title: 'when computed name already exists',
context: {
input: {
label: globalTestContext.existingAgentLabel,
prompt: 'Duplicate agent',
modelId: TEST_AI_MODEL_ID,
},
},
},
{
title: 'when responseFormat has invalid type',
context: {
input: {
label: 'Invalid Response Format Agent',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
responseFormat: {
type: 'invalid',
} as any,
},
},
},
{
title: 'when responseFormat type is json but schema is missing',
context: {
input: {
label: 'JSON Without Schema Agent',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
responseFormat: {
type: 'json',
} as any,
},
},
},
{
title: 'when responseFormat type is text but schema is present',
context: {
input: {
label: 'Text With Schema Agent',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
responseFormat: {
type: 'text',
schema: { type: 'object' },
} as any,
},
},
},
];
it.each(eachTestingContextFilter(failingAgentCreationTestCases))(
'$title',
async ({ context }) => {
const { errors } = await createOneAgent({
expectToFail: true,
input: context.input,
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
},
);
});

View File

@@ -0,0 +1,68 @@
import { faker } from '@faker-js/faker';
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { findAgents } from 'test/integration/metadata/suites/agent/utils/find-agents.util';
import {
eachTestingContextFilter,
type EachTestingContext,
} from 'twenty-shared/testing';
type TestContext = {
input: () => {
id: string;
};
};
type DeleteOneAgentTestingContext = EachTestingContext<TestContext>[];
describe('Agent deletion should fail', () => {
const failingAgentDeletionTestCases: DeleteOneAgentTestingContext = [
{
title: 'when deleting a non-existent agent',
context: {
input: () => ({
id: faker.string.uuid(),
}),
},
},
];
it.each(eachTestingContextFilter(failingAgentDeletionTestCases))(
'$title',
async ({ context }) => {
const { id } = context.input();
const { errors } = await deleteOneAgent({
expectToFail: true,
input: {
id,
},
});
expectOneNotInternalServerErrorSnapshot({ errors });
},
);
it('should fail when attempting to delete a standard agent', async () => {
const { data } = await findAgents({
expectToFail: false,
input: undefined,
gqlFields: 'id name isCustom',
});
const helperAgent = data.findManyAgents.find(
(agent) => agent.name === 'helper' && agent.isCustom === false,
);
expect(helperAgent).toBeDefined();
const { errors } = await deleteOneAgent({
expectToFail: true,
input: {
id: helperAgent!.id,
},
});
expectOneNotInternalServerErrorSnapshot({ errors });
});
});

View File

@@ -0,0 +1,227 @@
import { TEST_AI_MODEL_ID } from 'test/integration/constants/test-ai-model-ids.constants';
import { faker } from '@faker-js/faker';
import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { findAgents } from 'test/integration/metadata/suites/agent/utils/find-agents.util';
import { updateOneAgent } from 'test/integration/metadata/suites/agent/utils/update-one-agent.util';
import {
eachTestingContextFilter,
type EachTestingContext,
} from 'twenty-shared/testing';
import { type UpdateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/update-agent.input';
type TestContext = {
input: (testSetup: TestSetup) => UpdateAgentInput;
};
type TestSetup = {
testAgentId: string;
existingAgentLabelForDuplicate: string;
};
type GlobalTestContext = {
existingAgentLabelForDuplicate: string;
};
const globalTestContext: GlobalTestContext = {
existingAgentLabelForDuplicate: 'Existing Agent For Duplicate Test',
};
type UpdateOneAgentTestingContext = EachTestingContext<TestContext>[];
describe('Agent update should fail', () => {
let testAgentId: string;
let existingAgentIdForDuplicate: string;
beforeAll(async () => {
const { data: duplicateData } = await createOneAgent({
expectToFail: false,
input: {
label: globalTestContext.existingAgentLabelForDuplicate,
prompt: 'Existing agent for duplicate test',
modelId: TEST_AI_MODEL_ID,
},
});
existingAgentIdForDuplicate = duplicateData.createOneAgent.id;
});
beforeEach(async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'Test Agent To Update',
description: 'Original description',
icon: 'IconRobot',
prompt: 'Original prompt',
modelId: TEST_AI_MODEL_ID,
},
});
testAgentId = data.createOneAgent.id;
});
afterEach(async () => {
await deleteOneAgent({
expectToFail: false,
input: { id: testAgentId },
});
});
afterAll(async () => {
await deleteOneAgent({
expectToFail: false,
input: { id: existingAgentIdForDuplicate },
});
});
const failingAgentUpdateTestCases: UpdateOneAgentTestingContext = [
{
title: 'when updating label to one that already exists',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
label: testSetup.existingAgentLabelForDuplicate,
}),
},
},
{
title: 'when updating with empty label',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
label: '',
}),
},
},
{
title: 'when updating with empty prompt',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
prompt: '',
}),
},
},
{
title: 'when updating with empty modelId',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
modelId: '' as any,
}),
},
},
{
title: 'when settings null required properties',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
label: null,
prompt: null,
modelId: null,
}),
},
},
{
title: 'when updating responseFormat with invalid type',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
responseFormat: {
type: 'invalid',
} as any,
}),
},
},
{
title: 'when updating responseFormat type to json without schema',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
responseFormat: {
type: 'json',
} as any,
}),
},
},
{
title: 'when updating responseFormat type to text with schema',
context: {
input: (testSetup) => ({
id: testSetup.testAgentId,
responseFormat: {
type: 'text',
schema: { type: 'object' },
} as any,
}),
},
},
];
it.each(eachTestingContextFilter(failingAgentUpdateTestCases))(
'$title',
async ({ context }) => {
const testSetup: TestSetup = {
testAgentId,
existingAgentLabelForDuplicate:
globalTestContext.existingAgentLabelForDuplicate,
};
const input = context.input(testSetup);
const { errors } = await updateOneAgent({
expectToFail: true,
input,
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
},
);
it('should fail when updating a non-existent agent', async () => {
const nonExistentAgentId = faker.string.uuid();
const { errors } = await updateOneAgent({
expectToFail: true,
input: {
id: nonExistentAgentId,
label: 'Updated Label',
},
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
});
it('should fail when attempting to update a standard agent', async () => {
const { data } = await findAgents({
expectToFail: false,
input: undefined,
gqlFields: 'id name isCustom',
});
const helperAgent = data.findManyAgents.find(
(agent) => agent.name === 'helper' && agent.isCustom === false,
);
expect(helperAgent).toBeDefined();
const { errors } = await updateOneAgent({
expectToFail: true,
input: {
id: helperAgent!.id,
label: 'Attempted Update to Standard Agent',
},
});
expectOneNotInternalServerErrorSnapshot({
errors,
});
});
});

View File

@@ -0,0 +1,227 @@
import {
TEST_AI_MODEL_ID,
TEST_AI_OTHER_MODEL_ID,
} from 'test/integration/constants/test-ai-model-ids.constants';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { createOneRole } from 'test/integration/metadata/suites/role/utils/create-one-role.util';
import { deleteOneRole } from 'test/integration/metadata/suites/role/utils/delete-one-role.util';
import { type CreateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/create-agent.input';
describe('Agent creation should succeed', () => {
let createdAgentId: string;
afterEach(async () => {
if (createdAgentId) {
await deleteOneAgent({
expectToFail: false,
input: { id: createdAgentId },
});
}
});
it('should create a basic custom agent with minimal input', async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'Test Agent',
prompt: 'You are a helpful test assistant',
modelId: TEST_AI_MODEL_ID,
},
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
name: 'testAgent',
label: 'Test Agent',
icon: null,
description: null,
prompt: 'You are a helpful test assistant',
modelId: TEST_AI_MODEL_ID,
responseFormat: { type: 'text' },
roleId: null,
isCustom: true,
modelConfiguration: null,
evaluationInputs: [],
});
});
it('should create agent with all optional fields', async () => {
const input = {
name: 'customAgentName',
label: 'Custom Agent Label',
icon: 'IconRobot',
description: 'A custom agent with all fields specified',
prompt: 'You are a specialized assistant for testing',
modelId: TEST_AI_OTHER_MODEL_ID,
responseFormat: { type: 'text' },
modelConfiguration: {
webSearch: {
enabled: true,
configuration: {
maxTokens: 1000,
temperature: 0.7,
},
},
twitterSearch: {
enabled: true,
configuration: {},
},
},
evaluationInputs: ['test input 1', 'test input 2'],
} as const satisfies CreateAgentInput;
const { data } = await createOneAgent({
expectToFail: false,
input,
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
...input,
});
});
it('should create agent with JSON response format', async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'JSON Response Agent',
prompt: 'Return structured JSON data',
modelId: TEST_AI_MODEL_ID,
responseFormat: {
type: 'json',
schema: {
type: 'object',
properties: {
result: { type: 'string' },
confidence: { type: 'number' },
},
},
},
},
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
label: 'JSON Response Agent',
prompt: 'Return structured JSON data',
responseFormat: {
type: 'json',
schema: {
type: 'object',
properties: {
result: { type: 'string' },
confidence: { type: 'number' },
},
},
},
});
});
it('should create agent and automatically compute name from label', async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'My Test Agent With Spaces',
prompt: 'Testing name computation',
modelId: TEST_AI_MODEL_ID,
},
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
name: 'myTestAgentWithSpaces',
label: 'My Test Agent With Spaces',
});
});
it('should sanitize input by trimming whitespace', async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
name: ' agentWithSpaces ',
label: ' Agent With Spaces ',
icon: ' IconRobot ',
description: ' Description with spaces ',
prompt: ' Prompt with spaces ',
modelId: TEST_AI_MODEL_ID,
},
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
name: 'agentWithSpaces',
label: 'Agent With Spaces',
icon: 'IconRobot',
description: 'Description with spaces',
prompt: 'Prompt with spaces',
});
});
it('should create agent with role assignment', async () => {
const { data: roleData } = await createOneRole({
expectToFail: false,
input: {
label: 'Test Agent Role',
description: 'A role for agent testing',
canUpdateAllSettings: false,
canAccessAllTools: true,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canBeAssignedToUsers: false,
canBeAssignedToAgents: true,
canBeAssignedToApiKeys: false,
},
});
const createdRoleId = roleData?.createOneRole?.id;
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'Agent With Role',
prompt: 'Agent with role assignment',
modelId: TEST_AI_MODEL_ID,
roleId: createdRoleId,
},
});
createdAgentId = data?.createOneAgent?.id;
expect(data.createOneAgent).toMatchObject({
id: expect.any(String),
label: 'Agent With Role',
prompt: 'Agent with role assignment',
modelId: TEST_AI_MODEL_ID,
roleId: createdRoleId,
isCustom: true,
});
// Delete the agent first so its role_target is removed; otherwise
// deleting the role would refuse to orphan the agent (the workspace
// default role isn't agent-assignable).
await deleteOneAgent({
expectToFail: false,
input: { id: createdAgentId },
});
createdAgentId = '';
await deleteOneRole({
expectToFail: false,
input: { idToDelete: createdRoleId },
});
});
});

View File

@@ -0,0 +1,42 @@
import { TEST_AI_MODEL_ID } from 'test/integration/constants/test-ai-model-ids.constants';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { findOneAgent } from 'test/integration/metadata/suites/agent/utils/find-one-agent.util';
describe('Agent deletion should succeed', () => {
it('should successfully delete a custom agent', async () => {
const { data: createData } = await createOneAgent({
expectToFail: false,
input: {
label: 'Agent To Delete',
prompt: 'This agent will be deleted',
modelId: TEST_AI_MODEL_ID,
},
});
const agentId = createData.createOneAgent.id;
const { data: findBeforeData } = await findOneAgent({
expectToFail: false,
input: { id: agentId },
});
expect(findBeforeData.findOneAgent.id).toBe(agentId);
const { data: deleteData } = await deleteOneAgent({
expectToFail: false,
input: { id: agentId },
});
expect(deleteData.deleteOneAgent).toMatchObject({
id: agentId,
});
const { errors: findAfterErrors } = await findOneAgent({
expectToFail: true,
input: { id: agentId },
});
expect(findAfterErrors).toBeDefined();
});
});

View File

@@ -0,0 +1,160 @@
import { TEST_AI_MODEL_ID } from 'test/integration/constants/test-ai-model-ids.constants';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { updateOneAgent } from 'test/integration/metadata/suites/agent/utils/update-one-agent.util';
import { createOneRole } from 'test/integration/metadata/suites/role/utils/create-one-role.util';
import { deleteOneRole } from 'test/integration/metadata/suites/role/utils/delete-one-role.util';
describe('Agent role update should succeed', () => {
let testAgentId: string;
let testRoleId: string;
let secondTestRoleId: string;
beforeAll(async () => {
const { data: role1Data } = await createOneRole({
expectToFail: false,
input: {
label: 'Test Agent Role 1',
description: 'First test role for agent assignment',
canUpdateAllSettings: false,
canAccessAllTools: true,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canBeAssignedToUsers: false,
canBeAssignedToAgents: true,
canBeAssignedToApiKeys: false,
},
});
const { data: role2Data } = await createOneRole({
expectToFail: false,
input: {
label: 'Test Agent Role 2',
description: 'Second test role for agent assignment',
canUpdateAllSettings: false,
canAccessAllTools: false,
canReadAllObjectRecords: true,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canBeAssignedToUsers: false,
canBeAssignedToAgents: true,
canBeAssignedToApiKeys: false,
},
});
testRoleId = role1Data.createOneRole.id;
secondTestRoleId = role2Data.createOneRole.id;
});
afterAll(async () => {
await deleteOneRole({
expectToFail: false,
input: { idToDelete: testRoleId },
});
await deleteOneRole({
expectToFail: false,
input: { idToDelete: secondTestRoleId },
});
});
afterEach(async () => {
if (testAgentId) {
await deleteOneAgent({
expectToFail: false,
input: { id: testAgentId },
});
}
});
it('should add a role to an agent that does not have one initially', async () => {
const { data: createData } = await createOneAgent({
expectToFail: false,
input: {
label: 'Agent Without Role',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
},
});
testAgentId = createData.createOneAgent.id;
expect(createData.createOneAgent.roleId).toBeNull();
const { data: updateData } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
roleId: testRoleId,
},
});
expect(updateData.updateOneAgent).toMatchObject({
id: testAgentId,
roleId: testRoleId,
label: 'Agent Without Role',
});
});
it('should change the role of an agent that already has one', async () => {
const { data: createData } = await createOneAgent({
expectToFail: false,
input: {
label: 'Agent With Initial Role',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
roleId: testRoleId,
},
});
testAgentId = createData.createOneAgent.id;
expect(createData.createOneAgent.roleId).toBe(testRoleId);
const { data: updateData } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
roleId: secondTestRoleId,
},
});
expect(updateData.updateOneAgent).toMatchObject({
id: testAgentId,
roleId: secondTestRoleId,
label: 'Agent With Initial Role',
});
});
it('should remove a role from an agent that already has one', async () => {
const { data: createData } = await createOneAgent({
expectToFail: false,
input: {
label: 'Agent With Role To Remove',
prompt: 'Test prompt',
modelId: TEST_AI_MODEL_ID,
roleId: testRoleId,
},
});
testAgentId = createData.createOneAgent.id;
expect(createData.createOneAgent.roleId).toBe(testRoleId);
const { data: updateData } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
roleId: null,
},
});
expect(updateData.updateOneAgent).toMatchObject({
id: testAgentId,
roleId: null,
label: 'Agent With Role To Remove',
});
});
});

View File

@@ -0,0 +1,311 @@
import {
TEST_AI_MODEL_ID,
TEST_AI_OTHER_MODEL_ID,
} from 'test/integration/constants/test-ai-model-ids.constants';
import { DEFAULT_TOOL_INPUT_SCHEMA } from 'twenty-shared/logic-function';
import { type AgentResponseSchema } from 'twenty-shared/ai';
import { createOneAgent } from 'test/integration/metadata/suites/agent/utils/create-one-agent.util';
import { deleteOneAgent } from 'test/integration/metadata/suites/agent/utils/delete-one-agent.util';
import { updateOneAgent } from 'test/integration/metadata/suites/agent/utils/update-one-agent.util';
describe('Agent update should succeed', () => {
let testAgentId: string;
beforeEach(async () => {
const { data } = await createOneAgent({
expectToFail: false,
input: {
label: 'Original Agent Label',
description: 'Original description',
icon: 'IconRobot',
prompt: 'Original prompt',
modelId: TEST_AI_MODEL_ID,
responseFormat: { type: 'text' },
evaluationInputs: ['input 1'],
},
});
testAgentId = data.createOneAgent.id;
});
afterEach(async () => {
await deleteOneAgent({
expectToFail: false,
input: { id: testAgentId },
});
});
it('should update agent label', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
label: 'Updated Agent Label',
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
label: 'Updated Agent Label',
description: 'Original description',
icon: 'IconRobot',
prompt: 'Original prompt',
});
});
it('should update agent description', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
description: 'Updated description for the agent',
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
label: 'Original Agent Label',
description: 'Updated description for the agent',
});
});
it('should update agent icon', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
icon: 'IconSparkles',
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
icon: 'IconSparkles',
});
});
it('should update agent prompt', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
prompt: 'Updated prompt with new instructions',
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
prompt: 'Updated prompt with new instructions',
});
});
it('should update agent modelId', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
modelId: TEST_AI_OTHER_MODEL_ID,
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
modelId: TEST_AI_OTHER_MODEL_ID,
});
});
it('should update agent responseFormat from text to json', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
responseFormat: {
type: 'json',
schema: {
type: 'object',
properties: {
answer: { type: 'string' },
confidence: { type: 'number' },
},
},
},
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
responseFormat: {
type: 'json',
schema: {
type: 'object',
properties: {
answer: { type: 'string' },
confidence: { type: 'number' },
},
},
},
});
});
it('should update agent responseFormat from json to text', async () => {
await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
responseFormat: {
type: 'json',
schema: DEFAULT_TOOL_INPUT_SCHEMA as AgentResponseSchema,
},
},
});
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
responseFormat: { type: 'text' },
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
responseFormat: { type: 'text' },
});
});
it('should update agent modelConfiguration', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
modelConfiguration: {
twitterSearch: {
enabled: true,
configuration: {
temperature: 0.9,
maxTokens: 2000,
topP: 0.95,
},
},
},
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
modelConfiguration: {
twitterSearch: {
enabled: true,
configuration: {
temperature: 0.9,
maxTokens: 2000,
topP: 0.95,
},
},
},
});
});
it('should update agent evaluationInputs', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
evaluationInputs: ['new input 1', 'new input 2', 'new input 3'],
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
evaluationInputs: ['new input 1', 'new input 2', 'new input 3'],
});
});
it('should update multiple agent properties at once', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
label: 'Comprehensive Update',
description: 'Updated multiple fields',
icon: 'IconBrain',
prompt: 'New comprehensive prompt',
modelId: TEST_AI_OTHER_MODEL_ID,
responseFormat: {
type: 'json',
schema: DEFAULT_TOOL_INPUT_SCHEMA as AgentResponseSchema,
},
evaluationInputs: ['eval 1', 'eval 2'],
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
label: 'Comprehensive Update',
description: 'Updated multiple fields',
icon: 'IconBrain',
prompt: 'New comprehensive prompt',
modelId: TEST_AI_OTHER_MODEL_ID,
responseFormat: {
type: 'json',
schema: { type: 'object' },
},
evaluationInputs: ['eval 1', 'eval 2'],
});
});
it('should sanitize input by trimming whitespace', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
label: ' Updated Label With Spaces ',
icon: ' IconRobot ',
description: ' Description with spaces ',
prompt: ' Prompt with spaces ',
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
label: 'Updated Label With Spaces',
icon: 'IconRobot',
description: 'Description with spaces',
prompt: 'Prompt with spaces',
});
});
it('should clear optional fields by setting to null', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
icon: null,
description: null,
modelConfiguration: null,
} as any,
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
icon: null,
description: null,
modelConfiguration: null,
});
});
it('should clear evaluationInputs by setting to empty array', async () => {
const { data } = await updateOneAgent({
expectToFail: false,
input: {
id: testAgentId,
evaluationInputs: [],
},
});
expect(data.updateOneAgent).toMatchObject({
id: testAgentId,
evaluationInputs: [],
});
});
});

View File

@@ -0,0 +1,40 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { type CreateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/create-agent.input';
export type CreateOneAgentFactoryInput = CreateAgentInput;
const DEFAULT_AGENT_GQL_FIELDS = `
id
name
label
icon
description
prompt
modelId
responseFormat
roleId
isCustom
applicationId
modelConfiguration
evaluationInputs
createdAt
updatedAt
`;
export const createOneAgentQueryFactory = ({
input,
gqlFields = DEFAULT_AGENT_GQL_FIELDS,
}: PerformMetadataQueryParams<CreateOneAgentFactoryInput>) => ({
query: gql`
mutation CreateOneAgent($input: CreateAgentInput!) {
createOneAgent(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});

View File

@@ -0,0 +1,43 @@
import {
type CreateOneAgentFactoryInput,
createOneAgentQueryFactory,
} from 'test/integration/metadata/suites/agent/utils/create-one-agent-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type AgentDTO } from 'src/engine/metadata-modules/ai/ai-agent/dtos/agent.dto';
export const createOneAgent = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<CreateOneAgentFactoryInput>): CommonResponseBody<{
createOneAgent: AgentDTO;
}> => {
const graphqlOperation = createOneAgentQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Agent creation should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Agent creation has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@@ -0,0 +1,23 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
export type DeleteOneAgentFactoryInput = {
id: string;
};
export const deleteOneAgentQueryFactory = ({
input,
}: PerformMetadataQueryParams<DeleteOneAgentFactoryInput>) => ({
query: gql`
mutation DeleteOneAgent($input: AgentIdInput!) {
deleteOneAgent(input: $input) {
id
}
}
`,
variables: {
input: {
id: input.id,
},
},
});

View File

@@ -0,0 +1,41 @@
import {
type DeleteOneAgentFactoryInput,
deleteOneAgentQueryFactory,
} from 'test/integration/metadata/suites/agent/utils/delete-one-agent-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
export const deleteOneAgent = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<DeleteOneAgentFactoryInput>): CommonResponseBody<{
deleteOneAgent: { id: string };
}> => {
const graphqlOperation = deleteOneAgentQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Agent deletion should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Agent deletion has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@@ -0,0 +1,32 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
const DEFAULT_AGENT_GQL_FIELDS = `
id
name
label
icon
description
prompt
modelId
responseFormat
roleId
isCustom
applicationId
modelConfiguration
evaluationInputs
createdAt
updatedAt
`;
export const findAgentsQueryFactory = ({
gqlFields = DEFAULT_AGENT_GQL_FIELDS,
}: PerformMetadataQueryParams<void>) => ({
query: gql`
query findManyAgents {
findManyAgents {
${gqlFields}
}
}
`,
});

View File

@@ -0,0 +1,39 @@
import { findAgentsQueryFactory } from 'test/integration/metadata/suites/agent/utils/find-agents-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type AgentDTO } from 'src/engine/metadata-modules/ai/ai-agent/dtos/agent.dto';
export const findAgents = async ({
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<undefined>): CommonResponseBody<{
findManyAgents: AgentDTO[];
}> => {
const graphqlOperation = findAgentsQueryFactory({
gqlFields,
input: undefined,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Finding agents should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Finding agents has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@@ -0,0 +1,42 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
export type FindOneAgentFactoryInput = {
id: string;
};
const DEFAULT_AGENT_GQL_FIELDS = `
id
name
label
icon
description
prompt
modelId
responseFormat
roleId
isCustom
applicationId
modelConfiguration
evaluationInputs
createdAt
updatedAt
`;
export const findOneAgentQueryFactory = ({
input,
gqlFields = DEFAULT_AGENT_GQL_FIELDS,
}: PerformMetadataQueryParams<FindOneAgentFactoryInput>) => ({
query: gql`
query FindOneAgent($input: AgentIdInput!) {
findOneAgent(input: $input) {
${gqlFields}
}
}
`,
variables: {
input: {
id: input.id,
},
},
});

View File

@@ -0,0 +1,43 @@
import {
type FindOneAgentFactoryInput,
findOneAgentQueryFactory,
} from 'test/integration/metadata/suites/agent/utils/find-one-agent-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type AgentDTO } from 'src/engine/metadata-modules/ai/ai-agent/dtos/agent.dto';
export const findOneAgent = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<FindOneAgentFactoryInput>): CommonResponseBody<{
findOneAgent: AgentDTO;
}> => {
const graphqlOperation = findOneAgentQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Finding agent should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Finding agent has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@@ -0,0 +1,40 @@
import gql from 'graphql-tag';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { type UpdateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/update-agent.input';
export type UpdateOneAgentFactoryInput = UpdateAgentInput;
const DEFAULT_AGENT_GQL_FIELDS = `
id
name
label
icon
description
prompt
modelId
responseFormat
roleId
isCustom
applicationId
modelConfiguration
evaluationInputs
createdAt
updatedAt
`;
export const updateOneAgentQueryFactory = ({
gqlFields = DEFAULT_AGENT_GQL_FIELDS,
input,
}: PerformMetadataQueryParams<UpdateOneAgentFactoryInput>) => ({
query: gql`
mutation UpdateOneAgent($input: UpdateAgentInput!) {
updateOneAgent(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});

View File

@@ -0,0 +1,43 @@
import {
type UpdateOneAgentFactoryInput,
updateOneAgentQueryFactory,
} from 'test/integration/metadata/suites/agent/utils/update-one-agent-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
import { type AgentDTO } from 'src/engine/metadata-modules/ai/ai-agent/dtos/agent.dto';
export const updateOneAgent = async ({
input,
gqlFields,
expectToFail = false,
token,
}: PerformMetadataQueryParams<UpdateOneAgentFactoryInput>): CommonResponseBody<{
updateOneAgent: AgentDTO;
}> => {
const graphqlOperation = updateOneAgentQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation, token);
if (expectToFail === true) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Agent update should have failed but did not',
});
}
if (expectToFail === false) {
warnIfErrorButNotExpectedToFail({
response,
errorMessage: 'Agent update has failed but should not',
});
}
return { data: response.body.data, errors: response.body.errors };
};