Restructure agent chat messages with parts-based architecture (#14749)

Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
Abdul Rahman
2025-09-29 17:01:55 +05:30
committed by GitHub
parent 84cbd8e092
commit 2685f4a5b9
69 changed files with 1200 additions and 1539 deletions
@@ -8,6 +8,8 @@ import {
Resolver,
} from '@nestjs/graphql';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import {
ApiKeyException,
@@ -83,7 +85,7 @@ export class ApiKeyResolver {
@AuthWorkspace() workspace: Workspace,
@Args('input') input: UpdateApiKeyDTO,
): Promise<ApiKey | null> {
const updateData: Partial<ApiKey> = {};
const updateData: QueryDeepPartialEntity<ApiKey> = {};
if (input.name !== undefined) updateData.name = input.name;
if (input.expiresAt !== undefined)
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { DataSource, IsNull, Repository } from 'typeorm';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/api-key-role.service';
import { ApiKey } from 'src/engine/core-modules/api-key/api-key.entity';
@@ -78,7 +79,7 @@ export class ApiKeyService {
async update(
id: string,
workspaceId: string,
updateData: Partial<ApiKey>,
updateData: QueryDeepPartialEntity<ApiKey>,
): Promise<ApiKey | null> {
const apiKey = await this.findById(id, workspaceId);
@@ -10,6 +10,8 @@ import {
UseGuards,
} from '@nestjs/common';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { RestApiExceptionFilter } from 'src/engine/api/rest/rest-api-exception.filter';
import { type ApiKey } from 'src/engine/core-modules/api-key/api-key.entity';
import { ApiKeyService } from 'src/engine/core-modules/api-key/api-key.service';
@@ -65,7 +67,7 @@ export class ApiKeyController {
@Body() updateApiKeyDto: UpdateApiKeyDTO,
@AuthWorkspace() workspace: Workspace,
): Promise<ApiKey | null> {
const updateData: Partial<ApiKey> = {};
const updateData: QueryDeepPartialEntity<ApiKey> = {};
if (updateApiKeyDto.name !== undefined)
updateData.name = updateApiKeyDto.name;
@@ -10,6 +10,7 @@ export enum FileFolder {
ServerlessFunction = 'serverless-function',
ServerlessFunctionToDelete = 'serverless-function-to-delete',
File = 'file',
AgentChat = 'agent-chat',
}
registerEnumType(FileFolder, {
@@ -42,6 +43,9 @@ export const fileFolderConfigs: Record<FileFolder, FileFolderConfig> = {
[FileFolder.File]: {
ignoreExpirationToken: false,
},
[FileFolder.AgentChat]: {
ignoreExpirationToken: false,
},
};
export type AllowedFolders = KebabCase<keyof typeof FileFolder>;
@@ -3,15 +3,16 @@ import { InjectRepository } from '@nestjs/typeorm';
import { t } from '@lingui/core/macro';
import { Repository } from 'typeorm';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { DnsManagerService } from 'src/engine/core-modules/dns-manager/services/dns-manager.service';
import { PublicDomainDTO } from 'src/engine/core-modules/public-domain/dtos/public-domain.dto';
import { PublicDomain } from 'src/engine/core-modules/public-domain/public-domain.entity';
import {
PublicDomainException,
PublicDomainExceptionCode,
} from 'src/engine/core-modules/public-domain/public-domain.exception';
import { DnsManagerService } from 'src/engine/core-modules/dns-manager/services/dns-manager.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@Injectable()
export class PublicDomainService {
@@ -90,7 +91,9 @@ export class PublicDomainService {
});
try {
await this.publicDomainRepository.insert(publicDomain);
await this.publicDomainRepository.insert(
publicDomain as QueryDeepPartialEntity<PublicDomain>,
);
} catch (error) {
await this.dnsManagerService.deleteHostnameSilently(formattedDomain, {
isPublicDomain: true,
@@ -1,6 +1,8 @@
import { UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { CreateWebhookDTO } from 'src/engine/core-modules/webhook/dtos/create-webhook.dto';
import { DeleteWebhookDTO } from 'src/engine/core-modules/webhook/dtos/delete-webhook.dto';
import { GetWebhookDTO } from 'src/engine/core-modules/webhook/dtos/get-webhook.dto';
@@ -56,7 +58,7 @@ export class WebhookResolver {
@Args('input') input: UpdateWebhookDTO,
): Promise<Webhook | null> {
try {
const updateData: Partial<Webhook> = {};
const updateData: QueryDeepPartialEntity<Webhook> = {};
if (input.targetUrl !== undefined) updateData.targetUrl = input.targetUrl;
if (input.operations !== undefined)
@@ -3,6 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { ArrayContains, IsNull, Repository } from 'typeorm';
import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { Webhook } from './webhook.entity';
import { WebhookException, WebhookExceptionCode } from './webhook.exception';
@@ -93,7 +94,7 @@ export class WebhookService {
async update(
id: string,
workspaceId: string,
updateData: Partial<Webhook>,
updateData: QueryDeepPartialEntity<Webhook>,
): Promise<Webhook | null> {
const webhook = await this.findById(id, workspaceId);
@@ -102,7 +103,9 @@ export class WebhookService {
}
if (isDefined(updateData.targetUrl)) {
const normalizedTargetUrl = this.normalizeTargetUrl(updateData.targetUrl);
const normalizedTargetUrl = this.normalizeTargetUrl(
updateData.targetUrl as string,
);
if (!this.validateTargetUrl(normalizedTargetUrl)) {
throw new WebhookException(