dshmarket 1.73.2 → 1.73.3
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/pending-updates.js +37 -14
- package/package.json +1 -1
package/lib/pending-updates.js
CHANGED
|
@@ -24,7 +24,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
24
24
|
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
25
25
|
import { dirname, join } from 'node:path';
|
|
26
26
|
import { logEvent } from './log.js';
|
|
27
|
-
import { readInstalledVersion, readManifestDeps, readProfileBundles } from './profile.js';
|
|
27
|
+
import { readInstalledManifest, readInstalledVersion, readManifestDeps, readProfileBundles } from './profile.js';
|
|
28
28
|
const STATE_VERSION = 1;
|
|
29
29
|
/**
|
|
30
30
|
* The per-profile journal file.
|
|
@@ -175,14 +175,29 @@ function managerSucceeded(result) {
|
|
|
175
175
|
|| result.application === 'overridden';
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
178
|
-
* Whether this profile
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
178
|
+
* Whether this profile is actually composed with the package.
|
|
179
|
+
*
|
|
180
|
+
* `readInstalledVersion` only looks at node_modules, and the half-removed
|
|
181
|
+
* state #928 describes is exactly "still on disk, no longer declared" —
|
|
182
|
+
* treating that as settled cleared the record while the plugin was not
|
|
183
|
+
* composed at all (#949 review). Being declared is necessary but not
|
|
184
|
+
* sufficient: a package that loads through the bundle layer is composed only
|
|
185
|
+
* when the profile lists it in `dsh.profile.bundles`, and the desktop manager
|
|
186
|
+
* can fail at its application stage AFTER writing the build and the
|
|
187
|
+
* dependency but BEFORE that row (#928) — the reporter's restart restored
|
|
188
|
+
* files and dependencies, left `dsh.profile.bundles` without the name, and
|
|
189
|
+
* the record said "recorded as finished".
|
|
190
|
+
*
|
|
191
|
+
* The row is required only of a package that declares `dsh.bundle`: a
|
|
192
|
+
* client-only package has no bundle layer to be listed in, and demanding the
|
|
193
|
+
* row of one would reinstall it on every start.
|
|
183
194
|
*/
|
|
184
|
-
function
|
|
185
|
-
if (Object.hasOwn(readManifestDeps(profile, profileDirectory), name))
|
|
195
|
+
function composed(profile, profileDirectory, name) {
|
|
196
|
+
if (!Object.hasOwn(readManifestDeps(profile, profileDirectory), name))
|
|
197
|
+
return false;
|
|
198
|
+
const manifest = readInstalledManifest(profile, name, profileDirectory);
|
|
199
|
+
const dsh = manifest?.dsh;
|
|
200
|
+
if (dsh?.bundle === undefined)
|
|
186
201
|
return true;
|
|
187
202
|
return readProfileBundles(profileDirectory).includes(name);
|
|
188
203
|
}
|
|
@@ -242,16 +257,17 @@ export async function repairInterruptedUpdates(options) {
|
|
|
242
257
|
const pending = journal.list().filter(entry => entry.profile === options.profile);
|
|
243
258
|
for (const entry of pending) {
|
|
244
259
|
const installed = readInstalledVersion(options.profile, entry.name, options.profileDirectory);
|
|
245
|
-
const
|
|
246
|
-
// Settled means
|
|
247
|
-
//
|
|
248
|
-
// removal itself, so it falls
|
|
249
|
-
|
|
260
|
+
const settled = composed(options.profile, options.profileDirectory, entry.name);
|
|
261
|
+
// Settled means every half agrees: the build is on disk, the profile
|
|
262
|
+
// declares it, and a bundle-layer package is listed as one. "On disk but
|
|
263
|
+
// no longer composed" is the interrupted removal itself, so it falls
|
|
264
|
+
// through to the reinstall.
|
|
265
|
+
if (installed !== null && settled && (entry.to === '' || installed === entry.to || installed === entry.from)) {
|
|
250
266
|
journal.finish(entry.id);
|
|
251
267
|
report.finished.push(entry.name);
|
|
252
268
|
continue;
|
|
253
269
|
}
|
|
254
|
-
if (installed !== null &&
|
|
270
|
+
if (installed !== null && settled) {
|
|
255
271
|
journal.bump(entry.id);
|
|
256
272
|
report.failed.push({
|
|
257
273
|
name: entry.name,
|
|
@@ -275,6 +291,13 @@ export async function repairInterruptedUpdates(options) {
|
|
|
275
291
|
if (after === null || (entry.to !== '' && after !== entry.to)) {
|
|
276
292
|
throw new Error(`the desktop app refused the reinstall (${result.application})`);
|
|
277
293
|
}
|
|
294
|
+
// The files landing is not the same answer as the plugin loading:
|
|
295
|
+
// this manager failed at the application stage, which is the step
|
|
296
|
+
// that writes `dsh.profile.bundles` (#928). Finishing here cleared
|
|
297
|
+
// the record for a package the host still would not compose.
|
|
298
|
+
if (!composed(options.profile, options.profileDirectory, entry.name)) {
|
|
299
|
+
throw new Error(`the desktop app wrote ${after} but did not compose it — no dsh.profile.bundles row`);
|
|
300
|
+
}
|
|
278
301
|
journal.finish(entry.id);
|
|
279
302
|
report.reinstalled.push(entry.name);
|
|
280
303
|
logEvent('warn', 'update-repair', `${entry.name}: the interrupted update had already written ${after}; recorded as finished`);
|
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.73.
|
|
4
|
+
"version": "1.73.3",
|
|
5
5
|
"icon": "assets/logo.svg",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|