Merge branch 'main' into develop

This commit is contained in:
sean
2025-06-02 09:31:49 +08:00
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

View File

@ -0,0 +1,232 @@
const BasePouchCommand = require('../BasePouchCommand')
const fs = require('fs-extra')
const path = require('path')
const PackageProtocol = require('../../resource/protocols/PackageProtocol')
const { buildCommand } = require('../../../../constants')
/**
* 角色注册锦囊命令
* 负责将新创建的角色注册到系统中
*/
class RegisterCommand extends BasePouchCommand {
constructor () {
super()
this.packageProtocol = new PackageProtocol()
}
getPurpose () {
return '注册新创建的角色到系统中,使其可以被发现和激活'
}
async getContent (args) {
const [roleId] = args
if (!roleId) {
return `❌ 请指定要注册的角色ID
🔍 使用方法:
\`\`\`bash
${buildCommand.register('<角色ID>')}
\`\`\`
💡 例如:
\`\`\`bash
${buildCommand.register('my-custom-role')}
\`\`\``
}
try {
// 1. 检查角色文件是否存在
const roleExists = await this.checkRoleExists(roleId)
if (!roleExists) {
return `❌ 角色文件不存在!
请确保以下文件存在:
- prompt/domain/${roleId}/${roleId}.role.md
- prompt/domain/${roleId}/thought/${roleId}.thought.md
- prompt/domain/${roleId}/execution/${roleId}.execution.md
💡 您可以使用角色设计师来创建完整的角色套件:
\`\`\`bash
${buildCommand.action('role-designer')}
\`\`\``
}
// 2. 提取角色元数据
const roleMetadata = await this.extractRoleMetadata(roleId)
// 3. 注册角色到系统
const registrationResult = await this.registerRole(roleId, roleMetadata)
if (registrationResult.success) {
return `✅ 角色 "${roleId}" 注册成功!
📋 **注册信息**
- 名称:${roleMetadata.name}
- 描述:${roleMetadata.description}
- 文件路径:${roleMetadata.filePath}
🎯 **下一步操作**
\`\`\`bash
${buildCommand.action(roleId)}
\`\`\`
💡 现在您可以激活这个角色了!`
} else {
return `❌ 角色注册失败:${registrationResult.error}
🔍 请检查:
- 角色文件格式是否正确
- 是否有写入权限
- 注册表文件是否可访问`
}
} catch (error) {
console.error('Register command error:', error)
return `❌ 注册角色 "${roleId}" 时发生错误:${error.message}
💡 请确保角色文件存在且格式正确。`
}
}
/**
* 检查角色文件是否存在
*/
async checkRoleExists (roleId) {
try {
const packageRoot = await this.packageProtocol.getPackageRoot()
const roleFile = path.join(packageRoot, 'prompt', 'domain', roleId, `${roleId}.role.md`)
return await fs.pathExists(roleFile)
} catch (error) {
return false
}
}
/**
* 提取角色元数据
*/
async extractRoleMetadata (roleId) {
const packageRoot = await this.packageProtocol.getPackageRoot()
const roleFile = path.join(packageRoot, 'prompt', 'domain', roleId, `${roleId}.role.md`)
const content = await fs.readFile(roleFile, 'utf-8')
const relativePath = path.relative(packageRoot, roleFile)
// 提取元数据
let name = `🎭 ${roleId}`
let description = '用户自定义角色'
// 从注释中提取元数据(支持多行)
const nameMatch = content.match(/name:\s*(.+?)(?:\n|$)/i)
if (nameMatch) {
name = nameMatch[1].trim()
}
const descMatch = content.match(/description:\s*(.+?)(?:\n|$)/i)
if (descMatch) {
description = descMatch[1].trim()
}
// 如果没有找到注释,尝试从文件内容推断
if (name === `🎭 ${roleId}` && description === '用户自定义角色') {
// 可以根据角色内容进行更智能的推断
if (content.includes('产品')) {
name = `📊 ${roleId}`
} else if (content.includes('开发') || content.includes('代码')) {
name = `💻 ${roleId}`
} else if (content.includes('设计')) {
name = `🎨 ${roleId}`
}
}
return {
name,
description,
filePath: `@package://${relativePath}`
}
}
/**
* 注册角色到系统
*/
async registerRole (roleId, metadata) {
try {
const packageRoot = await this.packageProtocol.getPackageRoot()
const registryPath = path.join(packageRoot, 'src', 'resource.registry.json')
// 读取当前注册表
const registry = await fs.readJson(registryPath)
// 添加新角色
if (!registry.protocols.role.registry) {
registry.protocols.role.registry = {}
}
registry.protocols.role.registry[roleId] = {
file: metadata.filePath,
name: metadata.name,
description: metadata.description
}
// 写回注册表
await fs.writeJson(registryPath, registry, { spaces: 2 })
return { success: true }
} catch (error) {
return { success: false, error: error.message }
}
}
getPATEOAS (args) {
const [roleId] = args
if (!roleId) {
return {
currentState: 'register_awaiting_role',
availableTransitions: ['hello', 'action'],
nextActions: [
{
name: '查看可用角色',
description: '查看已注册的角色',
command: buildCommand.hello(),
priority: 'medium'
},
{
name: '创建新角色',
description: '使用角色设计师创建新角色',
command: buildCommand.action('role-designer'),
priority: 'high'
}
],
metadata: {
message: '需要指定角色ID'
}
}
}
return {
currentState: 'register_completed',
availableTransitions: ['action', 'hello'],
nextActions: [
{
name: '激活角色',
description: '激活刚注册的角色',
command: buildCommand.action(roleId),
priority: 'high'
},
{
name: '查看所有角色',
description: '查看角色列表',
command: buildCommand.hello(),
priority: 'medium'
}
],
metadata: {
registeredRole: roleId,
systemVersion: '锦囊串联状态机 v1.0'
}
}
}
}
module.exports = RegisterCommand

