@michengai/dsh-agency-agents 0.1.13 → 0.1.15
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/docs/00-/344/272/244/346/216/245/345/205/245/345/217/243/05-/346/212/200/346/234/257/346/236/266/346/236/204/345/237/272/347/272/277.md +3 -2
- package/docs/03-/346/212/200/346/234/257/346/236/266/346/236/204/00-/346/217/222/344/273/266/346/236/266/346/236/204.md +3 -0
- package/lib/client.js +160 -25
- package/lib/i18n-BmBLXFtD.js +442 -0
- package/lib/index.d.ts +8 -1
- package/lib/index.js +44 -338
- package/lib/remote.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
21
|
-
-
|
|
21
|
+
- Filter by category or search, then enable or disable bundled experts in **Settings → Experts**.
|
|
22
22
|
- Summon enabled experts by name or slug from the composer's **Experts** picker.
|
|
23
23
|
- Use `list_experts` to discover experts and `summon_expert` to start a one-shot specialist subagent.
|
|
24
24
|
- Use 271 bundled personas immediately, or connect a separately synchronized expert directory.
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 技术架构基线
|
|
2
2
|
|
|
3
|
-
更新时间:2026-08-
|
|
3
|
+
更新时间:2026-08-17 03:00(Asia/Shanghai)
|
|
4
4
|
|
|
5
5
|
- 运行时:Node.js ESM、TypeScript 严格模式、DSH/Cordis 插件机制。
|
|
6
6
|
- 智能体资产:`assets\agency-agents` 是默认根目录;显式 `root` 优先,其次读取 `AGENCY_AGENTS_ROOT`。
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
- 深度:`maxDepth` 为可选正整数绝对上限;未配置时不改变宿主的既有深度策略。
|
|
10
10
|
- 启停与持久化:通过 `@deepseek-ai/dsh-settings` 的 settings namespace(`agency-agents`,schema `{ enabled: string[] }`)在宿主侧持久化;**白名单语义,默认全停用**,用户在设置「专家」标签页启用。宿主工具按「已启用」过滤。
|
|
11
11
|
- 客户端取数:启用状态不经过 `api.settings`(那是 Host 自有配置面,`WEB_SETTINGS_NAMESPACES` 白名单对第三方插件硬编码封死),改走插件自有的 **Typert Remote** 通道 —— 宿主 `AgencyAgentsRemote extends TypertRemoteService`(`@Remote getEnabled/setEnabled`)由 gateway SRC 自动发现,客户端 `$mount(TYPERT_REMOTE)` 后经 `ctx.remote.agencyAgents` 读写(`src/client/remote.ts` 手写 strict 贡献)。第三方安装无需修改或重编 DSH 源码。
|
|
12
|
-
- 客户端:client bundle(`lib/client.js`,`window.__ModuleLoader__.load` 格式)提供 composer「专家」按钮 + 弹窗、设置「专家」标签页、@
|
|
12
|
+
- 客户端:client bundle(`lib/client.js`,`window.__ModuleLoader__.load` 格式)提供 composer「专家」按钮 + 弹窗、设置「专家」标签页、@ 菜单;静态花名册与中英文名打包进 client(`src/client/roster.ts`、`src/names.ts`)。界面词条走 `agency` 命名空间;专家名/简介/排序跟随 `locale` 的 `zh`/`en`。
|
|
13
|
+
- 宿主文案:`list_experts` 的名单、分区标题和用户可见错误读取 settings `locale.preference`(仅显式 `en` 走英文,其余回退 `zh`)。分区筛选同时认 key、中文名和英文名。
|
|
13
14
|
- 发布:包必须包含 `lib`(含 `client.js`)、智能体资产、`cordis.patch.yml`、Apache `LICENSE` 和 `NOTICE`。
|
|
14
15
|
|
|
15
16
|
## 与早期临时动态插件(agency-1)的差异
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
## 组件职责
|
|
8
8
|
|
|
9
9
|
- `src\index.ts`:解析 frontmatter、加载目录、注册工具和系统提示。
|
|
10
|
+
- `src\i18n.ts`:宿主侧中英文词条,以及分区/专家名的语言切换。
|
|
11
|
+
- `src\names.ts`:中英文分区名与中文专家名。
|
|
12
|
+
- `src\client\locales.ts`:设置页、按钮、`@` 菜单的客户端词条。
|
|
10
13
|
- `cordis.patch.yml`:通过 DSH bundle 把插件挂载进 profile。
|
|
11
14
|
- `scripts\verify.mjs`:校验构建入口、发布文件、bundle patch 和许可证资产。
|
|
12
15
|
- `assets\agency-agents`:上游 persona 快照;仅其中的合法 frontmatter Markdown 会进入目录。
|
package/lib/client.js
CHANGED
|
@@ -49,6 +49,26 @@ window.__ModuleLoader__.load({
|
|
|
49
49
|
support: "支持",
|
|
50
50
|
testing: "测试"
|
|
51
51
|
};
|
|
52
|
+
/** 分区目录名 → 英文分区名。 */
|
|
53
|
+
const EN_DIVISION = {
|
|
54
|
+
academic: "Academic",
|
|
55
|
+
design: "Design",
|
|
56
|
+
engineering: "Engineering",
|
|
57
|
+
finance: "Finance",
|
|
58
|
+
"game-development": "Game Development",
|
|
59
|
+
gis: "GIS",
|
|
60
|
+
healthcare: "Healthcare",
|
|
61
|
+
marketing: "Marketing",
|
|
62
|
+
"paid-media": "Paid Media",
|
|
63
|
+
product: "Product",
|
|
64
|
+
"project-management": "Project Management",
|
|
65
|
+
sales: "Sales",
|
|
66
|
+
security: "Security",
|
|
67
|
+
"spatial-computing": "Spatial Computing",
|
|
68
|
+
specialized: "Specialized",
|
|
69
|
+
support: "Support",
|
|
70
|
+
testing: "Testing"
|
|
71
|
+
};
|
|
52
72
|
/** 智能体 slug(文件名去 .md)→ 中文名(现实岗位)。缺省时回退英文 frontmatter name。 */
|
|
53
73
|
const ZH_NAME = {
|
|
54
74
|
"academic-anthropologist": "人类学家",
|
|
@@ -2509,6 +2529,16 @@ window.__ModuleLoader__.load({
|
|
|
2509
2529
|
"settings.loading": "正在加载专家…",
|
|
2510
2530
|
"settings.enabled": "已启用",
|
|
2511
2531
|
"settings.disabled": "已停用",
|
|
2532
|
+
"settings.filter.category": "分类",
|
|
2533
|
+
"settings.filter.all": "全部",
|
|
2534
|
+
"settings.filter.option": "{name}({count})",
|
|
2535
|
+
"settings.filter.showing.one": "显示 {count} 位",
|
|
2536
|
+
"settings.filter.showing.other": "显示 {count} 位",
|
|
2537
|
+
"settings.search": "搜索",
|
|
2538
|
+
"settings.search.placeholder": "名称、slug 或简介",
|
|
2539
|
+
"settings.search.clear": "清除搜索",
|
|
2540
|
+
"settings.empty": "没有匹配的专家。试试其他关键词,或切换到「{all}」。",
|
|
2541
|
+
"settings.empty.reset": "清除筛选",
|
|
2512
2542
|
"error.conflict": "配置已被其他窗口修改。",
|
|
2513
2543
|
"error.conflict.refreshed": "配置已被其他窗口修改,已为您刷新。",
|
|
2514
2544
|
"error.conflict.refreshFailed": "配置已被其他窗口修改,但刷新失败,请手动刷新。",
|
|
@@ -2522,7 +2552,6 @@ window.__ModuleLoader__.load({
|
|
|
2522
2552
|
"summary.group": "{count} 个",
|
|
2523
2553
|
"button.title": "召唤专家",
|
|
2524
2554
|
"menu.empty": "暂无可召唤的专家",
|
|
2525
|
-
"group.count": "{division}({count})",
|
|
2526
2555
|
"summon.instruction": "召唤专家「{name}」({slug})处理以下任务:",
|
|
2527
2556
|
"summon.instruction.withTask": "召唤专家「{name}」({slug})处理以下任务:\n{task}",
|
|
2528
2557
|
"division.academic": ZH_DIVISION.academic,
|
|
@@ -2550,6 +2579,16 @@ window.__ModuleLoader__.load({
|
|
|
2550
2579
|
"settings.loading": "Loading experts…",
|
|
2551
2580
|
"settings.enabled": "Enabled",
|
|
2552
2581
|
"settings.disabled": "Disabled",
|
|
2582
|
+
"settings.filter.category": "Category",
|
|
2583
|
+
"settings.filter.all": "All",
|
|
2584
|
+
"settings.filter.option": "{name} ({count})",
|
|
2585
|
+
"settings.filter.showing.one": "Showing {count} expert",
|
|
2586
|
+
"settings.filter.showing.other": "Showing {count} experts",
|
|
2587
|
+
"settings.search": "Search",
|
|
2588
|
+
"settings.search.placeholder": "Name, slug, or description",
|
|
2589
|
+
"settings.search.clear": "Clear search",
|
|
2590
|
+
"settings.empty": "No matching experts. Try another keyword, or switch to {all}.",
|
|
2591
|
+
"settings.empty.reset": "Clear filters",
|
|
2553
2592
|
"error.conflict": "Settings were changed in another window.",
|
|
2554
2593
|
"error.conflict.refreshed": "Settings were changed in another window and have been refreshed.",
|
|
2555
2594
|
"error.conflict.refreshFailed": "Settings were changed in another window, but refresh failed. Please refresh manually.",
|
|
@@ -2563,26 +2602,25 @@ window.__ModuleLoader__.load({
|
|
|
2563
2602
|
"summary.group": "{count} items",
|
|
2564
2603
|
"button.title": "Summon expert",
|
|
2565
2604
|
"menu.empty": "No experts available yet",
|
|
2566
|
-
"group.count": "{division} ({count})",
|
|
2567
2605
|
"summon.instruction": "Summon expert \"{name}\" ({slug}) to handle the following task:",
|
|
2568
2606
|
"summon.instruction.withTask": "Summon expert \"{name}\" ({slug}) to handle the following task:\n{task}",
|
|
2569
|
-
"division.academic":
|
|
2570
|
-
"division.design":
|
|
2571
|
-
"division.engineering":
|
|
2572
|
-
"division.finance":
|
|
2573
|
-
"division.game-development": "
|
|
2574
|
-
"division.gis":
|
|
2575
|
-
"division.healthcare":
|
|
2576
|
-
"division.marketing":
|
|
2577
|
-
"division.paid-media": "
|
|
2578
|
-
"division.product":
|
|
2579
|
-
"division.project-management": "
|
|
2580
|
-
"division.sales":
|
|
2581
|
-
"division.security":
|
|
2582
|
-
"division.spatial-computing": "
|
|
2583
|
-
"division.specialized":
|
|
2584
|
-
"division.support":
|
|
2585
|
-
"division.testing":
|
|
2607
|
+
"division.academic": EN_DIVISION.academic,
|
|
2608
|
+
"division.design": EN_DIVISION.design,
|
|
2609
|
+
"division.engineering": EN_DIVISION.engineering,
|
|
2610
|
+
"division.finance": EN_DIVISION.finance,
|
|
2611
|
+
"division.game-development": EN_DIVISION["game-development"],
|
|
2612
|
+
"division.gis": EN_DIVISION.gis,
|
|
2613
|
+
"division.healthcare": EN_DIVISION.healthcare,
|
|
2614
|
+
"division.marketing": EN_DIVISION.marketing,
|
|
2615
|
+
"division.paid-media": EN_DIVISION["paid-media"],
|
|
2616
|
+
"division.product": EN_DIVISION.product,
|
|
2617
|
+
"division.project-management": EN_DIVISION["project-management"],
|
|
2618
|
+
"division.sales": EN_DIVISION.sales,
|
|
2619
|
+
"division.security": EN_DIVISION.security,
|
|
2620
|
+
"division.spatial-computing": EN_DIVISION["spatial-computing"],
|
|
2621
|
+
"division.specialized": EN_DIVISION.specialized,
|
|
2622
|
+
"division.support": EN_DIVISION.support,
|
|
2623
|
+
"division.testing": EN_DIVISION.testing
|
|
2586
2624
|
};
|
|
2587
2625
|
//#endregion
|
|
2588
2626
|
//#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
@@ -6627,10 +6665,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6627
6665
|
emoji: e.emoji,
|
|
6628
6666
|
division: e.division,
|
|
6629
6667
|
divisionZh: ZH_DIVISION[e.division] ?? e.division,
|
|
6668
|
+
divisionEn: EN_DIVISION[e.division] ?? e.division,
|
|
6630
6669
|
description: e.description,
|
|
6631
6670
|
descriptionEn: e.descriptionEn
|
|
6632
6671
|
})).sort((a, b) => a.division.localeCompare(b.division) || a.slug.localeCompare(b.slug));
|
|
6633
|
-
|
|
6672
|
+
/** 按当前语言比较专家显示名,供设置页和菜单分组排序。 */
|
|
6673
|
+
function compareExpertName(a, b, active) {
|
|
6674
|
+
const left = active === "en" ? a.nameEn : a.name;
|
|
6675
|
+
const right = active === "en" ? b.nameEn : b.name;
|
|
6676
|
+
return left.localeCompare(right, active === "en" ? "en" : "zh");
|
|
6677
|
+
}
|
|
6678
|
+
function groupByDivision(list, active) {
|
|
6634
6679
|
const groups = /* @__PURE__ */ new Map();
|
|
6635
6680
|
for (const e of list) {
|
|
6636
6681
|
const arr = groups.get(e.division) ?? [];
|
|
@@ -6640,9 +6685,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6640
6685
|
return DIVISION_ORDER.filter((d) => groups.has(d)).map((d) => ({
|
|
6641
6686
|
division: d,
|
|
6642
6687
|
divisionZh: ZH_DIVISION[d] ?? d,
|
|
6643
|
-
experts: (groups.get(d) ?? []).slice().sort((a, b) => a
|
|
6688
|
+
experts: (groups.get(d) ?? []).slice().sort((a, b) => compareExpertName(a, b, active))
|
|
6644
6689
|
}));
|
|
6645
6690
|
}
|
|
6691
|
+
/** 规范化检索词:去首尾空白并转小写,便于中英和 slug 统一匹配。 */
|
|
6692
|
+
function normalizeExpertQuery(query) {
|
|
6693
|
+
return query.trim().toLowerCase();
|
|
6694
|
+
}
|
|
6695
|
+
/** 按名称、slug、分区或简介做包含匹配;空检索视为全部命中。 */
|
|
6696
|
+
function matchExpertQuery(expert, query) {
|
|
6697
|
+
const q = normalizeExpertQuery(query);
|
|
6698
|
+
if (q === "") return true;
|
|
6699
|
+
return [
|
|
6700
|
+
expert.slug,
|
|
6701
|
+
expert.name,
|
|
6702
|
+
expert.nameEn,
|
|
6703
|
+
expert.division,
|
|
6704
|
+
expert.divisionZh,
|
|
6705
|
+
expert.divisionEn,
|
|
6706
|
+
expert.description,
|
|
6707
|
+
expert.descriptionEn
|
|
6708
|
+
].some((field) => field.toLowerCase().includes(q));
|
|
6709
|
+
}
|
|
6710
|
+
/** 先按分区收窄,再按检索词过滤。division 为空表示全部分类。 */
|
|
6711
|
+
function filterExperts(list, options) {
|
|
6712
|
+
const division = options.division ?? "";
|
|
6713
|
+
return list.filter((expert) => (division === "" || expert.division === division) && matchExpertQuery(expert, options.query ?? ""));
|
|
6714
|
+
}
|
|
6715
|
+
const DIVISION_COUNTS = Object.fromEntries(DIVISION_ORDER.map((division) => [division, EXPERTS.filter((expert) => expert.division === division).length]));
|
|
6646
6716
|
/** 按当前 locale 取专家显示名:en 用花名册英文名,其余用中文名。 */
|
|
6647
6717
|
function displayName(e, active) {
|
|
6648
6718
|
return active === "en" ? e.nameEn : e.name;
|
|
@@ -6651,7 +6721,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6651
6721
|
function displayDescription(e, active) {
|
|
6652
6722
|
return active === "en" && e.descriptionEn !== "" ? e.descriptionEn : e.description;
|
|
6653
6723
|
}
|
|
6654
|
-
const CSS = ".aag-btn-wrap{position:relative;order:1;margin-right:-8px}.aag-btn{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 4px 0 8px;border:none;border-radius:24px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;font-weight:500;cursor:pointer}.aag-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.aag-menu{position:absolute;bottom:calc(100% + 4px);left:0;box-sizing:border-box;padding:4px;display:flex;flex-direction:column;gap:0;width:300px;max-width:360px;max-height:calc(100vh - 24px);overflow-y:auto;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);z-index:10000}.aag-menu-title{padding:8px 10px;font-size:12px;line-height:16px;color:var(--dsw-alias-label-tertiary)}.aag-menu-item{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:none;border-radius:10px;background:transparent;cursor:pointer;text-align:left;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);box-sizing:border-box}.aag-menu-item:hover{background:var(--dsw-alias-interactive-bg-hover)}.aag-emoji{flex:0 0 auto;font-size:16px}.aag-menu-empty{padding:8px 10px;color:var(--dsw-alias-label-secondary);font-size:13px}[data-composer-card] :has(> button[aria-haspopup=\"listbox\"]) > :nth-child(2){order:2}\n.aag-section{box-sizing:border-box;display:flex;min-width:0;max-width:760px;width:100%;margin:0 auto;flex-direction:column;gap:16px;padding:0 0 32px;color:var(--dsw-alias-label-primary)}\n.aag-toolbar{display:flex;align-items:flex-start;gap:16px;padding-bottom:12px}\n.aag-title{margin:0;font-size:20px;line-height:28px;font-weight:650;letter-spacing:-.2px}\n.aag-desc{margin:4px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.aag-actions{display:flex;align-items:center;gap:8px;margin-left:auto}\n.aag-action{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-height:32px;padding:0 12px;border:1px solid transparent;border-radius:8px;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);font:inherit;font-size:13px;font-weight:550;cursor:pointer;transition:opacity 180ms ease,background 180ms ease,border-color 180ms ease}\n.aag-action:hover:not(:disabled){opacity:.9}.aag-action:disabled{opacity:.5;cursor:default}\n.aag-action-secondary{background:transparent;border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}\n.aag-action:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}\n.aag-summary{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}\n.aag-summary-count{font-size:18px;font-weight:650}.aag-summary-label{color:var(--dsw-alias-label-secondary);font-size:12px}.aag-summary-separator{width:1px;height:24px;background:var(--dsw-alias-border-l2)}\n.aag-group{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2)}\n.aag-group-head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.aag-group-title{margin:0;font-size:14px;font-weight:600}.aag-count{color:var(--dsw-alias-label-tertiary);font-size:12px}\n.aag-row{display:flex;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.aag-row:last-child{border-bottom:0}\n.aag-row-main{display:flex;min-width:0;flex:1;flex-direction:column;gap:3px}\n.aag-row-id{display:flex;align-items:center;gap:7px;min-width:0}\n.aag-row-name{overflow:hidden;font-size:13px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}\n.aag-tag{flex:none;padding:1px 6px;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:16px}\n.aag-tag-on{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}\n.aag-tag-off{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}\n.aag-note{overflow:hidden;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}\n.aag-error{color:var(--dsw-alias-state-error-primary);font-size:13px;line-height:20px}\n@media (max-width:560px){.aag-toolbar{flex-wrap:wrap}.aag-actions{margin-left:0}.aag-row{align-items:flex-start;flex-wrap:wrap}.aag-row>.aag-action{margin-left:auto}}\n@media (prefers-reduced-motion:reduce){.aag-action{transition:none}}\n" + DIVISION_ORDER.map((d) => `[role="listbox"] div[data-source="division.${d}"] ~ button span:last-child`).join(",") + "{flex:1 1 auto;max-width:none;min-width:0}";
|
|
6724
|
+
const CSS = ".aag-btn-wrap{position:relative;order:1;margin-right:-8px}.aag-btn{display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 4px 0 8px;border:none;border-radius:24px;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;font-weight:500;cursor:pointer}.aag-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.aag-menu{position:absolute;bottom:calc(100% + 4px);left:0;box-sizing:border-box;padding:4px;display:flex;flex-direction:column;gap:0;width:300px;max-width:360px;max-height:calc(100vh - 24px);overflow-y:auto;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);z-index:10000}.aag-menu-title{padding:8px 10px;font-size:12px;line-height:16px;color:var(--dsw-alias-label-tertiary)}.aag-menu-item{display:flex;align-items:center;gap:8px;width:100%;min-height:40px;padding:8px 10px;border:none;border-radius:10px;background:transparent;cursor:pointer;text-align:left;font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary);box-sizing:border-box}.aag-menu-item:hover{background:var(--dsw-alias-interactive-bg-hover)}.aag-emoji{flex:0 0 auto;font-size:16px}.aag-menu-empty{padding:8px 10px;color:var(--dsw-alias-label-secondary);font-size:13px}[data-composer-card] :has(> button[aria-haspopup=\"listbox\"]) > :nth-child(2){order:2}\n.aag-section{box-sizing:border-box;display:flex;min-width:0;max-width:760px;width:100%;margin:0 auto;flex-direction:column;gap:16px;padding:0 0 32px;color:var(--dsw-alias-label-primary)}\n.aag-toolbar{display:flex;align-items:flex-start;gap:16px;padding-bottom:12px}\n.aag-title{margin:0;font-size:20px;line-height:28px;font-weight:650;letter-spacing:-.2px}\n.aag-desc{margin:4px 0 0;max-width:42em;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.aag-actions{display:flex;align-items:center;gap:8px;margin-left:auto}\n.aag-action{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;min-height:32px;padding:0 12px;border:1px solid transparent;border-radius:8px;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);font:inherit;font-size:13px;font-weight:550;cursor:pointer;transition:opacity 180ms ease,background 180ms ease,border-color 180ms ease}\n.aag-action:hover:not(:disabled){opacity:.9}.aag-action:disabled{opacity:.5;cursor:default}\n.aag-action-secondary{background:transparent;border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}\n.aag-action:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}\n.aag-summary{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}\n.aag-summary-count{font-size:18px;font-weight:650}.aag-summary-label{color:var(--dsw-alias-label-secondary);font-size:12px}.aag-summary-separator{width:1px;height:24px;background:var(--dsw-alias-border-l2)}\n.aag-group{display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2)}\n.aag-group-head{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.aag-group-title{margin:0;font-size:14px;font-weight:600}.aag-count{color:var(--dsw-alias-label-tertiary);font-size:12px}\n.aag-row{display:flex;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.aag-row:last-child{border-bottom:0}\n.aag-row-main{display:flex;min-width:0;flex:1;flex-direction:column;gap:3px}\n.aag-row-id{display:flex;align-items:center;gap:7px;min-width:0}\n.aag-row-name{overflow:hidden;font-size:13px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}\n.aag-tag{flex:none;padding:1px 6px;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;color:var(--dsw-alias-label-secondary);font-size:11px;line-height:16px}\n.aag-tag-on{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}\n.aag-tag-off{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}\n.aag-note{overflow:hidden;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}\n.aag-error{color:var(--dsw-alias-state-error-primary);font-size:13px;line-height:20px}\n.aag-filters{display:flex;align-items:flex-end;gap:10px}\n.aag-field{display:flex;min-width:0;flex:1;flex-direction:column;gap:6px}\n.aag-field-category{flex:0 1 220px}\n.aag-field-search{flex:1 1 240px}\n.aag-label{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:16px}\n.aag-control{box-sizing:border-box;width:100%;min-height:32px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}\n.aag-control:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}\n.aag-search-wrap{position:relative;display:flex;align-items:center}\n.aag-search{padding-right:32px}.aag-search::-webkit-search-cancel-button,.aag-search::-webkit-search-decoration{-webkit-appearance:none;appearance:none}\n.aag-search-clear{position:absolute;right:4px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);font:inherit;font-size:16px;line-height:1;cursor:pointer}\n.aag-search-clear:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.aag-search-clear:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}\n.aag-empty{display:flex;flex-direction:column;align-items:center;gap:12px;padding:28px 16px;border:1px dashed var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;text-align:center}\n.aag-filter-meta{margin-left:auto;color:var(--dsw-alias-label-tertiary);font-size:12px}\n@media (max-width:560px){.aag-toolbar{flex-wrap:wrap}.aag-actions{margin-left:0}.aag-filters{flex-direction:column;align-items:stretch}.aag-field-category,.aag-field-search{flex:none}.aag-row{align-items:flex-start;flex-wrap:wrap}.aag-row>.aag-action{margin-left:auto}.aag-filter-meta{margin-left:0}}\n@media (prefers-reduced-motion:reduce){.aag-action{transition:none}}\n" + DIVISION_ORDER.map((d) => `[role="listbox"] div[data-source="division.${d}"] ~ button span:last-child`).join(",") + "{flex:1 1 auto;max-width:none;min-width:0}";
|
|
6655
6725
|
/** 将写失败映射到 agency 词条;非冲突错误返回 null,由调用方展示原始消息。 */
|
|
6656
6726
|
function writeErrorKey(error, options) {
|
|
6657
6727
|
if (error instanceof Error && error.message.includes("changed since it was read")) {
|
|
@@ -6773,7 +6843,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6773
6843
|
});
|
|
6774
6844
|
setOpen(false);
|
|
6775
6845
|
};
|
|
6776
|
-
const groups = groupByDivision(EXPERTS.filter((e) => enabled.has(e.slug)));
|
|
6846
|
+
const groups = groupByDivision(EXPERTS.filter((e) => enabled.has(e.slug)), props.getActive());
|
|
6777
6847
|
const menu = open ? react.default.createElement("div", { className: "aag-menu" }, groups.length === 0 ? react.default.createElement("div", { className: "aag-menu-empty" }, props.t("menu.empty")) : groups.map((g) => menuGroup(g, pick, props.t, props.getActive))) : null;
|
|
6778
6848
|
return react.default.createElement("div", { className: "aag-btn-wrap" }, react.default.createElement("button", {
|
|
6779
6849
|
type: "button",
|
|
@@ -6785,6 +6855,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6785
6855
|
function AgentsSettings(props) {
|
|
6786
6856
|
const [state, setState] = react.default.useState(null);
|
|
6787
6857
|
const [error, setError] = react.default.useState(null);
|
|
6858
|
+
const [query, setQuery] = react.default.useState("");
|
|
6859
|
+
const [division, setDivision] = react.default.useState("");
|
|
6788
6860
|
const saving = react.default.useRef(false);
|
|
6789
6861
|
const [isSaving, setIsSaving] = react.default.useState(false);
|
|
6790
6862
|
const load = react.default.useCallback(() => {
|
|
@@ -6852,9 +6924,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6852
6924
|
className: "aag-note"
|
|
6853
6925
|
}, props.t("settings.loading")));
|
|
6854
6926
|
else {
|
|
6855
|
-
const
|
|
6927
|
+
const filtered = filterExperts(EXPERTS, {
|
|
6928
|
+
query,
|
|
6929
|
+
division
|
|
6930
|
+
});
|
|
6931
|
+
const groups = groupByDivision(filtered, props.getActive());
|
|
6856
6932
|
const enabledCount = [...state.enabled].filter((slug) => EXPERTS.some((e) => e.slug === slug)).length;
|
|
6857
6933
|
const total = EXPERTS.length;
|
|
6934
|
+
const filteredCount = filtered.length;
|
|
6935
|
+
const hasFilter = normalizeExpertQuery(query) !== "" || division !== "";
|
|
6936
|
+
const resetFilters = () => {
|
|
6937
|
+
setQuery("");
|
|
6938
|
+
setDivision("");
|
|
6939
|
+
};
|
|
6858
6940
|
nodes.push(react.default.createElement("div", {
|
|
6859
6941
|
key: "toolbar",
|
|
6860
6942
|
className: "aag-toolbar"
|
|
@@ -6867,7 +6949,56 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6867
6949
|
nodes.push(react.default.createElement("div", {
|
|
6868
6950
|
key: "summary",
|
|
6869
6951
|
className: "aag-summary"
|
|
6870
|
-
}, react.default.createElement("span", { className: "aag-summary-count" }, total), react.default.createElement("span", { className: "aag-summary-label" }, props.t(total === 1 ? "summary.total.one" : "summary.total.other", { count: total })), react.default.createElement("span", { className: "aag-summary-separator" }), react.default.createElement("span", { className: "aag-summary-count" }, enabledCount), react.default.createElement("span", { className: "aag-summary-label" }, props.t(enabledCount === 1 ? "summary.enabled.one" : "summary.enabled.other", { count: enabledCount }))
|
|
6952
|
+
}, react.default.createElement("span", { className: "aag-summary-count" }, total), react.default.createElement("span", { className: "aag-summary-label" }, props.t(total === 1 ? "summary.total.one" : "summary.total.other", { count: total })), react.default.createElement("span", { className: "aag-summary-separator" }), react.default.createElement("span", { className: "aag-summary-count" }, enabledCount), react.default.createElement("span", { className: "aag-summary-label" }, props.t(enabledCount === 1 ? "summary.enabled.one" : "summary.enabled.other", { count: enabledCount })), hasFilter ? react.default.createElement("span", {
|
|
6953
|
+
className: "aag-filter-meta",
|
|
6954
|
+
"aria-live": "polite"
|
|
6955
|
+
}, props.t(filteredCount === 1 ? "settings.filter.showing.one" : "settings.filter.showing.other", { count: filteredCount })) : null));
|
|
6956
|
+
nodes.push(react.default.createElement("div", {
|
|
6957
|
+
key: "filters",
|
|
6958
|
+
className: "aag-filters"
|
|
6959
|
+
}, react.default.createElement("div", { className: "aag-field aag-field-category" }, react.default.createElement("label", {
|
|
6960
|
+
className: "aag-label",
|
|
6961
|
+
htmlFor: "aag-filter-category"
|
|
6962
|
+
}, props.t("settings.filter.category")), react.default.createElement("select", {
|
|
6963
|
+
id: "aag-filter-category",
|
|
6964
|
+
className: "aag-control",
|
|
6965
|
+
value: division,
|
|
6966
|
+
onChange: (ev) => setDivision(ev.currentTarget.value)
|
|
6967
|
+
}, react.default.createElement("option", { value: "" }, props.t("settings.filter.option", {
|
|
6968
|
+
name: props.t("settings.filter.all"),
|
|
6969
|
+
count: total
|
|
6970
|
+
})), DIVISION_ORDER.map((key) => react.default.createElement("option", {
|
|
6971
|
+
key,
|
|
6972
|
+
value: key
|
|
6973
|
+
}, props.t("settings.filter.option", {
|
|
6974
|
+
name: props.t(`division.${key}`),
|
|
6975
|
+
count: DIVISION_COUNTS[key] ?? 0
|
|
6976
|
+
}))))), react.default.createElement("div", { className: "aag-field aag-field-search" }, react.default.createElement("label", {
|
|
6977
|
+
className: "aag-label",
|
|
6978
|
+
htmlFor: "aag-filter-search"
|
|
6979
|
+
}, props.t("settings.search")), react.default.createElement("div", { className: "aag-search-wrap" }, react.default.createElement("input", {
|
|
6980
|
+
id: "aag-filter-search",
|
|
6981
|
+
className: "aag-control aag-search",
|
|
6982
|
+
type: "search",
|
|
6983
|
+
value: query,
|
|
6984
|
+
autoComplete: "off",
|
|
6985
|
+
spellCheck: false,
|
|
6986
|
+
placeholder: props.t("settings.search.placeholder"),
|
|
6987
|
+
onChange: (ev) => setQuery(ev.currentTarget.value)
|
|
6988
|
+
}), query !== "" ? react.default.createElement("button", {
|
|
6989
|
+
type: "button",
|
|
6990
|
+
className: "aag-search-clear",
|
|
6991
|
+
"aria-label": props.t("settings.search.clear"),
|
|
6992
|
+
onClick: () => setQuery("")
|
|
6993
|
+
}, "×") : null))));
|
|
6994
|
+
if (groups.length === 0) nodes.push(react.default.createElement("div", {
|
|
6995
|
+
key: "empty",
|
|
6996
|
+
className: "aag-empty"
|
|
6997
|
+
}, react.default.createElement("div", null, props.t("settings.empty", { all: props.t("settings.filter.all") })), react.default.createElement("button", {
|
|
6998
|
+
type: "button",
|
|
6999
|
+
className: "aag-action aag-action-secondary",
|
|
7000
|
+
onClick: resetFilters
|
|
7001
|
+
}, props.t("settings.empty.reset"))));
|
|
6871
7002
|
for (const g of groups) nodes.push(react.default.createElement("div", {
|
|
6872
7003
|
key: g.division,
|
|
6873
7004
|
className: "aag-group"
|
|
@@ -6965,7 +7096,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6965
7096
|
exports.apply = apply;
|
|
6966
7097
|
exports.applyExpertSummon = applyExpertSummon;
|
|
6967
7098
|
exports.buildSummonInstruction = buildSummonInstruction;
|
|
7099
|
+
exports.compareExpertName = compareExpertName;
|
|
7100
|
+
exports.filterExperts = filterExperts;
|
|
6968
7101
|
exports.inject = inject;
|
|
7102
|
+
exports.matchExpertQuery = matchExpertQuery;
|
|
7103
|
+
exports.normalizeExpertQuery = normalizeExpertQuery;
|
|
6969
7104
|
exports.writeErrorKey = writeErrorKey;
|
|
6970
7105
|
exports.writeErrorMessage = writeErrorMessage;
|
|
6971
7106
|
return module.exports;
|