dsh-m 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core/market.js +34 -7
- package/lib/tools.js +3 -1
- package/package.json +1 -1
- package/registry.json +19 -0
package/lib/core/market.js
CHANGED
|
@@ -674,7 +674,10 @@ function lockResolutionOf(lockText, pkg) {
|
|
|
674
674
|
for (const line of lines) {
|
|
675
675
|
if (body !== null && /^\S/.test(line))
|
|
676
676
|
break; // 顶层新段 → 收集结束
|
|
677
|
-
|
|
677
|
+
// 0.5.1 修复:收尾引号必须可选消耗——pnpm lockfile 对 scoped 包键恒带引号
|
|
678
|
+
//(`'@scope/name@1.2.3':`),旧正则匹配不到任何带引号键,导致 scoped 已装插件
|
|
679
|
+
// 的 lockResolution 恒为 null → derivePrior 误判 restorable:false → 升级被守卫硬拒。
|
|
680
|
+
const keyMatch = /^ '?(?:[^'\n]*node_modules\/)?([^\s':]+)'?:\s*$/.exec(line);
|
|
678
681
|
if (keyMatch) {
|
|
679
682
|
if (body)
|
|
680
683
|
break;
|
|
@@ -690,7 +693,9 @@ function lockResolutionOf(lockText, pkg) {
|
|
|
690
693
|
return null;
|
|
691
694
|
const text = body.join('\n');
|
|
692
695
|
const version = /version:\s*'?([^'\n]+)/.exec(text)?.[1]?.trim();
|
|
693
|
-
|
|
696
|
+
// 0.5.1:integrity 捕获排除 flow 结尾(`,`/`}`/引号)——与 npm-integrity.ts parsePackagesSection
|
|
697
|
+
// 同口径;旧 `(\S+)` 会把 `{integrity: sha512-...}` 的收尾 `}` 一起带进 prior 证据。
|
|
698
|
+
const integrity = /integrity:\s*([^,}\s'"]+)/.exec(text)?.[1]?.trim();
|
|
694
699
|
const commit = /commit:\s*'?([0-9a-f]{40})/.exec(text)?.[1]?.trim();
|
|
695
700
|
if (!version && !integrity && !commit)
|
|
696
701
|
return null;
|
|
@@ -915,7 +920,8 @@ function guardManualRequired(message, violations) {
|
|
|
915
920
|
export async function installEntry(entry, cfg = {}, opts = {}, deps) {
|
|
916
921
|
return withMutationSession(() => installEntryLocked(entry, cfg, opts, deps));
|
|
917
922
|
}
|
|
918
|
-
/** installEntry 主体(session
|
|
923
|
+
/** installEntry 主体(session 区间内)。入口约定:installFromRegistry 走 installEntry(获取 session);
|
|
924
|
+
* upgradePlugin 已持有 session,必须直调本函数——二次获取 session 会自死锁(session 非重入)。 */
|
|
919
925
|
async function installEntryLocked(entry, cfg = {}, opts = {}, deps) {
|
|
920
926
|
const timeoutMs = cfg.timeoutMs ?? 20_000;
|
|
921
927
|
const profileDir = deps?.transaction?.profileDir ?? webProfileDir();
|
|
@@ -936,7 +942,7 @@ async function installEntryLocked(entry, cfg = {}, opts = {}, deps) {
|
|
|
936
942
|
throw new Error(`prior 关联歧义:${prior.reason};拒绝安装(fail-closed)`);
|
|
937
943
|
}
|
|
938
944
|
if (prior.kind === 'dependency' && !prior.state.restorable) {
|
|
939
|
-
throw guardManualRequired(`「${pkg}」的原安装形态(${prior.state.sourceKind === 'other' ? 'link/file 等非 registry 来源' : '
|
|
945
|
+
throw guardManualRequired(`「${pkg}」的原安装形态(${prior.state.sourceKind === 'other' ? 'link/file 等非 registry 来源' : 'pnpm-lock.yaml 未解析出该依赖的 integrity(键缺失或为别名/URL 等非 registry 写法)'})无法自动回退,请先手动处理(卸载或修复后重试)`, [{ pkg, code: 'NO_DSH_MARKER', detail: `prior restorable:false(sourceKind=${prior.state.sourceKind})` }]);
|
|
940
946
|
}
|
|
941
947
|
// npm:无论 latest 还是用户指定 exact,都先读取该精确版本的 dist metadata(事务外解析)
|
|
942
948
|
let version;
|
|
@@ -1051,7 +1057,7 @@ async function installEntryLocked(entry, cfg = {}, opts = {}, deps) {
|
|
|
1051
1057
|
throw new Error(`prior 关联歧义:${candidatePrior.reason};拒绝安装(fail-closed)`);
|
|
1052
1058
|
}
|
|
1053
1059
|
if (candidatePrior.kind === 'dependency' && !candidatePrior.state.restorable) {
|
|
1054
|
-
throw guardManualRequired(`「${candidate}」的原安装形态(link/file
|
|
1060
|
+
throw guardManualRequired(`「${candidate}」的原安装形态(pnpm-lock.yaml 未解析出该依赖的可回退依据——integrity/commit 缺失,或 link/file/别名等非 registry 写法)无法自动回退,请先手动处理(卸载或修复后重试)`, [{ pkg: candidate, code: 'NO_DSH_MARKER', detail: 'candidate 命中 restorable:false prior(lockfile 依据缺失)' }]);
|
|
1055
1061
|
}
|
|
1056
1062
|
const result = await runProfileTransaction({ kind: 'install-github', repo: entry.github, sha, tag, signal: opts.signal }, deps?.transaction ?? {});
|
|
1057
1063
|
if (!result.ok)
|
|
@@ -1168,12 +1174,33 @@ async function upgradePluginLocked(pkg, cfg = {}, opts = {}, deps) {
|
|
|
1168
1174
|
const target = installed.find((it) => it.pkg === pkg);
|
|
1169
1175
|
if (!target)
|
|
1170
1176
|
throw new Error(`web profile 未安装该插件: ${pkg}`);
|
|
1171
|
-
|
|
1177
|
+
let entry = loaded.registry.plugins.find((e) => matchInstalledByEntry(e, [target]));
|
|
1178
|
+
// 0.5.1:合并市场安装的社区条目同样可升级——主清单 miss 时查社区目录
|
|
1179
|
+
if (!entry)
|
|
1180
|
+
entry = await findCommunityUpgradeEntry(target, cfg, opts, deps);
|
|
1172
1181
|
if (!entry)
|
|
1173
1182
|
throw new Error(`「${pkg}」不是经 dsh-m 收录的插件;直接升级请用 dsh plugin update 或先在 registry 收录它`);
|
|
1174
|
-
|
|
1183
|
+
// 0.5.1 修复:直调 installEntryLocked——upgradePlugin 已在 mutation session 区间内,
|
|
1184
|
+
// 再经 installEntry 二次获取 session 会自死锁(session 非重入,见 withMutationSession 契约)。
|
|
1185
|
+
const result = await installEntryLocked(entry, cfg, opts, deps);
|
|
1175
1186
|
return { ...result, fromVersion: target.version };
|
|
1176
1187
|
}
|
|
1188
|
+
/**
|
|
1189
|
+
* 社区条目升级查找(0.5.1):主清单 miss 时按同一 matchInstalledByEntry 语义查社区目录。
|
|
1190
|
+
* 社区清单未启用/不可用/加载异常/未命中 → undefined,由调用方统一报「不是经 dsh-m 收录」。
|
|
1191
|
+
*/
|
|
1192
|
+
async function findCommunityUpgradeEntry(target, cfg, opts, deps) {
|
|
1193
|
+
try {
|
|
1194
|
+
const loaded = await (deps?.fetchCommunityCatalog ?? defaultFetchCommunityCatalog)(cfg, { namespace: opts.namespace ?? 'host', signal: opts.signal });
|
|
1195
|
+
if (!loaded.catalog)
|
|
1196
|
+
return undefined;
|
|
1197
|
+
const adapted = adaptCommunityCatalog(loaded.catalog);
|
|
1198
|
+
return adapted.entries.find((e) => matchInstalledByEntry(e, [target]));
|
|
1199
|
+
}
|
|
1200
|
+
catch {
|
|
1201
|
+
return undefined;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1177
1204
|
/** 自升级(0.5.0 收编:host-api 直调事务的旁路封死):npmLatest + integrity fail-closed + installEntryLocked(session/守卫经 installEntry)。 */
|
|
1178
1205
|
export async function selfUpgrade(pkgName, currentVersion, cfg = {}, opts = {}, deps) {
|
|
1179
1206
|
return withMutationSession(async () => {
|
package/lib/tools.js
CHANGED
|
@@ -337,6 +337,7 @@ export function registerTools(ctx, cfg, deps = {}) {
|
|
|
337
337
|
description: 'Upgrade an installed DSH plugin to the latest version (npm 拉最新精确版 / github 重新锁 HEAD)。pkg 来自 dshm_list 或 dshm_outdated。用户确认升级哪一个之后再调用。After success, tell the user it needs a restart, and offer dshm_restart.',
|
|
338
338
|
parameters: {
|
|
339
339
|
pkg: { type: 'string', required: true, description: '包名 from dshm_list / dshm_outdated' },
|
|
340
|
+
force: { type: 'boolean', description: 'peer 兼容预检不通过且用户已确认风险后置 true(等价 forceIncompatible,跳过 @deepseek-ai/dsh(-*) peer 拦截);守卫拦截(guard)无 force 通道,不受此参数影响。' },
|
|
340
341
|
},
|
|
341
342
|
output: {
|
|
342
343
|
schema: { type: 'object', additionalProperties: true },
|
|
@@ -355,8 +356,9 @@ export function registerTools(ctx, cfg, deps = {}) {
|
|
|
355
356
|
const target = String(args.pkg || '').trim();
|
|
356
357
|
if (!target)
|
|
357
358
|
throw new Error('缺少 pkg');
|
|
359
|
+
const force = args.force === true;
|
|
358
360
|
try {
|
|
359
|
-
return cloneJson(await m.upgradePlugin(target, cfg, { namespace: 'host' }));
|
|
361
|
+
return cloneJson(await m.upgradePlugin(target, cfg, { forceIncompatible: force, namespace: 'host' }));
|
|
360
362
|
}
|
|
361
363
|
catch (err) {
|
|
362
364
|
if (err instanceof InstallGuardError) {
|
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -138,6 +138,25 @@
|
|
|
138
138
|
"github": "iasiv5/dsh-onetree-log",
|
|
139
139
|
"homepage": "https://github.com/iasiv5/dsh-onetree-log"
|
|
140
140
|
},
|
|
141
|
+
{
|
|
142
|
+
"id": "dsh-quota-watch",
|
|
143
|
+
"name": "DSH Quota Watch",
|
|
144
|
+
"description": "侧栏额度监控卡片:显示 GLM Coding Plan 窗口与 Copilot 额度快照,凭据宿主解析,不留存历史;已适配 0.1.7-rc.2,详见仓库。",
|
|
145
|
+
"category": "tools",
|
|
146
|
+
"tags": [
|
|
147
|
+
"配额",
|
|
148
|
+
"监控",
|
|
149
|
+
"GLM",
|
|
150
|
+
"Copilot"
|
|
151
|
+
],
|
|
152
|
+
"verified": [
|
|
153
|
+
"0.1.7-rc.2"
|
|
154
|
+
],
|
|
155
|
+
"source": "npm",
|
|
156
|
+
"npm": "@iasiv5/dsh-quota-watch",
|
|
157
|
+
"github": "iasiv5/dsh-quota-watch",
|
|
158
|
+
"homepage": "https://github.com/iasiv5/dsh-quota-watch"
|
|
159
|
+
},
|
|
141
160
|
{
|
|
142
161
|
"id": "dsh-better-sidebar",
|
|
143
162
|
"name": "DSH Better Sidebar",
|