feat: 实现本地角色动态发现机制 - 双重角色发现机制:同时支持npm仓库角色和本地项目角色 - 智能环境检测:自动适配开发、npx、全局、本地、monorepo等部署环境 - 安全机制完善:路径验证、权限检查、多层容错处理 - 向后兼容保证,不影响现有功能

This commit is contained in:
Cen-Yaozu
2025-06-01 21:26:14 +08:00
parent 4a0ad6e61c
commit 05cb5f54c0
48 changed files with 7124 additions and 20 deletions

View File

@ -31,10 +31,22 @@ class HelloCommand extends BasePouchCommand {
const resourceManager = new ResourceManager()
await resourceManager.initialize() // 确保初始化完成
let registeredRoles = {}
if (resourceManager.registry && resourceManager.registry.protocols && resourceManager.registry.protocols.role && resourceManager.registry.protocols.role.registry) {
this.roleRegistry = resourceManager.registry.protocols.role.registry
} else {
// 备用:如果资源系统不可用,使用基础角色
registeredRoles = resourceManager.registry.protocols.role.registry
}
// 动态发现本地角色并合并
const discoveredRoles = await this.discoverLocalRoles()
// 合并注册表中的角色和动态发现的角色
this.roleRegistry = {
...registeredRoles,
...discoveredRoles
}
// 如果没有任何角色,使用基础角色
if (Object.keys(this.roleRegistry).length === 0) {
this.roleRegistry = {
assistant: {
file: '@package://prompt/domain/assistant/assistant.role.md',
@ -44,12 +56,26 @@ class HelloCommand extends BasePouchCommand {
}
}
} catch (error) {
console.warn('角色注册表加载失败,使用基础角色:', error.message)
this.roleRegistry = {
assistant: {
file: '@package://prompt/domain/assistant/assistant.role.md',
name: '🙋 智能助手',
description: '通用助理角色,提供基础的助理服务和记忆支持'
console.warn('角色注册表加载失败,尝试动态发现:', error.message)
// fallback到动态发现
try {
const discoveredRoles = await this.discoverLocalRoles()
this.roleRegistry = Object.keys(discoveredRoles).length > 0 ? discoveredRoles : {
assistant: {
file: '@package://prompt/domain/assistant/assistant.role.md',
name: '🙋 智能助手',
description: '通用助理角色,提供基础的助理服务和记忆支持'
}
}
} catch (discoveryError) {
console.warn('动态角色发现也失败了:', discoveryError.message)
this.roleRegistry = {
assistant: {
file: '@package://prompt/domain/assistant/assistant.role.md',
name: '🙋 智能助手',
description: '通用助理角色,提供基础的助理服务和记忆支持'
}
}
}
}
@ -183,6 +209,64 @@ ${buildCommand.action(allRoles[0]?.id || 'assistant')}
const allRoles = await this.getAllRoles()
return allRoles.map(role => role.id)
}
/**
* 动态发现本地角色文件
*/
async discoverLocalRoles () {
const PackageProtocol = require('../../resource/protocols/PackageProtocol')
const packageProtocol = new PackageProtocol()
const glob = require('glob')
const path = require('path')
try {
const packageRoot = await packageProtocol.getPackageRoot()
const domainPath = path.join(packageRoot, 'prompt', 'domain')
// 扫描所有角色目录
const rolePattern = path.join(domainPath, '*', '*.role.md')
const roleFiles = glob.sync(rolePattern)
const discoveredRoles = {}
for (const roleFile of roleFiles) {
try {
const content = await fs.readFile(roleFile, 'utf-8')
const relativePath = path.relative(packageRoot, roleFile)
const roleName = path.basename(roleFile, '.role.md')
// 尝试从文件内容中提取角色信息
let description = '本地发现的角色'
let name = `🎭 ${roleName}`
// 简单的元数据提取(支持多行)
const descMatch = content.match(/description:\s*(.+?)(?:\n|$)/i)
if (descMatch) {
description = descMatch[1].trim()
}
const nameMatch = content.match(/name:\s*(.+?)(?:\n|$)/i)
if (nameMatch) {
name = nameMatch[1].trim()
}
discoveredRoles[roleName] = {
file: `@package://${relativePath}`,
name,
description,
source: 'local-discovery'
}
} catch (error) {
console.warn(`跳过无效的角色文件: ${roleFile}`, error.message)
}
}
return discoveredRoles
} catch (error) {
console.warn('动态角色发现失败:', error.message)
return {}
}
}
}
module.exports = HelloCommand