@michengai/dsh-agency-agents 0.1.14 → 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 CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  ## Features
20
20
 
21
- - Browse, enable, and disable bundled experts across 17 divisions in **Settings → Experts**.
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
@@ -18,7 +18,7 @@
18
18
 
19
19
  ## 功能概览
20
20
 
21
- - 在「设置 → 专家」中按 17 个分区浏览、启用或停用内置专家。
21
+ - 在「设置 → 专家」中按分类筛选或搜索,再启用或停用内置专家。
22
22
  - 在输入框的「专家」中按名称或 slug 召唤已启用的专家处理完整任务。
23
23
  - 提供 `list_experts` 与 `summon_expert` 工具,分别用于发现专家和启动一次性子代理。
24
24
  - 内置 271 份 persona,无需额外下载;也可接入自行同步的专家目录。
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-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")) {
@@ -6809,6 +6855,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6809
6855
  function AgentsSettings(props) {
6810
6856
  const [state, setState] = react.default.useState(null);
6811
6857
  const [error, setError] = react.default.useState(null);
6858
+ const [query, setQuery] = react.default.useState("");
6859
+ const [division, setDivision] = react.default.useState("");
6812
6860
  const saving = react.default.useRef(false);
6813
6861
  const [isSaving, setIsSaving] = react.default.useState(false);
6814
6862
  const load = react.default.useCallback(() => {
@@ -6876,9 +6924,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6876
6924
  className: "aag-note"
6877
6925
  }, props.t("settings.loading")));
6878
6926
  else {
6879
- const groups = groupByDivision(EXPERTS, props.getActive());
6927
+ const filtered = filterExperts(EXPERTS, {
6928
+ query,
6929
+ division
6930
+ });
6931
+ const groups = groupByDivision(filtered, props.getActive());
6880
6932
  const enabledCount = [...state.enabled].filter((slug) => EXPERTS.some((e) => e.slug === slug)).length;
6881
6933
  const total = EXPERTS.length;
6934
+ const filteredCount = filtered.length;
6935
+ const hasFilter = normalizeExpertQuery(query) !== "" || division !== "";
6936
+ const resetFilters = () => {
6937
+ setQuery("");
6938
+ setDivision("");
6939
+ };
6882
6940
  nodes.push(react.default.createElement("div", {
6883
6941
  key: "toolbar",
6884
6942
  className: "aag-toolbar"
@@ -6891,7 +6949,56 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6891
6949
  nodes.push(react.default.createElement("div", {
6892
6950
  key: "summary",
6893
6951
  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 }))));
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"))));
6895
7002
  for (const g of groups) nodes.push(react.default.createElement("div", {
6896
7003
  key: g.division,
6897
7004
  className: "aag-group"
@@ -6990,7 +7097,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6990
7097
  exports.applyExpertSummon = applyExpertSummon;
6991
7098
  exports.buildSummonInstruction = buildSummonInstruction;
6992
7099
  exports.compareExpertName = compareExpertName;
7100
+ exports.filterExperts = filterExperts;
6993
7101
  exports.inject = inject;
7102
+ exports.matchExpertQuery = matchExpertQuery;
7103
+ exports.normalizeExpertQuery = normalizeExpertQuery;
6994
7104
  exports.writeErrorKey = writeErrorKey;
6995
7105
  exports.writeErrorMessage = writeErrorMessage;
6996
7106
  return module.exports;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@michengai/dsh-agency-agents",
3
3
  "description": "Agency Experts — a summonable domain-expert roster for DSH (expert mode)",
4
- "version": "0.1.14",
4
+ "version": "0.1.15",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",