@michengai/dsh-agency-agents 0.1.8 → 0.1.10

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,8 +18,8 @@
18
18
 
19
19
  ## Features
20
20
 
21
- - Browse, enable, and disable bundled experts across 17 divisions in **Settings → Agents**.
22
- - Summon enabled experts by name or slug from the composer’s **Agent** mode.
21
+ - Browse, enable, and disable bundled experts across 17 divisions in **Settings → Experts**.
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.
25
25
 
@@ -27,13 +27,17 @@ The parent session keeps task context, judgment, and the final answer. Expert ch
27
27
 
28
28
  ## Screenshots
29
29
 
30
- Enable the experts you need in **Settings → Agents**:
30
+ Enable the experts you need in **Settings → Experts**:
31
31
 
32
- ![DSH Agents panel](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/agent-roster.png)
32
+ ![DSH Experts panel](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/agent-roster.png)
33
33
 
34
- Then switch the composer to **Agent** mode and summon an expert by name and slug:
34
+ Open the composer's **Experts** picker and choose an enabled expert:
35
35
 
36
- ![Summoning an agent from the composer](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/summon-prompt.png)
36
+ ![Experts picker](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/expert-picker.png)
37
+
38
+ Then write the complete task with the expert name and slug:
39
+
40
+ ![Summoning an expert from the composer](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/summon-prompt.png)
37
41
 
38
42
  ## Prerequisites
39
43
 
@@ -78,12 +82,12 @@ Restart DSH Web and hard-refresh the browser. `dsh plugin ... add .` reads the p
78
82
 
79
83
  ## Usage
80
84
 
81
- 1. Open **Settings → Agents** and enable the needed experts.
82
- 2. Select **Agent** mode in the composer.
85
+ 1. Open **Settings → Experts** and enable the needed experts.
86
+ 2. Open the composer's **Experts** picker and choose an enabled expert.
83
87
  3. Name the expert and slug, then provide the complete task.
84
88
 
85
89
  ```text
86
- Summon the "Code Review Engineer" agent (engineering-code-reviewer) for this task:
90
+ Summon the "Code Review Engineer" expert (engineering-code-reviewer) for this task:
87
91
  Review the changes in the current workspace and list reproducible issues by severity.
88
92
  ```
89
93
 
package/README.zh-CN.md CHANGED
@@ -18,8 +18,8 @@
18
18
 
19
19
  ## 功能概览
20
20
 
21
- - 在「设置 → 智能体」中按 17 个分区浏览、启用或停用内置专家。
22
- - 在输入框的「智能体」模式中按名称或 slug 召唤已启用的专家处理完整任务。
21
+ - 在「设置 → 专家」中按 17 个分区浏览、启用或停用内置专家。
22
+ - 在输入框的「专家」中按名称或 slug 召唤已启用的专家处理完整任务。
23
23
  - 提供 `list_experts` 与 `summon_expert` 工具,分别用于发现专家和启动一次性子代理。
24
24
  - 内置 271 份 persona,无需额外下载;也可接入自行同步的专家目录。
25
25
 
@@ -27,13 +27,17 @@
27
27
 
28
28
  ## 界面预览
29
29
 
30
- 在「设置 → 智能体」中启用需要的专家:
30
+ 在「设置 → 专家」中启用需要的专家:
31
31
 
32
- ![DSH 智能体面板](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/agent-roster.png)
32
+ ![DSH 专家面板](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/agent-roster.png)
33
33
 
34
- 再把输入框切到「智能体」模式,按名称和 slug 召唤专家:
34
+ 在输入框点击「专家」,选择已启用的专家:
35
35
 
