@sparkelf/dsh-plus 0.1.0-rc.35 → 0.1.0-rc.37
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/bin.js +80 -22
- package/lib/types/standalone-profile.d.ts +31 -10
- package/lib/types/standalone-profile.js +97 -26
- package/package.json +31 -27
package/lib/bin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { r as runApply } from "./apply-e0aMC4B4.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
5
|
-
import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join, posix, resolve, win32 } from "node:path";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import semver from "semver";
|
|
@@ -307,7 +307,8 @@ function resolveDistributionDirectory(anchor) {
|
|
|
307
307
|
/** The reviewed bundle order and pins the installed distribution declares. */
|
|
308
308
|
function readDistributionProfile(distributionDirectory) {
|
|
309
309
|
const manifest = requireRecord(JSON.parse(readFileSync(join(distributionDirectory, "package.json"), "utf8")), "Plus distribution manifest");
|
|
310
|
-
const
|
|
310
|
+
const plus = requireRecord(manifest.dshPlus, "dshPlus");
|
|
311
|
+
const profile = requireRecord(plus.profile, "dshPlus.profile");
|
|
311
312
|
const rawDependencies = requireRecord(profile.dependencies, "dshPlus.profile.dependencies");
|
|
312
313
|
const rawAllowBuilds = requireRecord(profile.allowBuilds, "dshPlus.profile.allowBuilds");
|
|
313
314
|
const dependencies = {};
|
|
@@ -326,37 +327,88 @@ function readDistributionProfile(distributionDirectory) {
|
|
|
326
327
|
if (typeof spec !== "string" || spec === "") throw new Error("dshPlus.profile.overrides." + name + " must be a non-empty string");
|
|
327
328
|
overrides[name] = spec;
|
|
328
329
|
}
|
|
330
|
+
const compatibility = requireRecord(plus.compatibility, "dshPlus.compatibility");
|
|
329
331
|
return {
|
|
330
332
|
name: String(manifest.name),
|
|
331
333
|
bundles: requireStringArray(profile.bundles, "dshPlus.profile.bundles"),
|
|
332
334
|
dependencies,
|
|
333
335
|
allowBuilds,
|
|
334
336
|
overrides,
|
|
337
|
+
dshRange: String(compatibility.dsh),
|
|
335
338
|
version: String(manifest.version)
|
|
336
339
|
};
|
|
337
340
|
}
|
|
338
341
|
/**
|
|
339
|
-
*
|
|
342
|
+
* Give the profile its own installed tree, built from the distribution's declarations.
|
|
340
343
|
*
|
|
341
|
-
* The launcher resolves a bundle from the profile directory, so
|
|
342
|
-
* `node_modules
|
|
343
|
-
*
|
|
344
|
+
* The launcher resolves a bundle from the profile directory, so the profile needs its
|
|
345
|
+
* own `node_modules`. Pointing it at the consumer's tree was cheaper, but it made the
|
|
346
|
+
* profile inherit whatever npm had already installed — including the official packages
|
|
347
|
+
* the distribution's `overrides` exist to replace. npm applies `overrides` only from a
|
|
348
|
+
* project's own root, so a profile without its own tree cannot receive them at all, and
|
|
349
|
+
* a patch delivered that way silently never arrives.
|
|
344
350
|
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
351
|
+
* Installing here makes the profile that root: pnpm reads `overrides` from the
|
|
352
|
+
* profile's own `pnpm-workspace.yaml`, which `writeProfileOverrides` writes before this
|
|
353
|
+
* runs. The install is skipped once the tree exists so a start does not pay for it
|
|
354
|
+
* twice; `dsh-plus apply` remains the command that reinstalls after a change.
|
|
349
355
|
*
|
|
350
356
|
* @param paths - resolved standalone paths.
|
|
351
|
-
* @param consumerDirectory - directory whose `node_modules` holds the
|
|
357
|
+
* @param consumerDirectory - directory whose `node_modules` holds the installation.
|
|
352
358
|
*/
|
|
353
|
-
function
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
359
|
+
function installProfilePackages(paths, consumerDirectory) {
|
|
360
|
+
if (!existsSync(join(consumerDirectory, "node_modules"))) throw new Error("no node_modules in " + consumerDirectory + "; run npm install there first");
|
|
361
|
+
const profileModules = join(paths.profileDirectory, "node_modules");
|
|
362
|
+
if (existsSync(profileModules)) {
|
|
363
|
+
linkNestedBundles(paths, profileModules);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
runPnpm(paths.profileDirectory, ["install", "--no-frozen-lockfile"], "pnpm install in the plus profile");
|
|
367
|
+
alignReplacedPackageNames(profileModules);
|
|
368
|
+
linkNestedBundles(paths, profileModules);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Make each replaced package declare the name of the location it occupies.
|
|
372
|
+
*
|
|
373
|
+
* \`overrides\` installs our build at the official path, but the manifest inside still
|
|
374
|
+
* names our scope. The client module system resolves a loader entry's declared name and
|
|
375
|
+
* then requires the manifest it finds to declare that same name
|
|
376
|
+
* (\`client/modules\`: \`name === expectedPackageName\`); a mismatch makes the package own no
|
|
377
|
+
* browser module at all. The symptom is silent — the packages install, the server starts,
|
|
378
|
+
* and the panels those packages render simply never appear.
|
|
379
|
+
*
|
|
380
|
+
* The rewrite replaces the file rather than writing through it: pnpm hard-links a package
|
|
381
|
+
* manifest into its content-addressed store, so an in-place write would edit every
|
|
382
|
+
* profile sharing that store entry.
|
|
383
|
+
*
|
|
384
|
+
* @param profileModules - the profile's \`node_modules\` directory.
|
|
385
|
+
*/
|
|
386
|
+
function alignReplacedPackageNames(profileModules) {
|
|
387
|
+
const scoped = join(profileModules, "@deepseek-ai");
|
|
388
|
+
if (!existsSync(scoped)) return;
|
|
389
|
+
for (const entry of readdirSync(scoped)) {
|
|
390
|
+
const manifestPath = join(scoped, entry, "package.json");
|
|
391
|
+
if (!existsSync(manifestPath)) continue;
|
|
392
|
+
const declared = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
393
|
+
const expected = "@deepseek-ai/" + entry;
|
|
394
|
+
if (declared.name === expected) continue;
|
|
395
|
+
const replaced = {
|
|
396
|
+
...declared,
|
|
397
|
+
name: expected
|
|
398
|
+
};
|
|
399
|
+
const temporary = manifestPath + ".dsh-name";
|
|
400
|
+
writeFileSync(temporary, JSON.stringify(replaced, null, 2) + "\n");
|
|
401
|
+
renameSync(temporary, manifestPath);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/** Run pnpm in one directory, inheriting its output. */
|
|
405
|
+
function runPnpm(cwd, args, label) {
|
|
406
|
+
const result = spawnSync(process.platform === "win32" ? "pnpm.cmd" : "pnpm", [...args], {
|
|
407
|
+
cwd,
|
|
408
|
+
stdio: "inherit"
|
|
409
|
+
});
|
|
410
|
+
if (result.error !== void 0) throw result.error;
|
|
411
|
+
if (result.status !== 0) throw new Error(label + " failed with exit code " + String(result.status));
|
|
360
412
|
}
|
|
361
413
|
/**
|
|
362
414
|
* Expose the distribution's nested packages at the top level the profile searches.
|
|
@@ -413,10 +465,13 @@ function resolvePaths(anchor, env = process.env) {
|
|
|
413
465
|
* @returns whether this call created the manifest.
|
|
414
466
|
*/
|
|
415
467
|
function ensureProfile(paths, consumerDirectory) {
|
|
416
|
-
linkConsumerPackages(paths, consumerDirectory);
|
|
417
468
|
const manifestPath = join(paths.profileDirectory, "package.json");
|
|
418
|
-
if (existsSync(manifestPath)) return false;
|
|
419
469
|
const distribution = readDistributionProfile(paths.distributionDirectory);
|
|
470
|
+
if (existsSync(manifestPath)) {
|
|
471
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
472
|
+
installProfilePackages(paths, consumerDirectory);
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
420
475
|
mkdirSync(paths.profileDirectory, { recursive: true });
|
|
421
476
|
const manifest = {
|
|
422
477
|
name: "dsh-profile-plus",
|
|
@@ -424,6 +479,7 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
424
479
|
type: "module",
|
|
425
480
|
dependencies: {
|
|
426
481
|
"@sparkelf/dsh-plus": distribution.version,
|
|
482
|
+
"@deepseek-ai/dsh": distribution.dshRange,
|
|
427
483
|
...distribution.dependencies
|
|
428
484
|
},
|
|
429
485
|
dsh: { profile: {
|
|
@@ -432,7 +488,8 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
432
488
|
} }
|
|
433
489
|
};
|
|
434
490
|
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
435
|
-
writeProfileOverrides(paths.profileDirectory, distribution.overrides);
|
|
491
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
492
|
+
installProfilePackages(paths, consumerDirectory);
|
|
436
493
|
return true;
|
|
437
494
|
}
|
|
438
495
|
/**
|
|
@@ -445,13 +502,14 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
445
502
|
* @param profileDirectory - the standalone profile directory.
|
|
446
503
|
* @param overrides - official package name to published replacement spec.
|
|
447
504
|
*/
|
|
448
|
-
function writeProfileOverrides(profileDirectory, overrides) {
|
|
505
|
+
function writeProfileOverrides(profileDirectory, overrides, allowBuilds) {
|
|
449
506
|
const workspacePath = join(profileDirectory, "pnpm-workspace.yaml");
|
|
450
507
|
const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, "utf8") : "");
|
|
451
508
|
const [documentError] = document.errors;
|
|
452
509
|
if (documentError !== void 0) throw new Error("Plus profile workspace is not valid YAML", { cause: documentError });
|
|
453
510
|
if (document.get("packages") === void 0) document.set("packages", ["."]);
|
|
454
511
|
for (const [name, spec] of Object.entries(overrides)) document.setIn(["overrides", name], spec);
|
|
512
|
+
for (const [name, allowed] of Object.entries(allowBuilds)) document.setIn(["allowBuilds", name], allowed);
|
|
455
513
|
if (document.get("nodeLinker") === void 0) document.set("nodeLinker", "hoisted");
|
|
456
514
|
if (document.get("autoInstallPeers") === void 0) document.set("autoInstallPeers", false);
|
|
457
515
|
writeFileSync(workspacePath, String(document));
|
|
@@ -55,24 +55,45 @@ export declare function readDistributionProfile(distributionDirectory: string):
|
|
|
55
55
|
readonly dependencies: Readonly<Record<string, string>>;
|
|
56
56
|
readonly allowBuilds: Readonly<Record<string, boolean>>;
|
|
57
57
|
readonly overrides: Readonly<Record<string, string>>;
|
|
58
|
+
readonly dshRange: string;
|
|
58
59
|
readonly version: string;
|
|
59
60
|
};
|
|
60
61
|
/**
|
|
61
|
-
*
|
|
62
|
+
* Give the profile its own installed tree, built from the distribution's declarations.
|
|
62
63
|
*
|
|
63
|
-
* The launcher resolves a bundle from the profile directory, so
|
|
64
|
-
* `node_modules
|
|
65
|
-
*
|
|
64
|
+
* The launcher resolves a bundle from the profile directory, so the profile needs its
|
|
65
|
+
* own `node_modules`. Pointing it at the consumer's tree was cheaper, but it made the
|
|
66
|
+
* profile inherit whatever npm had already installed — including the official packages
|
|
67
|
+
* the distribution's `overrides` exist to replace. npm applies `overrides` only from a
|
|
68
|
+
* project's own root, so a profile without its own tree cannot receive them at all, and
|
|
69
|
+
* a patch delivered that way silently never arrives.
|
|
66
70
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
+
* Installing here makes the profile that root: pnpm reads `overrides` from the
|
|
72
|
+
* profile's own `pnpm-workspace.yaml`, which `writeProfileOverrides` writes before this
|
|
73
|
+
* runs. The install is skipped once the tree exists so a start does not pay for it
|
|
74
|
+
* twice; `dsh-plus apply` remains the command that reinstalls after a change.
|
|
71
75
|
*
|
|
72
76
|
* @param paths - resolved standalone paths.
|
|
73
|
-
* @param consumerDirectory - directory whose `node_modules` holds the
|
|
77
|
+
* @param consumerDirectory - directory whose `node_modules` holds the installation.
|
|
74
78
|
*/
|
|
75
|
-
export declare function
|
|
79
|
+
export declare function installProfilePackages(paths: StandalonePaths, consumerDirectory: string): void;
|
|
80
|
+
/**
|
|
81
|
+
* Make each replaced package declare the name of the location it occupies.
|
|
82
|
+
*
|
|
83
|
+
* \`overrides\` installs our build at the official path, but the manifest inside still
|
|
84
|
+
* names our scope. The client module system resolves a loader entry's declared name and
|
|
85
|
+
* then requires the manifest it finds to declare that same name
|
|
86
|
+
* (\`client/modules\`: \`name === expectedPackageName\`); a mismatch makes the package own no
|
|
87
|
+
* browser module at all. The symptom is silent — the packages install, the server starts,
|
|
88
|
+
* and the panels those packages render simply never appear.
|
|
89
|
+
*
|
|
90
|
+
* The rewrite replaces the file rather than writing through it: pnpm hard-links a package
|
|
91
|
+
* manifest into its content-addressed store, so an in-place write would edit every
|
|
92
|
+
* profile sharing that store entry.
|
|
93
|
+
*
|
|
94
|
+
* @param profileModules - the profile's \`node_modules\` directory.
|
|
95
|
+
*/
|
|
96
|
+
export declare function alignReplacedPackageNames(profileModules: string): void;
|
|
76
97
|
/** Resolve every path a command needs, without creating anything. */
|
|
77
98
|
export declare function resolvePaths(anchor: string, env?: NodeJS.ProcessEnv): StandalonePaths;
|
|
78
99
|
/**
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* bundle's own list.
|
|
10
10
|
*/
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
13
13
|
import { createRequire } from 'node:module';
|
|
14
14
|
import { homedir } from 'node:os';
|
|
15
15
|
import { dirname, join, posix, resolve, win32 } from 'node:path';
|
|
@@ -118,42 +118,93 @@ export function readDistributionProfile(distributionDirectory) {
|
|
|
118
118
|
throw new Error('dshPlus.profile.overrides.' + name + ' must be a non-empty string');
|
|
119
119
|
overrides[name] = spec;
|
|
120
120
|
}
|
|
121
|
+
const compatibility = requireRecord(plus.compatibility, 'dshPlus.compatibility');
|
|
121
122
|
return {
|
|
122
123
|
name: String(manifest.name),
|
|
123
124
|
bundles: requireStringArray(profile.bundles, 'dshPlus.profile.bundles'),
|
|
124
125
|
dependencies,
|
|
125
126
|
allowBuilds,
|
|
126
127
|
overrides,
|
|
128
|
+
dshRange: String(compatibility.dsh),
|
|
127
129
|
version: String(manifest.version),
|
|
128
130
|
};
|
|
129
131
|
}
|
|
130
132
|
/**
|
|
131
|
-
*
|
|
133
|
+
* Give the profile its own installed tree, built from the distribution's declarations.
|
|
132
134
|
*
|
|
133
|
-
* The launcher resolves a bundle from the profile directory, so
|
|
134
|
-
* `node_modules
|
|
135
|
-
*
|
|
135
|
+
* The launcher resolves a bundle from the profile directory, so the profile needs its
|
|
136
|
+
* own `node_modules`. Pointing it at the consumer's tree was cheaper, but it made the
|
|
137
|
+
* profile inherit whatever npm had already installed — including the official packages
|
|
138
|
+
* the distribution's `overrides` exist to replace. npm applies `overrides` only from a
|
|
139
|
+
* project's own root, so a profile without its own tree cannot receive them at all, and
|
|
140
|
+
* a patch delivered that way silently never arrives.
|
|
136
141
|
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
142
|
+
* Installing here makes the profile that root: pnpm reads `overrides` from the
|
|
143
|
+
* profile's own `pnpm-workspace.yaml`, which `writeProfileOverrides` writes before this
|
|
144
|
+
* runs. The install is skipped once the tree exists so a start does not pay for it
|
|
145
|
+
* twice; `dsh-plus apply` remains the command that reinstalls after a change.
|
|
141
146
|
*
|
|
142
147
|
* @param paths - resolved standalone paths.
|
|
143
|
-
* @param consumerDirectory - directory whose `node_modules` holds the
|
|
148
|
+
* @param consumerDirectory - directory whose `node_modules` holds the installation.
|
|
144
149
|
*/
|
|
145
|
-
export function
|
|
146
|
-
const
|
|
147
|
-
if (!existsSync(
|
|
150
|
+
export function installProfilePackages(paths, consumerDirectory) {
|
|
151
|
+
const consumerModules = join(consumerDirectory, 'node_modules');
|
|
152
|
+
if (!existsSync(consumerModules)) {
|
|
148
153
|
throw new Error('no node_modules in ' + consumerDirectory + '; run npm install there first');
|
|
149
154
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
const profileModules = join(paths.profileDirectory, 'node_modules');
|
|
156
|
+
if (existsSync(profileModules)) {
|
|
157
|
+
// A profile installed before the distribution declared overrides still needs the
|
|
158
|
+
// packages it reaches from the consumer tree, which npm nested rather than hoisted.
|
|
159
|
+
linkNestedBundles(paths, profileModules);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
runPnpm(paths.profileDirectory, ['install', '--no-frozen-lockfile'], 'pnpm install in the plus profile');
|
|
163
|
+
alignReplacedPackageNames(profileModules);
|
|
164
|
+
linkNestedBundles(paths, profileModules);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Make each replaced package declare the name of the location it occupies.
|
|
168
|
+
*
|
|
169
|
+
* \`overrides\` installs our build at the official path, but the manifest inside still
|
|
170
|
+
* names our scope. The client module system resolves a loader entry's declared name and
|
|
171
|
+
* then requires the manifest it finds to declare that same name
|
|
172
|
+
* (\`client/modules\`: \`name === expectedPackageName\`); a mismatch makes the package own no
|
|
173
|
+
* browser module at all. The symptom is silent — the packages install, the server starts,
|
|
174
|
+
* and the panels those packages render simply never appear.
|
|
175
|
+
*
|
|
176
|
+
* The rewrite replaces the file rather than writing through it: pnpm hard-links a package
|
|
177
|
+
* manifest into its content-addressed store, so an in-place write would edit every
|
|
178
|
+
* profile sharing that store entry.
|
|
179
|
+
*
|
|
180
|
+
* @param profileModules - the profile's \`node_modules\` directory.
|
|
181
|
+
*/
|
|
182
|
+
export function alignReplacedPackageNames(profileModules) {
|
|
183
|
+
const scoped = join(profileModules, '@deepseek-ai');
|
|
184
|
+
if (!existsSync(scoped))
|
|
185
|
+
return;
|
|
186
|
+
for (const entry of readdirSync(scoped)) {
|
|
187
|
+
const manifestPath = join(scoped, entry, 'package.json');
|
|
188
|
+
if (!existsSync(manifestPath))
|
|
189
|
+
continue;
|
|
190
|
+
const declared = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
191
|
+
const expected = '@deepseek-ai/' + entry;
|
|
192
|
+
if (declared.name === expected)
|
|
193
|
+
continue;
|
|
194
|
+
const replaced = { ...declared, name: expected };
|
|
195
|
+
const temporary = manifestPath + '.dsh-name';
|
|
196
|
+
writeFileSync(temporary, JSON.stringify(replaced, null, 2) + '\n');
|
|
197
|
+
renameSync(temporary, manifestPath);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/** Run pnpm in one directory, inheriting its output. */
|
|
201
|
+
function runPnpm(cwd, args, label) {
|
|
202
|
+
const command = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';
|
|
203
|
+
const result = spawnSync(command, [...args], { cwd, stdio: 'inherit' });
|
|
204
|
+
if (result.error !== undefined)
|
|
205
|
+
throw result.error;
|
|
206
|
+
if (result.status !== 0)
|
|
207
|
+
throw new Error(label + ' failed with exit code ' + String(result.status));
|
|
157
208
|
}
|
|
158
209
|
/**
|
|
159
210
|
* Expose the distribution's nested packages at the top level the profile searches.
|
|
@@ -217,17 +268,30 @@ export function resolvePaths(anchor, env = process.env) {
|
|
|
217
268
|
* @returns whether this call created the manifest.
|
|
218
269
|
*/
|
|
219
270
|
export function ensureProfile(paths, consumerDirectory) {
|
|
220
|
-
linkConsumerPackages(paths, consumerDirectory);
|
|
221
271
|
const manifestPath = join(paths.profileDirectory, 'package.json');
|
|
222
|
-
if (existsSync(manifestPath))
|
|
223
|
-
return false;
|
|
224
272
|
const distribution = readDistributionProfile(paths.distributionDirectory);
|
|
273
|
+
if (existsSync(manifestPath)) {
|
|
274
|
+
// The workspace carries decisions the distribution owns — overrides and the build
|
|
275
|
+
// script allowlist — and a distribution release changes them. Rewriting on every
|
|
276
|
+
// start is what lets an upgraded installation receive the new values; a profile
|
|
277
|
+
// written once keeps whatever its own release decided and can never be corrected.
|
|
278
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
279
|
+
installProfilePackages(paths, consumerDirectory);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
225
282
|
mkdirSync(paths.profileDirectory, { recursive: true });
|
|
226
283
|
const manifest = {
|
|
227
284
|
name: 'dsh-profile-' + STANDALONE_PROFILE,
|
|
228
285
|
private: true,
|
|
229
286
|
type: 'module',
|
|
230
|
-
dependencies: {
|
|
287
|
+
dependencies: {
|
|
288
|
+
'@sparkelf/dsh-plus': distribution.version,
|
|
289
|
+
// The launcher's own tree supplies every service package the bundles mount. A
|
|
290
|
+
// profile that lists only the distribution's plugins installs a partial tree and
|
|
291
|
+
// fails at load with a module the launcher would have carried.
|
|
292
|
+
'@deepseek-ai/dsh': distribution.dshRange,
|
|
293
|
+
...distribution.dependencies,
|
|
294
|
+
},
|
|
231
295
|
dsh: {
|
|
232
296
|
profile: {
|
|
233
297
|
bundles: distribution.bundles,
|
|
@@ -236,7 +300,9 @@ export function ensureProfile(paths, consumerDirectory) {
|
|
|
236
300
|
},
|
|
237
301
|
};
|
|
238
302
|
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
239
|
-
|
|
303
|
+
// The overrides must reach the workspace before the install that reads them.
|
|
304
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
305
|
+
installProfilePackages(paths, consumerDirectory);
|
|
240
306
|
return true;
|
|
241
307
|
}
|
|
242
308
|
/**
|
|
@@ -249,7 +315,7 @@ export function ensureProfile(paths, consumerDirectory) {
|
|
|
249
315
|
* @param profileDirectory - the standalone profile directory.
|
|
250
316
|
* @param overrides - official package name to published replacement spec.
|
|
251
317
|
*/
|
|
252
|
-
function writeProfileOverrides(profileDirectory, overrides) {
|
|
318
|
+
function writeProfileOverrides(profileDirectory, overrides, allowBuilds) {
|
|
253
319
|
const workspacePath = join(profileDirectory, 'pnpm-workspace.yaml');
|
|
254
320
|
const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, 'utf8') : '');
|
|
255
321
|
const [documentError] = document.errors;
|
|
@@ -259,6 +325,11 @@ function writeProfileOverrides(profileDirectory, overrides) {
|
|
|
259
325
|
document.set('packages', ['.']);
|
|
260
326
|
for (const [name, spec] of Object.entries(overrides))
|
|
261
327
|
document.setIn(['overrides', name], spec);
|
|
328
|
+
// pnpm refuses an install whose packages want to run build scripts until each is
|
|
329
|
+
// decided, so the distribution's reviewed decisions travel with the install rather
|
|
330
|
+
// than waiting for an interactive approval no start can offer.
|
|
331
|
+
for (const [name, allowed] of Object.entries(allowBuilds))
|
|
332
|
+
document.setIn(['allowBuilds', name], allowed);
|
|
262
333
|
// The profile resolves bundles from this directory, so peers the official tree would
|
|
263
334
|
// supply have to come from what the consumer installed.
|
|
264
335
|
if (document.get('nodeLinker') === undefined)
|
package/package.json
CHANGED
|
@@ -58,12 +58,16 @@
|
|
|
58
58
|
],
|
|
59
59
|
"profile": {
|
|
60
60
|
"allowBuilds": {
|
|
61
|
-
"@
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
61
|
+
"@deepseek-ai/dsh-subprocess-local@0.1.5-rc.2": true,
|
|
62
|
+
"@google/genai@1.52.0": false,
|
|
63
|
+
"@officecli/officecli@1.0.147": true,
|
|
64
|
+
"cpu-features@0.0.10": false,
|
|
65
|
+
"koffi@3.3.0": true,
|
|
66
|
+
"node-pty@1.1.0": true,
|
|
67
|
+
"node-pty@1.2.0-beta.15": true,
|
|
68
|
+
"oracledb@7.0.1": true,
|
|
69
|
+
"protobufjs@7.6.6": false,
|
|
70
|
+
"ssh2@1.17.0": true
|
|
67
71
|
},
|
|
68
72
|
"bundles": [
|
|
69
73
|
"@deepseek-ai/dsh-base",
|
|
@@ -100,26 +104,26 @@
|
|
|
100
104
|
"dsh-video-preview": "0.1.4"
|
|
101
105
|
},
|
|
102
106
|
"overrides": {
|
|
103
|
-
"@deepseek-ai/dsh-agent-presets": "npm:@sparkelf/dsh-agent-presets@0.1.5-rc.
|
|
104
|
-
"@deepseek-ai/dsh-api-gateway": "npm:@sparkelf/dsh-api-gateway@0.1.5-rc.
|
|
105
|
-
"@deepseek-ai/dsh-api-session-controller": "npm:@sparkelf/dsh-api-session-controller@0.1.5-rc.
|
|
106
|
-
"@deepseek-ai/dsh-client-connection": "npm:@sparkelf/dsh-client-connection@0.1.5-rc.
|
|
107
|
-
"@deepseek-ai/dsh-client-ui-agent-preset": "npm:@sparkelf/dsh-client-ui-agent-preset@0.1.5-rc.
|
|
108
|
-
"@deepseek-ai/dsh-client-ui-conversation": "npm:@sparkelf/dsh-client-ui-conversation@0.1.5-rc.
|
|
109
|
-
"@deepseek-ai/dsh-client-ui-deliverables": "npm:@sparkelf/dsh-client-ui-deliverables@0.1.5-rc.
|
|
110
|
-
"@deepseek-ai/dsh-client-ui-layout": "npm:@sparkelf/dsh-client-ui-layout@0.1.5-rc.
|
|
111
|
-
"@deepseek-ai/dsh-client-ui-model-selection": "npm:@sparkelf/dsh-client-ui-model-selection@0.1.5-rc.
|
|
112
|
-
"@deepseek-ai/dsh-client-ui-primitives": "npm:@sparkelf/dsh-client-ui-primitives@0.1.5-rc.
|
|
113
|
-
"@deepseek-ai/dsh-client-ui-settings-models": "npm:@sparkelf/dsh-client-ui-settings-models@0.1.5-rc.
|
|
114
|
-
"@deepseek-ai/dsh-client-ui-trajectory": "npm:@sparkelf/dsh-client-ui-trajectory@0.1.5-rc.
|
|
115
|
-
"@deepseek-ai/dsh-host-frontend-static": "npm:@sparkelf/dsh-host-frontend-static@0.1.5-rc.
|
|
116
|
-
"@deepseek-ai/dsh-host-webserver": "npm:@sparkelf/dsh-host-webserver@0.1.5-rc.
|
|
117
|
-
"@deepseek-ai/dsh-llm-pi-ai": "npm:@sparkelf/dsh-llm-pi-ai@0.1.5-rc.
|
|
118
|
-
"@deepseek-ai/dsh-session-log-export": "npm:@sparkelf/dsh-session-log-export@0.1.5-rc.
|
|
119
|
-
"@deepseek-ai/dsh-tools": "npm:@sparkelf/dsh-tools@0.1.5-rc.
|
|
120
|
-
"@deepseek-ai/dsh-web-app": "npm:@sparkelf/dsh-web-app@0.1.5-rc.
|
|
121
|
-
"@deepseek-ai/dsh-web-frontend": "npm:@sparkelf/dsh-web-frontend@0.1.5-rc.
|
|
122
|
-
"@deepseek-ai/dsh-workspace": "npm:@sparkelf/dsh-workspace@0.1.5-rc.
|
|
107
|
+
"@deepseek-ai/dsh-agent-presets": "npm:@sparkelf/dsh-agent-presets@0.1.5-rc.6",
|
|
108
|
+
"@deepseek-ai/dsh-api-gateway": "npm:@sparkelf/dsh-api-gateway@0.1.5-rc.6",
|
|
109
|
+
"@deepseek-ai/dsh-api-session-controller": "npm:@sparkelf/dsh-api-session-controller@0.1.5-rc.6",
|
|
110
|
+
"@deepseek-ai/dsh-client-connection": "npm:@sparkelf/dsh-client-connection@0.1.5-rc.6",
|
|
111
|
+
"@deepseek-ai/dsh-client-ui-agent-preset": "npm:@sparkelf/dsh-client-ui-agent-preset@0.1.5-rc.6",
|
|
112
|
+
"@deepseek-ai/dsh-client-ui-conversation": "npm:@sparkelf/dsh-client-ui-conversation@0.1.5-rc.6",
|
|
113
|
+
"@deepseek-ai/dsh-client-ui-deliverables": "npm:@sparkelf/dsh-client-ui-deliverables@0.1.5-rc.6",
|
|
114
|
+
"@deepseek-ai/dsh-client-ui-layout": "npm:@sparkelf/dsh-client-ui-layout@0.1.5-rc.6",
|
|
115
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "npm:@sparkelf/dsh-client-ui-model-selection@0.1.5-rc.6",
|
|
116
|
+
"@deepseek-ai/dsh-client-ui-primitives": "npm:@sparkelf/dsh-client-ui-primitives@0.1.5-rc.6",
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-settings-models": "npm:@sparkelf/dsh-client-ui-settings-models@0.1.5-rc.6",
|
|
118
|
+
"@deepseek-ai/dsh-client-ui-trajectory": "npm:@sparkelf/dsh-client-ui-trajectory@0.1.5-rc.6",
|
|
119
|
+
"@deepseek-ai/dsh-host-frontend-static": "npm:@sparkelf/dsh-host-frontend-static@0.1.5-rc.6",
|
|
120
|
+
"@deepseek-ai/dsh-host-webserver": "npm:@sparkelf/dsh-host-webserver@0.1.5-rc.6",
|
|
121
|
+
"@deepseek-ai/dsh-llm-pi-ai": "npm:@sparkelf/dsh-llm-pi-ai@0.1.5-rc.6",
|
|
122
|
+
"@deepseek-ai/dsh-session-log-export": "npm:@sparkelf/dsh-session-log-export@0.1.5-rc.6",
|
|
123
|
+
"@deepseek-ai/dsh-tools": "npm:@sparkelf/dsh-tools@0.1.5-rc.6",
|
|
124
|
+
"@deepseek-ai/dsh-web-app": "npm:@sparkelf/dsh-web-app@0.1.5-rc.6",
|
|
125
|
+
"@deepseek-ai/dsh-web-frontend": "npm:@sparkelf/dsh-web-frontend@0.1.5-rc.6",
|
|
126
|
+
"@deepseek-ai/dsh-workspace": "npm:@sparkelf/dsh-workspace@0.1.5-rc.6"
|
|
123
127
|
}
|
|
124
128
|
},
|
|
125
129
|
"sourceBase": {
|
|
@@ -162,5 +166,5 @@
|
|
|
162
166
|
},
|
|
163
167
|
"type": "module",
|
|
164
168
|
"types": "lib/types/index.d.ts",
|
|
165
|
-
"version": "0.1.0-rc.
|
|
169
|
+
"version": "0.1.0-rc.37"
|
|
166
170
|
}
|