dshmarket 1.66.33 → 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/client/client.js +3 -3
- 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/client/MarketSection.tsx +7 -3
- package/src/dsh-cli.ts +11 -0
- package/src/official-desktop.ts +44 -1
- package/src/routes.ts +14 -2
package/client/client.js
CHANGED
|
@@ -9587,12 +9587,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
9587
9587
|
const row = recentRowRef.current;
|
|
9588
9588
|
if (row === null || typeof ResizeObserver === "undefined") return;
|
|
9589
9589
|
const observer = new ResizeObserver(([entry]) => {
|
|
9590
|
-
if (entry !== void 0) setRecentColumns(Math.max(1, Math.floor((entry.contentRect.width + 10) / 290)));
|
|
9590
|
+
if (entry !== void 0) setRecentColumns(Math.min(2, Math.max(1, Math.floor((entry.contentRect.width + 10) / 290))));
|
|
9591
9591
|
});
|
|
9592
9592
|
observer.observe(row);
|
|
9593
9593
|
return () => observer.disconnect();
|
|
9594
9594
|
}, [hasRecent, loadError]);
|
|
9595
|
-
const recentPlugins = recentlyAdded.slice(0, recentColumns);
|
|
9595
|
+
const recentPlugins = recentlyAdded.slice(0, recentColumns * 2);
|
|
9596
9596
|
const { currentPage, totalPages, pageSize, goToPage, changePageSize } = usePagination(plugins.length, [
|
|
9597
9597
|
q,
|
|
9598
9598
|
cat,
|
|
@@ -13188,7 +13188,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
|
|
|
13188
13188
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
13189
13189
|
ref: recentRowRef,
|
|
13190
13190
|
className: Market_module_css_default.recentRow,
|
|
13191
|
-
style: { gridTemplateColumns: `repeat(${
|
|
13191
|
+
style: { gridTemplateColumns: `repeat(${recentColumns}, minmax(0, 1fr))` },
|
|
13192
13192
|
children: recentPlugins.map((plugin) => pluginCard(plugin, `recent:${plugin.url}`))
|
|
13193
13193
|
})]
|
|
13194
13194
|
}),
|
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",
|
|
@@ -3074,18 +3074,22 @@ export function MarketSection(props: MarketSectionProps) {
|
|
|
3074
3074
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3075
3075
|
[data, tab, q, cat, timeRange, lang, hostCompatibility, compatibleWithHost, blockedNameSet, installed, repoIdentities, repoHints])
|
|
3076
3076
|
const recentRowRef = useRef<HTMLDivElement>(null)
|
|
3077
|
+
// Two per row, like the grid below it: three across read as a different
|
|
3078
|
+
// list rather than the same one (and left an odd one out at any width).
|
|
3079
|
+
// Two rows of two keeps the block square and the cards the size of the
|
|
3080
|
+
// cards underneath.
|
|
3077
3081
|
const [recentColumns, setRecentColumns] = useState(1)
|
|
3078
3082
|
const hasRecent = recentlyAdded.length > 0
|
|
3079
3083
|
useLayoutEffect(() => {
|
|
3080
3084
|
const row = recentRowRef.current
|
|
3081
3085
|
if (row === null || typeof ResizeObserver === 'undefined') return
|
|
3082
3086
|
const observer = new ResizeObserver(([entry]) => {
|
|
3083
|
-
if (entry !== undefined) setRecentColumns(Math.max(1, Math.floor((entry.contentRect.width + 10) / 290)))
|
|
3087
|
+
if (entry !== undefined) setRecentColumns(Math.min(2, Math.max(1, Math.floor((entry.contentRect.width + 10) / 290))))
|
|
3084
3088
|
})
|
|
3085
3089
|
observer.observe(row)
|
|
3086
3090
|
return () => observer.disconnect()
|
|
3087
3091
|
}, [hasRecent, loadError])
|
|
3088
|
-
const recentPlugins = recentlyAdded.slice(0, recentColumns)
|
|
3092
|
+
const recentPlugins = recentlyAdded.slice(0, recentColumns * 2)
|
|
3089
3093
|
const { currentPage, totalPages, pageSize, goToPage, changePageSize } =
|
|
3090
3094
|
usePagination(plugins.length, [q, cat, sortField, sortDir, timeRange, compatibleWithHost], scrollToTop)
|
|
3091
3095
|
const pagePlugins = plugins.slice((currentPage - 1) * pageSize, currentPage * pageSize)
|
|
@@ -6490,7 +6494,7 @@ export function MarketSection(props: MarketSectionProps) {
|
|
|
6490
6494
|
{hasRecent && (
|
|
6491
6495
|
<section aria-labelledby="dshm-recently-added">
|
|
6492
6496
|
<h3 id="dshm-recently-added" className={css.favoritesSectionHead}>{t('recentlyAdded')}</h3>
|
|
6493
|
-
<div ref={recentRowRef} className={css.recentRow} style={{ gridTemplateColumns: `repeat(${
|
|
6497
|
+
<div ref={recentRowRef} className={css.recentRow} style={{ gridTemplateColumns: `repeat(${recentColumns}, minmax(0, 1fr))` }}>
|
|
6494
6498
|
{recentPlugins.map(plugin => pluginCard(plugin, `recent:${plugin.url}`))}
|
|
6495
6499
|
</div>
|
|
6496
6500
|
</section>
|
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,
|