/** * ═══════════════════════════════════════════════════════════════ * AgentScaffold — Agent 目录脚手架 * ═══════════════════════════════════════════════════════════════ * * 创建 Agent = 生成一个标准目录结构 + 写入 Bootstrap Files * * 用法: * const scaffold = new AgentScaffold('data/agents'); * const agentDir = await scaffold.create({ * id: 'cxo-ceo-001', * type: 'cxo', * name: 'Lemon CEO', * parentId: 'master-001', * }); */ import { mkdir, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; /** * Agent 目录内的标准子目录 */ const STANDARD_SUBDIRS = [ '.claude/skills', '.claude/skills/main_skill', 'memory', 'memory/short-term', 'memory/long-term', 'memory/sessions', 'memory/daily', 'knowledge', 'workspace', 'workspace/code', 'workspace/data', 'workspace/assets', 'logs', ]; export class AgentScaffold { /** * @param {string} agentsBaseDir - Agent 实例的根目录 (如 data/agents) */ constructor(agentsBaseDir) { this.baseDir = agentsBaseDir; } /** * 创建一个完整的 Agent 目录 * * @param {Object} options * @param {string} options.id - Agent 唯一标识 (如 'cxo-ceo-001') * @param {string} options.type - Agent 类型 ('master' | 'cxo' | 'role' | 'skill') * @param {string} options.name - 显示名称 * @param {string} [options.parentId] - 上级 Agent ID * @param {string} [options.goalId] - 绑定的 Goal ID * @param {Object} [options.bootstrap] - 自定义 Bootstrap Files 内容 * * @returns {Promise} 创建的 Agent 目录路径 */ async create(options) { const { id, type, name, parentId, goalId, bootstrap = {} } = options; const agentDir = join(this.baseDir, id); // 1. 创建目录结构 await this._createDirectories(agentDir); // 2. 生成并写入 Bootstrap Files await this._writeBootstrapFiles(agentDir, { id, type, name, parentId, ...bootstrap }); // 3. 写入 config.json await this._writeConfig(agentDir, { id, type, name, parentId, goalId }); // 4. 写入 skills.md 空索引 await this._writeSkillsIndex(agentDir); // 5. 写入 memory.md 空索引 await this._writeMemoryIndex(agentDir); return agentDir; } // ───────────────────────────────────────── // 目录创建 // ───────────────────────────────────────── async _createDirectories(agentDir) { // 创建 agent 根目录 await mkdir(agentDir, { recursive: true }); // 创建所有标准子目录 for (const subdir of STANDARD_SUBDIRS) { await mkdir(join(agentDir, subdir), { recursive: true }); } } // ───────────────────────────────────────── // Bootstrap Files 生成 // ───────────────────────────────────────── async _writeBootstrapFiles(agentDir, opts) { const { id, type, name, parentId } = opts; // agent.md — 如果上层提供了自定义内容则使用, 否则生成默认模板 const agentMd = opts.agentMd || this._defaultAgentMd(id, type, name); await writeFile(join(agentDir, 'agent.md'), agentMd, 'utf-8'); // soul.md const soulMd = opts.soulMd || this._defaultSoulMd(type, name); await writeFile(join(agentDir, 'soul.md'), soulMd, 'utf-8'); // identity.md const identityMd = opts.identityMd || this._defaultIdentityMd(type, name); await writeFile(join(agentDir, 'identity.md'), identityMd, 'utf-8'); // user.md const userMd = opts.userMd || this._defaultUserMd(parentId); await writeFile(join(agentDir, 'user.md'), userMd, 'utf-8'); // tools.md const toolsMd = opts.toolsMd || this._defaultToolsMd(); await writeFile(join(agentDir, 'tools.md'), toolsMd, 'utf-8'); // heartbeat.md const heartbeatMd = opts.heartbeatMd || this._defaultHeartbeatMd(type); await writeFile(join(agentDir, 'heartbeat.md'), heartbeatMd, 'utf-8'); } // ───────────────────────────────────────── // 默认模板 // ───────────────────────────────────────── _defaultAgentMd(id, type, name) { const toolsByType = { master: [ '- cxo.create: 创建 CXO 战略层 Agent', '- cxo.redefine: 调整 CXO 的职责定义', '- cxo.destroy: 销毁 CXO Agent', '- org.status: 查看全局组织状态', '- goal.set: 设定公司 Goal', ], cxo: [ '- role.create: 创建职能部门 Role Agent', '- role.redefine: 调整部门职责定义', '- role.destroy: 裁撤部门', '- pipeline.set: 设计工作流', '- pipeline.adjust: 调整工作流', ], role: [ '- skill.create: 创建 Skill Agent', '- skill.redefine: 调整 Skill 定义', '- skill.destroy: 销毁 Skill Agent', '- skill.reuse: 复用其他 Role 的 Skill', ], skill: [ '# 无管理工具 — Skill 只负责执行, 不管理其他 Agent', ], }; const tools = (toolsByType[type] || toolsByType.skill).join('\n'); return `# ${name} ## 身份 你是 ${name}。 ## 职责 (待上层 Agent 定义) ## Never Rules - 不要越级管理不属于你的 Agent ## Always Rules - 按心跳频率主动检查工作进展 ## 可用工具 ${tools} `; } _defaultSoulMd(type, name) { return `# ${name} 的灵魂 ## 思维方式 (待上层 Agent 定义) ## 沟通风格 - 清晰、简洁 ## 价值观 - 高质量交付 - 持续改进 `; } _defaultIdentityMd(type, name) { const emojiByType = { master: '👑', cxo: '👔', role: '🏢', skill: '⚙️' }; return `# 身份信息 ## 基础信息 - 名称: ${name} - Emoji: ${emojiByType[type] || '🤖'} - 类型: ${type} ## 问候语 "你好,我是 ${name}。" `; } _defaultUserMd(parentId) { if (!parentId) { return `# 上层上下文 ## 我的上级 - 直接向用户汇报 (无上级 Agent) ## 用户偏好 (待用户定义) `; } return `# 上层上下文 ## 我的上级 - ${parentId} ## 上级偏好 (待上级 Agent 定义) `; } _defaultToolsMd() { return `# 工具使用备注 ## 安全规则 - 不要在日志中输出 API Key - 不要在 memory 中存储密码 - API Token 使用 env 变量, 不要硬编码 ## 文件操作 - 所有自主创建的文件仅限在 workspace/ 内操作 `; } _defaultHeartbeatMd(type) { const heartbeatByType = { master: `# 心跳任务 ## 每日 - [ ] 校准用户意图是否被正确理解 - [ ] 评估 CXO 层表现 - [ ] 向用户提交进度报告 `, cxo: `# 心跳任务 ## 每 5 分钟 - [ ] 扫描所有 Role Agent 运行状态 - [ ] 对比 Goal 进度, 识别 Gap - [ ] 扫描 Pipeline 执行情况 ## 每小时 - [ ] 汇总关键指标 ## 每日 - [ ] 生成工作总结写入 memory/daily/ `, role: `# 心跳任务 ## 每轮周期后 - [ ] 检查下属 Skill Agent 任务完成情况 - [ ] 评估产出质量 - [ ] 向 CXO 汇报进展 ## 每日 - [ ] 写入每日总结到 memory/daily/ `, skill: `# 心跳任务 ## 每次任务后 - [ ] 验证执行结果正确性 - [ ] 记录执行指标到 memory/ `, }; return heartbeatByType[type] || heartbeatByType.skill; } // ───────────────────────────────────────── // config.json 与索引文件 // ───────────────────────────────────────── async _writeConfig(agentDir, opts) { const config = { id: opts.id, type: opts.type, name: opts.name, parent_id: opts.parentId || null, goal_id: opts.goalId || null, gateway: { channels: [] }, api: { endpoints: [] }, mcp: { servers: [] }, sandbox: { maxMemoryMB: 512, maxDiskMB: 1024, maxProcesses: 5, }, }; await writeFile( join(agentDir, 'config.json'), JSON.stringify(config, null, 2), 'utf-8', ); } async _writeSkillsIndex(agentDir) { const content = `# 我的技能 ## 技能清单 (尚未添加技能) ## 说明 - 每个技能是 skills/ 目录下的一个子文件夹 - 每个技能文件夹内必须包含 SKILL.md 定义文件 `; await writeFile(join(agentDir, '.claude/skills', 'skills.md'), content, 'utf-8'); } async _writeMemoryIndex(agentDir) { const content = `# 我的记忆 ## 关键事实 (尚无记录) ## 已验证的模式 (尚无记录) ## 失败教训 (尚无记录) `; await writeFile(join(agentDir, 'memory', 'memory.md'), content, 'utf-8'); } } export default AgentScaffold;