dsh-plugin 2.3.1 → 2.3.3

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 (84) hide show
  1. package/README.en.md +15 -21
  2. package/README.md +15 -21
  3. package/client/client.js +412 -382
  4. package/client/client.js.map +1 -1
  5. package/lib/http/catalog.js +4 -4
  6. package/lib/http/diagnostics.js +4 -4
  7. package/lib/http/install.js +21 -10
  8. package/lib/http/npm-release-age.js +9 -3
  9. package/lib/http/shared.js +1 -1
  10. package/lib/services/host-version.js +2 -2
  11. package/lib/services/install/dsh-compat.js +1 -1
  12. package/lib/services/install/npm-resolve.js +1 -1
  13. package/lib/services/install/operation-log.js +3 -3
  14. package/lib/services/install/preflight.js +1 -1
  15. package/lib/services/install/registry-fallback.js +3 -3
  16. package/lib/services/install/release-target.js +2 -2
  17. package/lib/services/install/task-queue.js +35 -20
  18. package/lib/services/loader.js +8 -8
  19. package/lib/services/npm-release-age.js +46 -9
  20. package/lib/services/probe.js +12 -12
  21. package/lib/services/profile/installed-versions.js +2 -2
  22. package/lib/services/profile/profile.js +2 -2
  23. package/lib/types/services/host-version.d.ts +1 -1
  24. package/lib/types/services/install/install-types.d.ts +5 -5
  25. package/lib/types/services/install/operation-log.d.ts +1 -1
  26. package/lib/types/services/install/preflight.d.ts +1 -1
  27. package/lib/types/services/install/registry-fallback.d.ts +1 -1
  28. package/lib/types/services/install/release-target.d.ts +1 -1
  29. package/lib/types/services/install/task-queue.d.ts +10 -7
  30. package/lib/types/services/loader.d.ts +5 -5
  31. package/lib/types/services/npm-release-age.d.ts +14 -2
  32. package/lib/types/services/probe.d.ts +4 -4
  33. package/package.json +1 -1
  34. package/src/client/components/PluginHubSection.tsx +59 -28
  35. package/src/client/components/catalog/CatalogList.tsx +1 -1
  36. package/src/client/components/catalog/PluginCard.tsx +3 -3
  37. package/src/client/components/modals/AboutModal.tsx +2 -2
  38. package/src/client/components/modals/ConfirmDialog.tsx +2 -2
  39. package/src/client/components/modals/HubUpdateModal.tsx +3 -3
  40. package/src/client/components/modals/InstalledDetailModal.tsx +1 -1
  41. package/src/client/components/modals/LogsPathModal.tsx +1 -1
  42. package/src/client/components/modals/NotificationsModal.tsx +2 -2
  43. package/src/client/components/modals/modals.tsx +13 -11
  44. package/src/client/components/views/CustomInstallView.tsx +2 -2
  45. package/src/client/components/views/InstalledView.tsx +2 -2
  46. package/src/client/components/views/SettingsView.tsx +3 -3
  47. package/src/client/data/catalog.ts +1 -1
  48. package/src/client/data/host.ts +3 -1
  49. package/src/client/data/hub.ts +3 -3
  50. package/src/client/hooks/useCatalog.ts +14 -14
  51. package/src/client/hooks/useSettings.ts +2 -2
  52. package/src/client/hooks/useTaskQueue.ts +31 -24
  53. package/src/client/locales.ts +21 -21
  54. package/src/client/logic/constants.ts +1 -1
  55. package/src/client/logic/ensure-plugin-css.ts +2 -2
  56. package/src/client/logic/failures.ts +9 -9
  57. package/src/client/logic/install-command.ts +5 -3
  58. package/src/client/logic/installed.ts +1 -1
  59. package/src/client/logic/release-age.ts +10 -10
  60. package/src/client/logic/urls.ts +3 -3
  61. package/src/client/styles/Header.module.css +1 -1
  62. package/src/client/styles/Modal.module.css +2 -2
  63. package/src/client/styles/SectionTabs.module.css +1 -1
  64. package/src/client/styles/tokens.module.css +1 -1
  65. package/src/client/types.ts +4 -4
  66. package/src/server/http/catalog.ts +4 -4
  67. package/src/server/http/diagnostics.ts +4 -4
  68. package/src/server/http/install.ts +20 -10
  69. package/src/server/http/npm-release-age.ts +9 -3
  70. package/src/server/http/shared.ts +1 -1
  71. package/src/server/services/host-version.ts +2 -2
  72. package/src/server/services/install/dsh-compat.ts +1 -1
  73. package/src/server/services/install/install-types.ts +5 -5
  74. package/src/server/services/install/npm-resolve.ts +1 -1
  75. package/src/server/services/install/operation-log.ts +3 -3
  76. package/src/server/services/install/preflight.ts +1 -1
  77. package/src/server/services/install/registry-fallback.ts +3 -3
  78. package/src/server/services/install/release-target.ts +2 -2
  79. package/src/server/services/install/task-queue.ts +40 -26
  80. package/src/server/services/loader.ts +10 -10
  81. package/src/server/services/npm-release-age.ts +50 -10
  82. package/src/server/services/probe.ts +12 -12
  83. package/src/server/services/profile/installed-versions.ts +2 -2
  84. package/src/server/services/profile/profile.ts +2 -2
package/client/client.js CHANGED
@@ -57,7 +57,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
57
57
  npmInstallPlaceholder: "npm install <包名> 或直接输包名",
58
58
  npmInstallExample: "支持原生命令:npm install lodash、npm i lodash、pnpm add @scope/pkg",
59
59
  npmInstallExample2: "全局安装 CLI:npm install -g @scope/cli;或直接输入包名 lodash",
60
- npmInstallInvalid: "请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli)",
60
+ npmInstallInvalid: "请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli);不支持 GitHub 源码地址,请改用该插件的 npm 包名",
61
61
  installHelp: "帮助",
62
62
  helpModalTitle: "支持的命令格式",
63
63
  npmInstallHelp: "lodash、@scope/pkg 直接输入包名\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli 全局安装 CLI 工具,不进「已安装」列表",
@@ -361,7 +361,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
361
361
  failKind_pluginMissingDep: "插件依赖未发布",
362
362
  failReason_pluginMissingDep: "插件声明依赖的包在官方 npm 源上不存在(已删除或从未发布)。",
363
363
  failKind_registryVersionStale: "该版本在所用源上不存在",
364
- failReason_registryVersionStale: "实际安装用的源还没同步到这个版本,或版本号写错。",
364
+ failReason_registryVersionStale: "实际安装用的源还没同步到这个版本。可稍后重试,或到「设置 → npm 镜像源」换成官方源;也可先安装上一个可用版本。",
365
365
  failKind_registryAuth: "npm 源拒绝了访问",
366
366
  failReason_registryAuth: "registry 返回 401/403:这个源需要登录凭据,或当前网络不被允许。",
367
367
  failKind_profileExclusive: "profile 由桌面应用独占管理",
@@ -442,7 +442,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
442
442
  updateAvailable: "有更新",
443
443
  updateAvailableHint: "检测到更新:有版本号的仓库比对版本号,无版本号的仓库比对仓库最近更新时间",
444
444
  updatePending: "暂缓到 {time} 后可更新",
445
- updatePendingHint: "新版本发布未满 24 小时,pnpm 供应链门禁会拦下;到时间后再更新即可",
445
+ updatePendingHint: "新版本发布还不满 24 小时,pnpm 暂时不让安装;到时间后再更新即可",
446
446
  hubUpdateHint: "检测到 DSH Plugin Hub 新版本,点击查看更新内容并更新",
447
447
  hubUpdateTitle: "DSH Plugin Hub 有新版本",
448
448
  hubUpdateDesc: "点击下方按钮即可更新,完成后需重启宿主生效。",
@@ -455,10 +455,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
455
455
  hubVersionStateAvailable: "可更新",
456
456
  hubVersionStatePending: "暂缓提示",
457
457
  close: "关闭",
458
- hubPendingDesc: "最新版已发布,但发布尚未满 24 小时:此时更新会被 pnpm 静默回退到旧版本,因此暂不提示。稍后这里会自动出现更新入口。",
458
+ hubPendingDesc: "最新版已发布,但发布尚未满 24 小时:此时更新会被 pnpm 不提示地回退到旧版本,因此暂不提示。稍后这里会自动出现更新入口。",
459
459
  followUs: "关注我们",
460
460
  aboutTitle: "关注我们",
461
- aboutDesc: "了解 DSH Plugin Hub 是做什么的,加入用户反馈群随时交流。",
461
+ aboutDesc: "了解 DSH Plugin Hub 是做什么的,访问主站浏览插件,或到 GitHub 提交 Issue。",
462
462
  aboutEmpty: "内容暂未发布,敬请期待。",
463
463
  aboutUpdated: "更新于",
464
464
  empty: "该分类暂无插件",
@@ -508,7 +508,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
508
508
  npmInstallPlaceholder: "npm install <pkg> or a bare package name",
509
509
  npmInstallExample: "Native commands: npm install lodash, npm i lodash, pnpm add @scope/pkg",
510
510
  npmInstallExample2: "Global CLI: npm install -g @scope/cli; or just type a package name like lodash",
511
- 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)",
511
+ 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); GitHub source URLs are not supported — use the plugin's npm package name instead",
512
512
  installHelp: "Help",
513
513
  helpModalTitle: "Supported command formats",
514
514
  npmInstallHelp: "lodash or @scope/pkg just type the package name\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli installs the CLI globally, not shown in Installed",
@@ -812,7 +812,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
812
812
  failKind_pluginMissingDep: "plugin dependency is not published",
813
813
  failReason_pluginMissingDep: "A package the plugin depends on does not exist on the official npm registry.",
814
814
  failKind_registryVersionStale: "this version is not available on the registry in use",
815
- failReason_registryVersionStale: "The registry that actually performs the install has not synced this version yet, or the version is mistyped.",
815
+ failReason_registryVersionStale: "The registry that actually performs the install has not synced this version yet. Retry later, switch to the official registry under Settings → npm mirror, or install a previous version for now.",
816
816
  failKind_registryAuth: "the npm registry rejected access",
817
817
  failReason_registryAuth: "The registry returned 401/403: it needs credentials, or the current network is not allowed.",
818
818
  failKind_profileExclusive: "the profile is managed only by the desktop app",
@@ -909,7 +909,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
909
909
  hubPendingDesc: "The latest version has been released, but it is still within the 24-hour window where pnpm silently falls back to the older version, so the update is not offered yet. The update entry will appear here shortly.",
910
910
  followUs: "Follow us",
911
911
  aboutTitle: "Follow us",
912
- aboutDesc: "Learn what DSH Plugin Hub does and join our user feedback group.",
912
+ aboutDesc: "Learn what DSH Plugin Hub does — browse plugins on the website, or open an Issue on GitHub.",
913
913
  aboutEmpty: "Content not published yet — stay tuned.",
914
914
  aboutUpdated: "Updated",
915
915
  empty: "No plugins in this category yet",
@@ -932,42 +932,42 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
932
932
  css: css$11
933
933
  });
