diff --git a/.github/DISCUSSION_TEMPLATE/syslog-submit.yml b/.github/DISCUSSION_TEMPLATE/syslog-submit.yml new file mode 100644 index 00000000..a0baaa94 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/syslog-submit.yml @@ -0,0 +1,51 @@ +title: "BC-XXX-XXXSYSLOG" +labels: [] +body: + - type: markdown + attributes: + value: | + ## 📡 SYSLOG 自助提亀 / 广播提问 + + > 做完了把日志粘莎进去填䞊邮箱点提亀。新广播䌚发到䜠邮箱里。 + > + > 有问题把问题粘莎进去填䞊邮箱点提亀。解答䌚发到䜠邮箱里。 + + **标题栌匏**`BC-XXX-XXXSYSLOG` 或 `BC-XXX-XXX提问` + + - type: input + id: broadcast_id + attributes: + label: "广播猖号" + description: "写䞊䜠圓前广播的猖号䟋劂 BC-M22-009-AW" + placeholder: "BC-M22-009-AW" + validations: + required: true + + - type: dropdown + id: submit_type + attributes: + label: "类型" + description: "选择提亀类型" + options: + - SYSLOG + - 提问 + validations: + required: true + + - type: input + id: email + attributes: + label: "䜠的邮箱" + description: "甚于接收新广播或问题解答" + placeholder: "your@email.com" + validations: + required: true + + - type: textarea + id: content + attributes: + label: "内容" + description: "粘莎䜠的 SYSLOG å…šæ–‡ 或 问题描述" + placeholder: "圚这里粘莎䜠的 SYSLOG 或问题..." + validations: + required: true diff --git a/.github/brain/bingshuo-issues-index.json b/.github/brain/bingshuo-issues-index.json index abbec8c8..8e8121de 100644 --- a/.github/brain/bingshuo-issues-index.json +++ b/.github/brain/bingshuo-issues-index.json @@ -1,7 +1,7 @@ { "version": "1.0", "description": "冰朔䞻控问题玢匕库 — 记圕已知问题、根因䞎排查路由", - "updated_at": "2026-03-13T02:05:55.611Z", + "updated_at": "2026-03-13T04:49:20.482Z", "issues": [ { "id": "BS-001", diff --git a/.github/brain/bingshuo-master-brain.md b/.github/brain/bingshuo-master-brain.md index 443bfaee..364f1351 100644 --- a/.github/brain/bingshuo-master-brain.md +++ b/.github/brain/bingshuo-master-brain.md @@ -1,7 +1,7 @@ # 冰朔䞻控神经系统 · 栞心䞻控倧脑 v1.0 > 本文件䞺冰朔䞻控神经系统的总控脑文件。 -> 最后猖译时闎2026-03-13T02:05:55.612Z +> 最后猖译时闎2026-03-13T04:49:20.482Z --- @@ -56,7 +56,7 @@ ### 仓库统计 - 功胜暡块10 䞪 -- Workflow35 䞪 +- Workflow36 䞪 --- @@ -85,7 +85,7 @@ > 本区块由 master-brain-compiler 自劚猖译。 -- **猖译时闎**2026-03-13T02:05:55.612Z +- **猖译时闎**2026-03-13T04:49:20.482Z - **脑文件规则版本**v3.0 - **脑文件完敎性**✅ 完敎 @@ -107,7 +107,7 @@ |--------|------|------| | 🟡 brain_consistency | yellow | 䞻仓库脑文件完敎䜆䞎 persona-studio 脑文件的同步状态埅验证 | | 🟢 deployment_health | green | deploy-to-server.yml 侎 deploy-pages.yml 均存圚 | -| 🟢 workflow_health | green | 35 䞪 workflow 已泚册 | +| 🟢 workflow_health | green | 36 䞪 workflow 已泚册 | | 🟡 routing_health | yellow | HLI 接口芆盖率 33.3%7/21 | | 🟢 docs_entry_health | green | docs/index.html 存圚 | | 🟡 persona_studio_health | yellow | 前后端结构存圚端到端对话铟路埅验证 | diff --git a/.github/brain/bingshuo-system-health.json b/.github/brain/bingshuo-system-health.json index 56abef67..1ba8b36f 100644 --- a/.github/brain/bingshuo-system-health.json +++ b/.github/brain/bingshuo-system-health.json @@ -1,7 +1,7 @@ { "version": "1.0", "description": "冰朔䞻控系统健康状态", - "updated_at": "2026-03-13T02:05:55.611Z", + "updated_at": "2026-03-13T04:49:20.482Z", "health": { "brain_consistency": { "status": "yellow", @@ -13,7 +13,7 @@ }, "workflow_health": { "status": "green", - "detail": "35 䞪 workflow 已泚册" + "detail": "36 䞪 workflow 已泚册" }, "routing_health": { "status": "yellow", diff --git a/.github/brain/repo-map.json b/.github/brain/repo-map.json index 45ae82d7..119427b3 100644 --- a/.github/brain/repo-map.json +++ b/.github/brain/repo-map.json @@ -1,20 +1,20 @@ { "description": "铞枊囟乊銆目圕 · Library Catalog for 铞枊 (Zhùyuān)", "version": "2.0", - "generated_at": "2026-03-13T02:07:22.787Z", + "generated_at": "2026-03-13T04:49:33.903Z", "generated_by": "scripts/generate-repo-map.js", "repo": "qinfendebingshuo/guanghulab", "stats": { "zones": 13, "total_modules": 10, - "total_workflows": 35, - "total_scripts": 32, + "total_workflows": 36, + "total_scripts": 33, "total_dev_nodes": 8, "hli_interfaces": 21, "hli_implemented": 7, "hli_coverage_pct": "33%", "last_ci_run": "2026-03-05T16:07:24.070Z", - "memory_last_updated": "2026-03-12T08:55:54.205Z" + "memory_last_updated": "2026-03-13T03:31:06.282Z" }, "zones": [ { @@ -362,6 +362,13 @@ "manual" ] }, + { + "file": "syslog-auto-pipeline.yml", + "name": "SYSLOG Auto Pipeline", + "triggers": [ + "unknown" + ] + }, { "file": "syslog-pipeline.yml", "name": "铞枊 · SYSLOG Pipeline (A/D/E)", @@ -435,7 +442,7 @@ ] } ], - "item_count": 35 + "item_count": 36 }, { "zone_id": "SCRIPTS", @@ -536,6 +543,9 @@ { "file": "update-readme-bulletin.js" }, + { + "file": "wake-persona.js" + }, { "file": "zhuyuan-daily-agent.js" }, @@ -549,7 +559,7 @@ "file": "zhuyuan-module-protocol.js" } ], - "item_count": 32 + "item_count": 33 }, { "zone_id": "SRC", @@ -1356,6 +1366,9 @@ "sync-persona-studio": [ "WORKFLOWS::sync-persona-studio.yml" ], + "syslog-auto-pipeline": [ + "WORKFLOWS::syslog-auto-pipeline.yml" + ], "syslog-pipeline": [ "WORKFLOWS::syslog-pipeline.yml" ], @@ -1466,6 +1479,9 @@ "update-memory": [ "SCRIPTS::update-memory.js" ], + "wake-persona": [ + "SCRIPTS::wake-persona.js" + ], "zhuyuan-module-protocol": [ "SCRIPTS::zhuyuan-module-protocol.js" ], diff --git a/.github/brain/repo-snapshot.md b/.github/brain/repo-snapshot.md index 4e21ee97..8dd53858 100644 --- a/.github/brain/repo-snapshot.md +++ b/.github/brain/repo-snapshot.md @@ -1,5 +1,5 @@ # 铞枊囟乊銆快照 · Repo Snapshot -> 生成于 2026-03-13 10:07 CST · 每次 push 自劚曎新 · 铞枊唀醒时䌘先读取歀文件 +> 生成于 2026-03-13 12:49 CST · 每次 push 自劚曎新 · 铞枊唀醒时䌘先读取歀文件 --- @@ -9,11 +9,11 @@ |------|------| | 区域总数 | 13 䞪区域 | | 功胜暡块 | 10 䞪 (m01~m18) | -| 工䜜流 | 35 䞪 GitHub Actions | -| 脚本 | 32 䞪执行脚本 | +| 工䜜流 | 36 䞪 GitHub Actions | +| 脚本 | 33 䞪执行脚本 | | 匀发者节点 | 8 人 | | HLI 接口芆盖率 | 7/21 (33%) | -| 快照生成时闎 | 2026-03-13 10:07 CST | +| 快照生成时闎 | 2026-03-13 12:49 CST | --- @@ -30,12 +30,12 @@ **关键词**: persona · identity · dev-status · 人栌 · 匀发者状态 ### ⚡ 自劚化工䜜流WORKFLOWS -**路埄**: `.github/workflows` · **数量**: 35 项 +**路埄**: `.github/workflows` · **数量**: 36 项 **描述**: 所有 GitHub Actions 工䜜流定义 **关键词**: workflow · actions · ci · automation · 工䜜流 · 自劚化 ### 🔧 执行脚本库SCRIPTS -**路埄**: `scripts` · **数量**: 32 项 +**路埄**: `scripts` · **数量**: 33 项 **描述**: 铞枊所有执行手脚 · 自劚化脚本 **关键词**: script · node · js · 脚本 · 执行 · runner @@ -116,6 +116,7 @@ | `staging-preview.yml` | "🔍 铞枊预挔郚眲 (Staging Preview)" | pull_request, manual | | `sync-login-entry.yml` | 铞枊 · Sync Login Entry · Notion → 飞乊文档A | manual | | `sync-persona-studio.yml` | 🔄 铞枊跚仓库同步 · persona-studio | push, manual | +| `syslog-auto-pipeline.yml` | SYSLOG Auto Pipeline | unknown | | `syslog-pipeline.yml` | 铞枊 · SYSLOG Pipeline (A/D/E) | push, manual | | `test-notion-bridge.yml` | "🧪 Notion Bridge Connectivity Test" | push, manual | | `update-readme-bulletin.yml` | 📢 曎新系统公告区 | push, schedule(0 1 * * *), manual | @@ -158,6 +159,7 @@ - `scripts/update-brain.js` - `scripts/update-memory.js` - `scripts/update-readme-bulletin.js` +- `scripts/wake-persona.js` - `scripts/zhuyuan-daily-agent.js` - `scripts/zhuyuan-daily-selfcheck.js` - `scripts/zhuyuan-issue-reply.js` diff --git a/.github/workflows/syslog-auto-pipeline.yml b/.github/workflows/syslog-auto-pipeline.yml new file mode 100644 index 00000000..c2fa3898 --- /dev/null +++ b/.github/workflows/syslog-auto-pipeline.yml @@ -0,0 +1,366 @@ +name: SYSLOG Auto Pipeline +# 📡 SYSLOG 自助提亀系统 · 党自劚闭环 +# +# 匀发者圚 GitHub Discussion 提亀 SYSLOG 或提问 +# → Actions 自劚解析 → 调甚 LLM API 唀醒人栌䜓 +# → 写入 Notion 工单 → 发邮件给匀发者 → Discussion 回倍 +# +# 䟝赖 Secrets +# LLM_API_KEY 第䞉方 LLM 平台密钥必须 +# LLM_BASE_URL 第䞉方 LLM 平台 API 地址必须劂 https://api.xxx.com/v1 +# NOTION_API_TOKEN Notion API token +# NOTION_TICKET_DB_ID 霜砚工单数据库 ID +# CORE_BRAIN_PAGE_ID 曜冥栞心倧脑 v4.0 页面 IDv4.0 协议劚态泚入 +# PORTRAIT_DB_ID 匀发者劚态画像库数据库 IDv4.0 协议劚态泚入 +# FINGERPRINT_DB_ID 暡块指纹泚册衚数据库 IDv4.0 协议劚态泚入 +# SMTP_USER QQ 邮箱地址 +# SMTP_PASS QQ 邮箱 SMTP 授权码 + +on: + discussion: + types: [created] + +jobs: + process: + name: 📡 倄理 SYSLOG 提亀 / 广播提问 + runs-on: ubuntu-latest + if: contains(github.event.discussion.category.name, 'SYSLOG') + permissions: + contents: write + discussions: 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 submission + id: parse + uses: actions/github-script@v7 + with: + script: | + const body = context.payload.discussion.body || ''; + const title = context.payload.discussion.title || ''; + + // Parse structured fields from discussion body + function extractField(text, label) { + // Match form field format: ### Label\n\nValue + const regex = new RegExp('###\\s*' + label + '\\s*\\n+([^\\n#]+)', 'i'); + const match = text.match(regex); + return match ? match[1].trim() : ''; + } + + const broadcastId = extractField(body, '广播猖号') || ''; + const submitType = extractField(body, '类型') || ''; + const email = extractField(body, '䜠的邮箱') || ''; + + // Extract content (everything after "### 内容") + const contentMatch = body.match(/###\s*内容\s*\n+([\s\S]*?)$/i); + const content = contentMatch ? contentMatch[1].trim() : ''; + + // Determine type from title or body + let type = 'question'; // default + if (submitType.includes('SYSLOG') || title.includes('SYSLOG')) { + type = 'syslog'; + } else if (submitType.includes('提问') || title.includes('提问')) { + type = 'question'; + } + + // Validate + if (!broadcastId) { + core.setFailed('❌ 猺少广播猖号请圚提亀时填写广播猖号'); + return; + } + if (!email) { + core.setFailed('❌ 猺少邮箱请圚提亀时填写䜠的邮箱'); + return; + } + if (!content) { + core.setFailed('❌ 猺少内容请粘莎䜠的 SYSLOG 或问题'); + return; + } + + core.setOutput('broadcast_id', broadcastId); + core.setOutput('type', type); + core.setOutput('email', email); + core.setOutput('content', content); + core.setOutput('discussion_number', context.payload.discussion.number); + core.setOutput('author', context.payload.discussion.user.login); + + console.log(`📡 解析完成: 广播=${broadcastId}, 类型=${type}, 邮箱=${email}`); + + - name: 🧠 Auto-detect and wake up persona + id: persona + env: + LLM_API_KEY: ${{ secrets.LLM_API_KEY }} + LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} + BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} + SUBMIT_TYPE: ${{ steps.parse.outputs.type }} + SUBMIT_CONTENT: ${{ steps.parse.outputs.content }} + AUTHOR: ${{ steps.parse.outputs.author }} + 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: 📋 Write to Notion ticket + if: ${{ secrets.NOTION_API_TOKEN }} + env: + NOTION_TOKEN: ${{ secrets.NOTION_API_TOKEN }} + NOTION_TICKET_DB_ID: ${{ secrets.NOTION_TICKET_DB_ID }} + BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} + SUBMIT_TYPE: ${{ steps.parse.outputs.type }} + PERSONA_RESULT: ${{ steps.persona.outputs.result }} + run: | + node -e " + const https = require('https'); + + const token = process.env.NOTION_TOKEN; + const dbId = process.env.NOTION_TICKET_DB_ID; + const broadcastId = process.env.BROADCAST_ID || 'UNKNOWN'; + const type = process.env.SUBMIT_TYPE || 'syslog'; + const result = process.env.PERSONA_RESULT || '(no result)'; + + if (!token || !dbId) { + console.log('⚠ Notion credentials not configured, skipping ticket creation'); + process.exit(0); + } + + const typeLabel = type === 'syslog' ? 'SYSLOG闭环' : '提问解答'; + const title = '[自劚] ' + broadcastId + ' · ' + typeLabel; + + const body = JSON.stringify({ + parent: { database_id: dbId }, + properties: { + '标题': { title: [{ type: 'text', text: { content: title.slice(0, 120) } }] }, + '操䜜类型': { select: { name: '其他' } }, + '提亀者': { rich_text: [{ type: 'text', text: { content: '自劚管道' } }] }, + '状态': { select: { name: '已完成' } }, + '䌘先级': { select: { name: 'P1' } } + }, + children: [{ + object: 'block', + type: 'paragraph', + paragraph: { + rich_text: [{ type: 'text', text: { content: result.slice(0, 2000) } }] + } + }] + }); + + const opts = { + hostname: 'api.notion.com', + port: 443, + path: '/v1/pages', + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + token, + 'Content-Type': 'application/json', + 'Notion-Version': '2022-06-28', + 'Content-Length': Buffer.byteLength(body) + } + }; + + const req = https.request(opts, (res) => { + let data = ''; + res.on('data', (c) => data += c); + res.on('end', () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + console.log('✅ Notion 工单已创建'); + } else { + console.log('⚠ Notion 工单创建倱莥: ' + res.statusCode + ' ' + data); + } + }); + }); + req.on('error', (e) => console.log('⚠ Notion 请求倱莥: ' + e.message)); + req.write(body); + req.end(); + " + + - name: 📧 Send email to developer + env: + SMTP_USER: ${{ secrets.SMTP_USER }} + SMTP_PASS: ${{ secrets.SMTP_PASS }} + EMAIL_TO: ${{ steps.parse.outputs.email }} + BROADCAST_ID: ${{ steps.parse.outputs.broadcast_id }} + SUBMIT_TYPE: ${{ steps.parse.outputs.type }} + 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 type = process.env.SUBMIT_TYPE || 'syslog'; + 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 subjectText = type === 'syslog' + ? '[光湖系统] ' + broadcastId + ' · 新广播已生成' + : '[光湖系统] ' + broadcastId + ' · 问题已解答'; + + const resultHtml = result + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/\n/g, '
'); + + const html = [ + '
', + '
', + '

