dsh-skill-picker 0.5.25 → 0.5.27

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
@@ -26169,6 +26169,44 @@ async function skillOp(action, payload = {}) {
26169
26169
  return { ok: false, error: String(cause?.message ?? cause) };
26170
26170
  }
26171
26171
  }
26172
+ function focusComposer(from, onlyIfFocused = false) {
26173
+ try {
26174
+ let node = from;
26175
+ for (let depth = 0; depth < 8 && node !== null && node !== void 0; depth += 1) {
26176
+ const editor = typeof node.querySelector === "function" ? node.querySelector('[contenteditable="true"], textarea') : null;
26177
+ if (editor !== null && editor !== void 0) {
26178
+ if (onlyIfFocused && document.activeElement !== editor) return false;
26179
+ if (typeof editor.focus === "function") {
26180
+ try {
26181
+ window.__dshSkillPickerFocusing = Date.now();
26182
+ } catch {
26183
+ }
26184
+ editor.focus();
26185
+ }
26186
+ try {
26187
+ if (editor.isContentEditable === true) {
26188
+ const range = document.createRange();
26189
+ range.selectNodeContents(editor);
26190
+ range.collapse(false);
26191
+ const selection = window.getSelection();
26192
+ if (selection !== null && selection !== void 0) {
26193
+ selection.removeAllRanges();
26194
+ selection.addRange(range);
26195
+ }
26196
+ } else if (typeof editor.setSelectionRange === "function") {
26197
+ const end = String(editor.value ?? "").length;
26198
+ editor.setSelectionRange(end, end);
26199
+ }
26200
+ } catch {
26201
+ }
26202
+ return true;
26203
+ }
26204
+ node = node.parentElement;
26205
+ }
26206
+ } catch {
26207
+ }
26208
+ return false;
26209
+ }
26172
26210
  function isUserFacingSkill(skill) {
26173
26211
  const flag = skill?.userInvocable ?? skill?.invocation?.userInvocable;
26174
26212
  return flag !== false;
@@ -26198,9 +26236,12 @@ function groupByPinned(skills, usage, pinned) {
26198
26236
  else rest.push(skill);
26199
26237
  }
26200
26238
  return [
26201
- { title: "\u{1F4CC} \u7F6E\u9876", items: pinnedList },
26202
- { title: "\u{1F525} \u6700\u8FD1\u4F7F\u7528", items: recent },
26203
- { title: "\u{1F5C2}\uFE0F \u5168\u90E8", items: rest }
26239
+ // Plain titles, no emoji: these are section headings, and DSH's own
26240
+ // headings (侧栏的「工作区」/「会话」) are plain text. 国豪: "加图标,那前面
26241
+ // 一团火,这种图标看着不像 DSH 的风格".
26242
+ { title: "\u7F6E\u9876", items: pinnedList },
26243
+ { title: "\u6700\u8FD1\u4F7F\u7528", items: recent },
26244
+ { title: "\u5168\u90E8", items: rest }
26204
26245
  ].filter((group) => group.items.length > 0);
26205
26246
  }
26206
26247
  var pinyinCache = /* @__PURE__ */ new Map();
@@ -26272,6 +26313,7 @@ var buttonStyle = {
26272
26313
  lineHeight: "1",
26273
26314
  flex: "none"
26274
26315
  };
