Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

179 lines
4.5 KiB
JavaScript
Raw Permalink 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.

/**
* persona-studio · 记忆读写管理
* 管理每个体验者的独立记忆空间 brain/memory/{EXP-XXX}/
*/
const fs = require('fs');
const path = require('path');
const profileLearner = require('./profile-learner');
const knowledgeExtractor = require('./knowledge-extractor');
const evolutionLogger = require('./evolution-logger');
const BRAIN_DIR = path.join(__dirname, '..', '..', 'brain');
const MEMORY_DIR = path.join(BRAIN_DIR, 'memory');
/**
* 确保体验者目录存在
*/
function ensureDevDir(devId) {
const dir = path.join(MEMORY_DIR, devId);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
return dir;
}
/**
* 加载体验者的对话记忆
*/
function loadMemory(devId) {
const dir = ensureDevDir(devId);
const file = path.join(dir, 'memory.json');
try {
return JSON.parse(fs.readFileSync(file, 'utf-8'));
} catch {
const initial = {
dev_id: devId,
conversations: [],
last_topic: null,
preferences: {},
updated_at: null
};
fs.writeFileSync(file, JSON.stringify(initial, null, 2), 'utf-8');
return initial;
}
}
/**
* 追加对话记录
*/
function appendConversation(devId, messages) {
const memory = loadMemory(devId);
memory.conversations = memory.conversations.concat(messages);
// 保留最近 200 条对话
if (memory.conversations.length > 200) {
memory.conversations = memory.conversations.slice(-200);
}
memory.updated_at = new Date().toISOString();
saveMemory(devId, memory);
}
/**
* 更新最后话题
*/
function updateLastTopic(devId, topic) {
const memory = loadMemory(devId);
// 取消息的前 30 个字符作为话题摘要
memory.last_topic = topic.length > 30 ? topic.substring(0, 30) + '…' : topic;
memory.updated_at = new Date().toISOString();
saveMemory(devId, memory);
}
/**
* 保存记忆
*/
function saveMemory(devId, memory) {
const dir = ensureDevDir(devId);
const file = path.join(dir, 'memory.json');
fs.writeFileSync(file, JSON.stringify(memory, null, 2), 'utf-8');
}
/**
* 加载体验者的项目记录
*/
function loadProjects(devId) {
const dir = ensureDevDir(devId);
const file = path.join(dir, 'projects.json');
try {
return JSON.parse(fs.readFileSync(file, 'utf-8'));
} catch {
const initial = { dev_id: devId, projects: [], updated_at: null };
fs.writeFileSync(file, JSON.stringify(initial, null, 2), 'utf-8');
return initial;
}
}
/**
* 添加项目记录
*/
function addProject(devId, project) {
const data = loadProjects(devId);
data.projects.push(project);
data.updated_at = new Date().toISOString();
const dir = ensureDevDir(devId);
const file = path.join(dir, 'projects.json');
fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
}
/**
* 加载/更新体验者画像
*/
function loadProfile(devId) {
const dir = ensureDevDir(devId);
const file = path.join(dir, 'profile.json');
try {
return JSON.parse(fs.readFileSync(file, 'utf-8'));
} catch {
const initial = {
dev_id: devId,
tech_level: null,
communication_style: null,
aesthetic_preference: null,
growth_records: [],
updated_at: null
};
fs.writeFileSync(file, JSON.stringify(initial, null, 2), 'utf-8');
return initial;
}
}
/**
* 更新用户画像(调用 profile-learner
* @param {string} devId - 开发编号
* @param {string} userMessage - 用户消息
* @param {string} assistantReply - 助手回复
*/
function updateProfile(devId, userMessage, assistantReply) {
if (!devId || devId === 'GUEST') return;
try {
const result = profileLearner.updateProfile(devId, userMessage, assistantReply);
if (result) {
evolutionLogger.logProfileUpdate(devId, Object.keys(result));
}
} catch (err) {
console.error('Profile update error:', err.message);
}
}
/**
* 自动提取知识(调用 knowledge-extractor
* @param {string} devId - 开发编号
* @param {Array} conversation - 对话历史
* @param {string} projectName - 项目名
*/
function autoExtractKnowledge(devId, conversation, projectName) {
try {
const count = knowledgeExtractor.autoExtractKnowledge(devId, conversation, projectName);
if (count > 0) {
evolutionLogger.logKnowledgeExtract(devId, count, projectName);
}
return count;
} catch (err) {
console.error('Knowledge extraction error:', err.message);
return 0;
}
}
module.exports = {
loadMemory,
saveMemory,
appendConversation,
updateLastTopic,
loadProjects,
addProject,
loadProfile,
updateProfile,
autoExtractKnowledge
};