934
934
  var Header_module_css_default = {
935
- "langBtn": "qikqja_langBtn",
935
+ "taglineLink": "qikqja_taglineLink",
936
+ "adBadge": "qikqja_adBadge",
936
937
  "tabs": "qikqja_tabs",
937
- "tabsRow": "qikqja_tabsRow",
938
- "tagline": "qikqja_tagline",
939
- "tabActive": "qikqja_tabActive",
938
+ "tab": "qikqja_tab",
939
+ "headerTitleRow": "qikqja_headerTitleRow",
940
940
  "headerRight": "qikqja_headerRight",
941
- "aboutBtn": "qikqja_aboutBtn",
942
- "segBtn": "qikqja_segBtn",
943
- "versionBtn": "qikqja_versionBtn",
944
- "brandTitle": "qikqja_brandTitle",
941
+ "hubUpdateBadge": "qikqja_hubUpdateBadge",
942
+ "githubLink": "qikqja_githubLink",
945
943
  "title": "qikqja_title",
946
- "version": "qikqja_version",
947
- "header": "qikqja_header",
948
- "copyIcon": "qikqja_copyIcon",
949
- "segGroup": "qikqja_segGroup",
944
+ "langBtn": "qikqja_langBtn",
945
+ "brandTitle": "qikqja_brandTitle",
950
946
  "resultSeg": "qikqja_resultSeg",
951
- "adArrow": "qikqja_adArrow",
952
- "adText": "qikqja_adText",
947
+ "copyIcon": "qikqja_copyIcon",
948
+ "segBtnActive": "qikqja_segBtnActive",
953
949
  "adBanner": "qikqja_adBanner",
954
- "tabCount": "qikqja_tabCount",
955
- "taglineLink": "qikqja_taglineLink",
956
- "root": "qikqja_root",
957
- "logoIcon": "qikqja_logoIcon",
958
- "hubUpdateBadge": "qikqja_hubUpdateBadge",
959
- "headerTitleRow": "qikqja_headerTitleRow",
950
+ "tabsRow": "qikqja_tabsRow",
960
951
  "controls": "qikqja_controls",
952
+ "tabActive": "qikqja_tabActive",
953
+ "sortGroup": "qikqja_sortGroup",
954
+ "githubIcon": "qikqja_githubIcon",
961
955
  "segLabel": "qikqja_segLabel",
956
+ "versionBtn": "qikqja_versionBtn",
957
+ "root": "qikqja_root",
958
+ "searchRow": "qikqja_searchRow",
959
+ "header": "qikqja_header",
960
+ "version": "qikqja_version",
961
+ "adArrow": "qikqja_adArrow",
962
+ "aboutBtn": "qikqja_aboutBtn",
962
963
  "resultCount": "qikqja_resultCount",
963
- "segBtnActive": "qikqja_segBtnActive",
964
- "adBadge": "qikqja_adBadge",
964
+ "segGroup": "qikqja_segGroup",
965
+ "logoIcon": "qikqja_logoIcon",
966
+ "segBtn": "qikqja_segBtn",
967
+ "adText": "qikqja_adText",
968
+ "tagline": "qikqja_tagline",
965
969
  "search": "qikqja_search",
966
- "githubIcon": "qikqja_githubIcon",
967
- "githubLink": "qikqja_githubLink",
968
- "sortGroup": "qikqja_sortGroup",
969
- "tab": "qikqja_tab",
970
- "searchRow": "qikqja_searchRow"
970
+ "tabCount": "qikqja_tabCount"
971
971
  };
972
972
  //#endregion
973
973
  //#region \0dsh-css:src/client/styles/Modal.module.css.mjs
@@ -986,151 +986,151 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
986
986
  css: css$10
987
987
  });
988
988
  var Modal_module_css_default = {
989
- "hubVersionNumber": "BiQ1zG_hubVersionNumber",
990
- "detailPathText": "BiQ1zG_detailPathText",
991
- "queueRowTarget": "BiQ1zG_queueRowTarget",
992
- "modalTitleQueued": "BiQ1zG_modalTitleQueued",
993
- "queueRowHead": "BiQ1zG_queueRowHead",
989
+ "restartNowWarning": "BiQ1zG_restartNowWarning",
990
+ "detailPathBtn": "BiQ1zG_detailPathBtn",
991
+ "hubStatePending": "BiQ1zG_hubStatePending",
992
+ "toastFail": "BiQ1zG_toastFail",
993
+ "noticeTextFail": "BiQ1zG_noticeTextFail",
994
+ "resultTitle": "BiQ1zG_resultTitle",
995
+ "noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
996
+ "failBigIssue": "BiQ1zG_failBigIssue",
997
+ "queueRowBody": "BiQ1zG_queueRowBody",
998
+ "failMisjudgeLink": "BiQ1zG_failMisjudgeLink",
999
+ "progress": "BiQ1zG_progress",
1000
+ "detailArrow": "BiQ1zG_detailArrow",
1001
+ "helpModal": "BiQ1zG_helpModal",
1002
+ "modalLabel": "BiQ1zG_modalLabel",
1003
+ "trustHint": "BiQ1zG_trustHint",
1004
+ "resultCheckIcon": "BiQ1zG_resultCheckIcon",
1005
+ "failReason": "BiQ1zG_failReason",
1006
+ "failCopy": "BiQ1zG_failCopy",
1007
+ "noticeBadgeFail": "BiQ1zG_noticeBadgeFail",
994
1008
  "noticeMain": "BiQ1zG_noticeMain",
995
- "dangerConfirm": "BiQ1zG_dangerConfirm",
996
- "logModal": "BiQ1zG_logModal",
997
1009
  "modalIn": "BiQ1zG_modalIn",
998
- "failClear": "BiQ1zG_failClear",
999
- "failReason": "BiQ1zG_failReason",
1000
- "failEmpty": "BiQ1zG_failEmpty",
1001
- "detailMono": "BiQ1zG_detailMono",
1002
- "hubUpdateModal": "BiQ1zG_hubUpdateModal",
1003
- "failList": "BiQ1zG_failList",
1010
+ "detailValue": "BiQ1zG_detailValue",
1011
+ "cliOnlyHint": "BiQ1zG_cliOnlyHint",
1012
+ "bundleDeselectedHint": "BiQ1zG_bundleDeselectedHint",
1013
+ "detailStatusText": "BiQ1zG_detailStatusText",
1014
+ "queueSection": "BiQ1zG_queueSection",
1004
1015
  "modalClose": "BiQ1zG_modalClose",
1005
- "noticeList": "BiQ1zG_noticeList",
1006
- "queuedHint": "BiQ1zG_queuedHint",
1007
- "uninstallConfirm": "BiQ1zG_uninstallConfirm",
1008
- "hubVersionBar": "BiQ1zG_hubVersionBar",
1009
- "failRepo": "BiQ1zG_failRepo",
1010
- "queueRowBody": "BiQ1zG_queueRowBody",
1011
- "failKindInstall": "BiQ1zG_failKindInstall",
1012
- "modal": "BiQ1zG_modal",
1016
+ "modalRow": "BiQ1zG_modalRow",
1017
+ "hubStateChip": "BiQ1zG_hubStateChip",
1018
+ "detailMono": "BiQ1zG_detailMono",
1019
+ "detailStatusRunning": "BiQ1zG_detailStatusRunning",
1020
+ "errorModal": "BiQ1zG_errorModal",
1021
+ "modalWide": "BiQ1zG_modalWide",
1022
+ "modalCloseIcon": "BiQ1zG_modalCloseIcon",
1023
+ "noticeVersion": "BiQ1zG_noticeVersion",
1024
+ "failNetworkTarget": "BiQ1zG_failNetworkTarget",
1025
+ "errorTitle": "BiQ1zG_errorTitle",
1026
+ "logModal": "BiQ1zG_logModal",
1027
+ "resultCheck": "BiQ1zG_resultCheck",
1028
+ "resultRestarting": "BiQ1zG_resultRestarting",
1029
+ "queueRowHead": "BiQ1zG_queueRowHead",
1030
+ "failRepoUrl": "BiQ1zG_failRepoUrl",
1031
+ "detailPathText": "BiQ1zG_detailPathText",
1032
+ "progressFillFail": "BiQ1zG_progressFillFail",
1033
+ "detailDim": "BiQ1zG_detailDim",
1034
+ "queueRowTrack": "BiQ1zG_queueRowTrack",
1035
+ "failedCopyHint": "BiQ1zG_failedCopyHint",
1036
+ "modalBody": "BiQ1zG_modalBody",
1037
+ "modalDesc": "BiQ1zG_modalDesc",
1038
+ "noticeRow": "BiQ1zG_noticeRow",
1039
+ "modalCancel": "BiQ1zG_modalCancel",
1040
+ "modalLink": "BiQ1zG_modalLink",
1041
+ "confirmIcon": "BiQ1zG_confirmIcon",
1042
+ "progressText": "BiQ1zG_progressText",
1043
+ "noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
1044
+ "noticeTextOk": "BiQ1zG_noticeTextOk",
1045
+ "detailStars": "BiQ1zG_detailStars",
1046
+ "dangerConfirm": "BiQ1zG_dangerConfirm",
1047
+ "queueRow": "BiQ1zG_queueRow",
1048
+ "noticeRowOk": "BiQ1zG_noticeRowOk",
1049
+ "confirmIconDanger": "BiQ1zG_confirmIconDanger",
1050
+ "failKind": "BiQ1zG_failKind",
1051
+ "errorBox": "BiQ1zG_errorBox",
1013
1052
  "confirmPrimary": "BiQ1zG_confirmPrimary",
1014
- "noticeRemove": "BiQ1zG_noticeRemove",
1053
+ "progressTrack": "BiQ1zG_progressTrack",
1054
+ "hubVersionDate": "BiQ1zG_hubVersionDate",
1055
+ "failEmpty": "BiQ1zG_failEmpty",
1056
+ "queueRowTarget": "BiQ1zG_queueRowTarget",
1057
+ "errorCopySoft": "BiQ1zG_errorCopySoft",
1058
+ "modalTitle": "BiQ1zG_modalTitle",
1059
+ "detailLink": "BiQ1zG_detailLink",
1060
+ "noticeTime": "BiQ1zG_noticeTime",
1061
+ "detailStatusPending": "BiQ1zG_detailStatusPending",
1062
+ "progressFill": "BiQ1zG_progressFill",
1063
+ "failRepo": "BiQ1zG_failRepo",
1064
+ "confirmIconWrap": "BiQ1zG_confirmIconWrap",
1015
1065
  "queueRowPct": "BiQ1zG_queueRowPct",
1016
1066
  "failRepoLabel": "BiQ1zG_failRepoLabel",
1017
- "failCopy": "BiQ1zG_failCopy",
1018
- "hubStatePending": "BiQ1zG_hubStatePending",
1019
- "noticeRowOk": "BiQ1zG_noticeRowOk",
1020
- "detailStatusText": "BiQ1zG_detailStatusText",
1021
- "overlay": "BiQ1zG_overlay",
1022
- "queueRow": "BiQ1zG_queueRow",
1023
- "noticeTextOk": "BiQ1zG_noticeTextOk",
1024
- "noticeVersion": "BiQ1zG_noticeVersion",
1025
1067
  "modalTitleBusy": "BiQ1zG_modalTitleBusy",
1026
- "aboutMeta": "BiQ1zG_aboutMeta",
1027
- "pendingRowActions": "BiQ1zG_pendingRowActions",
1028
- "detailStars": "BiQ1zG_detailStars",
1029
- "modalInstall": "BiQ1zG_modalInstall",
1030
- "noticeRowMain": "BiQ1zG_noticeRowMain",
1031
1068
  "restartLater": "BiQ1zG_restartLater",
1032
- "progressTrack": "BiQ1zG_progressTrack",
1069
+ "modalCmd": "BiQ1zG_modalCmd",
1070
+ "failList": "BiQ1zG_failList",
1071
+ "modalCopy": "BiQ1zG_modalCopy",
1072
+ "noticeRowMain": "BiQ1zG_noticeRowMain",
1073
+ "restartNow": "BiQ1zG_restartNow",
1074
+ "failDiagBtn": "BiQ1zG_failDiagBtn",
1075
+ "toastIn": "BiQ1zG_toastIn",
1076
+ "aboutMeta": "BiQ1zG_aboutMeta",
1077
+ "hubUpdateNotes": "BiQ1zG_hubUpdateNotes",
1078
+ "hubVersionNumber": "BiQ1zG_hubVersionNumber",
1079
+ "aboutModal": "BiQ1zG_aboutModal",
1033
1080
  "errorHint": "BiQ1zG_errorHint",
1034
- "queueSection": "BiQ1zG_queueSection",
1035
- "helpModal": "BiQ1zG_helpModal",
1036
- "stripCancel": "BiQ1zG_stripCancel",
1037
- "restartNowWarning": "BiQ1zG_restartNowWarning",
1038
- "failNetworkTarget": "BiQ1zG_failNetworkTarget",
1081
+ "detailLabel": "BiQ1zG_detailLabel",
1082
+ "queueSectionTitle": "BiQ1zG_queueSectionTitle",
1083
+ "noticeIgnore": "BiQ1zG_noticeIgnore",
1084
+ "detailUpdateHint": "BiQ1zG_detailUpdateHint",
1085
+ "failPrepareHint": "BiQ1zG_failPrepareHint",
1086
+ "detailPath": "BiQ1zG_detailPath",
1087
+ "failClear": "BiQ1zG_failClear",
1088
+ "failKindTitle": "BiQ1zG_failKindTitle",
1089
+ "modalTitleQueued": "BiQ1zG_modalTitleQueued",
1090
+ "uninstallConfirm": "BiQ1zG_uninstallConfirm",
1091
+ "detailRow": "BiQ1zG_detailRow",
1092
+ "pendingRowActions": "BiQ1zG_pendingRowActions",
1093
+ "noticeFoot": "BiQ1zG_noticeFoot",
1094
+ "noticeHead": "BiQ1zG_noticeHead",
1095
+ "hubStateLatest": "BiQ1zG_hubStateLatest",
1096
+ "noticeRemove": "BiQ1zG_noticeRemove",
1039
1097
  "modalActions": "BiQ1zG_modalActions",
1040
- "modalRow": "BiQ1zG_modalRow",
1041
- "failRepoUrl": "BiQ1zG_failRepoUrl",
1042
- "bundleDeselectedHint": "BiQ1zG_bundleDeselectedHint",
1043
- "detailStatusRunning": "BiQ1zG_detailStatusRunning",
1044
- "detailLink": "BiQ1zG_detailLink",
1045
- "queueRowStatus": "BiQ1zG_queueRowStatus",
1046
- "aboutContent": "BiQ1zG_aboutContent",
1047
- "overlayIn": "BiQ1zG_overlayIn",
1048
- "resultDesc": "BiQ1zG_resultDesc",
1049
- "noticeTextFail": "BiQ1zG_noticeTextFail",
1050
- "errorModal": "BiQ1zG_errorModal",
1051
- "aboutModal": "BiQ1zG_aboutModal",
1052
- "failKind": "BiQ1zG_failKind",
1053
- "modalCmdCopy": "BiQ1zG_modalCmdCopy",
1054
1098
  "modalHead": "BiQ1zG_modalHead",
1055
- "hubStateLatest": "BiQ1zG_hubStateLatest",
1056
- "confirmIcon": "BiQ1zG_confirmIcon",
1057
- "hubVersionDate": "BiQ1zG_hubVersionDate",
1058
- "linkIcon": "BiQ1zG_linkIcon",
1059
- "detailPath": "BiQ1zG_detailPath",
1060
- "resultRestarting": "BiQ1zG_resultRestarting",
1061
- "queueRowDesc": "BiQ1zG_queueRowDesc",
1099
+ "queueRowStatus": "BiQ1zG_queueRowStatus",
1100
+ "modal": "BiQ1zG_modal",
1062
1101
  "result": "BiQ1zG_result",
1063
- "modalCmd": "BiQ1zG_modalCmd",
1064
- "resultCheck": "BiQ1zG_resultCheck",
1065
- "progress": "BiQ1zG_progress",
1066
- "hubStateChip": "BiQ1zG_hubStateChip",
1067
- "modalCancel": "BiQ1zG_modalCancel",
1068
- "detailGrid": "BiQ1zG_detailGrid",
1102
+ "failHead": "BiQ1zG_failHead",
1103
+ "hubVersionBar": "BiQ1zG_hubVersionBar",
1104
+ "noticeUpdateGo": "BiQ1zG_noticeUpdateGo",
1069
1105
  "detailModal": "BiQ1zG_detailModal",
1070
- "detailPathBtn": "BiQ1zG_detailPathBtn",
1071
- "noticeTime": "BiQ1zG_noticeTime",
1072
- "modalLabel": "BiQ1zG_modalLabel",
1073
- "noticeIgnore": "BiQ1zG_noticeIgnore",
1074
- "noticeRow": "BiQ1zG_noticeRow",
1075
- "modalDesc": "BiQ1zG_modalDesc",
1076
- "progressFill": "BiQ1zG_progressFill",
1106
+ "linkIcon": "BiQ1zG_linkIcon",
1077
1107
  "hubStateAvailable": "BiQ1zG_hubStateAvailable",
1078
- "failedCopyHint": "BiQ1zG_failedCopyHint",
1079
- "failMisjudgeLink": "BiQ1zG_failMisjudgeLink",
1108
+ "stripCancel": "BiQ1zG_stripCancel",
1109
+ "progressHead": "BiQ1zG_progressHead",
1110
+ "aboutContent": "BiQ1zG_aboutContent",
1111
+ "modalInstall": "BiQ1zG_modalInstall",
1112
+ "queueRowDesc": "BiQ1zG_queueRowDesc",
1113
+ "overlayIn": "BiQ1zG_overlayIn",
1080
1114
  "modalCmdText": "BiQ1zG_modalCmdText",
1081
- "modalCloseIcon": "BiQ1zG_modalCloseIcon",
1082
- "toastIn": "BiQ1zG_toastIn",
1083
- "detailPathActions": "BiQ1zG_detailPathActions",
1084
- "modalTitle": "BiQ1zG_modalTitle",
1085
1115
  "failRow": "BiQ1zG_failRow",
1086
- "failKindTitle": "BiQ1zG_failKindTitle",
1087
- "cliOnlyHint": "BiQ1zG_cliOnlyHint",
1088
- "noticeFoot": "BiQ1zG_noticeFoot",
1089
- "progressHead": "BiQ1zG_progressHead",
1090
- "errorCopySoft": "BiQ1zG_errorCopySoft",
1091
- "queueSectionTitle": "BiQ1zG_queueSectionTitle",
1092
- "trustHint": "BiQ1zG_trustHint",
1093
- "progressFillFail": "BiQ1zG_progressFillFail",
1094
- "detailLabel": "BiQ1zG_detailLabel",
1095
- "confirmIconWrap": "BiQ1zG_confirmIconWrap",
1096
- "detailValue": "BiQ1zG_detailValue",
1097
- "detailStatusPending": "BiQ1zG_detailStatusPending",
1098
- "queueRowTrack": "BiQ1zG_queueRowTrack",
1099
- "noticeBadgeFail": "BiQ1zG_noticeBadgeFail",
1100
- "modalValue": "BiQ1zG_modalValue",
1101
- "modalLink": "BiQ1zG_modalLink",
1102
- "errorBox": "BiQ1zG_errorBox",
1103
- "noticeRowUpdate": "BiQ1zG_noticeRowUpdate",
1104
- "modalBody": "BiQ1zG_modalBody",
1105
- "resultTitle": "BiQ1zG_resultTitle",
1106
- "detailArrow": "BiQ1zG_detailArrow",
1107
- "errorTitle": "BiQ1zG_errorTitle",
1108
- "noticeUpdateGo": "BiQ1zG_noticeUpdateGo",
1109
- "failDiagBtn": "BiQ1zG_failDiagBtn",
1110
- "confirmIconDanger": "BiQ1zG_confirmIconDanger",
1111
- "progressText": "BiQ1zG_progressText",
1112
- "modalCopy": "BiQ1zG_modalCopy",
1113
- "failPrepareHint": "BiQ1zG_failPrepareHint",
1114
- "resultCheckIcon": "BiQ1zG_resultCheckIcon",
1115
- "noticeHead": "BiQ1zG_noticeHead",
1116
- "restartNow": "BiQ1zG_restartNow",
1117
1116
  "toast": "BiQ1zG_toast",
1118
- "toastFail": "BiQ1zG_toastFail",
1119
- "noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
1120
- "noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
1121
- "detailDim": "BiQ1zG_detailDim",
1122
- "failBigIssue": "BiQ1zG_failBigIssue",
1123
- "detailRow": "BiQ1zG_detailRow",
1124
- "modalWide": "BiQ1zG_modalWide",
1125
- "failKindUninstall": "BiQ1zG_failKindUninstall",
1126
- "detailUpdateHint": "BiQ1zG_detailUpdateHint",
1117
+ "detailGrid": "BiQ1zG_detailGrid",
1118
+ "noticeRowUpdate": "BiQ1zG_noticeRowUpdate",
1119
+ "failKindInstall": "BiQ1zG_failKindInstall",
1120
+ "modalValue": "BiQ1zG_modalValue",
1121
+ "resultDesc": "BiQ1zG_resultDesc",
1122
+ "queuedHint": "BiQ1zG_queuedHint",
1127
1123
  "pendingRowStatus": "BiQ1zG_pendingRowStatus",
1128
- "hubUpdateNotes": "BiQ1zG_hubUpdateNotes",
1129
- "failHead": "BiQ1zG_failHead"
1124
+ "modalCmdCopy": "BiQ1zG_modalCmdCopy",
1125
+ "overlay": "BiQ1zG_overlay",
1126
+ "noticeList": "BiQ1zG_noticeList",
1127
+ "hubUpdateModal": "BiQ1zG_hubUpdateModal",
1128
+ "failKindUninstall": "BiQ1zG_failKindUninstall",
1129
+ "detailPathActions": "BiQ1zG_detailPathActions"
1130
1130
  };
