@dsh-electron/dsh-plugin-multi-root-workspace 0.1.6 → 0.1.8

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 (95) hide show
  1. package/CHANGELOG.en.md +51 -1
  2. package/CHANGELOG.md +51 -1
  3. package/README.en.md +155 -92
  4. package/README.md +156 -91
  5. package/cordis.patch.yml +69 -4
  6. package/lib/client.js +2678 -276
  7. package/lib/client.js.map +1 -1
  8. package/lib/command-CESuwlVt.js +1306 -0
  9. package/lib/command.js +2 -2
  10. package/lib/compat-DR2LvmYZ.js +600 -0
  11. package/lib/compat.js +1 -1
  12. package/lib/contract-DZ4zczDT.js +238 -0
  13. package/lib/{fs-D_Sw3o5z.js → fs-Nlp2AiRX.js} +56 -24
  14. package/lib/fs.js +2 -1
  15. package/lib/index.js +10 -8
  16. package/lib/{instructions-DfzN-wVf.js → instructions-D19jRxN0.js} +3 -2
  17. package/lib/instructions.js +1 -1
  18. package/lib/lsp.js +7 -2
  19. package/lib/method-wrapper-CFY3p3j2.js +26 -0
  20. package/lib/process-fence.js +280 -0
  21. package/lib/providers.js +87 -0
  22. package/lib/{registry-DySMbjgW.js → registry-DCxC5Lay.js} +256 -35
  23. package/lib/registry.js +2 -2
  24. package/lib/{roots-DasWEBJk.js → roots-B-0l8mNG.js} +117 -20
  25. package/lib/sandbox-CVAcT_gy.js +743 -0
  26. package/lib/sandbox.js +2 -1
  27. package/lib/scope.js +229 -20
  28. package/lib/types/client/RootSwitcher.d.ts +63 -0
  29. package/lib/types/client/WorkspaceFoldersAction.d.ts +39 -1
  30. package/lib/types/client/files-tree/FilesBody.module.css.d.ts +24 -0
  31. package/lib/types/client/files-tree/FilesTree.d.ts +47 -0
  32. package/lib/types/client/files-tree/adapter.d.ts +94 -0
  33. package/lib/types/client/files-tree/directory-node.d.ts +62 -0
  34. package/lib/types/client/files-tree/face.d.ts +107 -0
  35. package/lib/types/client/files-tree/locales.d.ts +10 -0
  36. package/lib/types/client/files-tree/primitives.d.ts +33 -0
  37. package/lib/types/client/files-tree/store.d.ts +81 -0
  38. package/lib/types/client/locales.d.ts +56 -10
  39. package/lib/types/client/open-in-app/OpenInAppAction.d.ts +27 -0
  40. package/lib/types/client/open-in-app/OpenTargetButton.d.ts +52 -0
  41. package/lib/types/client/open-in-app/OpenTargetButton.module.css.d.ts +29 -0
  42. package/lib/types/client/open-in-app/adapter.d.ts +46 -0
  43. package/lib/types/client/open-in-app/applications.d.ts +4 -0
  44. package/lib/types/client/open-in-app/controller.d.ts +53 -0
  45. package/lib/types/client/open-in-app/locales.d.ts +10 -0
  46. package/lib/types/client/open-in-app/open-failure-toast.d.ts +11 -0
  47. package/lib/types/client/open-in-app/open-path.d.ts +13 -0
  48. package/lib/types/client/panel-client.d.ts +2 -1
  49. package/lib/types/client/styles.d.ts +1 -1
  50. package/lib/types/command.d.ts +16 -3
  51. package/lib/types/compat/client-icons.d.ts +18 -0
  52. package/lib/types/compat/dsh-version.d.ts +57 -9
  53. package/lib/types/compat/open-in-app-routes.d.ts +38 -0
  54. package/lib/types/compat/process-entrypoints.d.ts +31 -0
  55. package/lib/types/compat/process-result.d.ts +14 -0
  56. package/lib/types/compat/pty-marker.d.ts +83 -0
  57. package/lib/types/compat/sandbox-confine.d.ts +2 -0
  58. package/lib/types/compat/storage-zod.d.ts +65 -0
  59. package/lib/types/compat/windows-deny-preflight.d.ts +21 -0
  60. package/lib/types/compat/windows-native.d.ts +68 -0
  61. package/lib/types/compat/windows-path-guard.d.ts +56 -0
  62. package/lib/types/compat/workspace-files.d.ts +2 -0
  63. package/lib/types/compat.d.ts +15 -5
  64. package/lib/types/contract.d.ts +31 -19
  65. package/lib/types/dialects.d.ts +99 -3
  66. package/lib/types/fs.d.ts +32 -10
  67. package/lib/types/index.d.ts +8 -3
  68. package/lib/types/process-fence.d.ts +54 -0
  69. package/lib/types/profile-isolation.d.ts +178 -0
  70. package/lib/types/providers.d.ts +70 -0
  71. package/lib/types/registry.d.ts +132 -31
  72. package/lib/types/roots.d.ts +100 -13
  73. package/lib/types/sandbox.d.ts +59 -3
  74. package/lib/types/scope.d.ts +200 -14
  75. package/lib/types/windows-broker.d.ts +17 -0
  76. package/lib/types/windows-deny.d.ts +1 -0
  77. package/lib/types/windows-profile.d.ts +10 -13
  78. package/lib/types/windows-runner-contract.d.ts +97 -0
  79. package/lib/windows-runner-contract-CEfmZzu0.js +141 -0
  80. package/lib/windows-runner.js +1256 -13
  81. package/lib/workspace-files.js +138 -3
  82. package/lib/workspace-routing-YPxaQ4V3.js +26 -0
  83. package/package.json +84 -62
  84. package/scripts/windows-broker/install.ps1 +89 -0
  85. package/scripts/windows-broker/rights.cs +58 -0
  86. package/scripts/windows-broker/service.cs +323 -0
  87. package/scripts/windows-broker/verify-install.ps1 +80 -0
  88. package/lib/command-CTdNvwt1.js +0 -791
  89. package/lib/compat-B6ZqbQBy.js +0 -295
  90. package/lib/method-wrapper-Zc-JlDP3.js +0 -51
  91. package/lib/sandbox-BRXl_FpF.js +0 -132
  92. package/lib/types/client/RootFileTree.d.ts +0 -12
  93. package/lib/types/panel-files.d.ts +0 -3
  94. package/lib/windows-profile-CiFsFYIV.js +0 -216
  95. package/lib/{registry-lease-win32-dy8TQMD9.js → registry-lease-win32-DTO6QpT9.js} +2 -2
