chore(core): Use interfaces instead of session / agent entities to solve partial deep type issues (#23438)

This commit is contained in:
Jaakko Husso
2025-12-19 09:51:20 +02:00
committed by GitHub
parent da9014faeb
commit 5c69d7435c
7 changed files with 53 additions and 25 deletions
+1 -1
View File
@@ -459,7 +459,7 @@ export class ChatHubUpdateAgentRequest extends Z.class({
icon: agentIconOrEmojiSchema.optional(),
systemPrompt: z.string().min(1).optional(),
credentialId: z.string().optional(),
provider: chatHubProviderSchema.optional(),
provider: chatHubLLMProviderSchema.optional(),
model: z.string().max(64).optional(),
tools: z.array(INodeSchema).optional(),
}) {}
@@ -3,6 +3,21 @@ import { User, CredentialsEntity, JsonColumn, WithTimestamps } from '@n8n/db';
import { Column, Entity, ManyToOne, JoinColumn, PrimaryGeneratedColumn } from '@n8n/typeorm';
import { INode } from 'n8n-workflow';
export interface IChatHubAgent {
id: string;
createdAt: Date;
updatedAt: Date;
name: string;
description: string | null;
icon: AgentIconOrEmoji | null;
systemPrompt: string;
ownerId: string;
credentialId: string | null;
provider: ChatHubLLMProvider;
model: string;
tools: INode[];
}
@Entity({ name: 'chat_hub_agents' })
export class ChatHubAgent extends WithTimestamps {
@PrimaryGeneratedColumn('uuid')
@@ -2,7 +2,7 @@ import { withTransaction } from '@n8n/db';
import { Service } from '@n8n/di';
import { DataSource, EntityManager, Repository } from '@n8n/typeorm';
import { ChatHubAgent } from './chat-hub-agent.entity';
import { ChatHubAgent, IChatHubAgent } from './chat-hub-agent.entity';
@Service()
export class ChatHubAgentRepository extends Repository<ChatHubAgent> {
@@ -10,7 +10,10 @@ export class ChatHubAgentRepository extends Repository<ChatHubAgent> {
super(ChatHubAgent, dataSource.manager);
}
async createAgent(agent: Partial<ChatHubAgent>, trx?: EntityManager) {
async createAgent(
agent: Partial<IChatHubAgent> & Pick<IChatHubAgent, 'id'>,
trx?: EntityManager,
) {
return await withTransaction(this.manager, trx, async (em) => {
await em.insert(ChatHubAgent, agent);
return await em.findOneOrFail(ChatHubAgent, {
@@ -19,16 +22,7 @@ export class ChatHubAgentRepository extends Repository<ChatHubAgent> {
});
}
async updateAgent(
id: string,
updates: Partial<
Pick<
ChatHubAgent,
'name' | 'description' | 'systemPrompt' | 'provider' | 'model' | 'credentialId'
>
>,
trx?: EntityManager,
) {
async updateAgent(id: string, updates: Partial<IChatHubAgent>, trx?: EntityManager) {
return await withTransaction(this.manager, trx, async (em) => {
await em.update(ChatHubAgent, { id }, updates);
return await em.findOneOrFail(ChatHubAgent, {
@@ -8,7 +8,7 @@ import type { User } from '@n8n/db';
import { Service } from '@n8n/di';
import { v4 as uuidv4 } from 'uuid';
import type { ChatHubAgent } from './chat-hub-agent.entity';
import type { ChatHubAgent, IChatHubAgent } from './chat-hub-agent.entity';
import { ChatHubAgentRepository } from './chat-hub-agent.repository';
import { ChatHubCredentialsService } from './chat-hub-credentials.service';
import { getModelMetadata } from './chat-hub.constants';
@@ -75,7 +75,7 @@ export class ChatHubAgentService {
tools: data.tools,
});
this.logger.info(`Chat agent created: ${id} by user ${user.id}`);
this.logger.debug(`Chat agent created: ${id} by user ${user.id}`);
return agent;
}
@@ -95,20 +95,20 @@ export class ChatHubAgentService {
await this.chatHubCredentialsService.ensureCredentialById(user, updates.credentialId);
}
const updateData: Partial<ChatHubAgent> = {};
const updateData: Partial<IChatHubAgent> = {};
if (updates.name !== undefined) updateData.name = updates.name;
if (updates.description !== undefined) updateData.description = updates.description ?? null;
if (updates.icon !== undefined) updateData.icon = updates.icon;
if (updates.systemPrompt !== undefined) updateData.systemPrompt = updates.systemPrompt;
if (updates.credentialId !== undefined) updateData.credentialId = updates.credentialId ?? null;
if (updates.provider !== undefined)
updateData.provider = updates.provider as ChatHubAgent['provider'];
if (updates.provider !== undefined) updateData.provider = updates.provider;
if (updates.model !== undefined) updateData.model = updates.model ?? null;
if (updates.tools !== undefined) updateData.tools = updates.tools;
const agent = await this.chatAgentRepository.updateAgent(id, updateData);
this.logger.info(`Chat agent updated: ${id} by user ${user.id}`);
this.logger.debug(`Chat agent updated: ${id} by user ${user.id}`);
return agent;
}
@@ -121,6 +121,6 @@ export class ChatHubAgentService {
await this.chatAgentRepository.deleteAgent(id);
this.logger.info(`Chat agent deleted: ${id} by user ${userId}`);
this.logger.debug(`Chat agent deleted: ${id} by user ${userId}`);
}
}
@@ -21,6 +21,22 @@ import type { INode } from 'n8n-workflow';
import type { ChatHubMessage } from './chat-hub-message.entity';
import type { ChatHubAgent } from './chat-hub-agent.entity';
export interface IChatHubSession {
id: string;
createdAt: Date;
updatedAt: Date;
title: string;
ownerId: string;
lastMessageAt: Date | null;
credentialId: string | null;
provider: ChatHubProvider | null;
model: string | null;
workflowId: string | null;
agentId: string | null;
agentName: string | null;
tools: INode[];
}
@Entity({ name: 'chat_hub_sessions' })
export class ChatHubSession extends WithTimestamps {
@PrimaryGeneratedColumn('uuid')
@@ -45,7 +45,7 @@ import {
import { ChatHubAgentService } from './chat-hub-agent.service';
import { ChatHubCredentialsService } from './chat-hub-credentials.service';
import type { ChatHubMessage } from './chat-hub-message.entity';
import type { ChatHubSession } from './chat-hub-session.entity';
import type { ChatHubSession, IChatHubSession } from './chat-hub-session.entity';
import { ChatHubWorkflowService } from './chat-hub-workflow.service';
import { ChatHubAttachmentService } from './chat-hub.attachment.service';
import {
@@ -1419,7 +1419,7 @@ export class ChatHubService {
}
// Prepare the actual updates to be sent to the repository
const sessionUpdates: Partial<ChatHubSession> = {};
const sessionUpdates: Partial<IChatHubSession> = {};
if (updates.agent) {
const model = updates.agent.model;
@@ -2,7 +2,7 @@ import { withTransaction } from '@n8n/db';
import { Service } from '@n8n/di';
import { DataSource, EntityManager, Repository } from '@n8n/typeorm';
import { ChatHubSession } from './chat-hub-session.entity';
import { ChatHubSession, IChatHubSession } from './chat-hub-session.entity';
import { NotFoundError } from '@/errors/response-errors/not-found.error';
@@ -12,7 +12,10 @@ export class ChatHubSessionRepository extends Repository<ChatHubSession> {
super(ChatHubSession, dataSource.manager);
}
async createChatSession(session: Partial<ChatHubSession>, trx?: EntityManager) {
async createChatSession(
session: Partial<IChatHubSession> & Pick<IChatHubSession, 'id'>,
trx?: EntityManager,
) {
return await withTransaction(this.manager, trx, async (em) => {
await em.insert(ChatHubSession, session);
return await em.findOneOrFail(ChatHubSession, {
@@ -42,7 +45,7 @@ export class ChatHubSessionRepository extends Repository<ChatHubSession> {
});
}
async updateChatSession(id: string, updates: Partial<ChatHubSession>, trx?: EntityManager) {
async updateChatSession(id: string, updates: Partial<IChatHubSession>, trx?: EntityManager) {
return await withTransaction(this.manager, trx, async (em) => {
await em.update(ChatHubSession, { id }, updates);
return await em.findOneOrFail(ChatHubSession, {