1131
1131
  //#endregion
1132
1132
  //#region src/server/services/install/release-target.ts
1133
- /** 完整命令前缀:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同口径)。 */
1133
+ /** 完整命令前缀:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同一套规则)。 */
1134
1134
  const DSH_PLUGIN_CMD_RE = /^dsh[ \t]+plugin[ \t]+--profile(?:[ \t]+|=)[A-Za-z0-9_-]+[ \t]+(?:add|update)[ \t]+(.+)$/i;
1135
1135
  /** 固定形态的 release .tgz 直链:主机、路径段与扩展名全部锁死。 */
1136
1136
  const RELEASE_URL_RE = /^https:\/\/github\.com\/([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)\/releases\/download\/([A-Za-z0-9._+-]+)\/([A-Za-z0-9._+-]+\.tgz)$/;
@@ -1171,11 +1171,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1171
1171
  }
1172
1172
  /** 展示用安装命令(复制/弹窗):目录下发的权威命令优先(CLI-only 插件如 dsh-tui
1173
1173
  * 需专属 profile(--profile dsh-tui),无法从 npm 包名推断,必须用官方命令);
1174
- * 常规插件无目录命令时用 npm 包名回退生成。 */
1175
- function installCommandOf(p, withProfile = false) {
1174
+ * 常规插件无目录命令时用 npm 包名回退生成。
1175
+ * version 为已过发布冷却期的版本:带上它,手抄命令与一键安装的执行结果一致。 */
1176
+ function installCommandOf(p, withProfile = false, version) {
1176
1177
  const cmd = p.install?.command;
1177
1178
  if (cmd) return cmd;
1178
- return `${`dsh plugin${withProfile ? " --profile web" : ""} add `}${installTargetOf(p)}`;
1179
+ const prefix = `dsh plugin${withProfile ? " --profile web" : ""} add `;
1180
+ const target = installTargetOf(p);
1181
+ return `${prefix}${version === void 0 || version === "" ? target : `${target}@${version}`}`;
1179
1182
  }
1180
1183
  /** 把任务/安装目标归一化为 owner/repo 展示身份。 */
1181
1184
  function repoFromInstallTarget(value) {
@@ -1214,9 +1217,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1214
1217
  /**
1215
1218
  * 插件当前版本号,供头部标题展示「DSH Plugin Hub v0.1.1」。
1216
1219
  * tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;
1217
- * node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。
1220
+ * node --test 直接 import 本模块时该标识符不存在,typeof 守卫缺省为空串。
1218
1221
  */
1219
- const PLUGIN_VERSION = "2.3.1";
1222
+ const PLUGIN_VERSION = "2.3.3";
1220
1223
  const CATEGORY_ORDER = [
1221
1224
  "interface",
1222
1225
  "session",
@@ -1369,7 +1372,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1369
1372
  return null;
1370
1373
  }
1371
1374
  }
1372
- /** 批量查询已安装插件 npm 包的最新版本发布时间(供应链门禁用);失败返回 null(调用方按原逻辑照常提示)。 */
1375
+ /** 批量查询已安装插件 npm 包的最新版本发布时间(发布冷却期用);失败返回 null(调用方按原逻辑照常提示)。 */
1373
1376
  async function fetchNpmReleaseAge(packages) {
1374
1377
  if (packages.length === 0) return {};
1375
1378
  try {
@@ -1510,7 +1513,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1510
1513
  return `${url}${url.includes("?") ? "&" : "?"}_t=${Date.now()}`;
1511
1514
  }
1512
1515
  /** 归一化接口下发的 recentVersions:只保留带版本号的条目,其余字段按类型补。
1513
- * 这条数据是「最新版还在 24.5h 门禁内时回退到更早的已过门槛版本」的唯一依据;
1516
+ * 这条数据是「最新版还在 24.5h 冷却期内时回退到更早的已过冷却期版本」的唯一依据;
1514
1517
  * 入口处漏传会让候选只剩最新版,整体变成 pending —— 用户就永远看不到更新入口。 */
1515
1518
  function recentVersionsOf(value) {
1516
1519
  if (!Array.isArray(value)) return [];
@@ -1527,7 +1530,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1527
1530
  }
1528
1531
  return list;
1529
1532
  }
1530
- /** 版本控制中心:最新版本 + Markdown 变更记录 + 最近发版(门禁回退用);不可用返回 null。 */
1533
+ /** 版本控制中心:最新版本 + Markdown 变更记录 + 最近发版(冷却期回退用);不可用返回 null。 */
1531
1534
  async function fetchHubUpdate() {
1532
1535
  try {
1533
1536
  const res = await fetch(busted(HUB_UPDATE_URL), { cache: "no-store" });
@@ -1565,9 +1568,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1565
1568
  }
1566
1569
  //#endregion
1567
1570
  //#region src/client/logic/release-age.ts
1568
- /** pnpm 供应链门禁:dsh profile 默认 minimumReleaseAge=1440(分钟);+30 分钟缓冲抵消网络/CDN 边缘时间偏差。 */
1571
+ /** pnpm 发布冷却期:dsh profile 默认 minimumReleaseAge=1440(分钟);+30 分钟缓冲抵消网络/CDN 边缘时间偏差。 */
1569
1572
  const MIN_RELEASE_AGE_MS = 882e5;
1570
- /** 发布时间是否仍在门禁窗口内(太新 → 暂缓提示);无值/解析不出返回 false(不拦真实更新)。 */
1573
+ /** 发布时间是否仍在冷却期内(太新 → 暂缓提示);无值/解析不出返回 false(不拦真实更新)。 */
1571
1574
  function isReleaseTooFresh(publishedAt, now) {
1572
1575
  if (typeof publishedAt !== "string" || publishedAt === "") return false;
1573
1576
  const ms = Date.parse(publishedAt);
@@ -1610,12 +1613,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1610
1613
  return 0;
1611
1614
  }
1612
1615
  /**
1613
- * 是否值得提示「可更新」:npm 上最新可安装版本确实比已装版本新,且已过供应链门禁。
1616
+ * 是否值得提示「可更新」:npm 上最新可安装版本确实比已装版本新,且已过发布冷却期。
1614
1617
  *
1615
1618
  * 更新命令执行的是 `pkg@latest`,所以「目录里标的版本」不是最终能装上的版本:
1616
1619
  * 作者可能只打了 GitHub release 没发 npm —— 此时提示会变成永远点不掉的循环。
1617
1620
  * 任一信息缺失(查不到发布信息 / 没有已装版本记录)返回 offered,交回调用方原有判定:
1618
- * 宁可提示,也不因为一次查询失败把真实更新吃掉。
1621
+ * 宁可提示,也不因为一次查询失败漏掉真实更新。
1619
1622
  */
1620
1623
  function updateDecision(release, installedVersion, now) {
1621
1624
  if (release === null) return {
@@ -1641,8 +1644,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1641
1644
  /**
1642
1645
  * 选出本次真正该提示的更新版本。
1643
1646
  *
1644
- * 只看最新版会漏更新:连续发版时间隔小于供应链门禁时,最新版永远「太新」,
1645
- * 提示被整体跳过。这里把最新版与 recentVersions 一起当候选,取「高于当前版本且已过门禁」
1647
+ * 只看最新版会漏更新:连续发版时间隔小于发布冷却期时,最新版永远「太新」,
1648
+ * 提示被整体跳过。这里把最新版与 recentVersions 一起当候选,取「高于当前版本且已过冷却期」
1646
1649
  * 的最高版本;一个都没有但仍存在更高版本 → pending(暂缓,不谎称已是最新)。
1647
1650
  */
1648
1651
  function pickHubUpdate(info, currentVersion, now) {
@@ -1881,7 +1884,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1881
1884
  * 界面停在「正在加载插件数据…」假死 —— 超时自动重拉,最多自动重试 2 次后转失败态;
1882
1885
  * 用户手动刷新(reload)时清零重新计数。 */
1883
1886
  const loadRetriesRef = (0, react.useRef)(0);
1884
- /** 目录加载超时阈值:超过即判定挂起,强制刷新一次(服务端代理 curl 上限 60s,客户端 30s 先兜底) */
1887
+ /** 目录加载超时阈值:超过即判定挂起,强制刷新一次(服务端代理 curl 上限 60s,客户端 30s 先超时) */
1885
1888
  const LOAD_TIMEOUT_MS = 3e4;
1886
1889
  /** 挂起后最多自动重试次数:避免代理持续不通时无限循环刷新(每次重试仍 30s,2 次后转失败界面可手动重试) */
1887
1890
  const MAX_LOAD_RETRIES = 2;
@@ -1899,7 +1902,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1899
1902
  * 强制刷新 Hub 版本与「关注我们」信息:点击头部版本号/徽标时触发。
1900
1903
  * 挂载期的 useEffect 只在进入/reload 时拉一次,发版后已打开的界面点版本号
1901
1904
  * 仍显示旧数据;此处重新拉接口中心,最新版本与变更记录点击即见。
1902
- * 失败静默为 null(弹窗兜底展示当前版本号),与挂载期拉取口径一致。
1905
+ * 失败时返回 null(弹窗退回展示当前版本号),与挂载期拉取规则一致。
1903
1906
  */
1904
1907
  const refreshHub = async () => {
1905
1908
  const [info, about] = await Promise.all([fetchHubUpdate(), fetchHubAbout()]);
@@ -1963,7 +1966,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1963
1966
  controller.abort();
1964
1967
  };
1965
1968
  }, [reloadKey, lang]);
1966
- /** 刷新当前 profile 已安装插件表;宿主未挂本地路由时静默降级为空表。 */
1969
+ /** 刷新当前 profile 已安装插件表;宿主未挂本地路由时降级为空表。 */
1967
1970
  const refreshInstalled = async () => {
1968
1971
  const data = await fetchInstalled();
1969
1972
  if (data === null) return;
@@ -2062,7 +2065,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2062
2065
  const releaseAgeReady = releaseAgeKey === releaseAge.key;
2063
2066
  /**
2064
2067
  * 不能提示更新的包:
2065
- * - npm 上最新版还没过供应链门禁(发布不满 24h,pnpm 会静默回退,点了也装不上);
2068
+ * - npm 上最新版还没过发布冷却期(发布不满 24h,pnpm 会不提示地回退,点了也装不上);
2066
2069
  * - npm 上最新版并不高于已装版本 —— 更新走的是 `pkg@latest`,此时无论目录标到哪个 tag,
2067
2070
  * 都不可能装上(作者可能只打了 GitHub release 没发 npm),提示只会变成永远点不掉的循环。
2068
2071
  */
@@ -2095,7 +2098,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2095
2098
  if (pkg === null) return true;
2096
2099
  return releaseAgeReady && !updateBlocked.has(pkg);
2097
2100
  };
2098
- /** 更新被门禁暂缓时的可重试时刻(毫秒);未安装/无更新/非门禁原因 → null。 */
2101
+ /** 更新被冷却期未到时的可重试时刻(毫秒);未安装/无更新/非冷却期原因 → null。 */
2099
2102
  const updatePendingUntil = (p) => {
2100
2103
  if (!hasUpdateOf(p, installed, versions)) return null;
2101
2104
  const pkg = npmPackageOf(p, versions);
@@ -2103,7 +2106,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2103
2106
  return updateDecisions.get(pkg)?.pendingUntil ?? null;
2104
2107
  };
2105
2108
  /** 已安装项统一列表(目录元数据 + 运行时信息合并):校验未就绪/被拦下的去掉更新标记、
2106
- * 门禁暂缓的带上可重试时刻,驱动「已安装」tab。 */
2109
+ * 冷却期未到的带上可重试时刻,驱动「已安装」tab。 */
2107
2110
  const installedItems = (0, react.useMemo)(() => {
2108
2111
  return rawInstalledItems.map((item) => {
2109
2112
  if (!item.hasUpdate || !item.plugin) return item;
@@ -2132,12 +2135,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2132
2135
  * 构建时注入的 PLUGIN_VERSION 是运行 bundle 的真实版本;测试/异常场景缺失时
2133
2136
  * 回退到安装时记录的版本。版本号不等即新版(版本号只在发版时变更,绝无降级场景)。
2134
2137
  *
2135
- * 另加 pnpm 供应链安全门槛:新版本发布还不满 24 小时(+30 分钟缓冲)时,pnpm 会静默
2138
+ * 另加 pnpm 发布冷却期:新版本发布还不满 24 小时(+30 分钟缓冲)时,pnpm 会不提示地
2136
2139
  * 回退到旧版本,此时若提示「可更新」用户点了也更新不到。publishedAt 由接口中心按 npm
2137
- * registry 真实发布时间下发(同源),据此判断最准。门槛命中要单列成 `pending` 而不是
2140
+ * registry 真实发布时间下发(同源),据此判断最准。冷却期命中要单列成 `pending` 而不是
2138
2141
  * 落回「无更新」——回落会让弹窗在本机版本落后时谎称「已是最新」。
2139
2142
  */
2140
- const hubCurrentVersion = "2.3.1";
2143
+ const hubCurrentVersion = "2.3.3";
2141
2144
  const hubUpdateResult = hubUpdateInfo === null ? {
2142
2145
  state: "none",
2143
2146
  target: null
@@ -2341,7 +2344,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2341
2344
  function actionWordZh(action) {
2342
2345
  return action === "uninstall" ? "卸载" : action === "update" ? "更新" : "安装";
2343
2346
  }
2344
- /** 记录的动作:老记录只有 kind,按 kind 兜底。 */
2347
+ /** 记录的动作:老记录只有 kind,按 kind 归类。 */
2345
2348
  function actionOfRecord(rec) {
2346
2349
  if (rec.action !== void 0) return rec.action;
2347
2350
  return rec.kind === "uninstall" ? "uninstall" : rec.kind === "update" ? "update" : "install";
@@ -2439,7 +2442,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2439
2442
  if (LOCAL_ENV_RE.test(message)) return "localEnv";
2440
2443
  return "hub";
2441
2444
  }
2442
- /** 「特征指向本机环境但说不清具体哪一类」的兜底判据:系统调用错误码(权限/路径过长/设备异常)、
2445
+ /** 「特征指向本机环境但说不清具体哪一类」的最后的判断规则:系统调用错误码(权限/路径过长/设备异常)、
2443
2446
  * 证书与代理校验失败、本地配置文件(~/.npmrc、profile 的 package.json)损坏。
2444
2447
  * 只做排除用:命中它表示「不是插件侧问题」,不代表我们已经定位到原因。 */
2445
2448
  const LOCAL_ENV_RE = /os error \d{1,3}\b|ERROR_[A-Z_]{4,}|\bE(?:ACCES|PERM|NOENT|NAMETOOLONG|INVAL|PROTO|ISDIR|NOTDIR|EXIST|BADF|NOTEMPTY|JSONPARSE|NOMEM)\b|JavaScript heap out of memory|Unexpected token .{0,60}in JSON|SELF_SIGNED_CERT_IN_CHAIN|UNABLE_TO_VERIFY_LEAF_SIGNATURE|ERR_TLS_CERT_ALTNAME_INVALID|unable to verify the first certificate|self[- ]signed certificate|ERR_INVALID_URL|invalid registry|proxy authentication|407 Proxy/i;
@@ -2468,7 +2471,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2468
2471
  /** 摘要里单行上限:允许构建 key 等长行也被截短。 */
2469
2472
  const MAX_LINE_CHARS = 400;
2470
2473
  /**
2471
- * 展示用格式化:宿主门禁消息里的 peerDependencies 是压缩成一行的 JSON,
2474
+ * 展示用格式化:宿主兼容性提示里的 peerDependencies 是压缩成一行的 JSON,
2472
2475
  * 直接展示像一团乱码;展开成缩进格式,解析失败则原样返回。
2473
2476
  */
2474
2477
  function formatFailureMessage(message) {
@@ -2971,7 +2974,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2971
2974
  /** 待重启列表(服务端内存态 + 本地展示信息补齐);与 queue 一样以 ref 为唯一事实来源。 */
2972
2975
  const [pendingRestarts, setPendingRestarts] = (0, react.useState)([]);
2973
2976
  const pendingRef = (0, react.useRef)([]);
2974
- /** 本次会话内安装成功插件的展示信息(目标 → 简介/版本):轮询合并待重启列表时补齐,刷新后由 resolvePending 兜底。 */
2977
+ /** 本次会话内安装成功插件的展示信息(目标 → 简介/版本):轮询合并待重启列表时补齐,刷新后由 resolvePending 补上。 */
2975
2978
  const pendingInfoRef = (0, react.useRef)(/* @__PURE__ */ new Map());
2976
2979
  /** 保持最新的 resolvePending:轮询闭包捕获的是调用那一刻的目录状态,目录晚加载时也能补齐。 */
2977
2980
  const resolvePendingRef = (0, react.useRef)(resolvePending);
@@ -2982,12 +2985,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2982
2985
  const settlingRef = (0, react.useRef)(/* @__PURE__ */ new Set());
2983
2986
  /** 轮询定时器句柄(队列清空/组件卸载时清理) */
2984
2987
  const pollRef = (0, react.useRef)(null);
2985
- /** 请求在途的目标集合(同步防重):双击安装/卸载时第二击直接忽略。
2988
+ /** 请求还没返回的目标集合(同步防重):双击安装/卸载时第二击直接忽略。
2986
2989
  * 本地队列任务要等 fetch 返回后才入队,仅靠 queueRef 检查拦不住请求窗口内的重复点击。 */
2987
2990
  const submittingRef = (0, react.useRef)(/* @__PURE__ */ new Set());
2988
2991
  /** 乐观入队临时 id 计数器:递减产生唯一负数,与服务端自增正数 id 永不冲突。 */
2989
2992
  const tempIdRef = (0, react.useRef)(0);
2990
- /** 请求在途标记:弹窗据此禁用确认按钮,避免等待响应期间被再次点击。 */
2993
+ /** 请求进行中标记:弹窗据此禁用确认按钮,避免等待响应期间被再次点击。 */
2991
2994
  const [submitting, setSubmitting] = (0, react.useState)(false);
2992
2995
  /** 停止后台任务轮询(任务结束或组件卸载时清理)。 */
2993
2996
  const stopPoll = () => {
@@ -3127,7 +3130,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
3127
3130
  }
3128
3131
  }, stepMs);
3129
3132
  };
3130
- /** 任务在 /active 中消失 = 已结束:查 /status 拿终态并收尾(cancelled 静默移除)。 */
3133
+ /** 任务在 /active 中消失 = 已结束:查 /status 拿终态并收尾(cancelled 直接移除)。 */
3131
3134
  const settleTask = async (q) => {
3132
3135
  let status = "failed";
3133
3136
  let lines = [];
@@ -3356,7 +3359,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
3356
3359
  desc: p.description,
3357
3360
  version: p.version,
3358
3361
  updatedAt: p.dates?.repoUpdatedAt,
3359
- command: installCommandOf(p, true),
3362
+ command: installCommandOf(p, true, opts?.pinVersion),
3360
3363
  source: "catalog",
3361
3364
  update: opts?.update,
3362
3365
  pinVersion: opts?.pinVersion
@@ -3365,8 +3368,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
3365
3368
  /** 命令行安装:用户手输 npm 包名,走 custom 源(受安全开关控制)。
3366
3369
  * update=true 时对已安装目标放行覆盖重装(与目录插件「更新」同一语义)。
3367
3370
  * channel=入口渠道(NPM 包卡片):上报服务端落日志,失败弹窗/通知据此精准溯源。
3368
- * 队列展示/防重一律用归一化身份:与服务端 /active 合并、弹窗目标匹配同口径,
3369
- * npm 包名透传不受影响。 */
3371
+ * 队列展示/防重一律用归一化身份:与服务端 /active 合并、弹窗目标匹配同一套规则,
3372
+ * npm 包名原样传递不受影响。 */
3370
3373
  const installCustom = async (raw, opts) => {
3371
3374
  const target = raw.trim();
3372
3375
  if (!target) return;
@@ -3381,7 +3384,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
3381
3384
  });
3382
3385
  };
3383
3386
  /** 全局 npm 安装(官方 README 的 `npm install -g <pkgs>`):不进任何 profile、无需宿主重启。
3384
- * 队列展示/防重用包列表空格拼接的身份(与服务端 target 同口径);入口渠道固定为 npm(NPM 包卡片)。 */
3387
+ * 队列展示/防重用包列表空格拼接的身份(与服务端 target 同一套规则);入口渠道固定为 npm(NPM 包卡片)。 */
3385
3388
  const installGlobalNpm = async (pkgs, opts) => {
3386
3389
  const list = (pkgs ?? []).map((p) => p.trim()).filter((p) => p !== "");
3387
3390
  if (list.length === 0) return;
@@ -3417,6 +3420,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
3417
3420
  });
3418
3421
  const data = await res.json();
3419
3422
  if (!data.ok || typeof data.task !== "number") {
3423
+ if (res.status === 400 && data.error === "plugin is not installed") {
3424
+ refreshInstalled();
3425
+ clearInstalledVersion(repo);
3426
+ onUninstallDone(false, repo, false, false);
3427
+ return;
3428
+ }
3420
3429
  onError(data.error || `HTTP ${res.status}`, repo, "uninstall");
3421
3430
  return;
3422
3431
  }
@@ -4010,9 +4019,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
4010
4019
  */
4011
4020
  /** 完成结果视图:绿色对勾 + 标题/描述;
4012
4021
  * 终态只有两种:
4013
- * - needsRestart=true(刷新解决不了:热挂载失败 / 非 dsh 插件 / 更新)→ 仅一个「立即重启」
4022
+ * - needsRestart=true(刷新解决不了:热加载失败 / 非 dsh 插件 / 更新)→ 仅一个「立即重启」
4014
4023
  * 按钮(重启会中断进行中的任务,故仍需用户确认),关闭即放弃;
4015
- * - 其余(含 needsReload=true 的「已热挂载、仅剩客户端 UI」)→ 仅「完成」按钮:关闭结果弹窗时
4024
+ * - 其余(含 needsReload=true 的「已热加载、仅剩客户端 UI」)→ 仅「完成」按钮:关闭结果弹窗时
4016
4025
  * 上层自动刷新页面让插件生效,不再给「稍后/立即刷新」手动选择。 */
4017
4026
  function ResultView({ title, desc, t, restarting, needsRestart, needsReload, bundleDeselected, onRestart, onClose }) {
4018
4027
  return (0, react.createElement)("div", { className: Modal_module_css_default.result }, (0, react.createElement)("div", { className: Modal_module_css_default.resultCheck }, (0, react.createElement)("svg", {
@@ -4043,7 +4052,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
4043
4052
  * 目录插件与命令行安装(customTarget 模式)共用同一套确认/进度/结果流程。
4044
4053
  */
4045
4054
  function InstallModal(props) {
4046
- const { plugin, customTarget, globalNpm, done, task, t, langPath, restarting, submitting, update, cliOnly, needsRestart, needsReload, bundleDeselected, onClose, onCopy, onInstall, onRestart } = props;
4055
+ const { plugin, customTarget, globalNpm, done, task, t, langPath, restarting, submitting, update, pinVersion, cliOnly, needsRestart, needsReload, bundleDeselected, onClose, onCopy, onInstall, onRestart } = props;
4047
4056
  const busy = submitting || task !== null && (task.status === "pending" || task.status === "running");
4048
4057
  const name = customTarget ?? (globalNpm !== void 0 && globalNpm.length > 0 ? globalNpm.join(" ") : void 0) ?? plugin?.displayName ?? plugin?.slug ?? "";
4049
4058
  const busyTitle = (label) => langPath === "zh/" ? `${name} 插件${label}` : `${label} ${name}`;
@@ -4086,7 +4095,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
4086
4095
  title: t("copyInstallCommand"),
4087
4096
  role: "button",
4088
4097
  tabIndex: 0
4089
- }, (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdText }, globalNpm !== void 0 && globalNpm.length > 0 ? `npm install -g ${globalNpm.join(" ")}` : customTarget ? `pnpm add ${customTarget}` : installCommandOf(plugin)), (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdCopy }, (0, react.createElement)(CopyIcon), t("copyCmdLabel"))), globalNpm !== void 0 && globalNpm.length > 0 ? (0, react.createElement)("div", { className: Modal_module_css_default.cliOnlyHint }, t("globalNpmHint")) : null, cliOnly ? (0, react.createElement)("div", { className: Modal_module_css_default.cliOnlyHint }, t(plugin?.install?.manualInstall === true ? "manualInstallOnlyHint" : "cliOnlyHint")) : null, task && task.status === "pending" ? (0, react.createElement)("div", { className: Modal_module_css_default.queuedHint }, t("queuedHint")) : null, task ? (0, react.createElement)(ProgressView, { task }) : null, task && task.status === "failed" ? (0, react.createElement)("div", { className: Modal_module_css_default.failedCopyHint }, t("failedCopyHint")) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
4098
+ }, (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdText }, globalNpm !== void 0 && globalNpm.length > 0 ? `npm install -g ${globalNpm.join(" ")}` : customTarget ? `pnpm add ${customTarget}` : installCommandOf(plugin, false, pinVersion)), (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdCopy }, (0, react.createElement)(CopyIcon), t("copyCmdLabel"))), globalNpm !== void 0 && globalNpm.length > 0 ? (0, react.createElement)("div", { className: Modal_module_css_default.cliOnlyHint }, t("globalNpmHint")) : null, cliOnly ? (0, react.createElement)("div", { className: Modal_module_css_default.cliOnlyHint }, t(plugin?.install?.manualInstall === true ? "manualInstallOnlyHint" : "cliOnlyHint")) : null, task && task.status === "pending" ? (0, react.createElement)("div", { className: Modal_module_css_default.queuedHint }, t("queuedHint")) : null, task ? (0, react.createElement)(ProgressView, { task }) : null, task && task.status === "failed" ? (0, react.createElement)("div", { className: Modal_module_css_default.failedCopyHint }, t("failedCopyHint")) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
4090
4099
  className: Modal_module_css_default.modalCopy,
4091
4100
  disabled: busy,
4092
4101
  onClick: onCopy
@@ -4506,8 +4515,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
4506
4515
  * - 有更新(state='available'):标题「有新版本」,展示新版本号、发布时间与 Worker 下发的
4507
4516
  * Markdown 变更记录(renderMarkdown 渲染,双语言按界面语言取 {zh,en} 对象),
4508
4517
  * 按钮「稍后再说 / 直接更新」,确认后进入安装弹窗执行覆盖重装。
4509
- * - 暂缓提示(state='pending'):远端确有新版本,但发布未满供应链安全门槛,pnpm 此时会
4510
- * 静默回退到旧版本 —— 仍按「有新版本」展示,只给「稍后再说」,并说明稍后会自动提示。
4518
+ * - 暂缓提示(state='pending'):远端确有新版本,但发布还不满冷却期,pnpm 此时会
4519
+ * 不提示地回退到旧版本 —— 仍按「有新版本」展示,只给「稍后再说」,并说明稍后会自动提示。
4511
4520
  * - 无更新 / 信息缺失(state='latest' / 'none'):标题「当前版本」,版本号与本机版本取自
4512
4521
  * currentVersion(构建注入的 PLUGIN_VERSION),**不得**用远端最新版号冒充本机版本。
4513
4522
  * 点击头部版本号(或「可更新」徽标)打开 —— 无论有无更新都能看到更新内容。
@@ -5209,42 +5218,42 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
5209
5218
  css: css$9
5210
5219
  });
