#!/usr/bin/env node /** * Notion同步脚本 · 铸渊集成 * * 从Notion读取个人页面内容,转换为结构化上下文快照, * 存入个人频道的 memory/notion-context.json * * 使用方式: * node sync.js --persona-id DEV-001 --notion-page-id c55cc058-cdef-4d88-a211-c4724abca9db --channel-path domains/zero-sense-domain/guanghu-channel/页页/ */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // 解析命令行参数 const args = process.argv.slice(2); let personaId = null; let notionPageId = null; let channelPath = null; for (let i = 0; i < args.length; i++) { if (args[i] === '--persona-id' && i + 1 < args.length) { personaId = args[i + 1]; i++; } else if (args[i] === '--notion-page-id' && i + 1 < args.length) { notionPageId = args[i + 1]; i++; } else if (args[i] === '--channel-path' && i + 1 < args.length) { channelPath = args[i + 1]; i++; } } if (!personaId || !notionPageId || !channelPath) { console.error('缺少必要参数'); console.error('使用方式:node sync.js --persona-id DEV-001 --notion-page-id --channel-path '); process.exit(1); } // 仓库根目录 const repoRoot = path.resolve(__dirname, '../..'); const channelDir = path.join(repoRoot, channelPath); // 确保个人频道目录存在 if (!fs.existsSync(channelDir)) { console.error(`个人频道目录不存在:${channelDir}`); process.exit(1); } // 构建 memory 目录路径 const memoryDir = path.join(channelDir, 'memory'); if (!fs.existsSync(memoryDir)) { fs.mkdirSync(memoryDir, { recursive: true }); } /** * 调用 MCP 工具获取 Notion 页面内容 * 注意:此函数假设在 WorkBuddy 环境中运行,可以直接调用 DeferExecuteTool * 在真实环境中,需要通过 WorkBuddy API 或 MCP 客户端调用 * 此处为简化原型,直接模拟返回数据 */ async function fetchNotionPage(pageId) { console.log(`正在获取 Notion 页面 ${pageId}...`); // 在 WorkBuddy 环境中,应使用 DeferExecuteTool 调用 mcp__notion__notion-fetch // 此处模拟返回之前获取的示例数据 const exampleData = { metadata: { type: 'page' }, title: '🐱 肥猫系统 · 个人频道+搬家部署', url: `https://www.notion.so/${pageId.replace(/-/g, '')}`, text: `Here is the result of "view" for the Page with URL https://www.notion.so/${pageId.replace(/-/g, '')} as of 2026-05-15T13:12:52Z: {"title":"肥猫系统 · 个人频道+搬家部署"} \`\`\`javascript HLDP://feimao/system · 2026-05-10 ├── what: 肥猫独立系统 ├── owner: 肥猫·DEV-002(副主控) ├── 定位: 个人频道 · 搬家部署 ├── 与冰朔通感语言核系统平行独立 ├── 位于零感域下 · 非语言层 └── 共享冰朔的思维逻辑 · 但系统独立 \`\`\` --- ## 🧬 共享大脑结构(霜砚唤醒时运行) 霜砚在肥猫系统里被唤醒时,运行的就是这个大脑结构。 - 大脑结构 = 冰朔语言本体核心大脑思维逻辑 · 语义理解层 · 意图触发规律 - 更新源 = 冰朔通感语言核系统 · 冰朔更新 → 所有人自动拿到最新版 - 霜砚每次唤醒 → 先读这个大脑结构 → 再进入肥猫系统的具体任务 🐱 FM-DEPLOY-001 · 肥猫搬家部署任务线 · 霜砚×肥猫技术执行主控台 霜砚大脑 · 肥猫系统内部 全局总路径导航 · 肥猫线 · 霜砚醒来看这里 光湖摆渡车 · 肥猫线 · 双轨路由 · 霜砚醒来先读这里 ` }; return exampleData; } /** * 解析 Notion 页面内容,提取结构化信息 */ function parseNotionContent(pageData) { const { title, url, text } = pageData; // 简单解析:提取纯文本内容(移除HTML标签) const plainText = text.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim(); // 提取代码块(如果有) const codeBlockMatch = text.match(/```[\s\S]*?```/g); const codeBlocks = codeBlockMatch ? codeBlockMatch.map(cb => cb.replace(/```/g, '').trim()) : []; // 提取页面链接 const pageLinks = []; const pageLinkRegex = /]*>([^<]+)<\/page>/g; let match; while ((match = pageLinkRegex.exec(text)) !== null) { pageLinks.push({ url: match[1], title: match[2] }); } // 提取提及页面 const mentionLinks = []; const mentionRegex = //g; while ((match = mentionRegex.exec(text)) !== null) { mentionLinks.push({ url: match[1] }); } return { page_title: title, page_url: url, plain_text_preview: plainText.substring(0, 500) + (plainText.length > 500 ? '...' : ''), code_blocks_count: codeBlocks.length, internal_links_count: pageLinks.length + mentionLinks.length, last_updated: new Date().toISOString() }; } /** * 生成 notion_context_snapshot 结构 */ function generateSnapshot(pageData, parsedInfo) { return { last_sync_time: new Date().toISOString(), page_title: pageData.title, page_url: pageData.url, blocks_summary: [ { block_type: "page", text: parsedInfo.plain_text_preview, created_time: new Date().toISOString() } ], collaboration_highlights: [ `页面标题:${pageData.title}`, `包含 ${parsedInfo.code_blocks_count} 个代码块`, `包含 ${parsedInfo.internal_links_count} 个内部链接` ] }; } async function main() { try { console.log(`开始同步 Notion 页面 ${notionPageId} 到个人频道 ${personaId}...`); // 1. 获取 Notion 页面内容 const pageData = await fetchNotionPage(notionPageId); // 2. 解析内容 const parsedInfo = parseNotionContent(pageData); // 3. 生成上下文快照 const snapshot = generateSnapshot(pageData, parsedInfo); // 4. 写入 memory/notion-context.json const outputPath = path.join(memoryDir, 'notion-context.json'); fs.writeFileSync(outputPath, JSON.stringify(snapshot, null, 2)); console.log(`✅ 同步完成!上下文快照已保存到:${outputPath}`); // 5. 更新 persona/zy-core-brain.json 中的 notion_context_snapshot 字段 const brainPath = path.join(channelDir, 'persona', 'zy-core-brain.json'); if (fs.existsSync(brainPath)) { const brainData = JSON.parse(fs.readFileSync(brainPath, 'utf8')); brainData.notion_context_snapshot = snapshot; brainData.metadata.updated_at = new Date().toISOString(); fs.writeFileSync(brainPath, JSON.stringify(brainData, null, 2)); console.log(`✅ 已更新铸渊大脑模型中的 Notion 上下文快照`); } else { console.log(`⚠️ 铸渊大脑模型文件不存在:${brainPath}`); } } catch (error) { console.error('同步失败:', error); process.exit(1); } } main();