import { IVersionRepository } from '../repositories/interfaces'; import { AgentVersion, CreateVersionRequest, UpdateVersionDetailsRequest, VersionComparison, VersionDifference } from '../types'; export interface IVersionService { getAllVersions(agentId: string): Promise; getVersion(agentId: string, versionId: string): Promise; createVersion(agentId: string, request: CreateVersionRequest): Promise; activateVersion(agentId: string, versionId: string): Promise; updateVersionDetails(agentId: string, versionId: string, request: UpdateVersionDetailsRequest): Promise; getActiveVersion(agentId: string): Promise; getVersionByNumber(agentId: string, versionNumber: number): Promise; } export class VersionService implements IVersionService { constructor(private repository: IVersionRepository) {} async getAllVersions(agentId: string): Promise { const versions = await this.repository.getAllVersions(agentId); return versions.sort((a, b) => b.versionNumber.value - a.versionNumber.value); } async getVersion(agentId: string, versionId: string): Promise { return this.repository.getVersion(agentId, versionId); } async createVersion( agentId: string, request: CreateVersionRequest ): Promise { if (!request.system_prompt?.trim()) { throw new Error('System prompt cannot be empty'); } const newVersion = await this.repository.createVersion(agentId, request); console.log(`Created version ${newVersion.versionName} for agent ${agentId}`); return newVersion; } async activateVersion(agentId: string, versionId: string): Promise { await this.repository.activateVersion(agentId, versionId); console.log(`Activated version ${versionId} for agent ${agentId}`); } async compareVersions( agentId: string, version1Id: string, version2Id: string ): Promise { return this.repository.compareVersions(agentId, version1Id, version2Id); } async rollbackToVersion( agentId: string, versionId: string ): Promise { const newVersion = await this.repository.rollbackToVersion(agentId, versionId); console.log(`Rolled back to version ${versionId} for agent ${agentId}`); return newVersion; } async updateVersionDetails( agentId: string, versionId: string, request: UpdateVersionDetailsRequest ): Promise { const updatedVersion = await this.repository.updateVersionDetails(agentId, versionId, request); console.log(`Updated version details for ${versionId} in agent ${agentId}`); return updatedVersion; } async getActiveVersion(agentId: string): Promise { const versions = await this.getAllVersions(agentId); return versions.find(v => v.isActive) || null; } async getVersionByNumber( agentId: string, versionNumber: number ): Promise { const versions = await this.getAllVersions(agentId); return versions.find(v => v.versionNumber.value === versionNumber) || null; } calculateDifferences(v1: AgentVersion, v2: AgentVersion): VersionDifference[] { const differences: VersionDifference[] = []; if (v1.systemPrompt !== v2.systemPrompt) { differences.push({ field: 'systemPrompt', type: 'modified', oldValue: v1.systemPrompt, newValue: v2.systemPrompt }); } const v1Tools = new Set(Object.keys(v1.toolConfiguration.tools)); const v2Tools = new Set(Object.keys(v2.toolConfiguration.tools)); for (const tool of v2Tools) { if (!v1Tools.has(tool)) { differences.push({ field: `tool.${tool}`, type: 'added', newValue: v2.toolConfiguration.tools[tool] }); } } for (const tool of v1Tools) { if (!v2Tools.has(tool)) { differences.push({ field: `tool.${tool}`, type: 'removed', oldValue: v1.toolConfiguration.tools[tool] }); } } for (const tool of v1Tools) { if (v2Tools.has(tool) && JSON.stringify(v1.toolConfiguration.tools[tool]) !== JSON.stringify(v2.toolConfiguration.tools[tool])) { differences.push({ field: `tool.${tool}`, type: 'modified', oldValue: v1.toolConfiguration.tools[tool], newValue: v2.toolConfiguration.tools[tool] }); } } return differences; } }