dshmarket 1.66.34 → 1.66.35
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/official-desktop.js +44 -1
- package/lib/routes.js +14 -2
- package/lib/types/dsh-cli.d.ts +11 -0
- package/package.json +1 -1
- package/src/dsh-cli.ts +11 -0
- package/src/official-desktop.ts +44 -1
- package/src/routes.ts +14 -2
package/lib/official-desktop.js
CHANGED
|
@@ -18,8 +18,48 @@ function detail(error) {
|
|
|
18
18
|
return error.message;
|
|
19
19
|
if (error === undefined)
|
|
20
20
|
return 'plugin manager did not explain the failure';
|
|
21
|
+
const code = managementCode(error);
|
|
22
|
+
const copy = code === undefined ? undefined : REFUSAL_COPY[code];
|
|
23
|
+
// The code stays on the line: it is what the log and the issue report carry.
|
|
24
|
+
if (copy !== undefined)
|
|
25
|
+
return `${copy.zh} / ${copy.en} (${code})`;
|
|
21
26
|
return JSON.stringify(error);
|
|
22
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* What the manager's refusal means, in the user's terms.
|
|
30
|
+
*
|
|
31
|
+
* These codes are the manager's localization keys, not sentences; they used to
|
|
32
|
+
* reach the page as `{"code":"already-installed"}` and, on the update route,
|
|
33
|
+
* wrapped in "restoration of the previous build could not be verified" — alarm
|
|
34
|
+
* about a profile that was never touched (#897). The bilingual half is picked
|
|
35
|
+
* by the same `localizeBilingual` every other server message goes through.
|
|
36
|
+
*/
|
|
37
|
+
const REFUSAL_COPY = {
|
|
38
|
+
'already-installed': {
|
|
39
|
+
zh: '桌面端认为这个包已经装在 profile 里,因此在运行 pnpm 之前就拒绝了这次安装,profile 没有任何改动',
|
|
40
|
+
en: 'the desktop app treats this package as already installed and refused the install before pnpm ran, so the profile is unchanged',
|
|
41
|
+
},
|
|
42
|
+
'not-removable': {
|
|
43
|
+
zh: '这个插件由桌面端自己管理,市场不能移除它',
|
|
44
|
+
en: 'the desktop app manages this plugin itself, so the market cannot remove it',
|
|
45
|
+
},
|
|
46
|
+
'bundle-in-use': {
|
|
47
|
+
zh: '这个插件正在使用中,桌面端不允许现在移除',
|
|
48
|
+
en: 'the plugin is in use, and the desktop app will not remove it right now',
|
|
49
|
+
},
|
|
50
|
+
'stop-profile': {
|
|
51
|
+
zh: '要移除它得先停止这个 profile',
|
|
52
|
+
en: 'removing it requires stopping this profile first',
|
|
53
|
+
},
|
|
54
|
+
'management-required': {
|
|
55
|
+
zh: '这个 profile 由桌面端自己管理,市场不能直接改动',
|
|
56
|
+
en: 'this profile is managed by the desktop app itself, so the market cannot change it',
|
|
57
|
+
},
|
|
58
|
+
'incompatible-version': {
|
|
59
|
+
zh: '这个版本与当前 DSH 不兼容,宿主拒绝安装',
|
|
60
|
+
en: 'this version is not compatible with the running DSH, so the host refused it',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
23
63
|
/** The manager's own refusal code, whether it was returned or thrown. */
|
|
24
64
|
function managementCode(error) {
|
|
25
65
|
const code = error?.code;
|
|
@@ -172,11 +212,14 @@ _profileDirectory) {
|
|
|
172
212
|
stdout: output,
|
|
173
213
|
stderr: message,
|
|
174
214
|
cancelled: current.cancelled || result.application === 'cancelled',
|
|
215
|
+
// No package result means the manager stopped before it ran pnpm: the
|
|
216
|
+
// profile is untouched, and the route must not try to "restore" it.
|
|
217
|
+
wroteNothing: !ok && result.packageResult === undefined,
|
|
175
218
|
};
|
|
176
219
|
}, (error) => {
|
|
177
220
|
const message = detail(error);
|
|
178
221
|
progress.error = message;
|
|
179
|
-
return failure(message, 127);
|
|
222
|
+
return { ...failure(message, 127), wroteNothing: managementCode(error) !== undefined };
|
|
180
223
|
}).finally(() => {
|
|
181
224
|
progress.active = false;
|
|
182
225
|
progress.cancelling = false;
|
package/lib/routes.js
CHANGED
|
@@ -4597,7 +4597,13 @@ export function mountMarketRoutes(host, config, commandRuntime, agentsLookup, ho
|
|
|
4597
4597
|
+ (dropped ? '' : ' (nothing to drop: the profile did not declare it under either key)'));
|
|
4598
4598
|
};
|
|
4599
4599
|
if ((result.exitCode !== 0 || result.timedOut) && !cancelled && result.busy !== true
|
|
4600
|
-
&& !pnpmNeverStarted(result)
|
|
4600
|
+
&& !pnpmNeverStarted(result)
|
|
4601
|
+
// The host refused before running pnpm (#897): nothing was
|
|
4602
|
+
// written, so there is nothing to restore — and the "could not
|
|
4603
|
+
// verify restoration, inspect this profile" warning this block
|
|
4604
|
+
// raises on a failed rollback would be alarm about an untouched
|
|
4605
|
+
// profile.
|
|
4606
|
+
&& result.wroteNothing !== true) {
|
|
4601
4607
|
if (pnpmBlockedByOpenFiles(result)) {
|
|
4602
4608
|
const kept = keepLockedBuild();
|
|
4603
4609
|
rollbackOk = kept.ok;
|
|
@@ -4941,7 +4947,13 @@ export function mountMarketRoutes(host, config, commandRuntime, agentsLookup, ho
|
|
|
4941
4947
|
// Last, so the specific ones above keep the floor they had: this
|
|
4942
4948
|
// only fills the case where every named branch said nothing and
|
|
4943
4949
|
// the user would otherwise get pnpm's stack (#848).
|
|
4944
|
-
|
|
4950
|
+
// The host's own refusal sentence (#897): when it stopped
|
|
4951
|
+
// before running pnpm there is no classifier for its words and
|
|
4952
|
+
// no rollback behind it, so without this the answer carried no
|
|
4953
|
+
// reason at all.
|
|
4954
|
+
error: versionFailureError ?? renamedError ?? trialError ?? brokenEntryError ?? hardFailureRollbackError ?? staleError
|
|
4955
|
+
?? (result.wroteNothing === true && result.stderr.trim() !== '' ? result.stderr.trim() : undefined)
|
|
4956
|
+
?? pnpmFailureMessage(result) ?? undefined,
|
|
4945
4957
|
exitCode: result.exitCode,
|
|
4946
4958
|
timedOut: result.timedOut,
|
|
4947
4959
|
stdout: result.stdout,
|
package/lib/types/dsh-cli.d.ts
CHANGED
|
@@ -161,6 +161,17 @@ export interface InstallResult {
|
|
|
161
161
|
cancelled: boolean;
|
|
162
162
|
/** Desktop's generation-wide package-operation gate rejected the start. */
|
|
163
163
|
busy?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* The host refused before it ran the package manager, so the profile is
|
|
166
|
+
* exactly as it was.
|
|
167
|
+
*
|
|
168
|
+
* The update route answers a failed run by reinstalling the previous build
|
|
169
|
+
* and, when that cannot be verified, tells the user to inspect a profile
|
|
170
|
+
* nothing touched. Desktop's manager has refusals of this kind of its own —
|
|
171
|
+
* it declines a spec it considers already installed before pnpm starts
|
|
172
|
+
* (#897) — and their only true account is "nothing happened".
|
|
173
|
+
*/
|
|
174
|
+
wroteNothing?: boolean;
|
|
164
175
|
/** Package names pnpm reported as having ignored build scripts (ndjson). */
|
|
165
176
|
ignoredBuilds?: string[];
|
|
166
177
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dshmarket",
|
|
3
3
|
"description": "Visual plugin market inside DeepSeek Harness — browse, search, and one-click install community plugins. · DSH 可视化插件市场:逛一逛,点一下,装好。",
|
|
4
|
-
"version": "1.66.
|
|
4
|
+
"version": "1.66.35",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
package/src/dsh-cli.ts
CHANGED
|
@@ -500,6 +500,17 @@ export interface InstallResult {
|
|
|
500
500
|
cancelled: boolean
|
|
501
501
|
/** Desktop's generation-wide package-operation gate rejected the start. */
|
|
502
502
|
busy?: boolean
|
|
503
|
+
/**
|
|
504
|
+
* The host refused before it ran the package manager, so the profile is
|
|
505
|
+
* exactly as it was.
|
|
506
|
+
*
|
|
507
|
+
* The update route answers a failed run by reinstalling the previous build
|
|
508
|
+
* and, when that cannot be verified, tells the user to inspect a profile
|
|
509
|
+
* nothing touched. Desktop's manager has refusals of this kind of its own —
|
|
510
|
+
* it declines a spec it considers already installed before pnpm starts
|
|
511
|
+
* (#897) — and their only true account is "nothing happened".
|
|
512
|
+
*/
|
|
513
|
+
wroteNothing?: boolean
|
|
503
514
|
/** Package names pnpm reported as having ignored build scripts (ndjson). */
|
|
504
515
|
ignoredBuilds?: string[]
|
|
505
516
|
/**
|
package/src/official-desktop.ts
CHANGED
|
@@ -31,9 +31,49 @@ function detail(error: unknown): string {
|
|
|
31
31
|
if (typeof error === 'string') return error
|
|
32
32
|
if (error instanceof Error) return error.message
|
|
33
33
|
if (error === undefined) return 'plugin manager did not explain the failure'
|
|
34
|
+
const code = managementCode(error)
|
|
35
|
+
const copy = code === undefined ? undefined : REFUSAL_COPY[code]
|
|
36
|
+
// The code stays on the line: it is what the log and the issue report carry.
|
|
37
|
+
if (copy !== undefined) return `${copy.zh} / ${copy.en} (${code})`
|
|
34
38
|
return JSON.stringify(error)
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
/**
|
|
42
|
+
* What the manager's refusal means, in the user's terms.
|
|
43
|
+
*
|
|
44
|
+
* These codes are the manager's localization keys, not sentences; they used to
|
|
45
|
+
* reach the page as `{"code":"already-installed"}` and, on the update route,
|
|
46
|
+
* wrapped in "restoration of the previous build could not be verified" — alarm
|
|
47
|
+
* about a profile that was never touched (#897). The bilingual half is picked
|
|
48
|
+
* by the same `localizeBilingual` every other server message goes through.
|
|
49
|
+
*/
|
|
50
|
+
const REFUSAL_COPY: Record<string, { zh: string; en: string }> = {
|
|
51
|
+
'already-installed': {
|
|
52
|
+
zh: '桌面端认为这个包已经装在 profile 里,因此在运行 pnpm 之前就拒绝了这次安装,profile 没有任何改动',
|
|
53
|
+
en: 'the desktop app treats this package as already installed and refused the install before pnpm ran, so the profile is unchanged',
|
|
54
|
+
},
|
|
55
|
+
'not-removable': {
|
|
56
|
+
zh: '这个插件由桌面端自己管理,市场不能移除它',
|
|
57
|
+
en: 'the desktop app manages this plugin itself, so the market cannot remove it',
|
|
58
|
+
},
|
|
59
|
+
'bundle-in-use': {
|
|
60
|
+
zh: '这个插件正在使用中,桌面端不允许现在移除',
|
|
61
|
+
en: 'the plugin is in use, and the desktop app will not remove it right now',
|
|
62
|
+
},
|
|
63
|
+
'stop-profile': {
|
|
64
|
+
zh: '要移除它得先停止这个 profile',
|
|
65
|
+
en: 'removing it requires stopping this profile first',
|
|
66
|
+
},
|
|
67
|
+
'management-required': {
|
|
68
|
+
zh: '这个 profile 由桌面端自己管理,市场不能直接改动',
|
|
69
|
+
en: 'this profile is managed by the desktop app itself, so the market cannot change it',
|
|
70
|
+
},
|
|
71
|
+
'incompatible-version': {
|
|
72
|
+
zh: '这个版本与当前 DSH 不兼容,宿主拒绝安装',
|
|
73
|
+
en: 'this version is not compatible with the running DSH, so the host refused it',
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
37
77
|
/** The manager's own refusal code, whether it was returned or thrown. */
|
|
38
78
|
function managementCode(error: unknown): string | undefined {
|
|
39
79
|
const code = (error as { code?: unknown } | null | undefined)?.code
|
|
@@ -189,11 +229,14 @@ export function createOfficialDesktopRuntime(
|
|
|
189
229
|
stdout: output,
|
|
190
230
|
stderr: message,
|
|
191
231
|
cancelled: current.cancelled || result.application === 'cancelled',
|
|
232
|
+
// No package result means the manager stopped before it ran pnpm: the
|
|
233
|
+
// profile is untouched, and the route must not try to "restore" it.
|
|
234
|
+
wroteNothing: !ok && result.packageResult === undefined,
|
|
192
235
|
}
|
|
193
236
|
}, (error): InstallResult => {
|
|
194
237
|
const message = detail(error)
|
|
195
238
|
progress.error = message
|
|
196
|
-
return failure(message, 127)
|
|
239
|
+
return { ...failure(message, 127), wroteNothing: managementCode(error) !== undefined }
|
|
197
240
|
}).finally(() => {
|
|
198
241
|
progress.active = false
|
|
199
242
|
progress.cancelling = false
|
package/src/routes.ts
CHANGED
|
@@ -4808,7 +4808,13 @@ sendJson(response, 200, { updates })
|
|
|
4808
4808
|
+ (dropped ? '' : ' (nothing to drop: the profile did not declare it under either key)'))
|
|
4809
4809
|
}
|
|
4810
4810
|
if ((result.exitCode !== 0 || result.timedOut) && !cancelled && result.busy !== true
|
|
4811
|
-
&& !pnpmNeverStarted(result)
|
|
4811
|
+
&& !pnpmNeverStarted(result)
|
|
4812
|
+
// The host refused before running pnpm (#897): nothing was
|
|
4813
|
+
// written, so there is nothing to restore — and the "could not
|
|
4814
|
+
// verify restoration, inspect this profile" warning this block
|
|
4815
|
+
// raises on a failed rollback would be alarm about an untouched
|
|
4816
|
+
// profile.
|
|
4817
|
+
&& result.wroteNothing !== true) {
|
|
4812
4818
|
if (pnpmBlockedByOpenFiles(result)) {
|
|
4813
4819
|
const kept = keepLockedBuild()
|
|
4814
4820
|
rollbackOk = kept.ok
|
|
@@ -5170,7 +5176,13 @@ sendJson(response, 200, { updates })
|
|
|
5170
5176
|
// Last, so the specific ones above keep the floor they had: this
|
|
5171
5177
|
// only fills the case where every named branch said nothing and
|
|
5172
5178
|
// the user would otherwise get pnpm's stack (#848).
|
|
5173
|
-
|
|
5179
|
+
// The host's own refusal sentence (#897): when it stopped
|
|
5180
|
+
// before running pnpm there is no classifier for its words and
|
|
5181
|
+
// no rollback behind it, so without this the answer carried no
|
|
5182
|
+
// reason at all.
|
|
5183
|
+
error: versionFailureError ?? renamedError ?? trialError ?? brokenEntryError ?? hardFailureRollbackError ?? staleError
|
|
5184
|
+
?? (result.wroteNothing === true && result.stderr.trim() !== '' ? result.stderr.trim() : undefined)
|
|
5185
|
+
?? pnpmFailureMessage(result) ?? undefined,
|
|
5174
5186
|
exitCode: result.exitCode,
|
|
5175
5187
|
timedOut: result.timedOut,
|
|
5176
5188
|
stdout: result.stdout,
|