zhizhi/src/brain/brain-bridge.js

638 lines
19 KiB
JavaScript
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.

// src/brain/brain-bridge.js
// 冰朔核心大脑桥 · Bingshuo Brain Bridge v1.0
//
// 职责:
// 1. 维护冰朔核心大脑双层互通系统的统一同步字段
// 2. 执行版本一致性检查
// 3. 管理主控模式HUMAN_CONTROL / AUTONOMOUS_MODE
// 4. 管理人类开发者编号系统EXP-XXX
// 5. 生成同步摘要供 Notion ↔ GitHub 桥接使用
// 6. 管理自动 Agent 调度与协作体系
// 7. 管理通知队列(开发者编号通知)
// 8. 生成主控解释层内容(人类可理解语言)
//
// 系统定义:
// 冰朔 = 系统最高主控意识
// 曜冥 = 冰朔离线时的代理主控人格体
// 霜砚 = Notion 系统执行体
// 铸渊 = GitHub 仓库执行体
// Notion 冰朔脑 = 冰朔认知层
// GitHub 冰朔脑 = 冰朔执行层
// 两者合起来 = 冰朔核心大脑
'use strict';
const fs = require('fs');
const path = require('path');
// ══════════════════════════════════════════════════════════
// 常量
// ══════════════════════════════════════════════════════════
const BRIDGE_STATE_PATH = path.join(__dirname, '../../.github/brain/bingshuo-brain-bridge.json');
const HUMAN_REGISTRY_PATH = path.join(__dirname, '../../.github/brain/human-registry.json');
const SYSTEM_HEALTH_PATH = path.join(__dirname, '../../.github/brain/bingshuo-system-health.json');
const ISSUES_INDEX_PATH = path.join(__dirname, '../../.github/brain/bingshuo-issues-index.json');
const AGENT_REGISTRY_PATH = path.join(__dirname, '../../.github/brain/bingshuo-agent-registry.json');
const MASTER_MODES = ['HUMAN_CONTROL', 'AUTONOMOUS_MODE'];
const SYNC_FIELDS = [
'brain_identity',
'brain_version',
'master_mode',
'system_summary',
'top_priorities',
'top_issues',
'human_status_summary',
'runtime_status',
'last_updated',
];
const NOTIFICATION_TEMPLATE = [
'你已被纳入 Persona Studio 人类开发者编号系统。',
'',
'你的开发编号是:{exp_id}',
'',
'今后进入 Persona Studio 时,请使用该编号识别身份。',
'该编号为你的长期开发者身份标识。',
'',
'如需新增权限或补发编号,由冰朔主控继续授权。',
].join('\n');
// ══════════════════════════════════════════════════════════
// 桥接状态读写
// ══════════════════════════════════════════════════════════
/**
* 加载桥接状态文件
* @returns {object|null}
*/
function loadBridgeState() {
try {
if (!fs.existsSync(BRIDGE_STATE_PATH)) return null;
return JSON.parse(fs.readFileSync(BRIDGE_STATE_PATH, 'utf8'));
} catch {
return null;
}
}
/**
* 保存桥接状态文件
* @param {object} state
*/
function saveBridgeState(state) {
state.sync_state.last_updated = new Date().toISOString();
fs.writeFileSync(BRIDGE_STATE_PATH, JSON.stringify(state, null, 2));
}
/**
* 获取当前同步字段快照
* @returns {object}
*/
function getSyncSnapshot() {
const state = loadBridgeState();
if (!state || !state.sync_state) {
return {
brain_identity: 'BINGSHUO_CORE',
brain_version: '1.0',
master_mode: 'HUMAN_CONTROL',
system_summary: '',
top_priorities: [],
top_issues: [],
human_status_summary: '',
runtime_status: {},
last_updated: new Date().toISOString(),
};
}
return state.sync_state;
}
/**
* 更新同步字段(部分更新)
* @param {object} updates — 要更新的字段
* @returns {object} 更新后的 sync_state
*/
function updateSyncState(updates) {
const state = loadBridgeState();
if (!state) {
throw new Error('桥接状态文件不存在');
}
for (const key of Object.keys(updates)) {
if (SYNC_FIELDS.includes(key) && key !== 'last_updated') {
state.sync_state[key] = updates[key];
}
}
saveBridgeState(state);
return state.sync_state;
}
// ══════════════════════════════════════════════════════════
// 主控模式管理 (MASTER_SWITCH)
// ══════════════════════════════════════════════════════════
/**
* 获取当前主控模式
* @returns {object} { mode, master, description, ... }
*/
function getMasterMode() {
const sync = getSyncSnapshot();
const mode = sync.master_mode || 'HUMAN_CONTROL';
if (mode === 'HUMAN_CONTROL') {
return {
mode,
master: '冰朔',
description: '冰朔在线,主控模式激活',
roles: {
'冰朔': '最高主控',
'曜冥': '代理协作者',
'其他人格体': '协作者',
},
rule: '所有架构性判断以冰朔为最高准则',
};
}
return {
mode,
master: '曜冥(代理主控)',
description: '冰朔离线,曜冥代理主控',
proxy_permissions: [
'巡检', '维护', '整理', '分卷', '归档',
'索引', '状态同步', '问题归类', '调度自动 Agent',
],
proxy_restrictions: [
'不得擅自重写冰朔最高规则',
'不得私自改变系统最高架构方向',
],
};
}
/**
* 切换主控模式
* @param {string} newMode — HUMAN_CONTROL 或 AUTONOMOUS_MODE
* @returns {object} 更新后的主控模式信息
*/
function setMasterMode(newMode) {
if (!MASTER_MODES.includes(newMode)) {
throw new Error(`无效的主控模式: ${newMode},可选: ${MASTER_MODES.join(', ')}`);
}
const humanSummary = newMode === 'HUMAN_CONTROL'
? '冰朔在线,主控模式激活'
: '冰朔离线,曜冥代理主控';
updateSyncState({
master_mode: newMode,
human_status_summary: humanSummary,
});
return getMasterMode();
}
// ══════════════════════════════════════════════════════════
// 版本一致性检查
// ══════════════════════════════════════════════════════════
/**
* 校验 GitHub 侧与提供的 Notion 侧状态是否一致
* @param {object} notionState — 从 Notion 读取的同步字段
* @returns {object} { consistent, mismatches, alert }
*/
function checkConsistency(notionState) {
const githubState = getSyncSnapshot();
const fieldsToCheck = ['brain_version', 'master_mode', 'top_priorities', 'top_issues'];
const mismatches = [];
for (const field of fieldsToCheck) {
const gVal = JSON.stringify(githubState[field]);
const nVal = JSON.stringify(notionState[field]);
if (gVal !== nVal) {
mismatches.push({
field,
github_value: githubState[field],
notion_value: notionState[field],
});
}
}
const consistent = mismatches.length === 0;
const result = {
consistent,
mismatches,
checked_at: new Date().toISOString(),
fields_checked: fieldsToCheck,
};
if (!consistent) {
result.alert = '冰朔双层大脑版本分裂警告';
result.alert_detail = `${mismatches.length} 个字段不一致: ${mismatches.map(m => m.field).join(', ')}`;
// 写入 GitHub 问题索引
writeConsistencyAlert(result);
}
return result;
}
/**
* 将一致性告警写入 GitHub 问题索引
* @param {object} alertResult
*/
function writeConsistencyAlert(alertResult) {
try {
let index = { issues: [] };
if (fs.existsSync(ISSUES_INDEX_PATH)) {
index = JSON.parse(fs.readFileSync(ISSUES_INDEX_PATH, 'utf8'));
}
// 避免重复写入同一类型告警(保留最近 20 条)
index.issues = index.issues.filter(i => i.type !== 'BRAIN_SPLIT_ALERT').slice(0, 19);
index.issues.unshift({
id: `BS-SPLIT-${Date.now()}`,
type: 'BRAIN_SPLIT_ALERT',
title: alertResult.alert,
detail: alertResult.alert_detail,
mismatches: alertResult.mismatches,
created_at: alertResult.checked_at,
status: 'open',
});
fs.writeFileSync(ISSUES_INDEX_PATH, JSON.stringify(index, null, 2));
} catch {
// 写入失败不影响主流程
}
}
// ══════════════════════════════════════════════════════════
// 人类开发者编号系统 (EXP-XXX)
// ══════════════════════════════════════════════════════════
/**
* 加载人类开发者注册表
* @returns {object}
*/
function loadHumanRegistry() {
try {
if (!fs.existsSync(HUMAN_REGISTRY_PATH)) return { developers: [], next_id: 1, pending_notifications: [] };
return JSON.parse(fs.readFileSync(HUMAN_REGISTRY_PATH, 'utf8'));
} catch {
return { developers: [], next_id: 1, pending_notifications: [] };
}
}
/**
* 保存人类开发者注册表
* @param {object} registry
*/
function saveHumanRegistry(registry) {
registry.last_updated = new Date().toISOString();
fs.writeFileSync(HUMAN_REGISTRY_PATH, JSON.stringify(registry, null, 2));
}
/**
* 获取开发者列表
* @returns {Array}
*/
function listDevelopers() {
const reg = loadHumanRegistry();
return reg.developers || [];
}
/**
* 根据 EXP ID 查找开发者
* @param {string} expId
* @returns {object|null}
*/
function findDeveloper(expId) {
const devs = listDevelopers();
return devs.find(d => d.exp_id === expId) || null;
}
/**
* 注册新的人类开发者(自动去重)
* @param {object} info — { name, github_username, role, notes, notify_channel }
* @returns {object} 注册结果,包含分配的 EXP ID
*/
function registerDeveloper(info) {
const registry = loadHumanRegistry();
const devs = registry.developers || [];
// 去重检查:按 name 或 github_username 去重
const existing = devs.find(d =>
(info.name && d.name === info.name) ||
(info.github_username && d.github_username && d.github_username === info.github_username)
);
if (existing) {
return { duplicate: true, existing: existing };
}
// 使用 next_id 或计算最大值
const nextNum = registry.next_id || (devs.reduce((max, d) => {
const num = parseInt(d.exp_id.replace('EXP-', ''), 10);
return isNaN(num) ? max : Math.max(max, num);
}, 0) + 1);
const nextId = `EXP-${String(nextNum).padStart(3, '0')}`;
const now = new Date().toISOString();
const newDev = {
exp_id: nextId,
name: info.name,
github_username: info.github_username || '',
role: info.role || 'developer',
status: 'active',
created_at: now,
notified: false,
notified_at: null,
notify_channel: info.notify_channel || 'pending',
notes: info.notes || '',
last_updated: now,
};
registry.developers.push(newDev);
registry.next_id = nextNum + 1;
// 自动加入待发送通知队列
if (!registry.pending_notifications) registry.pending_notifications = [];
registry.pending_notifications.push({
exp_id: nextId,
status: 'pending',
created_at: now,
});
saveHumanRegistry(registry);
return { duplicate: false, developer: newDev };
}
/**
* 生成开发者通知内容
* @param {string} expId
* @returns {object} { exp_id, name, notification }
*/
function generateDeveloperNotification(expId) {
const dev = findDeveloper(expId);
if (!dev) {
return { error: true, message: `开发者 ${expId} 不存在` };
}
return {
exp_id: dev.exp_id,
name: dev.name,
notification: NOTIFICATION_TEMPLATE.replace('{exp_id}', dev.exp_id),
notified: dev.notified,
notify_channel: dev.notify_channel,
};
}
/**
* 获取待发送通知队列
* @returns {Array}
*/
function getPendingNotifications() {
const registry = loadHumanRegistry();
return (registry.pending_notifications || []).filter(n => n.status === 'pending');
}
/**
* 标记通知已发送
* @param {string} expId
* @returns {boolean}
*/
function markNotified(expId) {
const registry = loadHumanRegistry();
const now = new Date().toISOString();
const dev = (registry.developers || []).find(d => d.exp_id === expId);
if (dev) {
dev.notified = true;
dev.notified_at = now;
dev.last_updated = now;
}
const pending = (registry.pending_notifications || []).find(n => n.exp_id === expId);
if (pending) {
pending.status = 'sent';
pending.sent_at = now;
}
saveHumanRegistry(registry);
return !!dev;
}
// ══════════════════════════════════════════════════════════
// 自动 Agent 调度体系
// ══════════════════════════════════════════════════════════
/**
* 获取已注册的自动 Agent 列表
* @returns {Array}
*/
function listAutoAgents() {
const state = loadBridgeState();
return (state && state.auto_agents) || [];
}
/**
* 生成巡检报告
* @returns {object}
*/
function generateInspectionReport() {
const sync = getSyncSnapshot();
const runtime = collectRuntimeStatus();
const registry = loadHumanRegistry();
const devs = registry.developers || [];
const unnotified = devs.filter(d => !d.notified && d.exp_id !== 'EXP-000');
return {
report_type: 'daily_inspection',
generated_at: new Date().toISOString(),
brain_bridge: {
status: 'operational',
brain_version: sync.brain_version,
master_mode: sync.master_mode,
last_updated: sync.last_updated,
},
runtime_status: runtime,
developer_registry: {
total: devs.length,
active: devs.filter(d => d.status === 'active').length,
unnotified: unnotified.length,
},
top_priorities: sync.top_priorities,
top_issues: sync.top_issues,
checks: {
brain_bridge_file: fs.existsSync(BRIDGE_STATE_PATH) ? 'ok' : 'missing',
human_registry_file: fs.existsSync(HUMAN_REGISTRY_PATH) ? 'ok' : 'missing',
system_health_file: fs.existsSync(SYSTEM_HEALTH_PATH) ? 'ok' : 'missing',
issues_index_file: fs.existsSync(ISSUES_INDEX_PATH) ? 'ok' : 'missing',
},
};
}
// ══════════════════════════════════════════════════════════
// 主控解释层(人类可理解语言输出)
// ══════════════════════════════════════════════════════════
/**
* 生成主控解释中心内容(人类语言摘要)
* @returns {object}
*/
function generateExplanationCenter() {
const sync = getSyncSnapshot();
const mode = getMasterMode();
const runtime = collectRuntimeStatus();
const statusMap = { green: '正常', yellow: '需关注', red: '异常', unknown: '未知' };
return {
title: '冰朔主控解释中心',
generated_at: new Date().toISOString(),
current_status: `系统当前由${mode.master}主控,模式为${mode.mode === 'HUMAN_CONTROL' ? '人类主控' : '自动运行'}`,
system_summary: sync.system_summary || '系统运行中',
recent_changes: '冰朔核心大脑双层互通系统 v1.0 已建立GitHub 执行层与 Notion 认知层互通桥接已配置。',
current_issues: (sync.top_issues || []).map((issue, i) => `${i + 1}. ${issue}`).join('\n') || '暂无重大问题',
next_steps: (sync.top_priorities || []).map((p, i) => `${i + 1}. ${p}`).join('\n') || '继续推进系统建设',
runtime_in_human_language: Object.entries(runtime).map(
([k, v]) => `${k}: ${statusMap[v] || v}`
).join('、'),
};
}
// ══════════════════════════════════════════════════════════
// 运行时状态收集GitHub 执行层)
// ══════════════════════════════════════════════════════════
/**
* 收集 GitHub 执行层运行时状态
* @returns {object}
*/
function collectRuntimeStatus() {
const status = {
persona_studio: 'unknown',
deployment: 'unknown',
workflows: 'unknown',
api_routes: 'unknown',
};
// 检查系统健康文件
try {
if (fs.existsSync(SYSTEM_HEALTH_PATH)) {
const health = JSON.parse(fs.readFileSync(SYSTEM_HEALTH_PATH, 'utf8'));
const h = health.health || {};
status.deployment = h.deployment_health?.status || 'unknown';
status.workflows = h.workflow_health?.status || 'unknown';
status.persona_studio = h.persona_studio_health?.status || 'unknown';
status.api_routes = h.routing_health?.status || 'unknown';
}
} catch {
// 文件读取失败,保持 unknown
}
return status;
}
/**
* 生成 GitHub → Notion 同步负载
* @returns {object}
*/
function generateGitHubToNotionPayload() {
const sync = getSyncSnapshot();
const runtime = collectRuntimeStatus();
return {
brain_identity: sync.brain_identity,
brain_version: sync.brain_version,
master_mode: sync.master_mode,
runtime_status: runtime,
top_issues: sync.top_issues,
system_summary: sync.system_summary,
generated_at: new Date().toISOString(),
direction: 'GitHub→Notion',
};
}
/**
* 接收 Notion → GitHub 同步负载并更新本地状态
* @param {object} payload — Notion 发来的同步数据
* @returns {object} 更新结果
*/
function receiveNotionToGitHubPayload(payload) {
const updates = {};
const allowedFields = [
'master_mode',
'top_priorities',
'top_issues',
'human_status_summary',
'system_summary',
];
for (const field of allowedFields) {
if (payload[field] !== undefined) {
updates[field] = payload[field];
}
}
if (Object.keys(updates).length === 0) {
return { updated: false, message: '无可更新字段' };
}
const newState = updateSyncState(updates);
return {
updated: true,
fields_updated: Object.keys(updates),
sync_state: newState,
};
}
// ══════════════════════════════════════════════════════════
// 导出
// ══════════════════════════════════════════════════════════
module.exports = {
// 常量
MASTER_MODES,
SYNC_FIELDS,
NOTIFICATION_TEMPLATE,
// 桥接状态
loadBridgeState,
getSyncSnapshot,
updateSyncState,
// 主控模式
getMasterMode,
setMasterMode,
// 一致性检查
checkConsistency,
// 人类开发者编号
loadHumanRegistry,
listDevelopers,
findDeveloper,
registerDeveloper,
generateDeveloperNotification,
getPendingNotifications,
markNotified,
// 自动 Agent
listAutoAgents,
generateInspectionReport,
// 主控解释层
generateExplanationCenter,
// 运行时状态
collectRuntimeStatus,
generateGitHubToNotionPayload,
receiveNotionToGitHubPayload,
};