26316
+ var FONT_FAMILY = 'var(--dsw-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif)';
26275
26317
  var popoverStyle = {
26276
26318
  position: "fixed",
26277
26319
  right: "24px",
@@ -26284,20 +26326,34 @@ var popoverStyle = {
26284
26326
  borderRadius: "12px",
26285
26327
  boxShadow: "0 8px 28px rgba(0,0,0,0.35)",
26286
26328
  overflow: "hidden",
26287
- zIndex: 1e3
26329
+ zIndex: 1e3,
26330
+ fontFamily: FONT_FAMILY,
26331
+ fontSize: "14px",
26332
+ lineHeight: "24px"
26288
26333
  };
26289
26334
  var searchStyle = {
26290
26335
  boxSizing: "border-box",
26291
26336
  width: "calc(100% - 16px)",
26337
+ height: "32px",
26338
+ // The panel is a column flex container with a max-height, so any child that
26339
+ // can shrink will: the field measured 21px instead of the declared height
26340
+ // until this was pinned. The list below is the thing that should scroll.
26341
+ flex: "none",
26292
26342
  margin: "8px",
26293
- padding: "6px 10px",
26294
- border: "1px solid var(--dsw-alias-border-l1, rgba(128,128,128,0.3))",
26343
+ padding: "0 10px",
26344
+ border: "1px solid transparent",
26295
26345
  borderRadius: "8px",
26296
26346
  background: "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.1))",
26297
26347
  color: "var(--dsw-alias-label-primary, #e6ebf2)",
26298
- fontSize: "13px",
26348
+ fontFamily: FONT_FAMILY,
26349
+ fontSize: "14px",
26350
+ lineHeight: "20px",
26299
26351
  outline: "none"
26300
26352
  };
26353
+ var searchFocusStyle = {
26354
+ background: "var(--dsw-alias-interactive-bg-active, var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.16)))",
26355
+ boxShadow: "0 0 0 1px var(--dsw-alias-border-l2, rgba(128,128,128,0.35))"
26356
+ };
26301
26357
  var listStyle = {
26302
26358
  overflowY: "auto",
26303
26359
  flex: "auto",
@@ -26315,15 +26371,22 @@ var itemStyle = {
26315
26371
  background: "transparent",
26316
26372
  color: "var(--dsw-alias-label-primary, #e6ebf2)",
26317
26373
  cursor: "pointer",
26318
- textAlign: "left"
26374
+ textAlign: "left",
26375
+ // Explicit: a bare <button> keeps the browser's own 13.3333px / Arial.
26376
+ fontFamily: FONT_FAMILY,
26377
+ fontSize: "14px",
26378
+ lineHeight: "22px",
26379
+ fontWeight: 400
26319
26380
  };
26320
26381
  var nameStyle = {
26321
- fontFamily: "var(--ds-font-family-code, ui-monospace, monospace)",
26322
- fontSize: "13px",
26323
- fontWeight: 500
26382
+ fontFamily: FONT_FAMILY,
26383
+ fontSize: "14px",
26384
+ fontWeight: 400,
26385
+ lineHeight: "22px"
26324
26386
  };
26325
26387
  var descStyle = {
26326
26388
  color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26389
+ fontFamily: FONT_FAMILY,
26327
26390
  fontSize: "12px",
26328
26391
  lineHeight: "16px",
26329
26392
  overflow: "hidden",
@@ -26334,20 +26397,9 @@ var descStyle = {
26334
26397
  var statusStyle = {
26335
26398
  padding: "12px",
26336
26399
  color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26400
+ fontFamily: FONT_FAMILY,
26337
26401
  fontSize: "13px"
26338
26402
  };
26339
- var actionSpanStyle = {
26340
- flex: "none",
26341
- marginLeft: "6px",
26342
- padding: "2px 4px",
26343
- borderRadius: "6px",
26344
- fontSize: "12px",
26345
- lineHeight: "16px",
26346
- cursor: "pointer",
26347
- color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26348
- opacity: 0.55,
26349
- userSelect: "none"
26350
- };
26351
26403
  var noticeStyle = {
26352
26404
  display: "flex",
26353
26405
  alignItems: "center",
@@ -26366,18 +26418,21 @@ var menuStyle = {
26366
26418
  minWidth: "196px",
26367
26419
  padding: "4px",
26368
26420
  borderRadius: "10px",
26369
- border: "1px solid var(--dsw-alias-border-secondary, rgba(128,128,128,0.24))",
26370
- background: "var(--dsw-alias-bg-elevated, #23262e)",
26421
+ border: "1px solid var(--dsw-alias-border-l1, rgba(128,128,128,0.35))",
26422
+ background: "var(--dsw-specific-tip, #23262e)",
26423
+ backdropFilter: "blur(8px)",
26371
26424
  boxShadow: "0 8px 28px rgba(0,0,0,0.36)",
26372
- color: "var(--dsw-alias-label-primary, #e6e9ef)",
26373
- fontSize: "13px",
26425
+ color: "var(--dsw-alias-label-primary, #e6ebf2)",
26426
+ fontFamily: FONT_FAMILY,
26427
+ fontSize: "14px",
26428
+ lineHeight: "24px",
26374
26429
  userSelect: "none"
26375
26430
  };
26376
26431
  var menuHeaderStyle = {
26377
26432
  padding: "6px 10px 4px",
26378
- fontSize: "11px",
26433
+ fontSize: "12px",
26379
26434
  color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26380
- borderBottom: "1px solid var(--dsw-alias-border-secondary, rgba(128,128,128,0.18))",
26435
+ borderBottom: "1px solid var(--dsw-alias-border-l1, rgba(128,128,128,0.28))",
26381
26436
  marginBottom: "4px",
26382
26437
  overflow: "hidden",
26383
26438
  textOverflow: "ellipsis",
@@ -26389,6 +26444,14 @@ var menuItemStyle = {
26389
26444
  cursor: "pointer",
26390
26445
  whiteSpace: "nowrap"
26391
26446
  };
26447
+ var menuItemHandlers = {
26448
+ onMouseEnter: (event) => {
26449
+ event.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.16))";
26450
+ },
26451
+ onMouseLeave: (event) => {
26452
+ event.currentTarget.style.background = "transparent";
26453
+ }
26454
+ };
26392
26455
  function BoltIcon() {
26393
26456
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", width: "16", height: "16", "aria-hidden": "true", style: { display: "block" }, children: [
26394
26457
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("linearGradient", { id: "dsh-sp-bolt-grad", x1: "0", y1: "0", x2: "0", y2: "1", children: [
@@ -26415,7 +26478,14 @@ function SkillPickerButton(props) {
26415
26478
  const [disabledSkills, setDisabledSkills] = (0, import_react.useState)([]);
26416
26479
  const [busySkill, setBusySkill] = (0, import_react.useState)("");
26417
26480
  const [notice, setNotice] = (0, import_react.useState)(void 0);
26481
+ (0, import_react.useEffect)(() => {
26482
+ if (notice === void 0) return void 0;
26483
+ const timer = window.setTimeout(() => setNotice(void 0), notice.undo === void 0 ? 2600 : 1e4);
26484
+ return () => window.clearTimeout(timer);
26485
+ }, [notice]);
26418
26486
  const [menu, setMenu] = (0, import_react.useState)(void 0);
26487
+ const [view, setView] = (0, import_react.useState)("all");
26488
+ const [searchFocus, setSearchFocus] = (0, import_react.useState)(false);
26419
26489
  const [query, setQuery] = (0, import_react.useState)("");
26420
26490
  const [usage, setUsage] = (0, import_react.useState)(() => loadUsage());
26421
26491
  const [pinned, setPinned] = (0, import_react.useState)(() => loadPinned());
@@ -26470,7 +26540,8 @@ function SkillPickerButton(props) {
26470
26540
  const res = await fetch(`/dsh-skill-picker/skills${cwd}`, { headers: { accept: "application/json" } });
26471
26541
  const json = await res.json();
26472
26542
  if (!json.ok) throw new Error(json.error || "bad response");
26473
- setSkills((Array.isArray(json.skills) ? json.skills : []).filter(isUserFacingSkill));
26543
+ const listed = Array.isArray(json.skills) ? json.skills : [];
26544
+ setSkills(listed.filter((skill) => isUserFacingSkill(skill) && skill.disabled !== true));
26474
26545
  setSource("host");
26475
26546
  } catch (cause) {
26476
26547
  setError(String(cause?.message ?? cause));
@@ -26559,6 +26630,8 @@ function SkillPickerButton(props) {
26559
26630
  }
26560
26631
  void syncSharedState();
26561
26632
  setUsage(loadUsage());
26633
+ setNotice(void 0);
26634
+ setView("all");
26562
26635
  void load();
26563
26636
  void loadDisabled();
26564
26637
  }
@@ -26582,6 +26655,11 @@ function SkillPickerButton(props) {
26582
26655
  saveUsage(nextUsage);
26583
26656
  setOpen(false);
26584
26657
  setQuery("");
26658
+ const from = boxRef.current;
26659
+ window.requestAnimationFrame(() => {
26660
+ focusComposer(from);
26661
+ window.setTimeout(() => focusComposer(from, true), 60);
26662
+ });
26585
26663
  };
26586
26664
  const togglePin = (name) => {
26587
26665
  const next = pinned.includes(name) ? pinned.filter((n) => n !== name) : [...pinned, name];
@@ -26596,7 +26674,12 @@ function SkillPickerButton(props) {
26596
26674
  document.addEventListener("mousedown", onDown);
26597
26675
  return () => document.removeEventListener("mousedown", onDown);
26598
26676
  }, [open]);
26599
- const groups = groupByPinned(skills ?? [], usage, pinned);
26677
+ const disabledNames = new Set(disabledSkills.map((skill) => skill.name));
26678
+ const groups = groupByPinned(
26679
+ (skills ?? []).filter((skill) => !disabledNames.has(skill.name)),
26680
+ usage,
26681
+ pinned
26682
+ );
26600
26683
  const flat = groups.flatMap((group) => group.items);
26601
26684
  const filtered = (() => {
26602
26685
  const q = query.trim().toLowerCase();
@@ -26605,6 +26688,11 @@ function SkillPickerButton(props) {
26605
26688
  })();
26606
26689
  const showTitles = query.trim() === "" && groups.length > 1;
26607
26690
  const filteredNames = new Set(filtered.map((skill) => skill.name));
26691
+ const offFiltered = (() => {
26692
+ const q = query.trim().toLowerCase();
26693
+ if (q === "") return disabledSkills;
26694
+ return disabledSkills.filter((skill) => matchRank(skill, q) < 4);
26695
+ })();
26608
26696
  (0, import_react.useEffect)(() => {
26609
26697
  setActive(0);
26610
26698
  }, [query]);
@@ -26630,291 +26718,277 @@ function SkillPickerButton(props) {
26630
26718
  setOpen(false);
26631
26719
  }
26632
26720
  };
26633
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: boxRef, style: { position: "relative", display: "inline-flex", flex: "none" }, children: [
26634
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26635
- "button",
26636
- {
26637
- type: "button",
26638
- onClick: toggle,
26639
- title: `\u9009\u62E9\u6280\u80FD\uFF08\u63D2\u5165 /\u6280\u80FD\u540D \u5230\u53D1\u9001\u6846\uFF09${source === "host" ? "\u3000\xB7\u3000\u5217\u8868\u6765\u81EA\u672C\u5730\u626B\u63CF" : ""}${slashEnhancementMode() === "runtime" ? "\u3000\xB7\u3000/ \u589E\u5F3A\uFF1A\u8FD0\u884C\u65F6\u63A5\u7BA1" : ""}`,
26640
- "aria-label": "\u9009\u62E9\u6280\u80FD",
26641
- style: {
26642
- ...buttonStyle,
26643
- ...open ? { color: "var(--dsw-alias-label-primary-bluish, #4cc9f0)" } : {}
26644
- },
26645
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BoltIcon, {})
26646
- }
26647
- ),
26648
- open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...popoverStyle, bottom: `${panelBottom}px` }, children: [
26721
+ return (
26722
+ // The marker is how dsh-pocket's mobile "file open guard" learns to leave
26723
+ // this panel alone: its rows are <button>s whose text starts with "/技能名",
26724
+ // which its looksLikeFilePath() reads as a Windows path, so it swallowed the
26725
+ // click and popped "手机上无法直接打开电脑上的文件" (see the pocket patch of
26726
+ // 2026-10-02). Guarded there, marked here.
26727
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: boxRef, "data-dsh-skill-picker": "1", style: { position: "relative", display: "inline-flex", flex: "none" }, children: [
26649
26728
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26650
- "input",
26729
+ "button",
26651
26730
  {
26652
- value: query,
26653
- onChange: (event) => setQuery(event.target.value),
26654
- onKeyDown,
26655
- placeholder: "\u641C\u7D22\u6280\u80FD\u2026\uFF08\u2191\u2193 \u9009\u62E9\uFF0CEnter \u63D2\u5165\uFF09",
26656
- style: searchStyle,
26657
- autoFocus: true
26731
+ type: "button",
26732
+ onClick: toggle,
26733
+ title: `\u9009\u62E9\u6280\u80FD\uFF08\u63D2\u5165 /\u6280\u80FD\u540D \u5230\u53D1\u9001\u6846\uFF09${source === "host" ? "\u3000\xB7\u3000\u5217\u8868\u6765\u81EA\u672C\u5730\u626B\u63CF" : ""}${slashEnhancementMode() === "runtime" ? "\u3000\xB7\u3000/ \u589E\u5F3A\uFF1A\u8FD0\u884C\u65F6\u63A5\u7BA1" : ""}`,
26734
+ "aria-label": "\u9009\u62E9\u6280\u80FD",
26735
+ style: {
26736
+ ...buttonStyle,
26737
+ ...open ? { color: "var(--dsw-alias-label-primary-bluish, #4cc9f0)" } : {}
26738
+ },
26739
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BoltIcon, {})
26658
26740
  }
26659
26741
  ),
26660
- error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: `\u52A0\u8F7D\u5931\u8D25\uFF1A${error}` }) : skills === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: "\u52A0\u8F7D\u4E2D\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
26661
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: listStyle, children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD" }) : (() => {
26662
- let itemIndex = 0;
26663
- const renderItem = (skill, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26664
- "button",
26742
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...popoverStyle, bottom: `${panelBottom}px` }, children: [
26743
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26744
+ "input",
26745
+ {
26746
+ value: query,
26747
+ onChange: (event) => setQuery(event.target.value),
26748
+ onKeyDown,
26749
+ onFocus: () => setSearchFocus(true),
26750
+ onBlur: () => setSearchFocus(false),
26751
+ placeholder: "\u641C\u7D22\u6280\u80FD\u2026\uFF08\u2191\u2193 \u9009\u62E9\uFF0CEnter \u63D2\u5165\uFF09",
26752
+ style: { ...searchStyle, ...searchFocus ? searchFocusStyle : {} },
26753
+ autoFocus: true
26754
+ }
26755
+ ),
26756
+ error !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: `\u52A0\u8F7D\u5931\u8D25\uFF1A${error}` }) : skills === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: "\u52A0\u8F7D\u4E2D\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
26757
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: listStyle, children: view === "off" ? offFiltered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: query.trim() === "" ? "\u6CA1\u6709\u88AB\u5173\u95ED\u7684\u6280\u80FD" : "\u6CA1\u6709\u5339\u914D\u7684\u5DF2\u5173\u95ED\u6280\u80FD" }) : offFiltered.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26758
+ "div",
26665
26759
  {
26666
- type: "button",
26667
- ref: (el) => {
26668
- itemRefs.current[index] = el;
26669
- },
26670
- onClick: () => pick(skill.name),
26671
26760
  onContextMenu: (event) => {
26672
26761
  event.preventDefault();
26673
26762
  event.stopPropagation();
26674
- openMenu(event, skill, false);
26763
+ openMenu(event, skill, true);
26675
26764
  },
26676
26765
  onTouchStart: (event) => {
26677
26766
  const touch = event.touches?.[0];
26678
26767
  if (touch === void 0) return;
26679
26768
  longPressRef.current = window.setTimeout(
26680
- () => openMenu({ clientX: touch.clientX, clientY: touch.clientY }, skill, false),
26769
+ () => openMenu({ clientX: touch.clientX, clientY: touch.clientY }, skill, true),
26681
26770
  500
26682
26771
  );
26683
26772
  },
26684
26773
  onTouchEnd: () => window.clearTimeout(longPressRef.current),
26685
26774
  onTouchMove: () => window.clearTimeout(longPressRef.current),
26686
- onMouseEnter: (event) => {
26687
- setActive(index);
26688
- event.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.12))";
26689
- },
26690
- onMouseLeave: (event) => {
26691
- event.currentTarget.style.background = "transparent";
26775
+ style: { ...itemStyle, flexDirection: "column", alignItems: "flex-start", opacity: 0.6 },
26776
+ children: [
26777
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: nameStyle, children: `/${skill.name}` }),
26778
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: descStyle, children: skill.description ?? "" })
26779
+ ]
26780
+ },
26781
+ `off-${skill.name}`
26782
+ )) : filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: statusStyle, children: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD" }) : (() => {
26783
+ let itemIndex = 0;
26784
+ const renderItem = (skill, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26785
+ "button",
26786
+ {
26787
+ type: "button",
26788
+ ref: (el) => {
26789
+ itemRefs.current[index] = el;
26790
+ },
26791
+ onClick: () => pick(skill.name),
26792
+ onContextMenu: (event) => {
26793
+ event.preventDefault();
26794
+ event.stopPropagation();
26795
+ openMenu(event, skill, false);
26796
+ },
26797
+ onTouchStart: (event) => {
26798
+ const touch = event.touches?.[0];
26799
+ if (touch === void 0) return;
26800
+ longPressRef.current = window.setTimeout(
26801
+ () => openMenu({ clientX: touch.clientX, clientY: touch.clientY }, skill, false),
26802
+ 500
26803
+ );
26804
+ },
26805
+ onTouchEnd: () => window.clearTimeout(longPressRef.current),
26806
+ onTouchMove: () => window.clearTimeout(longPressRef.current),
26807
+ onMouseEnter: (event) => {
26808
+ setActive(index);
26809
+ event.currentTarget.style.background = "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.12))";
26810
+ },
26811
+ onMouseLeave: (event) => {
26812
+ event.currentTarget.style.background = "transparent";
26813
+ },
26814
+ style: {
26815
+ ...itemStyle,
26816
+ flexDirection: "row",
26817
+ alignItems: "center",
26818
+ ...index === active ? { background: "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.12))" } : {}
26819
+ },
26820
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "2px", flex: "1", minWidth: "0" }, children: [
26821
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: nameStyle, children: `/${skill.name}` }),
26822
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: descStyle, children: skill.description ?? "" })
26823
+ ] })
26692
26824
  },
