@sparkelf/dsh-plus 0.1.0-rc.11 → 0.1.0-rc.13
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/README.i18n.yaml +2 -2
- package/README.md +5 -3
- package/README.zh.md +5 -3
- package/cordis.patch.yml +5 -0
- package/lib/apply.js +155 -29
- package/lib/types/apply.d.ts +19 -0
- package/package.json +54 -27
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/bundle/plus/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: a8ac5367fb3de36c0ee24c27bfc0f7f1cc72c8cc
|
|
6
|
+
README.zh.md: a179074b4bec9ec8f857c6cbe5fa8b9e4bbebde6
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
This distribution composes official `@deepseek-ai/dsh-base` and `@deepseek-ai/dsh-web-app` with the selected external sidebar, mobile bridge, plugin market, GenUI package, five
|
|
12
|
+
This distribution composes official `@deepseek-ai/dsh-base` and `@deepseek-ai/dsh-web-app` with the selected external sidebar, mobile bridge, plugin market, GenUI package, five in-repository Plus capability packages and one externally owned Supervisor package, and fifteen independent patch packages. It owns only ordered composition, minimum compatibility metadata, dependency closure, explicit materialization, and the credential-free deployment lock; capability behavior and patch payloads stay in their owning packages.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -31,9 +31,11 @@ dsh plugin --profile plus exec dsh-plus apply --dsh-root /path/to/official-dsh
|
|
|
31
31
|
dsh --profile plus
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
The explicit apply step requires official revision `
|
|
34
|
+
The explicit apply step requires official revision `0a53fb55bea101816fa226bb964ae2bed71c343b`, materializes every selected runtime package as a profile-direct dependency, applies all pending source payloads together, configures exact npm patches, removes retired Plus-owned entries, and writes `.dsh-plus/patchset.lock.json` with mode `0600`. It installs stable `dsh-better-sidebar@0.17.1`, Office preview `0.1.2`, and video preview `0.1.4` at the profile root, applies the exact alpha.2 Settings patch, explicitly allows only the sidebar's `node-pty` native build, and builds the profile's `@deepseek-ai` scope from the exact official dsh CLI dependency tree plus official source workspaces needed by out-of-tree plugin peers. SparkElf-owned external Mobile Bridge `0.2.10` and independently maintained dshmarket `1.38.1` each carry alpha.2 Settings compatibility in their own release, so Plus applies no Mobile Bridge patch. Version conflicts and source mismatches fail before profile installation or source mutation. The package has no install lifecycle script.
|
|
35
35
|
|
|
36
|
-
Official DSH supplies onboarding, Workspace selection, Session export, Turn folding, and the base image path. The external `@changfenhuang/dsh-genui` bundle owns generated UI, including inline interactive charts emitted by the model as `dsh-ui`.
|
|
36
|
+
Official DSH supplies onboarding, Workspace selection, Session export, Turn folding, and the base image path. Plus builds that source with the official client profile, keeps the attachment chooser directly after the composer command button, adds Better Sidebar previews for Office documents and video, replaces mixed English `Session` wording in the Simplified-Chinese Session export UI, and places the desktop Session-log action immediately before Trajectory search while retaining its Header position on phones. The external `@changfenhuang/dsh-genui` bundle owns generated UI, including inline interactive charts emitted by the model as `dsh-ui`. Two exact `0.9.6` patches keep top-level streaming complete, register the bundled `genui` skill, publish the compact chart signature, and reject invalid chart fields; each retires after its upstream behavior ships and the real DataOps chart path passes without it. The registry-pinned Supervisor from `SparkElf/dsh-plugins-plus` manages an explicitly materialized runtime and restores Sessions interrupted by its own restart; optional Desktop from `SparkElf/dsh-plus-desktop` delegates tray commands to that package. Neither source tree lives in this fork. DataOps and Document Attachments mount only when their endpoint environment variables exist. Agent Teams is excluded because the official packages are private experimental workspaces and shipped profiles disable them.
|
|
37
|
+
|
|
38
|
+
Plus explicitly selects `browserAuthentication: disabled`: its Web URL is clean and opens without a process-token exchange or browser cookie, while Connection still applies the official Host/Origin trust fence. Every process that can reach an accepted authority can therefore use the complete Host API, including Shell, files, and Sessions. The official `web` profile keeps the upstream `required` default; only the Plus composition opts out.
|
|
37
39
|
|
|
38
40
|
-----
|
|
39
41
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@ kind: "package-bundle"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
该distribution把official `@deepseek-ai/dsh-base`及`@deepseek-ai/dsh-web-app`与selected external sidebar、mobile bridge、plugin market、GenUI package
|
|
12
|
+
该distribution把official `@deepseek-ai/dsh-base`及`@deepseek-ai/dsh-web-app`与selected external sidebar、mobile bridge、plugin market、GenUI package、五个in-repository Plus capability packages及一个externally owned Supervisor package及十五个independent patch packages组合起来。它只持有ordered composition、minimum compatibility metadata、dependency closure、explicit materialization及credential-free deployment lock;capability behavior和patch payloads仍属于各自package。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -31,9 +31,11 @@ dsh plugin --profile plus exec dsh-plus apply --dsh-root /path/to/official-dsh
|
|
|
31
31
|
dsh --profile plus
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
explicit apply步骤要求official revision `
|
|
34
|
+
explicit apply步骤要求official revision `0a53fb55bea101816fa226bb964ae2bed71c343b`,把每个selected runtime package materialize为profile-direct dependency,一次应用全部pending source payloads,配置exact npm patches,删除retired Plus-owned entries,并以`0600` mode写入`.dsh-plus/patchset.lock.json`。它在profile root安装stable `dsh-better-sidebar@0.17.1`、Office preview `0.1.2`与video preview `0.1.4`,应用exact alpha.2 Settings patch,只显式允许sidebar的`node-pty` native build,并用exact official dsh CLI dependency tree及out-of-tree plugin peers所需的official source workspaces共同构建profile的`@deepseek-ai` scope。SparkElf自有external Mobile Bridge `0.2.10`与独立维护的dshmarket `1.38.1`各自在自身release中包含alpha.2 Settings compatibility,因此Plus不应用Mobile Bridge patch。version conflict和source mismatch会在profile installation或source mutation前失败。该package没有install lifecycle script。
|
|
35
35
|
|
|
36
|
-
Official DSH提供onboarding、Workspace selection、Session export、Turn folding及base image path。External `@changfenhuang/dsh-genui` bundle拥有generated UI,包括模型以`dsh-ui`输出的inline interactive charts
|
|
36
|
+
Official DSH提供onboarding、Workspace selection、Session export、Turn folding及base image path。Plus使用official client profile构建该source,把附件选择器保持在输入框指令按钮正右侧,增加Better Sidebar的Office document与video preview,把简体中文会话导出界面中混用的英文`Session`替换为中文,并在桌面端把会话日志操作放到Trajectory搜索框紧邻左侧,同时在手机上保留其Header位置。External `@changfenhuang/dsh-genui` bundle拥有generated UI,包括模型以`dsh-ui`输出的inline interactive charts。两个exact `0.9.6` patch分别保持top-level streaming完整,并注册bundled `genui` skill、发布紧凑chart signature及拒绝非法chart fields;各自upstream behavior发布且真实DataOps chart path在不使用对应patch时通过后退役。来自`SparkElf/dsh-plugins-plus`且由registry精确固定的Supervisor管理显式materialize的runtime并恢复被其自身restart中断的Sessions;来自`SparkElf/dsh-plus-desktop`的可选Desktop把tray commands委托给该package。两个source tree都不在本fork中。DataOps和Document Attachments仅在对应endpoint environment variables存在时mount。Agent Teams被排除,因为official packages属于private experimental workspaces且shipped profiles会禁用它们。
|
|
37
|
+
|
|
38
|
+
Plus显式选择`browserAuthentication: disabled`:其Web URL保持clean,无需process-token exchange或browser cookie即可打开,同时Connection仍执行official Host/Origin trust fence。因此所有能访问accepted authority的进程都能使用包含Shell、files与Sessions在内的完整Host API。official `web` profile保留upstream `required` default;只有Plus composition选择关闭。
|
|
37
39
|
|
|
38
40
|
-----
|
|
39
41
|
|
package/cordis.patch.yml
CHANGED
package/lib/apply.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { chmodSync, copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
5
6
|
import { satisfies, valid, validRange } from "semver";
|
|
6
7
|
import { parseDocument } from "yaml";
|
|
7
8
|
//#region lib/types/apply.js
|
|
8
9
|
/** Materialize the Plus distribution's independent patch packages without Desktop. */
|
|
9
10
|
const FORMAT_VERSION = 1;
|
|
11
|
+
function isSelectedNpmPatch(patch) {
|
|
12
|
+
return patch.target.kind === "npm";
|
|
13
|
+
}
|
|
10
14
|
function readJsonObject(path, label) {
|
|
11
15
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
12
16
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(label + " must be a JSON object");
|
|
@@ -113,6 +117,40 @@ function sourcePatchState(root, file) {
|
|
|
113
117
|
]);
|
|
114
118
|
throw new Error("unreachable");
|
|
115
119
|
}
|
|
120
|
+
/** 在隔离index中按真实顺序预演source patches,避免失败后污染official worktree。 */
|
|
121
|
+
function preflightSourcePatches(root, files) {
|
|
122
|
+
if (files.length === 0) return;
|
|
123
|
+
const directory = mkdtempSync(resolve(tmpdir(), "dsh-plus-source-patches-"));
|
|
124
|
+
const index = resolve(directory, "index");
|
|
125
|
+
const env = {
|
|
126
|
+
...process.env,
|
|
127
|
+
GIT_INDEX_FILE: index
|
|
128
|
+
};
|
|
129
|
+
const run = (args) => {
|
|
130
|
+
const result = spawnSync("git", args, {
|
|
131
|
+
cwd: root,
|
|
132
|
+
encoding: "utf8",
|
|
133
|
+
env
|
|
134
|
+
});
|
|
135
|
+
if (result.status === 0) return;
|
|
136
|
+
const detail = result.stderr.trim();
|
|
137
|
+
throw new Error("git " + args.join(" ") + " failed" + (detail === "" ? "" : ": " + detail));
|
|
138
|
+
};
|
|
139
|
+
try {
|
|
140
|
+
run(["read-tree", "HEAD"]);
|
|
141
|
+
for (const file of files) run([
|
|
142
|
+
"apply",
|
|
143
|
+
"--cached",
|
|
144
|
+
"--3way",
|
|
145
|
+
file
|
|
146
|
+
]);
|
|
147
|
+
} finally {
|
|
148
|
+
rmSync(directory, {
|
|
149
|
+
recursive: true,
|
|
150
|
+
force: true
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
116
154
|
function requireSourceBase(root, baseRevision) {
|
|
117
155
|
const checkoutRevision = requireString(git(root, ["rev-parse", "HEAD"]), "DSH checkout revision");
|
|
118
156
|
if (checkoutRevision !== baseRevision) throw new Error("DSH checkout must be exact official base " + baseRevision + ", found " + checkoutRevision);
|
|
@@ -160,18 +198,14 @@ function prepareSelection(distributionDirectory, profileDirectory, dshRoot) {
|
|
|
160
198
|
groups.set(variant.id, entries);
|
|
161
199
|
}
|
|
162
200
|
const sourceStates = /* @__PURE__ */ new Map();
|
|
163
|
-
|
|
201
|
+
const orderedGroups = [...groups].sort(([left], [right]) => left.localeCompare(right));
|
|
202
|
+
for (const [, variants] of orderedGroups) for (const variant of variants) {
|
|
164
203
|
if (variant.target.kind !== "dsh-source" || variant.target.baseRevision !== baseRevision || !satisfies(dshVersion, variant.dsh, { includePrerelease: true })) continue;
|
|
165
204
|
const file = resolvePatchFile(variant.patchPackage.directory, variant.file);
|
|
166
205
|
sourceStates.set(file.absoluteFile, sourcePatchState(dshRoot, file.absoluteFile));
|
|
167
206
|
}
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
"apply",
|
|
171
|
-
"--check",
|
|
172
|
-
...pendingSourceFiles
|
|
173
|
-
]);
|
|
174
|
-
if (writeProfileRequirements(profileDirectory, profileDependencySpecs, allowBuilds)) runPnpm(profileDirectory, ["install"], "pnpm install Plus profile dependencies");
|
|
207
|
+
preflightSourcePatches(dshRoot, [...sourceStates].flatMap(([file, state]) => state === "pending" ? [file] : []));
|
|
208
|
+
if (writeProfileRequirements(profileDirectory, profileDependencySpecs, allowBuilds)) runPnpm(profileDirectory, ["install", "--no-frozen-lockfile"], "pnpm install Plus profile dependencies");
|
|
175
209
|
const profileDependencies = Object.keys(profileDependencySpecs).sort().map((name) => {
|
|
176
210
|
return {
|
|
177
211
|
name,
|
|
@@ -185,8 +219,8 @@ function prepareSelection(distributionDirectory, profileDirectory, dshRoot) {
|
|
|
185
219
|
};
|
|
186
220
|
}), ...profileDependencies].sort((left, right) => left.name.localeCompare(right.name));
|
|
187
221
|
const selected = [];
|
|
188
|
-
for (const id of
|
|
189
|
-
const candidates =
|
|
222
|
+
for (const [id, variants] of orderedGroups) {
|
|
223
|
+
const candidates = variants.flatMap((variant) => {
|
|
190
224
|
if (!satisfies(dshVersion, variant.dsh, { includePrerelease: true })) return [];
|
|
191
225
|
const file = resolvePatchFile(variant.patchPackage.directory, variant.file);
|
|
192
226
|
if (variant.target.kind === "dsh-source") {
|
|
@@ -258,13 +292,14 @@ function prepareSelection(distributionDirectory, profileDirectory, dshRoot) {
|
|
|
258
292
|
}
|
|
259
293
|
};
|
|
260
294
|
}
|
|
295
|
+
/** 保留每个独立payload,并为同一npm目标生成pnpm可消费的唯一组合patch。 */
|
|
261
296
|
function materializePatchFiles(profileDirectory, patches) {
|
|
262
297
|
const root = resolve(profileDirectory, ".dsh-plus", "patches");
|
|
263
298
|
rmSync(root, {
|
|
264
299
|
recursive: true,
|
|
265
300
|
force: true
|
|
266
301
|
});
|
|
267
|
-
|
|
302
|
+
const stablePatches = patches.map((patch) => {
|
|
268
303
|
const destination = resolve(root, patch.patchPackage.name, patch.patchPackage.version, patch.file);
|
|
269
304
|
mkdirSync(dirname(destination), { recursive: true });
|
|
270
305
|
copyFileSync(patch.absoluteFile, destination);
|
|
@@ -273,23 +308,49 @@ function materializePatchFiles(profileDirectory, patches) {
|
|
|
273
308
|
absoluteFile: destination
|
|
274
309
|
};
|
|
275
310
|
});
|
|
311
|
+
const npmGroups = /* @__PURE__ */ new Map();
|
|
312
|
+
for (const patch of stablePatches) {
|
|
313
|
+
if (!isSelectedNpmPatch(patch)) continue;
|
|
314
|
+
const key = patch.target.name + "@" + patch.target.version;
|
|
315
|
+
const group = npmGroups.get(key);
|
|
316
|
+
if (group === void 0) npmGroups.set(key, [patch]);
|
|
317
|
+
else group.push(patch);
|
|
318
|
+
}
|
|
319
|
+
const npmPatchFiles = /* @__PURE__ */ new Map();
|
|
320
|
+
for (const [key, group] of npmGroups) {
|
|
321
|
+
const first = group[0];
|
|
322
|
+
if (group.length === 1) {
|
|
323
|
+
npmPatchFiles.set(key, first.absoluteFile);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const members = group.map((patch) => encodeURIComponent(patch.id + "@" + patch.patchPackage.version)).join("+");
|
|
327
|
+
const destination = resolve(root, "combined", encodeURIComponent(key), members + ".patch");
|
|
328
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
329
|
+
writeFileSync(destination, group.map((patch) => {
|
|
330
|
+
const content = readFileSync(patch.absoluteFile, "utf8");
|
|
331
|
+
return content.endsWith("\n") ? content : content + "\n";
|
|
332
|
+
}).join(""));
|
|
333
|
+
npmPatchFiles.set(key, destination);
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
patches: stablePatches,
|
|
337
|
+
npmPatchFiles
|
|
338
|
+
};
|
|
276
339
|
}
|
|
277
|
-
function profilePatchConfiguration(profileDirectory,
|
|
340
|
+
function profilePatchConfiguration(profileDirectory, npmPatchFiles) {
|
|
278
341
|
const document = parseDocument(readFileSync(resolve(profileDirectory, "pnpm-workspace.yaml"), "utf8"));
|
|
279
342
|
const [documentError] = document.errors;
|
|
280
343
|
if (documentError !== void 0) throw new Error("Plus profile workspace is not valid YAML", { cause: documentError });
|
|
281
344
|
let changed = false;
|
|
282
|
-
const desiredKeys = new Set(
|
|
345
|
+
const desiredKeys = new Set(npmPatchFiles.keys());
|
|
283
346
|
const workspace = requireObject(document.toJS(), "Plus profile workspace");
|
|
284
347
|
const configured = workspace.patchedDependencies === void 0 ? {} : requireObject(workspace.patchedDependencies, "Plus profile patchedDependencies");
|
|
285
348
|
for (const [key, value] of Object.entries(configured)) if (typeof value === "string" && value.startsWith(".dsh-plus/patches/") && !desiredKeys.has(key)) {
|
|
286
349
|
document.deleteIn(["patchedDependencies", key]);
|
|
287
350
|
changed = true;
|
|
288
351
|
}
|
|
289
|
-
for (const
|
|
290
|
-
|
|
291
|
-
const key = patch.target.name + "@" + patch.target.version;
|
|
292
|
-
const value = relative(profileDirectory, patch.absoluteFile).replaceAll("\\", "/");
|
|
352
|
+
for (const [key, file] of npmPatchFiles) {
|
|
353
|
+
const value = relative(profileDirectory, file).replaceAll("\\", "/");
|
|
293
354
|
const current = document.getIn(["patchedDependencies", key]);
|
|
294
355
|
if (current !== void 0 && current !== value && (typeof current !== "string" || !current.startsWith(".dsh-plus/patches/"))) throw new Error("profile patchedDependencies." + key + " is already owned by another payload");
|
|
295
356
|
if (current === value) continue;
|
|
@@ -375,27 +436,92 @@ function pendingSourcePatchFiles(patches) {
|
|
|
375
436
|
return patches.flatMap((patch) => "alreadyApplied" in patch && !patch.alreadyApplied ? [patch.absoluteFile] : []);
|
|
376
437
|
}
|
|
377
438
|
function applySelectedPatches(profileDirectory, dshRoot, patches, profileChanged) {
|
|
378
|
-
const
|
|
439
|
+
const materialized = materializePatchFiles(profileDirectory, patches);
|
|
379
440
|
const workspacePath = resolve(profileDirectory, "pnpm-workspace.yaml");
|
|
380
|
-
const workspace = profilePatchConfiguration(profileDirectory,
|
|
441
|
+
const workspace = profilePatchConfiguration(profileDirectory, materialized.npmPatchFiles);
|
|
381
442
|
if (workspace.changed) writeFileSync(workspacePath, workspace.text);
|
|
382
|
-
if (profileChanged || workspace.changed) runPnpm(profileDirectory, ["install"], "pnpm install in Plus profile");
|
|
383
|
-
const sourceFiles = pendingSourcePatchFiles(
|
|
384
|
-
if (sourceFiles.length > 0) git(dshRoot, ["
|
|
385
|
-
|
|
443
|
+
if (profileChanged || workspace.changed) runPnpm(profileDirectory, ["install", "--no-frozen-lockfile"], "pnpm install in Plus profile");
|
|
444
|
+
const sourceFiles = pendingSourcePatchFiles(materialized.patches);
|
|
445
|
+
if (sourceFiles.length > 0) git(dshRoot, ["update-index", "--refresh"], true);
|
|
446
|
+
for (const file of sourceFiles) git(dshRoot, [
|
|
447
|
+
"apply",
|
|
448
|
+
"--3way",
|
|
449
|
+
file
|
|
450
|
+
]);
|
|
451
|
+
if (materialized.patches.some((patch) => patch.target.kind === "dsh-source")) runPnpm(dshRoot, ["run", "build:official"], "official DSH build after source patches");
|
|
386
452
|
}
|
|
387
453
|
function officialPackageRoot(dshRoot) {
|
|
388
454
|
return resolve(dshRoot, "apps", "cli");
|
|
389
455
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
456
|
+
/**
|
|
457
|
+
* Parse pnpm's workspace roster into exact official package directories.
|
|
458
|
+
* @param dshRoot - exact official DSH checkout root.
|
|
459
|
+
* @param stdout - JSON emitted by `pnpm -r list --json --depth -1`.
|
|
460
|
+
* @returns sorted official package names and directories inside the checkout.
|
|
461
|
+
*/
|
|
462
|
+
function parseOfficialWorkspacePackages(dshRoot, stdout) {
|
|
463
|
+
const parsed = JSON.parse(stdout);
|
|
464
|
+
if (!Array.isArray(parsed)) throw new Error("pnpm workspace package list must be an array");
|
|
465
|
+
const packages = /* @__PURE__ */ new Map();
|
|
466
|
+
for (const [index, value] of parsed.entries()) {
|
|
467
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("pnpm workspace package list[" + String(index) + "] must be an object");
|
|
468
|
+
const entry = value;
|
|
469
|
+
if (typeof entry.name !== "string" || !entry.name.startsWith("@deepseek-ai/")) continue;
|
|
470
|
+
const localName = entry.name.slice(13);
|
|
471
|
+
if (localName === "" || localName.includes("/")) throw new Error("unsupported official workspace package name: " + entry.name);
|
|
472
|
+
if (typeof entry.path !== "string" || entry.path === "") throw new Error("pnpm workspace package " + entry.name + " has no path");
|
|
473
|
+
const directory = resolve(dshRoot, entry.path);
|
|
474
|
+
const local = relative(dshRoot, directory);
|
|
475
|
+
if (isAbsolute(local) || local === ".." || local.startsWith("../")) throw new Error("official workspace package escapes DSH root: " + entry.name);
|
|
476
|
+
const previous = packages.get(entry.name);
|
|
477
|
+
if (previous !== void 0 && previous !== directory) throw new Error("duplicate official workspace package: " + entry.name);
|
|
478
|
+
packages.set(entry.name, directory);
|
|
479
|
+
}
|
|
480
|
+
return [...packages].sort(([left], [right]) => left.localeCompare(right)).map(([name, directory]) => ({
|
|
481
|
+
name,
|
|
482
|
+
directory
|
|
483
|
+
}));
|
|
484
|
+
}
|
|
485
|
+
function listOfficialWorkspacePackages(dshRoot) {
|
|
486
|
+
const result = spawnSync("pnpm", [
|
|
487
|
+
"-r",
|
|
488
|
+
"list",
|
|
489
|
+
"--json",
|
|
490
|
+
"--depth",
|
|
491
|
+
"-1"
|
|
492
|
+
], {
|
|
493
|
+
cwd: dshRoot,
|
|
494
|
+
encoding: "utf8",
|
|
495
|
+
shell: process.platform === "win32"
|
|
496
|
+
});
|
|
497
|
+
if (result.error !== void 0) throw result.error;
|
|
498
|
+
if (result.status !== 0) throw new Error("pnpm list official DSH workspace packages failed with exit code " + String(result.status));
|
|
499
|
+
return parseOfficialWorkspacePackages(dshRoot, result.stdout);
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Build the profile's official scope from the CLI closure plus source workspaces.
|
|
503
|
+
* @param profileDirectory - materialized Plus profile root.
|
|
504
|
+
* @param cliScope - official packages already installed under the DSH CLI.
|
|
505
|
+
* @param workspacePackages - additional official source workspaces required by external peers.
|
|
506
|
+
*/
|
|
507
|
+
function materializeOfficialPackageScope(profileDirectory, cliScope, workspacePackages) {
|
|
508
|
+
if (!existsSync(cliScope)) throw new Error("official DSH dependencies are missing under " + cliScope);
|
|
393
509
|
const destination = resolve(profileDirectory, "node_modules", "@deepseek-ai");
|
|
394
510
|
rmSync(destination, {
|
|
395
511
|
recursive: true,
|
|
396
512
|
force: true
|
|
397
513
|
});
|
|
398
|
-
|
|
514
|
+
mkdirSync(destination, { recursive: true });
|
|
515
|
+
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
516
|
+
for (const name of readdirSync(cliScope).sort()) symlinkSync(resolve(cliScope, name), resolve(destination, name), linkType);
|
|
517
|
+
for (const entry of workspacePackages) {
|
|
518
|
+
const target = resolve(destination, entry.name.slice(13));
|
|
519
|
+
if (existsSync(target)) continue;
|
|
520
|
+
symlinkSync(entry.directory, target, linkType);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
function linkOfficialPackages(profileDirectory, dshRoot) {
|
|
524
|
+
materializeOfficialPackageScope(profileDirectory, resolve(officialPackageRoot(dshRoot), "node_modules", "@deepseek-ai"), listOfficialWorkspacePackages(dshRoot));
|
|
399
525
|
}
|
|
400
526
|
function writeLock(profileDirectory, lock) {
|
|
401
527
|
const directory = resolve(profileDirectory, ".dsh-plus");
|
|
@@ -446,4 +572,4 @@ function runApply(argv) {
|
|
|
446
572
|
process.stdout.write("[dsh-plus] applied " + String(selection.patches.length) + " patches; lock " + lock + "\n");
|
|
447
573
|
}
|
|
448
574
|
//#endregion
|
|
449
|
-
export { runApply };
|
|
575
|
+
export { materializeOfficialPackageScope, parseOfficialWorkspacePackages, runApply };
|
package/lib/types/apply.d.ts
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
/** Materialize the Plus distribution's independent patch packages without Desktop. */
|
|
2
|
+
/** One official workspace package available as a profile peer dependency. */
|
|
3
|
+
export interface OfficialWorkspacePackage {
|
|
4
|
+
name: string;
|
|
5
|
+
directory: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parse pnpm's workspace roster into exact official package directories.
|
|
9
|
+
* @param dshRoot - exact official DSH checkout root.
|
|
10
|
+
* @param stdout - JSON emitted by `pnpm -r list --json --depth -1`.
|
|
11
|
+
* @returns sorted official package names and directories inside the checkout.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseOfficialWorkspacePackages(dshRoot: string, stdout: string): OfficialWorkspacePackage[];
|
|
14
|
+
/**
|
|
15
|
+
* Build the profile's official scope from the CLI closure plus source workspaces.
|
|
16
|
+
* @param profileDirectory - materialized Plus profile root.
|
|
17
|
+
* @param cliScope - official packages already installed under the DSH CLI.
|
|
18
|
+
* @param workspacePackages - additional official source workspaces required by external peers.
|
|
19
|
+
*/
|
|
20
|
+
export declare function materializeOfficialPackageScope(profileDirectory: string, cliScope: string, workspacePackages: readonly OfficialWorkspacePackage[]): void;
|
|
2
21
|
/**
|
|
3
22
|
* Apply the installed Plus distribution metadata from a DSH profile directory.
|
|
4
23
|
* @param argv - Explicit `apply --dsh-root <path>` command arguments.
|
package/package.json
CHANGED
|
@@ -3,32 +3,42 @@
|
|
|
3
3
|
"dsh-plus": "lib/bin.js"
|
|
4
4
|
},
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@
|
|
7
|
-
"@sparkelf/dsh-
|
|
8
|
-
"@sparkelf/dsh-patch-better-sidebar-app-frame": ">=0.1.0-rc.
|
|
9
|
-
"@sparkelf/dsh-patch-
|
|
10
|
-
"@sparkelf/dsh-patch-
|
|
11
|
-
"@sparkelf/dsh-patch-
|
|
12
|
-
"@sparkelf/dsh-patch-
|
|
13
|
-
"@sparkelf/dsh-patch-
|
|
14
|
-
"@sparkelf/dsh-patch-
|
|
15
|
-
"@sparkelf/dsh-patch-
|
|
16
|
-
"@sparkelf/dsh-patch-
|
|
17
|
-
"@sparkelf/dsh-
|
|
18
|
-
"@sparkelf/dsh-
|
|
19
|
-
"@sparkelf/dsh-
|
|
20
|
-
"@sparkelf/dsh-
|
|
21
|
-
"@sparkelf/dsh-
|
|
22
|
-
"
|
|
6
|
+
"@sparkelf/dsh-mobile-bridge": ">=0.2.10",
|
|
7
|
+
"@sparkelf/dsh-patch-better-sidebar-alpha2-settings": ">=0.1.0-rc.13",
|
|
8
|
+
"@sparkelf/dsh-patch-better-sidebar-app-frame": ">=0.1.0-rc.13",
|
|
9
|
+
"@sparkelf/dsh-patch-browser-auth-mode": ">=0.1.0-rc.13",
|
|
10
|
+
"@sparkelf/dsh-patch-document-attachments": ">=0.1.0-rc.13",
|
|
11
|
+
"@sparkelf/dsh-patch-genui-skill-chart-contract": ">=0.1.0-rc.13",
|
|
12
|
+
"@sparkelf/dsh-patch-genui-streaming-echart": ">=0.1.0-rc.13",
|
|
13
|
+
"@sparkelf/dsh-patch-legacy-code-preset": ">=0.1.0-rc.13",
|
|
14
|
+
"@sparkelf/dsh-patch-mobile-web-layout": ">=0.1.0-rc.13",
|
|
15
|
+
"@sparkelf/dsh-patch-ptc-mcp-schema-types": ">=0.1.0-rc.13",
|
|
16
|
+
"@sparkelf/dsh-patch-responses-reasoning-status": ">=0.1.0-rc.13",
|
|
17
|
+
"@sparkelf/dsh-patch-session-export-chinese": ">=0.1.0-rc.13",
|
|
18
|
+
"@sparkelf/dsh-patch-session-log-trajectory-toolbar": ">=0.1.0-rc.13",
|
|
19
|
+
"@sparkelf/dsh-patch-subagent-settings-presets": ">=0.1.0-rc.13",
|
|
20
|
+
"@sparkelf/dsh-patch-univer-office-alpha2": ">=0.1.0-rc.13",
|
|
21
|
+
"@sparkelf/dsh-patch-web-base-path": ">=0.1.0-rc.13",
|
|
22
|
+
"@sparkelf/dsh-patch-workspace-storage-restore": ">=0.1.0-rc.13",
|
|
23
|
+
"@sparkelf/dsh-plugin-backup": ">=0.1.0-rc.13",
|
|
24
|
+
"@sparkelf/dsh-plugin-dataops": ">=0.1.0-rc.13",
|
|
25
|
+
"@sparkelf/dsh-plugin-document-attachments": ">=0.1.0-rc.13",
|
|
26
|
+
"@sparkelf/dsh-plugin-mcp-credentials": ">=0.1.0-rc.13",
|
|
27
|
+
"@sparkelf/dsh-plugin-subagent-settings": ">=0.1.0-rc.13",
|
|
28
|
+
"dshmarket": ">=1.38.1",
|
|
23
29
|
"semver": ">=7.7.3",
|
|
24
30
|
"yaml": ">=2.9.0"
|
|
25
31
|
},
|
|
26
32
|
"description": "DeepSeek Harness Plus official-base Web distribution profile and ranged compatibility patchset",
|
|
27
33
|
"devDependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@deepseek-ai/
|
|
34
|
+
"@changfenhuang/dsh-genui": "0.9.6",
|
|
35
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
36
|
+
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
|
|
37
|
+
"@huanlin/dsh-plugin-better-sidebar-plugin-office": "0.1.2",
|
|
30
38
|
"@types/semver": ">=7.7.1",
|
|
31
|
-
"dsh-better-sidebar": "0.17.1"
|
|
39
|
+
"dsh-better-sidebar": "0.17.1",
|
|
40
|
+
"dsh-univer-office": "0.2.12",
|
|
41
|
+
"dsh-video-preview": "0.1.4"
|
|
32
42
|
},
|
|
33
43
|
"dsh": {
|
|
34
44
|
"bundle": {
|
|
@@ -37,39 +47,56 @@
|
|
|
37
47
|
},
|
|
38
48
|
"dshPlus": {
|
|
39
49
|
"compatibility": {
|
|
40
|
-
"dsh": ">=0.1.2-alpha.
|
|
50
|
+
"dsh": ">=0.1.2-alpha.2"
|
|
41
51
|
},
|
|
42
52
|
"formatVersion": 1,
|
|
43
53
|
"patchPackages": [
|
|
44
54
|
"@sparkelf/dsh-patch-better-sidebar-app-frame",
|
|
55
|
+
"@sparkelf/dsh-patch-better-sidebar-alpha2-settings",
|
|
56
|
+
"@sparkelf/dsh-patch-univer-office-alpha2",
|
|
45
57
|
"@sparkelf/dsh-patch-genui-streaming-echart",
|
|
46
|
-
"@sparkelf/dsh-patch-
|
|
58
|
+
"@sparkelf/dsh-patch-genui-skill-chart-contract",
|
|
59
|
+
"@sparkelf/dsh-patch-browser-auth-mode",
|
|
47
60
|
"@sparkelf/dsh-patch-workspace-storage-restore",
|
|
48
61
|
"@sparkelf/dsh-patch-subagent-settings-presets",
|
|
49
62
|
"@sparkelf/dsh-patch-document-attachments",
|
|
63
|
+
"@sparkelf/dsh-patch-legacy-code-preset",
|
|
64
|
+
"@sparkelf/dsh-patch-session-export-chinese",
|
|
65
|
+
"@sparkelf/dsh-patch-session-log-trajectory-toolbar",
|
|
50
66
|
"@sparkelf/dsh-patch-responses-reasoning-status",
|
|
67
|
+
"@sparkelf/dsh-patch-ptc-mcp-schema-types",
|
|
51
68
|
"@sparkelf/dsh-patch-mobile-web-layout",
|
|
52
69
|
"@sparkelf/dsh-patch-web-base-path"
|
|
53
70
|
],
|
|
54
71
|
"profile": {
|
|
55
72
|
"allowBuilds": {
|
|
56
|
-
"node-pty": true
|
|
73
|
+
"node-pty": true,
|
|
74
|
+
"protobufjs": false
|
|
57
75
|
},
|
|
58
76
|
"bundles": [
|
|
59
77
|
"@deepseek-ai/dsh-base",
|
|
60
78
|
"@deepseek-ai/dsh-web-app",
|
|
61
79
|
"dsh-better-sidebar",
|
|
80
|
+
"@huanlin/dsh-plugin-better-sidebar-plugin-office",
|
|
81
|
+
"dsh-video-preview",
|
|
82
|
+
"dsh-univer-office",
|
|
62
83
|
"@sparkelf/dsh-mobile-bridge",
|
|
63
84
|
"dshmarket",
|
|
64
85
|
"@changfenhuang/dsh-genui",
|
|
86
|
+
"@sparkelf/dsh-plugin-supervisor",
|
|
65
87
|
"@sparkelf/dsh-plus"
|
|
66
88
|
],
|
|
67
89
|
"dependencies": {
|
|
68
|
-
"dsh-
|
|
90
|
+
"@changfenhuang/dsh-genui": "0.9.6",
|
|
91
|
+
"@huanlin/dsh-plugin-better-sidebar-plugin-office": "0.1.2",
|
|
92
|
+
"@sparkelf/dsh-plugin-supervisor": "0.1.1",
|
|
93
|
+
"dsh-better-sidebar": "0.17.1",
|
|
94
|
+
"dsh-univer-office": "0.2.12",
|
|
95
|
+
"dsh-video-preview": "0.1.4"
|
|
69
96
|
}
|
|
70
97
|
},
|
|
71
98
|
"sourceBase": {
|
|
72
|
-
"revision": "
|
|
99
|
+
"revision": "0a53fb55bea101816fa226bb964ae2bed71c343b"
|
|
73
100
|
}
|
|
74
101
|
},
|
|
75
102
|
"exports": {
|
|
@@ -101,7 +128,7 @@
|
|
|
101
128
|
"name": "@sparkelf/dsh-plus",
|
|
102
129
|
"peerDependencies": {
|
|
103
130
|
"@deepseek-ai/cordis": ">=4.0.1",
|
|
104
|
-
"@deepseek-ai/dsh-invariants": ">=0.1.2-alpha.
|
|
131
|
+
"@deepseek-ai/dsh-invariants": ">=0.1.2-alpha.2"
|
|
105
132
|
},
|
|
106
133
|
"publishConfig": {
|
|
107
134
|
"access": "public"
|
|
@@ -113,5 +140,5 @@
|
|
|
113
140
|
},
|
|
114
141
|
"type": "module",
|
|
115
142
|
"types": "lib/types/index.d.ts",
|
|
116
|
-
"version": "0.1.0-rc.
|
|
143
|
+
"version": "0.1.0-rc.13"
|
|
117
144
|
}
|