dsh-capability-panel 1.2.1 → 1.3.0

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/lib/client.js CHANGED
@@ -32,10 +32,10 @@ let react = require("react");
32
32
  react = __toESM(react);
33
33
  let react_jsx_runtime = require("react/jsx-runtime");
34
34
  react_jsx_runtime = __toESM(react_jsx_runtime);
35
- let react_dom = require("react-dom");
36
- react_dom = __toESM(react_dom);
37
35
  let __deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
38
36
  __deepseek_ai_dsh_client_ui_primitives = __toESM(__deepseek_ai_dsh_client_ui_primitives);
37
+ let react_dom = require("react-dom");
38
+ react_dom = __toESM(react_dom);
39
39
 
40
40
  //#region src/wire.ts
41
41
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -413,6 +413,8 @@ const zh = {
413
413
  "group.skills": "技能 ({shown}/{total})",
414
414
  "group.mcp": "MCP ({shown}/{total})",
415
415
  "group.system": "系统工具 ({shown}/{total})",
416
+ "group.systemTools": "系统工具",
417
+ "group.count": "{shown}/{total}",
416
418
  "tab.all": "全部",
417
419
  "tab.skills": "技能",
418
420
  "tab.mcp": "MCP",
@@ -427,6 +429,8 @@ const zh = {
427
429
  "filter.count": "匹配 {shown} / {total} 项",
428
430
  "footer.feedback": "反馈问题",
429
431
  "footer.feedbackHint": "在 GitHub 上打开能力面板的 issue 页",
432
+ "footer.openSettings": "全局配置",
433
+ "footer.openSettingsHint": "打开设置并进入「能力面板」页",
430
434
  "disclosure.expand": "展开 {subject} 的{detail}",
431
435
  "disclosure.collapse": "收起 {subject} 的{detail}",
432
436
  "disclosure.pinned": "{subject} 的{detail}(筛选时保持展开)",
@@ -482,6 +486,8 @@ const en = {
482
486
  "group.skills": "Skills ({shown}/{total})",
483
487
  "group.mcp": "MCP ({shown}/{total})",
484
488
  "group.system": "System tools ({shown}/{total})",
489
+ "group.systemTools": "System tools",
490
+ "group.count": "{shown}/{total}",
485
491
  "tab.all": "All",
486
492
  "tab.skills": "Skills",
487
493
  "tab.mcp": "MCP",
@@ -496,6 +502,8 @@ const en = {
496
502
  "filter.count": "{shown} / {total} matched",
497
503
  "footer.feedback": "Report an issue",
498
504
  "footer.feedbackHint": "Open the capability panel’s issues on GitHub",
505
+ "footer.openSettings": "Global settings",
506
+ "footer.openSettingsHint": "Open Settings on the Capability Panel page",
499
507
  "disclosure.expand": "Expand {detail} for {subject}",
500
508
  "disclosure.collapse": "Collapse {detail} for {subject}",
501
509
  "disclosure.pinned": "{detail} for {subject} (kept open while filtering)",
@@ -553,6 +561,7 @@ const TOK = {
553
561
  menuBg: "var(--dsw-specific-menu, #ffffff)",
554
562
  menuBorder: "var(--dsw-alias-border-inverted, rgba(0,0,0,.1))",
555
563
  menuShadow: "var(--dsw-shadow-lv3, 0 12px 32px rgba(0,0,0,.22))",
564
+ menuBlur: "var(--dsw-menu-backdrop-filter, none)",
556
565
  bgBase: "var(--dsw-alias-bg-base, #ffffff)",
557
566
  fontFamily: "var(--dsw-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif)",
558
567
  success: "var(--dsw-alias-state-success-primary, #22c55e)",
@@ -584,31 +593,36 @@ const PANEL_CSS = [
584
593
  ".ci-description{padding:3px 0 0 24px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);word-break:break-word}",
585
594
  ".ci-chevron{display:grid;place-items:center;width:18px;height:18px;flex:none;color:var(--dsw-alias-label-tertiary,#81858c);border-radius:4px}",
586
595
  ".ci-chevron svg{transition:transform .12s var(--ds-ease-in-out,ease)}",
587
- ".ci-server-trigger[aria-expanded=\"true\"] .ci-chevron svg,.ci-disclosure-trigger[aria-expanded=\"true\"] .ci-chevron svg{transform:rotate(90deg)}",
588
- ".ci-tabs{display:flex;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-bg-base,#ffffff);border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.04))}",
596
+ ".ci-server-trigger[aria-expanded=\"true\"] .ci-chevron svg,.ci-disclosure-trigger[aria-expanded=\"true\"] .ci-chevron svg,.ci-preset-part-trigger[aria-expanded=\"true\"] .ci-chevron svg{transform:rotate(90deg)}",
597
+ ".ci-tabs{display:flex;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
589
598
  ".ci-tab{flex:1;height:24px;border:none;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#61666b);font:inherit;font-size:12px;line-height:1;cursor:pointer;font-variant-numeric:tabular-nums;padding:0 4px}",
590
599
  ".ci-tab:hover{color:var(--dsw-alias-label-primary,#0f1115)}",
591
- ".ci-tab[data-active]{background:var(--dsw-specific-menu,#fff);color:var(--dsw-alias-label-primary,#0f1115);box-shadow:0 1px 2px rgba(0,0,0,.08)}",
592
- ".ci-preset-section{max-width:720px;color:var(--dsw-alias-label-secondary,#61666b)}",
593
- ".ci-settings-title{margin:0 0 6px;color:var(--dsw-alias-label-primary,#0f1115);font-size:18px;line-height:26px}",
594
- ".ci-settings-intro,.ci-settings-description,.ci-settings-note{margin:0 0 16px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858c)}",
600
+ ".ci-tab[data-active]{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);box-shadow:var(--dsw-elevation-soft,0 1px 2px rgba(0,0,0,.08))}",
601
+ ".ci-preset-section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary,#0f1115);display:flex;flex-direction:column;gap:14px}",
602
+ ".ci-settings-title{margin:0;color:var(--dsw-alias-label-primary,#0f1115);font-size:18px;font-weight:600;line-height:26px}",
603
+ ".ci-settings-intro,.ci-settings-description,.ci-settings-note{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858c)}",
595
604
  ".ci-settings-note{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:8px}",
596
- ".ci-preset-toolbar{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;margin:10px 0}",
597
- ".ci-preset-filter{flex:1 1 220px;min-width:180px;height:34px;box-sizing:border-box;padding:0 10px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:8px;background-color:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-weight:400}",
598
- ".ci-preset-part{margin:18px 0 0}",
599
- ".ci-preset-part:first-of-type{margin-top:10px}",
600
- ".ci-preset-part-title{margin:0;font-size:14px;font-weight:600;line-height:22px;color:var(--dsw-alias-label-primary,#0f1115)}",
601
- ".ci-preset-badge{display:inline-block;margin-left:6px;padding:1px 6px;line-height:1.5;border-radius:999px;font-size:11px;font-weight:500;vertical-align:middle;background-color:var(--dsw-alias-bg-fill-2,rgba(0,0,0,.05));color:var(--dsw-alias-label-tertiary,#81858c)}",
605
+ ".ci-preset-toolbar{display:flex;gap:10px;align-items:center;margin:0}",
606
+ ".ci-search{position:relative;flex:1 1 auto;min-width:180px;display:flex;align-items:center;color:var(--dsw-alias-label-tertiary,#81858c)}",
607
+ ".ci-search>svg{position:absolute;left:12px;pointer-events:none}",
608
+ ".ci-preset-filter{width:100%;height:36px;box-sizing:border-box;padding:0 34px 0 36px;border:.5px solid var(--dsw-alias-border-l4,rgba(0,0,0,.16));border-radius:var(--dsw-radius-md,12px);background-color:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:13px;font-weight:400;outline:none}",
609
+ ".ci-preset-filter:focus-visible{border-color:var(--dsw-alias-state-business-primary,#4176e6);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 18%,transparent)}",
610
+ ".ci-preset-part{display:flex;flex-direction:column;gap:10px;margin:0;padding:14px 0 0;border-top:.5px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}",
611
+ ".ci-preset-part:first-of-type{border-top:0;padding-top:0}",
612
+ ".ci-preset-part-trigger{display:flex;align-items:center;gap:8px;min-height:32px;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}",
613
+ ".ci-preset-part-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:4px}",
614
+ ".ci-preset-part-title{margin:0;font-size:14px;font-weight:400;line-height:22px;color:var(--dsw-alias-label-primary,#0f1115)}",
615
+ ".ci-preset-part-sub{margin:-4px 0 0 26px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);font-variant-numeric:tabular-nums}",
616
+ ".ci-preset-badge{display:inline-block;margin-left:6px;padding:1px 6px;line-height:1.5;border-radius:999px;font-size:11px;font-weight:500;vertical-align:middle;background-color:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.05));color:var(--dsw-alias-label-tertiary,#81858c)}",
602
617
  ".ci-preset-group{padding:0}",
603
618
  ".ci-preset-server-trigger{display:flex;align-items:center;gap:8px;flex:1;min-width:0;background:none;border:none;padding:0;text-align:left;font:inherit;color:inherit;cursor:pointer}",
604
619
  ".ci-preset-server-trigger:disabled{cursor:default}",
605
620
  ".ci-preset-group .ci-preset-tool-list{margin:0;padding-left:26px}",
606
- ".ci-preset-picker-label{display:grid;gap:6px;color:var(--dsw-alias-label-primary,#0f1115);font-weight:600}",
607
- ".ci-preset-picker-trigger{height:28px;display:flex;align-items:center;gap:4px;padding:0 4px 0 8px;border:none;border-radius:24px;background:transparent;color:var(--dsw-alias-label-secondary,#61666b);font-size:13px;font-weight:500;line-height:20px;cursor:pointer;outline:none;max-width:280px}",
621
+ ".ci-preset-picker-trigger{height:36px;display:inline-flex;align-items:center;gap:8px;padding:0 14px;border:none;border-radius:var(--dsw-radius-md,12px);background:var(--dsw-alias-bg-module-platform,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:14px;font-weight:400;line-height:22px;cursor:pointer;outline:none;max-width:280px;flex:none;white-space:nowrap}",
608
622
  ".ci-preset-picker-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
609
- ".ci-preset-picker-trigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3,rgba(0,0,0,.16))}",
623
+ ".ci-preset-picker-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px}",
610
624
  ".ci-preset-picker-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}",
611
- ".ci-preset-picker-chevron{color:var(--dsw-alias-label-caption,#81858c);flex:none;display:inline-grid;place-items:center;transition:transform .12s}",
625
+ ".ci-preset-picker-chevron{color:var(--dsw-alias-label-tertiary,#81858c);flex:none;display:inline-grid;place-items:center;transition:transform .12s}",
612
626
  ".ci-preset-picker-chevron-open{transform:rotate(180deg)}",
613
627
  ".ci-settings-subtitle{margin:0 0 6px;color:var(--dsw-alias-label-primary,#0f1115);font-size:14px;line-height:22px}",
614
628
  ".ci-preset-tool-list{list-style:none;margin:0;padding:0}",
@@ -620,7 +634,7 @@ const PANEL_CSS = [
620
634
  ".ci-preset-disclosure{display:block}",
621
635
  ".ci-preset-spacer{width:18px;flex:none}",
622
636
  ".ci-preset-detail{padding:0 0 10px 24px;color:var(--dsw-alias-label-tertiary,#81858c);line-height:18px;overflow-wrap:anywhere}",
623
- ".ci-preset-kinds{margin:0 0 4px}",
637
+ ".ci-preset-kinds{margin:0}",
624
638
  ".ci-preset-kinds .ci-tabs{display:inline-flex}",
625
639
  ".ci-preset-kinds .ci-tab{flex:0 0 auto;padding:0 12px}",
626
640
  ".ci-source-header:hover .ci-folder-icon{opacity:1 !important}",
@@ -637,6 +651,7 @@ const PANEL_CSS = [
637
651
  ".ci-feedback-link:hover{color:var(--dsw-alias-label-primary,#0f1115);text-decoration:underline}",
638
652
  ".ci-feedback-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:3px}",
639
653
  ".ci-feedback-icon{display:inline-grid;place-items:center;flex:none}",
654
+ ".ci-settings-link{border:0;background:none;padding:0;font-family:inherit}",
640
655
  "@media (prefers-reduced-motion: reduce){.ci-thumb,.ci-panel,.ci-collapse,.ci-chevron svg{transition:none !important}}"
641
656
  ].join("\n");
642
657
 
@@ -1969,14 +1984,22 @@ const SwitchThumb = /* @__PURE__ */ react.forwardRef(function SwitchThumb$1(comp
1969
1984
  /**
1970
1985
  * The capability switch, in one place for both panels.
1971
1986
  *
1972
- * The two panels each had their own copy, and the copies had already drifted:
1973
- * the thumb was a circle in one and a pill in the other, with different
1974
- * transition durations and shadows. Nobody noticed, which is the point --
1975
- * "how a control looks" belongs to the design system, while "what a row is
1976
- * made of" belongs to each panel, so only the latter is written twice.
1987
+ * dsh 0.1.7 ships a design-system `Switch` (36×20 capsule, brand-primary on
1988
+ * state, its own disabled dimming and focus ring) — using it keeps the panel's
1989
+ * toggles pixel-identical to every settings page the host ships, which is the
1990
+ * alignment this file exists for. Hosts older than that export fall back to
1991
+ * the local Base UI rendition below, so one build still serves both
1992
+ * generations; the probe runs per call, the same way the icon table resolves.
1977
1993
  */
1978
1994
  function capabilitySwitch(options) {
1979
1995
  const inert = options.disabled || options.busy;
1996
+ const HostSwitch = __deepseek_ai_dsh_client_ui_primitives.Switch;
1997
+ if (HostSwitch !== void 0) return react.createElement(HostSwitch, {
1998
+ checked: options.checked,
1999
+ onChange: options.onCheckedChange,
2000
+ label: options.label,
2001
+ disabled: inert
2002
+ });
1980
2003
  return react.createElement(SwitchRoot, {
1981
2004
  className: "ci-switch",
1982
2005
  checked: options.checked,
@@ -4553,6 +4576,45 @@ const TabsList = /* @__PURE__ */ react.forwardRef(function TabsList$1(componentP
4553
4576
  });
4554
4577
  });
4555
4578
 
4579
+ //#endregion
4580
+ //#region src/client/icons.ts
4581
+ /** Rendered when a host generation has neither name: the panel stays usable. */
4582
+ const MissingIcon = () => null;
4583
+ /**
4584
+ * Pick the first export name the host's primitives package actually provides.
4585
+ * Exported separately from the module-level constants so tests can drive every
4586
+ * branch with a fake table.
4587
+ */
4588
+ function pickIcon(table$1, modern, legacy) {
4589
+ const found = table$1[modern] ?? table$1[legacy];
4590
+ return typeof found === "function" ? found : MissingIcon;
4591
+ }
4592
+ const table = __deepseek_ai_dsh_client_ui_primitives;
4593
+ const IconChevronRight = pickIcon(table, "IconChevronRightOutlineRegular", "IconChevronRightOutline14");
4594
+ const IconContextInjection = pickIcon(table, "IconContextInjectionOutlineRegular", "IconContextInjectionOutline16");
4595
+ const IconFolderClose = pickIcon(table, "IconFolderCloseRegular", "IconFolderClose16");
4596
+ const IconSend = pickIcon(table, "IconSendOutlineRegular", "IconSendOutline14");
4597
+ const IconSearch = pickIcon(table, "IconSearchOutlineRegular", "IconSearchOutline16");
4598
+ const IconRefresh = pickIcon(table, "IconRefreshOutlineRegular", "IconRefreshOutline14");
4599
+ const IconChevronDown = pickIcon(table, "IconChevronDownOutlineRegular", "IconChevronDownOutline14");
4600
+ const IconSettings = pickIcon(table, "IconSettingsOutlineRegular", "IconSettingsOutline16");
4601
+ /**
4602
+ * Whether the host ships the 0.1.7 stroke-weight icon set. Exported as a
4603
+ * function so tests can drive both branches; the module constant resolves it
4604
+ * against the real package.
4605
+ *
4606
+ * One consumer: the footer settings entry. The `settings.open` keybinding that
4607
+ * entry drives shipped in the SAME host generation as the renamed icon set
4608
+ * (verified: 0.1.6's settings bundle has no such binding), so this is the
4609
+ * closest client-visible signal that the shortcut exists. If a future host
4610
+ * renames icons again this reads false and the entry hides — the safe
4611
+ * direction.
4612
+ */
4613
+ function hasModernShell(table$1) {
4614
+ return typeof table$1["IconSettingsOutlineRegular"] === "function";
4615
+ }
4616
+ const HOST_HAS_MODERN_SHELL = hasModernShell(table);
4617
+
4556
4618
  //#endregion
4557
4619
  //#region src/client/disclosure-row.ts
4558
4620
  /**
@@ -4667,7 +4729,8 @@ function parsePresetToolPayload(value) {
4667
4729
  for (const raw of rawPresets) {
4668
4730
  if (!isRecord(raw)) return null;
4669
4731
  const { id, name, description, broken, trust, skills: rawSkills, mcp: rawMcp, systemTools: rawSystem } = raw;
4670
- if (typeof id !== "string" || typeof name !== "string" || trust !== "system" && trust !== "user") return null;
4732
+ if (typeof id !== "string" || typeof name !== "string") return null;
4733
+ if (trust !== void 0 && trust !== "system" && trust !== "user") return null;
4671
4734
  if (!Array.isArray(rawMcp) || !Array.isArray(rawSystem) || !Array.isArray(rawSkills)) return null;
4672
4735
  if (description !== void 0 && typeof description !== "string") return null;
4673
4736
  if (broken !== void 0 && typeof broken !== "string") return null;
@@ -4701,7 +4764,7 @@ function parsePresetToolPayload(value) {
4701
4764
  name,
4702
4765
  ...description === void 0 ? {} : { description },
4703
4766
  ...broken === void 0 ? {} : { broken },
4704
- trust,
4767
+ ...trust === void 0 ? {} : { trust },
4705
4768
  skills,
4706
4769
  mcp,
4707
4770
  systemTools
@@ -4914,6 +4977,7 @@ function PresetToolSection(props) {
4914
4977
  }, []);
4915
4978
  const [query, setQuery] = react.useState("");
4916
4979
  const [expanded, setExpanded] = react.useState({});
4980
+ const [partOpen, setPartOpen] = react.useState({});
4917
4981
  const [kind, setKind] = react.useState("all");
4918
4982
  const [pickerOpen, setPickerOpen] = react.useState(false);
4919
4983
  const [reconnecting, setReconnecting] = react.useState(null);
@@ -5014,7 +5078,7 @@ function PresetToolSection(props) {
5014
5078
  opacity: 0,
5015
5079
  transition: "opacity 0.15s"
5016
5080
  }
5017
- }, react.createElement(__deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 12 })) : null, `${label} (${items.length})`), rule(true)));
5081
+ }, react.createElement(IconFolderClose, { size: 12 })) : null, `${label} (${items.length})`), rule(true)));
5018
5082
  };
5019
5083
  const toggle$1 = (tool, presetId) => switchFor(tool.enabled, tool.reserved === true, tool.reserved === true ? t("preset.reserved", { name: tool.label }) : t(tool.enabled ? "action.disable" : "action.enable", { name: tool.label }), (checked) => {
5020
5084
  setPresetTool(presetId, tool.name, checked);
@@ -5096,18 +5160,29 @@ function PresetToolSection(props) {
5096
5160
  systemTools: selected.systemTools.length
5097
5161
  };
5098
5162
  const groups = [];
5099
- const group = (key, label, rows) => {
5163
+ const group = (key, title, rows, total, shown) => {
5100
5164
  if (kind !== "all" && kind !== key) return;
5101
5165
  if (rows.length === 0) return;
5102
- groups.push(react.createElement("section", {
5166
+ const open = filtering || (partOpen[key] ?? true);
5167
+ groups.push(react.createElement(CollapsibleRoot, {
5103
5168
  key,
5104
- className: "ci-preset-part"
5105
- }, react.createElement("h3", { className: "ci-preset-part-title" }, label), react.createElement("ul", { className: "ci-preset-tool-list" }, ...rows)));
5169
+ className: "ci-preset-part",
5170
+ open,
5171
+ onOpenChange: (next) => {
5172
+ setPartOpen((prev) => ({
5173
+ ...prev,
5174
+ [key]: next
5175
+ }));
5176
+ }
5177
+ }, react.createElement(CollapsibleTrigger, { className: "ci-preset-part-trigger" }, react.createElement("span", {
5178
+ className: "ci-chevron",
5179
+ "aria-hidden": true
5180
+ }, chevronIcon), react.createElement("h3", { className: "ci-preset-part-title" }, title)), react.createElement("p", { className: "ci-preset-part-sub" }, t("group.count", {
5181
+ shown,
5182
+ total
5183
+ })), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...rows))));
5106
5184
  };
5107
- group("skills", t("group.skills", {
5108
- shown: view.skills.length,
5109
- total: totals.skills
5110
- }), groupBy(view.skills, (skill) => skill.group ?? skill.source ?? "unknown").flatMap(([groupKey, items], i) => [sourceDivider(groupKey, items, i === 0), ...items.map((skill) => skillRow(skill, selected.id))]));
5185
+ group("skills", t("tab.skills"), groupBy(view.skills, (skill) => skill.group ?? skill.source ?? "unknown").flatMap(([groupKey, items], i) => [sourceDivider(groupKey, items, i === 0), ...items.map((skill) => skillRow(skill, selected.id))]), totals.skills, view.skills.length);
5111
5186
  const serverRow = (server) => {
5112
5187
  const key = `mcp:${server.server}`;
5113
5188
  const disclosure = resolveDisclosure(expanded[key] === true, filtering);
@@ -5151,16 +5226,10 @@ function PresetToolSection(props) {
5151
5226
  }, react.createElement("span", {
5152
5227
  className: "ci-reconnect-glyph",
5153
5228
  "aria-hidden": true
5154
- }, react.createElement(__deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: 12 })), t("action.reload.label")) : null), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...server.tools.map((tool) => toolRow(tool, selected.id, true))))));
5229
+ }, react.createElement(IconRefresh, { size: 12 })), t("action.reload.label")) : null), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...server.tools.map((tool) => toolRow(tool, selected.id, true))))));
5155
5230
  };
5156
- group("mcp", t("group.mcp", {
5157
- shown: view.mcp.length,
5158
- total: totals.mcp
5159
- }), groupBy(view.mcp, (server) => server.source === void 0 || server.source === "host" ? "host" : `preset:${server.source}`).flatMap(([groupKey, items], i) => [sourceDivider(groupKey, items, i === 0), ...items.map((server) => serverRow(server))]));
5160
- group("system", t("group.system", {
5161
- shown: view.systemTools.length,
5162
- total: totals.systemTools
5163
- }), view.systemTools.map((tool) => toolRow(tool, selected.id, false)));
5231
+ group("mcp", t("tab.mcp"), groupBy(view.mcp, (server) => server.source === void 0 || server.source === "host" ? "host" : `preset:${server.source}`).flatMap(([groupKey, items], i) => [sourceDivider(groupKey, items, i === 0), ...items.map((server) => serverRow(server))]), totals.mcp, view.mcp.length);
5232
+ group("system", t("group.systemTools"), view.systemTools.map((tool) => toolRow(tool, selected.id, false)), totals.systemTools, view.systemTools.length);
5164
5233
  if (groups.length === 0) return react.createElement("p", null, filtering ? t("empty.match") : t("preset.noTools"));
5165
5234
  return react.createElement(react.Fragment, null, ...groups);
5166
5235
  };
@@ -5173,7 +5242,21 @@ function PresetToolSection(props) {
5173
5242
  }, t("status.loading")) : null, state.payload === null ? null : react.createElement(react.Fragment, null, writable ? null : react.createElement("p", {
5174
5243
  role: "note",
5175
5244
  className: "ci-settings-note"
5176
- }, t("preset.readonly")), react.createElement("div", { className: "ci-preset-toolbar" }, react.createElement("span", { className: "ci-preset-picker-label" }, react.createElement("span", null, t("preset.choose")), react.createElement(__deepseek_ai_dsh_client_ui_primitives.Menu, {
5245
+ }, t("preset.readonly")), react.createElement("div", { className: "ci-preset-toolbar" }, react.createElement("div", { className: "ci-search" }, react.createElement(IconSearch, { size: 16 }), react.createElement(Input, {
5246
+ className: "ci-filter ci-preset-filter",
5247
+ value: query,
5248
+ placeholder: t("filter.placeholder"),
5249
+ "aria-label": t("filter.aria"),
5250
+ autoComplete: "off",
5251
+ spellCheck: false,
5252
+ name: "ci-preset-filter",
5253
+ onChange: (event) => {
5254
+ setQuery(event.target.value);
5255
+ },
5256
+ onKeyDown: (event) => {
5257
+ if (event.key === "Escape" && filtering) setQuery("");
5258
+ }
5259
+ })), react.createElement(__deepseek_ai_dsh_client_ui_primitives.Menu, {
5177
5260
  open: pickerOpen,
5178
5261
  anchor: react.createElement("button", {
5179
5262
  type: "button",
@@ -5187,7 +5270,7 @@ function PresetToolSection(props) {
5187
5270
  }, react.createElement("span", { className: "ci-preset-picker-name" }, selected?.name ?? ""), react.createElement("span", {
5188
5271
  className: `ci-preset-picker-chevron${pickerOpen ? " ci-preset-picker-chevron-open" : ""}`,
5189
5272
  "aria-hidden": true
5190
- }, react.createElement(__deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 }))),
5273
+ }, react.createElement(IconChevronDown, { size: 14 }))),
5191
5274
  items: state.payload.presets.map((preset) => ({
5192
5275
  id: preset.id,
5193
5276
  label: preset.name
@@ -5200,43 +5283,58 @@ function PresetToolSection(props) {
5200
5283
  onClose: () => {
5201
5284
  setPickerOpen(false);
5202
5285
  }
5203
- })), react.createElement(Input, {
5204
- className: "ci-filter ci-preset-filter",
5205
- value: query,
5206
- placeholder: t("filter.placeholder"),
5207
- "aria-label": t("filter.aria"),
5208
- autoComplete: "off",
5209
- spellCheck: false,
5210
- name: "ci-preset-filter",
5211
- onChange: (event) => {
5212
- setQuery(event.target.value);
5213
- },
5214
- onKeyDown: (event) => {
5215
- if (event.key === "Escape" && filtering) setQuery("");
5216
- }
5217
- })), selected === void 0 ? null : react.createElement(TabsRoot, {
5218
- value: kind,
5219
- onValueChange: (value) => {
5220
- setKind(value);
5221
- },
5222
- className: "ci-preset-kinds"
5223
- }, react.createElement(TabsList, {
5224
- "aria-label": t("preset.kindAria"),
5225
- className: "ci-tabs"
5226
- }, react.createElement(TabsTab, {
5227
- value: "all",
5228
- className: "ci-tab"
5229
- }, t("tab.all")), react.createElement(TabsTab, {
5230
- value: "skills",
5231
- className: "ci-tab"
5232
- }, `${t("tab.skills")} ${selected.skills.length}`), react.createElement(TabsTab, {
5233
- value: "mcp",
5234
- className: "ci-tab"
5235
- }, `${t("tab.mcp")} ${selected.mcp.length}`), react.createElement(TabsTab, {
5236
- value: "system",
5237
- className: "ci-tab",
5238
- "aria-label": t("tab.system.aria", { count: selected.systemTools.length })
5239
- }, `${t("tab.system")} ${selected.systemTools.length}`))), selected?.description === void 0 ? null : react.createElement("p", { className: "ci-settings-description" }, selected.description), view === null || !filtering ? null : react.createElement("p", {
5286
+ })), selected === void 0 ? null : (() => {
5287
+ const Segmented = __deepseek_ai_dsh_client_ui_primitives.SegmentedControl;
5288
+ if (Segmented !== void 0) return react.createElement(Segmented, {
5289
+ id: "ci-preset-kinds",
5290
+ label: t("preset.kindAria"),
5291
+ value: kind,
5292
+ options: [
5293
+ {
5294
+ value: "all",
5295
+ label: t("tab.all")
5296
+ },
5297
+ {
5298
+ value: "skills",
5299
+ label: `${t("tab.skills")} ${selected.skills.length}`
5300
+ },
5301
+ {
5302
+ value: "mcp",
5303
+ label: `${t("tab.mcp")} ${selected.mcp.length}`
5304
+ },
5305
+ {
5306
+ value: "system",
5307
+ label: `${t("tab.system")} ${selected.systemTools.length}`
5308
+ }
5309
+ ],
5310
+ onChange: (next) => {
5311
+ setKind(next);
5312
+ }
5313
+ });
5314
+ return react.createElement(TabsRoot, {
5315
+ value: kind,
5316
+ onValueChange: (value) => {
5317
+ setKind(value);
5318
+ },
5319
+ className: "ci-preset-kinds"
5320
+ }, react.createElement(TabsList, {
5321
+ "aria-label": t("preset.kindAria"),
5322
+ className: "ci-tabs"
5323
+ }, react.createElement(TabsTab, {
5324
+ value: "all",
5325
+ className: "ci-tab"
5326
+ }, t("tab.all")), react.createElement(TabsTab, {
5327
+ value: "skills",
5328
+ className: "ci-tab"
5329
+ }, `${t("tab.skills")} ${selected.skills.length}`), react.createElement(TabsTab, {
5330
+ value: "mcp",
5331
+ className: "ci-tab"
5332
+ }, `${t("tab.mcp")} ${selected.mcp.length}`), react.createElement(TabsTab, {
5333
+ value: "system",
5334
+ className: "ci-tab",
5335
+ "aria-label": t("tab.system.aria", { count: selected.systemTools.length })
5336
+ }, `${t("tab.system")} ${selected.systemTools.length}`)));
5337
+ })(), selected?.description === void 0 ? null : react.createElement("p", { className: "ci-settings-description" }, selected.description), view === null || !filtering ? null : react.createElement("p", {
5240
5338
  "aria-live": "polite",
5241
5339
  className: "ci-settings-description"
5242
5340
  }, t("filter.count", {
@@ -10924,6 +11022,75 @@ const STATE_ORDER = {
10924
11022
  function sortSkills(skills) {
10925
11023
  return [...skills].sort((a, b) => STATE_ORDER[a.state] - STATE_ORDER[b.state] || a.name.localeCompare(b.name));
10926
11024
  }
11025
+ /**
11026
+ * Platform for the settings shortcut's modifier: the host binds
11027
+ * `settings.open` to Cmd+, on macOS and Ctrl+, elsewhere (the `primary`
11028
+ * modifier in its binding table resolves the same way).
11029
+ */
11030
+ function isMacPlatform() {
11031
+ const platform$2 = navigator.platform ?? "";
11032
+ return platform$2 !== "" ? /mac/i.test(platform$2) : /mac/i.test(navigator.userAgent ?? "");
11033
+ }
11034
+ /**
11035
+ * Open the Settings modal by driving its official keybinding through the input
11036
+ * pipeline. The host's shortcuts service listens for `keydown` on `window`
11037
+ * with no `isTrusted` gate, so a synthesized event is processed exactly like a
11038
+ * physical press — region "page" (no editable/terminal ancestor), no open
11039
+ * shortcut-modal, both of which the `settings.open` command accepts.
11040
+ *
11041
+ * This deliberately uses the input seam, not a host internal: the shortcuts
11042
+ * service is not visible to plugin contexts, and the settings shell exposes no
11043
+ * section deep-link (`openSection` stays internal to the shell). Caveats,
11044
+ * accepted over shipping no entry at all: a user who rebound the settings
11045
+ * shortcut changed what this gesture triggers, and hosts older than 0.1.7 have
11046
+ * no such binding at all — the caller gates the entry on `HOST_HAS_MODERN_SHELL`.
11047
+ */
11048
+ function dispatchOpenSettings() {
11049
+ const mac$1 = isMacPlatform();
11050
+ window.dispatchEvent(new KeyboardEvent("keydown", {
11051
+ code: "Comma",
11052
+ key: ",",
11053
+ metaKey: mac$1,
11054
+ ctrlKey: !mac$1,
11055
+ bubbles: true,
11056
+ cancelable: true
11057
+ }));
11058
+ }
11059
+ /**
11060
+ * Select our own section inside an open Settings dialog by clicking its nav
11061
+ * row — the official user interaction, located through two anchors that cannot
11062
+ * drift with host internals: the dialog's own `data-shortcut-modal="settings"`
11063
+ * attribute (the shortcut system's public hook) and OUR OWN localized section
11064
+ * label as the row's text. Returns false when the row is not (yet) there, so
11065
+ * the caller can retry while the modal mounts.
11066
+ */
11067
+ function selectCapabilitySection(label) {
11068
+ const buttons = document.querySelector("[data-shortcut-modal=\"settings\"]")?.querySelectorAll("nav button") ?? [];
11069
+ for (const button of buttons) if (button.textContent?.trim() === label) {
11070
+ button.click();
11071
+ return true;
11072
+ }
11073
+ return false;
11074
+ }
11075
+ /**
11076
+ * Open Settings ON the capability-panel section. The shell offers no section
11077
+ * deep-link, so this drives the two official gestures in sequence: the
11078
+ * settings.open keybinding (which TOGGLES — skipped when the dialog is already
11079
+ * open, or it would close it), then a nav-row click once the dialog has
11080
+ * mounted. The retry is bounded; if the row never appears the user still lands
11081
+ * on the settings landing page, which is the pre-existing behavior.
11082
+ */
11083
+ function openGlobalSettings(sectionLabel) {
11084
+ close();
11085
+ if (document.querySelector("[data-shortcut-modal=\"settings\"]") === null) dispatchOpenSettings();
11086
+ let attempts = 0;
11087
+ const trySelect = () => {
11088
+ attempts += 1;
11089
+ if (selectCapabilitySection(sectionLabel)) return;
11090
+ if (attempts < 20) requestAnimationFrame(trySelect);
11091
+ };
11092
+ requestAnimationFrame(trySelect);
11093
+ }
10927
11094
  function apply(ctx) {
10928
11095
  const react$1 = react;
10929
11096
  const h = react$1.createElement;
@@ -10946,14 +11113,14 @@ function apply(ctx) {
10946
11113
  };
10947
11114
  }, "capability-panel: stylesheet");
10948
11115
  /** Host iconography: the panel inspects what lands in the session's context. */
10949
- const layersIcon = (size$3) => h(__deepseek_ai_dsh_client_ui_primitives.IconContextInjectionOutline16, { size: size$3 });
11116
+ const layersIcon = (size$3) => h(IconContextInjection, { size: size$3 });
10950
11117
  /** Magnifier sitting inside the filter input. */
10951
- const searchIcon = (size$3) => h(__deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { size: size$3 });
11118
+ const searchIcon = (size$3) => h(IconSearch, { size: size$3 });
10952
11119
  /** Paper plane: the row action lands the command in the composer,
10953
11120
  * ready for the user's own Enter. */
10954
- const insertIcon = (size$3) => h(__deepseek_ai_dsh_client_ui_primitives.IconSendOutline14, { size: size$3 });
11121
+ const insertIcon = (size$3) => h(IconSend, { size: size$3 });
10955
11122
  /** Circular arrows: pull a declared-but-offline server's connection up now. */
10956
- const reconnectIcon = (size$3) => h(__deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: size$3 });
11123
+ const reconnectIcon = (size$3) => h(IconRefresh, { size: size$3 });
10957
11124
  /** The GitHub mark. Not in the host icon set (brand logos are not shipped
10958
11125
  * there), so this one path is inlined for the feedback link's recognizability. */
10959
11126
  const githubIcon = (size$3) => h("svg", {
@@ -11119,7 +11286,7 @@ function apply(ctx) {
11119
11286
  opacity: 0,
11120
11287
  transition: "opacity 0.15s"
11121
11288
  }
11122
- }, h(__deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, { size: 12 })) : null, `${label} (${count})`), rule(true));
11289
+ }, h(IconFolderClose, { size: 12 })) : null, `${label} (${count})`), rule(true));
11123
11290
  };
11124
11291
  /** Group items by source, preserving order within each group. */
11125
11292
  const groupBySource = (items, getSource) => {
@@ -11191,7 +11358,7 @@ function apply(ctx) {
11191
11358
  }
11192
11359
  });
11193
11360
  /** Right chevron the disclosure CSS rotates 90° when expanded. */
11194
- const chevronIcon$1 = h(__deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { size: 12 });
11361
+ const chevronIcon$1 = h(IconChevronRight, { size: 12 });
11195
11362
  const groupLabel = (text, first) => h("div", {
11196
11363
  key: `group:${text}`,
11197
11364
  style: {
@@ -11478,9 +11645,12 @@ function apply(ctx) {
11478
11645
  boxSizing: "border-box",
11479
11646
  width: "480px",
11480
11647
  maxHeight: "min(60vh, var(--available-height, 60vh))",
11481
- overflowY: "auto",
11648
+ display: "flex",
11649
+ flexDirection: "column",
11650
+ overflow: "hidden",
11482
11651
  padding: "10px 12px",
11483
11652
  background: TOK.menuBg,
11653
+ backdropFilter: TOK.menuBlur,
11484
11654
  color: TOK.textSecondary,
11485
11655
  border: `1px solid ${TOK.menuBorder}`,
11486
11656
  borderRadius: "12px",
@@ -11490,7 +11660,14 @@ function apply(ctx) {
11490
11660
  lineHeight: "20px",
11491
11661
  cursor: "default"
11492
11662
  }
11493
- }, h("div", { style: { marginBottom: "6px" } }, h("div", { style: {
11663
+ }, h("div", { style: {
11664
+ flex: "1 1 auto",
11665
+ minHeight: 0,
11666
+ overflowY: "auto",
11667
+ overflowX: "hidden",
11668
+ margin: "0 -12px",
11669
+ padding: "0 12px"
11670
+ } }, h("div", { style: { marginBottom: "6px" } }, h("div", { style: {
11494
11671
  display: "flex",
11495
11672
  alignItems: "center",
11496
11673
  gap: "6px"
@@ -11567,11 +11744,27 @@ function apply(ctx) {
11567
11744
  }, t("filter.count", {
11568
11745
  shown: view?.total ?? 0,
11569
11746
  total: totalAll
11570
- })) : null), ...notices, ...body, h("div", { style: {
11747
+ })) : null), ...notices, ...body), h("div", { style: {
11748
+ flex: "none",
11571
11749
  display: "flex",
11572
- justifyContent: "flex-end",
11573
- marginTop: "10px"
11574
- } }, h("a", {
11750
+ justifyContent: "space-between",
11751
+ alignItems: "center",
11752
+ marginTop: "6px",
11753
+ paddingTop: "8px",
11754
+ borderTop: "0.5px solid var(--dsw-alias-border-l2, rgba(0,0,0,.1))"
11755
+ } }, (() => {
11756
+ return HOST_HAS_MODERN_SHELL ? h("button", {
11757
+ type: "button",
11758
+ className: "ci-feedback-link ci-settings-link",
11759
+ title: t("footer.openSettingsHint"),
11760
+ onClick: () => {
11761
+ openGlobalSettings(t("preset.nav"));
11762
+ }
11763
+ }, h("span", {
11764
+ className: "ci-feedback-icon",
11765
+ "aria-hidden": true
11766
+ }, h(IconSettings, { size: 12 })), t("footer.openSettings")) : h("span");
11767
+ })(), h("a", {
11575
11768
  href: FEEDBACK_URL,
11576
11769
  target: "_blank",
11577
11770
  rel: "noopener noreferrer",