36
- ![召唤智能体的输入方式](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/summon-prompt.png)
36
+ ![专家选择器](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/expert-picker.png)
37
+
38
+ 再用名称和 slug 写出完整任务:
39
+
40
+ ![召唤专家的输入方式](https://raw.githubusercontent.com/MichengAI/dsh-agency-agents/main/assets/screenshots/summon-prompt.png)
37
41
 
38
42
  ## 前置条件
39
43
 
@@ -78,12 +82,12 @@ dsh --profile web --dump-config
78
82
 
79
83
  ## 使用
80
84
 
81
- 1. 打开「设置 → 智能体」,启用需要的专家。
82
- 2. 在对话输入框选择「智能体」模式。
85
+ 1. 打开「设置 → 专家」,启用需要的专家。
86
+ 2. 在对话输入框点击「专家」,选择已启用的专家。
83
87
  3. 用名称和 slug 明确指定专家,并给出完整任务。例如:
84
88
 
85
89
  ```text
86
- 召唤智能体「代码审查工程师」(engineering-code-reviewer)处理以下任务:
90
+ 召唤专家「代码审查工程师」(engineering-code-reviewer)处理以下任务:
87
91
  审查当前工作区的改动,按严重程度列出可复现的问题。
88
92
  ```
89
93
 
Binary file
package/lib/client.js CHANGED
@@ -2505,11 +2505,20 @@ window.__ModuleLoader__.load({
2505
2505
  /** 简体中文词条(key 集真相源)。 */
2506
2506
  const zh = {
2507
2507
  "settings.nav": "专家",
2508
- "button.title": "召唤专家",
2509
- "menu.empty": "暂无可召唤的专家",
2508
+ "settings.intro": "选择对话里可以召唤的专家。停用后不会出现在 @ 菜单中。",
2510
2509
  "settings.loading": "正在加载专家…",
2511
2510
  "settings.enabled": "已启用",
2512
2511
  "settings.disabled": "已停用",
2512
+ "btn.refresh": "刷新",
2513
+ "btn.enable": "启用",
2514
+ "btn.disable": "停用",
2515
+ "summary.total.one": "位专家",
2516
+ "summary.total.other": "位专家",
2517
+ "summary.enabled.one": "位已启用",
2518
+ "summary.enabled.other": "位已启用",
2519
+ "summary.group": "{count} 个",
2520
+ "button.title": "召唤专家",
2521
+ "menu.empty": "暂无可召唤的专家",
2513
2522
  "group.count": "{division}({count})",
2514
2523
  "summon.instruction": "召唤专家「{name}」({slug})处理以下任务:",
2515
2524
  "summon.instruction.withTask": "召唤专家「{name}」({slug})处理以下任务:\n{task}",
@@ -2534,11 +2543,20 @@ window.__ModuleLoader__.load({
2534
2543
  /** 英文词条,key 完整性由 satisfies 在编译期保证。 */
2535
2544
  const en = {
2536
2545
  "settings.nav": "Experts",
2537
- "button.title": "Summon expert",
2538
- "menu.empty": "No experts available yet",
2546
+ "settings.intro": "Choose which experts can be summoned in chat. Disabled experts stay out of the @ menu.",
2539
2547
  "settings.loading": "Loading experts…",
2540
2548
  "settings.enabled": "Enabled",
2541
2549
  "settings.disabled": "Disabled",
2550
+ "btn.refresh": "Refresh",
2551
+ "btn.enable": "Enable",
2552
+ "btn.disable": "Disable",
2553
+ "summary.total.one": "expert",
2554
+ "summary.total.other": "experts",
2555
+ "summary.enabled.one": "enabled",
2556
+ "summary.enabled.other": "enabled",
2557
+ "summary.group": "{count} items",
2558
+ "button.title": "Summon expert",
2559
+ "menu.empty": "No experts available yet",
2542
2560
  "group.count": "{division} ({count})",
2543
2561
  "summon.instruction": "Summon expert \"{name}\" ({slug}) to handle the following task:",
2544
2562
  "summon.instruction.withTask": "Summon expert \"{name}\" ({slug}) to handle the following task:\n{task}",
@@ -6627,7 +6645,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6627
6645
  function displayDescription(e, active) {
6628
6646
  return active === "en" && e.descriptionEn !== "" ? e.descriptionEn : e.description;
6629
6647
  }
6630
- 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}.aag-settings{padding:4px 0}.aag-group{margin-bottom:18px}.aag-group-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary);margin:0 0 8px 2px}.aag-row{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:8px;border:1px solid var(--dsw-alias-border-l1);margin-bottom:6px}.aag-row:hover{background:var(--dsw-alias-bg-layer-1)}.aag-info{flex:1 1 auto;min-width:0}.aag-name{font-size:13px;font-weight:500;color:var(--dsw-alias-label-primary)}.aag-desc{font-size:12px;color:var(--dsw-alias-label-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.aag-toggle{flex:0 0 auto;border:1px solid var(--dsw-alias-border-l1);background:transparent;border-radius:999px;padding:3px 12px;font-size:12px;cursor:pointer;color:var(--dsw-alias-label-primary)}.aag-toggle.aag-on{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.aag-toggle.aag-off{color:var(--dsw-alias-label-secondary)}.aag-loading,.aag-empty,.aag-error{padding:20px;color:var(--dsw-alias-label-secondary);font-size:13px}[data-composer-card] :has(> button[aria-haspopup=\"listbox\"]) > :nth-child(2){order:2}" + 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}";
6648
+ 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}";
6631
6649
  const SETTINGS_CONFLICT_MESSAGE = "配置已被其他窗口修改,已为您刷新。";
6632
6650
  function writeErrorMessage(error) {
6633
6651
  if (error instanceof Error && error.message.includes("changed since it was read")) return SETTINGS_CONFLICT_MESSAGE;
@@ -6747,6 +6765,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6747
6765
  const [error, setError] = react.default.useState(null);
6748
6766
  const saving = react.default.useRef(false);
6749
6767
  const [isSaving, setIsSaving] = react.default.useState(false);
6768
+ const load = react.default.useCallback(() => {
6769
+ readEnabled(props.remote).then((current) => {
6770
+ setState(current);
6771
+ setError(null);
6772
+ }).catch((err) => {
6773
+ setError(err instanceof Error ? err.message : String(err));
6774
+ });
6775
+ }, [props.remote]);
6750
6776
  react.default.useEffect(() => {
6751
6777
  let alive = true;
6752
6778
  readEnabled(props.remote).then((current) => {
@@ -6780,24 +6806,53 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6780
6806
  setIsSaving(false);
6781
6807
  });
6782
6808
  };
6783
- if (error !== null) return react.default.createElement("div", { className: "aag-error" }, error);
6784
- if (state === null) return react.default.createElement("div", { className: "aag-loading" }, props.t("settings.loading"));
6785
- const groups = groupByDivision(EXPERTS);
6786
- return react.default.createElement("div", { className: "aag-settings" }, groups.map((g) => react.default.createElement("div", {
6787
- key: g.division,
6788
- className: "aag-group"
6789
- }, react.default.createElement("div", { className: "aag-group-title" }, props.t("group.count", {
6790
- division: props.t(`division.${g.division}`),
6791
- count: g.experts.length
6792
- })), g.experts.map((e) => react.default.createElement("div", {
6793
- key: e.slug,
6794
- className: "aag-row"
6795
- }, react.default.createElement("span", { className: "aag-emoji" }, e.emoji), react.default.createElement("div", { className: "aag-info" }, react.default.createElement("div", { className: "aag-name" }, displayName(e, props.getActive())), react.default.createElement("div", { className: "aag-desc" }, displayDescription(e, props.getActive()))), react.default.createElement("button", {
6796
- type: "button",
6797
- disabled: isSaving,
6798
- className: `aag-toggle ${state.enabled.has(e.slug) ? "aag-on" : "aag-off"}`,
6799
- onClick: () => toggle(e.slug)
6800
- }, props.t(state.enabled.has(e.slug) ? "settings.enabled" : "settings.disabled")))))));
6809
+ const nodes = [];
6810
+ if (error !== null) nodes.push(react.default.createElement("div", {
6811
+ key: "error",
6812
+ className: "aag-error",
6813
+ role: "alert"
6814
+ }, error));
6815
+ if (state === null) nodes.push(react.default.createElement("div", {
6816
+ key: "loading",
6817
+ className: "aag-note"
6818
+ }, props.t("settings.loading")));
6819
+ else {
6820
+ const groups = groupByDivision(EXPERTS);
6821
+ const enabledCount = [...state.enabled].filter((slug) => EXPERTS.some((e) => e.slug === slug)).length;
6822
+ const total = EXPERTS.length;
6823
+ nodes.push(react.default.createElement("div", {
6824
+ key: "toolbar",
6825
+ className: "aag-toolbar"
6826
+ }, react.default.createElement("div", null, react.default.createElement("h2", { className: "aag-title" }, props.t("settings.nav")), react.default.createElement("p", { className: "aag-desc" }, props.t("settings.intro"))), react.default.createElement("div", { className: "aag-actions" }, react.default.createElement("button", {
6827
+ type: "button",
6828
+ className: "aag-action aag-action-secondary",
6829
+ disabled: isSaving,
6830
+ onClick: load
6831
+ }, props.t("btn.refresh")))));
6832
+ nodes.push(react.default.createElement("div", {
6833
+ key: "summary",
6834
+ className: "aag-summary"
6835
+ }, 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 }))));
6836
+ for (const g of groups) nodes.push(react.default.createElement("div", {
6837
+ key: g.division,
6838
+ className: "aag-group"
6839
+ }, react.default.createElement("div", { className: "aag-group-head" }, react.default.createElement("h3", { className: "aag-group-title" }, props.t(`division.${g.division}`)), react.default.createElement("span", { className: "aag-count" }, props.t("summary.group", { count: g.experts.length }))), g.experts.map((e) => {
6840
+ const on = state.enabled.has(e.slug);
6841
+ return react.default.createElement("div", {
6842
+ key: e.slug,
6843
+ className: "aag-row"
6844
+ }, react.default.createElement("div", { className: "aag-row-main" }, react.default.createElement("div", { className: "aag-row-id" }, react.default.createElement("span", { className: "aag-row-name" }, displayName(e, props.getActive())), react.default.createElement("span", { className: "aag-tag" }, e.slug), react.default.createElement("span", { className: `aag-tag ${on ? "aag-tag-on" : "aag-tag-off"}` }, props.t(on ? "settings.enabled" : "settings.disabled"))), react.default.createElement("div", {
6845
+ className: "aag-note",
6846
+ title: displayDescription(e, props.getActive())
6847
+ }, displayDescription(e, props.getActive()))), react.default.createElement("button", {
6848
+ type: "button",
6849
+ className: "aag-action aag-action-secondary",
6850
+ disabled: isSaving,
6851
+ onClick: () => toggle(e.slug)
6852
+ }, props.t(on ? "btn.disable" : "btn.enable")));
6853
+ })));
6854
+ }
6855
+ return react.default.createElement("section", { className: "aag-section" }, nodes);
6801
6856
  }
6802
6857
  const inject = [
6803
6858
  "slots",
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.8",
4
+ "version": "0.1.10",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",