dsh-plugin 1.4.13 → 1.5.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.
- package/README.en.md +11 -11
- package/README.md +11 -11
- package/client/client.js +345 -301
- package/client/client.js.map +1 -1
- package/lib/http/routes.js +17 -10
- package/lib/services/install/npm-resolve.js +29 -13
- package/lib/services/install/preflight.js +5 -0
- package/lib/services/install/release-target.js +38 -0
- package/lib/services/profile/profile.js +6 -0
- package/lib/types/services/install/npm-resolve.d.ts +22 -0
- package/lib/types/services/install/release-target.d.ts +28 -0
- package/package.json +1 -1
- package/src/client/components/modals/AboutModal.tsx +18 -2
- package/src/client/components/modals/NotificationsModal.tsx +1 -2
- package/src/client/components/modals/modals.tsx +1 -2
- package/src/client/logic/failures.ts +10 -12
- package/src/client/logic/install-command.ts +22 -8
- package/src/server/http/routes.ts +17 -10
- package/src/server/services/install/npm-resolve.ts +41 -13
- package/src/server/services/install/preflight.ts +4 -0
- package/src/server/services/install/release-target.ts +46 -0
- package/src/server/services/profile/profile.ts +5 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
|
|
3
|
+
* Website: https://dsh-plugin.org
|
|
4
|
+
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5
|
+
*
|
|
6
|
+
* 预构建 GitHub release 安装目标(目录权威命令 → 可安装直链)。
|
|
7
|
+
* 部分插件(如 loopx)把构建产物发布成 GitHub release 的 .tgz,仓库 HEAD 反而是
|
|
8
|
+
* monorepo 根、走 git 直装会因缺入口文件失败;目录下发的权威安装命令直接指向该
|
|
9
|
+
* release 包。这里把「目录命令」解析成安全的 release 目标,供客户端选路与服务端
|
|
10
|
+
* 校验共用(单一事实来源,避免两端口径漂移)。
|
|
11
|
+
*
|
|
12
|
+
* 只接受固定形态的 HTTPS `github.com/<owner>/<repo>/releases/download/<tag>/<asset>.tgz`:
|
|
13
|
+
* 目录命令是展示数据、绝非 shell 代码,绝不执行命令文本;跨仓跳转、外部主机、凭据、
|
|
14
|
+
* 移动的 latest 链接、query/fragment、多余 CLI 参数与 shell 片段一律拒绝。
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** release 包目标及其所属仓库身份(owner/repo);非法返回 null。 */
|
|
18
|
+
export interface GithubReleaseTarget {
|
|
19
|
+
/** 规范化后的安装目标(HTTPS 直链) */
|
|
20
|
+
target: string
|
|
21
|
+
/** 该直链所属仓库(owner/repo):供已装态读回、队列去重与展示身份复用 */
|
|
22
|
+
repo: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** 目录权威命令:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同口径)。 */
|
|
26
|
+
const DSH_PLUGIN_CMD_RE = /^dsh[ \t]+plugin[ \t]+--profile(?:[ \t]+|=)[A-Za-z0-9_-]+[ \t]+(?:add|update)[ \t]+(.+)$/i
|
|
27
|
+
|
|
28
|
+
/** 固定形态的 release .tgz 直链:主机、路径段与扩展名全部锁死。 */
|
|
29
|
+
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)$/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 解析一个 release 安装目标。
|
|
33
|
+
* @param value - 目录命令(`dsh plugin --profile web add <url>`)或裸直链。
|
|
34
|
+
* @returns 命中返回 `{ target, repo }`,否则 null。
|
|
35
|
+
*/
|
|
36
|
+
export function githubReleaseTarget(value: string): GithubReleaseTarget | null {
|
|
37
|
+
const input = typeof value === 'string' ? value.trim() : ''
|
|
38
|
+
if (input === '') return null
|
|
39
|
+
const command = DSH_PLUGIN_CMD_RE.exec(input)
|
|
40
|
+
const raw = command !== null ? command[1].trim() : input
|
|
41
|
+
const match = RELEASE_URL_RE.exec(raw)
|
|
42
|
+
if (match === null) return null
|
|
43
|
+
// 拒绝 `.` / `..` 路径段,杜绝借路径穿越跳出 release 目录
|
|
44
|
+
if (match.slice(1).some((part) => part === '.' || part === '..')) return null
|
|
45
|
+
return { target: raw, repo: `${match[1]}/${match[2]}` }
|
|
46
|
+
}
|
|
@@ -10,6 +10,7 @@ import { readFileSync, writeFileSync } from 'node:fs'
|
|
|
10
10
|
import { homedir } from 'node:os'
|
|
11
11
|
import { basename, dirname, join } from 'node:path'
|
|
12
12
|
import { PACKAGE_RE, REPO_RE } from '../install/install-types.ts'
|
|
13
|
+
import { githubReleaseTarget } from '../install/release-target.ts'
|
|
13
14
|
|
|
14
15
|
/** Resolve the active profile from the booted CLI args, falling back to `web`. */
|
|
15
16
|
export function readProfileArg(fallback = 'web'): string {
|
|
@@ -90,6 +91,10 @@ export function globalNpmPackagesOf(value: string): string[] | null {
|
|
|
90
91
|
export function githubRepoOf(value: string): string | null {
|
|
91
92
|
if (typeof value !== 'string') return null
|
|
92
93
|
const input = value.trim()
|
|
94
|
+
// release 直链先归一到仓库身份:目录命令里的固定 HTTPS release 包不是 git 地址,
|
|
95
|
+
// 但它的所属仓库就是 owner/repo —— 已装态读回、去重、展示都要拿到这层身份。
|
|
96
|
+
const release = githubReleaseTarget(input)
|
|
97
|
+
if (release !== null) return release.repo
|
|
93
98
|
if (REPO_RE.test(input)) return input
|
|
94
99
|
const patterns = [
|
|
95
100
|
/^github:([^/]+)\/([^/]+)$/i,
|