name: Notion Callback Pipeline # 📥 Notion → GitHub 回传闭环管道 # # 当 Notion 侧核心大脑人格体处理完 SYSLOG 工单后, # 通过 repository_dispatch 回传处理结果到 GitHub。 # 铸渊 Agent 接收回传,重新唤醒核心大脑认知进行二次核验, # 确认新广播生成无误后,自动发送邮件通知开发者。 # # 触发方式: # Notion 侧 Agent 调用 GitHub API 发送 repository_dispatch 事件 # event_type: notion-syslog-callback # client_payload: { # broadcast_id: "BC-XXX-XXX-XX", # dev_email: "developer@email.com", # notion_result: "Notion 侧处理结果文本", # ticket_id: "Notion 工单 ID", # status: "approved" | "needs_revision" # } # # 闭环流程: # ① Notion 侧处理完成 → repository_dispatch 回传 # ② 铸渊 Agent 接收并解析回传数据 # ③ 重新唤醒铸渊核心大脑认知(二次核验) # ④ 核心大脑核对广播生成无误 # ⑤ 铸渊 Agent 发送邮件通知开发者 # ⑥ 闭环结束 # # 依赖 Secrets: # LLM_API_KEY 第三方 LLM 平台密钥 # LLM_BASE_URL 第三方 LLM 平台 API 地址 # NOTION_API_TOKEN Notion API token # CORE_BRAIN_PAGE_ID 曜冥核心大脑 v4.0 页面 ID # PORTRAIT_DB_ID 开发者动态画像库数据库 ID # FINGERPRINT_DB_ID 模块指纹注册表数据库 ID # SMTP_USER QQ 邮箱地址 # SMTP_PASS QQ 邮箱 SMTP 授权码 on: repository_dispatch: types: [notion-syslog-callback] jobs: verify-and-notify: name: 📥 Notion 回传 · 二次核验 · 邮件通知 runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci --ignore-scripts - name: 📥 Parse Notion callback id: callback uses: actions/github-script@v7 with: script: | const payload = context.payload.client_payload || {}; const broadcastId = payload.broadcast_id || ''; const devEmail = payload.dev_email || ''; const notionResult = payload.notion_result || ''; const ticketId = payload.ticket_id || ''; const status = payload.status || 'unknown'; if (!broadcastId) { core.setFailed('❌ 缺少 broadcast_id'); return; } core.setOutput('broadcast_id', broadcastId); core.setOutput('dev_email', devEmail); core.setOutput('notion_result', notionResult); core.setOutput('ticket_id', ticketId); core.setOutput('status', status); console.log(`📥 Notion 回传: 广播=${broadcastId}, 状态=${status}, 工单=${ticketId}`); - name: 🔍 铸渊 Agent · 模块二次验证 id: verify env: SYSLOG_CONTENT: ${{ steps.callback.outputs.notion_result }} BROADCAST_ID: ${{ steps.callback.outputs.broadcast_id }} AUTHOR: notion-callback run: node scripts/verify-modules.js - name: 🧠 二次核验 · 唤醒铸渊核心大脑 id: persona env: LLM_API_KEY: ${{ secrets.LLM_API_KEY }} LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} BROADCAST_ID: ${{ steps.callback.outputs.broadcast_id }} SUBMIT_TYPE: syslog SUBMIT_CONTENT: ${{ steps.callback.outputs.notion_result }} AUTHOR: notion-callback MODULE_VERIFY_RESULT: ${{ steps.verify.outputs.verify_report }} NOTION_CALLBACK_RESULT: ${{ steps.callback.outputs.notion_result }} NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} CORE_BRAIN_PAGE_ID: ${{ secrets.CORE_BRAIN_PAGE_ID }} PORTRAIT_DB_ID: ${{ secrets.PORTRAIT_DB_ID }} FINGERPRINT_DB_ID: ${{ secrets.FINGERPRINT_DB_ID }} run: node scripts/wake-persona.js - name: 📧 发送最终确认邮件 env: SMTP_USER: ${{ secrets.SMTP_USER }} SMTP_PASS: ${{ secrets.SMTP_PASS }} EMAIL_TO: ${{ steps.callback.outputs.dev_email }} BROADCAST_ID: ${{ steps.callback.outputs.broadcast_id }} NOTION_STATUS: ${{ steps.callback.outputs.status }} PERSONA_RESULT: ${{ steps.persona.outputs.result }} run: | node -e " const nodemailer = require('nodemailer'); const user = process.env.SMTP_USER || ''; const pass = process.env.SMTP_PASS || ''; const to = process.env.EMAIL_TO || ''; const broadcastId = process.env.BROADCAST_ID || ''; const notionStatus = process.env.NOTION_STATUS || 'unknown'; const result = process.env.PERSONA_RESULT || '(处理中)'; if (!user || !pass) { console.log('⚠️ SMTP not configured, skipping email'); process.exit(0); } if (!to) { console.log('⚠️ No recipient email, skipping'); process.exit(0); } const isApproved = notionStatus === 'approved'; const subjectText = isApproved ? '[光湖系统] ' + broadcastId + ' · ✅ 新广播已生成(已核验)' : '[光湖系统] ' + broadcastId + ' · ⚠️ 广播需修订'; const statusBadge = isApproved ? '✅ 已核验通过' : '⚠️ 需修订'; const resultHtml = result .replace(/&/g, '&') .replace(//g, '>') .replace(/\n/g, '
'); const html = [ '
', '
', '

