@sparkelf/dsh-plus 0.2.0-rc.16 → 0.2.0-rc.18
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/cordis.patch.yml +3 -11
- package/lib/bin.js +66 -14
- package/lib/types/standalone-cli.js +11 -10
- package/lib/types/standalone-profile.d.ts +45 -1
- package/lib/types/standalone-profile.js +84 -5
- package/package.json +47 -33
package/cordis.patch.yml
CHANGED
|
@@ -28,17 +28,9 @@
|
|
|
28
28
|
- id: plus-backup
|
|
29
29
|
name: '@sparkelf/dsh-plugin-backup'
|
|
30
30
|
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
config:
|
|
35
|
-
baseUrl: !!js process.env.DSH_DATAOPS_BASE_URL
|
|
36
|
-
serverName: dataops
|
|
37
|
-
credentialRef: dataops_access_token
|
|
38
|
-
targetCredentialRef: dataops_target_ref
|
|
39
|
-
callbackOrigin: !!js process.env.DSH_DATAOPS_CALLBACK_ORIGIN
|
|
40
|
-
toolCallTimeoutMs: 60000
|
|
41
|
-
failOnStartupError: false
|
|
31
|
+
# DataOps tools belong to the DataOps-managed workspace profile only. A
|
|
32
|
+
# standalone profile must not carry DataOps identity or endpoint config, so
|
|
33
|
+
# this layer mounts no DataOps plugin.
|
|
42
34
|
|
|
43
35
|
# A disabled root node carries the package's Web Settings entry into the
|
|
44
36
|
# client inventory; the startup nodes below exclusively own Host schemas.
|
package/lib/bin.js
CHANGED
|
@@ -532,8 +532,55 @@ async function waitForAuthenticatedUrl(logPath, timeoutMilliseconds) {
|
|
|
532
532
|
* the launcher mounts exactly the bundles the profile names and nothing expands a
|
|
533
533
|
* bundle's own list.
|
|
534
534
|
*/
|
|
535
|
-
/** Profile name a standalone installation owns. */
|
|
535
|
+
/** Profile name a standalone installation owns when its package declares none. */
|
|
536
536
|
const STANDALONE_PROFILE = "plus";
|
|
537
|
+
/**
|
|
538
|
+
* Read the deployment facts the installing package declares.
|
|
539
|
+
*
|
|
540
|
+
* A standalone package describes the profile it materializes and the capabilities it
|
|
541
|
+
* omits, so a reduced variant owns a differently named profile and a reduced install
|
|
542
|
+
* without the distribution naming either. The declaration travels with the package
|
|
543
|
+
* because npm resolves the tree long before any command of ours runs.
|
|
544
|
+
*
|
|
545
|
+
* @param anchor - path inside the installing package's tree.
|
|
546
|
+
* @param fallback - profile name to use when the declaration is absent.
|
|
547
|
+
* @returns the declared profile name and omitted capabilities.
|
|
548
|
+
*/
|
|
549
|
+
function readStandaloneDeclaration(anchor, fallback = STANDALONE_PROFILE) {
|
|
550
|
+
let current = resolve(anchor);
|
|
551
|
+
for (;;) {
|
|
552
|
+
const declared = readStandaloneFacts(join(current, "package.json"));
|
|
553
|
+
if (declared !== void 0) return declared;
|
|
554
|
+
const parent = dirname(current);
|
|
555
|
+
if (parent === current) return {
|
|
556
|
+
profileName: fallback,
|
|
557
|
+
omittedPackages: {}
|
|
558
|
+
};
|
|
559
|
+
current = parent;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/** Read one manifest's standalone declaration, or undefined when it carries none. */
|
|
563
|
+
function readStandaloneFacts(manifestPath) {
|
|
564
|
+
if (!existsSync(manifestPath)) return void 0;
|
|
565
|
+
let standalone;
|
|
566
|
+
try {
|
|
567
|
+
standalone = JSON.parse(readFileSync(manifestPath, "utf8")).dshPlusStandalone;
|
|
568
|
+
} catch {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
const profile = standalone?.profile;
|
|
572
|
+
if (standalone === void 0 || typeof profile !== "string" || profile === "") return void 0;
|
|
573
|
+
const rawOmitted = standalone.omittedPackages;
|
|
574
|
+
const omittedPackages = {};
|
|
575
|
+
if (rawOmitted !== void 0 && typeof rawOmitted === "object" && !Array.isArray(rawOmitted)) for (const [name, spec] of Object.entries(rawOmitted)) {
|
|
576
|
+
if (typeof spec !== "string" || spec === "") throw new Error("dshPlusStandalone.omittedPackages." + name + " must be a non-empty string");
|
|
577
|
+
omittedPackages[name] = spec;
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
profileName: profile,
|
|
581
|
+
omittedPackages
|
|
582
|
+
};
|
|
583
|
+
}
|
|
537
584
|
function requireRecord(value, label) {
|
|
538
585
|
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(label + " must be an object");
|
|
539
586
|
return value;
|
|
@@ -814,9 +861,12 @@ function linkBundle(consumerModules, name, source) {
|
|
|
814
861
|
/** Resolve every path a command needs, without creating anything. */
|
|
815
862
|
function resolvePaths(anchor, env = process.env) {
|
|
816
863
|
const home = resolveHome(env);
|
|
864
|
+
const declaration = readStandaloneDeclaration(anchor);
|
|
817
865
|
return {
|
|
818
866
|
home,
|
|
819
|
-
|
|
867
|
+
profileName: declaration.profileName,
|
|
868
|
+
omittedPackages: declaration.omittedPackages,
|
|
869
|
+
profileDirectory: join(home, "profiles", declaration.profileName),
|
|
820
870
|
distributionDirectory: resolveDistributionDirectory(anchor)
|
|
821
871
|
};
|
|
822
872
|
}
|
|
@@ -840,7 +890,7 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
840
890
|
const manifestPath = join(paths.profileDirectory, "package.json");
|
|
841
891
|
const distribution = readDistributionProfile(paths.distributionDirectory);
|
|
842
892
|
if (existsSync(manifestPath)) {
|
|
843
|
-
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
893
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds, paths.omittedPackages);
|
|
844
894
|
installProfilePackages(paths, consumerDirectory);
|
|
845
895
|
return false;
|
|
846
896
|
}
|
|
@@ -860,7 +910,7 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
860
910
|
} }
|
|
861
911
|
};
|
|
862
912
|
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
863
|
-
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
913
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds, paths.omittedPackages);
|
|
864
914
|
installProfilePackages(paths, consumerDirectory);
|
|
865
915
|
return true;
|
|
866
916
|
}
|
|
@@ -874,13 +924,14 @@ function ensureProfile(paths, consumerDirectory) {
|
|
|
874
924
|
* @param profileDirectory - the standalone profile directory.
|
|
875
925
|
* @param overrides - official package name to published replacement spec.
|
|
876
926
|
*/
|
|
877
|
-
function writeProfileOverrides(profileDirectory, overrides, allowBuilds) {
|
|
927
|
+
function writeProfileOverrides(profileDirectory, overrides, allowBuilds, omittedPackages) {
|
|
878
928
|
const workspacePath = join(profileDirectory, "pnpm-workspace.yaml");
|
|
879
929
|
const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, "utf8") : "");
|
|
880
930
|
const [documentError] = document.errors;
|
|
881
931
|
if (documentError !== void 0) throw new Error("Plus profile workspace is not valid YAML", { cause: documentError });
|
|
882
932
|
if (document.get("packages") === void 0) document.set("packages", ["."]);
|
|
883
933
|
for (const [name, spec] of Object.entries(overrides)) document.setIn(["overrides", name], spec);
|
|
934
|
+
for (const [name, spec] of Object.entries(omittedPackages)) document.setIn(["overrides", name], spec);
|
|
884
935
|
for (const [name, allowed] of Object.entries(allowBuilds)) document.setIn(["allowBuilds", name], allowed);
|
|
885
936
|
if (document.get("nodeLinker") === void 0) document.set("nodeLinker", "hoisted");
|
|
886
937
|
if (document.get("autoInstallPeers") === void 0) document.set("autoInstallPeers", false);
|
|
@@ -1044,11 +1095,11 @@ function launcherEntry(anchor) {
|
|
|
1044
1095
|
return createRequire(anchor).resolve("@deepseek-ai/dsh/lib/bin.js");
|
|
1045
1096
|
}
|
|
1046
1097
|
/** Run the server in this process, inheriting stdio. */
|
|
1047
|
-
function runForeground(entry, port, host, open) {
|
|
1098
|
+
function runForeground(entry, profileName, port, host, open) {
|
|
1048
1099
|
const args = [
|
|
1049
1100
|
entry,
|
|
1050
1101
|
"--profile",
|
|
1051
|
-
|
|
1102
|
+
profileName,
|
|
1052
1103
|
"--port",
|
|
1053
1104
|
String(port),
|
|
1054
1105
|
"--host",
|
|
@@ -1091,7 +1142,7 @@ async function start(argv) {
|
|
|
1091
1142
|
console.log("pnpm installed.");
|
|
1092
1143
|
}
|
|
1093
1144
|
const created = ensureProfile(paths, installationRoot());
|
|
1094
|
-
console.log(created ? "Created the
|
|
1145
|
+
console.log(created ? "Created the " + paths.profileName + " profile at " + paths.profileDirectory : "Using the existing " + paths.profileName + " profile");
|
|
1095
1146
|
for (const label of applyProfileNpmPatches(paths.distributionDirectory, paths.profileDirectory)) console.log("Applied the reviewed patch " + label);
|
|
1096
1147
|
const answers = created || !existsSync(join(paths.home, "capabilities.json")) ? await interviewCapabilities(true) : void 0;
|
|
1097
1148
|
if (answers !== void 0) {
|
|
@@ -1103,16 +1154,17 @@ async function start(argv) {
|
|
|
1103
1154
|
if (answers.enabled.includes("exa") && answers.exaApiKey === void 0) console.log(" Exa: add EXA_API_KEY to " + join(paths.home, CAPABILITY_ENV_FILE) + " when you have a key.");
|
|
1104
1155
|
}
|
|
1105
1156
|
const entry = launcherEntry(anchor);
|
|
1106
|
-
if (options.foreground) return runForeground(entry, options.port, options.host, options.open);
|
|
1157
|
+
if (options.foreground) return runForeground(entry, paths.profileName, options.port, options.host, options.open);
|
|
1107
1158
|
const existing = readState(paths.home);
|
|
1108
1159
|
if (existing !== void 0) {
|
|
1109
1160
|
console.log("Plus is already running at " + existing.url);
|
|
1110
1161
|
console.log("Stop it with: dsh-plus stop");
|
|
1111
1162
|
return 0;
|
|
1112
1163
|
}
|
|
1113
|
-
return startDetached(paths
|
|
1164
|
+
return startDetached(paths, entry, options);
|
|
1114
1165
|
}
|
|
1115
|
-
async function startDetached(
|
|
1166
|
+
async function startDetached(paths, entry, options) {
|
|
1167
|
+
const home = paths.home;
|
|
1116
1168
|
const port = await choosePort(options.port, options.host);
|
|
1117
1169
|
if (port === void 0) {
|
|
1118
1170
|
console.error("No free port in the range " + String(options.port) + "-" + String(options.port + 9) + ".");
|
|
@@ -1120,15 +1172,15 @@ async function startDetached(home, entry, options) {
|
|
|
1120
1172
|
return 1;
|
|
1121
1173
|
}
|
|
1122
1174
|
if (port !== options.port) console.log("Port " + String(options.port) + " is in use; using " + String(port) + ".");
|
|
1123
|
-
const logPath = join(stateDirectory(home), "server.log");
|
|
1175
|
+
const logPath = join(stateDirectory(paths.home), "server.log");
|
|
1124
1176
|
const env = {
|
|
1125
1177
|
...process.env,
|
|
1126
|
-
DSH_HOME: home
|
|
1178
|
+
DSH_HOME: paths.home
|
|
1127
1179
|
};
|
|
1128
1180
|
const args = [
|
|
1129
1181
|
entry,
|
|
1130
1182
|
"--profile",
|
|
1131
|
-
|
|
1183
|
+
paths.profileName,
|
|
1132
1184
|
"--port",
|
|
1133
1185
|
String(port),
|
|
1134
1186
|
"--host",
|
|
@@ -92,8 +92,8 @@ function launcherEntry(anchor) {
|
|
|
92
92
|
return createRequire(anchor).resolve('@deepseek-ai/dsh/lib/bin.js');
|
|
93
93
|
}
|
|
94
94
|
/** Run the server in this process, inheriting stdio. */
|
|
95
|
-
function runForeground(entry, port, host, open) {
|
|
96
|
-
const args = [entry, '--profile',
|
|
95
|
+
function runForeground(entry, profileName, port, host, open) {
|
|
96
|
+
const args = [entry, '--profile', profileName, '--port', String(port), '--host', host];
|
|
97
97
|
if (!open)
|
|
98
98
|
args.push('--no-open');
|
|
99
99
|
const result = spawnSync(process.execPath, args, { stdio: 'inherit' });
|
|
@@ -144,8 +144,8 @@ async function start(argv) {
|
|
|
144
144
|
}
|
|
145
145
|
const created = ensureProfile(paths, installationRoot());
|
|
146
146
|
console.log(created
|
|
147
|
-
? 'Created the ' +
|
|
148
|
-
: 'Using the existing ' +
|
|
147
|
+
? 'Created the ' + paths.profileName + ' profile at ' + paths.profileDirectory
|
|
148
|
+
: 'Using the existing ' + paths.profileName + ' profile');
|
|
149
149
|
// The profile symlinks the consumer's packages, so a patch lands on the installed
|
|
150
150
|
// copy the launcher loads. A reinstall restores the published bytes, which is why
|
|
151
151
|
// this runs on every start rather than only when the profile was created.
|
|
@@ -172,16 +172,17 @@ async function start(argv) {
|
|
|
172
172
|
}
|
|
173
173
|
const entry = launcherEntry(anchor);
|
|
174
174
|
if (options.foreground)
|
|
175
|
-
return runForeground(entry, options.port, options.host, options.open);
|
|
175
|
+
return runForeground(entry, paths.profileName, options.port, options.host, options.open);
|
|
176
176
|
const existing = readState(paths.home);
|
|
177
177
|
if (existing !== undefined) {
|
|
178
178
|
console.log('Plus is already running at ' + existing.url);
|
|
179
179
|
console.log('Stop it with: dsh-plus stop');
|
|
180
180
|
return 0;
|
|
181
181
|
}
|
|
182
|
-
return startDetached(paths
|
|
182
|
+
return startDetached(paths, entry, options);
|
|
183
183
|
}
|
|
184
|
-
async function startDetached(
|
|
184
|
+
async function startDetached(paths, entry, options) {
|
|
185
|
+
const home = paths.home;
|
|
185
186
|
const port = await choosePort(options.port, options.host);
|
|
186
187
|
if (port === undefined) {
|
|
187
188
|
console.error('No free port in the range ' + String(options.port) + '-' + String(options.port + 9) + '.');
|
|
@@ -190,9 +191,9 @@ async function startDetached(home, entry, options) {
|
|
|
190
191
|
}
|
|
191
192
|
if (port !== options.port)
|
|
192
193
|
console.log('Port ' + String(options.port) + ' is in use; using ' + String(port) + '.');
|
|
193
|
-
const logPath = join(stateDirectory(home), 'server.log');
|
|
194
|
-
const env = { ...process.env, DSH_HOME: home };
|
|
195
|
-
const args = [entry, '--profile',
|
|
194
|
+
const logPath = join(stateDirectory(paths.home), 'server.log');
|
|
195
|
+
const env = { ...process.env, DSH_HOME: paths.home };
|
|
196
|
+
const args = [entry, '--profile', paths.profileName, '--port', String(port), '--host', options.host, '--no-open'];
|
|
196
197
|
const pid = spawnServer({ command: process.execPath, args, env, logPath });
|
|
197
198
|
const url = 'http://' + options.host + ':' + String(port) + '/';
|
|
198
199
|
const ready = await waitForServer(url, READY_TIMEOUT_MILLISECONDS);
|
|
@@ -8,12 +8,56 @@
|
|
|
8
8
|
* the launcher mounts exactly the bundles the profile names and nothing expands a
|
|
9
9
|
* bundle's own list.
|
|
10
10
|
*/
|
|
11
|
-
/** Profile name a standalone installation owns. */
|
|
11
|
+
/** Profile name a standalone installation owns when its package declares none. */
|
|
12
12
|
export declare const STANDALONE_PROFILE = "plus";
|
|
13
|
+
/**
|
|
14
|
+
* Read the profile name the installing package declares.
|
|
15
|
+
*
|
|
16
|
+
* A standalone package describes the profile it materializes, so a reduced variant can
|
|
17
|
+
* own a differently named profile beside the full one instead of overwriting it. The
|
|
18
|
+
* declaration travels with the package because npm resolves the tree long before any
|
|
19
|
+
* command of ours runs, and the distribution cannot name a profile for a package it
|
|
20
|
+
* does not own.
|
|
21
|
+
*
|
|
22
|
+
* @param anchor - path inside the installing package's tree.
|
|
23
|
+
* @param fallback - profile name to use when the declaration is absent.
|
|
24
|
+
* @returns the declared profile name, or the fallback.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveStandaloneProfile(anchor: string, fallback?: string): string;
|
|
27
|
+
/** What the installing package declares about the deployment it owns. */
|
|
28
|
+
export interface StandaloneDeclaration {
|
|
29
|
+
/** Profile name the launcher materializes. */
|
|
30
|
+
readonly profileName: string;
|
|
31
|
+
/**
|
|
32
|
+
* Capabilities the deployment must not install, as package name to override spec.
|
|
33
|
+
*
|
|
34
|
+
* npm substitutes rather than deletes, so each entry names the placeholder the
|
|
35
|
+
* capability is replaced with. The profile workspace applies these as overrides,
|
|
36
|
+
* which is where pnpm reads them.
|
|
37
|
+
*/
|
|
38
|
+
readonly omittedPackages: Readonly<Record<string, string>>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read the deployment facts the installing package declares.
|
|
42
|
+
*
|
|
43
|
+
* A standalone package describes the profile it materializes and the capabilities it
|
|
44
|
+
* omits, so a reduced variant owns a differently named profile and a reduced install
|
|
45
|
+
* without the distribution naming either. The declaration travels with the package
|
|
46
|
+
* because npm resolves the tree long before any command of ours runs.
|
|
47
|
+
*
|
|
48
|
+
* @param anchor - path inside the installing package's tree.
|
|
49
|
+
* @param fallback - profile name to use when the declaration is absent.
|
|
50
|
+
* @returns the declared profile name and omitted capabilities.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readStandaloneDeclaration(anchor: string, fallback?: string): StandaloneDeclaration;
|
|
13
53
|
/** Resolved locations for one standalone installation. */
|
|
14
54
|
export interface StandalonePaths {
|
|
15
55
|
/** DSH home holding profiles, credentials, and session data. */
|
|
16
56
|
readonly home: string;
|
|
57
|
+
/** Profile name the launcher boots, as the installing package declares it. */
|
|
58
|
+
readonly profileName: string;
|
|
59
|
+
/** Capabilities the deployment omits, as package name to override spec. */
|
|
60
|
+
readonly omittedPackages: Readonly<Record<string, string>>;
|
|
17
61
|
/** Profile directory the launcher boots. */
|
|
18
62
|
readonly profileDirectory: string;
|
|
19
63
|
/** Installed Plus distribution directory. */
|
|
@@ -14,8 +14,79 @@ import { createRequire } from 'node:module';
|
|
|
14
14
|
import { homedir } from 'node:os';
|
|
15
15
|
import { dirname, join, posix, resolve, win32 } from 'node:path';
|
|
16
16
|
import { parseDocument } from 'yaml';
|
|
17
|
-
/** Profile name a standalone installation owns. */
|
|
17
|
+
/** Profile name a standalone installation owns when its package declares none. */
|
|
18
18
|
export const STANDALONE_PROFILE = 'plus';
|
|
19
|
+
/**
|
|
20
|
+
* Read the profile name the installing package declares.
|
|
21
|
+
*
|
|
22
|
+
* A standalone package describes the profile it materializes, so a reduced variant can
|
|
23
|
+
* own a differently named profile beside the full one instead of overwriting it. The
|
|
24
|
+
* declaration travels with the package because npm resolves the tree long before any
|
|
25
|
+
* command of ours runs, and the distribution cannot name a profile for a package it
|
|
26
|
+
* does not own.
|
|
27
|
+
*
|
|
28
|
+
* @param anchor - path inside the installing package's tree.
|
|
29
|
+
* @param fallback - profile name to use when the declaration is absent.
|
|
30
|
+
* @returns the declared profile name, or the fallback.
|
|
31
|
+
*/
|
|
32
|
+
export function resolveStandaloneProfile(anchor, fallback = STANDALONE_PROFILE) {
|
|
33
|
+
return readStandaloneDeclaration(anchor, fallback).profileName;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read the deployment facts the installing package declares.
|
|
37
|
+
*
|
|
38
|
+
* A standalone package describes the profile it materializes and the capabilities it
|
|
39
|
+
* omits, so a reduced variant owns a differently named profile and a reduced install
|
|
40
|
+
* without the distribution naming either. The declaration travels with the package
|
|
41
|
+
* because npm resolves the tree long before any command of ours runs.
|
|
42
|
+
*
|
|
43
|
+
* @param anchor - path inside the installing package's tree.
|
|
44
|
+
* @param fallback - profile name to use when the declaration is absent.
|
|
45
|
+
* @returns the declared profile name and omitted capabilities.
|
|
46
|
+
*/
|
|
47
|
+
export function readStandaloneDeclaration(anchor, fallback = STANDALONE_PROFILE) {
|
|
48
|
+
// The anchor is the CLI file; walk out to the package that declares the forwarder.
|
|
49
|
+
let current = resolve(anchor);
|
|
50
|
+
for (;;) {
|
|
51
|
+
const manifestPath = join(current, 'package.json');
|
|
52
|
+
const declared = readStandaloneFacts(manifestPath);
|
|
53
|
+
if (declared !== undefined)
|
|
54
|
+
return declared;
|
|
55
|
+
const parent = dirname(current);
|
|
56
|
+
if (parent === current)
|
|
57
|
+
return { profileName: fallback, omittedPackages: {} };
|
|
58
|
+
current = parent;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Read one manifest's standalone declaration, or undefined when it carries none. */
|
|
62
|
+
function readStandaloneFacts(manifestPath) {
|
|
63
|
+
if (!existsSync(manifestPath))
|
|
64
|
+
return undefined;
|
|
65
|
+
let standalone;
|
|
66
|
+
try {
|
|
67
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
68
|
+
standalone = manifest.dshPlusStandalone;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// A package whose manifest cannot be read declares nothing; the caller keeps walking
|
|
72
|
+
// because the declaring package may sit above it.
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const profile = standalone?.profile;
|
|
76
|
+
if (standalone === undefined || typeof profile !== 'string' || profile === '')
|
|
77
|
+
return undefined;
|
|
78
|
+
const rawOmitted = standalone.omittedPackages;
|
|
79
|
+
const omittedPackages = {};
|
|
80
|
+
if (rawOmitted !== undefined && typeof rawOmitted === 'object' && !Array.isArray(rawOmitted)) {
|
|
81
|
+
for (const [name, spec] of Object.entries(rawOmitted)) {
|
|
82
|
+
if (typeof spec !== 'string' || spec === '') {
|
|
83
|
+
throw new Error('dshPlusStandalone.omittedPackages.' + name + ' must be a non-empty string');
|
|
84
|
+
}
|
|
85
|
+
omittedPackages[name] = spec;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { profileName: profile, omittedPackages };
|
|
89
|
+
}
|
|
19
90
|
function requireRecord(value, label) {
|
|
20
91
|
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
21
92
|
throw new Error(label + ' must be an object');
|
|
@@ -336,9 +407,12 @@ function linkBundle(consumerModules, name, source) {
|
|
|
336
407
|
/** Resolve every path a command needs, without creating anything. */
|
|
337
408
|
export function resolvePaths(anchor, env = process.env) {
|
|
338
409
|
const home = resolveHome(env);
|
|
410
|
+
const declaration = readStandaloneDeclaration(anchor);
|
|
339
411
|
return {
|
|
340
412
|
home,
|
|
341
|
-
|
|
413
|
+
profileName: declaration.profileName,
|
|
414
|
+
omittedPackages: declaration.omittedPackages,
|
|
415
|
+
profileDirectory: join(home, 'profiles', declaration.profileName),
|
|
342
416
|
distributionDirectory: resolveDistributionDirectory(anchor),
|
|
343
417
|
};
|
|
344
418
|
}
|
|
@@ -366,7 +440,7 @@ export function ensureProfile(paths, consumerDirectory) {
|
|
|
366
440
|
// script allowlist — and a distribution release changes them. Rewriting on every
|
|
367
441
|
// start is what lets an upgraded installation receive the new values; a profile
|
|
368
442
|
// written once keeps whatever its own release decided and can never be corrected.
|
|
369
|
-
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
443
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds, paths.omittedPackages);
|
|
370
444
|
installProfilePackages(paths, consumerDirectory);
|
|
371
445
|
return false;
|
|
372
446
|
}
|
|
@@ -392,7 +466,7 @@ export function ensureProfile(paths, consumerDirectory) {
|
|
|
392
466
|
};
|
|
393
467
|
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
394
468
|
// The overrides must reach the workspace before the install that reads them.
|
|
395
|
-
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds);
|
|
469
|
+
writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds, paths.omittedPackages);
|
|
396
470
|
installProfilePackages(paths, consumerDirectory);
|
|
397
471
|
return true;
|
|
398
472
|
}
|
|
@@ -406,7 +480,7 @@ export function ensureProfile(paths, consumerDirectory) {
|
|
|
406
480
|
* @param profileDirectory - the standalone profile directory.
|
|
407
481
|
* @param overrides - official package name to published replacement spec.
|
|
408
482
|
*/
|
|
409
|
-
function writeProfileOverrides(profileDirectory, overrides, allowBuilds) {
|
|
483
|
+
function writeProfileOverrides(profileDirectory, overrides, allowBuilds, omittedPackages) {
|
|
410
484
|
const workspacePath = join(profileDirectory, 'pnpm-workspace.yaml');
|
|
411
485
|
const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, 'utf8') : '');
|
|
412
486
|
const [documentError] = document.errors;
|
|
@@ -416,6 +490,11 @@ function writeProfileOverrides(profileDirectory, overrides, allowBuilds) {
|
|
|
416
490
|
document.set('packages', ['.']);
|
|
417
491
|
for (const [name, spec] of Object.entries(overrides))
|
|
418
492
|
document.setIn(['overrides', name], spec);
|
|
493
|
+
// A capability the deployment omits is substituted rather than deleted, because npm's
|
|
494
|
+
// override has no removal form. Writing it here keeps the omission in the one place
|
|
495
|
+
// pnpm reads, so an install never receives the capability the variant excluded.
|
|
496
|
+
for (const [name, spec] of Object.entries(omittedPackages))
|
|
497
|
+
document.setIn(['overrides', name], spec);
|
|
419
498
|
// pnpm refuses an install whose packages want to run build scripts until each is
|
|
420
499
|
// decided, so the distribution's reviewed decisions travel with the install rather
|
|
421
500
|
// than waiting for an interactive approval no start can offer.
|
package/package.json
CHANGED
|
@@ -3,35 +3,30 @@
|
|
|
3
3
|
"dsh-plus": "lib/bin.js"
|
|
4
4
|
},
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@deepseek-ai/dsh-computer-use": ">=0.1.6-alpha.1",
|
|
7
|
-
"@deepseek-ai/dsh-experimental-computer-use-cua-driver-mcp": ">=0.1.6-alpha.1",
|
|
8
6
|
"@deepseek-ai/dsh-tool-session-query": ">=0.1.6-alpha.1",
|
|
9
|
-
"@
|
|
10
|
-
"@sparkelf/dsh-
|
|
11
|
-
"@sparkelf/dsh-
|
|
12
|
-
"@sparkelf/dsh-patch-better-sidebar-
|
|
13
|
-
"@sparkelf/dsh-patch-better-sidebar-
|
|
14
|
-
"@sparkelf/dsh-patch-
|
|
15
|
-
"@sparkelf/dsh-patch-
|
|
16
|
-
"@sparkelf/dsh-patch-
|
|
17
|
-
"@sparkelf/dsh-patch-
|
|
18
|
-
"@sparkelf/dsh-patch-
|
|
19
|
-
"@sparkelf/dsh-patch-
|
|
20
|
-
"@sparkelf/dsh-patch-
|
|
21
|
-
"@sparkelf/dsh-patch-
|
|
22
|
-
"@sparkelf/dsh-patch-
|
|
23
|
-
"@sparkelf/dsh-patch-session-
|
|
24
|
-
"@sparkelf/dsh-patch-session-
|
|
25
|
-
"@sparkelf/dsh-patch-
|
|
26
|
-
"@sparkelf/dsh-patch-
|
|
27
|
-
"@sparkelf/dsh-patch-
|
|
28
|
-
"@sparkelf/dsh-patch-
|
|
29
|
-
"@sparkelf/dsh-
|
|
30
|
-
"@sparkelf/dsh-
|
|
31
|
-
"@sparkelf/dsh-plugin-
|
|
32
|
-
"@sparkelf/dsh-plugin-dataops": ">=0.2.0-rc.8",
|
|
33
|
-
"@sparkelf/dsh-plugin-mcp-credentials": ">=0.2.0-rc.8",
|
|
34
|
-
"@sparkelf/dsh-plugin-subagent-settings": ">=0.2.0-rc.8",
|
|
7
|
+
"@sparkelf/dsh-client-ui-skill-center": ">=0.2.0-rc.17",
|
|
8
|
+
"@sparkelf/dsh-patch-better-sidebar-browser-url-seed": ">=0.2.0-rc.17",
|
|
9
|
+
"@sparkelf/dsh-patch-better-sidebar-html-preview-path": ">=0.2.0-rc.17",
|
|
10
|
+
"@sparkelf/dsh-patch-better-sidebar-main-view-session": ">=0.2.0-rc.17",
|
|
11
|
+
"@sparkelf/dsh-patch-better-sidebar-media-path": ">=0.2.0-rc.17",
|
|
12
|
+
"@sparkelf/dsh-patch-browser-auth-mode": ">=0.2.0-rc.17",
|
|
13
|
+
"@sparkelf/dsh-patch-composer-popover-boundaries": ">=0.2.0-rc.17",
|
|
14
|
+
"@sparkelf/dsh-patch-legacy-code-preset": ">=0.2.0-rc.17",
|
|
15
|
+
"@sparkelf/dsh-patch-mobile-journal-generation": ">=0.2.0-rc.17",
|
|
16
|
+
"@sparkelf/dsh-patch-officecli-deliverables": ">=0.2.0-rc.17",
|
|
17
|
+
"@sparkelf/dsh-patch-ptc-mcp-schema-types": ">=0.2.0-rc.17",
|
|
18
|
+
"@sparkelf/dsh-patch-responses-reasoning-status": ">=0.2.0-rc.17",
|
|
19
|
+
"@sparkelf/dsh-patch-session-export-chinese": ">=0.2.0-rc.17",
|
|
20
|
+
"@sparkelf/dsh-patch-session-format-legacy-restart": ">=0.2.0-rc.17",
|
|
21
|
+
"@sparkelf/dsh-patch-session-log-trajectory-toolbar": ">=0.2.0-rc.17",
|
|
22
|
+
"@sparkelf/dsh-patch-session-query-unindexable-session": ">=0.2.0-rc.17",
|
|
23
|
+
"@sparkelf/dsh-patch-subagent-settings-presets": ">=0.2.0-rc.17",
|
|
24
|
+
"@sparkelf/dsh-patch-web-base-path": ">=0.2.0-rc.17",
|
|
25
|
+
"@sparkelf/dsh-patch-workspace-storage-restore": ">=0.2.0-rc.17",
|
|
26
|
+
"@sparkelf/dsh-patch-wsl-native-open": ">=0.2.0-rc.17",
|
|
27
|
+
"@sparkelf/dsh-plugin-backup": ">=0.2.0-rc.17",
|
|
28
|
+
"@sparkelf/dsh-plugin-mcp-credentials": ">=0.2.0-rc.17",
|
|
29
|
+
"@sparkelf/dsh-plugin-subagent-settings": ">=0.2.0-rc.17",
|
|
35
30
|
"dshmarket": ">=1.45.1",
|
|
36
31
|
"semver": ">=7.7.3",
|
|
37
32
|
"yaml": ">=2.9.0"
|
|
@@ -67,11 +62,11 @@
|
|
|
67
62
|
"@sparkelf/dsh-patch-ptc-mcp-schema-types",
|
|
68
63
|
"@sparkelf/dsh-patch-web-base-path",
|
|
69
64
|
"@sparkelf/dsh-patch-composer-popover-boundaries",
|
|
70
|
-
"@sparkelf/dsh-patch-mobile-journal-generation",
|
|
71
65
|
"@sparkelf/dsh-patch-session-format-legacy-restart",
|
|
72
66
|
"@sparkelf/dsh-patch-wsl-native-open",
|
|
73
67
|
"@sparkelf/dsh-patch-better-sidebar-html-preview-path",
|
|
74
|
-
"@sparkelf/dsh-patch-session-query-unindexable-session"
|
|
68
|
+
"@sparkelf/dsh-patch-session-query-unindexable-session",
|
|
69
|
+
"@sparkelf/dsh-patch-mobile-journal-generation"
|
|
75
70
|
],
|
|
76
71
|
"profile": {
|
|
77
72
|
"allowBuilds": {
|
|
@@ -92,7 +87,6 @@
|
|
|
92
87
|
"@deepseek-ai/dsh-experimental-agent-team-web-profile",
|
|
93
88
|
"@sparkelf/dsh-mineru",
|
|
94
89
|
"@sparkelf/dsh-officecli",
|
|
95
|
-
"@sparkelf/dsh-mobile-bridge",
|
|
96
90
|
"dshmarket",
|
|
97
91
|
"@huanlin/dsh-plugin-better-locale",
|
|
98
92
|
"dsh-better-sidebar",
|
|
@@ -104,7 +98,8 @@
|
|
|
104
98
|
"@sparkelf/dsh-plus",
|
|
105
99
|
"dsh-sql-workbench",
|
|
106
100
|
"@sparkelf/dsh-ssh-manager",
|
|
107
|
-
"@sparkelf/dsh-api-client"
|
|
101
|
+
"@sparkelf/dsh-api-client",
|
|
102
|
+
"dsh-right-bg-anim"
|
|
108
103
|
],
|
|
109
104
|
"dependencies": {
|
|
110
105
|
"@changfenhuang/dsh-genui": "0.11.0",
|
|
@@ -120,6 +115,7 @@
|
|
|
120
115
|
"@sparkelf/dsh-ssh-manager": "0.7.2",
|
|
121
116
|
"@sparkelf/dsh-workbench-vault": "0.1.2",
|
|
122
117
|
"dsh-better-sidebar": "0.19.1",
|
|
118
|
+
"dsh-right-bg-anim": "1.1.0",
|
|
123
119
|
"dsh-sql-workbench": "0.5.1",
|
|
124
120
|
"dsh-video-preview": "0.1.4"
|
|
125
121
|
},
|
|
@@ -143,10 +139,23 @@
|
|
|
143
139
|
"@deepseek-ai/dsh-native-command": "npm:@sparkelf/dsh-native-command@0.1.6-alpha.2",
|
|
144
140
|
"@deepseek-ai/dsh-session-format-v0-to-v1": "npm:@sparkelf/dsh-session-format-v0-to-v1@0.1.6-alpha.2",
|
|
145
141
|
"@deepseek-ai/dsh-session-log-export": "npm:@sparkelf/dsh-session-log-export@0.1.6-alpha.2",
|
|
142
|
+
"@deepseek-ai/dsh-session-query-sqlite": "npm:@sparkelf/dsh-session-query-sqlite@0.1.6-alpha.2",
|
|
146
143
|
"@deepseek-ai/dsh-tools": "npm:@sparkelf/dsh-tools@0.1.6-alpha.2",
|
|
147
144
|
"@deepseek-ai/dsh-web-app": "npm:@sparkelf/dsh-web-app@0.1.6-alpha.2",
|
|
148
145
|
"@deepseek-ai/dsh-web-frontend": "npm:@sparkelf/dsh-web-frontend@0.1.6-alpha.2",
|
|
149
146
|
"@deepseek-ai/dsh-workspace": "npm:@sparkelf/dsh-workspace@0.1.6-alpha.2"
|
|
147
|
+
},
|
|
148
|
+
"standaloneVariants": {
|
|
149
|
+
"dataops": {
|
|
150
|
+
"excludeBundles": [],
|
|
151
|
+
"excludePackages": [
|
|
152
|
+
"@deepseek-ai/dsh-computer-use",
|
|
153
|
+
"@deepseek-ai/dsh-experimental-computer-use-cua-driver-mcp",
|
|
154
|
+
"@deepseek-ai/dsh-web-search-exa"
|
|
155
|
+
],
|
|
156
|
+
"packageName": "@sparkelf/dsh-dataops-standalone",
|
|
157
|
+
"profile": "dataops-web"
|
|
158
|
+
}
|
|
150
159
|
}
|
|
151
160
|
},
|
|
152
161
|
"sourceBase": {
|
|
@@ -176,6 +185,11 @@
|
|
|
176
185
|
"license": "MIT",
|
|
177
186
|
"main": "lib/index.js",
|
|
178
187
|
"name": "@sparkelf/dsh-plus",
|
|
188
|
+
"optionalDependencies": {
|
|
189
|
+
"@deepseek-ai/dsh-computer-use": ">=0.1.6-alpha.1",
|
|
190
|
+
"@deepseek-ai/dsh-experimental-computer-use-cua-driver-mcp": ">=0.1.6-alpha.1",
|
|
191
|
+
"@deepseek-ai/dsh-web-search-exa": ">=0.1.6-alpha.1"
|
|
192
|
+
},
|
|
179
193
|
"peerDependencies": {
|
|
180
194
|
"@deepseek-ai/cordis": ">=4.0.1"
|
|
181
195
|
},
|
|
@@ -189,5 +203,5 @@
|
|
|
189
203
|
},
|
|
190
204
|
"type": "module",
|
|
191
205
|
"types": "lib/types/index.d.ts",
|
|
192
|
-
"version": "0.2.0-rc.
|
|
206
|
+
"version": "0.2.0-rc.18"
|
|
193
207
|
}
|