26825
+ skill.name
26826
+ );
26827
+ if (!showTitles) {
26828
+ return filtered.map((skill) => renderItem(skill, itemIndex++));
26829
+ }
26830
+ return groups.map((group) => {
26831
+ const items = group.items.filter((skill) => filteredNames.has(skill.name));
26832
+ if (items.length === 0) return null;
26833
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [
26834
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26835
+ "div",
26836
+ {
26837
+ style: {
26838
+ display: "flex",
26839
+ alignItems: "center",
26840
+ justifyContent: "space-between",
26841
+ padding: "6px 10px 2px",
26842
+ color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26843
+ // Measured against DSH's own sidebar heading
26844
+ // (「工作区」): it is 14px / weight 400 / normal
26845
+ // letter-spacing. Mine had been 11px / 600 / 0.04em,
26846
+ // which is exactly what made it look foreign.
26847
+ fontSize: "14px",
26848
+ fontWeight: 400,
26849
+ letterSpacing: "normal",
26850
+ lineHeight: "24px"
26851
+ },
26852
+ children: [
26853
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: group.title }),
26854
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.7 }, children: items.length })
26855
+ ]
26856
+ }
26857
+ ),
26858
+ items.map((skill) => renderItem(skill, itemIndex++))
26859
+ ] }, group.title);
26860
+ });
26861
+ })() }),
26862
+ notice !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: noticeStyle, children: [
26863
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: "1", color: notice.kind === "err" ? "var(--dsw-alias-label-error, #ff7b72)" : void 0 }, children: notice.text }),
26864
+ typeof notice.undo === "string" && notice.undo !== "" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26865
+ "span",
26866
+ {
26867
+ role: "button",
26868
+ tabIndex: -1,
26869
+ onClick: () => void undoUninstall(notice.undo),
26870
+ style: { cursor: "pointer", textDecoration: "underline", flex: "none" },
26871
+ children: "\u64A4\u56DE"
26872
+ }
26873
+ )
26874
+ ] }),
26875
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26876
+ "div",
26877
+ {
26693
26878
  style: {
26694
- ...itemStyle,
26695
- flexDirection: "row",
26879
+ display: "flex",
26696
26880
  alignItems: "center",
26697
- ...index === active ? { background: "var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,0.12))" } : {}
26881
+ justifyContent: "flex-end",
26882
+ gap: "8px",
26883
+ margin: "0 12px 8px 16px",
26884
+ fontSize: "12px",
26885
+ lineHeight: "18px",
26886
+ color: "var(--dsw-alias-label-tertiary, #8a94a6)"
26698
26887
  },
26699
26888
  children: [
26700
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "2px", flex: "1", minWidth: "0" }, children: [
26701
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: nameStyle, children: `/${skill.name}` }),
26702
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: descStyle, children: skill.description ?? "" })
26703
- ] }),
26889
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { minWidth: "0", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: view === "off" ? "\u53F3\u952E\u53EF\u5F00\u542F \xB7 \u624B\u673A\u957F\u6309" : "\u53F3\u952E\u53EF\u7BA1\u7406 \xB7 \u624B\u673A\u957F\u6309" }),
26704
26890
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26705
26891
  "span",
26706
26892
  {
26707
26893
  role: "button",
26708
26894
  tabIndex: -1,
26709
- title: pinned.includes(skill.name) ? "\u53D6\u6D88\u7F6E\u9876" : "\u7F6E\u9876\u5230\u5217\u8868\u9876\u90E8",
26710
- "aria-label": pinned.includes(skill.name) ? "\u53D6\u6D88\u7F6E\u9876" : "\u7F6E\u9876",
26711
- onClick: (event) => {
26712
- event.stopPropagation();
26713
- togglePin(skill.name);
26895
+ title: view === "off" ? "\u56DE\u5230\u5168\u90E8\u6280\u80FD" : "\u67E5\u770B\u88AB\u5173\u95ED\u7684\u6280\u80FD",
26896
+ onClick: () => {
26897
+ setView(view === "off" ? "all" : "off");
26898
+ setQuery("");
26714
26899
  },
26715
26900
  style: {
26716
26901
  flex: "none",
26717
- marginLeft: "6px",
26718
- padding: "2px 4px",
26719
- borderRadius: "6px",
26720
- fontSize: "12px",
26721
- lineHeight: "16px",
26902
+ marginLeft: "auto",
26903
+ padding: "2px 8px",
26904
+ borderRadius: "999px",
26905
+ border: "1px solid var(--dsw-alias-border-l1, rgba(128,128,128,0.35))",
26722
26906
  cursor: "pointer",
26723
- color: pinned.includes(skill.name) ? "var(--dsw-alias-label-primary-bluish, #4cc9f0)" : "var(--dsw-alias-label-tertiary, #8a94a6)",
26724
- opacity: pinned.includes(skill.name) ? 1 : 0.55,
26725
- userSelect: "none"
26907
+ whiteSpace: "nowrap"
26726
26908
  },
26727
- children: pinned.includes(skill.name) ? "\u{1F4CC}" : "\u{1F4CD}"
26909
+ children: view === "off" ? "\u2190 \u5168\u90E8\u6280\u80FD" : `\u5DF2\u5173\u95ED ${disabledSkills.length}`
26728
26910
  }
26729
26911
  )
26730
26912
  ]
26731
- },
26732
- skill.name
26733
- );
26734
- if (!showTitles) {
26735
- return filtered.map((skill) => renderItem(skill, itemIndex++));
26736
- }
26737
- return groups.map((group) => {
26738
- const items = group.items.filter((skill) => filteredNames.has(skill.name));
26739
- if (items.length === 0) return null;
26740
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [
26741
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26742
- "div",
26743
- {
26744
- style: {
26745
- display: "flex",
26746
- alignItems: "center",
26747
- justifyContent: "space-between",
26748
- padding: "6px 10px 2px",
26749
- color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26750
- fontSize: "11px",
26751
- fontWeight: 600,
26752
- letterSpacing: "0.04em"
26753
- },
26754
- children: [
26755
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: group.title }),
26756
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.7 }, children: items.length })
26757
- ]
26758
- }
26759
- ),
26760
- items.map((skill) => renderItem(skill, itemIndex++))
26761
- ] }, group.title);
26762
- });
26763
- })() }),
26764
- notice !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: noticeStyle, children: [
26765
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { flex: "1", color: notice.kind === "err" ? "var(--dsw-alias-label-error, #ff7b72)" : void 0 }, children: notice.text }),
26766
- typeof notice.undo === "string" && notice.undo !== "" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26767
- "span",
26768
- {
26769
- role: "button",
26770
- tabIndex: -1,
26771
- onClick: () => void undoUninstall(notice.undo),
26772
- style: { cursor: "pointer", textDecoration: "underline", flex: "none" },
26773
- children: "\u64A4\u56DE"
26774
- }
26775
- )
26776
- ] }),
26777
- disabledSkills.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "4px" }, children: [
26778
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26779
- "div",
26780
- {
26781
- style: {
26782
- display: "flex",
26783
- alignItems: "center",
26784
- justifyContent: "space-between",
26785
- padding: "6px 10px 2px",
26786
- color: "var(--dsw-alias-label-tertiary, #8a94a6)",
26787
- fontSize: "11px",
26788
- fontWeight: 600,
26789
- letterSpacing: "0.04em"
26790
- },
26791
- children: [
26792
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u23FB \u5DF2\u5173\u95ED" }),
26793
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.7 }, children: disabledSkills.length })
26794
- ]
26795
26913
  }