@@ -0,0 +1,238 @@
1
+ import { z } from "zod";
2
+ //#region src/contract.ts
3
+ /**
4
+ * The wire contract between the browser panel and this plugin's host half.
5
+ *
6
+ * It is deliberately transport-agnostic plain data: the host registers one
7
+ * Connection RPC channel (see `command.ts`) and the client bundle inlines this
8
+ * module, so both sides agree on endpoint names and payload shapes without
9
+ * sharing any runtime identity. Error codes are the stable half of the
10
+ * contract; `message` is only a fallback the panel does not have to show.
11
+ *
12
+ * Two properties this module owns:
13
+ *
14
+ * - **One shape per endpoint.** {@link PanelResponseMap} is the single mapping
15
+ * from endpoint to response type, so the panel cannot silently decode one
16
+ * endpoint's answer as another's. `reveal` answers with
17
+ * {@link RevealedView}; root-management endpoints answer with
18
+ * {@link RootsView}.
19
+ * The host builds those answers in `command.ts` and the
20
+ * panel parses them here — one definition, two consumers.
21
+ * - **Runtime validation at the boundary.** The payload arrives from a browser
22
+ * and the answer arrives from the host; neither is trusted to match the
23
+ * TypeScript types. {@link parsePanelCall} and the `parse*View` functions
24
+ * check the shapes and report structural failures as a message, so a
25
+ * mismatch becomes a visible, localized error instead of a crash or a
26
+ * silently wrong render.
27
+ *
28
+ * Nothing here may import `node:*` or `@deepseek-ai/*`: this module is inlined
29
+ * into the browser bundle.
30
+ *
31
+ * @module @dsh-electron/dsh-plugin-multi-root-workspace/contract
32
+ */
33
+ /** The absolute logical channel both halves speak over. */
34
+ const PANEL_CHANNEL = "/multi-root-workspace";
35
+ /** Every endpoint name, for exhaustive iteration in tests and callers. */
36
+ const PANEL_ENDPOINTS = [
37
+ "list",
38
+ "add",
39
+ "remove",
40
+ "alias",
41
+ "move",
42
+ "setAccess",
43
+ "reveal"
44
+ ];
45
+ /** The shared nine-cell rule; tool dispatch may subsequently narrow writes. */
46
+ function effectiveRootAccess(access, mode) {
47
+ if (access !== "inherit") return access;
48
+ return mode === "danger-full-access" ? "full-access" : mode === "workspace-write" ? "read-write" : "read-only";
49
+ }
50
+ /**
51
+ * The request body on the wire. The endpoint travels as the RPC method, not as
52
+ * a field, so this schema covers the fields only; the host pairs it with the
53
+ * method the channel dispatched (and rejects the pair if the body contradicts
54
+ * it). Unknown keys are rejected rather than ignored: a client sending a field
55
+ * this host does not understand is out of contract, and silently dropping it
56
+ * would hide the drift.
57
+ */
58
+ const panelRequestSchema = z.object({
59
+ sessionId: z.string().min(1),
60
+ entry: z.object({
61
+ ordinal: z.number().int().positive(),
62
+ id: z.string(),
63
+ path: z.string(),
64
+ addedAt: z.string()
65
+ }).strict().optional(),
66
+ id: z.string().optional(),
67
+ path: z.string().optional(),
68
+ alias: z.string().optional(),
69
+ access: z.enum([
70
+ "inherit",
71
+ "read-write",
72
+ "read-only"
73
+ ]).optional(),
74
+ beforeEntry: z.object({
75
+ ordinal: z.number().int().positive(),
76
+ id: z.string(),
77
+ path: z.string(),
78
+ addedAt: z.string()
79
+ }).strict().optional(),
80
+ beforeId: z.string().optional()
81
+ }).strict();
82
+ /**
83
+ * One root as it travels over the channel. Deliberately NOT strict, in both
84
+ * directions: a newer host that adds a field must not brick an older panel, and
85
+ * the field that matters is the state it reports.
86
+ */
87
+ const rootViewSchema = z.object({
88
+ ordinal: z.number().int().positive(),
89
+ id: z.string(),
90
+ path: z.string(),
91
+ alias: z.string().optional(),
92
+ addedAt: z.string(),
93
+ state: z.enum([
94
+ "available",
95
+ "missing",
96
+ "redirected",
97
+ "invalid"
98
+ ]),
99
+ access: z.enum([
100
+ "inherit",
101
+ "read-write",
102
+ "read-only"
103
+ ]).optional(),
104
+ detail: z.string().optional(),
105
+ effectiveAccess: z.enum([
106
+ "read-only",
107
+ "read-write",
108
+ "full-access",
109
+ "unavailable"
110
+ ]).optional()
111
+ });
112
+ const rootsViewSchema = z.object({
113
+ primaryRoot: z.string(),
114
+ primaryName: z.string().optional(),
115
+ effectiveCwd: z.string().optional(),
116
+ mode: z.enum([
117
+ "read-only",
118
+ "workspace-write",
119
+ "danger-full-access"
120
+ ]).optional(),
121
+ cappedTools: z.array(z.string()).optional(),
122
+ toolAccessInvalid: z.boolean().optional(),
123
+ roots: z.array(rootViewSchema),
124
+ limit: z.number().int().nonnegative().optional(),
125
+ count: z.number().int().nonnegative().optional(),
126
+ unavailable: z.string().optional()
127
+ });
128
+ const revealedViewSchema = z.object({ revealed: z.string() });
129
+ z.object({
130
+ code: z.string(),
131
+ message: z.string(),
132
+ details: z.unknown().optional()
133
+ });
134
+ /**
135
+ * Validate the payload the host received for one endpoint.
136
+ * @param endpoint - the endpoint the channel dispatched (the RPC method).
137
+ * @param payload - the raw channel payload (the request body).
138
+ * @returns the call the host may act on, or the reason it is not one.
139
+ */
140
+ function parsePanelCall(endpoint, payload) {
141
+ if (!PANEL_ENDPOINTS.includes(endpoint)) return {
142
+ ok: false,
143
+ message: `unknown endpoint "${endpoint}"`
144
+ };
145
+ const parsed = panelRequestSchema.safeParse(payload ?? {});
146
+ if (!parsed.success) return {
147
+ ok: false,
148
+ message: `the request body is invalid: ${firstIssue(parsed.error)}`
149
+ };
150
+ return {
151
+ ok: true,
152
+ value: narrowCall(endpoint, parsed.data)
153
+ };
154
+ }
155
+ /**
156
+ * Validate a `RootsView` when it arrives.
157
+ * @param value - the raw endpoint value.
158
+ * @returns the view, or the reason it is not one.
159
+ */
160
+ function parseRootsView(value) {
161
+ const parsed = rootsViewSchema.safeParse(value);
162
+ if (!parsed.success) return {
163
+ ok: false,
164
+ message: `the answer is not a roots view: ${firstIssue(parsed.error)}`
165
+ };
166
+ const view = parsed.data;
167
+ return {
168
+ ok: true,
169
+ value: {
170
+ primaryRoot: view.primaryRoot,
171
+ ...view.primaryName === void 0 ? {} : { primaryName: view.primaryName },
172
+ ...view.effectiveCwd === void 0 ? {} : { effectiveCwd: view.effectiveCwd },
173
+ ...view.mode === void 0 ? {} : { mode: view.mode },
174
+ ...view.cappedTools === void 0 ? {} : { cappedTools: view.cappedTools },
175
+ ...view.toolAccessInvalid === void 0 ? {} : { toolAccessInvalid: view.toolAccessInvalid },
176
+ roots: view.roots.map(narrowRootView),
177
+ limit: view.limit ?? Number.MAX_SAFE_INTEGER,
178
+ count: view.count ?? view.roots.length,
179
+ ...view.unavailable === void 0 ? {} : { unavailable: view.unavailable }
180
+ }
181
+ };
182
+ }
183
+ /**
184
+ * Validate a `RevealedView` when it arrives.
185
+ * @param value - the raw endpoint value.
186
+ * @returns the view, or the reason it is not one.
187
+ */
188
+ function parseRevealedView(value) {
189
+ const parsed = revealedViewSchema.safeParse(value);
190
+ if (!parsed.success) return {
191
+ ok: false,
192
+ message: `the answer is not a reveal result: ${firstIssue(parsed.error)}`
193
+ };
194
+ return {
195
+ ok: true,
196
+ value: parsed.data
197
+ };
198
+ }
199
+ /**
200
+ * Rebuild a parsed call as the declared type, keeping absent optional fields
201
+ * ABSENT (`exactOptionalPropertyTypes` distinguishes "absent" from "undefined",
202
+ * and the host's own code reads the two the same way the panel sent them).
203
+ */
204
+ function narrowCall(endpoint, value) {
205
+ return {
206
+ endpoint,
207
+ sessionId: value.sessionId,
208
+ ...value.entry === void 0 ? {} : { entry: value.entry },
209
+ ...value.id === void 0 ? {} : { id: value.id },
210
+ ...value.path === void 0 ? {} : { path: value.path },
211
+ ...value.alias === void 0 ? {} : { alias: value.alias },
212
+ ...value.access === void 0 ? {} : { access: value.access },
213
+ ...value.beforeEntry === void 0 ? {} : { beforeEntry: value.beforeEntry },
214
+ ...value.beforeId === void 0 ? {} : { beforeId: value.beforeId }
215
+ };
216
+ }
217
+ /** Rebuild one parsed root as the declared `RootView`. */
218
+ function narrowRootView(value) {
219
+ return {
220
+ ordinal: value.ordinal,
221
+ id: value.id,
222
+ path: value.path,
223
+ addedAt: value.addedAt,
224
+ state: value.state,
225
+ access: value.access ?? "inherit",
226
+ ...value.effectiveAccess === void 0 ? {} : { effectiveAccess: value.effectiveAccess },
227
+ ...value.alias === void 0 ? {} : { alias: value.alias },
228
+ ...value.detail === void 0 ? {} : { detail: value.detail }
229
+ };
230
+ }
231
+ /** Render the first zod issue as one short sentence. */
232
+ function firstIssue(error) {
233
+ const issue = error.issues[0];
234
+ if (issue === void 0) return "invalid";
235
+ return `${issue.path.length === 0 ? "" : `${issue.path.join(".")}: `}${issue.message}`;
236
+ }
237
+ //#endregion
238
+ export { parseRevealedView as a, parsePanelCall as i, PANEL_ENDPOINTS as n, parseRootsView as o, effectiveRootAccess as r, PANEL_CHANNEL as t };
@@ -1,3 +1,4 @@
1
+ import { brandMultiRootProvider } from "./providers.js";
1
2
  import { dirname, sep } from "node:path";
