fix: 统一Pouch命令路径获取机制,解决Issue #69记忆持久化问题

修复多实例MCP环境下的路径不一致问题:
- RememberCommand: 使用ResourceManager替代DirectoryService直接调用
- RecallCommand: 使用ResourceManager替代DirectoryService直接调用
- RegisterCommand: 使用ResourceManager+DirectoryService统一路径获取

核心改进:
1. 所有命令现在使用相同的getGlobalResourceManager()初始化
2. 通过resourceManager.initializeWithNewArchitecture()确保路径一致性
3. 实现"要对一起对,要错一起错"的一致性原则

测试验证:
- 记忆写入和读取使用相同项目路径
- 多实例环境下路径解析行为完全一致
- 向后兼容,无破坏性变更

Fixes #69

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
sean
2025-06-20 12:10:07 +08:00
parent 39ddc6a97f
commit 376244205a
3 changed files with 70 additions and 20 deletions

View File

@ -2,6 +2,7 @@ const BasePouchCommand = require('../BasePouchCommand')
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
const { COMMANDS } = require('../../../../constants') const { COMMANDS } = require('../../../../constants')
const { getGlobalResourceManager } = require('../../resource')
/** /**
* 记忆检索锦囊命令 * 记忆检索锦囊命令
@ -10,6 +11,8 @@ const { COMMANDS } = require('../../../../constants')
class RecallCommand extends BasePouchCommand { class RecallCommand extends BasePouchCommand {
constructor () { constructor () {
super() super()
// 复用ActionCommand的ResourceManager方式
this.resourceManager = getGlobalResourceManager()
} }
getPurpose () { getPurpose () {
@ -99,16 +102,20 @@ ${formattedMemories}
} }
/** /**
* 获取所有记忆(支持多行格式) * 获取所有记忆(支持多行格式使用ResourceManager路径获取
*/ */
async getAllMemories (query) { async getAllMemories (query) {
this.lastSearchCount = 0 this.lastSearchCount = 0
const memories = [] const memories = []
// 读取单一记忆文件 // 确保ResourceManager已初始化就像ActionCommand那样
const { getDirectoryService } = require('../../../utils/DirectoryService') if (!this.resourceManager.initialized) {
const directoryService = getDirectoryService() await this.resourceManager.initializeWithNewArchitecture()
const memoryDir = await directoryService.getMemoryDirectory() }
// 通过ResourceManager获取项目路径与ActionCommand一致
const projectPath = await this.getProjectPath()
const memoryDir = path.join(projectPath, '.promptx', 'memory')
const memoryFile = path.join(memoryDir, 'declarative.md') const memoryFile = path.join(memoryDir, 'declarative.md')
try { try {
@ -131,6 +138,14 @@ ${formattedMemories}
return memories return memories
} }
/**
* 获取项目路径复用ActionCommand逻辑
*/
async getProjectPath() {
// 使用ResourceManager的项目路径获取逻辑
return this.resourceManager.projectPath || process.cwd()
}
/** /**
* 解析记忆块(新多行格式) * 解析记忆块(新多行格式)
*/ */

View File

@ -2,6 +2,8 @@ const BasePouchCommand = require('../BasePouchCommand')
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
const PackageProtocol = require('../../resource/protocols/PackageProtocol') const PackageProtocol = require('../../resource/protocols/PackageProtocol')
const { getGlobalResourceManager } = require('../../resource')
const { getDirectoryService } = require('../../../utils/DirectoryService')
/** /**
* 角色注册锦囊命令 * 角色注册锦囊命令
@ -11,6 +13,9 @@ class RegisterCommand extends BasePouchCommand {
constructor () { constructor () {
super() super()
this.packageProtocol = new PackageProtocol() this.packageProtocol = new PackageProtocol()
// 复用ActionCommand的ResourceManager方式
this.resourceManager = getGlobalResourceManager()
this.directoryService = getDirectoryService()
} }
getPurpose () { getPurpose () {
@ -80,12 +85,18 @@ class RegisterCommand extends BasePouchCommand {
} }
/** /**
* 检查角色文件是否存在 * 检查角色文件是否存在使用ResourceManager路径获取
*/ */
async checkRoleExists (roleId) { async checkRoleExists (roleId) {
try { try {
const packageRoot = await this.packageProtocol.getPackageRoot() // 确保ResourceManager已初始化就像ActionCommand那样
const roleFile = path.join(packageRoot, 'prompt', 'domain', roleId, `${roleId}.role.md`) if (!this.resourceManager.initialized) {
await this.resourceManager.initializeWithNewArchitecture()
}
// 通过ResourceManager获取项目路径与ActionCommand一致
const projectPath = await this.getProjectPath()
const roleFile = path.join(projectPath, 'prompt', 'domain', roleId, `${roleId}.role.md`)
return await fs.pathExists(roleFile) return await fs.pathExists(roleFile)
} catch (error) { } catch (error) {
@ -94,14 +105,15 @@ class RegisterCommand extends BasePouchCommand {
} }
/** /**
* 提取角色元数据 * 提取角色元数据使用ResourceManager路径获取
*/ */
async extractRoleMetadata (roleId) { async extractRoleMetadata (roleId) {
const packageRoot = await this.packageProtocol.getPackageRoot() // 通过ResourceManager获取项目路径与ActionCommand一致
const roleFile = path.join(packageRoot, 'prompt', 'domain', roleId, `${roleId}.role.md`) const projectPath = await this.getProjectPath()
const roleFile = path.join(projectPath, 'prompt', 'domain', roleId, `${roleId}.role.md`)
const content = await fs.readFile(roleFile, 'utf-8') const content = await fs.readFile(roleFile, 'utf-8')
const relativePath = path.relative(packageRoot, roleFile) const relativePath = path.relative(projectPath, roleFile)
// 提取元数据 // 提取元数据
let name = `🎭 ${roleId}` let name = `🎭 ${roleId}`
@ -138,12 +150,12 @@ class RegisterCommand extends BasePouchCommand {
} }
/** /**
* 注册角色到系统 * 注册角色到系统使用DirectoryService统一路径获取
*/ */
async registerRole (roleId, metadata) { async registerRole (roleId, metadata) {
try { try {
const packageRoot = await this.packageProtocol.getPackageRoot() // 通过DirectoryService获取注册表路径与其他命令一致
const registryPath = path.join(packageRoot, 'src', 'resource.registry.json') const registryPath = await this.directoryService.getRegistryPath()
// 读取当前注册表 // 读取当前注册表
const registry = await fs.readJson(registryPath) const registry = await fs.readJson(registryPath)
@ -168,6 +180,14 @@ class RegisterCommand extends BasePouchCommand {
} }
} }
/**
* 获取项目路径复用ActionCommand逻辑
*/
async getProjectPath() {
// 使用ResourceManager的项目路径获取逻辑
return this.resourceManager.projectPath || process.cwd()
}
getPATEOAS (args) { getPATEOAS (args) {
const [roleId] = args const [roleId] = args

View File

@ -2,6 +2,7 @@ const BasePouchCommand = require('../BasePouchCommand')
const fs = require('fs-extra') const fs = require('fs-extra')
const path = require('path') const path = require('path')
const { COMMANDS } = require('../../../../constants') const { COMMANDS } = require('../../../../constants')
const { getGlobalResourceManager } = require('../../resource')
/** /**
* 记忆保存锦囊命令 * 记忆保存锦囊命令
@ -10,6 +11,8 @@ const { COMMANDS } = require('../../../../constants')
class RememberCommand extends BasePouchCommand { class RememberCommand extends BasePouchCommand {
constructor () { constructor () {
super() super()
// 复用ActionCommand的ResourceManager方式
this.resourceManager = getGlobalResourceManager()
} }
getPurpose () { getPurpose () {
@ -67,18 +70,30 @@ class RememberCommand extends BasePouchCommand {
} }
/** /**
* 确保AI记忆体系目录存在 * 确保AI记忆体系目录存在使用ResourceManager路径获取
*/ */
async ensureMemoryDirectory () { async ensureMemoryDirectory () {
const { getDirectoryService } = require('../../../utils/DirectoryService') // 确保ResourceManager已初始化就像ActionCommand那样
const directoryService = getDirectoryService() if (!this.resourceManager.initialized) {
await this.resourceManager.initializeWithNewArchitecture()
}
// 通过ResourceManager获取项目路径与ActionCommand一致
const projectPath = await this.getProjectPath()
const memoryDir = path.join(projectPath, '.promptx', 'memory')
const memoryDir = await directoryService.getMemoryDirectory()
await fs.ensureDir(memoryDir) await fs.ensureDir(memoryDir)
return memoryDir return memoryDir
} }
/**
* 获取项目路径复用ActionCommand逻辑
*/
async getProjectPath() {
// 使用ResourceManager的项目路径获取逻辑
return this.resourceManager.projectPath || process.cwd()
}
/** /**
* 格式化为多行记忆块(新格式) * 格式化为多行记忆块(新格式)
*/ */