feat(腳色系統): 改用 skill RPG 攻防腳色、新增 Mage 邏輯角色並讓 Step3/4 套上 Paladin 裁決人設
This commit is contained in:
+63
-5
@@ -5,21 +5,79 @@ import yaml from 'js-yaml';
|
||||
|
||||
const ROLES_DIR = path.join(fileURLToPath(import.meta.url), '..', 'prompts', 'roles');
|
||||
|
||||
export function loadRoles() {
|
||||
/**
|
||||
* 解析單一角色 .md 檔:前置 YAML frontmatter(徽章、代表色、面向、個性等)+ 本文(審查重點)。
|
||||
* 回傳合併後的角色物件:{ name, side, focus, badge, color, personality, body }。
|
||||
*/
|
||||
export function parseRoleFile(content) {
|
||||
const normalized = content.replace(/\r\n/g, '\n');
|
||||
const match = normalized.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
||||
if (!match) throw new Error('角色檔缺少 frontmatter');
|
||||
const meta = yaml.load(match[1]) || {};
|
||||
return { ...meta, body: match[2].trim() };
|
||||
}
|
||||
|
||||
function readRoleFiles() {
|
||||
return fs.readdirSync(ROLES_DIR)
|
||||
.filter(f => f.endsWith('.yaml'))
|
||||
.filter(f => f.endsWith('.md'))
|
||||
.sort()
|
||||
.map(f => yaml.load(fs.readFileSync(path.join(ROLES_DIR, f), 'utf8')));
|
||||
.map(f => parseRoleFile(fs.readFileSync(path.join(ROLES_DIR, f), 'utf8')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 載入攻擊方角色(Step2 產生 findings 用),依檔名排序。
|
||||
* 防守方(如 Paladin)不在此列,裁決邏輯由去重/誤報過濾流程承擔。
|
||||
*/
|
||||
export function loadRoles() {
|
||||
return readRoleFiles().filter(r => r.side === 'attack');
|
||||
}
|
||||
|
||||
/** 依 frontmatter name 取得單一角色(不分大小寫),找不到回傳 null。 */
|
||||
export function loadRole(name) {
|
||||
const target = String(name).toLowerCase();
|
||||
return readRoleFiles().find(r => String(r.name).toLowerCase() === target) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 由角色定義組出攻擊方的 system prompt:
|
||||
* 套用其個性與審查重點本文,並要求以固定 JSON 陣列格式回傳 findings。
|
||||
*/
|
||||
export function buildAnalysisPrompt(role) {
|
||||
return [
|
||||
`你是 ${role.badge ? role.badge + ' ' : ''}${role.name},負責「${role.focus}」面向的程式碼審查(攻擊方)。`,
|
||||
role.personality ? `個性:${role.personality}` : '',
|
||||
'',
|
||||
role.body,
|
||||
'',
|
||||
'---',
|
||||
'',
|
||||
'請分析以下 Git Diff,只針對新增/修改處,依你的面向找出所有問題。',
|
||||
'回傳 JSON 陣列,每個問題格式如下:',
|
||||
'{',
|
||||
' "level": "critical|warning|info",',
|
||||
` "role": "${role.name}",`,
|
||||
' "location": "檔案路徑:行號 或 檔案路徑",',
|
||||
' "suggestion": "繁體中文(台灣用語)的具體修改建議"',
|
||||
'}',
|
||||
'',
|
||||
'等級定義:',
|
||||
'- critical:嚴重且應立即處理的問題',
|
||||
'- warning:建議修正的問題',
|
||||
'- info:可選的改善建議',
|
||||
'',
|
||||
'只回傳 JSON 陣列,不要有其他文字。如果沒有問題,回傳空陣列 []。',
|
||||
].filter(l => l !== '').join('\n');
|
||||
}
|
||||
|
||||
export function getRoleIntro(roles) {
|
||||
const lines = [
|
||||
'## 🤖 AI Code Review 團隊', '',
|
||||
'| 👤 名稱 | 🎯 職責 | 🧠 個性 |',
|
||||
'| 👤 角色 | 🎯 面向 | 🧠 個性 |',
|
||||
'|--------|--------|--------|',
|
||||
];
|
||||
for (const r of roles) {
|
||||
lines.push(`| **${r.name}** | ${r.role} | ${r.personality} |`);
|
||||
const badge = r.badge ? `${r.badge} ` : '';
|
||||
lines.push(`| **${badge}${r.name}** | ${r.focus} | ${r.personality} |`);
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user