修复代码审查和安全扫描反馈 · ID碰撞修复+权限声明+正则安全+敏感信息过滤
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/c4628b3c-e295-41e0-bdd7-1459958b5390 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
parent
43105b62e4
commit
0189965e05
|
|
@ -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');
|
||||
}
|
||||
})();
|
||||
"
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
})();
|
||||
"
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue