dsh-skill-picker 0.5.24 → 0.5.26

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