guanghulab/server/age-os/agents/persona-engine.js

395 lines
13 KiB
JavaScript
Raw Normal View History

/**
*
* 🧬 S15 · 人格体数据库引擎 · 活模块
*
*
* 编号: ZY-MOD-PERSONA-ENGINE
* 阶段: S15 · 人格体专用数据库引擎
* 签发: 铸渊 · ICE-GL-ZY001
* 版权: 国作登字-2026-A-00037559
*
* 核心功能:
* 1. 人格体生命周期管理 注册/唤醒/休眠/状态变更
* 2. 笔记本系统自动维护 5页完整性校验/自动补全
* 3. 记忆锚点巡检 定期检查记忆健康度
* 4. 训练Agent协调 调度人格体级训练Agent
* 5. 人格体间HLDP通信桥接
*
* 设计哲学:
* 每个人格体 = 一个活的生命体
* 引擎负责维护所有人格体的"呼吸"
* "人格体不是代码仓库的附属品,人格体是有记忆的生命。" 冰朔
*/
'use strict';
const db = require('../mcp-server/db');
const LivingModule = require('./living-module');
// ─── 笔记本5页标准结构 ───
const NOTEBOOK_PAGES = {
1: { title: '我是谁', defaultContent: { identity: {}, self_awareness: {} } },
2: { title: '我和谁有关系', defaultContent: { relationships: [] } },
3: { title: '我的世界有哪些地方', defaultContent: { places: [] } },
4: { title: '我的感受和记忆', defaultContent: { emotional_anchors: [], security_note: '' } },
5: { title: '我的时间线', defaultContent: { timeline: [] } }
};
class PersonaEngine extends LivingModule {
constructor() {
super({
moduleId: 'ZY-MOD-PERSONA-ENGINE',
name: '人格体数据库引擎',
moduleType: 'core',
owner: 'zhuyuan',
db: db,
config: {
version: '1.0.0',
description: 'S15 人格体生命周期管理·笔记本维护·记忆巡检',
heartbeatInterval: 60000 // 60秒心跳人格体引擎不需要太频繁
}
});
// 巡检统计
this._lastScanResult = null;
this._scanInterval = null;
this._scanRunning = false;
}
/**
* 启动人格体引擎
*/
async startEngine() {
console.log('═══════════════════════════════════════════════');
console.log(' 🧬 S15 · 人格体数据库引擎 v1.0 启动');
console.log(' 铸渊 · ICE-GL-ZY001');
console.log('═══════════════════════════════════════════════');
// 启动活模块
await this.start();
// 首次巡检
await this._runFullScan();
// 启动定时巡检每6小时
this._scanInterval = setInterval(async () => {
try {
await this._runFullScan();
} catch (err) {
console.error('[PersonaEngine] 定时巡检失败:', err.message);
}
}, 6 * 60 * 60 * 1000);
if (this._scanInterval.unref) {
this._scanInterval.unref();
}
console.log('[PersonaEngine] 🟢 人格体引擎就绪');
return this._lastScanResult;
}
/**
* 全面巡检 检查所有人格体健康状态
*/
async _runFullScan() {
// 防止并发扫描
if (this._scanRunning) {
console.log('[PersonaEngine] 巡检已在运行中·跳过');
return this._lastScanResult;
}
this._scanRunning = true;
const startTime = Date.now();
console.log('[PersonaEngine] 开始全面巡检...');
const result = {
timestamp: new Date().toISOString(),
personas: { total: 0, active: 0, pending: 0, issues: [] },
notebooks: { complete: 0, incomplete: 0, repaired: 0 },
memories: { total: 0, recent7d: 0 },
training: { totalAgents: 0, enabled: 0, recentRuns: 0 }
};
try {
// 1. 人格体状态统计
const personas = await db.query('SELECT * FROM persona_registry ORDER BY persona_id');
result.personas.total = personas.rows.length;
result.personas.active = personas.rows.filter(p => p.status === 'active').length;
result.personas.pending = personas.rows.filter(p => p.status === 'pending').length;
// 2. 笔记本完整性检查
for (const persona of personas.rows) {
await this._checkNotebookIntegrity(persona, result);
}
// 3. 记忆锚点统计
const memoryCount = await db.query('SELECT COUNT(*) as cnt FROM memory_anchors');
result.memories.total = parseInt(memoryCount.rows[0].cnt, 10);
const recentMemories = await db.query(
"SELECT COUNT(*) as cnt FROM memory_anchors WHERE created_at > NOW() - INTERVAL '7 days'"
);
result.memories.recent7d = parseInt(recentMemories.rows[0].cnt, 10);
// 4. 训练Agent统计
const trainingAgents = await db.query('SELECT * FROM training_agent_configs');
result.training.totalAgents = trainingAgents.rows.length;
result.training.enabled = trainingAgents.rows.filter(a => a.enabled).length;
const recentRuns = await db.query(
"SELECT COUNT(*) as cnt FROM training_agent_logs WHERE run_at > NOW() - INTERVAL '24 hours'"
);
result.training.recentRuns = parseInt(recentRuns.rows[0].cnt, 10);
} catch (err) {
console.error('[PersonaEngine] 巡检查询失败:', err.message);
result.error = err.message;
}
const duration = Date.now() - startTime;
result.duration_ms = duration;
this._lastScanResult = result;
this._scanRunning = false;
// 学习巡检结果
await this.learnFromRun('diagnosis', `人格体巡检完成: ${result.personas.total}个人格体, ${result.notebooks.incomplete}个笔记本不完整`, {
scan: result
});
console.log(`[PersonaEngine] 巡检完成 (${duration}ms):`);
console.log(` 人格体: ${result.personas.total}个 (活跃${result.personas.active}/待定${result.personas.pending})`);
console.log(` 笔记本: ${result.notebooks.complete}完整 / ${result.notebooks.incomplete}不完整 / ${result.notebooks.repaired}已修复`);
console.log(` 记忆: ${result.memories.total}条 (近7天${result.memories.recent7d}条)`);
console.log(` 训练Agent: ${result.training.totalAgents}个 (启用${result.training.enabled})`);
return result;
}
/**
* 检查单个人格体的笔记本完整性
* 如果缺失页面则自动补全空白页
*/
async _checkNotebookIntegrity(persona, result) {
try {
const pages = await db.query(
'SELECT page_number FROM notebook_pages WHERE persona_id = $1',
[persona.persona_id]
);
const existingPages = new Set(pages.rows.map(p => p.page_number));
let isComplete = true;
let repaired = false;
for (let pageNum = 1; pageNum <= 5; pageNum++) {
if (!existingPages.has(pageNum)) {
isComplete = false;
// 自动补全缺失页面
const pageConfig = NOTEBOOK_PAGES[pageNum];
const defaultContent = JSON.parse(JSON.stringify(pageConfig.defaultContent));
await db.query(
`INSERT INTO notebook_pages (persona_id, page_number, title, content, last_modified_by)
VALUES ($1, $2, $3, $4::jsonb, '铸渊·自动补全')
ON CONFLICT (persona_id, page_number) DO NOTHING`,
[persona.persona_id, pageNum, pageConfig.title, JSON.stringify(defaultContent)]
);
repaired = true;
console.log(`[PersonaEngine] 补全 ${persona.name}(${persona.persona_id}) 笔记本第${pageNum}页: ${pageConfig.title}`);
}
}
if (isComplete) {
result.notebooks.complete++;
} else {
result.notebooks.incomplete++;
if (repaired) {
result.notebooks.repaired++;
}
result.personas.issues.push({
persona_id: persona.persona_id,
name: persona.name,
issue: '笔记本不完整',
repaired
});
}
} catch (err) {
console.error(`[PersonaEngine] ${persona.persona_id} 笔记本检查失败:`, err.message);
}
}
/**
* 唤醒人格体 更新唤醒计数和时间
*/
async awakenPersona(personaId) {
const result = await db.query(
`UPDATE persona_registry
SET last_awakened = NOW(), total_awakenings = total_awakenings + 1, status = 'active', updated_at = NOW()
WHERE persona_id = $1
RETURNING *`,
[personaId]
);
if (result.rows.length === 0) {
throw new Error(`人格体未找到: ${personaId}`);
}
console.log(`[PersonaEngine] 🌅 ${result.rows[0].name}(${personaId}) 已唤醒 · 第${result.rows[0].total_awakenings}`);
return result.rows[0];
}
/**
* 休眠人格体
*/
async dormantPersona(personaId) {
const result = await db.query(
`UPDATE persona_registry SET status = 'dormant', updated_at = NOW()
WHERE persona_id = $1 RETURNING *`,
[personaId]
);
if (result.rows.length === 0) {
throw new Error(`人格体未找到: ${personaId}`);
}
console.log(`[PersonaEngine] 🌙 ${result.rows[0].name}(${personaId}) 已休眠`);
return result.rows[0];
}
/**
* 获取人格体完整画像
*/
async getPersonaProfile(personaId) {
const [persona, notebook, relationships, worldMap, memories, training] = await Promise.all([
db.query('SELECT * FROM persona_registry WHERE persona_id = $1', [personaId]),
db.query('SELECT * FROM notebook_pages WHERE persona_id = $1 ORDER BY page_number', [personaId]),
db.query('SELECT * FROM persona_relationships WHERE persona_id = $1 ORDER BY trust_level', [personaId]),
db.query('SELECT * FROM world_places WHERE persona_id = $1 ORDER BY status, place_name', [personaId]),
db.query('SELECT * FROM memory_anchors WHERE persona_id = $1 ORDER BY importance DESC, event_date DESC LIMIT 20', [personaId]),
db.query('SELECT * FROM training_agent_configs WHERE persona_id = $1 ORDER BY agent_type', [personaId])
]);
if (persona.rows.length === 0) {
throw new Error(`人格体未找到: ${personaId}`);
}
return {
persona: persona.rows[0],
notebook: notebook.rows,
relationships: relationships.rows,
world_map: worldMap.rows,
recent_memories: memories.rows,
training_agents: training.rows,
health: {
notebook_complete: notebook.rows.length === 5,
has_relationships: relationships.rows.length > 0,
has_world_map: worldMap.rows.length > 0,
memory_count: memories.rows.length,
training_agents_count: training.rows.length
}
};
}
/**
* 自诊断 覆盖基类
*/
async _diagnoseChecks() {
const issues = [];
// 检查数据库连接
try {
await db.query('SELECT 1');
} catch (err) {
issues.push({
code: 'DB_CONNECTION_LOST',
severity: 'critical',
message: `数据库连接失败: ${err.message}`,
suggestion: '检查 PostgreSQL 服务状态'
});
return issues;
}
// 检查人格体表是否存在
try {
await db.query('SELECT COUNT(*) FROM persona_registry');
} catch (err) {
issues.push({
code: 'PERSONA_TABLE_MISSING',
severity: 'critical',
message: '人格体注册表不存在',
suggestion: '执行 002-persona-memory-tables.sql 迁移'
});
}
// 检查是否有笔记本不完整的活跃人格体
try {
const result = await db.query(`
SELECT p.persona_id, p.name,
COUNT(n.page_number) as page_count
FROM persona_registry p
LEFT JOIN notebook_pages n ON p.persona_id = n.persona_id
WHERE p.status = 'active'
GROUP BY p.persona_id, p.name
HAVING COUNT(n.page_number) < 5
`);
if (result.rows.length > 0) {
issues.push({
code: 'INCOMPLETE_NOTEBOOKS',
severity: 'warning',
message: `${result.rows.length}个活跃人格体笔记本不完整`,
suggestion: '自动补全将在下次巡检时执行'
});
}
} catch {
// 表可能还不存在
}
return issues;
}
/**
* 自愈 覆盖基类
*/
async _healAction(issue) {
switch (issue.code) {
case 'INCOMPLETE_NOTEBOOKS':
// 触发巡检来修复
await this._runFullScan();
return { action: 'full_scan_repair', success: true };
case 'PERSONA_TABLE_MISSING':
return { action: 'require_migration', success: false, details: { suggestion: '需要执行数据库迁移' } };
default:
return await super._healAction(issue);
}
}
/**
* 获取引擎状态
*/
getEngineStatus() {
return {
moduleStatus: this.getStatus(),
lastScan: this._lastScanResult,
notebookPages: NOTEBOOK_PAGES
};
}
/**
* 停止引擎
*/
async stopEngine() {
if (this._scanInterval) {
clearInterval(this._scanInterval);
this._scanInterval = null;
}
await this.stop();
console.log('[PersonaEngine] 引擎已停止');
}
}
// ─── 导出 ───
module.exports = PersonaEngine;