View File

@ -12,11 +12,13 @@
"registry": {
"assistant": "@package://prompt/domain/assistant/thought/assistant.thought.md",
"remember": "@package://prompt/core/thought/remember.thought.md",
"recall": "@package://prompt/core/thought/recall.thought.md"
"recall": "@package://prompt/core/thought/recall.thought.md",
"product-manager": "@package://prompt/domain/product-manager/thought/product-manager.thought.md",
"java-backend-developer": "@package://prompt/domain/java-backend-developer/thought/java-backend-developer.thought.md"
}
},
"execution": {
"description": "执行模式资源协议",
"description": "执行模式资源协议",
"location": "execution://{execution_id}",
"params": {
"format": "string - 输出格式",
@ -24,16 +26,21 @@
},
"registry": {
"assistant": "@package://prompt/domain/assistant/execution/assistant.execution.md",
"deal-at-reference": "@package://prompt/core/execution/deal-at-reference.execution.md",
"memory-trigger": "@package://prompt/core/execution/memory-trigger.execution.md",
"deal-memory": "@package://prompt/core/execution/deal-memory.execution.md"
"product-manager": "@package://prompt/domain/product-manager/execution/product-manager.execution.md",
"market-analysis": "@package://prompt/domain/product-manager/execution/market-analysis.execution.md",
"user-research": "@package://prompt/domain/product-manager/execution/user-research.execution.md",
"java-backend-developer": "@package://prompt/domain/java-backend-developer/execution/java-backend-developer.execution.md",
"system-architecture": "@package://prompt/domain/java-backend-developer/execution/system-architecture.execution.md",
"spring-ecosystem": "@package://prompt/domain/java-backend-developer/execution/spring-ecosystem.execution.md",
"code-quality": "@package://prompt/domain/java-backend-developer/execution/code-quality.execution.md",
"database-design": "@package://prompt/domain/java-backend-developer/execution/database-design.execution.md"
}
},
"memory": {
"description": "项目记忆系统协议",
"location": "memory://{resource_id}",
"params": {
"format": "string - 输出格式",
"format": "string - 输出格式",
"cache": "boolean - 是否缓存"
},
"registry": {
@ -55,6 +62,26 @@
"file": "@package://prompt/domain/assistant/assistant.role.md",
"name": "🙋 智能助手",
"description": "通用助理角色,提供基础的助理服务和记忆支持"
},
"role-designer": {
"file": "@package://prompt/domain/role-designer/role-designer.role.md",
"name": "🎭 角色设计师",
"description": "专业角色设计专家基于DPML协议创建和优化新的AI角色"
},
"product-manager": {
"file": "@package://prompt/domain/product-manager/product-manager.role.md",
"name": "📊 产品经理",
"description": "专业产品管理专家,负责产品策略、用户研究、市场分析和团队协作"
},
"java-backend-developer": {
"file": "@package://prompt/domain/java-backend-developer/java-backend-developer.role.md",
"name": "☕ Java后端开发者",
"description": "专业Java后端开发专家精通Spring生态系统、微服务架构和系统设计"
},
"test-role": {
"file": "@package://prompt/domain/test-role/test-role.role.md",
"name": "🧪 测试角色",
"description": "这是一个用于测试动态发现和注册功能的示例角色"
}
}
},
@ -68,7 +95,7 @@
},
"registry": {
"protocols": "@package://prompt/protocol/**/*.md",
"core": "@package://prompt/core/**/*.md",
"core": "@package://prompt/core/**/*.md",
"domain": "@package://prompt/domain/**/*.md",
"resource": "@package://prompt/resource/**/*.md",
"bootstrap": "@package://bootstrap.md"
@ -90,7 +117,7 @@
}
},
"project": {
"description": "项目协议 - 访问项目根目录资源",
"description": "项目协议 - 访问项目根目录资源",
"location": "project://{path}",
"params": {
"from": "string - 指定搜索起始目录",
@ -101,7 +128,7 @@
},
"user": {
"description": "用户协议 - 访问用户目录资源",
"location": "user://{path}",
"location": "user://{path}",
"params": {
"exists": "boolean - 仅返回存在的文件/目录",
"type": "string - 过滤类型 (file|dir|both)"
@ -117,7 +144,7 @@
}
},
"https": {
"description": "HTTPS网络资源协议",
"description": "HTTPS网络资源协议",
"location": "https://{url}",
"params": {
"format": "string - 响应格式,如 json, text",
@ -126,4 +153,4 @@
}
}
}
}
}