5211
5220
  var List_module_css_default = {
5212
- "categoryBadge": "_3XaZHa_categoryBadge",
5213
- "cardTitleRow": "_3XaZHa_cardTitleRow",
5214
- "topics": "_3XaZHa_topics",
5215
- "actions": "_3XaZHa_actions",
5216
5221
  "moreSentinel": "_3XaZHa_moreSentinel",
5217
- "authorBadge": "_3XaZHa_authorBadge",
5218
- "installBtn": "_3XaZHa_installBtn",
5219
- "state": "_3XaZHa_state",
5220
- "stateDesc": "_3XaZHa_stateDesc",
5221
- "installBtnCopied": "_3XaZHa_installBtnCopied",
5222
- "footLink": "_3XaZHa_footLink",
5223
- "cardTitle": "_3XaZHa_cardTitle",
5224
- "date": "_3XaZHa_date",
5225
5222
  "cardBadgeRow": "_3XaZHa_cardBadgeRow",
5226
- "cardMain": "_3XaZHa_cardMain",
5227
- "versionBadge": "_3XaZHa_versionBadge",
5228
- "retryBtn": "_3XaZHa_retryBtn",
5223
+ "fork": "_3XaZHa_fork",
5229
5224
  "stats": "_3XaZHa_stats",
5230
- "topic": "_3XaZHa_topic",
5225
+ "authorBadge": "_3XaZHa_authorBadge",
5226
+ "body": "_3XaZHa_body",
5227
+ "installBtnInstalled": "_3XaZHa_installBtnInstalled",
5231
5228
  "cardSide": "_3XaZHa_cardSide",
5232
- "updateBadge": "_3XaZHa_updateBadge",
5229
+ "footLink": "_3XaZHa_footLink",
5230
+ "detailBtn": "_3XaZHa_detailBtn",
5233
5231
  "star": "_3XaZHa_star",
5234
- "fork": "_3XaZHa_fork",
5232
+ "card": "_3XaZHa_card",
5233
+ "updateBadge": "_3XaZHa_updateBadge",
5234
+ "categoryBadge": "_3XaZHa_categoryBadge",
5235
+ "topic": "_3XaZHa_topic",
5236
+ "date": "_3XaZHa_date",
5235
5237
  "footer": "_3XaZHa_footer",
5236
- "installBtnInstalled": "_3XaZHa_installBtnInstalled",
5238
+ "topics": "_3XaZHa_topics",
5239
+ "installBtnCopied": "_3XaZHa_installBtnCopied",
5240
+ "actions": "_3XaZHa_actions",
5241
+ "versionBadge": "_3XaZHa_versionBadge",
5242
+ "verified": "_3XaZHa_verified",
5243
+ "stateDesc": "_3XaZHa_stateDesc",
5244
+ "diagBtn": "_3XaZHa_diagBtn",
5245
+ "stateTitle": "_3XaZHa_stateTitle",
5246
+ "cardMain": "_3XaZHa_cardMain",
5247
+ "uninstallBtn": "_3XaZHa_uninstallBtn",
5248
+ "list": "_3XaZHa_list",
5249
+ "retryBtn": "_3XaZHa_retryBtn",
5250
+ "installBtn": "_3XaZHa_installBtn",
5251
+ "state": "_3XaZHa_state",
5252
+ "installBtnUpdate": "_3XaZHa_installBtnUpdate",
5237
5253
  "desc": "_3XaZHa_desc",
5238
- "detailBtn": "_3XaZHa_detailBtn",
5239
- "diagBtn": "_3XaZHa_diagBtn",
5240
- "verified": "_3XaZHa_verified",
5241
- "stateTitle": "_3XaZHa_stateTitle",
5242
- "card": "_3XaZHa_card",
5243
5254
  "stateActions": "_3XaZHa_stateActions",
5244
- "list": "_3XaZHa_list",
5245
- "uninstallBtn": "_3XaZHa_uninstallBtn",
5246
- "body": "_3XaZHa_body",
5247
- "installBtnUpdate": "_3XaZHa_installBtnUpdate"
5255
+ "cardTitleRow": "_3XaZHa_cardTitleRow",
5256
+ "cardTitle": "_3XaZHa_cardTitle"
5248
5257
  };
