Skip to content

Commit bd432a6

Browse files
Merge branch 'main' into upgrade-angular
2 parents 1b73c27 + e722034 commit bd432a6

File tree

54 files changed

+1565
-214
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1565
-214
lines changed

backend/.development.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ IS_SAAS=true
7171
# api key for using openai service
7272
OPENAI_API_KEY=
7373

74+
# assistant id for using openai service
75+
OPENAI_ASSISTANT_ID=
76+
7477
# optional parameters (it's only for testing)
7578
POSTGRES_CONNECTION_USERNAME=TEST_POSTGRES_CONNECTION_USERNAME
7679
POSTGRES_CONNECTION_PASSWORD=TEST_POSTGRES_CONNECTION_PASSWORD

backend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"eslint-plugin-security": "3.0.1",
7070
"express": "4.21.2",
7171
"express-rate-limit": "7.4.1",
72+
"fetch-blob": "^4.0.0",
7273
"helmet": "8.0.0",
7374
"ip-range-check": "0.2.0",
7475
"json2csv": "^5.0.7",

backend/src/common/application/global-database-context.interface.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ import { UserApiKeyEntity } from '../../entities/api-key/api-key.entity.js';
3636
import { IUserApiKeyRepository } from '../../entities/api-key/repository/user-api-key-repository.interface.js';
3737
import { ActionEventsEntity } from '../../entities/table-actions/table-action-events-module/action-event.entity.js';
3838
import { TableActionEntity } from '../../entities/table-actions/table-actions-module/table-action.entity.js';
39+
import { IAiUserThreadsRepository } from '../../entities/ai/ai-data-entities/ai-user-threads/ai-user-threads-repository.interface.js';
40+
import { AiUserThreadEntity } from '../../entities/ai/ai-data-entities/ai-user-threads/ai-user-threads.entity.js';
41+
import { IAiUserFilesRepository } from '../../entities/ai/ai-data-entities/ai-user-files/ai-user-files-repository.interface.js';
42+
import { AiUserFileEntity } from '../../entities/ai/ai-data-entities/ai-user-files/ai-user-files.entity.js';
3943

