@morehao/dsh-skills-console 0.3.3 → 0.3.5

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/client.js +36 -57
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -37,6 +37,7 @@ DSH(DeepSeek Harness)的**技能控制台**:装、更新、删除、接入
37
37
  - **两个入口**:默认在「设置 → 技能控制台」;页头 ⚙ 里可切到左侧栏独立面板,切换立即生效。
38
38
  - **一页两 tab**:已安装 / 订阅。页头右侧是「自动接入」(多选 Agent)与「添加技能 / 添加订阅」。
39
39
  - **每行五个动作**:开关(启停)、查看、更新、接入设置、删除;窄面板下隐藏「查看」,技能名本身仍是入口。状态标签覆盖最新 / 可更新 / 本地已改 / 上游已移除 / 软链断裂 / 无上游等。
40
+ - **窄面板不跳版**:页头动作恒在右上角,只有面板窄到 520px 以下才上下堆叠;列表按面板自身宽度在 860px 处切两列;页面预留滚动条槽位,滚动条出现/消失、切 tab、窗口微调都不会让整页翻面。
40
41
  - **Agent 多了不挤**:每行最多展示 3 个,其余折成 `+n`,悬浮或聚焦即可看全。
41
42
  - **找得到**:支持按名称 / 来源 / Agent 搜索,按「可更新 / 待检查 / 已停用」筛选,平铺或按 Agent 分组。
42
43
  - **待检查 vs 无上游**:「待检查」只表示*这次*没拿到上游结论(限流、网络、仓库 404 等);再次点「检查更新」时,如果上次没有结论、上游又只回了 304,会无视 ETag 完整重读一次树,不会把「待检查」永久粘住。没有可用订阅来源的技能标「无上游」——它们无法参与更新检查,不计入待检查。
