dsh-plugin 1.2.1 → 1.3.1

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 (96) hide show
  1. package/README.en.md +20 -15
  2. package/README.md +21 -16
  3. package/client/client.js +716 -445
  4. package/client/client.js.map +1 -1
  5. package/cordis.patch.yml +1 -1
  6. package/lib/http/routes.js +47 -3
  7. package/lib/index.js +1 -1
  8. package/lib/services/install/install-types.js +1 -1
  9. package/lib/services/install/npm-check.js +1 -1
  10. package/lib/services/install/npm-resolve.js +1 -1
  11. package/lib/services/install/preflight.js +1 -1
  12. package/lib/services/install/task-queue.js +1 -1
  13. package/lib/services/loader.js +1 -1
  14. package/lib/services/log.js +1 -1
  15. package/lib/services/probe.js +1 -1
  16. package/lib/services/profile/installed-versions.js +1 -1
  17. package/lib/services/profile/profile.js +6 -5
  18. package/lib/services/profile/progress.js +1 -1
  19. package/lib/services/settings.js +1 -1
  20. package/lib/types/index.d.ts +1 -1
  21. package/lib/types/services/install/install-types.d.ts +1 -1
  22. package/lib/types/services/install/install.d.ts +1 -1
  23. package/lib/types/services/profile/pending-restart.d.ts +1 -1
  24. package/lib/types/services/profile/progress.d.ts +1 -1
  25. package/package.json +2 -2
  26. package/src/client/components/PluginHubSection.tsx +98 -17
  27. package/src/client/components/catalog/CatalogList.tsx +1 -1
  28. package/src/client/components/catalog/PluginCard.tsx +1 -1
  29. package/src/client/components/layout/CatalogControls.tsx +1 -1
  30. package/src/client/components/layout/CatalogHeader.tsx +2 -2
  31. package/src/client/components/layout/CategoryTabs.tsx +1 -1
  32. package/src/client/components/layout/SectionTabs.tsx +1 -1
  33. package/src/client/components/modals/AboutModal.tsx +2 -2
  34. package/src/client/components/modals/HubUpdateModal.tsx +1 -1
  35. package/src/client/components/modals/InstalledDetailModal.tsx +1 -1
  36. package/src/client/components/modals/LogsModal.tsx +1 -1
  37. package/src/client/components/modals/LogsPathModal.tsx +1 -1
  38. package/src/client/components/modals/NotificationsModal.tsx +31 -14
  39. package/src/client/components/modals/ProgressView.tsx +1 -1
  40. package/src/client/components/modals/modals.tsx +1 -1
  41. package/src/client/components/ui/Dropdown.tsx +1 -1
  42. package/src/client/components/ui/Toggle.tsx +1 -1
  43. package/src/client/components/ui/icons.tsx +22 -1
  44. package/src/client/components/views/CustomInstallView.tsx +133 -44
  45. package/src/client/components/views/DiagnosticsView.tsx +2 -2
  46. package/src/client/components/views/InstalledView.tsx +1 -1
  47. package/src/client/components/views/LogsView.tsx +1 -1
  48. package/src/client/components/views/MarketView.tsx +1 -1
  49. package/src/client/components/views/SettingsView.tsx +1 -1
  50. package/src/client/data/catalog.ts +1 -1
  51. package/src/client/data/host.ts +1 -1
  52. package/src/client/data/hub.ts +12 -3
  53. package/src/client/hooks/useCatalog.ts +19 -6
  54. package/src/client/hooks/useIncrementalList.ts +1 -1
  55. package/src/client/hooks/useLanguage.ts +1 -1
  56. package/src/client/hooks/useSettings.ts +1 -1
  57. package/src/client/hooks/useTaskQueue.ts +1 -1
  58. package/src/client/index.tsx +1 -1
  59. package/src/client/locales.ts +50 -30
  60. package/src/client/logic/constants.ts +2 -2
  61. package/src/client/logic/failures.ts +48 -2
  62. package/src/client/logic/format.ts +1 -1
  63. package/src/client/logic/install-command.ts +1 -1
  64. package/src/client/logic/installed.ts +41 -2
  65. package/src/client/logic/normalize.ts +1 -1
  66. package/src/client/logic/renderMarkdown.ts +1 -1
  67. package/src/client/logic/urls.ts +2 -2
  68. package/src/client/styles/CustomInstallView.module.css +59 -1
  69. package/src/client/styles/DiagnosticsView.module.css +1 -1
  70. package/src/client/styles/Dropdown.module.css +1 -1
  71. package/src/client/styles/Header.module.css +1 -1
  72. package/src/client/styles/InstalledView.module.css +19 -6
  73. package/src/client/styles/List.module.css +11 -1
  74. package/src/client/styles/LogsView.module.css +1 -1
  75. package/src/client/styles/Modal.module.css +32 -1
  76. package/src/client/styles/SectionTabs.module.css +1 -1
  77. package/src/client/styles/SettingsView.module.css +1 -1
  78. package/src/client/styles/Toggle.module.css +1 -1
  79. package/src/client/styles/tokens.module.css +32 -5
  80. package/src/client/types.ts +1 -1
  81. package/src/server/http/routes.ts +54 -3
  82. package/src/server/index.ts +1 -1
  83. package/src/server/services/install/install-types.ts +1 -1
  84. package/src/server/services/install/install.ts +1 -1
  85. package/src/server/services/install/npm-check.ts +1 -1
  86. package/src/server/services/install/npm-resolve.ts +1 -1
  87. package/src/server/services/install/preflight.ts +1 -1
  88. package/src/server/services/install/task-queue.ts +1 -1
  89. package/src/server/services/loader.ts +1 -1
  90. package/src/server/services/log.ts +1 -1
  91. package/src/server/services/probe.ts +1 -1
  92. package/src/server/services/profile/installed-versions.ts +1 -1
  93. package/src/server/services/profile/pending-restart.ts +1 -1
  94. package/src/server/services/profile/profile.ts +6 -5
  95. package/src/server/services/profile/progress.ts +1 -1
  96. package/src/server/services/settings.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,18 +1,18 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
