UNPKG

dpml-prompt

Version:

DPML-powered AI prompt framework - Revolutionary AI-First CLI system based on Deepractice Prompt Markup Language. Build sophisticated AI agents with structured prompts, memory systems, and execution frameworks.

306 lines (271 loc) 9.33 kB
const PackageDiscovery = require('./PackageDiscovery') const ProjectDiscovery = require('./ProjectDiscovery') const logger = require('../../../utils/logger') /** * DiscoveryManager - 资源发现管理器 * * 统一管理多个资源发现器,按照文档架构设计: * 1. 按优先级排序发现器 (数字越小优先级越高) * 2. 并行执行资源发现 * 3. 收集并合并所有发现的资源 * 4. 提供容错机制,单个发现器失败不影响整体 */ class DiscoveryManager { /** * 构造函数 * @param {Array} discoveries - 自定义发现器列表,如果不提供则使用默认配置 */ constructor(discoveries = null) { if (discoveries) { this.discoveries = [...discoveries] } else { // 默认发现器配置:只包含包级和项目级发现 this.discoveries = [ new PackageDiscovery(), // 优先级: 1 new ProjectDiscovery() // 优先级: 2 ] } // 按优先级排序 this._sortDiscoveriesByPriority() } /** * 添加发现器 * @param {Object} discovery - 实现了发现器接口的对象 */ addDiscovery(discovery) { if (!discovery || typeof discovery.discover !== 'function') { throw new Error('Discovery must implement discover method') } this.discoveries.push(discovery) this._sortDiscoveriesByPriority() } /** * 移除发现器 * @param {string} source - 发现器源类型 */ removeDiscovery(source) { this.discoveries = this.discoveries.filter(discovery => discovery.source !== source) } /** * 发现所有资源(并行模式) * @returns {Promise<Array>} 所有发现的资源列表 */ async discoverAll() { const discoveryPromises = this.discoveries.map(async (discovery) => { try { const resources = await discovery.discover() return Array.isArray(resources) ? resources : [] } catch (error) { logger.warn(`[DiscoveryManager] ${discovery.source} discovery failed: ${error.message}`) return [] } }) // 并行执行所有发现器 const discoveryResults = await Promise.allSettled(discoveryPromises) // 收集所有成功的结果 const allResources = [] discoveryResults.forEach((result, index) => { if (result.status === 'fulfilled') { allResources.push(...result.value) } else { logger.warn(`[DiscoveryManager] ${this.discoveries[index].source} discovery rejected: ${result.reason}`) } }) return allResources } /** * 发现并合并所有注册表(RegistryData架构) * @returns {Promise<Map>} 合并后的资源注册表 Map<resourceId, reference> */ async discoverRegistries() { const registryPromises = this.discoveries.map(async (discovery) => { try { // 优先使用新的discoverRegistry方法 if (typeof discovery.discoverRegistry === 'function') { const registry = await discovery.discoverRegistry() return registry instanceof Map ? registry : new Map() } else { // 向后兼容:将discover()结果转换为注册表格式 const resources = await discovery.discover() const registry = new Map() if (Array.isArray(resources)) { resources.forEach(resource => { if (resource.id && resource.reference) { registry.set(resource.id, resource.reference) } }) } return registry } } catch (error) { logger.warn(`[DiscoveryManager] ${discovery.source} registry discovery failed: ${error.message}`) return new Map() } }) // 并行执行所有发现器 const registryResults = await Promise.allSettled(registryPromises) // 收集所有成功的注册表 const registries = [] registryResults.forEach((result, index) => { if (result.status === 'fulfilled') { registries.push(result.value) } else { logger.warn(`[DiscoveryManager] ${this.discoveries[index].source} registry discovery rejected: ${result.reason}`) registries.push(new Map()) } }) // 按发现器优先级合并注册表 return this._mergeRegistries(registries) } /** * 按源类型发现注册表 * @param {string} source - 发现器源类型 * @returns {Promise<Map>} 指定源的资源注册表 */ async discoverRegistryBySource(source) { const discovery = this._findDiscoveryBySource(source) if (!discovery) { throw new Error(`Discovery source ${source} not found`) } if (typeof discovery.discoverRegistry === 'function') { return await discovery.discoverRegistry() } else { // 向后兼容:将discover()结果转换为注册表格式 const resources = await discovery.discover() const registry = new Map() if (Array.isArray(resources)) { resources.forEach(resource => { if (resource.id && resource.reference) { registry.set(resource.id, resource.reference) } }) } return registry } } /** * 按源类型发现资源 * @param {string} source - 发现器源类型 * @returns {Promise<Array>} 指定源的资源列表 */ async discoverBySource(source) { const discovery = this._findDiscoveryBySource(source) if (!discovery) { throw new Error(`Discovery source ${source} not found`) } return await discovery.discover() } /** * 获取所有发现器信息 * @returns {Array} 发现器信息列表 */ getDiscoveryInfo() { return this.discoveries.map(discovery => { if (typeof discovery.getDiscoveryInfo === 'function') { return discovery.getDiscoveryInfo() } else { return { source: discovery.source || 'UNKNOWN', priority: discovery.priority || 0, description: 'No description available' } } }) } /** * 清理所有发现器缓存 */ clearCache() { this.discoveries.forEach(discovery => { if (typeof discovery.clearCache === 'function') { discovery.clearCache() } }) } /** * 获取发现器数量 * @returns {number} 注册的发现器数量 */ getDiscoveryCount() { return this.discoveries.length } /** * 合并多个注册表(支持分层级资源管理) * @param {Array<Map>} registries - 注册表数组,按优先级排序(数字越小优先级越高) * @returns {Map} 合并后的注册表 * @private */ _mergeRegistries(registries) { const mergedRegistry = new Map() // 第一阶段:收集所有资源(包括带前缀的) for (let i = registries.length - 1; i >= 0; i--) { const registry = registries[i] if (registry instanceof Map) { for (const [key, value] of registry) { mergedRegistry.set(key, value) } } } // 第二阶段:处理优先级覆盖 - 高优先级的无前缀版本覆盖低优先级的 const priorityLevels = ['package', 'project', 'user'] // 优先级:package < project < user // 为每个基础资源ID找到最高优先级的版本 const baseResourceMap = new Map() // baseId -> {source, reference, priority} for (const [fullId, reference] of mergedRegistry) { // 解析资源ID:可能是 "source:resourceId" 或 "resourceId" const colonIndex = fullId.indexOf(':') let source = 'unknown' let baseId = fullId if (colonIndex !== -1) { const possibleSource = fullId.substring(0, colonIndex) if (priorityLevels.includes(possibleSource)) { source = possibleSource baseId = fullId.substring(colonIndex + 1) } } const currentPriority = priorityLevels.indexOf(source) const existing = baseResourceMap.get(baseId) if (!existing || currentPriority > existing.priority) { baseResourceMap.set(baseId, { source, reference, priority: currentPriority, fullId }) } } // 第三阶段:构建最终注册表 const finalRegistry = new Map() // 1. 添加所有带前缀的资源(用于明确指定级别) for (const [key, value] of mergedRegistry) { if (key.includes(':') && priorityLevels.includes(key.split(':')[0])) { finalRegistry.set(key, value) } } // 2. 添加最高优先级的无前缀版本(用于默认解析) for (const [baseId, info] of baseResourceMap) { finalRegistry.set(baseId, info.reference) } return finalRegistry } /** * 按优先级排序发现器 * @private */ _sortDiscoveriesByPriority() { this.discoveries.sort((a, b) => { const priorityA = a.priority || 0 const priorityB = b.priority || 0 return priorityA - priorityB // 升序排序,数字越小优先级越高 }) } /** * 根据源类型查找发现器 * @param {string} source - 发现器源类型 * @returns {Object|undefined} 找到的发现器或undefined * @private */ _findDiscoveryBySource(source) { return this.discoveries.find(discovery => discovery.source === source) } } module.exports = DiscoveryManager