From 0189965e0576659c7701978943a9fa996caba1a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Apr 2026 13:23:34 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81=E5=AE=A1?= =?UTF-8?q?=E6=9F=A5=E5=92=8C=E5=AE=89=E5=85=A8=E6=89=AB=E6=8F=8F=E5=8F=8D?= =?UTF-8?q?=E9=A6=88=20=C2=B7=20ID=E7=A2=B0=E6=92=9E=E4=BF=AE=E5=A4=8D+?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=A3=B0=E6=98=8E+=E6=AD=A3=E5=88=99?= =?UTF-8?q?=E5=AE=89=E5=85=A8+=E6=95=8F=E6=84=9F=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/c4628b3c-e295-41e0-bdd7-1459958b5390 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/workflows/cos-alert-agent.yml | 17 +++++++++++------ .github/workflows/zhuyuan-training-agent.yml | 12 ++++++++---- .../mcp-server/tools/corpus-extractor-ops.js | 2 +- server/age-os/mcp-server/tools/cos-comm-ops.js | 3 ++- .../mcp-server/tools/notion-cos-bridge-ops.js | 9 +++++---- .../mcp-server/tools/notion-permission-ops.js | 5 +---- .../mcp-server/tools/training-agent-ops.js | 17 +++++++++++------ 7 files changed, 39 insertions(+), 26 deletions(-) diff --git a/.github/workflows/cos-alert-agent.yml b/.github/workflows/cos-alert-agent.yml index 571ef2fc..dc938b36 100644 --- a/.github/workflows/cos-alert-agent.yml +++ b/.github/workflows/cos-alert-agent.yml @@ -29,6 +29,9 @@ jobs: alert-scan: runs-on: ubuntu-latest timeout-minutes: 10 + permissions: + contents: read + issues: write steps: - name: 签出代码 @@ -68,14 +71,16 @@ jobs: console.log(JSON.stringify(commLink, null, 2)); // 输出结果 - console.log('::set-output name=critical::' + alerts.critical); - console.log('::set-output name=total::' + alerts.total); - console.log('::set-output name=health::' + commLink.health); + const fs = require('fs'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'critical=' + alerts.critical + '\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'total=' + alerts.total + '\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'health=' + commLink.health + '\n'); } catch (err) { console.error('扫描失败:', err.message); - console.log('::set-output name=critical::0'); - console.log('::set-output name=total::0'); - console.log('::set-output name=health::error'); + const fs = require('fs'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'critical=0\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'total=0\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'health=error\n'); } })(); " diff --git a/.github/workflows/zhuyuan-training-agent.yml b/.github/workflows/zhuyuan-training-agent.yml index 42f08c62..d2eede30 100644 --- a/.github/workflows/zhuyuan-training-agent.yml +++ b/.github/workflows/zhuyuan-training-agent.yml @@ -35,6 +35,8 @@ jobs: training: runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: read steps: - name: 签出代码 @@ -65,12 +67,14 @@ jobs: console.log(JSON.stringify(status, null, 2)); // 输出待处理数量 const pending = status.pending || 0; - console.log('::set-output name=pending::' + pending); - console.log('::set-output name=status::success'); + const fs = require('fs'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'pending=' + pending + '\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'status=success\n'); } catch (err) { console.error('语料检查失败:', err.message); - console.log('::set-output name=status::error'); - console.log('::set-output name=error::' + err.message); + const fs = require('fs'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'status=error\n'); + fs.appendFileSync(process.env.GITHUB_OUTPUT, 'error=' + err.message + '\n'); } })(); " diff --git a/server/age-os/mcp-server/tools/corpus-extractor-ops.js b/server/age-os/mcp-server/tools/corpus-extractor-ops.js index 42bcd3f0..30f415b1 100644 --- a/server/age-os/mcp-server/tools/corpus-extractor-ops.js +++ b/server/age-os/mcp-server/tools/corpus-extractor-ops.js @@ -389,7 +389,7 @@ function transformGPTToTCS(content, sourceKey) { if (conversation.mapping) { // ChatGPT格式 for (const [, node] of Object.entries(conversation.mapping)) { - if (node.message?.content?.parts) { + if (node.message?.content?.parts && Array.isArray(node.message.content.parts)) { const text = node.message.content.parts.join('\n'); if (text.trim()) { messages.push({ diff --git a/server/age-os/mcp-server/tools/cos-comm-ops.js b/server/age-os/mcp-server/tools/cos-comm-ops.js index d1027389..c8a249be 100644 --- a/server/age-os/mcp-server/tools/cos-comm-ops.js +++ b/server/age-os/mcp-server/tools/cos-comm-ops.js @@ -27,6 +27,7 @@ 'use strict'; +const crypto = require('crypto'); const cos = require('../cos'); // ─── 路径常量 ─── @@ -145,7 +146,7 @@ async function cosDispatchTask(input) { if (!title) throw new Error('缺少 title'); const targetBucket = bucket || 'team'; - const tId = task_id || `TASK-${formatDate()}-${String(Math.floor(Math.random() * 1000)).padStart(3, '0')}`; + const tId = task_id || `TASK-${formatDate()}-${crypto.randomBytes(4).toString('hex')}`; // 验证 task_id 安全性 if (!/^[a-zA-Z0-9_-]+$/.test(tId)) { diff --git a/server/age-os/mcp-server/tools/notion-cos-bridge-ops.js b/server/age-os/mcp-server/tools/notion-cos-bridge-ops.js index 43148a07..b68cd09a 100644 --- a/server/age-os/mcp-server/tools/notion-cos-bridge-ops.js +++ b/server/age-os/mcp-server/tools/notion-cos-bridge-ops.js @@ -28,8 +28,8 @@ 'use strict'; +const crypto = require('crypto'); const cos = require('../cos'); - // 运行时可选加载 notion-client(不影响核心功能) let notionClient = null; try { @@ -40,6 +40,7 @@ try { // ─── 常量 ─── const MIRROR_PREFIX = 'notion-mirror/'; +const MIRROR_PREFIX_REGEX = /^notion-mirror\/([^/]+)\//; const WORKORDER_PREFIX = 'workorders/'; /** @@ -158,7 +159,7 @@ async function notionCosListMirror(input) { // 提取唯一的page_id const pageIds = new Set(); for (const file of result.files) { - const match = file.key.match(new RegExp(`^${MIRROR_PREFIX.replace(/[/]/g, '\\/')}([^/]+)\\/`)); + const match = file.key.match(MIRROR_PREFIX_REGEX); if (match) pageIds.add(match[1]); } @@ -202,7 +203,7 @@ async function notionCosBuildIndex(input) { // 提取唯一的page_id和元数据 const pageMap = {}; for (const file of result.files) { - const match = file.key.match(new RegExp(`^${MIRROR_PREFIX.replace(/[/]/g, '\\/')}([^/]+)\\/`)); + const match = file.key.match(MIRROR_PREFIX_REGEX); if (match) { const pageId = match[1]; if (!pageMap[pageId]) pageMap[pageId] = { files: [] }; @@ -277,7 +278,7 @@ async function notionCosWriteWorkorder(input) { if (!title) throw new Error('缺少 title'); const targetBucket = bucket || 'team'; - const woId = workorder_id || `WO-${formatDate()}-${String(Math.floor(Math.random() * 1000)).padStart(3, '0')}`; + const woId = workorder_id || `WO-${formatDate()}-${crypto.randomBytes(4).toString('hex')}`; // 验证 workorder_id 安全性 if (!/^[a-zA-Z0-9_-]+$/.test(woId)) { diff --git a/server/age-os/mcp-server/tools/notion-permission-ops.js b/server/age-os/mcp-server/tools/notion-permission-ops.js index ebe09116..6720e72e 100644 --- a/server/age-os/mcp-server/tools/notion-permission-ops.js +++ b/server/age-os/mcp-server/tools/notion-permission-ops.js @@ -234,13 +234,10 @@ async function notionRepairPermissions(input) { let repaired = 0; let failed = 0; - // 1. 尝试重新连接(清除缓存的客户端实例) + // 1. 尝试重新连接 if (auto_retry) { repairLog.push({ step: '重新初始化Notion客户端', status: 'attempting' }); try { - // 通过重新require来重置客户端 - delete require.cache[require.resolve('../notion-client')]; - notionClient = require('../notion-client'); const check = await notionClient.checkConnection(); if (check.connected) { repairLog.push({ step: '重新连接', status: 'success', user: check.user }); diff --git a/server/age-os/mcp-server/tools/training-agent-ops.js b/server/age-os/mcp-server/tools/training-agent-ops.js index 84a0b65b..6b8b65f7 100644 --- a/server/age-os/mcp-server/tools/training-agent-ops.js +++ b/server/age-os/mcp-server/tools/training-agent-ops.js @@ -27,6 +27,7 @@ 'use strict'; const https = require('https'); +const crypto = require('crypto'); const cos = require('../cos'); // ─── LLM 配置 ─── @@ -71,6 +72,10 @@ const LLM_CONFIGS = { // ─── 模型降级路由 ─── const MODEL_FALLBACK_CHAIN = ['deepseek-v3', 'qwen-max', 'glm-4-long', 'moonshot-128k']; +// ─── 常量 ─── +const MAX_CONTENT_FOR_ANALYSIS = 3000; +const MAX_PROMPT_CONTENT = 5000; + /** * trainingStartSession — 启动训练会话 * @@ -85,7 +90,7 @@ async function trainingStartSession(input) { const { persona_id, corpus_bucket, corpus_prefix, target_model, session_name } = input; if (!persona_id) throw new Error('缺少 persona_id'); - const sessionId = `train-${persona_id}-${Date.now()}`; + const sessionId = `train-${persona_id}-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`; const now = new Date().toISOString(); // 扫描可用语料 @@ -175,8 +180,8 @@ async function trainingProcessCorpus(input) { for (const entry of toProcess) { // 用LLM分析和分类 const contentForAnalysis = typeof entry.content === 'string' - ? entry.content.substring(0, 3000) - : JSON.stringify(entry).substring(0, 3000); + ? entry.content.substring(0, MAX_CONTENT_FOR_ANALYSIS) + : JSON.stringify(entry).substring(0, MAX_CONTENT_FOR_ANALYSIS); const classificationPrompt = buildClassificationPrompt(persona_id, corpus.corpus_type, contentForAnalysis); @@ -246,7 +251,7 @@ async function trainingClassifyEntry(input) { const prompt = buildClassificationPrompt( persona_id, corpus_type || 'generic', - content.substring(0, 5000) + content.substring(0, MAX_PROMPT_CONTENT) ); const llmResult = await callLLMWithFallback(prompt, model); @@ -521,10 +526,10 @@ function callLLM(config, apiKey, prompt) { tokens: data.usage || {} }); } catch { - reject(new Error(`LLM响应解析失败: ${responseBody.substring(0, 200)}`)); + reject(new Error(`LLM响应解析失败`)); } } else { - reject(new Error(`LLM调用失败 ${res.statusCode}: ${responseBody.substring(0, 200)}`)); + reject(new Error(`LLM调用失败 ${res.statusCode}`)); } }); });