dsh-plugin 2.2.2 → 2.2.4
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.
|
@@ -18,7 +18,7 @@ import { backfillOperationLog, createOperationLogTap, hasSubstantiveOutput, oper
|
|
|
18
18
|
import { cleanLine, estimateProgress } from '../profile/progress.js';
|
|
19
19
|
import { hasClientUi, isDshPlugin, mountLoadedEntry, removeLoadedEntry } from '../loader.js';
|
|
20
20
|
import { addPendingRestart, clearPendingRestart } from '../profile/pending-restart.js';
|
|
21
|
-
import { addAllowBuildsKey, bundleIncludes, githubRepoOf, parseAllowBuildsKey, profileDirectory } from '../profile/profile.js';
|
|
21
|
+
import { addAllowBuildsKey, bundleIncludes, githubRepoOf, parseAllowBuildsKey, profileDirectory, validPackageName } from '../profile/profile.js';
|
|
22
22
|
import { appendLog } from '../log.js';
|
|
23
23
|
import { commandOnPath, gitMissingDetail } from './preflight.js';
|
|
24
24
|
import { isTransportFailure, registryHost } from './registry-fallback.js';
|
|
@@ -200,14 +200,17 @@ export function desktopCliBootstrap(entry) {
|
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
202
|
* 传给 CLI 的安装目标:钉住版本优先(Hub 自我更新提示的是已过供应链门禁的版本),
|
|
203
|
-
*
|
|
203
|
+
* 其次 npm 的 add/update 都显式 `@latest`;git 源、全局安装、已带版本/tag 的 spec 保持原样。
|
|
204
204
|
*/
|
|
205
205
|
export function npmInstallTargetOf(target, opts) {
|
|
206
206
|
if (opts.global || githubRepoOf(target) !== null)
|
|
207
207
|
return target;
|
|
208
208
|
if (opts.pinned !== undefined && opts.pinned !== '')
|
|
209
209
|
return opts.pinned;
|
|
210
|
-
|
|
210
|
+
// 裸包名才补 @latest:pnpm 对已存在的精确 spec 是幂等的,不显式要求就会留用旧版本
|
|
211
|
+
if (!(opts.update || opts.add) || !validPackageName(target))
|
|
212
|
+
return target;
|
|
213
|
+
return `${target}@latest`;
|
|
211
214
|
}
|
|
212
215
|
function stopChild(child) {
|
|
213
216
|
if (process.platform === 'win32' && child.pid !== undefined) {
|
|
@@ -372,15 +375,13 @@ function spawnMutation(options) {
|
|
|
372
375
|
&& process.versions.electron !== undefined) {
|
|
373
376
|
pushLine(task, '[desktop-cli-fallback] running inside Electron but no desktop CLI bootstrap was found — falling back to dsh on PATH (a desktop-managed profile will be rejected)');
|
|
374
377
|
}
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
// update 动作实际执行 `add <target>@latest`(pnpm 对已存在依赖带显式版本即原位覆盖升级),
|
|
379
|
-
// CLI 动词仍透传 add —— 不执行官方 update 动词,避免与既有覆盖重装机制分叉。
|
|
378
|
+
// 安装/更新 npm 包都显式 @latest:pnpm add <pkg>(无版本)对已存在的精确 spec 是幂等的,
|
|
379
|
+
// 会原样留用旧版本(更新不生效,普通安装也可能装回不支持当前宿主的旧包)。
|
|
380
|
+
// update 动作同样执行 `add <target>@latest`,CLI 动词透传 add,不与官方 update 动词分叉。
|
|
380
381
|
const isUpdate = action === 'update' || updateNpm === true;
|
|
381
382
|
const cliAction = action === 'update' ? 'add' : action;
|
|
382
383
|
// 钉住版本优先于 @latest:提示的是「已过门禁」的版本,装 latest 会被 pnpm 拒绝
|
|
383
|
-
const npmUpdateTarget = npmInstallTargetOf(target, { update: isUpdate, global: isGlobalNpm, pinned: installSpec });
|
|
384
|
+
const npmUpdateTarget = npmInstallTargetOf(target, { update: isUpdate, global: isGlobalNpm, pinned: installSpec, add: cliAction === 'add' });
|
|
384
385
|
const args = isGlobalNpm
|
|
385
386
|
? ['install', '-g', ...(globalNpm ?? [])]
|
|
386
387
|
: [...invocation.prefixArgs, 'plugin', '--profile', profile, cliAction, npmUpdateTarget];
|
|
@@ -40,12 +40,13 @@ export declare function cancelTask(id: number): boolean;
|
|
|
40
40
|
export declare function desktopCliBootstrap(entry: string): string | null;
|
|
41
41
|
/**
|
|
42
42
|
* 传给 CLI 的安装目标:钉住版本优先(Hub 自我更新提示的是已过供应链门禁的版本),
|
|
43
|
-
*
|
|
43
|
+
* 其次 npm 的 add/update 都显式 `@latest`;git 源、全局安装、已带版本/tag 的 spec 保持原样。
|
|
44
44
|
*/
|
|
45
45
|
export declare function npmInstallTargetOf(target: string, opts: {
|
|
46
46
|
update: boolean;
|
|
47
47
|
global: boolean;
|
|
48
48
|
pinned?: string;
|
|
49
|
+
add?: boolean;
|
|
49
50
|
}): string;
|
|
50
51
|
/**
|
|
51
52
|
* 插件变更入队并返回其任务。任务严格串行:队列 worker 只在上一个结束后才启动下一个。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.4",
|
|
4
4
|
"description": "A community plugin marketplace for DeepSeek Harness, built to the official plugin spec — browse, search and install 10000+ human-curated community plugins without leaving the app. · DeepSeek Harness 社区插件市场(遵循官方开发规范):10000+ 人工精选社区插件,每日更新。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
package/src/client/data/hub.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Hub 元数据仓库:自我更新检查与「关注我们」内容背后的 Cloudflare Worker 接口。
|
|
7
7
|
* 失败降级为 null —— 由调用方决定如何兜底(不显示徽标、占位文案),绝不抛错。
|
|
8
8
|
*/
|
|
9
|
-
import type { HubAboutInfo, HubUpdateInfo } from '../types.ts'
|
|
9
|
+
import type { HubAboutInfo, HubUpdateInfo, HubUpdateVersion } from '../types.ts'
|
|
10
10
|
import { HUB_ABOUT_URL, HUB_UPDATE_URL } from '../logic/constants.ts'
|
|
11
11
|
|
|
12
12
|
/** 版本接口是 Pages 静态文件,默认带 CDN 缓存(Cache-Control: public, max-age=43200,
|
|
@@ -18,7 +18,26 @@ function busted(url: string): string {
|
|
|
18
18
|
return `${url}${sep}_t=${Date.now()}`
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/**
|
|
21
|
+
/** 归一化接口下发的 recentVersions:只保留带版本号的条目,其余字段按类型补。
|
|
22
|
+
* 这条数据是「最新版还在 24.5h 门禁内时回退到更早的已过门槛版本」的唯一依据;
|
|
23
|
+
* 入口处漏传会让候选只剩最新版,整体变成 pending —— 用户就永远看不到更新入口。 */
|
|
24
|
+
function recentVersionsOf(value: unknown): HubUpdateVersion[] {
|
|
25
|
+
if (!Array.isArray(value)) return []
|
|
26
|
+
const list: HubUpdateVersion[] = []
|
|
27
|
+
for (const item of value) {
|
|
28
|
+
if (item === null || typeof item !== 'object') continue
|
|
29
|
+
const entry = item as { version?: unknown; publishedAt?: unknown; notes?: unknown }
|
|
30
|
+
if (typeof entry.version !== 'string' || entry.version === '') continue
|
|
31
|
+
list.push({
|
|
32
|
+
version: entry.version,
|
|
33
|
+
...(typeof entry.publishedAt === 'string' ? { publishedAt: entry.publishedAt } : {}),
|
|
34
|
+
...(entry.notes === undefined ? {} : { notes: entry.notes as HubUpdateVersion['notes'] }),
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
return list
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 版本控制中心:最新版本 + Markdown 变更记录 + 最近发版(门禁回退用);不可用返回 null。 */
|
|
22
41
|
export async function fetchHubUpdate(): Promise<HubUpdateInfo | null> {
|
|
23
42
|
try {
|
|
24
43
|
const res = await fetch(busted(HUB_UPDATE_URL), { cache: 'no-store' })
|
|
@@ -27,7 +46,12 @@ export async function fetchHubUpdate(): Promise<HubUpdateInfo | null> {
|
|
|
27
46
|
if (!data) return null
|
|
28
47
|
const version = typeof data.version === 'string' && data.version.length > 0 ? data.version : null
|
|
29
48
|
if (version === null) return null
|
|
30
|
-
return {
|
|
49
|
+
return {
|
|
50
|
+
version,
|
|
51
|
+
publishedAt: data.publishedAt ?? null,
|
|
52
|
+
notes: data.notes ?? null,
|
|
53
|
+
recentVersions: recentVersionsOf(data.recentVersions),
|
|
54
|
+
}
|
|
31
55
|
} catch {
|
|
32
56
|
return null
|
|
33
57
|
}
|
|
@@ -20,7 +20,7 @@ import { cleanLine, estimateProgress } from '../profile/progress.ts'
|
|
|
20
20
|
import type { LoaderHandle } from '../loader.ts'
|
|
21
21
|
import { hasClientUi, isDshPlugin, mountLoadedEntry, removeLoadedEntry } from '../loader.ts'
|
|
22
22
|
import { addPendingRestart, clearPendingRestart } from '../profile/pending-restart.ts'
|
|
23
|
-
import { addAllowBuildsKey, bundleIncludes, githubRepoOf, parseAllowBuildsKey, profileDirectory } from '../profile/profile.ts'
|
|
23
|
+
import { addAllowBuildsKey, bundleIncludes, githubRepoOf, parseAllowBuildsKey, profileDirectory, validPackageName } from '../profile/profile.ts'
|
|
24
24
|
import { appendLog } from '../log.ts'
|
|
25
25
|
import { commandOnPath, gitMissingDetail } from './preflight.ts'
|
|
26
26
|
import { isTransportFailure, registryHost } from './registry-fallback.ts'
|
|
@@ -218,12 +218,14 @@ export function desktopCliBootstrap(entry: string): string | null {
|
|
|
218
218
|
|
|
219
219
|
/**
|
|
220
220
|
* 传给 CLI 的安装目标:钉住版本优先(Hub 自我更新提示的是已过供应链门禁的版本),
|
|
221
|
-
*
|
|
221
|
+
* 其次 npm 的 add/update 都显式 `@latest`;git 源、全局安装、已带版本/tag 的 spec 保持原样。
|
|
222
222
|
*/
|
|
223
|
-
export function npmInstallTargetOf(target: string, opts: { update: boolean; global: boolean; pinned?: string }): string {
|
|
223
|
+
export function npmInstallTargetOf(target: string, opts: { update: boolean; global: boolean; pinned?: string; add?: boolean }): string {
|
|
224
224
|
if (opts.global || githubRepoOf(target) !== null) return target
|
|
225
225
|
if (opts.pinned !== undefined && opts.pinned !== '') return opts.pinned
|
|
226
|
-
|
|
226
|
+
// 裸包名才补 @latest:pnpm 对已存在的精确 spec 是幂等的,不显式要求就会留用旧版本
|
|
227
|
+
if (!(opts.update || opts.add) || !validPackageName(target)) return target
|
|
228
|
+
return `${target}@latest`
|
|
227
229
|
}
|
|
228
230
|
|
|
229
231
|
function stopChild(child: ReturnType<typeof spawn>): void {
|
|
@@ -432,15 +434,13 @@ function spawnMutation(options: {
|
|
|
432
434
|
&& (process.versions as Record<string, string | undefined>).electron !== undefined) {
|
|
433
435
|
pushLine(task, '[desktop-cli-fallback] running inside Electron but no desktop CLI bootstrap was found — falling back to dsh on PATH (a desktop-managed profile will be rejected)')
|
|
434
436
|
}
|
|
435
|
-
//
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
// update 动作实际执行 `add <target>@latest`(pnpm 对已存在依赖带显式版本即原位覆盖升级),
|
|
439
|
-
// CLI 动词仍透传 add —— 不执行官方 update 动词,避免与既有覆盖重装机制分叉。
|
|
437
|
+
// 安装/更新 npm 包都显式 @latest:pnpm add <pkg>(无版本)对已存在的精确 spec 是幂等的,
|
|
438
|
+
// 会原样留用旧版本(更新不生效,普通安装也可能装回不支持当前宿主的旧包)。
|
|
439
|
+
// update 动作同样执行 `add <target>@latest`,CLI 动词透传 add,不与官方 update 动词分叉。
|
|
440
440
|
const isUpdate = action === 'update' || updateNpm === true
|
|
441
441
|
const cliAction = action === 'update' ? 'add' : action
|
|
442
442
|
// 钉住版本优先于 @latest:提示的是「已过门禁」的版本,装 latest 会被 pnpm 拒绝
|
|
443
|
-
const npmUpdateTarget = npmInstallTargetOf(target, { update: isUpdate, global: isGlobalNpm, pinned: installSpec })
|
|
443
|
+
const npmUpdateTarget = npmInstallTargetOf(target, { update: isUpdate, global: isGlobalNpm, pinned: installSpec, add: cliAction === 'add' })
|
|
444
444
|
const args = isGlobalNpm
|
|
445
445
|
? ['install', '-g', ...(globalNpm ?? [])]
|
|
446
446
|
: [...invocation.prefixArgs, 'plugin', '--profile', profile, cliAction, npmUpdateTarget]
|