Files
PromptX/docs/role-discovery-optimization.md
sean 5779aa837c fix: 全面清理prompt关键词引用 - 完成prompt→resource重构
核心修复:
- 修复PackageDiscovery._isValidDevelopmentRoot()检查resource目录而非prompt
- 更新package.json files字段从prompt/改为resource/
- 修复RegisterCommand.js中的资源路径引用
- 更新WelcomeCommand.js中的@package://prompt/为@package://resource/
- 修复PromptProtocol.js中所有@package://prompt/路径引用
- 更新PackageProtocol.js示例路径
- 批量更新docs/目录下26个文档的路径引用

技术价值:
- 解决PackageDiscovery无法加载系统级角色的问题
- 消除PackageProtocol的Access denied错误
- 实现prompt→resource语义重构的100%完整性
- 确保所有8个系统级角色正常加载和激活

验证结果:
-  61个系统级资源正常加载
-  8个角色完全可用(assistant,frontend-developer,java-backend-developer,noface,nuwa,sean,xiaohongshu-marketer,product-manager)
-  welcome和action命令完全正常工作

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-28 15:12:17 +08:00

495 lines
12 KiB
Markdown
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.

# 角色发现机制优化设计
## 📋 概述
当前PromptX的角色发现机制存在过度复杂的扫描逻辑导致跨平台兼容性问题和性能瓶颈。本文档分析现状问题并提出系统性的优化方案。
## 🚨 当前问题分析
### 问题1: 双重角色发现机制
**现状**
- `ResourceManager.loadUnifiedRegistry()` - 统一资源管理
- `HelloCommand.discoverLocalRoles()` - 独立的本地角色发现
**问题**
- 逻辑重复,维护成本高
- 数据格式转换复杂
- 容易产生不一致的结果
### 问题2: glob库跨平台兼容性风险
**现状代码**
```javascript
// HelloCommand.js:254
const rolePattern = path.join(domainPath, '*', '*.role.md')
const roleFiles = glob.sync(rolePattern)
```
**风险点**
- Windows路径分隔符处理不一致
- glob模式匹配在不同平台行为差异
- 同步操作阻塞主线程
- 外部依赖增加包大小和安全风险
### 问题3: 过度复杂的文件系统扫描
**扫描流程**
```
ResourceManager.discoverUserResources()
scanResourceDirectory() - 扫描基础目录
scanRoleResources() - 扫描角色文件
scanOtherResources() - 扫描thought/execution
validateDPMLFormat() - DPML格式验证
extractRoleName() - 元数据提取
```
**复杂性问题**
- 4层嵌套的异步操作
- 每个目录多次`fs.stat()``fs.pathExists()`调用
- 错误处理不一致(有些抛异常,有些仅警告)
- 无缓存机制重复I/O操作
### 问题4: DPML验证过于简化
**当前验证**
```javascript
validateDPMLFormat(content, type) {
const tags = DPML_TAGS[type]
return content.includes(tags.start) && content.includes(tags.end)
}
```
**局限性**
- 只检查标签存在,不验证格式正确性
- 无结构验证和嵌套检查
- 验证失败时无详细错误信息
- 无法处理标签损坏的情况
### 问题5: PackageProtocol检测过度复杂
**现状**
```javascript
_performInstallModeDetection() {
// 5种检测模式每次都执行
_isNpxExecution()
_isGlobalInstall()
_isDevelopmentMode()
_isMonorepoWorkspace()
_isNpmLink()
}
```
**开销问题**
- 每次调用都重新检测环境
- 文件系统操作频繁
- 逻辑分支复杂,维护困难
## 🎯 优化方案设计
### 方案1: 统一角色发现架构(推荐)
#### 1.1 移除双重机制
```javascript
// 移除HelloCommand.discoverLocalRoles()
// 完全依赖ResourceManager统一管理
class HelloCommand {
async loadRoleRegistry() {
// 仅调用ResourceManager无独立扫描逻辑
const resourceManager = new ResourceManager()
const unifiedRegistry = await resourceManager.loadUnifiedRegistry()
return unifiedRegistry.role || {}
}
}
```
#### 1.2 简化ResourceManager
```javascript
class ResourceManager {
async loadUnifiedRegistry() {
// 并行加载,提升性能
const [systemRegistry, userRoles] = await Promise.all([
this.loadSystemRegistry(),
this.discoverUserRolesSimple()
])
return this.mergeRegistries(systemRegistry, userRoles)
}
async discoverUserRolesSimple() {
// 最小化用户资源发现逻辑
const userPath = path.join(await this.getPackageRoot(), USER_RESOURCE_DIR, ...RESOURCE_DOMAIN_PATH)
if (!await fs.pathExists(userPath)) {
return { role: {} }
}
return await this.scanUserRolesOptimized(userPath)
}
}
```
### 方案2: 原生API替代glob
#### 2.1 使用Node.js原生fs API
```javascript
async function discoverRolesNative(domainPath) {
const roles = {}
try {
// 使用withFileTypes提升性能
const entries = await fs.readdir(domainPath, { withFileTypes: true })
for (const entry of entries) {
if (entry.isDirectory()) {
const roleFile = path.join(domainPath, entry.name, `${entry.name}.role.md`)
// 单次检查文件存在性
if (await fs.pathExists(roleFile)) {
roles[entry.name] = {
file: roleFile,
name: entry.name,
source: 'user-generated'
}
}
}
}
} catch (error) {
// 统一错误处理
logger.warn(`角色发现失败 ${domainPath}: ${error.message}`)
return {}
}
return roles
}
```
#### 2.2 跨平台路径处理最佳实践
```javascript
class PathUtils {
static normalizeRolePath(roleName) {
// 确保跨平台路径兼容性
return path.join('.promptx', 'resource', 'domain', roleName, `${roleName}.role.md`)
}
static async safeReadDir(dirPath) {
try {
return await fs.readdir(dirPath, { withFileTypes: true })
} catch (error) {
// 处理权限问题
if (error.code === 'EACCES' || error.code === 'EPERM') {
logger.warn(`权限不足,跳过目录: ${dirPath}`)
return []
}
throw error
}
}
}
```
### 方案3: 增强DPML验证器
#### 3.1 结构化验证
```javascript
class DPMLValidator {
static validate(content, type) {
const result = {
isValid: false,
errors: [],
metadata: {},
structure: null
}
try {
// 1. 基础标签检查
if (!this.hasValidTags(content, type)) {
result.errors.push(`缺少${type}标签`)
return result
}
// 2. 结构验证
const structure = this.parseStructure(content, type)
if (!structure) {
result.errors.push('标签结构无效')
return result
}
// 3. 内容验证
const metadata = this.extractMetadata(content, type)
result.isValid = true
result.metadata = metadata
result.structure = structure
} catch (error) {
result.errors.push(`验证失败: ${error.message}`)
}
return result
}
static parseStructure(content, type) {
// 解析XML结构验证嵌套正确性
const regex = new RegExp(`<${type}>(.*?)</${type}>`, 's')
const match = content.match(regex)
return match ? match[1].trim() : null
}
static extractMetadata(content, type) {
// 提取角色元数据
const metadata = {}
// 提取标题
const titleMatch = content.match(/^#\s+(.+)$/m)
if (titleMatch) {
metadata.title = titleMatch[1].trim()
}
// 提取描述
const descMatch = content.match(/description:\s*(.+?)(?:\n|$)/i)
if (descMatch) {
metadata.description = descMatch[1].trim()
}
return metadata
}
}
```
### 方案4: 缓存机制
#### 4.1 文件扫描缓存
```javascript
class RoleDiscoveryCache {
constructor() {
this.cache = new Map()
this.timestamps = new Map()
this.ttl = 5 * 60 * 1000 // 5分钟缓存
}
async getOrScan(key, scanFn) {
const now = Date.now()
// 检查缓存是否有效
if (this.cache.has(key)) {
const timestamp = this.timestamps.get(key)
if (now - timestamp < this.ttl) {
return this.cache.get(key)
}
}
// 执行扫描并缓存结果
const result = await scanFn()
this.cache.set(key, result)
this.timestamps.set(key, now)
return result
}
invalidate(key) {
this.cache.delete(key)
this.timestamps.delete(key)
}
}
```
#### 4.2 智能缓存失效
```javascript
class SmartCache extends RoleDiscoveryCache {
async watchDirectory(dirPath) {
// 监听目录变化,智能失效缓存
const watcher = fs.watch(dirPath, (eventType, filename) => {
if (filename && filename.endsWith('.role.md')) {
this.invalidate(dirPath)
logger.debug(`角色文件变化,失效缓存: ${filename}`)
}
})
return watcher
}
}
```
### 方案5: 简化PackageProtocol
#### 5.1 基础环境检测
```javascript
class SimplePackageProtocol {
constructor() {
this.mode = this.detectMode()
this.packageRoot = null
}
detectMode() {
// 简化为3种基本模式
if (process.env.PROMPTX_ENV === 'development') {
return 'development'
}
if (process.argv[1]?.includes('npx')) {
return 'npx'
}
return 'installed'
}
async getPackageRoot() {
if (this.packageRoot) {
return this.packageRoot
}
switch (this.mode) {
case 'development':
this.packageRoot = process.cwd()
break
case 'npx':
this.packageRoot = await this.findNpxRoot()
break
default:
this.packageRoot = await this.findInstalledRoot()
}
return this.packageRoot
}
}
```
## 🚀 实施计划
### Phase 1: 移除glob依赖立即实施
**优先级**: 🔥 紧急
**影响**: 解决跨平台兼容性问题
**具体步骤**
1. ✅ 替换`HelloCommand.discoverLocalRoles()`中的glob调用
2. ✅ 使用`fs.readdir()``path.join()`替代
3. ✅ 添加跨平台路径处理
### Phase 2: 统一角色发现架构(本周)
**优先级**: 🔥 高
**影响**: 简化维护,提升性能
**具体步骤**
1. ✅ 移除`HelloCommand.discoverLocalRoles()`方法
2. ✅ 简化`ResourceManager.scanResourceDirectory()`逻辑
3. ✅ 统一错误处理机制
### Phase 3: 增强验证和缓存(下周)
**优先级**: 🔧 中
**影响**: 提升可靠性和性能
**具体步骤**
1. ✅ 实现`DPMLValidator`结构化验证
2. ✅ 添加`RoleDiscoveryCache`缓存机制
3. ✅ 优化PackageProtocol检测逻辑
### Phase 4: 性能监控和测试(持续)
**优先级**: 📊 中
**影响**: 确保优化效果
**具体步骤**
1. ✅ 添加角色发现性能指标
2. ✅ 完善跨平台测试用例
3. ✅ 建立性能回归测试
## 📊 预期收益
### 性能提升
- **文件扫描速度**: 提升60%移除glob减少I/O
- **初始化时间**: 减少40%(缓存机制)
- **内存使用**: 降低30%(移除重复数据结构)
### 兼容性改善
- **Windows兼容性**: 100%原生API
- **权限处理**: 增强错误恢复
- **路径处理**: 统一跨平台标准
### 维护性提升
- **代码复杂度**: 降低50%(移除双重机制)
- **测试覆盖**: 提升到95%
- **Bug减少**: 预计减少70%的跨平台问题
## 🔧 配置迁移指南
### 用户无感知迁移
优化后的角色发现机制对用户完全透明,无需修改现有配置:
**现有用户资源结构**(保持不变):
```
.promptx/
resource/
domain/
my-role/
my-role.role.md
thought/
my-role.thought.md
execution/
my-role.execution.md
```
**系统资源注册**(保持不变):
```json
// resource.registry.json
{
"role": {
"assistant": {
"file": "@package://resource/domain/assistant/assistant.role.md",
"name": "🙋 智能助手"
}
}
}
```
### 开发者API保持兼容
```javascript
// 现有API保持不变
const helloCommand = new HelloCommand()
const roles = await helloCommand.getAllRoles()
const roleInfo = await helloCommand.getRoleInfo('assistant')
```
## 🧪 测试策略
### 跨平台兼容性测试
```javascript
// 新增测试用例
describe('角色发现跨平台兼容性', () => {
test('Windows路径处理', () => {
// 测试Windows特殊字符处理
})
test('Unix权限处理', () => {
// 测试Unix文件权限
})
test('符号链接处理', () => {
// 测试符号链接角色文件
})
})
```
### 性能基准测试
```javascript
describe('角色发现性能', () => {
test('大量角色扫描性能', async () => {
// 创建100个测试角色
// 测试扫描时间<100ms
})
test('缓存命中率', async () => {
// 测试缓存有效性
})
})
```
## 📚 相关文档
- [用户角色创建系统](./user-role-creation-system.md)
- [DPML协议规范](../resource/protocol/dpml.protocol.md)
- [ResourceManager架构](../src/lib/core/resource/)
- [跨平台测试指南](../src/tests/commands/CrossPlatformDiscovery.unit.test.js)
---
**总结**: 通过系统性的优化PromptX的角色发现机制将更加简洁、高效、可靠为用户提供更好的跨平台体验。