🔧 修复代码审查反馈·磁盘验证·日志截断·SSH安全·危险命令·动态错误模式

Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/29df49f6-bbbb-49af-8e63-96704b11d9c5

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-01 18:03:11 +00:00 committed by GitHub
parent c9c0327127
commit 3ce4bb8514
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 4 deletions

View File

@ -50,6 +50,16 @@ function ensureDir(dir) {
}
}
// 智能截断日志:保留头部和尾部,确保错误信息不丢失
function truncateLog(content, maxLen) {
if (!content || content.length <= maxLen) return content;
const headSize = Math.floor(maxLen * 0.3); // 30%给头部
const tailSize = maxLen - headSize - 100; // 70%给尾部(错误通常在末尾)
const head = content.slice(0, headSize);
const tail = content.slice(-tailSize);
return `${head}\n\n... [截断 ${content.length - headSize - tailSize} 字符] ...\n\n${tail}`;
}
// ── GitHub API 请求 ────────────────────────────
function githubApi(endpoint) {
const token = process.env.GH_TOKEN || process.env.GITHUB_TOKEN;
@ -225,7 +235,7 @@ async function collectLogs() {
conclusion: s.conclusion,
number: s.number
})),
log_content: logContent.slice(0, 10000) // 限制日志大小
log_content: truncateLog(logContent, 10000) // 智能截断:保留头部和尾部
});
console.log(` ✅ 日志采集成功 (${logContent.length} 字符)`);
} catch (err) {
@ -330,6 +340,7 @@ async function collectLogs() {
// ── 简单错误分析 (模式匹配) ────────────────────
function simpleAnalysis(logContent) {
// 基础错误模式 + 动态加载经验库中的错误模式
const patterns = [
{ regex: /EADDRINUSE/i, name: '端口被占用', fix: '重启PM2进程释放端口', severity: 'medium' },
{ regex: /ECONNREFUSED/i, name: '服务连接被拒绝', fix: '检查PM2进程是否运行', severity: 'high' },
@ -349,6 +360,27 @@ function simpleAnalysis(logContent) {
{ regex: /exit code [1-9]/i, name: '命令执行失败', fix: '查看上方具体错误信息', severity: 'medium' }
];
// 尝试从经验数据库动态加载错误模式
try {
const errPatternsDb = JSON.parse(fs.readFileSync(ERROR_PATTERNS_DB, 'utf8'));
if (errPatternsDb.patterns) {
for (const p of errPatternsDb.patterns) {
// 提取经验库中的关键词作为匹配模式
const keywords = p.pattern.split(/[·\s+]/g).filter(k => k.length > 3);
if (keywords.length > 0) {
patterns.push({
regex: new RegExp(keywords.join('|'), 'i'),
name: `[经验库] ${p.pattern}`,
fix: (p.prevention || []).join(' → ') || '参考经验库',
severity: p.severity || 'medium'
});
}
}
}
} catch {
// 经验库加载失败不影响基础分析
}
const matched = [];
for (const p of patterns) {
if (p.regex.test(logContent)) {

View File

@ -99,7 +99,7 @@ const REPAIR_STRATEGIES = [
'sudo find /tmp -type f -mtime +1 -delete 2>/dev/null || true',
'df -h /'
],
verify: 'AVAIL=$(df / | tail -1 | awk \'{print $5}\' | tr -d \'%\'); [ "$AVAIL" -lt 90 ] || exit 1',
verify: 'USED=$(df / | tail -1 | awk \'{print $5}\' | tr -d \'%\'); [ "$USED" -lt 90 ] || exit 1',
severity: 'high',
success_rate: '中 · 取决于可清理的文件量'
},
@ -132,7 +132,7 @@ function sshExec(command) {
}
try {
const sshCmd = `ssh -i ~/.ssh/zy_key -o ConnectTimeout=10 -o StrictHostKeyChecking=no ${user}@${host} '${command.replace(/'/g, "'\\''")}'`;
const sshCmd = `ssh -i ~/.ssh/zy_key -o ConnectTimeout=10 ${user}@${host} '${command.replace(/'/g, "'\\''")}'`;
const output = execSync(sshCmd, {
timeout: 60000, // 60秒超时
encoding: 'utf8',
@ -463,7 +463,7 @@ async function repair() {
// ── 危险命令检测 ────────────────────────────
function isDangerousCommand(cmd) {
const dangerous = [
/rm\s+-rf\s+\//, // rm -rf /
/rm\s+-r[fF]*\s+(\/|~|\$HOME)/, // rm -rf / or ~ or $HOME
/mkfs/, // 格式化
/dd\s+if=/, // 磁盘写入
/shutdown/, // 关机
@ -474,6 +474,7 @@ function isDangerousCommand(cmd) {
/chmod\s+-R\s+777\s+\//, // 全局777
/userdel/, // 删除用户
/passwd/, // 修改密码
/rm\s+-r[fF]*\s+\/\w/, // rm -rf /home etc
];
return dangerous.some(regex => regex.test(cmd));
}