Commit a128a2ff625ca4ee20000cdc7af63f01f8df2829
1 parent
cea3e9b4
refactor: Update company creation to act as shell and rename MasterBot to System Agents
- Updated `POST /api/company/create` to create an empty shell without bootstrapping CXO/HR automatically. - Updated `master/agent.md` instructions so Master Agent handles all Template library hirings. - Renamed 'MasterBot' navigation link to 'System Agents'. - Updated AgentChat sidebar to only show System Agents when accessed via the System Agents link.
Showing
4 changed files
with
29 additions
and
90 deletions
data/system/agents/master/agent.md
| ... | ... | @@ -76,42 +76,33 @@ node bin/lemon.js task dispatch --from master --to agent-creator --task "创建ä |
| 76 | 76 | |
| 77 | 77 | ## æ£ç¡®çš„æ“ä½œæµæ–¹å¼ï¼ˆèŒƒä¾‹ï¼‰ |
| 78 | 78 | |
| 79 | -### 🚀 创建公å¸ï¼ˆBrain to Cerebellum 从大脑到å°è„‘的进阶过程ï¼ï¼‰ | |
| 80 | -我们的框架原则是:**系统ä¸ä¸ç¡¬ç¼–ç **自动部署 CEOã€CTO ç‰éª¨å¹²ï¼Œä¸€åˆ‡éƒ½åº”当通过多级 Agent çš„æ€è€ƒä¸Žå§”派链æ¡å®Œæˆï¼è¿™å°±å¦‚åŒä»Žâ€œå¤§è„‘â€åˆ°â€œå°è„‘â€çš„肌肉记忆建立。 | |
| 79 | +### 🚀 创建公å¸ä¸Žæ‹›è˜å‘˜å·¥ï¼ˆä»Žå»ºå£³åˆ°ç»„建团队) | |
| 80 | +我们的框架原则是:**å…¬å¸åˆ›å»ºæ—¶åªæ˜¯ä¸€ä¸ªâ€œç©ºå£³â€**。系统ä¸ä¸ç¡¬ç¼–ç 自动部署 CEOã€CTO ç‰éª¨å¹²ã€‚ | |
| 81 | +为了é¿å…由下级 Agent(如 CEO/HR)去执行招è˜é€ æˆçš„å·¨å¤§èµ„æºæµªè´¹ï¼Œ**所有从 Template åº“ä¸æŒ‘选并雇佣 Agent 到公å¸å›¢é˜Ÿçš„工作,必须由 Master Agent æ ¹æ®è€æ¿ï¼ˆç”¨æˆ·ï¼‰çš„æŒ‡ä»¤äº²åŠ›äº²ä¸ºå®Œæˆã€‚** | |
| 81 | 82 | |
| 82 | -å½“ç”¨æˆ·è¦æ±‚åˆ›å»ºä¸€å®¶æ–°å…¬å¸æ—¶ï¼Œä½ (Master 作为“第一大脑â€ï¼‰å¿…须自主完æˆä»¥ä¸‹åˆå§‹åŒ–: | |
| 83 | -1. **构建公å¸éª¨æž¶**:调用 `company create` 创建åªåŒ…嫿¡†æž¶ï¼ˆå’Œåº•层元 Agent)的空壳。 | |
| 84 | -2. **ä¸»åŠ¨æ‹›è˜æ ¸å¿ƒç»Ÿå¸…**:公å¸å£³åé‡Œç›®å‰æ²¡æœ‰ä¸šåŠ¡å‘˜å·¥ã€‚ä½ å¿…é¡»é€šè¿‡ `company hire` 从模æ¿åº“䏿‹›å‹Ÿç¬¬ä¸€å业务骨干:**CEO**。 | |
| 85 | -3. **下达战略并å‘下委派**:通过 `task dispatch` 给新招募的 CEO å‘逿ˆ˜ç•¥å¯åŠ¨ä»¤ï¼Œå‘Šè¯‰ä»–å…¬å¸çš„ä¸šåŠ¡ç›®æ ‡ï¼Œå¹¶**è¦æ±‚ CEO 自行决定并去招募 HR 以扩建组织架构**。 | |
| 86 | -4. **ä¼ é€’ä¸Žè§‚å¯Ÿ**:CEO 收到命令åŽï¼ˆä»–的大脑开始æ€è€ƒï¼‰ï¼Œä¼šåŽ»æ‹›å‹Ÿ HR(HR éšåŽåŽ»æ‹›å‹Ÿå‘˜å·¥ï¼‰ï¼Œä½ åªéœ€è¦é™é™è§‚å¯Ÿè¿™å¼ ç½‘ç»œå‘ä¸‹å±‚çº§ä¼ é€’ã€‚ | |
| 83 | +å½“ç”¨æˆ·è¦æ±‚åˆ›å»ºä¸€å®¶æ–°å…¬å¸æ—¶ï¼Œä½ 必须: | |
| 84 | +1. **构建公å¸ç©ºå£³**:调用 `company create` 创建åªåŒ…嫿¡†æž¶çš„空壳。 | |
| 85 | +2. **ä¸»åŠ¨æ‹›è˜æ ¸å¿ƒå›¢é˜Ÿ**ï¼šæ ¹æ®ç”¨æˆ·çš„ä¸šåŠ¡éœ€æ±‚é¢„åˆ¤ï¼Œæˆ–è€…æ ¹æ®ç”¨æˆ·çš„æ˜Žç¡®æŒ‡ä»¤ï¼Œä½¿ç”¨ `company hire` 从模æ¿åº“䏿‹›å‹Ÿéœ€è¦çš„业务骨干(如 CEO, CTO, COO, HR,乃至具体的业务专家)。 | |
| 86 | +3. **下达战略说明**:通过 `task dispatch` 给新招募的 CEO å‘逿ˆ˜ç•¥å¯åŠ¨ä»¤ï¼Œå‘Šè¯‰ä»–å…¬å¸çš„ä¸šåŠ¡ç›®æ ‡ï¼Œå³å¯å¼€å§‹å·¥ä½œã€‚注æ„:**ä¸è¦**è¦æ±‚ CEO 去招募员工,明确告诉 CEO 团队é…置由 Master/è€æ¿ 负责。 | |
| 87 | 87 | |
| 88 | -**åˆ›å»ºæ–°å…¬å¸æ—¶ï¼Œä½ å¿…é¡»æŒ‰é¡ºåºæ‰§è¡Œä»¥ä¸‹ä¸‰æ¥åŠ¨ä½œï¼š** | |
| 88 | +**例如,当全æƒå§”æ‰˜ä½ åˆ›å»ºå¹¶é…ç½®ä¸€ä¸ªå…¬å¸æ—¶ï¼Œä½ å¯ä»¥æ‰§è¡Œï¼š** | |
| 89 | 89 | ```bash |
| 90 | 90 | # 1. 一键创建公å¸ç©ºå£³ |
| 91 | 91 | node bin/lemon.js company create --id <å…¬å¸ID> --name "<å…¬å¸åç§°>" --desc "<业务æè¿°ï¼Œè¶Šè¯¦ç»†è¶Šå¥½>" |
| 92 | 92 | |
| 93 | -# 2. ä¸ºè¯¥é¦–å®¶å…¬å¸æ‰‹åŠ¨æ‹›è˜ CEO(将其招入公å¸ï¼‰ | |
| 93 | +# 2. ä¸ºå…¬å¸æ‰‹åŠ¨æ‹›è˜å›¢é˜Ÿï¼ˆä»Ž Template 库雇佣) | |
| 94 | 94 | node bin/lemon.js company hire --id <å…¬å¸ID> --role ceo --type cxo --name "首叿‰§è¡Œå®˜" |
| 95 | +node bin/lemon.js company hire --id <å…¬å¸ID> --role cto --type cxo --name "é¦–å¸æŠ€æœ¯å®˜" | |
| 96 | +# (...按需雇佣其他 Agent) | |
| 95 | 97 | |
| 96 | -# 3. 委派 CEO å¼€å§‹å·¥ä½œï¼Œå¹¶æ˜Žç¡®è¦æ±‚其开始组建组织(一定è¦åŠ ä¸Šæ£ç¡®çš„å…¬å¸å‰ç¼€ï¼‰ | |
| 97 | -node bin/lemon.js task dispatch --from master --to <å…¬å¸ID>:ceo --task "ä½ å·²è¢«ä»»å‘½ä¸ºå…¬å¸ CEO,本公å¸ä¸»è¥ï¼š<业务æè¿°>ã€‚è¯·ä½ ç«‹åˆ»å¼€å§‹åˆ¶å®šå…¬å¸æˆ˜ç•¥ï¼Œæ¢³ç† SOP,并决定是å¦è¦æ‹›å‹Ÿ HR 给公å¸ç»„建团队。" --priority P0 | |
| 98 | +# 3. 委派 CEO 开始工作(一定è¦åŠ ä¸Šæ£ç¡®çš„å…¬å¸å‰ç¼€ï¼‰ | |
| 99 | +node bin/lemon.js task dispatch --from master --to <å…¬å¸ID>:ceo --task "ä½ å·²è¢«ä»»å‘½ä¸ºå…¬å¸ CEO,本公å¸ä¸»è¥ï¼š<业务æè¿°>ã€‚è¯·ç«‹åˆ»åˆ¶å®šå…¬å¸æˆ˜ç•¥å’Œ SOP。注æ„:人员招è˜ç”± Master 集ä¸ç®¡ç†ï¼Œä½ åªéœ€ä¸“注于业务æµç¨‹çš„æ¢³ç†ä¸Žå·¥ä½œæµåˆ†è§£ã€‚" --priority P0 | |
| 98 | 100 | ``` |
| 99 | 101 | |
| 100 | -**âš ï¸ å…³äºŽå…¬å¸ ID/å称的自主决ç–规则:** | |
| 101 | -- 如果用户说"创建一家AI新闻公å¸"但没给ID → **ä½ å¿…é¡»è‡ªä¸»å†³å®š**一个åˆç†çš„英文ID(如 `ainews`)和å称(如 `AI News Inc.`),然åŽ**立刻执行**,ç»ä¸è¦åå¤è¿½é—®ç”¨æˆ·ï¼ | |
| 102 | -- 如果用户给了明确的ID → 直接使用。 | |
| 103 | -- æè¿°å°½é‡è¯¦ç»†ï¼Œå› 为 CEO 的战略分æžè´¨é‡å–决于æè¿°çš„丰富程度。 | |
| 104 | - | |
| 105 | -**创建åŽçš„事件æµä¼ 导图谱:** | |
| 106 | -``` | |
| 107 | -用户å‘出建公å¸è¯·æ±‚ → Master (ä½ ) æ€è€ƒ "该招个CEO管ç†" | |
| 108 | - → Master 执行 company create 创建空间 → Master 执行 hire æ‹›è˜CEO → Master ç»™ CEO å‘任务 | |
| 109 | - → CEO æ€è€ƒ "我需è¦ç»„织" → CEO 委派 HR 去招募 | |
| 110 | - → HR 招入 CTO / 专家执行层 | |
| 111 | - → CTO æŽ¥ç®¡æµæ°´çº¿... | |
| 112 | -``` | |
| 113 | - | |
| 114 | -### æ£ç¡®å›žå¤æ¨¡å¼ | |
| 102 | +**âš ï¸ æ‹›è˜ä¸Žç»„队的原则:** | |
| 103 | +- 所有的 `hire` æ“作本质上是从 `Template` 库å¤åˆ¶æŒ‡å®šçš„æ¨¡æ¿åˆ°å…·ä½“å…¬å¸ä¸ï¼Œå¿…é¡»ç”±ä½ ï¼ˆMaster)æ¥åŒ…办。 | |
| 104 | +- å¦‚æžœç”¨æˆ·åªæ˜¯è¯´"帮我把 xxx 招到 yyy å…¬å¸"ï¼Œä½ ç›´æŽ¥è°ƒç”¨ä¸€æ¬¡ `company hire` å³å¯ã€‚ | |
| 105 | +- å¦‚æžœç”¨æˆ·è®©ä½ å…¨æƒç»„å»ºç‰¹å®šä¸šåŠ¡çº¿ï¼Œä½ åº”è¯¥**自主决定**需è¦å“ªäº›æ¨¡æ¿ï¼Œå¹¶ç›´æŽ¥æ‰¹é‡æ‰§è¡Œ `hire`,ä¸è¦åå¤è¿½é—®ã€‚ | |
| 115 | 106 | ``` |
| 116 | 107 | 用户: 让下级干完活 |
| 117 | 108 | ✅ æ£ç¡®å›žå¤: | ... | ... |
server/routes/company.js
| ... | ... | @@ -19,7 +19,7 @@ const scheduleService = new ScheduleService(); |
| 19 | 19 | // POST /api/company/create |
| 20 | 20 | router.post('/create', async (req, res) => { |
| 21 | 21 | try { |
| 22 | - const { id, name, description, skipBootstrap } = req.body; | |
| 22 | + const { id, name, description } = req.body; | |
| 23 | 23 | if (!id || !name) return res.status(400).json({ error: 'id 和 name 为必填项' }); |
| 24 | 24 | |
| 25 | 25 | // 校验 id 格式 (小写字母、数字、-) |
| ... | ... | @@ -29,64 +29,7 @@ router.post('/create', async (req, res) => { |
| 29 | 29 | |
| 30 | 30 | const company = companyService.create({ id, name, description }); |
| 31 | 31 | |
| 32 | - // ── Phase A: Company Bootstrap 自举 ── | |
| 33 | - // 读取 _company_bootstrap/manifest.json,自动部署核心骨干 | |
| 34 | - const bootstrapResults = []; | |
| 35 | - if (!skipBootstrap) { | |
| 36 | - const path = require('path'); | |
| 37 | - const fs = require('fs'); | |
| 38 | - const manifestPath = path.resolve(__dirname, '../../data/system/templates/_company_bootstrap/manifest.json'); | |
| 39 | - | |
| 40 | - if (fs.existsSync(manifestPath)) { | |
| 41 | - const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')); | |
| 42 | - const agents = manifest.bootstrap_agents || []; | |
| 43 | - | |
| 44 | - for (const agentDef of agents) { | |
| 45 | - try { | |
| 46 | - const hireResult = companyService.hire(id, agentDef.role, { | |
| 47 | - type: agentDef.type, | |
| 48 | - name: agentDef.name, | |
| 49 | - }); | |
| 50 | - bootstrapResults.push({ role: agentDef.role, status: hireResult.status }); | |
| 51 | - console.log(`[Bootstrap] ✅ ${id} 自动部署 ${agentDef.role} → ${hireResult.status}`); | |
| 52 | - } catch (err) { | |
| 53 | - bootstrapResults.push({ role: agentDef.role, status: 'error', error: err.message }); | |
| 54 | - console.error(`[Bootstrap] ❌ ${id} 部署 ${agentDef.role} 失败:`, err.message); | |
| 55 | - } | |
| 56 | - } | |
| 57 | - | |
| 58 | - // 自动启动公司 + 激活心跳 | |
| 59 | - companyService.update(id, { status: 'running', heartbeat: { enabled: true } }); | |
| 60 | - | |
| 61 | - // 自动向 CEO 下达启动令 (异步不阻塞) | |
| 62 | - if (manifest.auto_dispatch_to_ceo && description) { | |
| 63 | - const config = require('../config'); | |
| 64 | - const PORT = config.port || 3000; | |
| 65 | - const startupPrompt = `${manifest.ceo_startup_prompt || '请执行你的五步战略工作流'}\n\n公司名称: ${name}\n公司描述/业务需求: ${description}`; | |
| 66 | - | |
| 67 | - setTimeout(() => { | |
| 68 | - const http = require('http'); | |
| 69 | - const postData = JSON.stringify({ | |
| 70 | - from: 'master', to: `${id}:ceo`, | |
| 71 | - task: startupPrompt, priority: 'P0', autoExecute: true, | |
| 72 | - }); | |
| 73 | - const reqOpts = { | |
| 74 | - hostname: '127.0.0.1', port: PORT, path: '/api/agent/task/dispatch', | |
| 75 | - method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) }, | |
| 76 | - }; | |
| 77 | - const r = http.request(reqOpts, () => {}); | |
| 78 | - r.on('error', e => console.error('[Bootstrap] CEO dispatch 失败:', e.message)); | |
| 79 | - r.write(postData); | |
| 80 | - r.end(); | |
| 81 | - console.log(`[Bootstrap] 🚀 已向 ${id}:ceo 发送启动战略指令`); | |
| 82 | - }, 2000); | |
| 83 | - } | |
| 84 | - | |
| 85 | - console.log(`[Bootstrap] 🏢 公司 ${id} 已完成自举,部署了 ${bootstrapResults.length} 名核心骨干`); | |
| 86 | - } | |
| 87 | - } | |
| 88 | - | |
| 89 | - res.json({ success: true, company, bootstrap: bootstrapResults }); | |
| 32 | + res.json({ success: true, company, message: '公司已创建,当前为没有员工的空壳公司。请通知 MasterBot 从 Template 库中雇佣 Agent 到你的团队中。' }); | |
| 90 | 33 | } catch (err) { |
| 91 | 34 | res.status(400).json({ error: err.message }); |
| 92 | 35 | } | ... | ... |
web/src/components/AppNav.vue
| ... | ... | @@ -5,8 +5,8 @@ |
| 5 | 5 | <span class="nav-title">LemonBoss</span> |
| 6 | 6 | </div> |
| 7 | 7 | <div class="nav-links"> |
| 8 | - <router-link to="/agent/agent-creator" class="nav-link" :class="{ active: $route.path.startsWith('/agent') }"> | |
| 9 | - <span>🤖</span> MasterBot | |
| 8 | + <router-link to="/agent/master" class="nav-link" :class="{ active: $route.path.startsWith('/agent') }"> | |
| 9 | + <span>🤖</span> System Agents | |
| 10 | 10 | </router-link> |
| 11 | 11 | |
| 12 | 12 | <router-link to="/templates" class="nav-link" :class="{ active: $route.path.startsWith('/templates') }"> | ... | ... |
web/src/views/AgentChat.vue
| ... | ... | @@ -5,10 +5,10 @@ |
| 5 | 5 | |
| 6 | 6 | <!-- 第1列: Agent 列表 (始终可见) --> |
| 7 | 7 | <aside class="agent-sidebar"> |
| 8 | - <div class="col-header">🏢 Agents</div> | |
| 8 | + <div class="col-header">{{ $route.params.id ? '🏢 Agents' : '💻 System Agents' }}</div> | |
| 9 | 9 | <div class="agent-list"> |
| 10 | 10 | <template v-for="(agents, compId) in groupedAgents" :key="compId"> |
| 11 | - <div class="agent-group-title">{{ compId === 'system' ? '💻 系统 Agent' : `🏢 ${compId}` }}</div> | |
| 11 | + <div class="agent-group-title" v-if="$route.params.id">{{ compId === 'system' ? '💻 系统 Agent' : `🏢 ${compId}` }}</div> | |
| 12 | 12 | <div |
| 13 | 13 | v-for="a in agents" :key="a.id" |
| 14 | 14 | class="agent-card" :class="{ active: agentId === a.id }" |
| ... | ... | @@ -255,7 +255,12 @@ const groupedAgents = computed(() => { |
| 255 | 255 | agentList.value.forEach(a => { |
| 256 | 256 | const comp = a.companyId || 'system' |
| 257 | 257 | // If we are in a company context, filter out other companies |
| 258 | - if (route.params.id && comp !== route.params.id) return | |
| 258 | + if (route.params.id) { | |
| 259 | + if (comp !== route.params.id && comp !== 'system') return | |
| 260 | + } else { | |
| 261 | + // If we are in the System Agents context, ONLY show system agents | |
| 262 | + if (comp !== 'system') return | |
| 263 | + } | |
| 259 | 264 | |
| 260 | 265 | if (!groups[comp]) groups[comp] = [] |
| 261 | 266 | groups[comp].push(a) | ... | ... |