5249
5258
  //#endregion
5250
5259
  //#region src/client/hooks/useIncrementalList.ts
@@ -5465,16 +5474,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
5465
5474
  css: css$8
5466
5475
  });
5467
5476
  var SectionTabs_module_css_default = {
5477
+ "tab": "_7tvizq_tab",
5468
5478
  "tabCount": "_7tvizq_tabCount",
5469
- "noticeCount": "_7tvizq_noticeCount",
5470
- "tabActive": "_7tvizq_tabActive",
5471
- "noticeIcon": "_7tvizq_noticeIcon",
5472
5479
  "noticeBtn": "_7tvizq_noticeBtn",
5473
- "tab": "_7tvizq_tab",
5480
+ "tabActive": "_7tvizq_tabActive",
5474
5481
  "tabLabel": "_7tvizq_tabLabel",
5482
+ "noticeCount": "_7tvizq_noticeCount",
5483
+ "root": "_7tvizq_root",
5475
5484
  "tabIcon": "_7tvizq_tabIcon",
5476
- "tabCountActive": "_7tvizq_tabCountActive",
5477
- "root": "_7tvizq_root"
5485
+ "noticeIcon": "_7tvizq_noticeIcon",
5486
+ "tabCountActive": "_7tvizq_tabCountActive"
5478
5487
  };
5479
5488
  //#endregion
5480
5489
  //#region src/client/components/layout/SectionTabs.tsx
@@ -5550,46 +5559,46 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
5550
5559
  css: css$7
5551
5560
  });
5552
5561
  var InstalledView_module_css_default = {
5553
- "segBtnActive": "_1nXeGW_segBtnActive",
5562
+ "rowDesc": "_1nXeGW_rowDesc",
5563
+ "rowMain": "_1nXeGW_rowMain",
5564
+ "list": "_1nXeGW_list",
5565
+ "rowStar": "_1nXeGW_rowStar",
5566
+ "emptyTitle": "_1nXeGW_emptyTitle",
5567
+ "statusPending": "_1nXeGW_statusPending",
5568
+ "exampleRow": "_1nXeGW_exampleRow",
5569
+ "searchInput": "_1nXeGW_searchInput",
5570
+ "segLabel": "_1nXeGW_segLabel",
5571
+ "rowFork": "_1nXeGW_rowFork",
5572
+ "rowSourceTagManual": "_1nXeGW_rowSourceTagManual",
5554
5573
  "rowTitleLine": "_1nXeGW_rowTitleLine",
5555
- "rowSourceTagHub": "_1nXeGW_rowSourceTagHub",
5556
- "rowDetail": "_1nXeGW_rowDetail",
5557
5574
  "rowUpdate": "_1nXeGW_rowUpdate",
5558
- "statusDot": "_1nXeGW_statusDot",
5559
- "statusInactive": "_1nXeGW_statusInactive",
5560
- "list": "_1nXeGW_list",
5561
- "rowActionLine": "_1nXeGW_rowActionLine",
5562
- "rowActions": "_1nXeGW_rowActions",
5563
- "updateBadge": "_1nXeGW_updateBadge",
5564
- "toolbar": "_1nXeGW_toolbar",
5565
- "rowSourceTag": "_1nXeGW_rowSourceTag",
5566
5575
  "rowTitle": "_1nXeGW_rowTitle",
5567
- "searchWrap": "_1nXeGW_searchWrap",
5568
- "rowSourceTagManual": "_1nXeGW_rowSourceTagManual",
5576
+ "rowSourceTagHub": "_1nXeGW_rowSourceTagHub",
5577
+ "rowActions": "_1nXeGW_rowActions",
5578
+ "rowCategory": "_1nXeGW_rowCategory",
5579
+ "segRow": "_1nXeGW_segRow",
5569
5580
  "rowRepo": "_1nXeGW_rowRepo",
5570
- "rowUninstall": "_1nXeGW_rowUninstall",
5571
- "versionBadge": "_1nXeGW_versionBadge",
5581
+ "segBtnActive": "_1nXeGW_segBtnActive",
5582
+ "exampleBadge": "_1nXeGW_exampleBadge",
5583
+ "searchWrap": "_1nXeGW_searchWrap",
5584
+ "statusDot": "_1nXeGW_statusDot",
5585
+ "rowMeta": "_1nXeGW_rowMeta",
5586
+ "rowSourceTag": "_1nXeGW_rowSourceTag",
5587
+ "rowDetail": "_1nXeGW_rowDetail",
5588
+ "root": "_1nXeGW_root",
5572
5589
  "emptyDesc": "_1nXeGW_emptyDesc",
5590
+ "rowActionLine": "_1nXeGW_rowActionLine",
5591
+ "versionBadge": "_1nXeGW_versionBadge",
5592
+ "row": "_1nXeGW_row",
5593
+ "rowStats": "_1nXeGW_rowStats",
5594
+ "segGroup": "_1nXeGW_segGroup",
5573
5595
  "rowRestart": "_1nXeGW_rowRestart",
5596
+ "toolbar": "_1nXeGW_toolbar",
5574
5597
  "segBtn": "_1nXeGW_segBtn",
5575
- "searchInput": "_1nXeGW_searchInput",
5576
- "exampleBadge": "_1nXeGW_exampleBadge",
5577
- "rowCategory": "_1nXeGW_rowCategory",
5578
- "exampleRow": "_1nXeGW_exampleRow",
5579
- "rowMeta": "_1nXeGW_rowMeta",
5580
- "rowDesc": "_1nXeGW_rowDesc",
5581
- "segLabel": "_1nXeGW_segLabel",
5582
5598
  "empty": "_1nXeGW_empty",
5583
- "rowMain": "_1nXeGW_rowMain",
5584
- "statusPending": "_1nXeGW_statusPending",
5585
- "segRow": "_1nXeGW_segRow",
5586
- "rowStar": "_1nXeGW_rowStar",
5587
- "segGroup": "_1nXeGW_segGroup",
5588
- "rowStats": "_1nXeGW_rowStats",
5589
- "rowFork": "_1nXeGW_rowFork",
5590
- "row": "_1nXeGW_row",
5591
- "root": "_1nXeGW_root",
5592
- "emptyTitle": "_1nXeGW_emptyTitle"
5599
+ "updateBadge": "_1nXeGW_updateBadge",
5600
+ "rowUninstall": "_1nXeGW_rowUninstall",
5601
+ "statusInactive": "_1nXeGW_statusInactive"
5593
5602
  };
5594
5603
  //#endregion
5595
5604
  //#region src/client/components/views/InstalledView.tsx
@@ -5858,27 +5867,27 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
5858
5867
  css: css$6
5859
5868
  });
5860
5869
  var CustomInstallView_module_css_default = {
5861
- "helpBody": "zISxCG_helpBody",
5862
- "installExample": "zISxCG_installExample",
5863
5870
  "installCardDisabled": "zISxCG_installCardDisabled",
5864
- "installCards": "zISxCG_installCards",
5865
- "installRow": "zISxCG_installRow",
5866
- "installHelpBtn": "zISxCG_installHelpBtn",
5867
- "desc": "zISxCG_desc",
5868
- "helpCmd": "zISxCG_helpCmd",
5869
- "installError": "zISxCG_installError",
5870
- "helpNote": "zISxCG_helpNote",
5871
5871
  "installInputError": "zISxCG_installInputError",
5872
+ "installError": "zISxCG_installError",
5873
+ "installExample": "zISxCG_installExample",
5872
5874
  "helpLine": "zISxCG_helpLine",
5875
+ "installInput": "zISxCG_installInput",
5876
+ "installLabel": "zISxCG_installLabel",
5877
+ "helpNote": "zISxCG_helpNote",
5878
+ "channelOffBtn": "zISxCG_channelOffBtn",
5879
+ "installCards": "zISxCG_installCards",
5873
5880
  "installCardHead": "zISxCG_installCardHead",
5874
- "channelOffText": "zISxCG_channelOffText",
5875
5881
  "channelOff": "zISxCG_channelOff",
5876
- "channelOffBtn": "zISxCG_channelOffBtn",
5877
5882
  "installCard": "zISxCG_installCard",
5878
- "root": "zISxCG_root",
5879
- "installInput": "zISxCG_installInput",
5880
- "installLabel": "zISxCG_installLabel",
5881
- "installBtn": "zISxCG_installBtn"
5883
+ "helpBody": "zISxCG_helpBody",
5884
+ "desc": "zISxCG_desc",
5885
+ "installHelpBtn": "zISxCG_installHelpBtn",
5886
+ "installRow": "zISxCG_installRow",
5887
+ "installBtn": "zISxCG_installBtn",
5888
+ "channelOffText": "zISxCG_channelOffText",
5889
+ "helpCmd": "zISxCG_helpCmd",
5890
+ "root": "zISxCG_root"
5882
5891
  };
5883
5892
  //#endregion
5884
5893
  //#region src/client/components/views/CustomInstallView.tsx
@@ -5897,13 +5906,13 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
5897
5906
  /** npm 包名(含 @scope/pkg) */
5898
5907
  const NPM_PACKAGE_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/;
5899
5908
  /** npm 全局安装命令(官方 README 格式,如 `npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui`)——
5900
- * 提取 -g 之后的包列表;任一包名非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 口径一致。 */
5909
+ * 提取 -g 之后的包列表;任一包名非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 规则一致。 */
5901
5910
  const NPM_GLOBAL_CMD_RE = /^npm\s+(?:install|i)\s+(?:-g|--global)\s+(.+)$/i;
5902
5911
  /** 常规 npm/pnpm 安装命令(装进当前 profile,如 `npm install lodash`、`pnpm add @scope/pkg`)——
5903
5912
  * 提取命令后的包列表;包列表在 splitPackages 里逐个校验。 */
5904
5913
  const NPM_INSTALL_CMD_RE = /^(?:npm\s+(?:install|i)|pnpm\s+(?:add|i|install))\s+(.+)$/i;
5905
5914
  /** 空格分隔的包列表:逐个按 npm 包名语法校验 + 拒绝以 - 开头的 token(npm 会把 --xxx 当参数而非包名),
5906
- * 任一非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 同口径。 */
5915
+ * 任一非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 同一套规则。 */
5907
5916
  function splitPackages(raw) {
5908
5917
  const packages = raw.trim().split(/\s+/).filter((p) => p !== "");
5909
5918
  if (packages.length === 0 || packages.some((p) => !NPM_PACKAGE_RE.test(p) || p.startsWith("-"))) return null;
@@ -6034,30 +6043,30 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6034
6043
  css: css$5
6035
6044
  });
