@michengai/dsh-agency-agents 0.1.14 → 0.1.16
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/lib/client.js +243 -3
- 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
package/lib/client.js
CHANGED
|
@@ -2529,6 +2529,16 @@ window.__ModuleLoader__.load({
|
|
|
2529
2529
|
"settings.loading": "正在加载专家…",
|
|
2530
2530
|
"settings.enabled": "已启用",
|
|
2531
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": "清除筛选",
|
|
2532
2542
|
"error.conflict": "配置已被其他窗口修改。",
|
|
2533
2543
|
"error.conflict.refreshed": "配置已被其他窗口修改,已为您刷新。",
|
|
2534
2544
|
"error.conflict.refreshFailed": "配置已被其他窗口修改,但刷新失败,请手动刷新。",
|
|
@@ -2569,6 +2579,16 @@ window.__ModuleLoader__.load({
|
|
|
2569
2579
|
"settings.loading": "Loading experts…",
|
|
2570
2580
|
"settings.enabled": "Enabled",
|
|
2571
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",
|
|
2572
2592
|
"error.conflict": "Settings were changed in another window.",
|
|
2573
2593
|
"error.conflict.refreshed": "Settings were changed in another window and have been refreshed.",
|
|
2574
2594
|
"error.conflict.refreshFailed": "Settings were changed in another window, but refresh failed. Please refresh manually.",
|
|
@@ -6645,6 +6665,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6645
6665
|
emoji: e.emoji,
|
|
6646
6666
|
division: e.division,
|
|
6647
6667
|
divisionZh: ZH_DIVISION[e.division] ?? e.division,
|
|
6668
|
+
divisionEn: EN_DIVISION[e.division] ?? e.division,
|
|
6648
6669
|
description: e.description,
|
|
6649
6670
|
descriptionEn: e.descriptionEn
|
|
6650
6671
|
})).sort((a, b) => a.division.localeCompare(b.division) || a.slug.localeCompare(b.slug));
|
|
@@ -6667,6 +6688,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6667
6688
|
experts: (groups.get(d) ?? []).slice().sort((a, b) => compareExpertName(a, b, active))
|
|
6668
6689
|
}));
|
|
6669
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]));
|
|
6670
6716
|
/** 按当前 locale 取专家显示名:en 用花名册英文名,其余用中文名。 */
|
|
6671
6717
|
function displayName(e, active) {
|
|
6672
6718
|
return active === "en" ? e.nameEn : e.name;
|
|
@@ -6675,7 +6721,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6675
6721
|
function displayDescription(e, active) {
|
|
6676
6722
|
return active === "en" && e.descriptionEn !== "" ? e.descriptionEn : e.description;
|
|
6677
6723
|
}
|
|
6678
|
-
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-select{position:relative}\n.aag-select-trigger{box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;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;line-height:20px;text-align:left;cursor:pointer}\n.aag-select-trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.aag-select-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-success-primary);outline-offset:2px}\n.aag-select-trigger[aria-expanded=\"true\"]{border-color:var(--dsw-alias-state-success-primary)}\n.aag-select-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.aag-select-caret{flex:none;width:12px;height:12px;color:var(--dsw-alias-label-tertiary)}\n.aag-select-menu{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:30;box-sizing:border-box;max-height:280px;overflow:auto;padding:4px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-shadow-lv3)}\n.aag-select-option{box-sizing:border-box;display:flex;align-items:center;width:100%;min-height:32px;padding:0 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer}\n.aag-select-option:hover,.aag-select-option[data-active=\"true\"]{background:var(--dsw-alias-interactive-bg-hover)}\n.aag-select-option[aria-selected=\"true\"]{color:var(--dsw-alias-state-success-primary)}\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}";
|
|
6679
6725
|
/** 将写失败映射到 agency 词条;非冲突错误返回 null,由调用方展示原始消息。 */
|
|
6680
6726
|
function writeErrorKey(error, options) {
|
|
6681
6727
|
if (error instanceof Error && error.message.includes("changed since it was read")) {
|
|
@@ -6806,9 +6852,138 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6806
6852
|
onClick
|
|
6807
6853
|
}, expertIcon(), react.default.createElement("span", null, props.t("settings.nav"))), menu);
|
|
6808
6854
|
}
|
|
6855
|
+
function CategorySelect(props) {
|
|
6856
|
+
const [open, setOpen] = react.default.useState(false);
|
|
6857
|
+
const selectedIndex = Math.max(0, props.options.findIndex((option) => option.value === props.value));
|
|
6858
|
+
const [active, setActive] = react.default.useState(selectedIndex);
|
|
6859
|
+
const rootRef = react.default.useRef(null);
|
|
6860
|
+
const triggerRef = react.default.useRef(null);
|
|
6861
|
+
const listRef = react.default.useRef(null);
|
|
6862
|
+
const wasOpen = react.default.useRef(false);
|
|
6863
|
+
const selected = props.options[selectedIndex];
|
|
6864
|
+
react.default.useEffect(() => {
|
|
6865
|
+
if (!open) return;
|
|
6866
|
+
setActive(selectedIndex);
|
|
6867
|
+
const onPointerDown = (ev) => {
|
|
6868
|
+
const target = ev.target;
|
|
6869
|
+
if (target instanceof Node && rootRef.current?.contains(target) === true) return;
|
|
6870
|
+
setOpen(false);
|
|
6871
|
+
};
|
|
6872
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
6873
|
+
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
6874
|
+
}, [open, selectedIndex]);
|
|
6875
|
+
react.default.useEffect(() => {
|
|
6876
|
+
if (open) {
|
|
6877
|
+
listRef.current?.focus();
|
|
6878
|
+
wasOpen.current = true;
|
|
6879
|
+
return;
|
|
6880
|
+
}
|
|
6881
|
+
if (wasOpen.current) {
|
|
6882
|
+
triggerRef.current?.focus();
|
|
6883
|
+
wasOpen.current = false;
|
|
6884
|
+
}
|
|
6885
|
+
}, [open]);
|
|
6886
|
+
react.default.useEffect(() => {
|
|
6887
|
+
if (!open) return;
|
|
6888
|
+
document.getElementById(props.id + "-opt-" + String(active))?.scrollIntoView({ block: "nearest" });
|
|
6889
|
+
}, [
|
|
6890
|
+
active,
|
|
6891
|
+
open,
|
|
6892
|
+
props.id
|
|
6893
|
+
]);
|
|
6894
|
+
const choose = (value) => {
|
|
6895
|
+
props.onChange(value);
|
|
6896
|
+
setOpen(false);
|
|
6897
|
+
};
|
|
6898
|
+
const move = (next) => {
|
|
6899
|
+
if (props.options.length === 0) return;
|
|
6900
|
+
setActive(Math.min(props.options.length - 1, Math.max(0, next)));
|
|
6901
|
+
};
|
|
6902
|
+
const onTriggerKeyDown = (ev) => {
|
|
6903
|
+
if (ev.key === "ArrowDown" || ev.key === "ArrowUp" || ev.key === "Enter" || ev.key === " ") {
|
|
6904
|
+
ev.preventDefault();
|
|
6905
|
+
setOpen(true);
|
|
6906
|
+
}
|
|
6907
|
+
};
|
|
6908
|
+
const onListKeyDown = (ev) => {
|
|
6909
|
+
if (ev.key === "ArrowDown") {
|
|
6910
|
+
ev.preventDefault();
|
|
6911
|
+
move(active + 1);
|
|
6912
|
+
return;
|
|
6913
|
+
}
|
|
6914
|
+
if (ev.key === "ArrowUp") {
|
|
6915
|
+
ev.preventDefault();
|
|
6916
|
+
move(active - 1);
|
|
6917
|
+
return;
|
|
6918
|
+
}
|
|
6919
|
+
if (ev.key === "Home") {
|
|
6920
|
+
ev.preventDefault();
|
|
6921
|
+
move(0);
|
|
6922
|
+
return;
|
|
6923
|
+
}
|
|
6924
|
+
if (ev.key === "End") {
|
|
6925
|
+
ev.preventDefault();
|
|
6926
|
+
move(props.options.length - 1);
|
|
6927
|
+
return;
|
|
6928
|
+
}
|
|
6929
|
+
if (ev.key === "Enter" || ev.key === " ") {
|
|
6930
|
+
ev.preventDefault();
|
|
6931
|
+
const option = props.options[active];
|
|
6932
|
+
if (option !== void 0) choose(option.value);
|
|
6933
|
+
return;
|
|
6934
|
+
}
|
|
6935
|
+
if (ev.key === "Escape" || ev.key === "Tab") setOpen(false);
|
|
6936
|
+
};
|
|
6937
|
+
return react.default.createElement("div", {
|
|
6938
|
+
className: "aag-select",
|
|
6939
|
+
ref: rootRef
|
|
6940
|
+
}, react.default.createElement("button", {
|
|
6941
|
+
id: props.id,
|
|
6942
|
+
ref: triggerRef,
|
|
6943
|
+
type: "button",
|
|
6944
|
+
className: "aag-select-trigger",
|
|
6945
|
+
"aria-haspopup": "listbox",
|
|
6946
|
+
"aria-expanded": open,
|
|
6947
|
+
"aria-controls": props.id + "-list",
|
|
6948
|
+
onClick: () => setOpen((current) => !current),
|
|
6949
|
+
onKeyDown: onTriggerKeyDown
|
|
6950
|
+
}, react.default.createElement("span", { className: "aag-select-value" }, selected === void 0 ? "" : selected.label), react.default.createElement("svg", {
|
|
6951
|
+
className: "aag-select-caret",
|
|
6952
|
+
viewBox: "0 0 12 12",
|
|
6953
|
+
"aria-hidden": true,
|
|
6954
|
+
focusable: false
|
|
6955
|
+
}, react.default.createElement("path", {
|
|
6956
|
+
d: "M2.5 4.5L6 8l3.5-3.5",
|
|
6957
|
+
fill: "none",
|
|
6958
|
+
stroke: "currentColor",
|
|
6959
|
+
strokeWidth: "1.5",
|
|
6960
|
+
strokeLinecap: "round",
|
|
6961
|
+
strokeLinejoin: "round"
|
|
6962
|
+
}))), open ? react.default.createElement("div", {
|
|
6963
|
+
id: props.id + "-list",
|
|
6964
|
+
ref: listRef,
|
|
6965
|
+
className: "aag-select-menu",
|
|
6966
|
+
role: "listbox",
|
|
6967
|
+
tabIndex: 0,
|
|
6968
|
+
"aria-activedescendant": props.id + "-opt-" + String(active),
|
|
6969
|
+
onKeyDown: onListKeyDown
|
|
6970
|
+
}, props.options.map((option, index) => react.default.createElement("button", {
|
|
6971
|
+
key: option.value === "" ? "all" : option.value,
|
|
6972
|
+
id: props.id + "-opt-" + String(index),
|
|
6973
|
+
type: "button",
|
|
6974
|
+
role: "option",
|
|
6975
|
+
className: "aag-select-option",
|
|
6976
|
+
"aria-selected": option.value === props.value,
|
|
6977
|
+
"data-active": index === active,
|
|
6978
|
+
onMouseEnter: () => setActive(index),
|
|
6979
|
+
onClick: () => choose(option.value)
|
|
6980
|
+
}, option.label))) : null);
|
|
6981
|
+
}
|
|
6809
6982
|
function AgentsSettings(props) {
|
|
6810
6983
|
const [state, setState] = react.default.useState(null);
|
|
6811
6984
|
const [error, setError] = react.default.useState(null);
|
|
6985
|
+
const [query, setQuery] = react.default.useState("");
|
|
6986
|
+
const [division, setDivision] = react.default.useState("");
|
|
6812
6987
|
const saving = react.default.useRef(false);
|
|
6813
6988
|
const [isSaving, setIsSaving] = react.default.useState(false);
|
|
6814
6989
|
const load = react.default.useCallback(() => {
|
|
@@ -6876,9 +7051,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6876
7051
|
className: "aag-note"
|
|
6877
7052
|
}, props.t("settings.loading")));
|
|
6878
7053
|
else {
|
|
6879
|
-
const
|
|
7054
|
+
const filtered = filterExperts(EXPERTS, {
|
|
7055
|
+
query,
|
|
7056
|
+
division
|
|
7057
|
+
});
|
|
7058
|
+
const groups = groupByDivision(filtered, props.getActive());
|
|
6880
7059
|
const enabledCount = [...state.enabled].filter((slug) => EXPERTS.some((e) => e.slug === slug)).length;
|
|
6881
7060
|
const total = EXPERTS.length;
|
|
7061
|
+
const filteredCount = filtered.length;
|
|
7062
|
+
const hasFilter = normalizeExpertQuery(query) !== "" || division !== "";
|
|
7063
|
+
const resetFilters = () => {
|
|
7064
|
+
setQuery("");
|
|
7065
|
+
setDivision("");
|
|
7066
|
+
};
|
|
6882
7067
|
nodes.push(react.default.createElement("div", {
|
|
6883
7068
|
key: "toolbar",
|
|
6884
7069
|
className: "aag-toolbar"
|
|
@@ -6891,7 +7076,59 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6891
7076
|
nodes.push(react.default.createElement("div", {
|
|
6892
7077
|
key: "summary",
|
|
6893
7078
|
className: "aag-summary"
|
|
6894
|
-
}, 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 }))
|
|
7079
|
+
}, 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", {
|
|
7080
|
+
className: "aag-filter-meta",
|
|
7081
|
+
"aria-live": "polite"
|
|
7082
|
+
}, props.t(filteredCount === 1 ? "settings.filter.showing.one" : "settings.filter.showing.other", { count: filteredCount })) : null));
|
|
7083
|
+
nodes.push(react.default.createElement("div", {
|
|
7084
|
+
key: "filters",
|
|
7085
|
+
className: "aag-filters"
|
|
7086
|
+
}, react.default.createElement("div", { className: "aag-field aag-field-category" }, react.default.createElement("label", {
|
|
7087
|
+
className: "aag-label",
|
|
7088
|
+
htmlFor: "aag-filter-category"
|
|
7089
|
+
}, props.t("settings.filter.category")), react.default.createElement(CategorySelect, {
|
|
7090
|
+
id: "aag-filter-category",
|
|
7091
|
+
value: division,
|
|
7092
|
+
onChange: setDivision,
|
|
7093
|
+
options: [{
|
|
7094
|
+
value: "",
|
|
7095
|
+
label: props.t("settings.filter.option", {
|
|
7096
|
+
name: props.t("settings.filter.all"),
|
|
7097
|
+
count: total
|
|
7098
|
+
})
|
|
7099
|
+
}, ...DIVISION_ORDER.map((key) => ({
|
|
7100
|
+
value: key,
|
|
7101
|
+
label: props.t("settings.filter.option", {
|
|
7102
|
+
name: props.t(`division.${key}`),
|
|
7103
|
+
count: DIVISION_COUNTS[key] ?? 0
|
|
7104
|
+
})
|
|
7105
|
+
}))]
|
|
7106
|
+
})), react.default.createElement("div", { className: "aag-field aag-field-search" }, react.default.createElement("label", {
|
|
7107
|
+
className: "aag-label",
|
|
7108
|
+
htmlFor: "aag-filter-search"
|
|
7109
|
+
}, props.t("settings.search")), react.default.createElement("div", { className: "aag-search-wrap" }, react.default.createElement("input", {
|
|
7110
|
+
id: "aag-filter-search",
|
|
7111
|
+
className: "aag-control aag-search",
|
|
7112
|
+
type: "search",
|
|
7113
|
+
value: query,
|
|
7114
|
+
autoComplete: "off",
|
|
7115
|
+
spellCheck: false,
|
|
7116
|
+
placeholder: props.t("settings.search.placeholder"),
|
|
7117
|
+
onChange: (ev) => setQuery(ev.currentTarget.value)
|
|
7118
|
+
}), query !== "" ? react.default.createElement("button", {
|
|
7119
|
+
type: "button",
|
|
7120
|
+
className: "aag-search-clear",
|
|
7121
|
+
"aria-label": props.t("settings.search.clear"),
|
|
7122
|
+
onClick: () => setQuery("")
|
|
7123
|
+
}, "×") : null))));
|
|
7124
|
+
if (groups.length === 0) nodes.push(react.default.createElement("div", {
|
|
7125
|
+
key: "empty",
|
|
7126
|
+
className: "aag-empty"
|
|
7127
|
+
}, react.default.createElement("div", null, props.t("settings.empty", { all: props.t("settings.filter.all") })), react.default.createElement("button", {
|
|
7128
|
+
type: "button",
|
|
7129
|
+
className: "aag-action aag-action-secondary",
|
|
7130
|
+
onClick: resetFilters
|
|
7131
|
+
}, props.t("settings.empty.reset"))));
|
|
6895
7132
|
for (const g of groups) nodes.push(react.default.createElement("div", {
|
|
6896
7133
|
key: g.division,
|
|
6897
7134
|
className: "aag-group"
|
|
@@ -6990,7 +7227,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6990
7227
|
exports.applyExpertSummon = applyExpertSummon;
|
|
6991
7228
|
exports.buildSummonInstruction = buildSummonInstruction;
|
|
6992
7229
|
exports.compareExpertName = compareExpertName;
|
|
7230
|
+
exports.filterExperts = filterExperts;
|
|
6993
7231
|
exports.inject = inject;
|
|
7232
|
+
exports.matchExpertQuery = matchExpertQuery;
|
|
7233
|
+
exports.normalizeExpertQuery = normalizeExpertQuery;
|
|
6994
7234
|
exports.writeErrorKey = writeErrorKey;
|
|
6995
7235
|
exports.writeErrorMessage = writeErrorMessage;
|
|
6996
7236
|
return module.exports;
|
package/package.json
CHANGED