dsh-plugin 1.2.0 → 1.3.0

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 +684 -446
  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 +83 -13
  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 +11 -2
  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 +8 -9
  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 +1 -1
  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
  *
@@ -8,7 +8,7 @@
8
8
  * install handler validates the target, then spawns the official dsh CLI
9
9
  * (see services/install/install.ts) and reports the captured result back.
10
10
  */
11
- import { mkdirSync, readFileSync } from 'node:fs'
11
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
12
12
  import type { IncomingMessage, ServerResponse } from 'node:http'
13
13
  import { homedir, release } from 'node:os'
14
14
  import { dirname, join, resolve } from 'node:path'
@@ -37,6 +37,44 @@ const PROFILE_RE = /^[A-Za-z0-9_-]+$/
37
37
  const BODY_LIMIT_BYTES = 4 * 1024
38
38
  const COMMAND_TIMEOUT_MS = 5 * 60 * 1000
39
39
 
40
+ /** 目录/统计数据代理的本地缓存时长:1 小时内重复打开插件中心直接读盘,
41
+ * 不重复走 curl 拉远程 —— 重启宿主后首次打开同样秒开(缓存跨重启存活)。 */
42
+ const CATALOG_CACHE_TTL_MS = 60 * 60 * 1000
43
+
44
+ /** 磁盘缓存内容:原始响应字符串 + 写入时间戳(TTL 判定用)。 */
45
+ interface CatalogCacheEntry {
46
+ at: number
47
+ body: string
48
+ }
49
+
50
+ function catalogCacheFile(profile: string, key: string): string {
51
+ return join(profileDirectory(profile), 'cache', `catalog-${key}.json`)
52
+ }
53
+
54
+ /** 读缓存:文件存在、JSON 合法、未过期 → 返回原始响应字符串;否则 null(视为 miss)。 */
55
+ function readCatalogCache(file: string): string | null {
56
+ try {
57
+ const entry = JSON.parse(readFileSync(file, 'utf8')) as CatalogCacheEntry
58
+ if (entry && typeof entry.at === 'number' && typeof entry.body === 'string'
59
+ && Date.now() - entry.at < CATALOG_CACHE_TTL_MS) {
60
+ return entry.body
61
+ }
62
+ } catch {
63
+ // 文件缺失 / 解析失败 / 字段不完整 → miss,重新拉取覆盖写盘
64
+ }
65
+ return null
66
+ }
67
+
68
+ /** 写缓存:目录不存在则创建;写失败静默忽略(缓存只是加速,不影响功能)。 */
69
+ function writeCatalogCache(file: string, body: string): void {
70
+ try {
71
+ mkdirSync(dirname(file), { recursive: true })
72
+ writeFileSync(file, JSON.stringify({ at: Date.now(), body } satisfies CatalogCacheEntry))
73
+ } catch {
74
+ // 磁盘只读/无权限等极端情况:忽略,继续走直连
75
+ }
76
+ }
77
+
40
78
  function profileDirectory(profile: string): string {
41
79
  return join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'profiles', profile)
42
80
  }
@@ -434,9 +472,21 @@ export function mountPluginHubRoutes(webServer: WebServerService, profile: strin
434
472
  ? settings.proxy
435
473
  : (systemProxy() ?? process.env.HTTPS_PROXY ?? process.env.https_proxy ?? '')
436
474
  const isStats = url.searchParams.get('stats') === '1'
475
+ const lang = url.searchParams.get('lang') === 'en' ? 'en' : 'zh'
437
476
  const target = isStats
438
477
  ? 'https://api.dsh-plugin.org/stats.json'
439
- : `https://api.dsh-plugin.org/plugins.${url.searchParams.get('lang') === 'en' ? 'en' : 'zh'}.json`
478
+ : `https://api.dsh-plugin.org/plugins.${lang}.json`
479
+ // 1 小时本地缓存:命中直接返回(跨重启生效,插件中心秒开),未命中才走 curl 拉远程
480
+ const cacheFile = catalogCacheFile(profile, isStats ? 'stats' : `plugins-${lang}`)
481
+ const cached = readCatalogCache(cacheFile)
482
+ if (cached !== null) {
483
+ try {
484
+ sendJson(response, 200, JSON.parse(cached))
485
+ return
486
+ } catch {
487
+ // 缓存正文损坏:忽略,走重新拉取并覆盖写盘
488
+ }
489
+ }
440
490
  const r = await fetchViaCurl(target, proxy, 20000)
441
491
  if (!r.ok || r.body === '') {
442
492
  sendJson(response, 502, { error: 'catalog fetch failed' })
@@ -444,6 +494,7 @@ export function mountPluginHubRoutes(webServer: WebServerService, profile: strin
444
494
  }
445
495
  try {
446
496
  sendJson(response, 200, JSON.parse(r.body))
497
+ writeCatalogCache(cacheFile, r.body)
447
498
  } catch {
448
499
  sendJson(response, 502, { error: 'catalog fetch returned invalid JSON' })
449
500
  }
@@ -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,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,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,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,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
  *
@@ -30,11 +30,12 @@ export function githubTarget(repo: string): string | null {
30
30
  }
31
31
 
32
32
  /**
33
- * DSH 命令行前缀(`dsh plugin [--profile|-p <p>] add <target>`)—— 提取其中的安装目标;
34
- * 非命令输入原样返回。兼容「直接粘贴完整命令」(防用户输错):--profile 段可选,
35
- * 支持 `-p` 简写与 `--profile=web` 等号形式,命令大小写不敏感。
33
+ * DSH 命令行前缀(官方唯一形式 `dsh plugin --profile <name> add <target>`)—— 提取其中的安装目标;
34
+ * 非命令输入原样返回。兼容「直接粘贴完整命令」(防用户输错):--profile 必填且只有长选项
35
+ * (官方 CLI 无 -p 简写,省略即报错),支持 `--profile=<name>` 等号形式,命令大小写不敏感。
36
+ * 与客户端 CustomInstallView 口径一致。
36
37
  */
37
- const DSH_PLUGIN_CMD_RE = /^dsh\s+plugin\s+(?:(?:--profile|-p)(?:=|\s+)\S+\s*)?add\s+(.+)$/i
38
+ const DSH_PLUGIN_CMD_RE = /^dsh\s+plugin\s+--profile(?:\s+|=)\S+\s+add\s+(.+)$/i
38
39
 
39
40
  export function installTargetOf(value: string): string {
40
41
  const input = typeof value === 'string' ? value.trim() : ''
@@ -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
  *