@humanclaw/humanclaw 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -147,7 +147,7 @@ Web 看板包含三个核心视图:
147
147
  - **智能规划** — 输入需求,AI 自动拆任务、匹配碳基节点、生成布置话术、设 DDL(支持按团队规划,注入团队关系上下文)
148
148
  - **模拟交付** — 点击按钮,AI 以碳基节点视角角色扮演,根据身份、技能、关系生成模拟交付物
149
149
  - **聚合审查** — 全部交付后,AI 审查每个交付物质量(支持 GitHub PR/Commit/Issue URL),生成评分报告
150
- - **绩效评价** — 支持三种评分体系(阿里 3.75 / SABCD / EM+MM-),AI 生成按人按任务的绩效评分和评语
150
+ - **绩效评价** — 支持三种评分体系(阿里 3.75 / SABCD / EM),AI 生成按人按任务的绩效评分和评语
151
151
  - **可配置 LLM** — 支持 3 种 API 格式(Anthropic Messages / OpenAI Chat Completions / OpenAI Responses),可自定义 Base URL 接入私有模型服务
152
152
 
153
153
  ### 可伸缩编辑器
@@ -158,9 +158,9 @@ Web 看板包含三个核心视图:
158
158
 
159
159
  Dashboard 内置三个开箱即用的 Demo 场景,一键加载碳基节点和团队:
160
160
 
161
- - **三国蜀汉** 🐉 — 你是刘备,底下有五虎上将和谋士团两个团队
162
- - **互联网大厂** 💻 — 你是技术总监,管理前端组、后端组、产品组、质量组
163
- - **美国政府** 🇺🇸 — 你是特朗普,指挥经济安全团队、国防外交团队、国内事务团队
161
+ - **三国蜀汉** 🐉 — 你是刘备,麾下关羽、张飞、赵云、诸葛亮等七员文臣武将
162
+ - **互联网大厂** 💻 — 你是技术总监,管理前端、后端、算法、产品、设计、测试、运维
163
+ - **美国政府** 🇺🇸 — 你是特朗普,指挥 Musk、Rubio、Bessent 等核心内阁
164
164
 
165
165
  ## 核心工作流
166
166
 
package/README_EN.md CHANGED
@@ -147,7 +147,7 @@ The web dashboard includes three core views:
147
147
  - **Smart Planning** — Input requirements, AI auto-breaks tasks, matches nodes, generates briefings, sets deadlines (supports team-based planning with team relationship context injection)
148
148
  - **Simulate Delivery** — Click a button, AI role-plays as the worker node based on identity, skills, and relationships to generate mock deliverables
149
149
  - **Aggregated Review** — After all deliveries, AI reviews each deliverable (supports GitHub PR/Commit/Issue URLs), generates quality report
150
- - **Performance Evaluation** — Three rating systems (Ali 3.75 / SABCD / EM+MM-), AI generates per-person per-task performance ratings and comments
150
+ - **Performance Evaluation** — Three rating systems (Ali 3.75 / SABCD / EM), AI generates per-person per-task performance ratings and comments
151
151
  - **Configurable LLM** — Supports 3 API formats (Anthropic Messages / OpenAI Chat Completions / OpenAI Responses), custom Base URL for private model services
152
152
 
153
153
  ### Resizable Editors
@@ -158,9 +158,9 @@ All text editing areas (task delivery, review results, planning briefings) suppo
158
158
 
159
159
  The dashboard includes three built-in demo scenarios, one-click to load carbon-based nodes and teams:
160
160
 
161
- - **Three Kingdoms (Shu Han)** 🐉 — You are Liu Bei, with the Five Tiger Generals and Strategist Council teams
162
- - **Tech Company** 💻 — You are the Tech Director, managing Frontend, Backend, Product, and QA teams
163
- - **US Government** 🇺🇸 — You are Trump, directing Economic Security, Defense & Diplomacy, and Domestic Affairs teams
161
+ - **Three Kingdoms (Shu Han)** 🐉 — You are Liu Bei, commanding Guan Yu, Zhang Fei, Zhao Yun, Zhuge Liang and more
162
+ - **Tech Company** 💻 — You are the Tech Director, managing frontend, backend, algorithm, product, design, QA, and DevOps
163
+ - **US Government** 🇺🇸 — You are Trump, directing Musk, Rubio, Bessent and the core cabinet
164
164
 
165
165
  ## Core Workflow
166
166
 
package/dist/index.js CHANGED
@@ -1071,7 +1071,7 @@ import { Router as Router4 } from "express";
1071
1071
  var RATING_SYSTEMS = {
1072
1072
  ali: ["3.25", "3.5", "3.5+", "3.75", "4.0"],
1073
1073
  letter: ["S", "A", "B", "C", "D"],
1074
- em: ["EM+", "EM", "MM+", "MM", "MM-"]
1074
+ em: ["E", "M+", "M", "M-", "L"]
1075
1075
  };