4044
export interface IGlobalDatabaseContext extends IDatabaseContext {
4145
userRepository: Repository<UserEntity> & IUserRepository;
@@ -65,4 +69,6 @@ export interface IGlobalDatabaseContext extends IDatabaseContext {
6569
actionRulesRepository: Repository<ActionRulesEntity> & IActionRulesRepository;
6670
actionEventsRepository: Repository<ActionEventsEntity> & IActionEventsRepository;
6771
userApiKeysRepository: Repository<UserApiKeyEntity> & IUserApiKeyRepository;
72+
aiUserThreadsRepository: Repository<AiUserThreadEntity> & IAiUserThreadsRepository;
73+
aiUserFilesRepository: Repository<AiUserFileEntity> & IAiUserFilesRepository;
6874
}

backend/src/common/application/global-database-context.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ import { actionEventsCustomRepositoryExtension } from '../../entities/table-acti
7878
import { IUserApiKeyRepository } from '../../entities/api-key/repository/user-api-key-repository.interface.js';
7979
import { UserApiKeyEntity } from '../../entities/api-key/api-key.entity.js';
8080
import { userApiRepositoryExtension } from '../../entities/api-key/repository/user-api-key-repository.extension.js';
81+
import { AiUserThreadEntity } from '../../entities/ai/ai-data-entities/ai-user-threads/ai-user-threads.entity.js';
82+
import { IAiUserThreadsRepository } from '../../entities/ai/ai-data-entities/ai-user-threads/ai-user-threads-repository.interface.js';
83+
import { IAiUserFilesRepository } from '../../entities/ai/ai-data-entities/ai-user-files/ai-user-files-repository.interface.js';
84+
import { AiUserFileEntity } from '../../entities/ai/ai-data-entities/ai-user-files/ai-user-files.entity.js';
85+
import { aiUserThreadRepositoryExtension } from '../../entities/ai/ai-data-entities/ai-user-threads/ai-user-threads-repository.extension.js';
86+
import { aiUserFileRepositoryExtension } from '../../entities/ai/ai-data-entities/ai-user-files/ai-user-file-repository.extension.js';
8187

8288
@Injectable({ scope: Scope.REQUEST })
8389
export class GlobalDatabaseContext implements IGlobalDatabaseContext {
@@ -110,6 +116,8 @@ export class GlobalDatabaseContext implements IGlobalDatabaseContext {
110116
private _actionRulesRepository: Repository<ActionRulesEntity> & IActionRulesRepository;
111117
private _actionEventsRepository: Repository<ActionEventsEntity> & IActionEventsRepository;
112118
private _userApiKeysRepository: Repository<UserApiKeyEntity> & IUserApiKeyRepository;
119+
private _aiUserThreadsRepository: Repository<AiUserThreadEntity> & IAiUserThreadsRepository;
120+
private _aiUserFilesRepository: Repository<AiUserFileEntity> & IAiUserFilesRepository;
113121

114122
public constructor(
115123
@Inject(BaseType.DATA_SOURCE)
@@ -186,6 +194,12 @@ export class GlobalDatabaseContext implements IGlobalDatabaseContext {
186194
.getRepository(ActionEventsEntity)
187195
.extend(actionEventsCustomRepositoryExtension);
188196
this._userApiKeysRepository = this.appDataSource.getRepository(UserApiKeyEntity).extend(userApiRepositoryExtension);
197+
this._aiUserThreadsRepository = this.appDataSource
198+
.getRepository(AiUserThreadEntity)
199+
.extend(aiUserThreadRepositoryExtension);
200+
this._aiUserFilesRepository = this.appDataSource
201+
.getRepository(AiUserFileEntity)
202+
.extend(aiUserFileRepositoryExtension);
189203
}
190204

191205
public get userRepository(): Repository<UserEntity> & IUserRepository {
@@ -296,6 +310,14 @@ export class GlobalDatabaseContext implements IGlobalDatabaseContext {
296310
return this._userApiKeysRepository;
297311
}
298312

313+
public get aiUserThreadsRepository(): Repository<AiUserThreadEntity> & IAiUserThreadsRepository {
314+
return this._aiUserThreadsRepository;
315+
}
316+
317+
public get aiUserFilesRepository(): Repository<AiUserFileEntity> & IAiUserFilesRepository {
318+
return this._aiUserFilesRepository;
319+
}
320+
299321
public startTransaction(): Promise<void> {
300322
this._queryRunner = this.appDataSource.createQueryRunner();
301323
this._queryRunner.startTransaction();

backend/src/common/data-injection.tokens.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,10 @@ export enum UseCaseType {
164164
DELETE_API_KEY = 'DELETE_API_KEY',
165165

166166
REQUEST_INFO_FROM_TABLE_WITH_AI = 'REQUEST_INFO_FROM_TABLE_WITH_AI',
167+
168+
CREATE_THREAD_WITH_AI_ASSISTANT = 'CREATE_THREAD_WITH_AI_ASSISTANT',
169+
ADD_MESSAGE_TO_THREAD_WITH_AI_ASSISTANT = 'ADD_MESSAGE_TO_THREAD_WITH_AI_ASSISTANT',
170+
GET_ALL_USER_THREADS_WITH_AI_ASSISTANT = 'GET_ALL_USER_THREADS_WITH_AI_ASSISTANT',
171+
GET_ALL_THREAD_MESSAGES = 'GET_ALL_THREAD_MESSAGES',
172+
DELETE_THREAD_WITH_AI_ASSISTANT = 'DELETE_THREAD_WITH_AI_ASSISTANT',
167173
}

backend/src/decorators/slug-uuid.decorator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ export type SlugUuidParameter =
1212
| 'ruleId'
1313
| 'eventId'
1414
| 'apiKeyId'
15-
| 'companyId';
15+
| 'companyId'
16+
| 'threadId';
1617
export const SlugUuid = createParamDecorator(
1718
(parameterName: SlugUuidParameter = 'slug', ctx: ExecutionContext): string => {
1819
const request: IRequestWithCognitoInfo = ctx.switchToHttp().getRequest();
19-
const availableSlagParameters = [
20+
const availableSlagParameters: Array<SlugUuidParameter> = [
2021
'slug',
2122
'connectionId',
2223
'groupId',
@@ -26,6 +27,7 @@ export const SlugUuid = createParamDecorator(
2627
'ruleId',
2728
'eventId',
2829
'companyId',
30+
'threadId',
2931
];
3032
if (!availableSlagParameters.includes(parameterName)) {
3133
throw new BadRequestException(Messages.UUID_INVALID);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { IAiUserFilesRepository } from './ai-user-files-repository.interface.js';
2+
import { AiUserFileEntity } from './ai-user-files.entity.js';
3+
4+
export const aiUserFileRepositoryExtension: IAiUserFilesRepository = {
5+
async findFileNyThreadId(threadId: string): Promise<AiUserFileEntity> {
6+
return await this.createQueryBuilder('ai_user_file')
7+
.leftJoin('ai_user_file.thread', 'thread')
8+
.where('thread.id = :threadId', { threadId })
9+
.getOne();
10+
},
11+
12+
async findAllFilesByUserId(userId: string): Promise<Array<AiUserFileEntity>> {
13+
return await this.createQueryBuilder('ai_user_file')
14+
.leftJoin('ai_user_file.thread', 'thread')
15+
.leftJoin('thread.user', 'user')
16+
.where('user.id = :userId', { userId })
17+
.getMany();
18+
},
19+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { AiUserFileEntity } from './ai-user-files.entity.js';
2+
3+
export interface IAiUserFilesRepository {
4+
findFileNyThreadId(threadId: string): Promise<AiUserFileEntity>;
5+
6+
findAllFilesByUserId(userId: string): Promise<Array<AiUserFileEntity>>;
7+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn, Relation } from 'typeorm';
2+
import { AiUserThreadEntity } from '../ai-user-threads/ai-user-threads.entity.js';
3+
4+
@Entity('ai_user_files')
5+
export class AiUserFileEntity {
6+
@PrimaryGeneratedColumn('uuid')
7+
id: string;
8+
9+
@Column({ type: 'varchar', length: 128 })
10+
file_ai_id: string;
11+
12+
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
13+
createdAt: Date;
14+
15+
@OneToOne((_) => AiUserThreadEntity, (thread) => thread.thread_file, { onDelete: 'CASCADE' })
16+
@JoinColumn()
17+
thread: Relation<AiUserThreadEntity>;
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { IAiUserThreadsRepository } from './ai-user-threads-repository.interface.js';
2+
import { AiUserThreadEntity } from './ai-user-threads.entity.js';
3+
4+
export const aiUserThreadRepositoryExtension: IAiUserThreadsRepository = {
5+
async findThreadsByUserId(userId: string): Promise<Array<AiUserThreadEntity>> {
6+
return await this.createQueryBuilder('ai_user_thread')
7+
.leftJoin('ai_user_thread.user', 'user')
8+
.where('user.id = :userId', { userId })
9+
.getMany();
10+
},
11+
12+
async findThreadByIdAndUserId(threadId: string, userId: string): Promise<AiUserThreadEntity> {
13+
return await this.createQueryBuilder('ai_user_thread')
14+
.leftJoin('ai_user_thread.user', 'user')
15+
.where('user.id = :userId', { userId })
16+
.andWhere('ai_user_thread.id = :threadId', { threadId })
17+
.getOne();
18+
},
19+
20+
async findThreadByIdAndUserIdWithFile(threadId: string, userId: string): Promise<AiUserThreadEntity> {
21+
return await this.createQueryBuilder('ai_user_thread')
22+
.leftJoin('ai_user_thread.user', 'user')
23+
.leftJoinAndSelect('ai_user_thread.thread_file', 'thread_file')
24+
.where('user.id = :userId', { userId })
25+
.andWhere('ai_user_thread.id = :threadId', { threadId })
26+
.getOne();
27+
},
28+
};

0 commit comments

Comments
 (0)