Files
PromptX/src/lib/core/resource/resourceManager.js
2025-06-12 17:31:02 +08:00

286 lines
8.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const fs = require('fs')
const ResourceRegistry = require('./resourceRegistry')
const ResourceProtocolParser = require('./resourceProtocolParser')
const DiscoveryManager = require('./discovery/DiscoveryManager')
// 导入协议处理器
const PackageProtocol = require('./protocols/PackageProtocol')
const ProjectProtocol = require('./protocols/ProjectProtocol')
const RoleProtocol = require('./protocols/RoleProtocol')
const ThoughtProtocol = require('./protocols/ThoughtProtocol')
const ExecutionProtocol = require('./protocols/ExecutionProtocol')
const KnowledgeProtocol = require('./protocols/KnowledgeProtocol')
class ResourceManager {
constructor() {
this.registry = new ResourceRegistry()
this.protocolParser = new ResourceProtocolParser()
this.parser = new ResourceProtocolParser() // 向后兼容别名
this.discoveryManager = new DiscoveryManager() // 新发现管理器
// 初始化协议处理器
this.protocols = new Map()
this.initializeProtocols()
}
/**
* 初始化所有协议处理器
*/
initializeProtocols() {
// 基础协议 - 直接文件系统映射
this.protocols.set('package', new PackageProtocol())
this.protocols.set('project', new ProjectProtocol())
// 逻辑协议 - 需要注册表查询
this.protocols.set('role', new RoleProtocol())
this.protocols.set('thought', new ThoughtProtocol())
this.protocols.set('execution', new ExecutionProtocol())
this.protocols.set('knowledge', new KnowledgeProtocol())
}
/**
* 新架构初始化方法
*/
async initializeWithNewArchitecture() {
try {
// 1. 使用DiscoveryManager发现并合并所有注册表
const discoveredRegistry = await this.discoveryManager.discoverRegistries()
// 2. 批量注册到ResourceRegistry
for (const [resourceId, reference] of discoveredRegistry) {
this.registry.register(resourceId, reference)
}
// 3. 为逻辑协议设置注册表引用
this.setupLogicalProtocols()
// 4. 设置初始化状态
this.initialized = true
// 初始化完成,不输出日志避免干扰用户界面
} catch (error) {
console.warn(`[ResourceManager] New architecture initialization failed: ${error.message}`)
console.warn('[ResourceManager] Continuing with empty registry')
this.initialized = true // 即使失败也标记为已初始化,避免重复尝试
}
}
/**
* 为逻辑协议设置注册表引用
*/
setupLogicalProtocols() {
// 将统一注册表传递给逻辑协议处理器
const roleProtocol = this.protocols.get('role')
const executionProtocol = this.protocols.get('execution')
const thoughtProtocol = this.protocols.get('thought')
const knowledgeProtocol = this.protocols.get('knowledge')
if (roleProtocol) {
roleProtocol.setRegistryManager(this)
}
if (executionProtocol) {
executionProtocol.setRegistryManager(this)
}
if (thoughtProtocol) {
thoughtProtocol.setRegistryManager(this)
}
if (knowledgeProtocol) {
knowledgeProtocol.setRegistryManager(this)
}
// 逻辑协议设置完成,不输出日志避免干扰用户界面
}
/**
* 通过协议解析加载资源内容
* @param {string} reference - 资源引用
* @returns {Promise<string>} 资源内容
*/
async loadResourceByProtocol(reference) {
// 1. 使用ResourceProtocolParser解析DPML语法
const parsed = this.protocolParser.parse(reference)
// 2. 获取对应的协议处理器
const protocol = this.protocols.get(parsed.protocol)
if (!protocol) {
throw new Error(`不支持的协议: ${parsed.protocol}`)
}
// 3. 委托给协议处理器解析并加载内容
const result = await protocol.resolve(parsed.path, parsed.queryParams)
// 4. 确保返回字符串内容,解包可能的对象格式
if (typeof result === 'string') {
return result
} else if (result && typeof result === 'object' && result.content) {
return result.content
} else {
throw new Error(`协议${parsed.protocol}返回了无效的内容格式`)
}
}
async loadResource(resourceId) {
try {
// 使用新架构初始化
if (this.registry.size === 0) {
await this.initializeWithNewArchitecture()
}
// 处理@!开头的DPML格式如 @!role://java-developer
if (resourceId.startsWith('@!')) {
const parsed = this.protocolParser.parse(resourceId)
const logicalResourceId = `${parsed.protocol}:${parsed.path}`
// 从注册表查找对应的@package://引用
const reference = this.registry.get(logicalResourceId)
if (!reference) {
throw new Error(`Resource not found: ${logicalResourceId}`)
}
// 通过协议解析加载内容
const content = await this.loadResourceByProtocol(reference)
return {
success: true,
content,
resourceId,
reference
}
}
// 处理传统格式(如 role:java-developer
const reference = this.registry.get(resourceId)
if (!reference) {
throw new Error(`Resource not found: ${resourceId}`)
}
// 通过协议解析加载内容
const content = await this.loadResourceByProtocol(reference)
return {
success: true,
content,
resourceId,
reference
}
} catch (error) {
return {
success: false,
error: error,
message: error.message
}
}
}
/**
* 统一协议解析入口点 - 按照架构文档设计
*/
async resolveProtocolReference(reference) {
// 1. 使用ResourceProtocolParser解析DPML语法
const parsed = this.parser.parse(reference)
// 2. 获取对应的协议处理器
const protocol = this.protocols.get(parsed.protocol)
if (!protocol) {
throw new Error(`不支持的协议: ${parsed.protocol}`)
}
// 3. 委托给协议处理器解析
return await protocol.resolve(parsed.path, parsed.queryParams)
}
/**
* 强制重新初始化资源发现(清除缓存)
* 用于解决新创建角色无法被发现的问题
*/
async forceRefresh() {
// 1. 清除ResourceManager的初始化状态
this.initialized = false
// 2. 清空注册表
this.registry.clear()
// 3. 清除所有发现器的缓存
if (this.discoveryManager && this.discoveryManager.clearCache) {
this.discoveryManager.clearCache()
}
// 4. 重新初始化
await this.initializeWithNewArchitecture()
}
/**
* 获取所有已注册的协议
* @returns {Array<string>} 协议名称列表
*/
getAvailableProtocols() {
return Array.from(this.protocols.keys())
}
/**
* 检查是否支持指定协议
* @param {string} protocol - 协议名称
* @returns {boolean} 是否支持
*/
supportsProtocol(protocol) {
return this.protocols.has(protocol)
}
/**
* 设置初始化状态
*/
set initialized(value) {
this._initialized = value
}
/**
* 获取初始化状态
*/
get initialized() {
return this._initialized || false
}
// 向后兼容方法
async resolve(resourceUrl) {
try {
// 使用新架构初始化
if (this.registry.size === 0) {
await this.initializeWithNewArchitecture()
}
// Handle old format: role:java-backend-developer or @package://...
if (resourceUrl.startsWith('@')) {
// Parse the reference to check if it's a custom protocol
const parsed = this.protocolParser.parse(resourceUrl)
// Check if it's a basic protocol that can be handled directly
const basicProtocols = ['package', 'project', 'file']
if (basicProtocols.includes(parsed.protocol)) {
// Direct protocol format - use protocol resolution
const content = await this.loadResourceByProtocol(resourceUrl)
return {
success: true,
content,
path: resourceUrl,
reference: resourceUrl
}
} else {
// Custom protocol - extract resource ID and use ResourceRegistry
const resourceId = `${parsed.protocol}:${parsed.path}`
return await this.loadResource(resourceId)
}
} else {
// Legacy format: treat as resource ID
return await this.loadResource(resourceUrl)
}
} catch (error) {
return {
success: false,
error: error,
message: error.message
}
}
}
}
module.exports = ResourceManager