26796
26914
  ),
26797
- disabledSkills.map((skill) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26915
+ menu !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26798
26916
  "div",
26799
26917
  {
26800
- onContextMenu: (event) => {
26801
- event.preventDefault();
26802
- event.stopPropagation();
26803
- openMenu(event, skill, true);
26804
- },
26805
- style: {
26806
- ...itemStyle,
26807
- flexDirection: "row",
26808
- alignItems: "center",
26809
- opacity: 0.55
26810
- },
26918
+ style: { ...menuStyle, left: `${menu.x}px`, top: `${menu.y}px` },
26919
+ onPointerDown: (event) => event.stopPropagation(),
26811
26920
  children: [
26812
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: "2px", flex: "1", minWidth: "0" }, children: [
26813
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: nameStyle, children: `/${skill.name}` }),
26814
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: descStyle, children: skill.description ?? "" })
26815
- ] }),
26921
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: menuHeaderStyle, children: `/${menu.skill.name}` }),
26922
+ !menu.disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26923
+ "div",
26924
+ {
26925
+ style: menuItemStyle,
26926
+ role: "button",
26927
+ tabIndex: -1,
26928
+ ...menuItemHandlers,
26929
+ onClick: () => {
26930
+ setMenu(void 0);
26931
+ togglePin(menu.skill.name);
26932
+ },
26933
+ children: pinned.includes(menu.skill.name) ? "\u53D6\u6D88\u7F6E\u9876" : "\u7F6E\u9876\u5230\u9876\u90E8"
26934
+ }
26935
+ ),
26816
26936
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26817
- "span",
26937
+ "div",
26818
26938
  {
26939
+ style: menuItemStyle,
26819
26940
  role: "button",
26820
26941
  tabIndex: -1,
26821
- title: "\u91CD\u65B0\u5F00\u542F\uFF08\u628A SKILL.md.disabled \u6539\u56DE SKILL.md\uFF09",
26822
- "aria-label": "\u91CD\u65B0\u5F00\u542F",
26823
- onClick: () => void runSkillOp("enable", skill),
26824
- style: actionSpanStyle,
26825
- children: busySkill === skill.name ? "\u2026" : "\u23FB \u5F00\u542F"
26942
+ ...menuItemHandlers,
26943
+ onClick: () => {
26944
+ const target = menu.skill;
26945
+ const turningOff = !menu.disabled;
26946
+ setMenu(void 0);
26947
+ void runSkillOp(turningOff ? "disable" : "enable", target);
26948
+ },
26949
+ children: menu.disabled ? "\u5F00\u542F" : "\u5173\u95ED\uFF08agent \u4E5F\u4E0D\u518D\u52A0\u8F7D\uFF09"
26826
26950
  }
