UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

163 lines (162 loc) 6.08 kB
/** * AiModule — AI Provider 服务注册 * * 从 ServiceContainer.initialize() 中提取的 AI Provider 初始化逻辑, * 作为独立的 DI 模块管理 AI 相关服务的生命周期。 * * 职责: * - AI Provider 自动探测与创建 * - AiProviderManager 统一管理层 * - Embedding fallback provider 管理 * - AiFactory 实例注入 * * @module AiModule */ import { AiProviderManager } from '../../external/ai/AiProviderManager.js'; /** * 初始化 AI Provider(在模块注册前调用) * * 1. 动态导入 AiFactory * 2. 自动探测可用 AI Provider * 3. 创建 AiProviderManager(统一管理层) * 4. 绑定 Token 追踪、Embedding fallback、DI 级联清理 */ export async function initialize(c) { const logger = c.logger; // AiFactory 模块引用 try { c.singletons._aiFactory = await import('../../external/ai/AiFactory.js'); } catch { c.singletons._aiFactory = null; } // 自动探测 AI Provider if (!c.singletons.aiProvider && c.singletons._aiFactory) { try { const aiFactory = c.singletons._aiFactory; if (typeof aiFactory.autoDetectProvider === 'function') { c.singletons.aiProvider = aiFactory.autoDetectProvider(); const provider = c.singletons.aiProvider; logger.info('AI provider injected into container', { provider: provider?.constructor?.name || 'unknown', }); } } catch { c.singletons.aiProvider = null; } } // ── 创建 AiProviderManager(统一管理层)── const manager = new AiProviderManager(c.singletons.aiProvider || { name: 'mock', model: 'mock-fallback' }); c.singletons._aiProviderManager = manager; // 绑定: DI 数据管道同步(切换时更新 singletons 中的 provider 引用,供工厂函数读取) manager._bindDiSync((provider, embed) => { c.singletons.aiProvider = provider; c.singletons._embedProvider = embed; }); // 绑定: DI 级联清理回调 manager._bindDependentClearer(() => { const cleared = []; for (const key of c._aiDependentSingletons || []) { if (c.singletons[key]) { c.singletons[key] = null; cleared.push(key); } } return cleared; }); // 绑定: Embedding fallback 初始化器 manager._bindEmbedFallbackInit((currentProvider) => { return createEmbedFallback(c, currentProvider); }); // Token 追踪 AOP(manager 自身已在构造时 wire,此处延迟注入 recorder) // recorder 注入放到 register() 之后(tokenUsageStore 需先注册) // Embedding fallback: manager 的 embedFallbackInit 回调已绑定,初始化时主动触发一次 // 优先使用独立的 embed provider(ASD_EMBED_PROVIDER),其次 fallback 机制 let initialEmbed = null; try { const aiFactory = c.singletons._aiFactory; if (typeof aiFactory?.createEmbedProvider === 'function') { initialEmbed = aiFactory.createEmbedProvider(); if (initialEmbed) { logger.info('Dedicated embed provider created from ASD_EMBED_PROVIDER', { provider: initialEmbed.name, }); } } } catch (err) { logger.warn('Failed to create dedicated embed provider', { error: err.message, }); } // 若无独立 embed provider,走旧的 fallback 逻辑 if (!initialEmbed) { initialEmbed = createEmbedFallback(c, c.singletons.aiProvider); } if (initialEmbed) { manager.setEmbedProvider(initialEmbed); c.singletons._embedProvider = initialEmbed; } } /** * 纯函数: 尝试为给定 provider 创建 Embedding fallback * 被 initEmbeddingFallback() 和 AiProviderManager 的 embedFallbackInit 回调共用 */ function createEmbedFallback(c, currentProvider) { if (!currentProvider || (typeof currentProvider.supportsEmbedding === 'function' && currentProvider.supportsEmbedding())) { return null; // 主 provider 已支持 embedding,无需 fallback } try { const aiFactory = (c.singletons._aiFactory || {}); const providerName = (currentProvider.name || '').replace('-', ''); const fbCandidates = typeof aiFactory.getAvailableFallbacks === 'function' ? aiFactory.getAvailableFallbacks(providerName) : []; for (const fb of fbCandidates) { try { const fbProvider = aiFactory.createProvider?.({ provider: fb }); if (fbProvider && typeof fbProvider.supportsEmbedding === 'function' && fbProvider.supportsEmbedding()) { c.logger.info('Embedding fallback provider created', { provider: fb }); return fbProvider; } } catch { /* skip */ } } } catch { /* no embed fallback available */ } return null; } /** * 注册 AI 相关的服务到容器 * * - 标记 AI 模块就绪 * - 注册 aiProviderManager 服务 * - 延迟注入 TokenRecorder(tokenUsageStore 此时已可用) */ export function register(c) { c.singletons._aiModuleReady = true; // 注册 aiProviderManager(消费者通过 container.get('aiProviderManager') 获取) c.register('aiProviderManager', () => c.singletons._aiProviderManager); // 延迟注入 TokenRecorder 到 manager(tokenUsageStore 在 AppModule 中注册) const manager = c.singletons._aiProviderManager; const containerRef = c; manager.setTokenRecorder({ record(r) { try { const store = containerRef.get('tokenUsageStore'); store.record(r); } catch { /* tokenUsageStore not available yet */ } }, }); }