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.
@@ -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
- error: versionFailureError ?? renamedError ?? trialError ?? brokenEntryError ?? hardFailureRollbackError ?? staleError ?? pnpmFailureMessage(result) ?? undefined,
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,
@@ -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.34",
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
  /**
@@ -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
- error: versionFailureError ?? renamedError ?? trialError ?? brokenEntryError ?? hardFailureRollbackError ?? staleError ?? pnpmFailureMessage(result) ?? undefined,
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,