fix: address code review — module-level JWT check, safer JSON extraction, Node.js in workflow

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/9f983442-2152-4e4a-82b7-c13fe55f0b9a
This commit is contained in:
copilot-swe-agent[bot] 2026-03-24 13:04:55 +00:00
parent d7ac8557ee
commit a04003e944
3 changed files with 42 additions and 36 deletions

View File

@ -52,7 +52,7 @@ jobs:
echo "🦅 天眼强制前置:检查健康状态..."
# 读取最新天眼报告(从 notion-cache 或 skyeye-core
if [ -f ".github/notion-cache/skyeye/latest-report.json" ]; then
STATUS=$(cat .github/notion-cache/skyeye/latest-report.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('overall_status','unknown'))" 2>/dev/null || echo "unknown")
STATUS=$(node -e "try{const d=require('./.github/notion-cache/skyeye/latest-report.json');console.log(d.overall_status||'unknown')}catch(_){console.log('unknown')}" 2>/dev/null || echo "unknown")
echo "天眼缓存状态:$STATUS"
if [ "$STATUS" = "critical" ] || [ "$STATUS" = "error" ]; then
echo "❌ 天眼报告严重问题,暂停执行"

View File

@ -15,9 +15,13 @@
const https = require('https');
// 模块级检查jsonwebtoken 是否可用
let jwtLib = null;
try { jwtLib = require('jsonwebtoken'); } catch (_) { /* fallback to crypto */ }
/**
* App Private Key 生成 JWT不依赖 jsonwebtoken 库的 fallback 实现
* CI 环境中可能没有安装 jsonwebtoken因此提供纯 Node.js 实现
* App Private Key 生成 JWT
* 优先使用 jsonwebtoken 不可用时降级到 Node.js crypto 实现
*/
function generateJWT() {
const privateKey = process.env.GHAPP_PRIVATE_KEY;
@ -27,16 +31,15 @@ function generateJWT() {
throw new Error('GHAPP_APP_ID 和 GHAPP_PRIVATE_KEY 环境变量必须设置');
}
// 尝试使用 jsonwebtoken 库
try {
const jwt = require('jsonwebtoken');
if (jwtLib) {
const payload = {
iat: Math.floor(Date.now() / 1000) - 60,
exp: Math.floor(Date.now() / 1000) + (10 * 60),
iss: appId
};
return jwt.sign(payload, privateKey, { algorithm: 'RS256' });
} catch (e) {
return jwtLib.sign(payload, privateKey, { algorithm: 'RS256' });
}
// jsonwebtoken 不可用时,使用 Node.js crypto 实现
const crypto = require('crypto');
@ -62,7 +65,6 @@ function generateJWT() {
const signature = base64url(sign.sign(privateKey));
return sigInput + '.' + signature;
}
}
/**

View File

@ -215,13 +215,17 @@ async function main() {
try {
plan = JSON.parse(aiResponse);
} catch (_) {
// 尝试从回复中提取 JSON
const jsonMatch = aiResponse.match(/\{[\s\S]*\}/);
// 尝试从回复中提取 JSON(非贪婪匹配,找第一个完整 JSON 对象)
const jsonMatch = aiResponse.match(/\{[\s\S]*?"actions"[\s\S]*?\}(?=\s*$|\s*\n)/);
if (jsonMatch) {
try {
plan = JSON.parse(jsonMatch[0]);
} catch (_2) {
plan = null;
// 降级:找所有 { } 对中最长的合法 JSON
const allMatches = aiResponse.match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g) || [];
for (const m of allMatches) {
try { plan = JSON.parse(m); if (plan.actions) break; } catch (_3) { plan = null; }
}
}
}
}