6
- * zh/en dictionaries for the DSH-Plugin Hub settings section.
6
+ * zh/en dictionaries for the DSH Plugin Hub settings section.
7
7
  */
8
8
  export const zh = {
9
9
  nav: '插件中心',
10
- title: 'DSH-Plugin Hub',
10
+ title: 'DSH Plugin Hub',
11
11
  // 收录/精选数量由组件从官网 /api/stats.json 实时拉取填充({total}/{verified}),不写死
12
- tagline: 'DSH-Plugin 插件中心:面向 DeepSeek Harness 插件收录平台,人工审验、来源可溯,免费安装',
12
+ tagline: 'DSH Plugin 插件中心:面向 DeepSeek Harness 插件收录平台,人工审验、来源可溯,免费安装',
13
13
  adBadge: '推荐',
14
14
  // 紫色广告横幅:突出数量(显眼)+ 更新节奏,与 tagline 职责分开、不重复
15
- ad: 'DSH-Plugin 插件中心:收录 {total} 款插件,{verified} 款人工精选验证,每日更新',
15
+ ad: 'DSH Plugin 插件中心:收录 {total} 款插件,{verified} 款人工精选验证,每日更新',
16
16
  search: '搜索插件名称、描述、标签…',
17
17
  all: '全部',
18
18
  sortStars: 'Star',
@@ -45,25 +45,31 @@ export const zh = {
45
45
  // 已安装视图
46
46
  installedEmpty: '还没有安装插件',
47
47
  installedEmptyDesc: '可以去「自定义安装」,手动安装 NPM 包或 GitHub 源码',
48
- npmInstallLabel: 'NPM 包',
49
- npmInstallPlaceholder: '输入 npm 包名',
50
- npmInstallExample: '例如:lodash、@scope/pkg',
51
- npmInstallInvalid: '请输入 npm 包名,例如:lodash、@scope/pkg',
48
+ npmInstallLabel: 'NPM 包 / 命令',
49
+ npmInstallPlaceholder: 'npm install <包名> 或直接输包名',
50
+ npmInstallExample: '支持原生命令:npm install lodash、npm i lodash、pnpm add @scope/pkg',
51
+ npmInstallExample2: '全局安装 CLI:npm install -g @scope/cli;或直接输入包名 lodash',
52
+ npmInstallInvalid: '请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli)',
52
53
  gitInstallLabel: 'GitHub 源码',
53
54
  gitInstallPlaceholder: '输入仓库地址',
54
55
  gitInstallExample: '例如:owner/repo 或 https://github.com/owner/repo',
55
56
  gitInstallInvalid: '请输入 GitHub 仓库地址,例如:owner/repo 或 https://github.com/owner/repo',
56
57
  dshCmdLabel: 'DeepSeek Harness 命令',
57
- dshCmdPlaceholder: '粘贴安装命令(npm install -g 或 dsh plugin add)',
58
- dshCmdExample: '例如:npm install -g @scope/cli 或 dsh plugin add github:owner/repo',
59
- dshCmdInvalid: '支持 npm install -g <包名> 全局安装,或完整 dsh plugin 命令。例如:npm install -g @scope/cli',
58
+ dshCmdPlaceholder: '粘贴官方 dsh plugin 命令',
59
+ dshCmdExample: '例如:dsh plugin --profile web add github:owner/repo',
60
+ dshCmdInvalid: '请输入官方 dsh plugin 安装命令(--profile 必填)。例如:dsh plugin --profile web add github:owner/repo',
61
+ installHelp: '帮助',
62
+ helpModalTitle: '支持的命令格式',
63
+ npmInstallHelp: 'lodash、@scope/pkg\t直接输入包名\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli\t全局安装 CLI 工具,不进「已安装」列表',
64
+ gitInstallHelp: 'owner/repo\nhttps://github.com/owner/repo\ngithub:owner/repo\ngit+https://github.com/owner/repo.git\ngit@github.com:owner/repo.git',
65
+ dshCmdHelp: 'dsh plugin --profile web add <目标>\ndsh plugin --profile=web add <目标>\n\t--profile 必填,官方 CLI 无 -p 简写;<目标> 可为 npm 包名或 github:owner/repo',
60
66
  globalNpmHint: '将全局安装 CLI 工具(npm install -g),不会出现在「已安装」列表,无需重启宿主',
61
67
  installCliBtn: '安装',
62
68
  // 安装通道关闭(安全信任开关关掉后,对应卡片禁用并引导去设置打开)
63
69
  channelDisabledHint: '该安装通道已关闭,请在「设置 → 安全信任」中打开开关',
64
70
  goToSettings: '前往设置',
65
71
  // 自定义安装视图:独立一级导航,说明文字
66
- customViewDesc: '手动安装目录外的 NPM 包、GitHub 源码,或粘贴官方安装命令(npm install -g / dsh plugin add)。装完的条目会出现在「已安装」列表,并标记为自定义安装。',
72
+ customViewDesc: '手动安装目录外的 NPM 包、GitHub 源码,或粘贴官方 dsh plugin 命令。装完的条目会出现在「已安装」列表,并标记为自定义安装。',
67
73
  customLabel: '自定义安装',
68
74
  installedSearch: '搜索已安装的插件…',
69
75
  installedFilterCatalog: '目录插件',
@@ -193,6 +199,10 @@ export const zh = {
193
199
  updatesFound: '发现 {n} 个插件可更新,已加入通知中心',
194
200
  updateNoticeTitle: '发现新版本',
195
201
  updateNoticeGo: '去更新',
202
+ ignoreUpdateRun: '忽略本次更新',
203
+ ignoreUpdateConfirmTitle: '忽略本次更新?',
204
+ ignoreUpdateConfirmDetail: '忽略后本次版本不再提醒;待插件发布下一个新版本时,会再次通知你。',
205
+ ignoreUpdateConfirm: '确认忽略',
196
206
  uninstall: '卸载',
197
207
  uninstalling: '卸载中…',
198
208
  uninstallTitle: '确认卸载?',
@@ -289,8 +299,8 @@ export const zh = {
289
299
  update: '可更新',
290
300
  updateAvailable: '有更新',
291
301
  updateAvailableHint: '检测到更新:有版本号的仓库比对版本号,无版本号的仓库比对仓库最近更新时间',
292
- hubUpdateHint: '检测到 DSH-Plugin Hub 新版本,点击查看更新内容并更新',
293
- hubUpdateTitle: 'DSH-Plugin Hub 有新版本',
302
+ hubUpdateHint: '检测到 DSH Plugin Hub 新版本,点击查看更新内容并更新',
303
+ hubUpdateTitle: 'DSH Plugin Hub 有新版本',
294
304
  hubUpdateDesc: 'v{version} 已发布,点击下方按钮即可更新,完成后需重启宿主生效。',
295
305
  hubUpdatePublished: '发布于',
296
306
  hubUpdateNotes: '更新记录',
@@ -302,7 +312,7 @@ export const zh = {
302
312
  // 头部「关注我们」弹窗:平台介绍 + 用户反馈群二维码(内容由 Worker /about Markdown 推送,非写死)
303
313
  followUs: '关注我们',
304
314
  aboutTitle: '关注我们',
305
- aboutDesc: '了解 DSH-Plugin Hub 是做什么的,加入用户反馈群随时交流。',
315
+ aboutDesc: '了解 DSH Plugin Hub 是做什么的,加入用户反馈群随时交流。',
306
316
  aboutEmpty: '内容暂未发布,敬请期待。',
307
317
  aboutUpdated: '更新于',
308
318
  empty: '该分类暂无插件',
@@ -311,11 +321,11 @@ export const zh = {
311
321
 
312
322
  export const en = {
313
323
  nav: 'Plugin Hub',
314
- title: 'DSH-Plugin Hub',
324
+ title: 'DSH Plugin Hub',
315
325
  // Plugin counts are filled from the live /api/stats.json ({total}/{verified}), never hardcoded
316
- tagline: 'DSH-Plugin Hub: a human-verified, free marketplace for DeepSeek Harness plugins',
326
+ tagline: 'DSH Plugin Hub: a human-verified, free marketplace for DeepSeek Harness plugins',
317
327
  adBadge: 'Featured',
318
- ad: 'DSH-Plugin Hub: {total} plugins indexed, {verified} human-verified, updated daily',
328
+ ad: 'DSH Plugin Hub: {total} plugins indexed, {verified} human-verified, updated daily',
319
329
  search: 'Search plugins by name, description, tags…',
320
330
  all: 'All',
321
331
  sortStars: 'Stars',
@@ -350,25 +360,31 @@ export const en = {
350
360
  // Installed view
351
361
  installedEmpty: 'No plugins installed yet',
352
362
  installedEmptyDesc: 'Go to Custom to add an npm package or GitHub source manually',
353
- npmInstallLabel: 'npm package',
354
- npmInstallPlaceholder: 'npm package name',
355
- npmInstallExample: 'e.g. lodash or @scope/pkg',
356
- npmInstallInvalid: 'Enter an npm package name, e.g. lodash or @scope/pkg',
363
+ npmInstallLabel: 'npm package / command',
364
+ npmInstallPlaceholder: 'npm install <pkg> or a bare package name',
365
+ npmInstallExample: 'Native commands: npm install lodash, npm i lodash, pnpm add @scope/pkg',
366
+ npmInstallExample2: 'Global CLI: npm install -g @scope/cli; or just type a package name like lodash',
367
+ npmInstallInvalid: 'Enter an npm package name (e.g. lodash, @scope/pkg), or a native install command (e.g. npm install lodash, npm i lodash, pnpm add @scope/pkg, npm install -g @scope/cli)',
357
368
  gitInstallLabel: 'GitHub source',
358
369
  gitInstallPlaceholder: 'Repository address',
359
370
  gitInstallExample: 'e.g. owner/repo or https://github.com/owner/repo',
360
371
  gitInstallInvalid: 'Enter a GitHub repository address, e.g. owner/repo or https://github.com/owner/repo',
361
372
  dshCmdLabel: 'DeepSeek Harness command',
362
- dshCmdPlaceholder: 'Paste an install command (npm install -g or dsh plugin add)',
363
- dshCmdExample: 'e.g. npm install -g @scope/cli or dsh plugin add github:owner/repo',
364
- dshCmdInvalid: 'Paste a global npm install (npm install -g <pkgs>) or a full dsh plugin command, e.g. npm install -g @scope/cli',
373
+ dshCmdPlaceholder: 'Paste an official dsh plugin command',
374
+ dshCmdExample: 'e.g. dsh plugin --profile web add github:owner/repo',
375
+ dshCmdInvalid: 'Paste an official dsh plugin install command (--profile required), e.g. dsh plugin --profile web add github:owner/repo',
376
+ installHelp: 'Help',
377
+ helpModalTitle: 'Supported command formats',
378
+ npmInstallHelp: 'lodash or @scope/pkg\tjust type the package name\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli\tinstalls the CLI globally, not shown in Installed',
379
+ gitInstallHelp: 'owner/repo\nhttps://github.com/owner/repo\ngithub:owner/repo\ngit+https://github.com/owner/repo.git\ngit@github.com:owner/repo.git',
380
+ dshCmdHelp: 'dsh plugin --profile web add <target>\ndsh plugin --profile=web add <target>\n\t--profile is required and there is no -p shorthand; <target> can be an npm package or github:owner/repo',
365
381
  globalNpmHint: 'This installs CLI tools globally (npm install -g). They won\'t appear in Installed and no host restart is needed.',
366
382
  installCliBtn: 'Install',
367
383
  // Install channel disabled (security-trust toggle off → card disabled, guides to settings)
368
384
  channelDisabledHint: 'This install channel is disabled — enable it in Settings → Security & Trust',
369
385
  goToSettings: 'Go to Settings',
370
386
  // Custom install view: standalone top-level section, description text
371
- customViewDesc: 'Manually install an npm package, a GitHub source, or paste an official install command (npm install -g / dsh plugin add). Finished installs appear in Installed, marked as custom.',
387
+ customViewDesc: 'Manually install an npm package, a GitHub source, or paste an official dsh plugin command. Finished installs appear in Installed, marked as custom.',
372
388
  customLabel: 'Custom install',
373
389
  installedSearch: 'Search installed plugins…',
374
390
  installedFilterCatalog: 'Catalog',
@@ -500,6 +516,10 @@ export const en = {
500
516
  updatesFound: '{n} plugin(s) have updates — check the notification center',
501
517
  updateNoticeTitle: 'Update available',
502
518
  updateNoticeGo: 'Update',
519
+ ignoreUpdateRun: 'Ignore this update',
520
+ ignoreUpdateConfirmTitle: 'Ignore this update?',
521
+ ignoreUpdateConfirmDetail: 'This version will no longer notify you. You will be alerted again when the next version is released.',
522
+ ignoreUpdateConfirm: 'Ignore',
503
523
  uninstall: 'Uninstall',
504
524
  uninstalling: 'Removing…',
505
525
  uninstallTitle: 'Confirm uninstall?',
@@ -594,8 +614,8 @@ export const en = {
594
614
  update: 'Update',
595
615
  updateAvailable: 'Update available',
596
616
  updateAvailableHint: 'An update was detected: repos with a release are compared by tag, repos without one by last push time',
597
- hubUpdateHint: 'A new DSH-Plugin Hub version is available — click to view the changelog and update',
598
- hubUpdateTitle: 'A new DSH-Plugin Hub version is available',
617
+ hubUpdateHint: 'A new DSH Plugin Hub version is available — click to view the changelog and update',
618
+ hubUpdateTitle: 'A new DSH Plugin Hub version is available',
599
619
  hubUpdateDesc: 'v{version} has been released — click below to update, then restart the host to apply it.',
600
620
  hubUpdatePublished: 'Published',
601
621
  hubUpdateNotes: "What's new",
@@ -607,7 +627,7 @@ export const en = {
607
627
  // Header "Follow us" modal: platform intro + user feedback group QR (content pushed via Worker /about Markdown)
608
628
  followUs: 'Follow us',
609
629
  aboutTitle: 'Follow us',
610
- aboutDesc: 'Learn what DSH-Plugin Hub does and join our user feedback group.',
630
+ aboutDesc: 'Learn what DSH Plugin Hub does and join our user feedback group.',
611
631
  aboutEmpty: 'Content not published yet — stay tuned.',
612
632
  aboutUpdated: 'Updated',
613
633
  empty: 'No plugins in this category yet',
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -32,7 +32,7 @@ export const HUB_ABOUT_URL = 'https://api.dsh-plugin.org/about.json'
32
32
  declare const __PLUGIN_VERSION__: string
33
33
 
34
34
  /**
35
- * 插件当前版本号,供头部标题展示「DSH-Plugin Hub v0.1.1」。
35
+ * 插件当前版本号,供头部标题展示「DSH Plugin Hub v0.1.1」。
36
36
  * tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;
37
37
  * node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。
38
38
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -84,11 +84,57 @@ export function addSuccess(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' |
84
84
  return addNotification({ ...record, ok: true, message: '' })
85
85
  }
86
86
 
87
- /** 记录一条「发现新版本」更新提醒:成功类轻量记录,携带目录新版本号供通知中心展示。 */
87
+ /** 记录一条「发现新版本」更新提醒:成功类轻量记录,携带目录新版本号供通知中心展示。
88
+ * 同一插件同一新版本已在通知中心时跳过:宿主重载会重新触发启动检查,不更新时
89
+ * 通知里已有的提醒保持单条,不重复追加。 */
88
90
  export function addUpdateNotice(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' | 'message'>): NotificationRecord[] {
91
+ const prev = loadNotifications()
92
+ const dup = prev.some((r) =>
93
+ r.kind === 'update' && r.repo === record.repo && (r.version ?? undefined) === (record.version ?? undefined))
94
+ if (dup) return prev
89
95
  return addNotification({ ...record, ok: true, message: '' })
90
96
  }
91
97
 
98
+ /** 已忽略的更新提醒持久化 key:`owner/repo@version` 字符串数组。 */
99
+ const IGNORE_KEY = 'gro.ngilp-hsd.ignored-updates'
100
+
101
+ /** 读取已忽略的更新提醒(`owner/repo@version` 字符串集合);损坏/不可用时返回空集合。 */
102
+ export function loadIgnoredUpdates(): Set<string> {
103
+ try {
104
+ const raw = storage()?.getItem(IGNORE_KEY)
105
+ if (!raw) return new Set()
106
+ const list = JSON.parse(raw) as unknown
107
+ if (!Array.isArray(list)) return new Set()
108
+ return new Set(list.filter((x): x is string => typeof x === 'string'))
109
+ } catch {
110
+ return new Set()
111
+ }
112
+ }
113
+
114
+ function saveIgnoredUpdates(ignored: Set<string>): void {
115
+ try {
116
+ storage()?.setItem(IGNORE_KEY, JSON.stringify([...ignored]))
117
+ } catch {
118
+ /* storage full / unavailable:仅保留内存态 */
119
+ }
120
+ }
121
+
122
+ /** 忽略某插件本次更新(repo+version 持久化入忽略集):本次版本不再提醒,直到下一个新版本发布。 */
123
+ export function ignoreUpdate(repo: string, version?: string): Set<string> {
124
+ const next = loadIgnoredUpdates()
125
+ next.add(`${repo}@${version ?? ''}`)
126
+ saveIgnoredUpdates(next)
127
+ return next
128
+ }
129
+
130
+ /** 移除某插件某版本的更新提醒记录(忽略本次更新时一并清理通知),返回更新后的列表。 */
131
+ export function removeUpdateNotice(repo: string, version?: string): NotificationRecord[] {
132
+ const next = loadNotifications().filter((r) =>
133
+ !(r.kind === 'update' && r.repo === repo && (r.version ?? undefined) === (version ?? undefined)))
134
+ save(next)
135
+ return next
136
+ }
137
+
92
138
  /** 清空全部通知记录,返回空列表。 */
93
139
  export function clearNotifications(): NotificationRecord[] {
94
140
  save([])
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -116,6 +116,40 @@ function isRepoLike(value: string): boolean {
116
116
  return /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/.test(value)
117
117
  }
118
118
 
119
+ /**
120
+ * 提 Issue 的仓库身份解析:失败目标可能是 owner/repo 也可能是 npm 包名(含 @scope/pkg、
121
+ * 可带 @version,如 dsh-plugin、@scope/pkg@1.2.3)。
122
+ * - 目标本身就能解析出 owner/repo → 直接用;
123
+ * - npm 包名 → 反查仓库身份:先查已安装表(该包名的条目若带仓库身份即命中),再查目录插件
124
+ * (source.npmPackage 与包名一致,取目录收录的仓库身份)。
125
+ * 反查到才返回,查不到返回 null —— 调用方据此不显示「一键提 Issue」按钮,避免把 Issue
126
+ * 提到错误的地址(别人发的 npm 包名不是 GitHub 仓库,直接拼 github.com/<包名> 是打不开的)。
127
+ */
128
+ export function issueRepoOf(
129
+ target: string,
130
+ installedItems: InstalledItem[],
131
+ plugins: HubPlugin[] | null,
132
+ ): string | null {
133
+ const input = target.trim()
134
+ if (!input) return null
135
+ const parsed = repoFromInstallTarget(input)
136
+ if (isRepoLike(parsed)) return parsed
137
+ const pkg = parsed.replace(/@[^@]*$/, '').toLowerCase()
138
+ // 已安装表:包名命中的条目(目录收录条目直接带仓库身份;自定义安装按 github: spec 解析)
139
+ for (const item of installedItems) {
140
+ if (item.name.toLowerCase() !== pkg) continue
141
+ if (item.repo) return item.repo
142
+ const repo = repoFromInstallTarget(item.spec)
143
+ if (isRepoLike(repo)) return repo
144
+ }
145
+ // 目录插件:npmPackage 与包名一致 → 用目录收录的仓库身份
146
+ for (const p of plugins ?? []) {
147
+ const pkgName = (p.source?.npmPackage ?? '').trim()
148
+ if (pkgName !== '' && pkgName.toLowerCase() === pkg && p.source?.repo) return p.source.repo
149
+ }
150
+ return null
151
+ }
152
+
119
153
  /** 已安装项 → 弹窗可用的伪插件对象:卸载确认弹窗只读名称/来源行,
120
154
  * 自定义安装(目录外)没有完整目录数据,用它把 InstalledItem 适配成 HubPlugin。 */
121
155
  export function pluginOfItem(item: InstalledItem): HubPlugin {
@@ -139,7 +173,12 @@ function isHubSelf(name: string, spec: string): boolean {
139
173
  if (name !== 'dsh-plugin') return false
140
174
  if (spec.startsWith('file:') || spec.startsWith('link:')) return true
141
175
  const repo = repoFromInstallTarget(spec)
142
- return isRepoLike(repo) && repo.toLowerCase() === HUB_REPO.toLowerCase()
176
+ if (isRepoLike(repo) && repo.toLowerCase() === HUB_REPO.toLowerCase()) return true
177
+ // npm 通道覆盖重装 hub 自身后,file:/link: 本地链接会被替换成 registry 版本号/范围
178
+ // (如 1.3.0、^1.3.0)——依赖 key `dsh-plugin` 在 npm 上唯一属于本插件(不存在第三方
179
+ // 同名包),版本号形态与仓库身份同样视为 hub 自身:命令窗口「自己装自己」成功后,
180
+ // 条目仍不进已安装列表(卸载接口对它的 400 拒绝是服务端最后一道防线)。
181
+ return !isRepoLike(repo)
143
182
  }
144
183
 
145
184
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
+ * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
3
3
  * Website: https://dsh-plugin.org
4
4
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
5
5
  *
@@ -64,7 +64,7 @@ export function pluginIssueUrl(repo: string, message: string, env?: EnvInfo | nu
64
64
  ...(code ? [`- Key error: \`${code}\``] : []),
65
65
  '',
66
66
  // 来源说明:标题(链官网)+ 一句来源(链仓库)+ 实际执行的安装命令(含 --profile)与执行结果,链接由常量动态拼接
67
- `## [DSH-Plugin 插件中心](${SITE_URL}) · 安装 Plugin 失败错误信息`,
67
+ `## [DSH Plugin 插件中心](${SITE_URL}) · 安装 Plugin 失败错误信息`,
68
68
  `本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件中心的安装程序自动生成,随本次安装失败一并提交。`,
69
69
  `- 实际执行的安装命令:\`${command ?? `dsh plugin${env?.profile ? ` --profile ${env.profile}` : ''} add git+https://github.com/${repo}.git`}\``,
70
70
  `- 执行结果:安装失败,未能安装该插件。`,
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -59,6 +59,31 @@
59
59
  color: var(--hub-text-primary);
60
60
  }
61
61
 
62
+ /* 卡片标题旁的帮助按钮:小号问号圆钮,弱化但可点,hover 提亮成品牌蓝 */
63
+ .installHelpBtn {
64
+ flex-shrink: 0;
65
+ margin-left: 6px;
66
+ display: inline-flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ width: 18px;
70
+ height: 18px;
71
+ padding: 0;
72
+ color: var(--hub-text-tertiary);
73
+ background: transparent;
74
+ border: 1px solid transparent;
75
+ border-radius: 50%;
76
+ cursor: pointer;
77
+ user-select: none;
78
+ transition: color 120ms ease, background 120ms ease, border-color 120ms ease;
79
+ }
80
+
81
+ .installHelpBtn:hover {
82
+ color: var(--hub-brand);
83
+ background: var(--hub-brand-tint);
84
+ border-color: var(--hub-brand-border-soft);
85
+ }
86
+
62
87
  /* 文本框上方的示例:灰字小字,告诉用户该通道的推荐写法 */
63
88
  .installExample {
64
89
  font-size: 11px;
@@ -189,3 +214,36 @@
189
214
  border-radius: 6px;
190
215
  padding: 5px 8px;
191
216
  }
217
+
218
+ /* —— 帮助弹窗内容:该通道支持的格式清单(命令 + 说明) —— */
219
+ .helpBody {
220
+ display: flex;
221
+ flex-direction: column;
222
+ gap: 7px;
223
+ padding: 4px 2px;
224
+ }
225
+
226
+ .helpLine {
227
+ display: flex;
228
+ align-items: baseline;
229
+ gap: 12px;
230
+ min-width: 0;
231
+ font-size: 12px;
232
+ line-height: 20px;
233
+ }
234
+
235
+ /* 命令/格式部分:等宽字体主文字色,不换行 —— 弹窗够宽,长格式也整行展示 */
236
+ .helpCmd {
237
+ flex-shrink: 0;
238
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
239
+ font-size: 11px;
240
+ color: var(--hub-text-primary);
241
+ white-space: nowrap;
242
+ }
243
+
244
+ /* 说明部分:灰字小号,跟在命令后面 */
245
+ .helpNote {
246
+ min-width: 0;
247
+ font-size: 11px;
248
+ color: var(--hub-text-tertiary);
249
+ }
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -262,8 +262,9 @@
262
262
  font-size: 11px;
263
263
  line-height: 16px;
264
264
  font-weight: 500;
265
- color: var(--hub-brand);
266
- background: var(--hub-brand-tint-strong);
265
+ color: var(--hub-warn);
266
+ background: var(--hub-warn-tint);
267
+ border: 1px solid var(--hub-warn-border);
267
268
  border-radius: 4px;
268
269
  padding: 0 5px;
269
270
  }
@@ -405,14 +406,14 @@
405
406
  border-color: var(--hub-warning);
406
407
  }
407
408
 
408
- /* 更新:品牌色实底小按钮,仅在「有更新」时出现 */
409
+ /* 更新:琥珀色实底小按钮(与插件中心「可更新」同色),仅在「有更新」时出现 */
409
410
  .rowUpdate {
410
411
  font-family: inherit;
411
412
  font-size: 12px;
412
413
  line-height: 18px;
413
414
  font-weight: 500;
414
415
  color: #fff;
415
- background: var(--hub-brand);
416
+ background: var(--hub-warn);
416
417
  border: none;
417
418
  border-radius: 6px;
418
419
  padding: 3px 10px;
@@ -422,7 +423,7 @@
422
423
  }
423
424
 
424
425
  .rowUpdate:hover {
425
- background: var(--hub-brand-hover);
426
+ background: var(--hub-warn-strong);
426
427
  }
427
428
 
428
429
  /* 卸载:危险色描边小按钮 */
@@ -445,3 +446,15 @@
445
446
  background: var(--hub-danger);
446
447
  border-color: var(--hub-danger);
447
448
  }
449
+
450
+ /* 夜间模式:卸载按钮直接红底白字(破坏性操作醒目化,无需 hover 才转实底) */
451
+ body[data-ds-dark-theme] .rowUninstall {
452
+ color: #fff;
453
+ background: var(--hub-danger);
454
+ border-color: var(--hub-danger);
455
+ }
456
+
457
+ body[data-ds-dark-theme] .rowUninstall:hover {
458
+ background: var(--hub-danger-hover);
459
+ border-color: var(--hub-danger-hover);
460
+ }
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -220,6 +220,16 @@
220
220
  background: var(--hub-danger-hover);
221
221
  }
222
222
 
223
+ /* 夜间模式:卸载按钮直接红底白字(破坏性操作醒目化,无需 hover 才转实底) */
224
+ body[data-ds-dark-theme] .uninstallBtn {
225
+ color: #ffffff;
226
+ background: var(--hub-danger);
227
+ }
228
+
229
+ body[data-ds-dark-theme] .uninstallBtn:hover {
230
+ background: var(--hub-danger-hover);
231
+ }
232
+
223
233
  .installBtn {
224
234
  color: var(--hub-text-on-fill);
225
235
  background: var(--hub-btn-fill);
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -52,6 +52,13 @@
52
52
  max-width: calc(100vw - 48px);
53
53
  }
54
54
 
55
+ /* 自定义安装「帮助」弹窗:比错误弹窗更宽 —— 命令格式 + 中文说明要排在一行,
56
+ 窄了容易折行,宽窗让每条格式整行展示 */
57
+ .helpModal {
58
+ width: 720px;
59
+ max-width: calc(100vw - 48px);
60
+ }
61
+
55
62
  /* 系统日志查看器弹窗:比错误弹窗更宽 —— 日志行带时间/级别/类别/事件/描述,
56
63
  加上筛选栏与底部操作栏后需要横向空间,窄了长行容易折行。
57
64
  高度固定(540px,小视口才让位给窗口上限):内容多寡不再让弹窗忽高忽低 */
@@ -999,6 +1006,30 @@
999
1006
  background: var(--hub-brand-hover);
1000
1007
  }
1001
1008
 
1009
+ /* 更新提醒:行尾「忽略本次更新」小按钮(中性描边,弱于实底的「去更新」),
1010
+ hover 转红提示可忽略本次版本 */
1011
+ .noticeIgnore {
1012
+ flex-shrink: 0;
1013
+ margin-left: 2px;
1014
+ font-size: 11px;
1015
+ line-height: 16px;
1016
+ font-weight: 500;
1017
+ color: var(--hub-text-secondary);
1018
+ background: transparent;
1019
+ border: 1px solid var(--hub-border-2);
1020
+ border-radius: 5px;
1021
+ padding: 1px 8px;
1022
+ cursor: pointer;
1023
+ user-select: none;
1024
+ transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
1025
+ }
1026
+
1027
+ .noticeIgnore:hover {
1028
+ color: var(--hub-danger-text);
1029
+ border-color: var(--hub-danger-border);
1030
+ background: var(--hub-danger-tint);
1031
+ }
1032
+
1002
1033
  /* 操作类型徽标:安装失败红 / 卸载失败黄 */
1003
1034
  .failKind {
1004
1035
  flex-shrink: 0;
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *
@@ -1,4 +1,4 @@
1
- /* DSH-Plugin Hub — the community plugin marketplace for DeepSeek Harness.
1
+ /* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
2
2
  * Website: https://dsh-plugin.org
3
3
  * GitHub: https://github.com/dshplugin/dsh-plugin-hub
4
4
  *