import { DyFM_AI_Provider } from '@futdevpro/fsm-dynamo/ai'; import { DyFM_AI_ProviderCapabilities } from '@futdevpro/fsm-dynamo/ai'; import { DyFM_AI_Config } from '@futdevpro/fsm-dynamo/ai'; import { DyFM_Log } from '@futdevpro/fsm-dynamo'; import { DyNTS_AI_CostEvent } from '../_models/interfaces/dynts-ai-cost-event.interface'; import { DyNTS_AI_CostEventCallback } from '../_models/interfaces/dynts-ai-cost-event-callback.interface'; import { DyNTS_SingletonService } from '../../../_services/base/singleton.service'; /** * Abstract base class for all AI providers * Defines the common interface that all AI providers must implement * * **Cost-event hook (FR-002)**: a leszármazott concrete service-ek (OAI * Embedding / LLM / Chat) a constructor-ban opcionálisan kapnak egy * `onCostEvent` callback-et. Minden sikeres AI-call után `emitCostEvent`-tel * hívják, ami safe (try/catch) — a callback hibája NEM akasztja meg az * AI-call-t. Lásd `DyNTS_AI_CostEvent` interface. */ export abstract class DyNTS_AI_Provider_ServiceBase extends DyNTS_SingletonService { /** The AI provider this service represents */ abstract readonly aiProvider: DyFM_AI_Provider; /** The capabilities supported by this provider */ abstract readonly capabilities: DyFM_AI_ProviderCapabilities; /** * Optional per-call cost-event callback (FR-002). * A leszármazott service-ek minden sikeres AI-call után meghívják az * `emitCostEvent` helper-en keresztül. Non-breaking: ha undefined, nincs emit. */ protected onCostEvent?: DyNTS_AI_CostEventCallback; /** * Initialize the provider with configuration * @param config - Provider-specific configuration */ abstract setup(config: DyFM_AI_Config): void; /** * Test the connection to the AI provider * @param issuer - The issuer making the request * @returns Promise - True if connection is successful */ abstract testConnection(issuer: string): Promise; /** * Safe cost-event emit: ha van regisztrált `onCostEvent` callback, meghívja. * A callback hibája NEM propagálódik — try/catch-csel safen hívjuk és * `DyFM_Log.warn`-nal jelezzük. Ezzel a consumer-oldali integráció * (CCAP `CT_`, telemetry, stb.) hibái nem akasztják meg az AI-call-t. */ protected emitCostEvent(event: DyNTS_AI_CostEvent): void { if (!this.onCostEvent) { return; } try { this.onCostEvent(event); } catch (err: unknown) { const msg: string = err instanceof Error ? err.message : String(err); DyFM_Log.warn( `DyNTS AI | onCostEvent callback threw (call-type: ${event.callType},` + ` model: ${event.model}, issuer: ${event.issuer}): ${msg}`, ); } } }