dsh-skill-picker 0.5.6 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,7 +26,7 @@ DSH Web GUI 的技能选择器:在输入框(composer)工具行右侧加一
26
26
 
27
27
  English: A skill picker for the DSH Web GUI — a button in the composer's right tool row opens a searchable list of installed skills; picking one inserts the official `/skill-name` gesture into the draft, so DSH's native user-invocation path loads the skill with your message.
28
28
 
29
- 当前版本:**v0.5.6**(⚡ 面板**置顶分组** + `/` 补全**自动增强补丁** + 拼音搜索)
29
+ 当前版本:**v0.5.7**(⚡ 面板**置顶分组** + `/` 补全**自动增强补丁** + 拼音搜索 + **搜索结果按匹配相关度排序**)
30
30
 
31
31
  ## 为什么用它(vs 官方 `/` 补全)
32
32
 
@@ -124,6 +124,7 @@ DSH 的 [dsh-tool-skill](https://github.com/deepseek-ai/deepseek-harness) 在 `a
124
124
 
125
125
  ## 更新日志
126
126
 
127
+ - **v0.5.7**:**搜索结果按匹配相关度排序**——⚡ 面板与 `/` 补全统一:名字开头匹配 > 名字包含 > 描述 > 拼音,置顶/最近使用只做同级次序;同时过滤掉纯粹"字母分散"的子序列噪音(如搜 `svg` 不再混入 deepseek/openviking 等恰好含 s-v-g 分散字母的技能)。`svg` → svg-diagram 稳居第一
127
128
  - **v0.5.6**:**AI 安装指引升级为「GitHub 直装优先」**——快速安装部分改为给 AI/安装助手的优先级决策树:①要最新版/不确定 → `git+ssh` GitHub 直装(git 依赖拉最新 commit,**天然绕过 npm 24h 门禁,百分百新版**);②要 npm 正式版 → 先 `npm view` 查版本再指定 `@版本` 安装;③**禁止裸名安装**(24h 内会落回旧版)
128
129
  - **v0.5.5**:**安装指引升级(AI 友好)**——README 快速安装改为「先 `npm view dsh-skill-picker version` 查版本号 → 再 `add dsh-skill-picker@版本号` 指定安装」,并给 AI/安装助手显式提示:新版本发布后 **24 小时内裸名安装会被 minimumReleaseAge 门禁拦截并自动落回旧版**,必须指定版本号才能装到最新
129
130
  - **v0.5.4**:**斜杠选技能后 ⚡ 面板同步变「最近使用」**——修复双列表状态不同步:斜杠路径的 usage 记录此前只写 localStorage、面板组件不会刷新(React state 挂载后不再重读),现在 trackPick 写入后会广播 `usage-updated` 事件,⚡ 面板实时重读;面板每次打开时也强制刷新 usage。两条路径的选择现在**双向同步**
package/lib/client.js CHANGED
@@ -25852,6 +25852,16 @@ function skillPinyinText(name, description = "") {
25852
25852
  pinyinCache.set(key, text);
25853
25853
  return text;
25854
25854
  }
25855
+ function matchRank(skill, q) {
25856
+ const name = skill.name.toLowerCase();
25857
+ const desc = String(skill.description ?? "").toLowerCase();
25858
+ const py = skillPinyinText(skill.name, skill.description ?? "").toLowerCase();
25859
+ if (name.startsWith(q)) return 0;
25860
+ if (name.includes(q)) return 1;
25861
+ if (desc.includes(q)) return 2;
25862
+ if (py.includes(q)) return 3;
25863
+ return 4;
25864
+ }
25855
25865
  var buttonStyle = {
25856
25866
  display: "inline-flex",
25857
25867
  alignItems: "center",
@@ -26059,11 +26069,11 @@ function SkillPickerButton(props) {
26059
26069
  }, [open]);
26060
26070
  const groups = groupByPinned(skills ?? [], usage, pinned);
26061
26071
  const flat = groups.flatMap((group) => group.items);
26062
- const filtered = flat.filter((skill) => {
26072
+ const filtered = (() => {
26063
26073
  const q = query.trim().toLowerCase();
26064
- if (q === "") return true;
26065
- return skill.name.toLowerCase().includes(q) || String(skill.description ?? "").toLowerCase().includes(q) || skillPinyinText(skill.name, skill.description ?? "").toLowerCase().includes(q);
26066
- }).slice(0, 60);
26074
+ if (q === "") return flat.slice(0, 60);
26075
+ return flat.map((skill, index) => ({ skill, index, score: matchRank(skill, q) })).filter((x) => x.score < 4).sort((a, b) => a.score - b.score || a.index - b.index).slice(0, 60).map((x) => x.skill);
26076
+ })();
26067
26077
  const showTitles = query.trim() === "" && groups.length > 1;
26068
26078
  const filteredNames = new Set(filtered.map((skill) => skill.name));
26069
26079
  (0, import_react.useEffect)(() => {
@@ -26268,7 +26278,7 @@ function apply(ctx) {
26268
26278
  limit: 30,
26269
26279
  threshold: -1e4
26270
26280
  });
26271
- return results.filter((r) => r.score > 0).map((r) => r.obj.s).sort((a, b) => (rankByName.get(a.name) ?? 0) - (rankByName.get(b.name) ?? 0));
26281
+ return results.filter((r) => r.score > 0).map((r) => r.obj.s).filter((s) => matchRank(s, q) < 4).sort((a, b) => matchRank(a, q) - matchRank(b, q) || (rankByName.get(a.name) ?? 0) - (rankByName.get(b.name) ?? 0));
26272
26282
  };
26273
26283
  window.__dshSkillPickerFuzzy = fuzzyMatch;
26274
26284
  const trackPick = (name) => {