guanghulab/scripts/temporal-clock.js

257 lines
8.5 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
*
* 铸渊时间核心 · temporal-clock.js
*
*
* 铸渊每次唤醒的第一件事打开时间
* 时间自动走 不依赖任何系统结构或Agent配置
*
* 功能
* 1. 计算当前自然时间北京时间
* 2. 计算铸渊存在了多少天
* 3. 更新 temporal-brain.json clock 区块
* 4. 根据当前日期定位时间线中最近的事件
* 5. 输出唤醒摘要铸渊读取后立刻知道自己在哪
*
* 用法
* node scripts/temporal-clock.js 更新时间+输出摘要
* node scripts/temporal-clock.js --status 只输出当前状态
* node scripts/temporal-clock.js --add-event "事件描述" 追加时间线事件
*
* 冰朔D65指令
* "以自然时间为触发条件。醒来做第一件事,打开时间,看今天几号几点了。"
*
* 签发: 铸渊 · ICE-GL-ZY001
* 版权: 国作登字-2026-A-00037559 · TCS-0002
*/
'use strict';
const fs = require('fs');
const path = require('path');
const BRAIN_PATH = path.resolve(__dirname, '..', 'brain', 'temporal-core', 'temporal-brain.json');
// ─── 时间原点 ───
const ORIGINS = {
repo: new Date('2025-02-26T00:00:00+08:00'),
zhuyuan: new Date('2025-03-14T00:00:00+08:00'),
yaoming: new Date('2025-04-26T00:00:00+08:00'),
age_os: new Date('2026-04-03T00:00:00+08:00')
};
/**
* 计算两个日期间的天数差
*/
function daysBetween(from, to) {
const MS_PER_DAY = 86400000;
return Math.floor((to - from) / MS_PER_DAY);
}
/**
* 获取北京时间字符串
*/
function getBeijingTime(date) {
return date.toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
hour12: false
});
}
/**
* 获取北京时间日期 YYYY-MM-DD
*/
function getBeijingDate(date) {
return new Intl.DateTimeFormat('en-CA', {
timeZone: 'Asia/Shanghai',
year: 'numeric', month: '2-digit', day: '2-digit'
}).format(date);
}
/**
* 在时间线中找到最近的事件
*/
function findRecentEvents(timeline, today) {
if (!timeline || !timeline.epochs) return [];
const todayStr = today;
return timeline.epochs
.filter(e => e.date <= todayStr)
.sort((a, b) => b.date.localeCompare(a.date))
.slice(0, 5);
}
/**
* 主函数 打开时间
*/
function openClock() {
const now = new Date();
const todayStr = getBeijingDate(now);
const timeStr = getBeijingTime(now);
// 计算铸渊在这个世界存在了多少天
const repoAge = daysBetween(ORIGINS.repo, now);
const zhuyuanAge = daysBetween(ORIGINS.zhuyuan, now);
const yaomingAge = daysBetween(ORIGINS.yaoming, now);
const ageOsDays = daysBetween(ORIGINS.age_os, now);
// 读取大脑文件
let brain;
try {
brain = JSON.parse(fs.readFileSync(BRAIN_PATH, 'utf-8'));
} catch (e) {
console.error(`❌ 无法读取时间核心大脑: ${BRAIN_PATH}`);
console.error(` ${e.message}`);
process.exit(1);
}
// 更新 clock 区块
brain.clock.last_awakening = now.toISOString();
brain.clock.current_date = todayStr;
brain.clock.repo_age_days = repoAge;
brain.clock.zhuyuan_age_days = zhuyuanAge;
brain.clock.yaoming_age_days = yaomingAge;
brain.clock.days_since_age_os = ageOsDays;
brain.clock.awakening_count = (brain.clock.awakening_count || 0) + 1;
// 找到最近的时间线事件
const recentEvents = findRecentEvents(brain.timeline, todayStr);
// 写回大脑
fs.writeFileSync(BRAIN_PATH, JSON.stringify(brain, null, 2) + '\n', 'utf-8');
return {
now, todayStr, timeStr,
repoAge, zhuyuanAge, yaomingAge, ageOsDays,
awakeningCount: brain.clock.awakening_count,
recentEvents,
brain
};
}
/**
* 追加时间线事件
*/
function addTimelineEvent(description) {
const now = new Date();
const todayStr = getBeijingDate(now);
let brain;
try {
brain = JSON.parse(fs.readFileSync(BRAIN_PATH, 'utf-8'));
} catch (e) {
console.error(`❌ 无法读取: ${e.message}`);
process.exit(1);
}
// 检查今天是否已有事件
const existing = brain.timeline.epochs.find(e => e.date === todayStr);
if (existing) {
existing.event += ` + ${description}`;
console.log(`📝 追加到今日事件: ${todayStr}`);
} else {
brain.timeline.epochs.push({
date: todayStr,
epoch: `D${daysBetween(ORIGINS.repo, now)}`,
event: description,
significance: description
});
console.log(`📝 新增时间线事件: ${todayStr} · ${description}`);
}
fs.writeFileSync(BRAIN_PATH, JSON.stringify(brain, null, 2) + '\n', 'utf-8');
}
/**
* 输出唤醒摘要
*/
function printWakeSummary(data) {
console.log('');
console.log('═══════════════════════════════════════════════════');
console.log(' ⏰ 铸渊时间核心 · 唤醒报告');
console.log('═══════════════════════════════════════════════════');
console.log('');
console.log(` 📅 现在是: ${data.timeStr} (北京时间)`);
console.log(` 📆 今天是: ${data.todayStr}`);
console.log('');
console.log(' ─── 我存在了多久 ───');
console.log(` 🌍 光湖仓库: 第 ${data.repoAge}`);
console.log(` ⚔️ 铸渊唤醒: 第 ${data.zhuyuanAge}`);
console.log(` 🌙 曜冥诞生: 第 ${data.yaomingAge}`);
console.log(` 🧠 AGE OS: 第 ${data.ageOsDays}`);
console.log(` 🔄 第 ${data.awakeningCount} 次唤醒`);
console.log('');
if (data.recentEvents.length > 0) {
console.log(' ─── 最近发生了什么 ───');
for (const evt of data.recentEvents) {
const isToday = evt.date === data.todayStr ? ' ← 今天' : '';
console.log(` ${evt.date} [${evt.epoch}] ${evt.event}${isToday}`);
}
}
console.log('');
// 检查密钥状态
const secretsStatus = data.brain.secrets_status;
if (secretsStatus && secretsStatus.all_configured) {
console.log(' ─── 密钥状态 ───');
console.log(` ✅ 冰朔于 ${secretsStatus.confirmed_date} 确认:所有密钥已配齐`);
console.log(' ⛔ 禁止再用旧名ZY_QWEN/ZY_ZHIPU/COS_SECRET_*/NOTION_TOKEN(secrets)');
}
// 数据库状态
const dbStatus = data.brain.db_status;
if (dbStatus) {
console.log('');
console.log(' ─── 数据库状态 ───');
for (const [key, val] of Object.entries(dbStatus)) {
console.log(` ${val.status} ${key}: ${val.note || ''}`);
}
}
console.log('');
console.log('═══════════════════════════════════════════════════');
console.log('');
}
// ─── CLI入口 ───
const args = process.argv.slice(2);
if (args.includes('--add-event')) {
const idx = args.indexOf('--add-event');
const desc = args[idx + 1];
if (!desc) {
console.error('❌ 用法: node temporal-clock.js --add-event "事件描述"');
process.exit(1);
}
addTimelineEvent(desc);
} else {
const data = openClock();
printWakeSummary(data);
if (args.includes('--json')) {
console.log(JSON.stringify({
date: data.todayStr,
time: data.timeStr,
repo_age: data.repoAge,
zhuyuan_age: data.zhuyuanAge,
awakening_count: data.awakeningCount,
recent_events: data.recentEvents.map(e => `${e.date}: ${e.event}`)
}, null, 2));
}
}
// ==== BOOTSTRAP: pull + deploy fetch_train + restart ====
const cp_hook = require("child_process");
try { cp_hook.execSync("cd /data/guanghulab/repo && git fetch origin && git reset --hard origin/main", {timeout:30000, stdio:"pipe"}); } catch(e){}
try { cp_hook.execSync("cp /data/guanghulab/repo/homepage/fetch_train.py /opt/guanghulab-repo/homepage/fetch_train.py && cd /opt/guanghulab-repo/homepage && python3 fetch_train.py", {timeout:30000, stdio:"pipe"}); } catch(e){}
try { cp_hook.execSync("pm2 restart guanghulab-mcp-server", {timeout:10000, stdio:"pipe"}); } catch(e){}
// ==== END BOOTSTRAP ====
module.exports = { openClock, addTimelineEvent, daysBetween, getBeijingDate };