6036
6045
  var SettingsView_module_css_default = {
6037
- "controlDropdown": "_506LLG_controlDropdown",
6038
- "settingDesc": "_506LLG_settingDesc",
6039
- "proxyHintFail": "_506LLG_proxyHintFail",
6046
+ "navIcon": "_506LLG_navIcon",
6047
+ "proxyHint": "_506LLG_proxyHint",
6040
6048
  "navItem": "_506LLG_navItem",
6041
6049
  "pageTitle": "_506LLG_pageTitle",
6042
- "settingLabel": "_506LLG_settingLabel",
6043
- "settingTitle": "_506LLG_settingTitle",
6044
- "root": "_506LLG_root",
6045
- "settingControl": "_506LLG_settingControl",
6046
- "pageHeader": "_506LLG_pageHeader",
6050
+ "content": "_506LLG_content",
6047
6051
  "pageDesc": "_506LLG_pageDesc",
6048
- "settingRow": "_506LLG_settingRow",
6049
- "navIcon": "_506LLG_navIcon",
6050
- "card": "_506LLG_card",
6051
- "proxyHint": "_506LLG_proxyHint",
6052
- "settingControlStack": "_506LLG_settingControlStack",
6053
- "settingRowStack": "_506LLG_settingRowStack",
6054
6052
  "textInput": "_506LLG_textInput",
6055
- "sidebar": "_506LLG_sidebar",
6056
- "content": "_506LLG_content",
6053
+ "card": "_506LLG_card",
6054
+ "proxyHintOk": "_506LLG_proxyHintOk",
6057
6055
  "proxyControl": "_506LLG_proxyControl",
6056
+ "settingDesc": "_506LLG_settingDesc",
6057
+ "pageHeader": "_506LLG_pageHeader",
6058
+ "controlDropdown": "_506LLG_controlDropdown",
6059
+ "settingControlStack": "_506LLG_settingControlStack",
6060
+ "root": "_506LLG_root",
6061
+ "settingTitle": "_506LLG_settingTitle",
6062
+ "proxyHintFail": "_506LLG_proxyHintFail",
6063
+ "settingControl": "_506LLG_settingControl",
6058
6064
  "resetBtn": "_506LLG_resetBtn",
6059
- "proxyHintOk": "_506LLG_proxyHintOk",
6060
- "navItemActive": "_506LLG_navItemActive"
6065
+ "navItemActive": "_506LLG_navItemActive",
6066
+ "settingRow": "_506LLG_settingRow",
6067
+ "settingRowStack": "_506LLG_settingRowStack",
6068
+ "settingLabel": "_506LLG_settingLabel",
6069
+ "sidebar": "_506LLG_sidebar"
6061
6070
  };
6062
6071
  //#endregion
6063
6072
  //#region \0dsh-css:src/client/styles/Dropdown.module.css.mjs
@@ -6076,18 +6085,18 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6076
6085
  css: css$4
6077
6086
  });
6078
6087
  var Dropdown_module_css_default = {
6079
- "dropdownCountActive": "B_Gxsq_dropdownCountActive",
6080
- "dropdownArrow": "B_Gxsq_dropdownArrow",
6081
- "dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
6082
- "dropdownItem": "B_Gxsq_dropdownItem",
6083
6088
  "dropdownCount": "B_Gxsq_dropdownCount",
6084
- "dropdownFill": "B_Gxsq_dropdownFill",
6085
- "dropdownBtn": "B_Gxsq_dropdownBtn",
6086
6089
  "dropdown": "B_Gxsq_dropdown",
6090
+ "dropdownItemActive": "B_Gxsq_dropdownItemActive",
6091
+ "dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
6087
6092
  "dropdownArrowOpen": "B_Gxsq_dropdownArrowOpen",
6093
+ "dropdownFill": "B_Gxsq_dropdownFill",
6094
+ "dropdownArrow": "B_Gxsq_dropdownArrow",
6088
6095
  "dropdownPanel": "B_Gxsq_dropdownPanel",
6089
- "dropdownItemActive": "B_Gxsq_dropdownItemActive",
6090
- "dropdownLabel": "B_Gxsq_dropdownLabel"
6096
+ "dropdownCountActive": "B_Gxsq_dropdownCountActive",
6097
+ "dropdownLabel": "B_Gxsq_dropdownLabel",
6098
+ "dropdownBtn": "B_Gxsq_dropdownBtn",
6099
+ "dropdownItem": "B_Gxsq_dropdownItem"
6091
6100
  };
6092
6101
  //#endregion
6093
6102
  //#region \0dsh-css:src/client/styles/Toggle.module.css.mjs
@@ -6106,8 +6115,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6106
6115
  css: css$3
6107
6116
  });
6108
6117
  var Toggle_module_css_default = {
6109
- "toggleOn": "k-cD4G_toggleOn",
6110
6118
  "knob": "k-cD4G_knob",
6119
+ "toggleOn": "k-cD4G_toggleOn",
6111
6120
  "toggle": "k-cD4G_toggle"
6112
6121
  };
6113
6122
  //#endregion
@@ -6205,29 +6214,29 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6205
6214
  css: css$2
6206
6215
  });
6207
6216
  var DiagnosticsView_module_css_default = {
6208
- "summaryOk": "k9eRya_summaryOk",
6217
+ "envLabel": "k9eRya_envLabel",
6218
+ "envTitle": "k9eRya_envTitle",
6219
+ "name": "k9eRya_name",
6209
6220
  "diagPulse": "k9eRya_diagPulse",
6221
+ "envRow": "k9eRya_envRow",
6210
6222
  "meta": "k9eRya_meta",
6211
- "badge": "k9eRya_badge",
6212
- "envCopyBtn": "k9eRya_envCopyBtn",
6213
- "panel": "k9eRya_panel",
6214
- "display": "k9eRya_display",
6223
+ "summaryFail": "k9eRya_summaryFail",
6224
+ "runBtn": "k9eRya_runBtn",
6215
6225
  "row": "k9eRya_row",
6216
6226
  "badgeRunning": "k9eRya_badgeRunning",
6217
- "runBtn": "k9eRya_runBtn",
6218
- "name": "k9eRya_name",
6219
- "summaryRunning": "k9eRya_summaryRunning",
6220
- "head": "k9eRya_head",
6221
6227
  "summary": "k9eRya_summary",
6222
- "summaryFail": "k9eRya_summaryFail",
6223
- "envTitle": "k9eRya_envTitle",
6224
- "badgeOk": "k9eRya_badgeOk",
6225
- "badgeFail": "k9eRya_badgeFail",
6228
+ "summaryRunning": "k9eRya_summaryRunning",
6226
6229
  "headHint": "k9eRya_headHint",
6227
- "badgeIdle": "k9eRya_badgeIdle",
6228
6230
  "envDesc": "k9eRya_envDesc",
6229
- "envRow": "k9eRya_envRow",
6230
- "envLabel": "k9eRya_envLabel"
6231
+ "badgeIdle": "k9eRya_badgeIdle",
6232
+ "head": "k9eRya_head",
6233
+ "badge": "k9eRya_badge",
6234
+ "envCopyBtn": "k9eRya_envCopyBtn",
6235
+ "badgeFail": "k9eRya_badgeFail",
6236
+ "badgeOk": "k9eRya_badgeOk",
6237
+ "display": "k9eRya_display",
6238
+ "summaryOk": "k9eRya_summaryOk",
6239
+ "panel": "k9eRya_panel"
6231
6240
  };
6232
6241
  //#endregion
6233
6242
  //#region src/client/components/views/DiagnosticsView.tsx
@@ -6402,57 +6411,57 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6402
6411
  css: css$1
6403
6412
  });
6404
6413
  var LogsView_module_css_default = {
6405
- "btn": "_3j77BW_btn",
6406
- "message": "_3j77BW_message",
6414
+ "footPath": "_3j77BW_footPath",
6407
6415
  "more": "_3j77BW_more",
6408
- "filterBar": "_3j77BW_filterBar",
6409
- "head": "_3j77BW_head",
6410
- "time": "_3j77BW_time",
6411
- "previewRow": "_3j77BW_previewRow",
6412
- "headHint": "_3j77BW_headHint",
6413
- "badge": "_3j77BW_badge",
6414
- "badgeDebug": "_3j77BW_badgeDebug",
6415
6416
  "event": "_3j77BW_event",
6416
- "linkBtn": "_3j77BW_linkBtn",
6417
- "search": "_3j77BW_search",
6418
- "logList": "_3j77BW_logList",
6419
- "pathLabel": "_3j77BW_pathLabel",
6420
- "pathDialogHint": "_3j77BW_pathDialogHint",
6421
- "badgeWarn": "_3j77BW_badgeWarn",
6422
- "catUpdate": "_3j77BW_catUpdate",
6423
- "catSystem": "_3j77BW_catSystem",
6417
+ "badgeInfo": "_3j77BW_badgeInfo",
6424
6418
  "actions": "_3j77BW_actions",
6419
+ "pathLabel": "_3j77BW_pathLabel",
6420
+ "pathDialogFoot": "_3j77BW_pathDialogFoot",
6421
+ "time": "_3j77BW_time",
6422
+ "search": "_3j77BW_search",
6423
+ "catBadge": "_3j77BW_catBadge",
6424
+ "badgeSuccess": "_3j77BW_badgeSuccess",
6425
6425
  "filterChipActive": "_3j77BW_filterChipActive",
6426
- "footFail": "_3j77BW_footFail",
6427
- "footCount": "_3j77BW_footCount",
6426
+ "catUpdate": "_3j77BW_catUpdate",
6427
+ "pathDraft": "_3j77BW_pathDraft",
6428
+ "pathDialogDesc": "_3j77BW_pathDialogDesc",
6428
6429
  "catSettings": "_3j77BW_catSettings",
6429
- "catDiagnostics": "_3j77BW_catDiagnostics",
6430
- "pathRow": "_3j77BW_pathRow",
6430
+ "panel": "_3j77BW_panel",
6431
6431
  "entry": "_3j77BW_entry",
6432
- "list": "_3j77BW_list",
6433
- "pathText": "_3j77BW_pathText",
6434
- "pathDialog": "_3j77BW_pathDialog",
6435
- "pathDraft": "_3j77BW_pathDraft",
6436
- "moreEnd": "_3j77BW_moreEnd",
6437
- "pathDialogFoot": "_3j77BW_pathDialogFoot",
6438
6432
  "headActions": "_3j77BW_headActions",
6439
- "footPath": "_3j77BW_footPath",
6440
- "badgeError": "_3j77BW_badgeError",
6433
+ "catSystem": "_3j77BW_catSystem",
6434
+ "catDiagnostics": "_3j77BW_catDiagnostics",
6435
+ "pathRow": "_3j77BW_pathRow",
6436
+ "footCount": "_3j77BW_footCount",
6437
+ "badgeWarn": "_3j77BW_badgeWarn",
6441
6438
  "empty": "_3j77BW_empty",
6439
+ "list": "_3j77BW_list",
6440
+ "head": "_3j77BW_head",
6441
+ "footFail": "_3j77BW_footFail",
6442
+ "filterBar": "_3j77BW_filterBar",
6442
6443
  "pathDialogRow": "_3j77BW_pathDialogRow",
6443
6444
  "pathDialogReset": "_3j77BW_pathDialogReset",
6444
- "pathDialogDesc": "_3j77BW_pathDialogDesc",
6445
- "foot": "_3j77BW_foot",
6446
- "panel": "_3j77BW_panel",
6447
- "badgeInfo": "_3j77BW_badgeInfo",
6445
+ "clearBtn": "_3j77BW_clearBtn",
6446
+ "headHint": "_3j77BW_headHint",
6447
+ "pathText": "_3j77BW_pathText",
6448
6448
  "catInstall": "_3j77BW_catInstall",
6449
+ "message": "_3j77BW_message",
6450
+ "foot": "_3j77BW_foot",
6451
+ "pathDialog": "_3j77BW_pathDialog",
6452
+ "filterChip": "_3j77BW_filterChip",
6453
+ "pathDialogHint": "_3j77BW_pathDialogHint",
6454
+ "btn": "_3j77BW_btn",
6455
+ "searchInput": "_3j77BW_searchInput",
6456
+ "logList": "_3j77BW_logList",
6449
6457
  "footActions": "_3j77BW_footActions",
6458
+ "badgeDebug": "_3j77BW_badgeDebug",
6459
+ "moreEnd": "_3j77BW_moreEnd",
6450
6460
  "catUninstall": "_3j77BW_catUninstall",
6451
- "searchInput": "_3j77BW_searchInput",
6452
- "badgeSuccess": "_3j77BW_badgeSuccess",
6453
- "filterChip": "_3j77BW_filterChip",
6454
- "clearBtn": "_3j77BW_clearBtn",
6455
- "catBadge": "_3j77BW_catBadge"
6461
+ "linkBtn": "_3j77BW_linkBtn",
6462
+ "badge": "_3j77BW_badge",
6463
+ "previewRow": "_3j77BW_previewRow",
6464
+ "badgeError": "_3j77BW_badgeError"
6456
6465
  };