2
3
  import { writableRoots } from "@deepseek-ai/dsh-sandbox";
3
4
  import { FsError } from "@deepseek-ai/dsh-fs";
@@ -64,14 +65,11 @@ async function isPathUnder(path, root, caseSensitive = process.platform !== "win
64
65
  * roots.
65
66
  */
66
67
  var MultiRootFileSystem = class extends LocalFileSystem {
67
- static inject = [
68
- "multiRootCompat",
69
- "sandboxPolicy",
70
- "multiRootScope"
71
- ];
68
+ static inject = ["sandboxPolicy", "multiRootScope"];
72
69
  defaultMode;
73
70
  constructor(ctx, config) {
74
71
  super(ctx, config);
72
+ brandMultiRootProvider(this, "fs");
75
73
  this.defaultMode = ctx.sandboxPolicy.defaultMode;
76
74
  }
77
75
  /** The deployment default mode — the capability fact the tool layer reads to advertise escalation. */
@@ -107,47 +105,81 @@ var MultiRootFileSystem = class extends LocalFileSystem {
107
105
  return super.editText(await this.checkedTarget(target, sandboxPolicy), edit, expected, signal);
108
106
  }
109
107
  /**
110
- * The writable roots of one workspace-write call: the upstream derivation
111
- * (primary root plus the platform temp areas, canonical and deduplicated)
112
- * widened by the scope's additional roots, in scope order.
108
+ * The writable roots of one confined call: the upstream derivation (primary
109
+ * root plus the platform temp areas, canonical and deduplicated — empty
110
+ * under `read-only`) widened by the scope's EFFECTIVE writable members.
111
+ * Under `read-only` that is exactly the fixed `read-write` roots (the tool
112
+ * cap may already have emptied the scope's list), so an explicit grant
113
+ * survives a globally read-only session. An unavailable registry authority
114
+ * never contributes members: a process that cannot read the store grants
115
+ * only the primary root (and no shared temp grant).
113
116
  * @param policy - the per-call policy.
114
117
  * @param scope - the scope resolved once for this call; both the fence and
115
118
  * the denial message below share it instead of re-resolving.
116
- * @returns the canonical writable roots; empty under `read-only`.
119
+ * @returns the canonical writable roots; possibly empty.
117
120
  */
118
121
  rootsFor(policy, scope) {
122
+ if (scope.authority === "unavailable") return policy.mode === "read-only" ? [] : [scope.primaryRoot];
119
123
  const roots = writableRoots(policy);
120
- if (roots.length === 0) return roots;
121
- for (const root of scope.additionalRoots) if (!roots.includes(root)) roots.push(root);
124
+ for (const root of scope.writableRoots) if (!roots.includes(root)) roots.push(root);
122
125
  return roots;
123
126
  }
124
127
  /**
125
- * Enforce the per-call policy against `target` and return the EXACT target the
126
- * mutation must use, so the checked identity is the mutated one (no
127
- * check-here-write-there TOCTOU). `read-only` denies; `workspace-write`
128
- * re-canonicalizes NOW (reflecting a concurrently swapped symlink ancestor),
129
- * requires containment under one of the scope's writable roots, and returns
130
- * THAT fresh target; `danger-full-access` returns the caller's target unfenced.
128
+ * Enforce the per-call policy against `target` and return the EXACT target
129
+ * the mutation must use, so the checked identity is the mutated one (no
130
+ * check-here-write-there TOCTOU). Deny precedes containment: a root in
131
+ * `scope.deniedRoots` — an explicit `read-only` root, or any member when the
132
+ * call is tool-capped — refuses writes under EVERY mode, including
133
+ * `danger-full-access` and where a broader grant (the platform temp area)
134
+ * would otherwise cover the path. `read-only` then grants only the fixed
135
+ * `read-write` members; `workspace-write` requires containment under the
136
+ * widened writable set.
137
+ *
138
+ * `danger-full-access` is the only mode with a fast path, and only while
139
+ * the deny set is empty: it then returns the caller's target untouched,
140
+ * upstream-exact. Once ANY deny boundary exists the caller's `FsTarget` may
141
+ * be stale — the directory it resolved through can since have been replaced
142
+ * by a symlink into a denied root — so the fence re-resolves
143
+ * `target.displayPath`, checks the FRESH target key, and mutates that fresh
144
+ * target rather than the stale one the caller resolved earlier.
145
+ *
146
+ * One more Full-access rule: while the registry authority is `unavailable`
147
+ * the empty deny set is not trustworthy — the store this process cannot
148
+ * read may hold explicit `read-only` registrations — so the mode degrades
149
+ * to primary-root-only writes (no shared temp or additional-root grants)
150
+ * until the authority returns.
131
151
  * @param target - the resolved target about to be mutated.
132
152
  * @param sandboxPolicy - the per-call policy; omit for the deployment fallback.
133
153
  * @returns the fresh canonical target the mutation must use.
134
154
  */
135
155
  async checkedTarget(target, sandboxPolicy) {
136
156
  const policy = sandboxPolicy ?? this.ctx.sandboxPolicy.resolve();
137
- const { mode } = policy;
138
- if (mode === "danger-full-access") return target;
139
- if (mode === "read-only") throw new FsError(`cannot write "${target.displayPath}": file access denied under read-only mode`, "FS_SANDBOX_DENIED");
140
- const fresh = await this.resolve(target.displayPath);
141
157
  const scope = this.ctx.multiRootScope.resolve(policy);
142
- const roots = this.rootsFor(policy, scope);
158
+ const effectiveMode = scope.authority === "unavailable" && policy.mode === "danger-full-access" ? "workspace-write" : policy.mode;
159
+ if (effectiveMode === "danger-full-access" && scope.deniedRoots.length === 0) return target;
160
+ const fresh = await this.resolve(target.displayPath);
161
+ if (scope.deniedRoots.length > 0) {
162
+ for (const path of scope.deniedRoots) if (await isPathUnder(fresh.targetKey, path)) {
163
+ const root = scope.roots.find((root) => root.path === path);
164
+ const reason = path === scope.protectedHome ? `${path} is the DSH home directory, which is protected under danger-full-access while workspace restrictions apply` : root?.access === "read-only" || root === void 0 ? `${path} is a read-only additional root` : `${path} is an additional root this call may not write`;
165
+ throw new FsError(`cannot write "${target.displayPath}": ${reason}`, "FS_SANDBOX_DENIED");
166
+ }
167
+ }
168
+ if (effectiveMode === "danger-full-access") return fresh;
169
+ const effectivePolicy = {
170
+ ...policy,
171
+ mode: effectiveMode
172
+ };
173
+ const roots = this.rootsFor(effectivePolicy, scope);
143
174
  let contained = false;
144
175
  for (const root of roots) if (await isPathUnder(fresh.targetKey, root)) {
145
176
  contained = true;
146
177
  break;
147
178
  }
148
179
  if (!contained) {
149
- const denial = `cannot write "${target.displayPath}": file access denied under workspace-write mode`;
150
- throw new FsError(scope.additionalRoots.length === 0 ? denial : `${denial}; allowed roots: ${roots.join(", ")}`, "FS_SANDBOX_DENIED");
180
+ let denial = `cannot write "${target.displayPath}": file access denied under ${effectiveMode} mode`;
181
+ if (scope.additionalRoots.length > 0) denial += `; allowed roots: ${roots.join(", ")}`;
182
+ throw new FsError(denial, "FS_SANDBOX_DENIED");
151
183
  }
152
184
  return fresh;
153
185
  }
package/lib/fs.js CHANGED
@@ -1,2 +1,3 @@
1
- import { t as MultiRootFileSystem } from "./fs-D_Sw3o5z.js";
1
+ import "./providers.js";
2
+ import { t as MultiRootFileSystem } from "./fs-Nlp2AiRX.js";
2
3
  export { MultiRootFileSystem, MultiRootFileSystem as default };
package/lib/index.js CHANGED
@@ -1,11 +1,13 @@
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-B6ZqbQBy.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-DfzN-wVf.js";
3
- import { n as widenConfined, t as MultiRootSandboxProvider } from "./sandbox-BRXl_FpF.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";
1
+ import { _ as classifyInstallation, c as agentPtyMarkerVerdict, d as HOST_SERVICE_PACKAGES, f as OPTIONAL_CORE_PACKAGES, g as SUPPORTED_DSH_RELEASES, h as RUNTIME_OPTIONAL_PACKAGES, i as assertSupportedInstallation, l as assertAgentPtyMarker, m as RUNNER_ANCHORED_PACKAGES, n as MultiRootCompatService, o as AGENT_PTY_MARKER, p as REQUIRED_CORE_PACKAGES, s as PtyMarkerContractError, t as DshCompatUnsupportedError, u as CORE_PACKAGES, v as compatEnforcement, y as readInstalledVersion } from "./compat-DR2LvmYZ.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-D19jRxN0.js";
3
+ import { n as widenConfined, t as MultiRootSandboxProvider } from "./sandbox-CVAcT_gy.js";
4
+ import { a as classifyStoredRoots, c as indexedStatuses, i as canonicalRoot, l as isCanonicallyUnder, m as validateRootCandidate, n as additionalRootId, p as resolveRootRef, r as availableRoots, s as expandRootInput, t as RootValidationError, u as removeStatusAt } from "./roots-B-0l8mNG.js";
5
+ import { MULTI_ROOT_PROVIDER_BRAND, MultiRootProviders, brandMultiRootProvider, isMultiRootProvider } from "./providers.js";
6
+ import { t as MultiRootFileSystem } from "./fs-Nlp2AiRX.js";
7
+ import { a as parseRevealedView, i as parsePanelCall, n as PANEL_ENDPOINTS, o as parseRootsView, t as PANEL_CHANNEL } from "./contract-DZ4zczDT.js";
6
8
  import { MultiRootScopeService, renderWorkspaceRootsContext, sanitizeAdditionalRoots } from "./scope.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 parseFilesView, f as parsePanelCall, i as parseFoldersCommand, l as PANEL_ENDPOINTS, m as parseRootsView, o as resolvePanelPrimaryRoot, p as parseRevealedView, s as revealArgv, t as COMMAND_NAME, u as parseFilePreview } from "./command-CTdNvwt1.js";
9
+ import { a as MultiRootRegistry, c as multiRootDomainSpec, i as MAX_ALIAS_LENGTH, l as RegistryAuthorityLease, n as DOMAIN_NAME, o as REGISTRY_CONTENDED_MESSAGE, r as MAX_ADDITIONAL_ROOTS_CEILING, t as DEFAULT_MAX_ADDITIONAL_ROOTS, u as RegistryLeaseContendedError } from "./registry-DCxC5Lay.js";
10
+ import { a as renderRootsReport, c as revealArgv, i as parseFoldersCommand, o as resolvePanelPrimaryRoot, t as COMMAND_NAME } from "./command-CESuwlVt.js";
9
11
  //#region src/index.ts
10
12
  /**
11
13
  * Carrier plugin face for the bare-package-name loader row (see the module
@@ -16,4 +18,4 @@ import { a as renderRootsReport, c as PANEL_CHANNEL, d as parseFilesView, f as p
16
18
  const inject = [];
17
19
  function apply() {}
18
20
  //#endregion
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, parseFilePreview, parseFilesView, parseFoldersCommand, parsePanelCall, parseRevealedView, parseRootsView, readInstalledVersion, removeStatusAt, renderInstructions, renderRootsReport, renderWorkspaceRootsContext, resolvePanelPrimaryRoot, resolveRootRef, revealArgv, sanitizeAdditionalRoots, validateRootCandidate, widenConfined };
21
+ export { AGENT_PTY_MARKER, COMMAND_NAME, CORE_PACKAGES, DEFAULT_MAX_ADDITIONAL_ROOTS, DEFAULT_MAX_BYTES, DOMAIN_NAME, DshCompatUnsupportedError, HOST_SERVICE_PACKAGES, MAX_ADDITIONAL_ROOTS_CEILING, MAX_ALIAS_LENGTH, MULTI_ROOT_PROVIDER_BRAND, MultiRootCompatService, MultiRootFileSystem, MultiRootProviders, MultiRootRegistry, MultiRootSandboxProvider, MultiRootScopeService, OPTIONAL_CORE_PACKAGES, PANEL_CHANNEL, PANEL_ENDPOINTS, PLUGIN_SOURCE, PtyMarkerContractError, REGISTRY_CONTENDED_MESSAGE, REQUIRED_CORE_PACKAGES, RUNNER_ANCHORED_PACKAGES, RUNTIME_OPTIONAL_PACKAGES, RegistryAuthorityLease, RegistryLeaseContendedError, RootValidationError, SUPPORTED_DSH_RELEASES, additionalRootId, agentPtyMarkerVerdict, apply, assertAgentPtyMarker, assertSupportedInstallation, availableRoots, brandMultiRootProvider, canonicalRoot, classifyInstallation, classifyStoredRoots, compatEnforcement, composeInstructionMessage, createInstructionMessage, expandRootInput, indexedStatuses, inject, instructionsApi, isCanonicallyUnder, isMultiRootProvider, multiRootDomainSpec, parseFoldersCommand, parsePanelCall, parseRevealedView, parseRootsView, readInstalledVersion, removeStatusAt, renderInstructions, renderRootsReport, renderWorkspaceRootsContext, resolvePanelPrimaryRoot, resolveRootRef, revealArgv, sanitizeAdditionalRoots, validateRootCandidate, widenConfined };
@@ -1,11 +1,11 @@
1
1
  import { t as effectiveDirectory } from "./session-directory-BLOstut1.js";
2
2
  import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
3
- import { l as isCanonicallyUnder } from "./roots-DasWEBJk.js";
3
+ import { l as isCanonicallyUnder } from "./roots-B-0l8mNG.js";
4
4
  import { createRequire } from "node:module";
5
5
  import "@deepseek-ai/cordis";
6
+ import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
6
7
  import { createHash } from "node:crypto";
7
8
  import { AsyncLocalStorage } from "node:async_hooks";
8
- import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
9
9
  import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
10
10
  //#region src/compat/agent-instructions.ts
11
11
  /**
@@ -430,6 +430,7 @@ function composeInstructionMessage(rendered, revoked, removed) {
430
430
  /** This row is gated on the compatibility contract like every other provider. */
431
431
  const inject = [
432
432
  "multiRootCompat",
433
+ "multiRootProviders",
433
434
  "multiRootScope",
434
435
  "sandboxPolicy"
435
436
  ];
@@ -1,2 +1,2 @@
1
- import { a as composeInstructionMessage, i as apply, n as DEFAULT_MAX_SOURCE_BYTES, o as inject, r as PLUGIN_SOURCE, s as touchedPathOfToolCall, t as DEFAULT_MAX_BYTES } from "./instructions-DfzN-wVf.js";
1
+ import { a as composeInstructionMessage, i as apply, n as DEFAULT_MAX_SOURCE_BYTES, o as inject, r as PLUGIN_SOURCE, s as touchedPathOfToolCall, t as DEFAULT_MAX_BYTES } from "./instructions-D19jRxN0.js";
2
2
  export { DEFAULT_MAX_BYTES, DEFAULT_MAX_SOURCE_BYTES, PLUGIN_SOURCE, apply, composeInstructionMessage, inject, touchedPathOfToolCall };
package/lib/lsp.js CHANGED
@@ -1,8 +1,13 @@
1
1
  import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
2
- import { n as routeWorkspacePath, t as wrapMethod } from "./method-wrapper-Zc-JlDP3.js";
2
+ import { t as routeWorkspacePath } from "./workspace-routing-YPxaQ4V3.js";
3
+ import { t as wrapMethod } from "./method-wrapper-CFY3p3j2.js";
3
4
  import { AsyncLocalStorage } from "node:async_hooks";
4
5
  //#region src/lsp.ts
5
- const inject = ["multiRootCompat", "multiRootScope"];
6
+ const inject = [
7
+ "multiRootCompat",
8
+ "multiRootProviders",
9
+ "multiRootScope"
10
+ ];
6
11
  function apply(ctx) {
7
12
  const callers = new AsyncLocalStorage();
8
13
  aroundTool(ctx, (exec, next) => exec.agent === void 0 ? next() : callers.run(exec.agent.session, next));
@@ -0,0 +1,26 @@
1
+ //#region src/method-wrapper.ts
2
+ /** Wrap a public method on a Cordis service without capturing a caller-context proxy. */
3
+ function wrapMethod(target, key, wrap) {
4
+ const own = Object.getOwnPropertyDescriptor(target, key);
5
+ let prototype = target;
6
+ let descriptor;
7
+ while (prototype !== null && descriptor === void 0) {
8
+ descriptor = Object.getOwnPropertyDescriptor(prototype, key);
9
+ prototype = Object.getPrototypeOf(prototype);
10
+ }
11
+ if (typeof descriptor?.value !== "function") throw new Error(`multi-root: ${String(key)} is not a public method`);
12
+ const value = wrap(descriptor.value);
13
+ Object.defineProperty(target, key, {
14
+ configurable: true,
15
+ writable: true,
16
+ enumerable: own?.enumerable ?? false,
17
+ value
18
+ });
19
+ return () => {
20
+ if (Object.getOwnPropertyDescriptor(target, key)?.value !== value) return;
21
+ if (own === void 0) Reflect.deleteProperty(target, key);
22
+ else Object.defineProperty(target, key, own);
23
+ };
24
+ }
25
+ //#endregion
26
+ export { wrapMethod as t };