@dsh-electron/dsh-plugin-multi-root-workspace 0.1.0 → 0.1.2

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.
Files changed (43) hide show
  1. package/CHANGELOG.en.md +89 -0
  2. package/CHANGELOG.md +89 -0
  3. package/README.en.md +96 -20
  4. package/README.md +97 -19
  5. package/cordis.patch.yml +22 -1
  6. package/lib/client.js +234 -71
  7. package/lib/client.js.map +1 -1
  8. package/lib/{command-BSkrYOAf.js → command-DyOWujPo.js} +24 -61
  9. package/lib/command.js +2 -2
  10. package/lib/compat-CRdv0vPw.js +272 -0
  11. package/lib/compat.js +2 -0
  12. package/lib/{fs-D7UoCb7T.js → fs-D_Sw3o5z.js} +7 -3
  13. package/lib/fs.js +1 -1
  14. package/lib/index.js +8 -6
  15. package/lib/instructions-Cn1Jj5Xi.js +703 -0
  16. package/lib/instructions.js +2 -0
  17. package/lib/registry-DySMbjgW.js +793 -0
  18. package/lib/registry-lease-win32-dy8TQMD9.js +93 -0
  19. package/lib/registry.js +2 -466
  20. package/lib/{sandbox-BhuMTDgH.js → sandbox-D8Fw95FM.js} +51 -4
  21. package/lib/sandbox.js +1 -1
  22. package/lib/scope.js +1 -1
  23. package/lib/types/client/locales.d.ts +6 -0
  24. package/lib/types/client/panel-client.d.ts +0 -2
  25. package/lib/types/command.d.ts +17 -0
  26. package/lib/types/compat/agent-instructions.d.ts +138 -0
  27. package/lib/types/compat/client-icons.d.ts +40 -0
  28. package/lib/types/compat/client-session.d.ts +32 -0
  29. package/lib/types/compat/dsh-version.d.ts +119 -0
  30. package/lib/types/compat/llm-message.d.ts +72 -0
  31. package/lib/types/compat/sandbox-confine.d.ts +58 -0
  32. package/lib/types/compat/tool-result.d.ts +29 -0
  33. package/lib/types/compat.d.ts +85 -0
  34. package/lib/types/contract.d.ts +6 -8
  35. package/lib/types/index.d.ts +19 -5
  36. package/lib/types/instructions.d.ts +125 -0
  37. package/lib/types/registry-lease-win32.d.ts +29 -0
  38. package/lib/types/registry-lease.d.ts +62 -0
  39. package/lib/types/registry.d.ts +130 -19
  40. package/lib/types/roots.d.ts +1 -1
  41. package/lib/types/sandbox.d.ts +22 -2
  42. package/package.json +60 -13
  43. package/lib/{roots-DyT2jgEP.js → roots-DasWEBJk.js} +1 -1
@@ -1,7 +1,6 @@
1
- import { f as resolveRootRef, i as canonicalRoot, o as entryRootRef, r as availableRoots, s as expandRootInput, t as RootValidationError } from "./roots-DyT2jgEP.js";
2
- import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
3
- import { statSync } from "node:fs";
1
+ import { f as resolveRootRef, i as canonicalRoot, o as entryRootRef, r as availableRoots, t as RootValidationError } from "./roots-DasWEBJk.js";
4
2
  import "@deepseek-ai/cordis";
3
+ import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
5
4
  import { z } from "zod";
6
5
  //#region src/contract.ts
7
6
  /**
@@ -53,8 +52,7 @@ const PANEL_ENDPOINTS = [
53
52
  * would hide the drift.
54
53
  */
