import { Injectable, Logger, OnModuleInit } from "@nestjs/common"; import type { AgentSession, IAgentProvider } from "@mosaic/shared"; import { InternalAgentProvider } from "./internal-agent.provider"; @Injectable() export class AgentProviderRegistry implements OnModuleInit { private readonly logger = new Logger(AgentProviderRegistry.name); private readonly providers = new Map(); constructor(private readonly internalProvider: InternalAgentProvider) {} onModuleInit(): void { this.registerProvider(this.internalProvider); } registerProvider(provider: IAgentProvider): void { const existingProvider = this.providers.get(provider.providerId); if (existingProvider !== undefined) { this.logger.warn(`Replacing existing provider registration for ${provider.providerId}`); } this.providers.set(provider.providerId, provider); } getProvider(providerId: string): IAgentProvider | null { return this.providers.get(providerId) ?? null; } async getProviderForSession( sessionId: string ): Promise<{ provider: IAgentProvider; session: AgentSession } | null> { for (const provider of this.providers.values()) { try { const session = await provider.getSession(sessionId); if (session !== null) { return { provider, session, }; } } catch (error) { this.logger.warn( `Failed to get session ${sessionId} for provider ${provider.providerId}: ${this.toErrorMessage(error)}` ); } } return null; } async listAllSessions(): Promise { const providers = [...this.providers.values()]; const sessionsByProvider = await Promise.all( providers.map(async (provider) => { try { const { sessions } = await provider.listSessions(); return sessions; } catch (error) { this.logger.warn( `Failed to list sessions for provider ${provider.providerId}: ${this.toErrorMessage(error)}` ); return []; } }) ); return sessionsByProvider .flat() .sort((left, right) => right.updatedAt.getTime() - left.updatedAt.getTime()); } private toErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message; } return String(error); } }