From 60001499dab3cf5cc3b3e7b60c9c3c0ee6997290 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 16 Jun 2026 17:00:24 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E8=85=B3=E8=89=B2=E8=BC=89=E5=85=A5?= =?UTF-8?q?=E5=99=A8):=20=E5=A3=9E=E8=A7=92=E8=89=B2=E6=AA=94=E6=94=B9?= =?UTF-8?q?=E8=A8=98=E9=8C=84=E8=AD=A6=E5=91=8A=E4=B8=A6=E7=95=A5=E9=81=8E?= =?UTF-8?q?=E3=80=81=E5=BF=AB=E5=8F=96=E8=A7=A3=E6=9E=90=E7=B5=90=E6=9E=9C?= =?UTF-8?q?=E4=B8=A6=E8=A3=9C=20focus/personality=20=E7=BC=BA=E6=BC=8F?= =?UTF-8?q?=E9=98=B2=E8=AD=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/roles.js | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/app/roles.js b/app/roles.js index 7e38b7b..3d7a680 100644 --- a/app/roles.js +++ b/app/roles.js @@ -2,6 +2,7 @@ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import yaml from 'js-yaml'; +import { warn } from './log.js'; const ROLES_DIR = path.join(fileURLToPath(import.meta.url), '..', 'prompts', 'roles'); @@ -17,11 +18,24 @@ export function parseRoleFile(content) { return { ...meta, body: match[2].trim() }; } +let cachedRoles = null; + +/** + * 讀取並解析所有角色 .md,結果快取於模組層級(單次程序生命週期內檔案不變)。 + * 單一檔案解析失敗(壞 YAML、缺 frontmatter 等)時記錄警告並略過,不讓整個流程崩潰。 + */ function readRoleFiles() { - return fs.readdirSync(ROLES_DIR) - .filter(f => f.endsWith('.md')) - .sort() - .map(f => parseRoleFile(fs.readFileSync(path.join(ROLES_DIR, f), 'utf8'))); + if (cachedRoles) return cachedRoles; + const roles = []; + for (const f of fs.readdirSync(ROLES_DIR).filter(f => f.endsWith('.md')).sort()) { + try { + roles.push(parseRoleFile(fs.readFileSync(path.join(ROLES_DIR, f), 'utf8'))); + } catch (e) { + warn(`角色檔解析失敗,已略過: ${f}(${e.message})`); + } + } + cachedRoles = roles; + return cachedRoles; } /** @@ -44,7 +58,7 @@ export function loadRole(name) { */ export function buildAnalysisPrompt(role) { return [ - `你是 ${role.badge ? role.badge + ' ' : ''}${role.name},負責「${role.focus}」面向的程式碼審查(攻擊方)。`, + `你是 ${role.badge ? role.badge + ' ' : ''}${role.name},負責「${role.focus || '綜合'}」面向的程式碼審查(攻擊方)。`, role.personality ? `個性:${role.personality}` : '', '', role.body, @@ -77,7 +91,7 @@ export function getRoleIntro(roles) { ]; for (const r of roles) { const badge = r.badge ? `${r.badge} ` : ''; - lines.push(`| **${badge}${r.name}** | ${r.focus} | ${r.personality} |`); + lines.push(`| **${badge}${r.name}** | ${r.focus || ''} | ${r.personality || ''} |`); } return lines.join('\n'); }