55
54
  const panelRequestSchema = z.object({
56
- primaryRoot: z.string().optional(),
57
- sessionId: z.string().optional(),
55
+ sessionId: z.string().min(1),
58
56
  entry: z.object({
59
57
  ordinal: z.number().int().positive(),
60
58
  id: z.string(),
@@ -170,8 +168,7 @@ function parseRevealedView(value) {
170
168
  function narrowCall(endpoint, value) {
171
169
  return {
172
170
  endpoint,
173
- ...value.primaryRoot === void 0 ? {} : { primaryRoot: value.primaryRoot },
174
- ...value.sessionId === void 0 ? {} : { sessionId: value.sessionId },
171
+ sessionId: value.sessionId,
175
172
  ...value.entry === void 0 ? {} : { entry: value.entry },
176
173
  ...value.id === void 0 ? {} : { id: value.id },
177
174
  ...value.path === void 0 ? {} : { path: value.path },
@@ -200,35 +197,6 @@ function firstIssue(error) {
200
197
  }
201
198
  //#endregion
202
199
  //#region src/command.ts
203
- /**
204
- * The user-facing surface: the `/workspace-folders` command and the panel's
205
- * RPC channel.
206
- *
207
- * They share one module because they are one thing — the operator-facing edge
208
- * over `ctx.multiRootRegistry`. The command serves the text surfaces (the
209
- * composer, headless diagnostics) and the channel serves the browser panel;
210
- * both resolve the same canonical workspace root, call the same registry, and
211
- * report the same `RootValidationCode` values.
212
- *
213
- * Both are also the two places a READ happens, so both go through the same
214
- * revalidation entry point: `registry.refresh()` re-stats every registered
215
- * directory, re-resolves it against the directory it was granted for, and
216
- * republishes the scope BEFORE the list is rendered. Listing is therefore
217
- * enough to notice that a directory disappeared (and enough to bring a
218
- * restored one back) — which is what the panel's "Retry" button and the
219
- * command's `list` both promise.
220
- *
221
- * Both halves are SOFT: the command registers only where a command registry is
222
- * composed, and the channel only where a host Connection and web server exist
223
- * (web), so a headless profile mounts this row with zero effect on the
224
- * providers.
225
- *
226
- * The command's own text is English: a host-side command handler has no active
227
- * locale to consult (the browser owns locale state). The panel is bilingual.
228
- * That split is recorded in the M3 plan and the requirements as a known limit.
229
- *
230
- * @module @dsh-electron/dsh-plugin-multi-root-workspace/command
231
- */
232
200
  /** Services this row needs before it may activate. */
233
201
  const inject = [
234
202
  "commands",
@@ -487,31 +455,26 @@ async function targetOf(registry, primaryRoot, text) {
487
455
  };
488
456
  }
489
457
  /**
490
- * Resolve the workspace root a panel request acts on.
458
+ * Derive the primary root a panel request may act on.
459
+ *
460
+ * The browser names a live session; the host looks that session up and uses
461
+ * its immutable cwd. There is no client-supplied path and no deployment-default
462
+ * fallback: a panel call without a real host session has no workspace to
463
+ * manage. Property access would demand an injected `sessions` dependency this
464
+ * row does not name, so the lookup stays an explicit sibling `get` (the same
465
+ * pattern as `directoryPicker` / `subprocess`).
491
466
  *
492
- * A client-supplied `primaryRoot` is accepted — the browser is the operator's
493
- * own trusted client, and the panel names the root it displays — but it must be
494
- * an existing directory. Otherwise the session's immutable cwd, then the
495
- * deployment fallback, decides.
467
+ * @param ctx - the host context that may carry `sessions`.
468
+ * @param sessionId - the id the panel sent; already required by the wire schema.
469
+ * @returns the canonical cwd of that session.
470
+ * @throws {RootValidationError} `session-not-found` when the service is absent,
471
+ * the id does not name a live session, or that session has no cwd.
496
472
  */
497
- function primaryRootOf(ctx, request) {
498
- if (request.primaryRoot !== void 0 && request.primaryRoot !== "") {
499
- const canonical = canonicalRoot(expandRootInput(request.primaryRoot));
500
- let isDirectory = false;
501
- try {
502
- isDirectory = statSync(canonical).isDirectory();
503
- } catch {
504
- isDirectory = false;
505
- }
506
- if (!isDirectory) throw new RootValidationError("missing", `"${request.primaryRoot}" is not an existing directory`, { reference: request.primaryRoot });
507
- return canonical;
508
- }
509
- if (request.sessionId !== void 0 && request.sessionId !== "") {
510
- const cwd = ctx.get("sessions")?.get(request.sessionId)?.header.cwd;
511
- if (cwd !== void 0 && cwd !== "") return canonicalPath(cwd);
512
- }
513
- const policy = ctx.sandboxPolicy.resolve();
514
- return canonicalRoot(policy.workspaceRoot);
473
+ function resolvePanelPrimaryRoot(ctx, sessionId) {
474
+ const session = ctx.get("sessions")?.get(sessionId);
475
+ const cwd = session?.header.cwd;
476
+ if (session === void 0 || cwd === void 0 || cwd === "") throw new RootValidationError("session-not-found", `session "${sessionId}" is not an active host session`, { reference: sessionId });
477
+ return canonicalPath(cwd);
515
478
  }
516
479
  /** Project one status into the panel's view. */
517
480
  function toRootView(status, index) {
@@ -589,7 +552,7 @@ async function dispatchPanelRequest(ctx, endpoint, payload, _signal) {
589
552
  };
590
553
  const request = parsed.value;
591
554
  const registry = ctx.multiRootRegistry;
592
- const primaryRoot = primaryRootOf(ctx, request);
555
+ const primaryRoot = resolvePanelPrimaryRoot(ctx, request.sessionId);
593
556
  switch (request.endpoint) {
594
557
  case "list": return {
595
558
  ok: true,
@@ -724,4 +687,4 @@ async function revealRoot(ctx, path) {
724
687
  if (outcome.exitCode !== 0) throw new RootValidationError("reveal-unavailable", `the file manager exited with ${String(outcome.exitCode)}`);
725
688
  }
726
689
  //#endregion
727
- export { renderRootsReport as a, PANEL_ENDPOINTS as c, parseRootsView as d, parseFoldersCommand as i, parsePanelCall as l, apply as n, revealArgv as o, inject as r, PANEL_CHANNEL as s, COMMAND_NAME as t, parseRevealedView as u };
690
+ export { renderRootsReport as a, PANEL_CHANNEL as c, parseRevealedView as d, parseRootsView as f, parseFoldersCommand as i, PANEL_ENDPOINTS as l, apply as n, resolvePanelPrimaryRoot as o, inject as r, revealArgv as s, COMMAND_NAME as t, parsePanelCall as u };
package/lib/command.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as renderRootsReport, i as parseFoldersCommand, n as apply, o as revealArgv, r as inject, t as COMMAND_NAME } from "./command-BSkrYOAf.js";
2
- export { COMMAND_NAME, apply, inject, parseFoldersCommand, renderRootsReport, revealArgv };
1
+ import { a as renderRootsReport, i as parseFoldersCommand, n as apply, o as resolvePanelPrimaryRoot, r as inject, s as revealArgv, t as COMMAND_NAME } from "./command-DyOWujPo.js";
2
+ export { COMMAND_NAME, apply, inject, parseFoldersCommand, renderRootsReport, resolvePanelPrimaryRoot, revealArgv };
@@ -0,0 +1,272 @@
1
+ import { createRequire } from "node:module";
2
+ import { Service } from "@deepseek-ai/cordis";
3
+ //#region src/compat/dsh-version.ts
4
+ /**
5
+ * The DSH compatibility contract: which upstream releases this plugin is
6
+ * actually verified against, and how an installation is judged against that
7
+ * list.
8
+ *
9
+ * This module is the ONE place the support matrix is spelled out. It is
10
+ * deliberately pure — no cordis, no logging, no process exit — so that the
11
+ * runtime gate (`src/compat.ts`), the static gate (`scripts/check-dsh-compat.mjs`)
12
+ * and the tests all judge an installation by the same code instead of three
13
+ * drifting copies of the same list.
14
+ *
15
+ * Why a contract exists at all: this plugin replaces `ctx.fs` and `ctx.sandbox`
16
+ * with subclasses of the upstream providers, and `src/dialects.ts` recognizes
17
+ * the kernel-sandbox profile by OBSERVING the argv shape `super.confine`
18
+ * produced (ADR-0003). Both couplings are to pre-stable upstream internals that
19
+ * carry no semver promise. An npm range like `>=0.1.2-alpha.4 <0.2.0` therefore
20
+ * promises far more than the code was ever verified against; the allowlist
21
+ * below promises exactly what CI has run.
22
+ *
23
+ * @module @dsh-electron/dsh-plugin-multi-root-workspace/compat/dsh-version
24
+ */
25
+ /**
26
+ * The releases this plugin is verified against, as EXACT version strings.
27
+ *
28
+ * Not a semver range, on purpose: a range is a prediction about releases that
29
+ * do not exist yet, and this plugin's coupling to upstream argv shapes makes
30
+ * that prediction unsafe. Adding an entry is always a human act performed after
31
+ * the upgrade smoke passed on that exact version — a green CI run on an
32
+ * unlisted release is evidence, not authorization (ADR-0009).
33
+ */
34
+ const SUPPORTED_DSH_RELEASES = [
35
+ "0.1.5-rc.2",
36
+ "0.1.6-alpha.1",
37
+ "0.1.6-alpha.2",
38
+ "0.1.7-alpha.1"
39
+ ];
40
+ /**
41
+ * Packages whose absence means this plugin cannot function at all: every one of
42
+ * them is either subclassed, imported for a value, or the owner of a service
43
+ * key the providers inject.
44
+ */
45
+ const REQUIRED_CORE_PACKAGES = [
46
+ "@deepseek-ai/dsh-fs",
47
+ "@deepseek-ai/dsh-fs-local",
48
+ "@deepseek-ai/dsh-sandbox",
49
+ "@deepseek-ai/dsh-sandbox-local",
50
+ "@deepseek-ai/dsh-sandbox-policy",
51
+ "@deepseek-ai/dsh-storage-domain"
52
+ ];
53
+ /**
54
+ * Packages a full composition provides and a minimal one legitimately omits.
55
+ * Absence is fine; a version that DISAGREES with the required packages is not —
56
+ * that is the mixed-installation failure this contract exists to catch.
57
+ */
58
+ const OPTIONAL_CORE_PACKAGES = [
59
+ "@deepseek-ai/dsh-agent",
60
+ "@deepseek-ai/dsh-agent-instructions",
61
+ "@deepseek-ai/dsh-client-connection",
62
+ "@deepseek-ai/dsh-commands",
63
+ "@deepseek-ai/dsh-llm",
64
+ "@deepseek-ai/dsh-session",
65
+ "@deepseek-ai/dsh-subprocess",
66
+ "@deepseek-ai/dsh-system-prompt"
67
+ ];
68
+ /** Every package the contract inspects, required first. */
69
+ const CORE_PACKAGES = [...REQUIRED_CORE_PACKAGES, ...OPTIONAL_CORE_PACKAGES];
70
+ /** The environment variable that relaxes the gate. */
71
+ const COMPAT_ENFORCEMENT_ENV = "DSH_MULTI_ROOT_COMPAT";
72
+ /**
73
+ * Read one package's declared version through Node resolution.
74
+ *
75
+ * Resolution runs from THIS module, which is what makes the answer meaningful:
76
+ * the upstream packages are peer dependencies, so they resolve to the single
77
+ * copy the host provides — the same copy the providers will subclass at
78
+ * runtime. A package that cannot be resolved is reported absent rather than
79
+ * throwing, because "not installed" is a legitimate answer for every optional
80
+ * package.
81
+ * @param packageName - the package to inspect.
82
+ * @returns the declared version, or `undefined` when the package or its
83
+ * manifest cannot be resolved.
84
+ */
85
+ function readInstalledVersion(packageName) {
86
+ try {
87
+ const manifest = createRequire(import.meta.url)(`${packageName}/package.json`);
88
+ return typeof manifest.version === "string" ? manifest.version : void 0;
89
+ } catch {
90
+ return;
91
+ }
92
+ }
93
+ /**
94
+ * Judge one installation against the contract.
95
+ *
96
+ * The three checks run in this order, and the first failure wins, because each
97
+ * later check would report nonsense about an installation that failed an
98
+ * earlier one: a missing required package has no version to compare, and a
99
+ * mixed installation has no single version to look up in the allowlist.
100
+ * @param readVersion - version reader; defaults to Node resolution. Tests and
101
+ * the static checker pass their own.
102
+ * @returns the report; never throws.
103
+ */
104
+ function classifyInstallation(readVersion = readInstalledVersion) {
105
+ const packages = CORE_PACKAGES.map((name) => ({
106
+ name,
107
+ version: readVersion(name),
108
+ required: REQUIRED_CORE_PACKAGES.includes(name)
109
+ }));
110
+ const missing = packages.filter((entry) => entry.required && entry.version === void 0);
111
+ if (missing.length > 0) return report("incomplete", void 0, packages, [
112
+ "multi-root workspace: required DSH packages are not installed.",
113
+ "",
114
+ ...missing.map((entry) => ` missing: ${entry.name}`)
115
+ ]);
116
+ const releases = [...new Set(packages.flatMap((entry) => entry.version === void 0 ? [] : [entry.version]))].sort();
117
+ const [release, ...extra] = releases;
118
+ if (release === void 0) return report("incomplete", void 0, packages, ["multi-root workspace: no DSH package could be inspected."]);
119
+ if (extra.length > 0) return report("mixed", void 0, packages, [
120
+ "multi-root workspace: this installation mixes several DSH releases.",
121
+ "",
122
+ "The filesystem fence and the kernel-sandbox dialects must agree on one upstream",
123
+ "release; a mixed installation means one half of the sandbox was verified against a",
124
+ "shape the other half no longer produces. Align every @deepseek-ai/dsh* package on",
125
+ "one release.",
126
+ "",
127
+ ` releases found: ${releases.join(", ")}`
128
+ ]);
129
+ if (!SUPPORTED_DSH_RELEASES.includes(release)) return report("unsupported", release, packages, [
130
+ `multi-root workspace: DSH ${release} is not a supported release.`,
131
+ "",
132
+ "This plugin replaces the workspace filesystem fence and the kernel-sandbox provider,",
133
+ "and it recognizes the sandbox profile by the argv shape the upstream provider produces.",
134
+ "Upstream makes no semver promise, so the plugin refuses to grant additional roots on a",
135
+ "release it has never been verified against rather than guess at that shape.",
136
+ "",
137
+ ` supported: ${SUPPORTED_DSH_RELEASES.join(", ")}`,
138
+ ` installed: ${release}`
139
+ ]);
140
+ return report("supported", release, packages, [`multi-root workspace: DSH ${release} is a supported release.`]);
141
+ }
142
+ /**
143
+ * Read the enforcement mode.
144
+ *
145
+ * `warn` exists for exactly one caller: the upgrade smoke, which must run the
146
+ * whole behavior matrix against a release that is deliberately NOT on the
147
+ * allowlist yet — that run is how a release earns its place on the list. It is
148
+ * not a production escape hatch, and the warning says so.
149
+ * @param env - the environment to read; defaults to this process's.
150
+ * @returns `warn` only when explicitly requested, `enforce` otherwise.
151
+ */
152
+ function compatEnforcement(env = process.env) {
153
+ return env["DSH_MULTI_ROOT_COMPAT"] === "warn" ? "warn" : "enforce";
154
+ }
155
+ /** Compose a report, appending the package inventory and the recovery pointer. */
156
+ function report(verdict, release, packages, lines) {
157
+ return {
158
+ verdict,
159
+ release,
160
+ packages,
161
+ message: (verdict === "supported" ? [...lines] : [
162
+ ...lines,
163
+ "",
164
+ "Inspected packages:",
165
+ ...packages.map((entry) => ` ${entry.name} ${entry.version ?? "(not installed)"}`),
166
+ "",
167
+ "See docs/troubleshooting/unsupported-dsh-release.md"
168
+ ]).join("\n")
169
+ };
170
+ }
171
+ //#endregion
172
+ //#region src/compat.ts
173
+ /**
174
+ * `multi-root-compat`: the startup gate that turns the DSH compatibility
175
+ * contract from documentation into a precondition.
176
+ *
177
+ * The four security-relevant rows of this bundle — `multi-root-fs`,
178
+ * `multi-root-sandbox`, `multi-root-registry`, `multi-root-instructions` —
179
+ * inject `multiRootCompat`. Cordis will not start a plugin whose injected
180
+ * service is absent, so this row is what decides whether they run at all:
181
+ *
182
+ * ```text
183
+ * compat check passes → ctx.multiRootCompat exists → the providers start
184
+ * compat check fails → the row throws → they never start
185
+ * ```
186
+ *
187
+ * That is why the gate is a plain `apply` and not a `Service` subclass mounted
188
+ * directly: the check has to be able to fail BEFORE the service exists. A
189
+ * `Service` constructor has already run `super(ctx, name)` — and therefore
190
+ * already claimed the service key — by the time it could inspect anything.
191
+ *
192
+ * The verdict itself, and the allowlist it is judged against, live in
193
+ * `./compat/dsh-version.ts`. This module owns only the reaction to it.
194
+ *
195
+ * @module @dsh-electron/dsh-plugin-multi-root-workspace/compat
196
+ */
197
+ /**
198
+ * Raised when the installed DSH release is not one this plugin is verified
199
+ * against. It is thrown from `apply`, so it surfaces as a plugin load failure
200
+ * with the full diagnosis attached — never as a silently degraded sandbox.
201
+ */
202
+ var DshCompatUnsupportedError = class extends Error {
203
+ /** The report that produced the refusal. */
204
+ report;
205
+ constructor(report) {
206
+ super(report.message);
207
+ this.name = "DshCompatUnsupportedError";
208
+ this.report = report;
209
+ }
210
+ };
211
+ /**
212
+ * The `ctx.multiRootCompat` service: the resolved compatibility verdict, held
213
+ * where the gated providers can read it.
214
+ *
215
+ * It intentionally exposes no per-version capability flags. The adapters under
216
+ * `./compat/` detect the shape they need STRUCTURALLY — whether a return value
217
+ * is a thenable, which export name a module carries — because a structural
218
+ * probe also survives upstream reshaping something within one release, while a
219
+ * version comparison does not. The release string here is for the gate and for
220
+ * diagnostics.
221
+ */
222
+ var MultiRootCompatService = class extends Service {
223
+ /** The verdict this composition started under. */
224
+ report;
225
+ constructor(ctx, report) {
226
+ super(ctx, "multiRootCompat");
227
+ this.report = report;
228
+ }
229
+ /** The single DSH release every inspected core package agreed on. */
230
+ get release() {
231
+ return this.report.release;
232
+ }
233
+ /** Whether the installation is on the allowlist. */
234
+ get supported() {
235
+ return this.report.verdict === "supported";
236
+ }
237
+ };
238
+ /** This row needs nothing: it is the thing everything else waits for. */
239
+ const inject = [];
240
+ /**
241
+ * Apply the gate policy to one report.
242
+ *
243
+ * Under `DSH_MULTI_ROOT_COMPAT=warn` exactly one verdict is relaxed: an
244
+ * `unsupported` release that every inspected package agrees on. That is the
245
+ * only shape the upgrade smoke probes — a coherent tree on a release the
246
+ * allowlist does not name yet, which is how a release earns its place there.
247
+ * `mixed` and `incomplete` describe an installation the contract cannot judge
248
+ * at all, so they are refused in either mode; production deployments leave the
249
+ * variable unset and get the refusal for everything.
250
+ * @param report - the verdict to act on.
251
+ * @param enforcement - how to react to a non-`supported` verdict.
252
+ * @returns the warning to log, or `undefined` when there is nothing to say.
253
+ * @throws {DshCompatUnsupportedError} when refusing to run.
254
+ */
255
+ function assertSupportedInstallation(report, enforcement) {
256
+ if (report.verdict === "supported") return void 0;
257
+ if (enforcement === "enforce" || report.verdict !== "unsupported") throw new DshCompatUnsupportedError(report);
258
+ return `${report.message}\n\nProceeding anyway because ${COMPAT_ENFORCEMENT_ENV}=warn. This is an upgrade-smoke mode: additional workspace roots are about to be granted through a sandbox profile shape that has not been verified on this release. Supported releases: ${SUPPORTED_DSH_RELEASES.join(", ")}.`;
259
+ }
260
+ /**
261
+ * Judge the installation, then either refuse to provide the service or provide
262
+ * it.
263
+ * @param ctx - the row's context.
264
+ */
265
+ function apply(ctx) {
266
+ const report = classifyInstallation();
267
+ const warning = assertSupportedInstallation(report, compatEnforcement());
268
+ if (warning !== void 0) ctx.logger.warn(warning);
269
+ ctx.plugin(MultiRootCompatService, report);
270
+ }
271
+ //#endregion
272
+ export { inject as a, REQUIRED_CORE_PACKAGES as c, compatEnforcement as d, readInstalledVersion as f, assertSupportedInstallation as i, SUPPORTED_DSH_RELEASES as l, MultiRootCompatService as n, CORE_PACKAGES as o, apply as r, OPTIONAL_CORE_PACKAGES as s, DshCompatUnsupportedError as t, classifyInstallation as u };
package/lib/compat.js ADDED
@@ -0,0 +1,2 @@
1
+ import { a as inject, i as assertSupportedInstallation, n as MultiRootCompatService, r as apply, t as DshCompatUnsupportedError } from "./compat-CRdv0vPw.js";
2
+ export { DshCompatUnsupportedError, MultiRootCompatService, apply, assertSupportedInstallation, inject };
@@ -1,8 +1,8 @@
1
+ import { dirname, sep } from "node:path";
2
+ import { writableRoots } from "@deepseek-ai/dsh-sandbox";
1
3
  import { FsError } from "@deepseek-ai/dsh-fs";
2
4
  import { LocalFileSystem } from "@deepseek-ai/dsh-fs-local";
3
- import { writableRoots } from "@deepseek-ai/dsh-sandbox";
4
5
  import { stat } from "node:fs/promises";
5
- import { dirname, sep } from "node:path";
6
6
  //#region src/containment.ts
7
7
  const MISSING_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR"]);
8
8
  function isMissing(error) {
@@ -64,7 +64,11 @@ async function isPathUnder(path, root, caseSensitive = process.platform !== "win
64
64
  * roots.
65
65
  */
66
66
  var MultiRootFileSystem = class extends LocalFileSystem {
67
- static inject = ["sandboxPolicy", "multiRootScope"];
67
+ static inject = [
68
+ "multiRootCompat",
69
+ "sandboxPolicy",
70
+ "multiRootScope"
71
+ ];
68
72
  defaultMode;
69
73
  constructor(ctx, config) {
70
74
  super(ctx, config);
package/lib/fs.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as MultiRootFileSystem } from "./fs-D7UoCb7T.js";
1
+ import { t as MultiRootFileSystem } from "./fs-D_Sw3o5z.js";
2
2
  export { MultiRootFileSystem, MultiRootFileSystem as default };
package/lib/index.js CHANGED
@@ -1,9 +1,11 @@
1
- import { t as MultiRootFileSystem } from "./fs-D7UoCb7T.js";
2
- import { t as MultiRootSandboxProvider } from "./sandbox-BhuMTDgH.js";
1
+ import { c as REQUIRED_CORE_PACKAGES, d as compatEnforcement, f as readInstalledVersion, i as assertSupportedInstallation, l as SUPPORTED_DSH_RELEASES, n as MultiRootCompatService, o as CORE_PACKAGES, s as OPTIONAL_CORE_PACKAGES, t as DshCompatUnsupportedError, u as classifyInstallation } from "./compat-CRdv0vPw.js";
2
+ import { a as composeInstructionMessage, c as createInstructionMessage, l as instructionsApi, r as PLUGIN_SOURCE, t as DEFAULT_MAX_BYTES, u as renderInstructions } from "./instructions-Cn1Jj5Xi.js";
3
+ import { n as widenConfined, t as MultiRootSandboxProvider } from "./sandbox-D8Fw95FM.js";
4
+ import { a as classifyStoredRoots, c as indexedStatuses, f as resolveRootRef, i as canonicalRoot, l as isCanonicallyUnder, n as additionalRootId, p as validateRootCandidate, r as availableRoots, s as expandRootInput, t as RootValidationError, u as removeStatusAt } from "./roots-DasWEBJk.js";
5
+ import { t as MultiRootFileSystem } from "./fs-D_Sw3o5z.js";
3
6
  import { MultiRootScopeService, renderWorkspaceRootsContext, sanitizeAdditionalRoots } from "./scope.js";
4
- import { a as classifyStoredRoots, c as indexedStatuses, f as resolveRootRef, i as canonicalRoot, l as isCanonicallyUnder, n as additionalRootId, p as validateRootCandidate, r as availableRoots, s as expandRootInput, t as RootValidationError, u as removeStatusAt } from "./roots-DyT2jgEP.js";
5
- import { DOMAIN_NAME, MAX_ALIAS_LENGTH, MultiRootRegistry, multiRootDomainSpec } from "./registry.js";
6
- import { a as renderRootsReport, c as PANEL_ENDPOINTS, d as parseRootsView, i as parseFoldersCommand, l as parsePanelCall, o as revealArgv, s as PANEL_CHANNEL, t as COMMAND_NAME, u as parseRevealedView } from "./command-BSkrYOAf.js";
7
+ import { c as RegistryLeaseContendedError, i as REGISTRY_CONTENDED_MESSAGE, n as MAX_ALIAS_LENGTH, o as multiRootDomainSpec, r as MultiRootRegistry, s as RegistryAuthorityLease, t as DOMAIN_NAME } from "./registry-DySMbjgW.js";
8
+ import { a as renderRootsReport, c as PANEL_CHANNEL, d as parseRevealedView, f as parseRootsView, i as parseFoldersCommand, l as PANEL_ENDPOINTS, o as resolvePanelPrimaryRoot, s as revealArgv, t as COMMAND_NAME, u as parsePanelCall } from "./command-DyOWujPo.js";
7
9
  //#region src/index.ts
8
10
  /**
9
11
  * Carrier plugin face for the bare-package-name loader row (see the module
@@ -14,4 +16,4 @@ import { a as renderRootsReport, c as PANEL_ENDPOINTS, d as parseRootsView, i as
14
16
  const inject = [];
15
17
  function apply() {}
16
18
  //#endregion
17
- export { COMMAND_NAME, DOMAIN_NAME, MAX_ALIAS_LENGTH, MultiRootFileSystem, MultiRootRegistry, MultiRootSandboxProvider, MultiRootScopeService, PANEL_CHANNEL, PANEL_ENDPOINTS, RootValidationError, additionalRootId, apply, availableRoots, canonicalRoot, classifyStoredRoots, expandRootInput, indexedStatuses, inject, isCanonicallyUnder, multiRootDomainSpec, parseFoldersCommand, parsePanelCall, parseRevealedView, parseRootsView, removeStatusAt, renderRootsReport, renderWorkspaceRootsContext, resolveRootRef, revealArgv, sanitizeAdditionalRoots, validateRootCandidate };
19
+ export { COMMAND_NAME, CORE_PACKAGES, DEFAULT_MAX_BYTES, DOMAIN_NAME, DshCompatUnsupportedError, MAX_ALIAS_LENGTH, MultiRootCompatService, MultiRootFileSystem, MultiRootRegistry, MultiRootSandboxProvider, MultiRootScopeService, OPTIONAL_CORE_PACKAGES, PANEL_CHANNEL, PANEL_ENDPOINTS, PLUGIN_SOURCE, REGISTRY_CONTENDED_MESSAGE, REQUIRED_CORE_PACKAGES, RegistryAuthorityLease, RegistryLeaseContendedError, RootValidationError, SUPPORTED_DSH_RELEASES, additionalRootId, apply, assertSupportedInstallation, availableRoots, canonicalRoot, classifyInstallation, classifyStoredRoots, compatEnforcement, composeInstructionMessage, createInstructionMessage, expandRootInput, indexedStatuses, inject, instructionsApi, isCanonicallyUnder, multiRootDomainSpec, parseFoldersCommand, parsePanelCall, parseRevealedView, parseRootsView, readInstalledVersion, removeStatusAt, renderInstructions, renderRootsReport, renderWorkspaceRootsContext, resolvePanelPrimaryRoot, resolveRootRef, revealArgv, sanitizeAdditionalRoots, validateRootCandidate, widenConfined };