小白龙 Bailongma - 初始提交

自主操作员与思考搭档系统。
包含 orchestrator-v2 多Agent编排层、后台意识引擎、记忆系统、ACUI 组件。
This commit is contained in:
chengjiaxi
2026-05-22 19:22:06 +08:00
commit 664ffb3834
64 changed files with 111533 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
const fs = require('fs');
const path = require('path');
const AGENCY_DIR = path.resolve('D:/q/Bailongma/agency-agents-zh');
class RoleTemplates {
constructor() {
this.roles = new Map(); // roleId -> role definition
this.byCategory = new Map(); // category -> [roleId, ...]
this.byKeyword = new Map(); // keyword -> [roleId, ...]
this.initialized = false;
}
async init() {
if (this.initialized) return;
this._scanDirectory(AGENCY_DIR);
this.initialized = true;
console.log(`[RoleTemplates] Loaded ${this.roles.size} roles in ${this.byCategory.size} categories`);
}
_scanDirectory(dir, category = null) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
const subCategory = category ? `${category}/${entry.name}` : entry.name;
if (!entry.name.startsWith('.')) {
this._scanDirectory(fullPath, subCategory);
}
} else if (entry.isFile() && entry.name.endsWith('.md') && entry.name !== 'README.md') {
// Skip non-role files
const skipFiles = ['CATALOG.md', 'UPSTREAM.md', 'CONTRIBUTING.md', 'LICENSE',
'AGENT-LIST.md', 'EXECUTIVE-BRIEF.md', 'QUICKSTART.md', 'nexus-strategy.md'];
if (skipFiles.includes(entry.name)) continue;
if (entry.name.startsWith('bug') || entry.name.startsWith('feature') || entry.name.startsWith('new_agent') || entry.name.startsWith('PULL_REQUEST')) continue;
this._parseRoleFile(fullPath, category);
}
}
}
_parseRoleFile(filePath, category) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
const roleId = path.basename(filePath, '.md');
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
let name = roleId;
let description = '';
let emoji = '🤖';
let color = 'gray';
let body = content;
if (match) {
const frontMatter = match[1];
body = match[2].trim();
const nameMatch = frontMatter.match(/^name:\s*(.+)$/m);
if (nameMatch) name = nameMatch[1].trim();
const descMatch = frontMatter.match(/^description:\s*(.+)$/m);
if (descMatch) description = descMatch[1].trim();
const emojiMatch = frontMatter.match(/^emoji:\s*(.+)$/m);
if (emojiMatch) emoji = emojiMatch[1].trim();
const colorMatch = frontMatter.match(/^color:\s*(.+)$/m);
if (colorMatch) color = colorMatch[1].trim();
}
const role = {
id: roleId,
name,
description,
emoji,
color,
category: category || 'uncategorized',
body,
filePath,
fullPrompt: body // The full markdown body serves as the system prompt template
};
this.roles.set(roleId, role);
// Index by category
const cat = category || 'uncategorized';
if (!this.byCategory.has(cat)) this.byCategory.set(cat, []);
this.byCategory.get(cat).push(roleId);
// Index keywords from name and description
const keywords = [...new Set(
(name + ' ' + description + ' ' + roleId)
.toLowerCase()
.split(/[\s,,、()\/\\\-_]+/)
.filter(k => k.length > 1)
)];
for (const kw of keywords) {
if (!this.byKeyword.has(kw)) this.byKeyword.set(kw, new Set());
this.byKeyword.get(kw).add(roleId);
}
} catch (e) {
console.error(`[RoleTemplates] Error parsing ${filePath}: ${e.message}`);
}
}
getTemplate(roleId) {
const role = this.roles.get(roleId);
if (!role) return null;
return {
id: role.id,
name: role.name,
description: role.description,
emoji: role.emoji,
color: role.color,
category: role.category,
prompt: role.fullPrompt
};
}
searchRoles(query) {
const q = query.toLowerCase();
const results = [];
for (const role of this.roles.values()) {
if (role.name.toLowerCase().includes(q) ||
role.description.toLowerCase().includes(q) ||
role.id.toLowerCase().includes(q) ||
role.category.toLowerCase().includes(q)) {
results.push({
id: role.id,
name: role.name,
emoji: role.emoji,
category: role.category,
description: role.description
});
}
}
return results;
}
searchByKeywords(keywords) {
const matched = new Set();
for (const kw of keywords.map(k => k.toLowerCase()).filter(k => k.length > 1)) {
const ids = this.byKeyword.get(kw);
if (ids) ids.forEach(id => matched.add(id));
}
return [...matched].map(id => ({
id,
name: this.roles.get(id).name,
emoji: this.roles.get(id).emoji,
category: this.roles.get(id).category,
description: this.roles.get(id).description
}));
}
getCategories() {
const result = [];
for (const [cat, roleIds] of this.byCategory) {
result.push({
category: cat,
count: roleIds.length,
roles: roleIds.map(id => ({
id,
name: this.roles.get(id).name,
emoji: this.roles.get(id).emoji
}))
});
}
return result.sort((a, b) => b.count - a.count);
}
getCategoryRoles(category) {
const ids = this.byCategory.get(category);
if (!ids) return [];
return ids.map(id => this.getTemplate(id));
}
getRoleCount() {
return this.roles.size;
}
}
module.exports = RoleTemplates;