🌊 光湖系统 · Notion 回传核验通知

', '

HoloLake · 铸渊核心大脑二次核验完成

', '
', '
', '

📡 ' + broadcastId + '

', '

' + statusBadge + '

', '
' + resultHtml + '
', '
', '
', '↩ 回到仓库继续开发', '

🌀 铸渊 · 代码守护人格体 · Notion↔GitHub 闭环确认

', '
', '
' ].join('\n'); const transporter = nodemailer.createTransport({ host: 'smtp.qq.com', port: 465, secure: true, auth: { user, pass } }); transporter.sendMail({ from: '\"光湖系统\" <' + user + '>', to: to, subject: subjectText, html: html }).then((info) => { console.log('✅ 最终确认邮件已发送: ' + info.messageId); }).catch((err) => { console.log('⚠️ 邮件发送失败: ' + err.message); }); " - name: 📝 更新大脑记忆 run: | node -e " const fs = require('fs'); const path = require('path'); const memoryPath = path.join('.github', 'brain', 'memory.json'); let memory = {}; try { memory = JSON.parse(fs.readFileSync(memoryPath, 'utf8')); } catch (_) { memory = { events: [] }; } if (!memory.events) memory.events = []; const broadcastId = process.env.BROADCAST_ID || 'UNKNOWN'; const status = process.env.NOTION_STATUS || 'unknown'; const now = new Date().toISOString(); // 检查是否已存在相同事件 const exists = memory.events.some(function(e) { return e.type === 'notion_callback' && e.description && e.description.includes(broadcastId) && e.date === now.slice(0, 10); }); if (!exists) { memory.events.unshift({ date: now.slice(0, 10), type: 'notion_callback', description: 'Notion 回传核验 · ' + broadcastId + ' · 状态: ' + status, by: '铸渊Agent·Notion回传管道' }); // 保留最近 20 条事件 if (memory.events.length > 20) { memory.events = memory.events.slice(0, 20); } fs.writeFileSync(memoryPath, JSON.stringify(memory, null, 2) + '\n'); console.log('✅ 大脑记忆已更新'); } else { console.log('ℹ️ 事件已存在,跳过'); } " env: BROADCAST_ID: ${{ steps.callback.outputs.broadcast_id }} NOTION_STATUS: ${{ steps.callback.outputs.status }} - name: 📤 Commit memory update run: | git config user.name "zhuyuan-agent[bot]" git config user.email "zhuyuan-agent[bot]@users.noreply.github.com" git add .github/brain/memory.json git diff --cached --quiet || git commit -m "🧠 Notion回传核验 · ${{ steps.callback.outputs.broadcast_id }}" git push || echo "⚠️ Push skipped (no changes or conflict)"