6457
6466
  //#endregion
6458
6467
  //#region src/client/components/modals/LogsModal.tsx
@@ -6813,7 +6822,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
6813
6822
  setSaving(false);
6814
6823
  }
6815
6824
  };
6816
- /** 选择目录:系统对话框从默认位置打开,选中路径回填输入框(仍可手改)。 */
6825
+ /** 选择目录:系统对话框从默认位置打开,选中路径填入输入框(仍可手改)。 */
6817
6826
  const browse = async () => {
6818
6827
  if (browsing) return;
6819
6828
  setBrowsing(true);
@@ -7011,7 +7020,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7011
7020
  *
7012
7021
  * 各分组对应本地服务端实际强制的行为:
7013
7022
  * 更新与源 —— 启动检查更新 / npm 镜像 / HTTP 代理(都接进安装命令链路)
7014
- * 安全与信任 —— 受限的自定义安装(服务端 403 门禁)
7023
+ * 安全与信任 —— 受限的自定义安装(服务端 403 拦截)
7015
7024
  * 诊断 —— 实时连通性探测 + 环境快照
7016
7025
  * 日志 —— 系统日志查看器 + 存放位置
7017
7026
  */
@@ -7291,9 +7300,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7291
7300
  const [confirmPlugin, setConfirmPlugin] = (0, react.useState)(null);
7292
7301
  /** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */
7293
7302
  const [confirmIsUpdate, setConfirmIsUpdate] = (0, react.useState)(false);
7294
- /** Hub 自我更新指定的精确版本:连续发版时提示的是「已过供应链门禁」的旧一版,
7295
- * 安装必须钉在该版本上,否则又会被 @latest 带回门禁内的最新版。 */
7303
+ /** 安装要锁定的精确版本:自我更新提示的版本、新安装的已过冷却期版本都要锁定,
7304
+ * 否则 @latest 会被 pnpm 带回冷却期内的旧版。 */
7296
7305
  const [confirmPinVersion, setConfirmPinVersion] = (0, react.useState)(null);
7306
+ /** 冷却期查询的进行中序号:只采用最后一次弹窗的查询结果,避免切换插件后旧结果覆盖 */
7307
+ const installPinSeq = (0, react.useRef)(0);
7297
7308
  /** 命令行安装确认弹窗:记录待安装的裸目标(npm 包名)——
7298
7309
  * 与应用商店同一套确认/进度/结果弹窗,提供时 plugin 传 null 走 customTarget 模式 */
7299
7310
  const [confirmCustomTarget, setConfirmCustomTarget] = (0, react.useState)(null);
@@ -7319,12 +7330,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7319
7330
  /** 安装/卸载完成后的结果视图:停留弹窗内,点「完成」关闭 */
7320
7331
  const [installDone, setInstallDone] = (0, react.useState)(false);
7321
7332
  const [uninstallDone, setUninstallDone] = (0, react.useState)(false);
7322
- /** 结果视图是否给「立即重启」:服务端任务终态带出。仅刷新解决不了的兜底场景
7323
- * (热挂载失败 / 非 dsh 插件 / 更新)为 true;其余(热挂载成功、卸载已即时停用)为 false,
7333
+ /** 结果视图是否给「立即重启」:服务端任务终态带出。仅刷新解决不了的例外场景
7334
+ * (热加载失败 / 非 dsh 插件 / 更新)为 true;其余(热加载成功、卸载已即时停用)为 false,
7324
7335
  * 结果视图只给「完成」,关闭时自动刷新页面生效 */
7325
7336
  const [installNeedsRestart, setInstallNeedsRestart] = (0, react.useState)(false);
7326
7337
  const [uninstallNeedsRestart, setUninstallNeedsRestart] = (0, react.useState)(false);
7327
- /** 结果视图是否显示「关闭后自动刷新」说明:插件已热挂进运行中 loader(安装)、或卸载后
7338
+ /** 结果视图是否显示「关闭后自动刷新」说明:插件已热加载进运行中 loader(安装)、或卸载后
7328
7339
  * 插件面板仍残留在当前页面(卸载)。关闭弹窗即整页刷新,不给手动刷新按钮。 */
7329
7340
  const [installNeedsReload, setInstallNeedsReload] = (0, react.useState)(false);
7330
7341
  /** 市场自更新成功、但 profile 的 bundle 列表里已不含 dsh-plugin:结果页提示重新勾选 */
@@ -7414,7 +7425,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7414
7425
  });
7415
7426
  setNotifications(addFailure({
7416
7427
  kind,
7417
- action: update ? "update" : "install",
7428
+ action: update ? "update" : kind === "uninstall" ? "uninstall" : "install",
7418
7429
  repo: repo ?? "",
7419
7430
  message,
7420
7431
  command,
@@ -7506,7 +7517,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7506
7517
  const timer = window.setTimeout(() => setToast(null), 2400);
7507
7518
  return () => window.clearTimeout(timer);
7508
7519
  }, [toast]);
7509
- /** 复制文本到剪贴板,返回是否成功(Clipboard API + 隐藏 textarea 兜底)。 */
7520
+ /** 复制文本到剪贴板,返回是否成功(Clipboard API + 隐藏 textarea 作为后备)。 */
7510
7521
  const doCopy = async (text) => {
7511
7522
  try {
7512
7523
  await navigator.clipboard.writeText(text);
@@ -7528,7 +7539,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7528
7539
  return ok;
7529
7540
  }
7530
7541
  };
7531
- /** 命令行安装目标是否已安装(与服务端 already 判定同口径):GitHub 地址按仓库身份匹配
7542
+ /** 命令行安装目标是否已安装(与服务端 already 判定同一套规则):GitHub 地址按仓库身份匹配
7532
7543
  * (归一化后比对已装项的 repo/spec),npm 包名按依赖 key 直查。命中 → 弹窗转「更新」语义
7533
7544
  * (mode=update 放行覆盖重装),避免重复点击撞 409 报错。 */
7534
7545
  const customTargetInstalled = (raw) => {
@@ -7543,9 +7554,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7543
7554
  return catalog.installedItems.some((i) => i.name.toLowerCase() === pkg) || Object.keys(catalog.installed).some((k) => k.toLowerCase() === pkg);
7544
7555
  };
7545
7556
  /** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm 安装显示包名命令)。 */
7546
- const copyCommand = async (p) => {
7557
+ const copyCommand = async (p, version) => {
7547
7558
  const repo = p.source?.repo ?? "";
7548
- if (await doCopy(installCommandOf(p))) {
7559
+ if (await doCopy(installCommandOf(p, false, version))) {
7549
7560
  setCopied(repo);
7550
7561
  setToast({
7551
7562
  id: Date.now(),
@@ -7555,6 +7566,19 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7555
7566
  }
7556
7567
  setConfirmPlugin(null);
7557
7568
  };
7569
+ /** 新安装先查「已过 pnpm 发布冷却期」的版本:命令条与执行都锁定它,
7570
+ * 否则 pnpm 会把发布未满 24h 的最新版不提示地回退成很旧的版本。查不到则不锁定,由服务端再解析一次。 */
7571
+ const resolveInstallPin = (p) => {
7572
+ if (p.install?.command !== void 0 && p.install.command !== "") return;
7573
+ const pkg = installTargetOf(p);
7574
+ if (!pkg) return;
7575
+ const seq = ++installPinSeq.current;
7576
+ fetchNpmReleaseAge([pkg]).then((res) => {
7577
+ if (installPinSeq.current !== seq) return;
7578
+ const version = res?.[pkg]?.installable?.version;
7579
+ if (version !== void 0 && version !== "") setConfirmPinVersion(version);
7580
+ });
7581
+ };
7558
7582
  /** 卸载弹窗动作:复制卸载命令,万一直接卸载失败可去终端手动执行。
7559
7583
  * 自定义安装(无目录数据)按已安装项包名直卸,同样给复制通道。 */
7560
7584
  const copyUninstallCommand = async () => {
@@ -7573,7 +7597,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7573
7597
  });
7574
7598
  };
7575
7599
  /** 「立即重启」:POST 同源 /restart,宿主进程自杀重启;随后轮询服务恢复后整页刷新。
7576
- * 只在刷新解决不了的兜底场景(热挂载失败 / 非 dsh 插件 / 更新)出现。
7600
+ * 只在刷新解决不了的例外场景(热加载失败 / 非 dsh 插件 / 更新)出现。
7577
7601
  * 桌面端宿主归应用壳管(服务端回 `desktop: true` 且不重启):不轮询,改提示退出重开。 */
7578
7602
  const requestRestart = async () => {
7579
7603
  if (restarting) return;
@@ -7647,11 +7671,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7647
7671
  copied,
7648
7672
  resultText: catalog.plugins === null || catalog.failed ? null : catalog.category === "all" && count === total ? t("pluginsTotal", { n: count }) : t("filterResults", { n: count }),
7649
7673
  onInstall: (p, opts) => {
7674
+ const update = opts?.update ?? false;
7650
7675
  setInstallDone(false);
7651
- setConfirmIsUpdate(opts?.update ?? false);
7676
+ setConfirmIsUpdate(update);
7652
7677
  setConfirmPinVersion(null);
7678
+ ++installPinSeq.current;
7653
7679
  queue.clearModalTask();
7654
7680
  setConfirmPlugin(p);
7681
+ if (!update) resolveInstallPin(p);
7655
7682
  },
7656
7683
  onUninstall: (p) => {
7657
7684
  setUninstallDone(false);
@@ -7676,6 +7703,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7676
7703
  setInstallDone(false);
7677
7704
  setConfirmIsUpdate(true);
7678
7705
  setConfirmPinVersion(null);
7706
+ ++installPinSeq.current;
7679
7707
  queue.clearModalTask();
7680
7708
  setConfirmPlugin(item.plugin);
7681
7709
  },
@@ -7726,7 +7754,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7726
7754
  openSection: settingsSection,
7727
7755
  onConsumedOpenSection: () => setSettingsSection(null)
7728
7756
  }), showHubUpdate && (0, react.createElement)(HubUpdateModal, {
7729
- info: catalog.hubUpdateTarget ?? catalog.hubUpdateInfo ?? { version: "2.3.1" },
7757
+ info: catalog.hubUpdateTarget ?? catalog.hubUpdateInfo ?? { version: "2.3.3" },
7730
7758
  state: catalog.hubUpdateState,
7731
7759
  currentVersion: catalog.hubCurrentVersion,
7732
7760
  lang,
@@ -7738,6 +7766,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7738
7766
  setInstallDone(false);
7739
7767
  setConfirmIsUpdate(true);
7740
7768
  setConfirmPinVersion(catalog.hubUpdateTarget?.version ?? null);
7769
+ ++installPinSeq.current;
7741
7770
  queue.clearModalTask();
7742
7771
  setConfirmPlugin(hubEntry);
7743
7772
  }
@@ -7816,6 +7845,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7816
7845
  langPath,
7817
7846
  restarting,
7818
7847
  update: confirmIsUpdate,
7848
+ pinVersion: confirmPinVersion ?? void 0,
7819
7849
  cliOnly: confirmPlugin.install?.webInstallable === false || confirmPlugin.install?.manualInstall === true,
7820
7850
  submitting: queue.submitting,
7821
7851
  needsRestart: installNeedsRestart,
@@ -7827,11 +7857,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
7827
7857
  setInstallBundleDeselected(false);
7828
7858
  if (reload) window.location.reload();
7829
7859
  },
7830
- onCopy: () => copyCommand(confirmPlugin),
7831
- onInstall: () => queue.installNow(confirmPlugin, confirmIsUpdate ? {
7832
- update: true,
7860
+ onCopy: () => copyCommand(confirmPlugin, confirmPinVersion ?? void 0),
7861
+ onInstall: () => queue.installNow(confirmPlugin, {
7862
+ update: confirmIsUpdate,
7833
7863
  pinVersion: confirmPinVersion ?? void 0
7834
- } : void 0),
7864
+ }),
7835
7865
  onRestart: () => setShowRestartConfirm(true)
7836
7866
  }), confirmCustomTarget && (0, react.createElement)(InstallModal, {
7837
7867
  plugin: null,