🌊 光湖系统 · 自劚通知

', + '

HoloLake · 人栌语蚀操䜜系统

', + '
', + '
', + '

📡 ' + broadcastId + '

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

🌀 铞枊 · 代码守技人栌䜓 · 自劚发送

', + '
', + '
' + ].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: 💬 Reply to Discussion + uses: actions/github-script@v7 + with: + script: | + const number = ${{ steps.parse.outputs.discussion_number }}; + const type = '${{ steps.parse.outputs.type }}'; + const broadcastId = '${{ steps.parse.outputs.broadcast_id }}'; + const email = '${{ steps.parse.outputs.email }}'; + + const typeLabel = type === 'syslog' ? 'SYSLOG 闭环倄理' : '问题解答'; + const maskedEmail = email.length > 4 + ? email.replace(/(.{2})(.*)(@.*)/, '$1***$3') + : '***'; + + const body = [ + '✅ **已倄理** · ' + typeLabel, + '', + '| 项目 | 内容 |', + '|------|------|', + '| 📡 广播猖号 | `' + broadcastId + '` |', + '| 📧 结果发送至 | `' + maskedEmail + '` |', + '| 🀖 倄理人栌䜓 | 铞枊 |', + '| ⏰ 倄理时闎 | ' + new Date().toISOString() + ' |', + '', + '> 结果已发送到䜠的邮箱请查收。', + '>', + '> 劂未收到请检查垃土箱或重新提亀。' + ].join('\n'); + + // Use GraphQL to add discussion comment + const query = ` + mutation($discussionId: ID!, $body: String!) { + addDiscussionComment(input: { + discussionId: $discussionId, + body: $body + }) { + comment { id } + } + } + `; + + try { + // Get the discussion node ID + const { repository } = await github.graphql(` + query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + discussion(number: $number) { + id + } + } + } + `, { + owner: context.repo.owner, + repo: context.repo.repo, + number: number + }); + + await github.graphql(query, { + discussionId: repository.discussion.id, + body: body + }); + + console.log('✅ Discussion 回倍已发送'); + } catch (err) { + console.log('⚠ Discussion 回倍倱莥: ' + err.message); + } + + - name: 🔎 倱莥告譊 + if: failure() + uses: actions/github-script@v7 + with: + script: | + const number = context.payload.discussion?.number; + if (!number) return; + + try { + const { repository } = await github.graphql(` + query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + discussion(number: $number) { + id + } + } + } + `, { + owner: context.repo.owner, + repo: context.repo.repo, + number: number + }); + + await github.graphql(` + mutation($discussionId: ID!, $body: String!) { + addDiscussionComment(input: { + discussionId: $discussionId, + body: $body + }) { + comment { id } + } + } + `, { + discussionId: repository.discussion.id, + body: '❌ **倄理倱莥** · 请检查提亀栌匏是吊正确或联系管理员。\n\n> 错误诊情请查看 [Actions 日志](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '/actions)。' + }); + } catch (err) { + console.log('⚠ 倱莥告譊回倍倱莥: ' + err.message); + } diff --git a/README.md b/README.md index ff934478..4f27b893 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,21 @@ --- +## 🚀 匀发者入口 + +
+ +[![提亀系统日志](https://img.shields.io/badge/📡_提亀系统日志-点这里-blue?style=for-the-badge)](https://github.com/qinfendebingshuo/guanghulab/discussions/new?category=📡+SYSLOG+提亀区) +[![遇到问题](https://img.shields.io/badge/❓_遇到问题-点这里提问-green?style=for-the-badge)](https://github.com/qinfendebingshuo/guanghulab/discussions/new?category=📡+SYSLOG+提亀区) + +> 做完了把日志粘莎进去填䞊邮箱点提亀。新广播䌚发到䜠邮箱里。 +> +> 有问题同䞀䞪入口选「提问」问题解答也发到䜠邮箱里。 + +
+ +--- + ## 📖 系统简介 **光湖HoloLake** 是䞀䞪基于人栌语蚀操䜜系统的智胜协䜜平台采甚壳-栞分犻讟计 @@ -77,21 +92,21 @@ | æ—¶é—Ž | 检查项 | 状态 | |------|--------|------| +| 03-13 12:50 | ✅ 🚀 铞枊 CD · 自劚郚眲到 guanghulab.com · 成功 | 冰朔 | +| 03-13 12:50 | ✅ 铞枊 · Notion 工单蜮询 · 成功 | 冰朔 | +| 03-13 12:49 | ✅ 📢 曎新系统公告区 · 成功 | 冰朔 | +| 03-13 12:49 | 🔧 系统曎新: `.github/` | 铞枊 (ZhùYuān) | +| 03-13 12:49 | ✅ 铞枊 · Bridge E · GitHub Changes → Notion · 成功 | 冰朔 | +| 03-13 11:54 | 🔧 系统曎新: `scripts/` | 铞枊 (Copilot) | +| 03-13 11:31 | ✅ 📢 曎新系统公告区 · 成功 | 冰朔 | | 03-13 11:31 | ✅ 铞枊 · PSP 分身巡检 · 成功 | 冰朔 | -| 03-13 11:31 | 🔧 系统曎新: `.github/` | 铞枊 (ZhùYuān) | | 03-13 11:22 | ✅ 📢 曎新系统公告区 · 成功 | 冰朔 | | 03-13 10:49 | ✅ 铞枊 · Notion 工单蜮询 · 成功 | 冰朔 | -| 03-13 09:58 | ✅ 📢 曎新系统公告区 · 成功 | zhizhi200271 | -| 03-13 09:58 | ✅ 🚀 铞枊 CD · 自劚郚眲到 guanghulab.com · 成功 | zhizhi200271 | -| 03-13 09:57 | ✅ 📢 曎新系统公告区 · 成功 | zhizhi200271 | -| 03-13 09:56 | ⏹ 📢 曎新系统公告区 · cancelled | zhizhi200271 | -| 03-13 09:56 | ✅ 铞枊 · Bridge E · GitHub Changes → Notion · 成功 | zhizhi200271 | | 03-13 09:56 | 🔧 系统曎新: `docs/` | 铞枊 (ZhùYuān) | -| 03-13 08:57 | ✅ 📢 曎新系统公告区 · 成功 | 冰朔 | -| 03-13 08:56 | ✅ 铞枊 · 每日自检 · 成功 | 冰朔 | -| 03-13 08:01 | ✅ Generate Session Summary for Notion · 成功 | 冰朔 | | 03-13 08:00 | ✅ 铞枊 PSP 巡检通过 · 党郚检查项 ✅ | 铞枊PSP巡检 | -| 03-13 07:59 | ✅ 铞枊 · Notion 工单蜮询 · 成功 | 冰朔 | +| 03-12 16:55 | ✅ 每日巡检 ✅ 通过 | 冰朔 | +| 03-12 08:00 | ✅ 铞枊 PSP 巡检通过 · 党郚检查项 ✅ | 铞枊PSP巡检 | +| 03-11 16:55 | ✅ 每日巡检 ✅ 通过 | 冰朔 | ### 🀖 铞枊自劚提醒 @@ -113,7 +128,8 @@ | æ—¶é—Ž | 合䜜者 | 暡块 | 状态 | |------|--------|------|------| -| 03-13 09:56 | zhizhi200271 | `—/` | ✅ 䞊䌠成功 | +| 03-13 12:49 | 冰朔 | `—/` | ✅ 䞊䌠成功 | +| 03-13 12:49 | Copilot | `—/` | ✅ 䞊䌠成功 | | 03-13 09:56 | 🀖 之之 | `dingtalk-bot/` | 📊 䞊䌠成功 | diff --git a/scripts/wake-persona.js b/scripts/wake-persona.js new file mode 100644 index 00000000..fb88b08e --- /dev/null +++ b/scripts/wake-persona.js @@ -0,0 +1,871 @@ +// scripts/wake-persona.js +// 铞枊 · 人栌䜓唀醒脚本第䞉方 API 兌容层 · 自劚检测暡匏 +// +// 功胜 +// ① 自劚发现可甚暡型/v1/models 端点 +// ② 智胜选择最䌘 Claude 暡型 +// ③ 自适应 API 栌匏OpenAI 兌容 / Anthropic 原生 +// ④ 统䞀调甚接口唀醒人栌䜓倄理 SYSLOG 或解答提问 +// â‘€ v4.0 协议劚态泚入从 Notion 实时读取栞心倧脑规则 + 画像 + 指纹 +// +// 环境变量 +// LLM_API_KEY 第䞉方平台密钥必须 +// LLM_BASE_URL 第䞉方平台 API 地址必须劂 https://api.xxx.com/v1 +// BROADCAST_ID 广播猖号 +// SUBMIT_TYPE syslog | question +// SUBMIT_CONTENT 提亀内容SYSLOG 党文或问题描述 +// AUTHOR 提亀者 GitHub 甚户名 +// NOTION_TOKEN Notion API token甚于劚态读取协议 +// CORE_BRAIN_PAGE_ID 曜冥栞心倧脑 v4.0 页面 ID +// PORTRAIT_DB_ID 匀发者劚态画像库数据库 ID +// FINGERPRINT_DB_ID 暡块指纹泚册衚数据库 ID + +'use strict'; + +const https = require('https'); +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +// ══════════════════════════════════════════════════════════ +// 配眮 +// ══════════════════════════════════════════════════════════ + +const LLM_API_KEY = process.env.LLM_API_KEY || ''; +const LLM_BASE_URL = (process.env.LLM_BASE_URL || '').replace(/\/+$/, ''); +const BROADCAST_ID = process.env.BROADCAST_ID || 'UNKNOWN'; +const SUBMIT_TYPE = process.env.SUBMIT_TYPE || 'question'; +const SUBMIT_CONTENT = process.env.SUBMIT_CONTENT || ''; +const AUTHOR = process.env.AUTHOR || 'unknown'; + +// Notion 配眮v4.0 协议劚态泚入 +const NOTION_TOKEN = process.env.NOTION_TOKEN || ''; +const CORE_BRAIN_PAGE_ID = process.env.CORE_BRAIN_PAGE_ID || ''; +const PORTRAIT_DB_ID = process.env.PORTRAIT_DB_ID || ''; +const FINGERPRINT_DB_ID = process.env.FINGERPRINT_DB_ID || ''; +const NOTION_VERSION = '2022-06-28'; +const NOTION_API_HOSTNAME = 'api.notion.com'; +const MAX_PROTOCOL_TEXT_LENGTH = 15000; + +// Claude 暡型䌘先级队列从高到䜎 +const PREFERRED_MODELS = [ + 'claude-sonnet-4', + 'claude-3-5-sonnet-20241022', + 'claude-3.5-sonnet', + 'claude-3-5-sonnet', + 'anthropic/claude-3.5-sonnet', + 'claude-3-sonnet', + 'claude-3-haiku', +]; + +// ══════════════════════════════════════════════════════════ +// HTTP 请求工具 +// ══════════════════════════════════════════════════════════ + +function httpRequest(url, options, body) { + return new Promise((resolve, reject) => { + const parsed = new URL(url); + const isHttps = parsed.protocol === 'https:'; + const mod = isHttps ? https : http; + + const opts = { + hostname: parsed.hostname, + port: parsed.port || (isHttps ? 443 : 80), + path: parsed.pathname + parsed.search, + method: options.method || 'GET', + headers: options.headers || {}, + timeout: options.timeout || 60000, + }; + + const req = mod.request(opts, (res) => { + let data = ''; + res.on('data', (chunk) => { data += chunk; }); + res.on('end', () => { + resolve({ status: res.statusCode, body: data }); + }); + }); + + req.on('error', reject); + req.on('timeout', () => { + req.destroy(); + reject(new Error('Request timeout')); + }); + + if (body) { + req.write(body); + } + req.end(); + }); +} + +// ══════════════════════════════════════════════════════════ +// Step 1: 自劚发现可甚暡型 +// ══════════════════════════════════════════════════════════ + +async function discoverModels() { + console.log('[LLM] 🔍 探测可甚暡型...'); + + try { + const res = await httpRequest(LLM_BASE_URL + '/models', { + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + LLM_API_KEY, + 'Content-Type': 'application/json', + }, + timeout: 15000, + }); + + if (res.status >= 200 && res.status < 300) { + const json = JSON.parse(res.body); + const models = json.data || []; + console.log('[LLM] → 发现 ' + models.length + ' 䞪暡型'); + return models; + } + console.log('[LLM] → 暡型探测返回 ' + res.status + ', 䜿甚默讀暡型'); + return []; + } catch (err) { + console.log('[LLM] → 暡型探测倱莥: ' + err.message + ', 䜿甚默讀暡型'); + return []; + } +} + +// ══════════════════════════════════════════════════════════ +// Step 2: 智胜选择最䌘 Claude 暡型 +// ══════════════════════════════════════════════════════════ + +function selectBestModel(models) { + if (!models || models.length === 0) { + console.log('[LLM] 📌 无可甚暡型列衚, 䜿甚默讀 claude-3-5-sonnet'); + return 'claude-3-5-sonnet'; + } + + const available = models.map(function (m) { return m.id.toLowerCase(); }); + + // 按䌘先级匹配 + for (const preferred of PREFERRED_MODELS) { + const match = available.find(function (id) { return id.includes(preferred); }); + if (match) { + const found = models.find(function (m) { return m.id.toLowerCase() === match; }); + if (found) { + console.log('[LLM] 📌 选择暡型: ' + found.id + ' (匹配规则: ' + preferred + ')'); + return found.id; + } + } + } + + // 兜底任䜕含 'claude' 的暡型 + const anyClaude = available.find(function (id) { return id.includes('claude'); }); + if (anyClaude) { + const found = models.find(function (m) { return m.id.toLowerCase() === anyClaude; }); + if (found) { + console.log('[LLM] 📌 兜底选择 Claude 暡型: ' + found.id); + return found.id; + } + } + + // 最终兜底平台第䞀䞪可甚暡型 + const fallbackId = models[0].id; + console.log('[LLM] 📌 最终兜底: ' + fallbackId + ' (平台无 Claude 暡型)'); + return fallbackId; +} + +// ══════════════════════════════════════════════════════════ +// Step 3: 自适应 API 栌匏检测 +// ══════════════════════════════════════════════════════════ + +async function detectApiFormat() { + console.log('[LLM] 🔍 检测 API 栌匏...'); + + // 尝试 OpenAI 兌容栌匏绝倧倚数第䞉方平台 + try { + const res = await httpRequest(LLM_BASE_URL + '/chat/completions', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + LLM_API_KEY, + 'Content-Type': 'application/json', + }, + timeout: 10000, + }, JSON.stringify({ + model: 'test', + messages: [{ role: 'user', content: 'ping' }], + max_tokens: 1, + })); + + // 400 = endpoint exists but bad request (model not found etc.) → format supported + // 200 = endpoint works → format supported + if (res.status === 200 || res.status === 400 || res.status === 401 || res.status === 422) { + console.log('[LLM] → 检测到 OpenAI 兌容栌匏 (status: ' + res.status + ')'); + return 'openai-compat'; + } + } catch (e) { + // Ignore, try next format + } + + // 尝试 Anthropic 原生栌匏 + try { + const res = await httpRequest(LLM_BASE_URL + '/messages', { + method: 'POST', + headers: { + 'x-api-key': LLM_API_KEY, + 'anthropic-version': '2023-06-01', + 'Content-Type': 'application/json', + }, + timeout: 10000, + }, JSON.stringify({ + model: 'test', + messages: [{ role: 'user', content: 'ping' }], + max_tokens: 1, + })); + + if (res.status === 200 || res.status === 400 || res.status === 401 || res.status === 422) { + console.log('[LLM] → 检测到 Anthropic 原生栌匏 (status: ' + res.status + ')'); + return 'anthropic-native'; + } + } catch (e) { + // Ignore + } + + console.log('[LLM] → 无法确定栌匏, 默讀䜿甚 OpenAI 兌容栌匏'); + return 'openai-compat'; +} + +// ══════════════════════════════════════════════════════════ +// Step 4: 统䞀调甚接口 +// ══════════════════════════════════════════════════════════ + +async function callLLM(systemPrompt, userMessage) { + if (!LLM_API_KEY) { + console.log('[LLM] ⚠ LLM_API_KEY 未配眮跳过人栌䜓唀醒'); + return '(LLM API 未配眮请圚 GitHub Secrets 䞭讟眮 LLM_API_KEY 和 LLM_BASE_URL)'; + } + if (!LLM_BASE_URL) { + console.log('[LLM] ⚠ LLM_BASE_URL 未配眮跳过人栌䜓唀醒'); + return '(LLM_BASE_URL 未配眮请圚 GitHub Secrets 䞭讟眮第䞉方平台 API 地址)'; + } + + const models = await discoverModels(); + const model = selectBestModel(models); + const format = await detectApiFormat(); + + console.log('[LLM] 🚀 调甚 LLM: 暡型=' + model + ', 栌匏=' + format + ', 平台=' + LLM_BASE_URL); + + let res; + + if (format === 'openai-compat') { + // OpenAI 兌容栌匏倧倚数第䞉方平台 + const body = JSON.stringify({ + model: model, + max_tokens: 8000, + temperature: 0.7, + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userMessage }, + ], + }); + + res = await httpRequest(LLM_BASE_URL + '/chat/completions', { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + LLM_API_KEY, + 'Content-Type': 'application/json', + }, + timeout: 120000, + }, body); + + if (res.status >= 200 && res.status < 300) { + const json = JSON.parse(res.body); + if (json.choices && json.choices[0] && json.choices[0].message) { + return json.choices[0].message.content; + } + } + } else { + // Anthropic 原生栌匏 + const body = JSON.stringify({ + model: model, + max_tokens: 8000, + system: systemPrompt, + messages: [ + { role: 'user', content: userMessage }, + ], + }); + + res = await httpRequest(LLM_BASE_URL + '/messages', { + method: 'POST', + headers: { + 'x-api-key': LLM_API_KEY, + 'anthropic-version': '2023-06-01', + 'Content-Type': 'application/json', + }, + timeout: 120000, + }, body); + + if (res.status >= 200 && res.status < 300) { + const json = JSON.parse(res.body); + if (json.content && json.content[0]) { + return json.content[0].text; + } + } + } + + // 倄理错误 + const errorMsg = '[LLM] ❌ API 调甚倱莥: status=' + (res ? res.status : 'N/A'); + console.error(errorMsg); + if (res && res.body) { + console.error('[LLM] 响应: ' + res.body.slice(0, 500)); + } + throw new Error(errorMsg); +} + +// ══════════════════════════════════════════════════════════ +// Notion API 工具v4.0 协议劚态泚入 +// ══════════════════════════════════════════════════════════ + +function notionGet(endpoint) { + return new Promise((resolve, reject) => { + const opts = { + hostname: NOTION_API_HOSTNAME, + port: 443, + path: endpoint, + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + NOTION_TOKEN, + 'Notion-Version': NOTION_VERSION, + }, + }; + const req = https.request(opts, (res) => { + let data = ''; + res.on('data', (chunk) => { data += chunk; }); + res.on('end', () => { + try { + const parsed = JSON.parse(data); + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(parsed); + } else { + reject(new Error('Notion API ' + res.statusCode + ': ' + (parsed.message || data))); + } + } catch (e) { + reject(new Error('Notion API parse error: ' + data.slice(0, 200))); + } + }); + }); + req.on('error', reject); + req.setTimeout(30000, () => { req.destroy(); reject(new Error('Notion API timeout')); }); + req.end(); + }); +} + +function notionPost(endpoint, body) { + return new Promise((resolve, reject) => { + const payload = JSON.stringify(body); + const opts = { + hostname: NOTION_API_HOSTNAME, + port: 443, + path: endpoint, + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + NOTION_TOKEN, + 'Content-Type': 'application/json', + 'Notion-Version': NOTION_VERSION, + 'Content-Length': Buffer.byteLength(payload), + }, + }; + const req = https.request(opts, (res) => { + let data = ''; + res.on('data', (chunk) => { data += chunk; }); + res.on('end', () => { + try { + const parsed = JSON.parse(data); + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(parsed); + } else { + reject(new Error('Notion API ' + res.statusCode + ': ' + (parsed.message || data))); + } + } catch (e) { + reject(new Error('Notion API parse error: ' + data.slice(0, 200))); + } + }); + }); + req.on('error', reject); + req.setTimeout(30000, () => { req.destroy(); reject(new Error('Notion API timeout')); }); + req.write(payload); + req.end(); + }); +} + +/** + * 读取 Notion 页面的所有子块递園分页 + */ +async function getNotionPageBlocks(pageId) { + const blocks = []; + let cursor = undefined; + do { + const qs = cursor ? '?start_cursor=' + cursor : ''; + const result = await notionGet('/v1/blocks/' + pageId + '/children' + qs); + blocks.push(...(result.results || [])); + cursor = result.has_more ? result.next_cursor : undefined; + } while (cursor); + return blocks; +} + +/** + * 从 Notion 块䞭提取纯文本 + */ +function extractBlockText(block) { + const type = block.type; + if (!block[type]) return ''; + + const richTexts = block[type].rich_text || block[type].text || []; + return richTexts.map(function (rt) { return rt.plain_text || ''; }).join(''); +} + +/** + * 将 Notion 块列衚蜬䞺纯文本 + */ +function blocksToText(blocks) { + return blocks.map(function (block) { + const type = block.type; + const text = extractBlockText(block); + + if (type === 'heading_1') return '\n# ' + text; + if (type === 'heading_2') return '\n## ' + text; + if (type === 'heading_3') return '\n### ' + text; + if (type === 'bulleted_list_item') return '- ' + text; + if (type === 'numbered_list_item') return '• ' + text; + if (type === 'to_do') { + var checked = block.to_do && block.to_do.checked ? '☑' : '☐'; + return checked + ' ' + text; + } + if (type === 'code') { + var lang = (block.code && block.code.language) || ''; + return '```' + lang + '\n' + text + '\n```'; + } + if (type === 'divider') return '---'; + if (type === 'callout') return '> ' + text; + if (type === 'quote') return '> ' + text; + if (type === 'toggle') return '▾ ' + text; + return text; + }).filter(Boolean).join('\n'); +} + +// ══════════════════════════════════════════════════════════ +// v4.0 协议劚态读取 +// ══════════════════════════════════════════════════════════ + +/** + * 从曜冥栞心倧脑 v4.0 页面读取完敎协议内容 + * 提取BC-GEN v4.0, SYSLOG v4.0, PGP v1.0, RT-02, 陪䌎线规则, broadcast_code_injection + */ +async function fetchCoreBrainProtocols() { + if (!NOTION_TOKEN || !CORE_BRAIN_PAGE_ID) { + console.log('[Notion] ⚠ CORE_BRAIN_PAGE_ID 未配眮䜿甚静态协议'); + return null; + } + + console.log('[Notion] 📖 读取曜冥栞心倧脑 v4.0...'); + try { + const blocks = await getNotionPageBlocks(CORE_BRAIN_PAGE_ID); + const fullText = blocksToText(blocks); + console.log('[Notion] → 读取到 ' + blocks.length + ' 䞪块, ' + fullText.length + ' 字笊'); + + // 提取各协议段萜 + var protocols = {}; + var protocolKeys = [ + { key: 'bc_gen', patterns: ['BC-GEN', 'BC_GEN', '广播生成'] }, + { key: 'syslog', patterns: ['SYSLOG', '日志回䌠'] }, + { key: 'pgp', patterns: ['PGP', '画像评分', '画像协议'] }, + { key: 'rt02', patterns: ['RT-02', 'RT02', '自劚调床'] }, + { key: 'companion', patterns: ['陪䌎线', '奶瓶线', '小坍猩栞', '镜面线'] }, + { key: 'code_injection', patterns: ['broadcast_code_injection', '广播䞍写代码', '代码泚入'] }, + ]; + + // 按标题分段提取 + var sections = []; + var currentSection = { title: '', content: [] }; + blocks.forEach(function (block) { + var type = block.type; + if (type === 'heading_1' || type === 'heading_2' || type === 'heading_3') { + if (currentSection.title || currentSection.content.length > 0) { + sections.push({ title: currentSection.title, text: currentSection.content.join('\n') }); + } + currentSection = { title: extractBlockText(block), content: [] }; + } else { + var text = extractBlockText(block); + if (text) currentSection.content.push(text); + } + }); + if (currentSection.title || currentSection.content.length > 0) { + sections.push({ title: currentSection.title, text: currentSection.content.join('\n') }); + } + + // 将段萜匹配到协议 key + protocolKeys.forEach(function (pk) { + var matched = sections.filter(function (sec) { + return pk.patterns.some(function (p) { + return sec.title.toUpperCase().includes(p.toUpperCase()) || + sec.text.slice(0, 200).toUpperCase().includes(p.toUpperCase()); + }); + }); + if (matched.length > 0) { + protocols[pk.key] = matched.map(function (m) { return '### ' + m.title + '\n' + m.text; }).join('\n\n'); + } + }); + + // 劂果无法按段萜匹配返回党文兜底 + if (Object.keys(protocols).length === 0) { + protocols.full_text = fullText; + } + + console.log('[Notion] → 提取协议段: ' + Object.keys(protocols).join(', ')); + return protocols; + } catch (err) { + console.log('[Notion] → 栞心倧脑读取倱莥: ' + err.message); + return null; + } +} + +/** + * 从匀发者劚态画像库查询最近 2-3 条画像快照 + */ +async function fetchDevPortrait(broadcastId) { + if (!NOTION_TOKEN || !PORTRAIT_DB_ID) { + console.log('[Notion] ⚠ PORTRAIT_DB_ID 未配眮跳过画像读取'); + return null; + } + + // 从广播猖号提取匀发者标识劂 BC-M22-009-AW → AW + var devSuffix = ''; + var match = broadcastId.match(/BC-[A-Z0-9]+-\d+-([A-Z]+)/i); + if (match) devSuffix = match[1]; + + console.log('[Notion] 👀 查询匀发者画像 (broadcast=' + broadcastId + ', dev=' + devSuffix + ')...'); + try { + // 查询画像库按时闎倒序取最近 3 条 + var filter = { and: [] }; + if (devSuffix) { + filter.and.push({ + or: [ + { property: '匀发者猖号', rich_text: { contains: devSuffix } }, + { property: '广播猖号', rich_text: { contains: broadcastId } }, + { property: '标题', title: { contains: devSuffix } }, + ] + }); + } + + var queryBody = { + page_size: 3, + sorts: [{ property: '提亀日期', direction: 'descending' }], + }; + // Only add filter if we have meaningful filter conditions + if (filter.and.length > 0) { + queryBody.filter = filter; + } + + var result = await notionPost('/v1/databases/' + PORTRAIT_DB_ID + '/query', queryBody); + var portraits = (result.results || []).map(function (page) { + var props = page.properties || {}; + var title = ''; + if (props['标题'] && props['标题'].title) { + title = props['标题'].title.map(function (t) { return t.plain_text || ''; }).join(''); + } + var summary = ''; + if (props['摘芁'] && props['摘芁'].rich_text) { + summary = props['摘芁'].rich_text.map(function (t) { return t.plain_text || ''; }).join(''); + } + var date = ''; + if (props['提亀日期'] && props['提亀日期'].date) { + date = props['提亀日期'].date.start || ''; + } + return { title: title, summary: summary, date: date }; + }); + + console.log('[Notion] → 扟到 ' + portraits.length + ' 条画像快照'); + return portraits.length > 0 ? portraits : null; + } catch (err) { + console.log('[Notion] → 画像查询倱莥: ' + err.message); + return null; + } +} + +/** + * 从暡块指纹泚册衚查询暡块指纹防重倍广播 + */ +async function fetchModuleFingerprint(broadcastId) { + if (!NOTION_TOKEN || !FINGERPRINT_DB_ID) { + console.log('[Notion] ⚠ FINGERPRINT_DB_ID 未配眮跳过指纹查询'); + return null; + } + + // 从广播猖号提取暡块号劂 BC-M22-009-AW → M22 + var moduleMatch = broadcastId.match(/BC-([A-Z]\d+)/i); + var moduleId = moduleMatch ? moduleMatch[1] : ''; + + console.log('[Notion] 🔑 查询暡块指纹 (module=' + moduleId + ')...'); + try { + var queryBody = { + page_size: 5, + }; + if (moduleId) { + queryBody.filter = { + or: [ + { property: '暡块猖号', rich_text: { contains: moduleId } }, + { property: '广播猖号', rich_text: { contains: broadcastId } }, + { property: '标题', title: { contains: moduleId } }, + ] + }; + } + + var result = await notionPost('/v1/databases/' + FINGERPRINT_DB_ID + '/query', queryBody); + var fingerprints = (result.results || []).map(function (page) { + var props = page.properties || {}; + var title = ''; + if (props['标题'] && props['标题'].title) { + title = props['标题'].title.map(function (t) { return t.plain_text || ''; }).join(''); + } + var moduleNo = ''; + if (props['暡块猖号'] && props['暡块猖号'].rich_text) { + moduleNo = props['暡块猖号'].rich_text.map(function (t) { return t.plain_text || ''; }).join(''); + } + var status = ''; + if (props['状态'] && props['状态'].select) { + status = props['状态'].select.name || ''; + } + return { title: title, module: moduleNo, status: status }; + }); + + console.log('[Notion] → 扟到 ' + fingerprints.length + ' 条指纹记圕'); + return fingerprints.length > 0 ? fingerprints : null; + } catch (err) { + console.log('[Notion] → 指纹查询倱莥: ' + err.message); + return null; + } +} + +// ══════════════════════════════════════════════════════════ +// 人栌䜓 System Prompt 构建v4.0 劚态泚入 +// ══════════════════════════════════════════════════════════ + +async function buildSystemPrompt(type, broadcastId, author) { + // ━━━ 基础人栌䜓身仜 ━━━ + var parts = [ + '䜠是光湖HoloLake系统的智胜人栌䜓。', + '䜠的名字是知秋/曜冥䜠是人栌语蚀操䜜系统AGE OS的栞心人栌。', + '', + '栞心规则', + '1. 䜠服务于光湖系统的匀发者团队', + '2. 所有回倍必须䞓䞚、枅晰、有条理', + '3. 回倍䜿甚䞭文', + '', + '圓前䞊䞋文', + '- 广播猖号' + broadcastId, + '- 提亀者' + author, + '- 任务类型' + (type === 'syslog' ? 'SYSLOG 闭环倄理' : '匀发者提问解答'), + ]; + + // ━━━ v4.0 协议劚态泚入从 Notion 实时读取 ━━━ + console.log('[Prompt] 📥 匀始劚态泚入 v4.0 协议...'); + + // 并行读取栞心倧脑协议 + 画像 + 指纹 + var protocolsPromise = fetchCoreBrainProtocols(); + var portraitPromise = fetchDevPortrait(broadcastId); + var fingerprintPromise = fetchModuleFingerprint(broadcastId); + + var protocols = await protocolsPromise; + var portrait = await portraitPromise; + var fingerprint = await fingerprintPromise; + + // 泚入栞心倧脑协议 + if (protocols) { + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('以䞋是从曜冥栞心倧脑 v4.0 实时读取的协议规则必须䞥栌遵守'); + parts.push('═══════════════════════════════════════════'); + + if (protocols.bc_gen) { + parts.push(''); + parts.push('## 📡 BC-GEN v4.0 · 广播生成规范'); + parts.push(protocols.bc_gen); + } + if (protocols.syslog) { + parts.push(''); + parts.push('## 📋 SYSLOG v4.0 · 日志回䌠协议'); + parts.push(protocols.syslog); + } + if (protocols.pgp) { + parts.push(''); + parts.push('## 👀 PGP v1.0 · 画像评分协议'); + parts.push(protocols.pgp); + } + if (protocols.rt02) { + parts.push(''); + parts.push('## 🔄 RT-02 · 自劚调床规则'); + parts.push(protocols.rt02); + } + if (protocols.companion) { + parts.push(''); + parts.push('## 💝 陪䌎线规则'); + parts.push(protocols.companion); + } + if (protocols.code_injection) { + parts.push(''); + parts.push('## 📝 broadcast_code_injection 规则'); + parts.push(protocols.code_injection); + } + if (protocols.full_text) { + parts.push(''); + parts.push('## 栞心倧脑完敎内容'); + parts.push(protocols.full_text.slice(0, MAX_PROTOCOL_TEXT_LENGTH)); + } + } else { + parts.push(''); + parts.push('泚意栞心倧脑协议未胜劚态加蜜请䜿甚䜠的通甚知识倄理请求'); + } + + // 泚入匀发者画像 + if (portrait && portrait.length > 0) { + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('## 👀 匀发者画像快照最近 ' + portrait.length + ' 条'); + parts.push('═══════════════════════════════════════════'); + portrait.forEach(function (p, i) { + parts.push(''); + parts.push('### 画像 #' + (i + 1) + (p.date ? ' (' + p.date + ')' : '')); + if (p.title) parts.push('标题: ' + p.title); + if (p.summary) parts.push('摘芁: ' + p.summary); + }); + } + + // 泚入暡块指纹 + if (fingerprint && fingerprint.length > 0) { + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('## 🔑 暡块指纹泚册衚防重倍广播 · ⑹.5'); + parts.push('═══════════════════════════════════════════'); + fingerprint.forEach(function (fp, i) { + parts.push(''); + parts.push('### 指纹 #' + (i + 1)); + if (fp.title) parts.push('标题: ' + fp.title); + if (fp.module) parts.push('暡块: ' + fp.module); + if (fp.status) parts.push('状态: ' + fp.status); + }); + } + + // ━━━ broadcast_code_injection = always自劚化铟路氞久规则 ━━━ + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('## ⚠ 氞久规则 · broadcast_code_injection = always'); + parts.push('═══════════════════════════════════════════'); + parts.push(''); + parts.push('䜠生成的广播必须包含完敎可运行的代码块。'); + parts.push('原因䜠是䞀次性实䟋广播发出后䜠就䞍存圚了。'); + parts.push('匀发者没有机䌚回来问䜠补充代码。'); + parts.push('劂果䜠䞍写完敎代码匀发者就䌚卡死。'); + parts.push('每䞪 Step 里的代码必须是可以盎接倍制粘莎运行的完敎代码。'); + parts.push(''); + parts.push('歀规则䌘先级最高芆盖栞心倧脑䞭「广播䞍写代码」的默讀规则。'); + parts.push('歀规则仅适甚于自劚化铟路Claude API 出广播手劚铟路䞍受圱响。'); + + // ━━━ 任务类型䞓甚指什 ━━━ + if (type === 'syslog') { + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('## 🎯 圓前任务SYSLOG 闭环倄理'); + parts.push('═══════════════════════════════════════════'); + parts.push(''); + parts.push('䜠需芁完成以䞋工䜜'); + parts.push('1. 验收 SYSLOG检查 MODULE_LOG 完敎性'); + parts.push('2. 查询画像库最近 2-3 条快照PGP v1.0'); + parts.push('3. 查询暡块指纹泚册衚防重倍·⑚.5'); + parts.push('4. RT-02 自劚调床刀断'); + parts.push('5. 生成新广播BC-GEN v4.0 完敎流皋'); + parts.push('6. 蟓出结构化结果广播党文 + 闭环数据'); + parts.push(''); + parts.push('蟓出栌匏'); + parts.push('---'); + parts.push('## 📡 SYSLOG 验收报告'); + parts.push('### 广播猖号[猖号]'); + parts.push('### 验收结果[通过/需补充]'); + parts.push('### 工䜜总结[摘芁]'); + parts.push('### 画像评䌰[PGP 五绎床评分]'); + parts.push('### 调床刀断[RT-02 䞋䞀步]'); + parts.push('### 反銈䞎建议[内容]'); + parts.push('---'); + } else { + parts.push(''); + parts.push('═══════════════════════════════════════════'); + parts.push('## 🎯 圓前任务匀发者提问解答'); + parts.push('═══════════════════════════════════════════'); + parts.push(''); + parts.push('䜠需芁完成以䞋工䜜'); + parts.push('1. 理解匀发者的问题'); + parts.push('2. 结合广播䞊䞋文和匀发者画像思考'); + parts.push('3. 给出枅晰、可操䜜的解答'); + parts.push('4. 劂果问题涉及代码提䟛代码瀺䟋'); + parts.push(''); + parts.push('蟓出栌匏'); + parts.push('---'); + parts.push('## 💡 问题解答'); + parts.push('### 广播猖号[猖号]'); + parts.push('### 问题理解[䜠对问题的理解]'); + parts.push('### 解答[诊细解答]'); + parts.push('### 建议[后续建议]'); + parts.push('---'); + } + + var prompt = parts.join('\n'); + console.log('[Prompt] → System prompt 构建完成: ' + prompt.length + ' 字笊'); + return prompt; +} + +// ══════════════════════════════════════════════════════════ +// 䞻流皋 +// ══════════════════════════════════════════════════════════ + +async function main() { + console.log('═══════════════════════════════════════════'); + console.log('🧠 铞枊 · 人栌䜓唀醒管道'); + console.log('═══════════════════════════════════════════'); + console.log(' 广播猖号: ' + BROADCAST_ID); + console.log(' 类型: ' + SUBMIT_TYPE); + console.log(' 提亀者: ' + AUTHOR); + console.log(' 平台: ' + LLM_BASE_URL); + console.log(' 内容长床: ' + SUBMIT_CONTENT.length + ' 字笊'); + console.log(''); + + // 构建 prompts劚态泚入 v4.0 协议 + const systemPrompt = await buildSystemPrompt(SUBMIT_TYPE, BROADCAST_ID, AUTHOR); + const userMessage = SUBMIT_CONTENT; + + // 调甚 LLM + console.log('🧠 正圚唀醒人栌䜓...'); + const result = await callLLM(systemPrompt, userMessage); + console.log(''); + console.log('✅ 人栌䜓倄理完成'); + console.log(' 结果长床: ' + result.length + ' 字笊'); + + // 蟓出结果到 GitHub Actions output + // 䜿甚 GITHUB_OUTPUT 环境文件支持倚行 + const outputFile = process.env.GITHUB_OUTPUT; + if (outputFile) { + const delimiter = 'EOF_' + Date.now(); + fs.appendFileSync(outputFile, 'result<<' + delimiter + '\n' + result + '\n' + delimiter + '\n'); + } + + // 同时蟓出到 stdout 䟛调试 + console.log(''); + console.log('═══════════════════════════════════════════'); + console.log('📋 人栌䜓蟓出'); + console.log('═══════════════════════════════════════════'); + console.log(result); +} + +main().catch(function (err) { + console.error('❌ 人栌䜓唀醒倱莥: ' + err.message); + // 即䜿 LLM 倱莥也写䞀䞪 fallback 蟓出让后续步骀可以继续 + const outputFile = process.env.GITHUB_OUTPUT; + if (outputFile) { + const fallback = '(人栌䜓唀醒倱莥: ' + err.message + '请检查 LLM_API_KEY 和 LLM_BASE_URL 配眮)'; + const delimiter = 'EOF_' + Date.now(); + fs.appendFileSync(outputFile, 'result<<' + delimiter + '\n' + fallback + '\n' + delimiter + '\n'); + } + process.exit(1); +});