refactor: 重构整个资源引用协议
This commit is contained in:
@ -14,14 +14,14 @@ class CrossPlatformFileScanner {
|
||||
* @param {Object} options - 扫描选项
|
||||
* @param {Array<string>} options.extensions - 文件扩展名列表,如 ['.role.md', '.execution.md']
|
||||
* @param {Array<string>} options.subdirs - 限制扫描的子目录,如 ['domain', 'execution']
|
||||
* @param {number} options.maxDepth - 最大扫描深度,默认10
|
||||
* @param {number} options.maxDepth - 最大扫描深度,默认5
|
||||
* @returns {Promise<Array<string>>} 匹配的文件路径列表
|
||||
*/
|
||||
async scanFiles(baseDir, options = {}) {
|
||||
const {
|
||||
extensions = [],
|
||||
subdirs = null,
|
||||
maxDepth = 10
|
||||
maxDepth = 5
|
||||
} = options
|
||||
|
||||
if (!await fs.pathExists(baseDir)) {
|
||||
@ -43,15 +43,19 @@ class CrossPlatformFileScanner {
|
||||
const resourceConfig = {
|
||||
role: {
|
||||
extensions: ['.role.md'],
|
||||
subdirs: ['domain'] // 角色文件通常在domain目录下
|
||||
subdirs: null // 不限制子目录,在所有地方查找role文件
|
||||
},
|
||||
execution: {
|
||||
extensions: ['.execution.md'],
|
||||
subdirs: ['execution'] // 执行模式文件在execution目录下
|
||||
subdirs: null // 不限制子目录,在所有地方查找execution文件
|
||||
},
|
||||
thought: {
|
||||
extensions: ['.thought.md'],
|
||||
subdirs: ['thought'] // 思维模式文件在thought目录下
|
||||
subdirs: null // 不限制子目录,在所有地方查找thought文件
|
||||
},
|
||||
knowledge: {
|
||||
extensions: ['.knowledge.md'],
|
||||
subdirs: null // 不限制子目录,在所有地方查找knowledge文件
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,82 @@ class DiscoveryManager {
|
||||
return allResources
|
||||
}
|
||||
|
||||
/**
|
||||
* 发现并合并所有注册表(新架构方法)
|
||||
* @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) {
|
||||
console.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 {
|
||||
console.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 - 发现器源类型
|
||||
@ -133,6 +209,30 @@ class DiscoveryManager {
|
||||
return this.discoveries.length
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并多个注册表
|
||||
* @param {Array<Map>} registries - 注册表数组,按优先级排序(数字越小优先级越高)
|
||||
* @returns {Map} 合并后的注册表
|
||||
* @private
|
||||
*/
|
||||
_mergeRegistries(registries) {
|
||||
const mergedRegistry = new Map()
|
||||
|
||||
// 从后往前合并:先添加低优先级的,再让高优先级的覆盖
|
||||
// registries按优先级升序排列 [high(0), med(1), low(2)]
|
||||
// 我们从低优先级开始,让高优先级的覆盖
|
||||
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) // 直接设置,让高优先级的最终覆盖
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mergedRegistry
|
||||
}
|
||||
|
||||
/**
|
||||
* 按优先级排序发现器
|
||||
* @private
|
||||
|
||||
@ -19,22 +19,18 @@ class PackageDiscovery extends BaseDiscovery {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发现包级资源
|
||||
* 发现包级资源 (新架构 - 纯动态扫描)
|
||||
* @returns {Promise<Array>} 发现的资源列表
|
||||
*/
|
||||
async discover() {
|
||||
const resources = []
|
||||
|
||||
try {
|
||||
// 1. 加载静态注册表资源
|
||||
const registryResources = await this._loadStaticRegistryResources()
|
||||
resources.push(...registryResources)
|
||||
|
||||
// 2. 扫描prompt目录资源
|
||||
// 扫描prompt目录资源(新架构只使用动态扫描)
|
||||
const scanResources = await this._scanPromptDirectory()
|
||||
resources.push(...scanResources)
|
||||
|
||||
// 3. 规范化所有资源
|
||||
// 规范化所有资源
|
||||
return resources.map(resource => this.normalizeResource(resource))
|
||||
|
||||
} catch (error) {
|
||||
@ -44,64 +40,44 @@ class PackageDiscovery extends BaseDiscovery {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从静态注册表加载资源
|
||||
* @returns {Promise<Array>} 注册表中的资源列表
|
||||
* 发现包级资源注册表 (新架构 - 纯动态扫描)
|
||||
* @returns {Promise<Map>} 发现的资源注册表 Map<resourceId, reference>
|
||||
*/
|
||||
async _loadStaticRegistryResources() {
|
||||
async discoverRegistry() {
|
||||
try {
|
||||
const registry = await this._loadStaticRegistry()
|
||||
const resources = []
|
||||
// 扫描动态资源(新架构只使用动态扫描)
|
||||
const scanResults = await this._scanPromptDirectory()
|
||||
const registry = this._buildRegistryFromScanResults(scanResults)
|
||||
|
||||
if (registry.protocols) {
|
||||
// 遍历所有协议
|
||||
for (const [protocol, protocolInfo] of Object.entries(registry.protocols)) {
|
||||
if (protocolInfo.registry) {
|
||||
// 遍历协议下的所有资源
|
||||
for (const [resourceId, resourceInfo] of Object.entries(protocolInfo.registry)) {
|
||||
const reference = typeof resourceInfo === 'string'
|
||||
? resourceInfo
|
||||
: resourceInfo.file
|
||||
return registry
|
||||
|
||||
if (reference) {
|
||||
resources.push({
|
||||
id: `${protocol}:${resourceId}`,
|
||||
reference: reference
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resources
|
||||
} catch (error) {
|
||||
console.warn(`[PackageDiscovery] Failed to load static registry: ${error.message}`)
|
||||
return []
|
||||
console.warn(`[PackageDiscovery] Registry discovery failed: ${error.message}`)
|
||||
return new Map()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 加载静态注册表文件
|
||||
* @returns {Promise<Object>} 注册表内容
|
||||
* 从扫描结果构建Map
|
||||
* @param {Array} scanResults - 扫描结果数组
|
||||
* @returns {Map} 资源注册表 Map<resourceId, reference>
|
||||
*/
|
||||
async _loadStaticRegistry() {
|
||||
const packageRoot = await this._findPackageRoot()
|
||||
|
||||
// 尝试主要路径:src/resource.registry.json
|
||||
const primaryPath = path.join(packageRoot, 'src', 'resource.registry.json')
|
||||
if (await fs.pathExists(primaryPath)) {
|
||||
return await fs.readJSON(primaryPath)
|
||||
_buildRegistryFromScanResults(scanResults) {
|
||||
const registry = new Map()
|
||||
|
||||
for (const resource of scanResults) {
|
||||
if (resource.id && resource.reference) {
|
||||
registry.set(resource.id, resource.reference)
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试后备路径:resource.registry.json
|
||||
const alternativePath = path.join(packageRoot, 'resource.registry.json')
|
||||
if (await fs.pathExists(alternativePath)) {
|
||||
return await fs.readJSON(alternativePath)
|
||||
}
|
||||
|
||||
throw new Error('Static registry file not found')
|
||||
return registry
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 扫描prompt目录发现资源
|
||||
* @returns {Promise<Array>} 扫描发现的资源列表
|
||||
@ -118,7 +94,7 @@ class PackageDiscovery extends BaseDiscovery {
|
||||
const resources = []
|
||||
|
||||
// 定义要扫描的资源类型
|
||||
const resourceTypes = ['role', 'execution', 'thought']
|
||||
const resourceTypes = ['role', 'execution', 'thought', 'knowledge']
|
||||
|
||||
// 并行扫描所有资源类型
|
||||
for (const resourceType of resourceTypes) {
|
||||
|
||||
@ -45,6 +45,50 @@ class ProjectDiscovery extends BaseDiscovery {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发现项目级资源注册表 (新架构方法)
|
||||
* @returns {Promise<Map>} 发现的资源注册表 Map<resourceId, reference>
|
||||
*/
|
||||
async discoverRegistry() {
|
||||
try {
|
||||
// 1. 查找项目根目录
|
||||
const projectRoot = await this._findProjectRoot()
|
||||
|
||||
// 2. 检查.promptx目录是否存在
|
||||
const hasPrompxDir = await this._checkPrompxDirectory(projectRoot)
|
||||
if (!hasPrompxDir) {
|
||||
return new Map()
|
||||
}
|
||||
|
||||
// 3. 扫描项目资源
|
||||
const resources = await this._scanProjectResources(projectRoot)
|
||||
|
||||
// 4. 构建注册表
|
||||
return this._buildRegistryFromResources(resources)
|
||||
|
||||
} catch (error) {
|
||||
console.warn(`[ProjectDiscovery] Registry discovery failed: ${error.message}`)
|
||||
return new Map()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从资源列表构建注册表
|
||||
* @param {Array} resources - 资源列表
|
||||
* @returns {Map} 资源注册表 Map<resourceId, reference>
|
||||
*/
|
||||
_buildRegistryFromResources(resources) {
|
||||
const registry = new Map()
|
||||
|
||||
for (const resource of resources) {
|
||||
if (resource.id && resource.reference) {
|
||||
registry.set(resource.id, resource.reference)
|
||||
}
|
||||
}
|
||||
|
||||
return registry
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找项目根目录
|
||||
* @returns {Promise<string>} 项目根目录路径
|
||||
@ -97,7 +141,7 @@ class ProjectDiscovery extends BaseDiscovery {
|
||||
const resources = []
|
||||
|
||||
// 定义要扫描的资源类型
|
||||
const resourceTypes = ['role', 'execution', 'thought']
|
||||
const resourceTypes = ['role', 'execution', 'thought', 'knowledge']
|
||||
|
||||
// 并行扫描所有资源类型
|
||||
for (const resourceType of resourceTypes) {
|
||||
@ -187,6 +231,10 @@ class ProjectDiscovery extends BaseDiscovery {
|
||||
return trimmedContent.includes('<execution>') && trimmedContent.includes('</execution>')
|
||||
case 'thought':
|
||||
return trimmedContent.includes('<thought>') && trimmedContent.includes('</thought>')
|
||||
case 'knowledge':
|
||||
// knowledge类型比较灵活,只要文件有内容就认为是有效的
|
||||
// 可以是纯文本、链接、图片等任何形式的知识内容
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user