Commit a128a2ff625ca4ee20000cdc7af63f01f8df2829

Authored by yibo
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.
data/system/agents/master/agent.md
@@ -76,42 +76,33 @@ node bin/lemon.js task dispatch --from master --to agent-creator --task "创建ä @@ -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 ```bash 89 ```bash
90 # 1. 一键创建公å¸ç©ºå£³ 90 # 1. 一键创建公å¸ç©ºå£³
91 node bin/lemon.js company create --id <å…¬å¸ID> --name "<å…¬å¸åç§°>" --desc "<业务æè¿°ï¼Œè¶Šè¯¦ç»†è¶Šå¥½>" 91 node bin/lemon.js company create --id <å…¬å¸ID> --name "<å…¬å¸åç§°>" --desc "<业务æè¿°ï¼Œè¶Šè¯¦ç»†è¶Šå¥½>"
92 92
93 -# 2. ä¸ºè¯¥é¦–å®¶å…¬å¸æ‰‹åŠ¨æ‹›è˜ CEO(将其招入公å¸ï¼‰ 93 +# 2. ä¸ºå…¬å¸æ‰‹åŠ¨æ‹›è˜å›¢é˜Ÿï¼ˆä»Ž Template 库雇佣)
94 node bin/lemon.js company hire --id <å…¬å¸ID> --role ceo --type cxo --name "首席执行官" 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,7 +19,7 @@ const scheduleService = new ScheduleService();
19 // POST /api/company/create 19 // POST /api/company/create
20 router.post('/create', async (req, res) => { 20 router.post('/create', async (req, res) => {
21 try { 21 try {
22 - const { id, name, description, skipBootstrap } = req.body; 22 + const { id, name, description } = req.body;
23 if (!id || !name) return res.status(400).json({ error: 'id 和 name 为必填项' }); 23 if (!id || !name) return res.status(400).json({ error: 'id 和 name 为必填项' });
24 24
25 // 校验 id 格式 (小写字母、数字、-) 25 // 校验 id 格式 (小写字母、数字、-)
@@ -29,64 +29,7 @@ router.post(&#39;/create&#39;, async (req, res) =&gt; { @@ -29,64 +29,7 @@ router.post(&#39;/create&#39;, async (req, res) =&gt; {
29 29
30 const company = companyService.create({ id, name, description }); 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 } catch (err) { 33 } catch (err) {
91 res.status(400).json({ error: err.message }); 34 res.status(400).json({ error: err.message });
92 } 35 }
web/src/components/AppNav.vue
@@ -5,8 +5,8 @@ @@ -5,8 +5,8 @@
5 <span class="nav-title">LemonBoss</span> 5 <span class="nav-title">LemonBoss</span>
6 </div> 6 </div>
7 <div class="nav-links"> 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 </router-link> 10 </router-link>
11 11
12 <router-link to="/templates" class="nav-link" :class="{ active: $route.path.startsWith('/templates') }"> 12 <router-link to="/templates" class="nav-link" :class="{ active: $route.path.startsWith('/templates') }">
web/src/views/AgentChat.vue
@@ -5,10 +5,10 @@ @@ -5,10 +5,10 @@
5 5
6 <!-- 第1列: Agent 列表 (始终可见) --> 6 <!-- 第1列: Agent 列表 (始终可见) -->
7 <aside class="agent-sidebar"> 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 <div class="agent-list"> 9 <div class="agent-list">
10 <template v-for="(agents, compId) in groupedAgents" :key="compId"> 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 <div 12 <div
13 v-for="a in agents" :key="a.id" 13 v-for="a in agents" :key="a.id"
14 class="agent-card" :class="{ active: agentId === a.id }" 14 class="agent-card" :class="{ active: agentId === a.id }"
@@ -255,7 +255,12 @@ const groupedAgents = computed(() =&gt; { @@ -255,7 +255,12 @@ const groupedAgents = computed(() =&gt; {
255 agentList.value.forEach(a => { 255 agentList.value.forEach(a => {
256 const comp = a.companyId || 'system' 256 const comp = a.companyId || 'system'
257 // If we are in a company context, filter out other companies 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 if (!groups[comp]) groups[comp] = [] 265 if (!groups[comp]) groups[comp] = []
261 groups[comp].push(a) 266 groups[comp].push(a)