1076
1076
  function validateRating(system, rating) {
1077
1077
  const values = RATING_SYSTEMS[system];
@@ -1148,7 +1148,7 @@ function buildReviewSystemPrompt(ratingSystem) {
1148
1148
  const systemLabels = {
1149
1149
  ali: "\u963F\u91CC\u7EE9\u6548\u4F53\u7CFB",
1150
1150
  letter: "SABCD \u7B49\u7EA7",
1151
- em: "EM/MM \u7EE9\u6548\u4F53\u7CFB"
1151
+ em: "EM \u7EE9\u6548\u4F53\u7CFB"
1152
1152
  };
1153
1153
  base += `
1154
1154
 
@@ -1347,6 +1347,18 @@ router5.put("/", (req, res) => {
1347
1347
  }
1348
1348
  res.json({ ok: true });
1349
1349
  });
1350
+ router5.post("/reset", (_req, res) => {
1351
+ const db2 = getDb();
1352
+ db2.exec(`
1353
+ DELETE FROM evaluations;
1354
+ DELETE FROM team_members;
1355
+ DELETE FROM tasks;
1356
+ DELETE FROM jobs;
1357
+ DELETE FROM teams;
1358
+ DELETE FROM agents;
1359
+ `);
1360
+ res.json({ ok: true });
1361
+ });
1350
1362
  var config_default = router5;
1351
1363
 
1352
1364
  // src/routes/teams.ts
@@ -1443,7 +1455,7 @@ function buildEvalPrompt(originalPrompt, ratingSystem, tasks) {
1443
1455
  const systemLabels = {
1444
1456
  ali: "\u963F\u91CC\u7EE9\u6548\u4F53\u7CFB\uFF083.25=\u4E0D\u5408\u683C, 3.5=\u57FA\u672C\u8FBE\u6807, 3.5+=\u8FBE\u6807, 3.75=\u4F18\u79C0, 4.0=\u5353\u8D8A\uFF09",
1445
1457
  letter: "SABCD \u7B49\u7EA7\uFF08S=\u5353\u8D8A, A=\u4F18\u79C0, B=\u8FBE\u6807, C=\u5F85\u6539\u8FDB, D=\u4E0D\u5408\u683C\uFF09",
1446
- em: "EM/MM \u4F53\u7CFB\uFF08EM+=\u8FDC\u8D85\u9884\u671F, EM=\u8D85\u51FA\u9884\u671F, MM+=\u8FBE\u6807, MM=\u57FA\u672C\u8FBE\u6807, MM-=\u4E0D\u8FBE\u6807\uFF09"
1458
+ em: "EM \u4F53\u7CFB\uFF08E=\u8FDC\u8D85\u9884\u671F, M+=\u8D85\u51FA\u9884\u671F, M=\u8FBE\u6807, M-=\u57FA\u672C\u8FBE\u6807, L=\u4E0D\u8FBE\u6807\uFF09"
1447
1459
  };
1448
1460
  let prompt = `\u539F\u59CB\u9700\u6C42: ${originalPrompt}
1449
1461
 
@@ -1806,6 +1818,9 @@ main{padding:24px 32px;max-width:1200px}
1806
1818
  .md-fullscreen-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:199}
1807
1819
  /* Team badge */
1808
1820
  .team-badge{display:inline-block;background:rgba(168,85,247,.12);border:1px solid rgba(168,85,247,.25);border-radius:4px;padding:1px 8px;font-size:10px;color:var(--purple);margin-right:4px;margin-bottom:2px}
1821
+ .team-group{margin-bottom:28px}
1822
+ .team-group-header{display:flex;align-items:center;gap:6px;padding:10px 0 8px;border-bottom:1px solid var(--border);margin-bottom:12px;cursor:pointer}
1823
+ .team-group-header:hover .agent-name{color:var(--accent)}
1809
1824
  /* Evaluation */
1810
1825
  .eval-badge{display:inline-block;padding:3px 10px;border-radius:12px;font-weight:700;font-size:13px;font-family:var(--font-mono)}
1811
1826
  .eval-badge.top{background:rgba(34,197,94,.15);color:var(--green)}
@@ -1869,8 +1884,7 @@ const DEMOS={
1869
1884
  desc:'\u6843\u56ED\u7ED3\u4E49\uFF0C\u4E09\u987E\u8305\u5E90\u3002\u4F5C\u4E3A\u8700\u6C49\u4E4B\u4E3B\uFF0C\u7EDF\u9886\u4E94\u864E\u4E0A\u5C06\u548C\u5367\u9F99\u51E4\u96CF\uFF0C\u9010\u9E7F\u4E2D\u539F\u3002',
1870
1885
  prompt:'\u5317\u4F10\u4E2D\u539F\uFF0C\u5175\u5206\u4E09\u8DEF\uFF0C\u9700\u8981\u653B\u57CE\u3001\u65AD\u7CAE\u548C\u5916\u4EA4\u4E09\u7BA1\u9F50\u4E0B',
1871
1886
  teams:[
1872
- {name:'\u4E94\u864E\u4E0A\u5C06',description:'\u8700\u6C49\u4E94\u5927\u731B\u5C06',members:['\u5173\u7FBD','\u5F20\u98DE','\u8D75\u4E91','\u9EC4\u5FE0','\u9A6C\u8D85'],relationships:{'\u5173\u7FBD':'\u4E49\u5F1F\u517C\u519B\u56E2\u7EDF\u5E05','\u5F20\u98DE':'\u4E49\u5F1F\u517C\u5148\u950B\u5927\u5C06','\u8D75\u4E91':'\u5FC3\u8179\u7231\u5C06','\u9EC4\u5FE0':'\u8001\u5F53\u76CA\u58EE\u7684\u731B\u5C06','\u9A6C\u8D85':'\u5F52\u964D\u7684\u897F\u51C9\u864E\u5C06'}},
1873
- {name:'\u8C0B\u58EB\u56E2',description:'\u8FD0\u7B79\u5E37\u5E44\u7684\u667A\u56CA\u56E2',members:['\u8BF8\u845B\u4EAE','\u5E9E\u7EDF'],relationships:{'\u8BF8\u845B\u4EAE':'\u9996\u5E2D\u519B\u5E08\uFF0C\u5982\u9C7C\u5F97\u6C34','\u5E9E\u7EDF':'\u526F\u519B\u5E08\uFF0C\u5947\u8C0B\u767E\u51FA'}}
1887
+ {name:'\u4E09\u56FD\u8700\u6C49',description:'\u5218\u5907\u9EBE\u4E0B\u5168\u4F53\u6587\u81E3\u6B66\u5C06',members:['\u5173\u7FBD','\u5F20\u98DE','\u8D75\u4E91','\u8BF8\u845B\u4EAE','\u5E9E\u7EDF','\u9EC4\u5FE0','\u9A6C\u8D85'],relationships:{'\u5173\u7FBD':'\u4E49\u5F1F\u517C\u519B\u56E2\u7EDF\u5E05','\u5F20\u98DE':'\u4E49\u5F1F\u517C\u5148\u950B\u5927\u5C06','\u8D75\u4E91':'\u5FC3\u8179\u7231\u5C06','\u8BF8\u845B\u4EAE':'\u9996\u5E2D\u519B\u5E08\uFF0C\u5982\u9C7C\u5F97\u6C34','\u5E9E\u7EDF':'\u526F\u519B\u5E08\uFF0C\u5947\u8C0B\u767E\u51FA','\u9EC4\u5FE0':'\u8001\u5F53\u76CA\u58EE\u7684\u731B\u5C06','\u9A6C\u8D85':'\u5F52\u964D\u7684\u897F\u51C9\u864E\u5C06'}}
1874
1888
  ],
1875
1889
  agents:[
1876
1890
  {name:'\u5173\u7FBD',capabilities:['\u6B66\u827A','\u7EDF\u5175','\u9547\u5B88\u8981\u5730','\u6C34\u519B\u6307\u6325'],relationship:'\u4E49\u5F1F\uFF0C\u6843\u56ED\u7ED3\u4E49\u4E8C\u5F1F\uFF0C\u6700\u4FE1\u4EFB\u7684\u5144\u5F1F\u548C\u5927\u5C06'},
@@ -1887,10 +1901,7 @@ const DEMOS={
1887
1901
  desc:'\u5E26\u9886\u4E00\u652F\u5168\u6808\u56E2\u961F\uFF0C\u4ECE\u524D\u7AEF\u5230\u8FD0\u7EF4\u4E00\u5E94\u4FF1\u5168\u3002\u5E94\u5BF9\u9AD8\u5E76\u53D1\u3001\u641E AI\u3001\u4E0A\u7EBF\u65B0\u7CFB\u7EDF\u3002',
1888
1902
  prompt:'\u4E0A\u7EBF\u4E00\u4E2A AI \u667A\u80FD\u5BA2\u670D\u7CFB\u7EDF\uFF0C\u5305\u62EC\u524D\u7AEF\u754C\u9762\u3001\u540E\u7AEF API\u3001\u63A8\u8350\u7B97\u6CD5\u3001\u538B\u529B\u6D4B\u8BD5\u548C\u7070\u5EA6\u53D1\u5E03\u65B9\u6848',
1889
1903
  teams:[
1890
- {name:'\u524D\u7AEF\u7EC4',description:'\u8D1F\u8D23\u6240\u6709\u524D\u7AEF\u9875\u9762\u5F00\u53D1',members:['\u524D\u7AEF\u8001\u674E','\u8BBE\u8BA1\u5E08\u5C0F\u6797'],relationships:{'\u524D\u7AEF\u8001\u674E':'\u524D\u7AEFTL\uFF0C\u6838\u5FC3\u9AA8\u5E72','\u8BBE\u8BA1\u5E08\u5C0F\u6797':'\u8D44\u6DF1\u8BBE\u8BA1\u5E08'}},
1891
- {name:'\u540E\u7AEF\u7EC4',description:'\u540E\u7AEF\u67B6\u6784\u4E0E\u670D\u52A1\u5F00\u53D1',members:['\u540E\u7AEF\u5927\u738B','\u7B97\u6CD5\u5C0F\u9648'],relationships:{'\u540E\u7AEF\u5927\u738B':'\u67B6\u6784\u5E08\uFF0C\u6280\u672F\u51B3\u7B56\u8005','\u7B97\u6CD5\u5C0F\u9648':'\u7B97\u6CD5\u5DE5\u7A0B\u5E08\uFF0C\u9700\u8981\u6307\u5BFC'}},
1892
- {name:'\u4EA7\u54C1\u7EC4',description:'\u4EA7\u54C1\u9700\u6C42\u4E0E\u9879\u76EE\u7BA1\u7406',members:['\u4EA7\u54C1\u7ECF\u7406 Amy'],relationships:{'\u4EA7\u54C1\u7ECF\u7406 Amy':'\u4EA7\u54C1\u8D1F\u8D23\u4EBA'}},
1893
- {name:'\u8D28\u91CF\u7EC4',description:'\u6D4B\u8BD5\u4E0E\u8FD0\u7EF4\u4FDD\u969C',members:['\u6D4B\u8BD5\u8D1F\u8D23\u4EBA\u8001\u8D75','\u8FD0\u7EF4 DevOps \u963F\u6770'],relationships:{'\u6D4B\u8BD5\u8D1F\u8D23\u4EBA\u8001\u8D75':'\u8D28\u91CF\u628A\u5173\u4EBA','\u8FD0\u7EF4 DevOps \u963F\u6770':'SRE\u8D1F\u8D23\u4EBA'}}
1904
+ {name:'\u4E92\u8054\u7F51\u5927\u5382',description:'\u6280\u672F\u603B\u76D1\u76F4\u7BA1\u7684\u5168\u6808\u56E2\u961F',members:['\u524D\u7AEF\u8001\u674E','\u540E\u7AEF\u5927\u738B','\u7B97\u6CD5\u5C0F\u9648','\u4EA7\u54C1\u7ECF\u7406 Amy','\u8BBE\u8BA1\u5E08\u5C0F\u6797','\u6D4B\u8BD5\u8D1F\u8D23\u4EBA\u8001\u8D75','\u8FD0\u7EF4 DevOps \u963F\u6770'],relationships:{'\u524D\u7AEF\u8001\u674E':'\u524D\u7AEFTL\uFF0C\u6838\u5FC3\u9AA8\u5E72','\u540E\u7AEF\u5927\u738B':'\u67B6\u6784\u5E08\uFF0C\u6280\u672F\u51B3\u7B56\u8005','\u7B97\u6CD5\u5C0F\u9648':'\u7B97\u6CD5\u5DE5\u7A0B\u5E08\uFF0C\u9700\u8981\u6307\u5BFC','\u4EA7\u54C1\u7ECF\u7406 Amy':'\u4EA7\u54C1\u8D1F\u8D23\u4EBA','\u8BBE\u8BA1\u5E08\u5C0F\u6797':'\u8D44\u6DF1\u8BBE\u8BA1\u5E08','\u6D4B\u8BD5\u8D1F\u8D23\u4EBA\u8001\u8D75':'\u8D28\u91CF\u628A\u5173\u4EBA','\u8FD0\u7EF4 DevOps \u963F\u6770':'SRE\u8D1F\u8D23\u4EBA'}}
1894
1905
  ],
1895
1906
  agents:[
1896
1907
  {name:'\u524D\u7AEF\u8001\u674E',capabilities:['React','TypeScript','Next.js','\u79FB\u52A8\u7AEF\u9002\u914D','\u6027\u80FD\u4F18\u5316'],relationship:'P7 \u524D\u7AEF TL\uFF0C\u8DDF\u4E86\u4F60\u4E09\u5E74\uFF0C\u6280\u672F\u8FC7\u786C\u4F46\u6700\u8FD1\u6709\u70B9\u5026\u6020'},
@@ -1907,9 +1918,7 @@ const DEMOS={
1907
1918
  desc:'Make the executive branch great again! \u7BA1\u7406\u4F60\u7684\u6838\u5FC3\u5185\u9601\u6210\u5458\uFF0C\u63A8\u884C\u653F\u7B56\u8BAE\u7A0B\u3002',
1908
1919
  prompt:'\u5236\u5B9A\u4E00\u4E2A\u8BA9\u7F8E\u56FD\u5236\u9020\u4E1A\u56DE\u6D41\u7684\u7EFC\u5408\u8BA1\u5212\uFF0C\u9700\u8981\u5173\u7A0E\u653F\u7B56\u3001\u51CF\u7A0E\u65B9\u6848\u3001\u80FD\u6E90\u4FDD\u969C\u3001\u8FB9\u5883\u5B89\u5168\u914D\u5408\u548C\u653F\u5E9C\u6548\u7387\u4F18\u5316',
1909
1920
  teams:[
1910
- {name:'\u7ECF\u6D4E\u5B89\u5168\u56E2\u961F',description:'\u7ECF\u6D4E\u653F\u7B56\u4E0E\u8D22\u653F\u7BA1\u7406',members:['Scott Bessent','Elon Musk'],relationships:{'Scott Bessent':'\u8D22\u653F\u90E8\u957F\uFF0C\u9996\u5E2D\u7ECF\u6D4E\u987E\u95EE','Elon Musk':'DOGE \u8D1F\u8D23\u4EBA\uFF0C\u6548\u7387\u6539\u9769\u63A8\u52A8\u8005'}},
1911
- {name:'\u56FD\u9632\u5916\u4EA4\u56E2\u961F',description:'\u56FD\u9632\u4E0E\u5916\u4EA4\u4E8B\u52A1',members:['Marco Rubio','Pete Hegseth','Tulsi Gabbard'],relationships:{'Marco Rubio':'\u56FD\u52A1\u537F\uFF0C\u5916\u4EA4\u603B\u7BA1','Pete Hegseth':'\u56FD\u9632\u90E8\u957F\uFF0C\u519B\u4E8B\u4E8B\u52A1','Tulsi Gabbard':'\u60C5\u62A5\u603B\u76D1\uFF0C\u5B89\u5168\u8BC4\u4F30'}},
1912
- {name:'\u56FD\u5185\u4E8B\u52A1\u56E2\u961F',description:'\u56FD\u5185\u5B89\u5168\u4E0E\u516C\u5171\u670D\u52A1',members:['Kristi Noem','Robert F. Kennedy Jr.'],relationships:{'Kristi Noem':'\u56FD\u571F\u5B89\u5168\u90E8\u957F\uFF0C\u8FB9\u5883\u5F3A\u786C\u6D3E','Robert F. Kennedy Jr.':'\u536B\u751F\u90E8\u957F\uFF0C\u533B\u7597\u6539\u9769'}}
1921
+ {name:'\u7F8E\u56FD\u653F\u5E9C',description:'\u603B\u7EDF\u76F4\u5C5E\u6838\u5FC3\u5185\u9601',members:['Elon Musk','Marco Rubio','Pete Hegseth','Scott Bessent','Kristi Noem','Tulsi Gabbard','Robert F. Kennedy Jr.'],relationships:{'Elon Musk':'DOGE \u8D1F\u8D23\u4EBA\uFF0C\u6548\u7387\u6539\u9769\u63A8\u52A8\u8005','Marco Rubio':'\u56FD\u52A1\u537F\uFF0C\u5916\u4EA4\u603B\u7BA1','Pete Hegseth':'\u56FD\u9632\u90E8\u957F\uFF0C\u519B\u4E8B\u4E8B\u52A1','Scott Bessent':'\u8D22\u653F\u90E8\u957F\uFF0C\u9996\u5E2D\u7ECF\u6D4E\u987E\u95EE','Kristi Noem':'\u56FD\u571F\u5B89\u5168\u90E8\u957F\uFF0C\u8FB9\u5883\u5F3A\u786C\u6D3E','Tulsi Gabbard':'\u60C5\u62A5\u603B\u76D1\uFF0C\u5B89\u5168\u8BC4\u4F30','Robert F. Kennedy Jr.':'\u536B\u751F\u90E8\u957F\uFF0C\u533B\u7597\u6539\u9769'}}
1913
1922
  ],
1914
1923
  agents:[
1915
1924
  {name:'Elon Musk',capabilities:['\u653F\u5E9C\u6548\u7387','\u6210\u672C\u524A\u51CF','\u79D1\u6280\u521B\u65B0','SpaceX','Tesla','\u793E\u4EA4\u5A92\u4F53'],relationship:'DOGE \u8D1F\u8D23\u4EBA\uFF0C\u4E16\u754C\u9996\u5BCC\uFF0CTwitter/X \u8001\u677F\uFF0C\u6700\u5177\u5F71\u54CD\u529B\u7684\u76DF\u53CB'},
@@ -2037,41 +2046,64 @@ async function loadFleet(el){
2037
2046
  h+=renderDemoCards();
2038
2047
  el.innerHTML=h;return;
2039
2048
  }
2040
- h+='<div class="grid">';
2041
- for(const a of d.agents){
2042
- h+='<div class="card"><div class="agent-header"><span class="dot '+a.status+'"></span><span class="agent-name">'+esc(a.name)+'</span></div>';
2043
- h+='<div class="agent-id">'+a.agent_id+'</div>';
2044
- if(a.relationship)h+='<div style="font-size:11px;color:var(--purple);margin-bottom:4px">&#128101; '+esc(a.relationship)+'</div>';
2045
- // Team badges
2046
- const agentTeams=cachedTeams.filter(tm=>tm.members&&tm.members.some(m=>m.agent_id===a.agent_id));
2047
- if(agentTeams.length){h+='<div style="margin-bottom:4px">';for(const tm of agentTeams)h+='<span class="team-badge">'+esc(tm.name)+'</span>';h+='</div>'}
2048
- h+='<div class="caps">';for(const c of a.capabilities)h+='<span class="cap">'+esc(c)+'</span>';h+='</div>';
2049
- h+='<div class="agent-meta"><span>\u4EFB\u52A1: '+a.active_task_count+'</span>';
2050
- if(a.avg_delivery_hours!==null)h+='<span>\u5E73\u5747\u4EA4\u4ED8: '+a.avg_delivery_hours+'h</span>';
2051
- h+='</div>';
2052
- h+='<div class="agent-actions">';
2053
- h+='<select onchange="changeStatus(\\''+a.agent_id+'\\',this.value)">';
2054
- for(const s of ['IDLE','BUSY','OFFLINE','OOM'])h+='<option'+(s===a.status?' selected':'')+'>'+s+'</option>';
2055
- h+='</select>';
2056
- h+='<button onclick="deleteAgent(\\''+a.agent_id+'\\')">\u5220\u9664</button>';
2057
- h+='</div></div>';
2049
+ // Build agent card HTML helper
2050
+ function agentCard(a){
2051
+ let c='<div class="card"><div class="agent-header"><span class="dot '+a.status+'"></span><span class="agent-name">'+esc(a.name)+'</span></div>';
2052
+ c+='<div class="agent-id">'+a.agent_id+'</div>';
2053
+ if(a.relationship)c+='<div style="font-size:11px;color:var(--purple);margin-bottom:4px">&#128101; '+esc(a.relationship)+'</div>';
2054
+ c+='<div class="caps">';for(const cap of a.capabilities)c+='<span class="cap">'+esc(cap)+'</span>';c+='</div>';
2055
+ c+='<div class="agent-meta"><span>\u4EFB\u52A1: '+a.active_task_count+'</span>';
2056
+ if(a.avg_delivery_hours!==null)c+='<span>\u5E73\u5747\u4EA4\u4ED8: '+a.avg_delivery_hours+'h</span>';
2057
+ c+='</div>';
2058
+ c+='<div class="agent-actions">';
2059
+ c+='<select onchange="changeStatus(\\''+a.agent_id+'\\',this.value)">';
2060
+ for(const s of ['IDLE','BUSY','OFFLINE','OOM'])c+='<option'+(s===a.status?' selected':'')+'>'+s+'</option>';
2061
+ c+='</select>';
2062
+ c+='<button onclick="deleteAgent(\\''+a.agent_id+'\\')">\u5220\u9664</button>';
2063
+ c+='</div></div>';
2064
+ return c;
2058
2065
  }
2059
- h+='</div>';
2060
- // Teams section
2061
- h+='<div style="margin-top:32px"><div class="section-hd"><h2>\u56E2\u961F\u7BA1\u7406</h2><button class="btn btn-primary btn-sm" onclick="showCreateTeam()">+ \u521B\u5EFA\u56E2\u961F</button></div>';
2066
+ // Group agents by team
2067
+ const assignedIds=new Set();
2062
2068
  if(cachedTeams.length){
2063
- h+='<div class="grid">';
2064
2069
  for(const tm of cachedTeams){
2065
- const memberCount=tm.members?tm.members.length:0;
2066
- h+='<div class="card" style="cursor:pointer" onclick="showTeamDetail(\\''+tm.team_id+'\\')">';
2067
- h+='<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px"><span style="font-size:20px">&#128101;</span><span class="agent-name">'+esc(tm.name)+'</span></div>';
2068
- if(tm.description)h+='<div style="font-size:12px;color:var(--text-dim);margin-bottom:8px">'+esc(tm.description)+'</div>';
2069
- h+='<div style="font-size:11px;color:var(--accent)">'+memberCount+' \u4E2A\u6210\u5458</div>';
2070
+ if(!tm.members||!tm.members.length)continue;
2071
+ const teamAgents=d.agents.filter(a=>tm.members.some(m=>m.agent_id===a.agent_id));
2072
+ if(!teamAgents.length)continue;
2073
+ for(const a of teamAgents)assignedIds.add(a.agent_id);
2074
+ h+='<div class="team-group">';
2075
+ h+='<div class="team-group-header" onclick="showTeamDetail(\\''+tm.team_id+'\\')">';
2076
+ h+='<span style="font-size:18px">&#128101;</span> <span class="agent-name">'+esc(tm.name)+'</span>';
2077
+ if(tm.description)h+=' <span style="font-size:12px;color:var(--text-dim);margin-left:8px">'+esc(tm.description)+'</span>';
2078
+ h+=' <span style="font-size:11px;color:var(--accent);margin-left:8px">'+teamAgents.length+' \u4EBA</span>';
2070
2079
  h+='</div>';
2080
+ h+='<div class="grid">';
2081
+ for(const a of teamAgents)h+=agentCard(a);
2082
+ h+='</div></div>';
2083
+ }
2084
+ }
2085
+ // Ungrouped agents
2086
+ const ungrouped=d.agents.filter(a=>!assignedIds.has(a.agent_id));
2087
+ if(ungrouped.length){
2088
+ if(assignedIds.size>0){
2089
+ h+='<div class="team-group">';
2090
+ h+='<div class="team-group-header"><span style="font-size:18px">&#128100;</span> <span class="agent-name">\u672A\u5206\u7EC4</span> <span style="font-size:11px;color:var(--accent);margin-left:8px">'+ungrouped.length+' \u4EBA</span></div>';
2091
+ h+='<div class="grid">';
2092
+ for(const a of ungrouped)h+=agentCard(a);
2093
+ h+='</div></div>';
2094
+ } else {
2095
+ h+='<div class="grid">';
2096
+ for(const a of ungrouped)h+=agentCard(a);
2097
+ h+='</div>';
2098
+ }
2099
+ }
2100
+ // Team management buttons
2101
+ h+='<div style="margin-top:24px;display:flex;gap:8px;align-items:center">';
2102
+ h+='<button class="btn btn-primary btn-sm" onclick="showCreateTeam()">+ \u521B\u5EFA\u56E2\u961F</button>';
2103
+ if(cachedTeams.length){
2104
+ for(const tm of cachedTeams){
2105
+ h+='<span class="team-badge" style="cursor:pointer" onclick="showTeamDetail(\\''+tm.team_id+'\\')">'+esc(tm.name)+'</span>';
2071
2106
  }
2072
- h+='</div>';
2073
- }else{
2074
- h+='<div style="font-size:12px;color:var(--text-dim);margin-top:8px">\u6682\u65E0\u56E2\u961F\u3002\u521B\u5EFA\u56E2\u961F\u540E\u53EF\u6309\u56E2\u961F\u5206\u914D\u4EFB\u52A1\u3002</div>';
2075
2107
  }
2076
2108
  h+='</div>';
2077
2109
  el.innerHTML=h;
@@ -2469,7 +2501,7 @@ window.showEvalDialog=function(jobId){
2469
2501
  +'<div class="fg"><label>\u8BC4\u5206\u4F53\u7CFB</label><select id="eval-system">'
2470
2502
  +'<option value="ali">\u963F\u91CC\u7EE9\u6548 (3.25 / 3.5 / 3.5+ / 3.75 / 4.0)</option>'
2471
2503
  +'<option value="letter">SABCD \u7B49\u7EA7 (S / A / B / C / D)</option>'
2472
- +'<option value="em">EM/MM \u4F53\u7CFB (EM+ / EM / MM+ / MM / MM-)</option>'
2504
+ +'<option value="em">EM \u4F53\u7CFB (E / M+ / M / M- / L)</option>'
2473
2505
  +'</select></div>'
2474
2506
  +'<div class="btn-group"><button class="btn btn-primary" onclick="generateEval(\\''+jobId+'\\')">\u751F\u6210\u8BC4\u4EF7</button><button class="btn btn-ghost" onclick="document.getElementById(\\'overlay\\').remove()">\u53D6\u6D88</button></div></div>';
2475
2507
  document.body.appendChild(ov);
@@ -2485,8 +2517,8 @@ window.generateEval=async function(jobId){
2485
2517
  if(!r.ok){toast(d.error||'\u8BC4\u4EF7\u751F\u6210\u5931\u8D25',false);ov.remove();return}
2486
2518
  let h='<h3>&#128202; \u7EE9\u6548\u8BC4\u4EF7\u7ED3\u679C</h3>';
2487
2519
  h+='<div style="font-size:11px;color:var(--text-dim);margin-bottom:16px;font-family:var(--font-mono)">\u751F\u6210\u65F6\u95F4: '+new Date(d.generated_at).toLocaleString()+'</div>';
2488
- const ratingTiers={ali:['4.0','3.75'],letter:['S','A'],em:['EM+','EM']};
2489
- const lowTiers={ali:['3.25'],letter:['D'],em:['MM-']};
2520
+ const ratingTiers={ali:['4.0','3.75'],letter:['S','A'],em:['E','M+']};
2521
+ const lowTiers={ali:['3.25'],letter:['D'],em:['L']};
2490
2522
  for(const ev of d.evaluations){
2491
2523
  const agent=cachedAgents.find(a=>a.agent_id===ev.agent_id);
2492
2524
  const isTop=(ratingTiers[ratingSystem]||[]).includes(ev.rating);
@@ -2642,7 +2674,8 @@ window.showSettings=async function(){
2642
2674
  +'<div class="fg"><label>API Key</label><input id="cfg-key" type="password" placeholder="'+(cfg.api_key_set?'\u5DF2\u914D\u7F6E\uFF0C\u7559\u7A7A\u5219\u4E0D\u4FEE\u6539':'\u8F93\u5165\u4F60\u7684 API Key...')+'"/><div class="hint">Anthropic: sk-ant-... | OpenAI: sk-...</div></div>'
2643
2675
  +'<div class="fg"><label>\u6A21\u578B <span style="color:var(--text-dim);font-weight:400">(\u53EF\u9009\uFF0C\u7559\u7A7A\u7528\u9ED8\u8BA4)</span></label><input id="cfg-model" value="'+esc(cfg.model||'')+'" placeholder="\u4F8B: claude-sonnet-4-20250514 / gpt-4o"/></div>'
2644
2676
  +'<div class="fg"><label>API Base URL <span style="color:var(--text-dim);font-weight:400">(\u53EF\u9009\uFF0C\u7559\u7A7A\u7528\u5B98\u65B9\u5730\u5740)</span></label><input id="cfg-baseurl" value="'+esc(cfg.base_url||'')+'" placeholder="\u4F8B: https://your-proxy.com"/><div class="hint">\u79C1\u6709\u90E8\u7F72: \u586B\u5199\u4F60\u7684\u6A21\u578B\u670D\u52A1\u5730\u5740\uFF0C\u5982 vLLM / Ollama / Azure \u7B49</div></div>'
2645
- +'<div class="btn-group"><button class="btn btn-primary" onclick="saveSettings()">\u4FDD\u5B58</button><button class="btn btn-ghost" onclick="document.getElementById(\\'overlay\\').remove()">\u53D6\u6D88</button></div>';
2677
+ +'<div class="btn-group"><button class="btn btn-primary" onclick="saveSettings()">\u4FDD\u5B58</button><button class="btn btn-ghost" onclick="document.getElementById(\\'overlay\\').remove()">\u53D6\u6D88</button></div>'
2678
+ +'<div style="margin-top:24px;padding-top:16px;border-top:1px solid var(--border)"><div style="font-size:12px;color:var(--text-dim);margin-bottom:8px">&#9888; \u5371\u9669\u64CD\u4F5C</div><button class="btn btn-sm" style="background:var(--red);color:#fff" onclick="resetAllData()">\u4E00\u952E\u6E05\u7A7A\u6240\u6709\u6570\u636E</button><div class="hint">\u6E05\u7A7A\u6240\u6709\u8282\u70B9\u3001\u56E2\u961F\u3001\u4EFB\u52A1\u548C\u8BC4\u4EF7\u6570\u636E\uFF0C\u53EF\u91CD\u65B0\u52A0\u8F7D Demo \u573A\u666F\u3002LLM \u914D\u7F6E\u4E0D\u53D7\u5F71\u54CD\u3002</div></div>';
2646
2679
  }catch{
2647
2680
  ov.querySelector('.form-card').innerHTML='<h3>LLM \u8BBE\u7F6E</h3><p style="color:var(--red)">\u52A0\u8F7D\u914D\u7F6E\u5931\u8D25</p>';
2648
2681
  }
@@ -2663,6 +2696,16 @@ window.saveSettings=async function(){
2663
2696
  document.getElementById('overlay').remove();
2664
2697
  }catch{toast('\u7F51\u7EDC\u9519\u8BEF',false)}
2665
2698
  };
2699
+ window.resetAllData=async function(){
2700
+ if(!confirm('\u786E\u5B9A\u6E05\u7A7A\u6240\u6709\u6570\u636E\uFF1F\u8282\u70B9\u3001\u56E2\u961F\u3001\u4EFB\u52A1\u3001\u8BC4\u4EF7\u5C06\u5168\u90E8\u5220\u9664\u3002\\n\\nLLM \u914D\u7F6E\u4E0D\u53D7\u5F71\u54CD\uFF0C\u6E05\u7A7A\u540E\u53EF\u91CD\u65B0\u52A0\u8F7D Demo\u3002'))return;
2701
+ try{
2702
+ const r=await fetch(API+'/config/reset',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'});
2703
+ if(!r.ok){toast('\u6E05\u7A7A\u5931\u8D25',false);return}
2704
+ toast('\u6240\u6709\u6570\u636E\u5DF2\u6E05\u7A7A',true);
2705
+ const ov=document.getElementById('overlay');if(ov)ov.remove();
2706
+ load('fleet');
2707
+ }catch{toast('\u7F51\u7EDC\u9519\u8BEF',false)}
2708
+ };
2666
2709
 
2667
2710
  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
2668
2711
  // TABS & INIT