WIP - ai process builder codex attempt

This commit is contained in:
Francisco Gaona
2026-01-17 20:16:04 +01:00
parent 20fc90a3fb
commit ded413b99b
34 changed files with 2199 additions and 13 deletions

View File

@@ -0,0 +1,120 @@
import { Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import { AiProcessesService } from './ai-processes.service';
import { AiProcessesStreamService } from './ai-processes.stream.service';
import { AiAssistantService } from '../ai-assistant/ai-assistant.service';
import { TenantDatabaseService } from '../tenant/tenant-database.service';
import { AiChatMessage, AiChatSession } from '../models/ai-chat.model';
@Injectable()
export class AiProcessesOrchestratorService {
constructor(
private readonly processesService: AiProcessesService,
private readonly streamService: AiProcessesStreamService,
private readonly tenantDbService: TenantDatabaseService,
private readonly aiAssistantService: AiAssistantService,
) {}
private async getTenantContext(tenantId: string) {
const resolvedTenantId = await this.tenantDbService.resolveTenantId(tenantId);
const knex = await this.tenantDbService.getTenantKnexById(resolvedTenantId);
return { knex, tenantId: resolvedTenantId };
}
private async createSessionWithContext(
knex: Knex,
tenantId: string,
userId: string,
) {
return AiChatSession.query(knex).insert({
tenantId,
userId,
});
}
async createSession(tenantId: string, userId: string) {
const { knex, tenantId: resolvedTenantId } =
await this.getTenantContext(tenantId);
return this.createSessionWithContext(knex, resolvedTenantId, userId);
}
async sendMessage(
tenantId: string,
userId: string,
message: string,
sessionId?: string,
processId?: string,
history?: { role: string; text: string }[],
context?: Record<string, unknown>,
) {
const { knex, tenantId: resolvedTenantId } =
await this.getTenantContext(tenantId);
const session = sessionId
? await AiChatSession.query(knex).findById(sessionId)
: await this.createSessionWithContext(knex, resolvedTenantId, userId);
if (!session || session.tenantId !== resolvedTenantId) {
throw new Error('Chat session not found.');
}
await AiChatMessage.query(knex).insert({
sessionId: session.id,
role: 'user',
content: message,
});
this.streamService.emit(session.id, { type: 'agent_started' });
const processes = await this.processesService.listProcesses(resolvedTenantId);
this.streamService.emit(session.id, {
type: 'processes_listed',
data: { count: processes.length },
});
if (!processes.length) {
const response = await this.aiAssistantService.handleChat(
resolvedTenantId,
userId,
message,
history ?? [],
context ?? {},
);
this.streamService.emit(session.id, {
type: 'final',
data: { reply: response.reply, action: response.action },
});
return {
sessionId: session.id,
reply: response.reply,
action: response.action,
record: response.record,
};
}
const selectedProcess = processId
? processes.find((proc) => proc.id === processId)
: processes[0];
if (!selectedProcess) {
throw new Error('Process not found.');
}
this.streamService.emit(session.id, {
type: 'process_selected',
processId: selectedProcess.id,
version: selectedProcess.latestVersion,
});
const { run, result } = await this.processesService.createRun(
resolvedTenantId,
userId,
selectedProcess.id,
{ message },
session.id,
(payload) => this.streamService.emit(session.id, payload),
);
return { sessionId: session.id, runId: run.id, status: result.status };
}
}