package/client.js CHANGED
@@ -99,9 +99,6 @@ var DICT = {
99
99
  "view.agent": "按 Agent",
100
100
  autoLink: "自动接入",
101
101
  "settings.title": "插件设置",
102
- "id.copy": "复制安装标识",
103
- "id.copied": "已复制安装标识",
104
- "id.copyFailed": "复制失败,请重试",
105
102
  "placement.label": "侧边栏入口",
106
103
  "placement.effect": "切换后立即生效",
107
104
  "placement.on": "已开启",
@@ -289,9 +286,6 @@ var DICT = {
289
286
  "view.agent": "By agent",
290
287
  "autoLink": "Auto-link",
291
288
  "settings.title": "Plugin settings",
292
- "id.copy": "Copy install specifier",
293
- "id.copied": "Install specifier copied",
294
- "id.copyFailed": "Copy failed, please retry",
295
289
  "placement.label": "Sidebar entry",
296
290
  "placement.effect": "Applies immediately",
297
291
  "placement.on": "on",
@@ -452,17 +446,6 @@ var DICT = {
452
446
  "viewer.info.none": "None"
453
447
  }
454
448
  };
455
- async function copyText(text) {
456
- const value = String(text ?? "");
457
- if (!value) return false;
458
- try {
459
- if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) return false;
460
- await navigator.clipboard.writeText(value);
461
- return true;
462
- } catch {
463
- return false;
464
- }
465
- }
466
449
  function buildTranslate(locale) {
467
450
  const active = () => {
468
451
  try {
@@ -832,37 +815,40 @@ var import_react5 = __toESM(require("react"), 1);
832
815
 
833
816
  // client/styles.js
834
817
  var CSS = `
835
- /* 主面板形态:与 DSH 自带管理页同一边距/滚动方式 */
818
+ /* 主面板形态:与 DSH 自带管理页同一边距/滚动方式。
819
+ scrollbar-gutter: stable 让滚动条出现/消失都不改变内容宽度——否则列表一长出来,
820
+ 内容就窄 5~15px,贴着断点的布局会整页跳一次。 */
836
821
  .dshsc-page { box-sizing: border-box; width: 100%; height: 100%; overflow: auto;
822
+ scrollbar-gutter: stable;
837
823
  padding: calc(28px + var(--dsh-frame-top-clearance, 0px)) clamp(24px, 4vw, 48px) 48px; }
838
824
  .dshsc-page .dshsc-root { max-width: 980px; margin: 0 auto; }
839
825
  .dshsc-page .dshsc-title { font-size: 20px; font-weight: 500; line-height: 28px; }
840
826
  .dshsc-page .dshsc-sub { font-size: 13px; line-height: 20px; }
841
827
  .dshsc-root { display: flex; flex-direction: column; gap: 14px; color: var(--dsw-alias-label-primary);
842
828
  container-type: inline-size; container-name: dshsc; }
843
- .dshsc-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
844
- .dshsc-heading { display: flex; align-items: flex-start; gap: 10px; min-width: 0; flex: 1; }
829
+ /* 页头两列:左边标题块、右边业务动作。动作组恒在右上角,宽度自动;
830
+ 页面宽度变化只让标题块收窄(身份胶囊省略、工具组内部换行),动作组不会整组跳到第二行。
831
+ 只有面板真的窄(≤520,见下面容器查询)才改成上下两段。 */
832
+ .dshsc-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 14px; }
833
+ .dshsc-heading { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
845
834
  .dshsc-heading-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
846
835
  .dshsc-logo { flex: none; display: block; border-radius: 8px; }
847
- .dshsc-title { font-size: 17px; font-weight: 600; letter-spacing: -.01em; margin: 0; }
836
+ /* 标题不参与收窄:窄面板里让身份胶囊先省略,标题本身不折行 */
837
+ .dshsc-title { font-size: 17px; font-weight: 600; letter-spacing: -.01em; margin: 0; flex: none; white-space: nowrap; }
848
838
  .dshsc-sub { font-size: 12px; line-height: 1.55; color: var(--dsw-alias-label-secondary); margin: 0; max-width: 64ch; }
849
839
  .dshsc-spacer { flex: 1; }
850
- .dshsc-head-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-left: auto; }
851
- .dshsc-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
840
+ .dshsc-head-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }
841
+ /* 标题行恒为一行:身份胶囊按剩余宽度省略,工具组不被挤走。
842
+ 不用 wrap 是因为一 wrap 就会按「身份胶囊整段」的宽度断行,窄面板里会折成 2~3 行、
843
+ 把页头撑高;省略号 + title 提示比整行折行更稳,也不随版本号变长而改变布局。 */
844
+ .dshsc-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; min-width: 0; }
852
845
 
853
- /* 身份:按「安装时输入的包名」显示(@scope/name@version),等宽 + 可点复制 */
854
- .dshsc-id { display: inline-flex; align-items: center; gap: 5px; box-sizing: border-box; min-width: 0;
855
- max-width: 100%; height: 22px; padding: 0 6px 0 7px; border: 1px solid var(--dsw-alias-border-l1);
856
- border-radius: 6px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-tertiary);
846
+ /* 身份:按「安装时输入的包名」显示(@scope/name@version),等宽只读、不描边 */
847
+ .dshsc-id { display: inline-flex; align-items: center; box-sizing: border-box; min-width: 0;
848
+ max-width: 100%; height: 22px; padding: 0 2px; color: var(--dsw-alias-label-tertiary);
857
849
  font-family: var(--ds-font-family-code, ui-monospace, SFMono-Regular, Menlo, monospace);
858
- font-size: 11px; line-height: 1; white-space: nowrap; cursor: pointer;
859
- transition: background .12s ease, border-color .12s ease, color .12s ease; }
860
- .dshsc-id:hover { border-color: var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2);
861
- color: var(--dsw-alias-label-primary); }
862
- .dshsc-id:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 1px; }
850
+ font-size: 11px; line-height: 1; white-space: nowrap; }
863
851
  .dshsc-spec { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
864
- .dshsc-idcopy { display: inline-flex; flex: none; opacity: .5; transition: opacity .12s ease; }
865
- .dshsc-id:hover .dshsc-idcopy, .dshsc-id:focus-visible .dshsc-idcopy { opacity: 1; }
866
852
 
867
853
  /* 插件级工具(设置 / GitHub):跟在身份胶囊后面,用细线分组;鬼影按钮不和业务按钮抢权重 */
868
854
  .dshsc-tools { display: inline-flex; align-items: center; gap: 2px; flex: none; margin-left: 2px;
@@ -1084,9 +1070,10 @@ var CSS = `
1084
1070
  .dshsc-sub-entry .dshsc-actions { margin-left: auto; display: flex; justify-content: flex-end; }
1085
1071
  .dshsc-sub-entry .dshsc-btn { height: 24px; padding: 0 9px; font-size: 11.5px; }
1086
1072
  /* 设置页的真实宽度常常远小于窗口(侧栏 + 页面缩放),视口 media query 不可靠;
1087
- 以 .dshsc-root 自身宽度为准,窄面板时切两列,避免固定列把 Agent 标签挤成竖排。 */
1088
- @container dshsc (max-width: 900px) {
1089
- .dshsc-head-actions { width: 100%; justify-content: flex-end; }
1073
+ 以 .dshsc-root 自身宽度为准,窄面板时切两列,避免固定列把 Agent 标签挤成竖排。
1074
+ 断点取 860 而不是贴着面板常见的 ~900:三列网格需要 300 + 268 + 2×14 gap + 中间列,
1075
+ 860 已经够用;留出 ~40px 余量后,滚动条(5~15px)、窗口微调、页面缩放都不会把整页翻面。 */
1076
+ @container dshsc (max-width: 860px) {
1090
1077
  .dshsc-search input { width: 180px; }
1091
1078
  .dshsc-row { grid-template-columns: minmax(0, 1fr) 196px; row-gap: 3px; padding: 9px 12px; }
1092
1079
  .dshsc-cell { grid-column: 1; }
@@ -1094,8 +1081,11 @@ var CSS = `
1094
1081
  .dshsc-row .dshsc-actions { grid-column: 2; grid-row: 1 / span 2; }
1095
1082
  .dshsc-row .dshsc-btn { padding: 0 5px; }
1096
1083
  }
1097
- /* 窄面板里工具组会换到下一行,行首的分割线就没有意义了 */
1084
+ /* 页头自己的断点,和上面的页面断点解耦:只有面板窄到放不下「标题块 + 动作组」才上下堆叠。
1085
+ 520 远低于设置面板/侧栏面板的实际宽度,正常窗口里页头永远是右上角那一组。 */
1098
1086
  @container dshsc (max-width: 520px) {
1087
+ .dshsc-head { grid-template-columns: minmax(0, 1fr); }
1088
+ .dshsc-head-actions { justify-content: flex-end; }
1099
1089
  .dshsc-tools { border-left: 0; padding-left: 0; margin-left: 0; }
1100
1090
  }
1101
1091
  .dshsc-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; }
@@ -1371,7 +1361,8 @@ var CSS = `
1371
1361
  .dshsc-reader-page .dshsc-md { max-width: 720px; }
1372
1362
  .dshsc-reader-page .dshsc-reader-actions { border-radius: 0 0 12px 12px; }
1373
1363
 
1374
- @container dshsc (max-width: 900px) {
1364
+ /* 与列表同一个页面断点(860):窄面板里行内「查看」让位、整页目录收起 */
1365
+ @container dshsc (max-width: 860px) {
1375
1366
  /* 行内「查看」先让位:技能名本身仍是入口 */
1376
1367
  .dshsc-row .dshsc-view { display: none; }
1377
1368
  .dshsc-reader-layout { grid-template-columns: minmax(0, 1fr); }
@@ -1781,14 +1772,9 @@ function Header({
1781
1772
  onChangePlacement,
1782
1773
  onOpenAutoLink,
1783
1774
  onAddSkill,
1784
- onAddSubscription,
1785
- onToast
1775
+ onAddSubscription
1786
1776
  }) {
1787
1777
  const spec = installSpec(plugin);
1788
- async function copySpec() {
1789
- const ok = await copyText(spec);
1790
- onToast?.(ok ? { kind: "ok", text: t("id.copied") } : { kind: "err", text: t("id.copyFailed") });
1791
- }
1792
1778
  const headTools = h(
1793
1779
  "div",
1794
1780
  { className: "dshsc-tools" },
@@ -1861,17 +1847,11 @@ function Header({
1861
1847
  { className: "dshsc-title-row" },
1862
1848
  h("h2", { className: "dshsc-title" }, page ? t("page.title") : t("section.title")),
1863
1849
  // 身份:按「安装时输入的包名」显示,点一下整段复制(Host 从 package.json 注入)
1850
+ // 身份:按「安装时输入的包名」显示,只读展示(Host 从 package.json 注入)
1864
1851
  spec ? h(
1865
- "button",
1866
- {
1867
- type: "button",
1868
- className: "dshsc-id",
1869
- title: `${t("id.copy")}:${spec}`,
1870
- "aria-label": `${t("id.copy")}:${spec}`,
1871
- onClick: () => void copySpec()
1872
- },
1873
- h("span", { className: "dshsc-spec" }, spec),
1874
- h("span", { className: "dshsc-idcopy", "aria-hidden": "true" }, h(CopyIcon, { size: 11 }))
1852
+ "span",
1853
+ { className: "dshsc-id", title: spec },
1854
+ h("span", { className: "dshsc-spec" }, spec)
1875
1855
  ) : null,
1876
1856
  headTools
1877
1857
  ),
@@ -3999,8 +3979,7 @@ function Section({ t, page = false, pickDirectory, onPlacementChange }) {
3999
3979
  onChangePlacement: (next) => void changePlacement(next),
4000
3980
  onOpenAutoLink: () => setModal({ type: "autolink" }),
4001
3981
  onAddSkill: actions.requestAddSkill,
4002
- onAddSubscription: actions.requestAddSubscription,
4003
- onToast: (next) => setToast(next)
3982
+ onAddSubscription: actions.requestAddSubscription
4004
3983
  }),
4005
3984
  error ? h("div", { className: "dshsc-banner err" }, `${error} · `, h("button", { className: "dshsc-btn ghost", onClick: () => void reload() }, t("action.retry"))) : null,
4006
3985
  data?.readOnly ? h("div", { className: "dshsc-banner warn" }, t("banner.readonly")) : null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morehao/dsh-skills-console",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "统一管理本地技能的安装、更新、删除与接入,让同一份技能在多个 Agent 间复用。A skill manager for DeepSeek Harness: install, update, remove, link and toggle agent skills.",
5
5
  "license": "MIT",
6
6
  "author": "morehao <morehao@qq.com>",