26827
26951
  ),
26828
26952
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26829
- "span",
26953
+ "div",
26830
26954
  {
26955
+ style: menuItemStyle,
26831
26956
  role: "button",
26832
26957
  tabIndex: -1,
26833
- title: "\u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u5B9A\u4F4D",
26834
- "aria-label": "\u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u5B9A\u4F4D",
26835
- onClick: () => void runSkillOp("reveal", skill),
26836
- style: actionSpanStyle,
26837
- children: "\u{1F4C2}"
26958
+ ...menuItemHandlers,
26959
+ onClick: () => {
26960
+ const target = menu.skill;
26961
+ setMenu(void 0);
26962
+ void runSkillOp("reveal", target);
26963
+ },
26964
+ children: "\u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u5B9A\u4F4D"
26838
26965
  }
26839
- )
26840
- ]
26841
- },
26842
- `off-${skill.name}`
26843
- ))
26844
- ] }),
26845
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { margin: "0 10px 8px", fontSize: "11px", color: "var(--dsw-alias-label-tertiary, #8a94a6)" }, children: "\u53F3\u952E\u6280\u80FD = \u7F6E\u9876 / \u5173\u95ED / \u5B9A\u4F4D / \u5378\u8F7D\uFF08\u624B\u673A\u957F\u6309\uFF09" }),
26846
- menu !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
26847
- "div",
26848
- {
26849
- style: { ...menuStyle, left: `${menu.x}px`, top: `${menu.y}px` },
26850
- onPointerDown: (event) => event.stopPropagation(),
26851
- children: [
26852
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: menuHeaderStyle, children: `/${menu.skill.name}` }),
26853
- !menu.disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26854
- "div",
26855
- {
26856
- style: menuItemStyle,
26857
- role: "button",
26858
- tabIndex: -1,
26859
- onClick: () => {
26860
- setMenu(void 0);
26861
- togglePin(menu.skill.name);
26862
- },
26863
- children: pinned.includes(menu.skill.name) ? "\u{1F4CC} \u53D6\u6D88\u7F6E\u9876" : "\u{1F4CC} \u7F6E\u9876\u5230\u9876\u90E8"
26864
- }
26865
- ),
26866
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26867
- "div",
26868
- {
26869
- style: menuItemStyle,
26870
- role: "button",
26871
- tabIndex: -1,
26872
- onClick: () => {
26873
- const target = menu.skill;
26874
- const turningOff = !menu.disabled;
26875
- setMenu(void 0);
26876
- void runSkillOp(turningOff ? "disable" : "enable", target);
26877
- },
26878
- children: menu.disabled ? "\u23FB \u5F00\u542F" : "\u23FB \u5173\u95ED\uFF08agent \u4E5F\u4E0D\u518D\u52A0\u8F7D\uFF09"
26879
- }
26880
- ),
26881
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26882
- "div",
26883
- {
26884
- style: menuItemStyle,
26885
- role: "button",
26886
- tabIndex: -1,
26887
- onClick: () => {
26888
- const target = menu.skill;
26889
- setMenu(void 0);
26890
- void runSkillOp("reveal", target);
26891
- },
26892
- children: "\u{1F4C2} \u5728\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u5B9A\u4F4D"
26893
- }
26894
- ),
26895
- !menu.disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26896
- "div",
26897
- {
26898
- style: { ...menuItemStyle, color: "var(--dsw-alias-label-error, #ff7b72)" },
26899
- role: "button",
26900
- tabIndex: -1,
26901
- onClick: () => {
26902
- const target = menu.skill;
26903
- setMenu(void 0);
26904
- if (!window.confirm(`\u5378\u8F7D /${target.name}\uFF1F
26966
+ ),
26967
+ !menu.disabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
26968
+ "div",
26969
+ {
26970
+ style: { ...menuItemStyle, color: "var(--dsw-alias-label-error, #e5534b)" },
26971
+ role: "button",
26972
+ tabIndex: -1,
26973
+ ...menuItemHandlers,
26974
+ onClick: () => {
26975
+ const target = menu.skill;
26976
+ setMenu(void 0);
26977
+ if (!window.confirm(`\u5378\u8F7D /${target.name}\uFF1F
26905
26978
 
26906
26979
  \u5B83\u4F1A\u88AB\u79FB\u8FDB\u5907\u4EFD\u76EE\u5F55\uFF08\u4E0D\u662F\u5220\u9664\uFF09\uFF0C\u9762\u677F\u91CC\u53EF\u4EE5\u64A4\u56DE\u3002`)) return;
26907
- void runSkillOp("uninstall", target);
26908
- },
26909
- children: "\u{1F5D1} \u5378\u8F7D\uFF08\u79FB\u5165\u5907\u4EFD\uFF0C\u53EF\u64A4\u56DE\uFF09"
26910
- }
26911
- )
26912
- ]
26913
- }
26914
- )
26980
+ void runSkillOp("uninstall", target);
26981
+ },
26982
+ children: "\u5378\u8F7D\uFF08\u79FB\u5165\u5907\u4EFD\uFF0C\u53EF\u64A4\u56DE\uFF09"
26983
+ }
26984
+ )
26985
+ ]
26986
+ }
26987
+ )
26988
+ ] })
26915
26989
  ] })
26916
26990
  ] })
26917
- ] });
26991
+ );
26918
26992
  }
26919
26993
  function apply(ctx) {
26920
26994
  void syncSharedState();