@dsh-electron/dsh-plugin-multi-root-workspace 0.1.0
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/LICENSE +21 -0
- package/README.en.md +156 -0
- package/README.md +156 -0
- package/cordis.patch.yml +44 -0
- package/lib/client.js +6512 -0
- package/lib/client.js.map +1 -0
- package/lib/command-BSkrYOAf.js +727 -0
- package/lib/command.js +2 -0
- package/lib/fs-D7UoCb7T.js +152 -0
- package/lib/fs.js +2 -0
- package/lib/index.js +17 -0
- package/lib/registry.js +466 -0
- package/lib/roots-DyT2jgEP.js +345 -0
- package/lib/sandbox-BhuMTDgH.js +243 -0
- package/lib/sandbox.js +2 -0
- package/lib/scope.js +143 -0
- package/lib/types/client/WorkspaceFoldersAction.d.ts +43 -0
- package/lib/types/client/index.d.ts +28 -0
- package/lib/types/client/locales.d.ts +118 -0
- package/lib/types/client/panel-client.d.ts +59 -0
- package/lib/types/client/styles.d.ts +14 -0
- package/lib/types/command.d.ts +66 -0
- package/lib/types/containment.d.ts +36 -0
- package/lib/types/contract.d.ts +164 -0
- package/lib/types/dialects.d.ts +92 -0
- package/lib/types/fs.d.ts +90 -0
- package/lib/types/index.d.ts +42 -0
- package/lib/types/registry.d.ts +293 -0
- package/lib/types/roots.d.ts +238 -0
- package/lib/types/sandbox.d.ts +65 -0
- package/lib/types/scope.d.ts +120 -0
- package/package.json +145 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire contract between the browser panel and this plugin's host half.
|
|
3
|
+
*
|
|
4
|
+
* It is deliberately transport-agnostic plain data: the host registers one
|
|
5
|
+
* Connection RPC channel (see `command.ts`) and the client bundle inlines this
|
|
6
|
+
* module, so both sides agree on endpoint names and payload shapes without
|
|
7
|
+
* sharing any runtime identity. Error codes are the stable half of the
|
|
8
|
+
* contract; `message` is only a fallback the panel does not have to show.
|
|
9
|
+
*
|
|
10
|
+
* Two properties this module owns:
|
|
11
|
+
*
|
|
12
|
+
* - **One shape per endpoint.** {@link PanelResponseMap} is the single mapping
|
|
13
|
+
* from endpoint to response type, so the panel cannot silently decode one
|
|
14
|
+
* endpoint's answer as another's. `reveal` answers with
|
|
15
|
+
* {@link RevealedView}; every other endpoint answers with a whole
|
|
16
|
+
* {@link RootsView}. The host builds those answers in `command.ts` and the
|
|
17
|
+
* panel parses them here — one definition, two consumers.
|
|
18
|
+
* - **Runtime validation at the boundary.** The payload arrives from a browser
|
|
19
|
+
* and the answer arrives from the host; neither is trusted to match the
|
|
20
|
+
* TypeScript types. {@link parsePanelCall} and the `parse*View` functions
|
|
21
|
+
* check the shapes and report structural failures as a message, so a
|
|
22
|
+
* mismatch becomes a visible, localized error instead of a crash or a
|
|
23
|
+
* silently wrong render.
|
|
24
|
+
*
|
|
25
|
+
* Nothing here may import `node:*` or `@deepseek-ai/*`: this module is inlined
|
|
26
|
+
* into the browser bundle.
|
|
27
|
+
*
|
|
28
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/contract
|
|
29
|
+
*/
|
|
30
|
+
/** The absolute logical channel both halves speak over. */
|
|
31
|
+
export declare const PANEL_CHANNEL = "/multi-root-workspace";
|
|
32
|
+
/** Endpoint names, relative to {@link PANEL_CHANNEL}. */
|
|
33
|
+
export type PanelEndpoint = 'list' | 'add' | 'remove' | 'alias' | 'move' | 'reveal';
|
|
34
|
+
/** Every endpoint name, for exhaustive iteration in tests and callers. */
|
|
35
|
+
export declare const PANEL_ENDPOINTS: readonly PanelEndpoint[];
|
|
36
|
+
/**
|
|
37
|
+
* How one registered root currently stands, as the panel renders it. Kept in
|
|
38
|
+
* step with the root vocabulary in `src/roots.ts` deliberately: this module is
|
|
39
|
+
* inlined into the browser bundle and must not pull in `node:*`, so the one
|
|
40
|
+
* value the two sides share is spelled out rather than imported.
|
|
41
|
+
*/
|
|
42
|
+
export type RootState = 'available' | 'missing' | 'redirected' | 'invalid';
|
|
43
|
+
/** One root as the panel renders it. */
|
|
44
|
+
export interface RootView {
|
|
45
|
+
/** 1-based position in the returned snapshot. */
|
|
46
|
+
readonly ordinal: number;
|
|
47
|
+
/** Stable identity, used by every mutating endpoint. */
|
|
48
|
+
readonly id: string;
|
|
49
|
+
/** Canonical absolute directory. */
|
|
50
|
+
readonly path: string;
|
|
51
|
+
/** Display alias as stored; absent when cleared. */
|
|
52
|
+
readonly alias?: string;
|
|
53
|
+
/** ISO-8601 registration instant. */
|
|
54
|
+
readonly addedAt: string;
|
|
55
|
+
/** Whether the directory is writable right now, withheld, or unusable. */
|
|
56
|
+
readonly state: RootState;
|
|
57
|
+
/** Why the root is not `available`; a code the panel localizes. */
|
|
58
|
+
readonly detail?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Exact identity of one row in a returned list snapshot. */
|
|
61
|
+
export interface RootEntryView {
|
|
62
|
+
readonly ordinal: number;
|
|
63
|
+
readonly id: string;
|
|
64
|
+
readonly path: string;
|
|
65
|
+
readonly addedAt: string;
|
|
66
|
+
}
|
|
67
|
+
/** The panel's whole view of one workspace root; every endpoint but `reveal` answers with this. */
|
|
68
|
+
export interface RootsView {
|
|
69
|
+
/** The canonical workspace root these registrations belong to. */
|
|
70
|
+
readonly primaryRoot: string;
|
|
71
|
+
/**
|
|
72
|
+
* Display name of the primary root: the workspace's upstream title when the
|
|
73
|
+
* host could resolve one; absent means the panel falls back to the path's
|
|
74
|
+
* basename.
|
|
75
|
+
*/
|
|
76
|
+
readonly primaryName?: string;
|
|
77
|
+
/** The additional roots, in registry order. */
|
|
78
|
+
readonly roots: readonly RootView[];
|
|
79
|
+
/** Set when the store itself could not be read; the panel shows this verbatim. */
|
|
80
|
+
readonly unavailable?: string;
|
|
81
|
+
}
|
|
82
|
+
/** What `reveal` answers with: the directory the host asked the file manager to show. */
|
|
83
|
+
export interface RevealedView {
|
|
84
|
+
/** Canonical path of the revealed root. */
|
|
85
|
+
readonly revealed: string;
|
|
86
|
+
}
|
|
87
|
+
/** The response type of every endpoint — the mapping the panel is typed against. */
|
|
88
|
+
export interface PanelResponseMap {
|
|
89
|
+
readonly list: RootsView;
|
|
90
|
+
readonly add: RootsView;
|
|
91
|
+
readonly remove: RootsView;
|
|
92
|
+
readonly alias: RootsView;
|
|
93
|
+
readonly move: RootsView;
|
|
94
|
+
readonly reveal: RevealedView;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The fields a request may carry. `primaryRoot` and `sessionId` are shared by
|
|
98
|
+
* every endpoint (a client may name the workspace root directly or let the host
|
|
99
|
+
* resolve it from the session); the remaining fields are used per endpoint and
|
|
100
|
+
* the host asserts which ones that endpoint requires.
|
|
101
|
+
*/
|
|
102
|
+
export interface PanelRequest {
|
|
103
|
+
/** The workspace root to act on; the host validates that it is an existing directory. */
|
|
104
|
+
readonly primaryRoot?: string;
|
|
105
|
+
/** The session whose workspace root should be used when `primaryRoot` is absent. */
|
|
106
|
+
readonly sessionId?: string;
|
|
107
|
+
/** Exact target row from the most recent list snapshot. */
|
|
108
|
+
readonly entry?: RootEntryView;
|
|
109
|
+
/** Compatibility reference; accepted only when the id is unique. */
|
|
110
|
+
readonly id?: string;
|
|
111
|
+
/** Candidate directory (add). */
|
|
112
|
+
readonly path?: string;
|
|
113
|
+
/** Display alias (add/alias); empty clears it. */
|
|
114
|
+
readonly alias?: string;
|
|
115
|
+
/** Exact anchor row (move): the target is placed in front of it; absent moves it last. */
|
|
116
|
+
readonly beforeEntry?: RootEntryView;
|
|
117
|
+
/** Compatibility anchor; accepted only when the id is unique. */
|
|
118
|
+
readonly beforeId?: string;
|
|
119
|
+
}
|
|
120
|
+
/** One validated call: the endpoint plus the request fields it may use. */
|
|
121
|
+
export interface PanelCall extends PanelRequest {
|
|
122
|
+
/** The endpoint to call. */
|
|
123
|
+
readonly endpoint: PanelEndpoint;
|
|
124
|
+
}
|
|
125
|
+
/** A failure the panel renders by `code`. */
|
|
126
|
+
export interface PanelFailure {
|
|
127
|
+
/** Stable code from the root vocabulary, or `panel/bad-request`. */
|
|
128
|
+
readonly code: string;
|
|
129
|
+
/** Human-readable fallback text. */
|
|
130
|
+
readonly message: string;
|
|
131
|
+
}
|
|
132
|
+
/** One parse result: the value, or one sentence naming what was wrong. */
|
|
133
|
+
export type Parsed<T> = {
|
|
134
|
+
readonly ok: true;
|
|
135
|
+
readonly value: T;
|
|
136
|
+
} | {
|
|
137
|
+
readonly ok: false;
|
|
138
|
+
readonly message: string;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Validate the payload the host received for one endpoint.
|
|
142
|
+
* @param endpoint - the endpoint the channel dispatched (the RPC method).
|
|
143
|
+
* @param payload - the raw channel payload (the request body).
|
|
144
|
+
* @returns the call the host may act on, or the reason it is not one.
|
|
145
|
+
*/
|
|
146
|
+
export declare function parsePanelCall(endpoint: string, payload: unknown): Parsed<PanelCall>;
|
|
147
|
+
/**
|
|
148
|
+
* Validate a `RootsView` when it arrives.
|
|
149
|
+
* @param value - the raw endpoint value.
|
|
150
|
+
* @returns the view, or the reason it is not one.
|
|
151
|
+
*/
|
|
152
|
+
export declare function parseRootsView(value: unknown): Parsed<RootsView>;
|
|
153
|
+
/**
|
|
154
|
+
* Validate a `RevealedView` when it arrives.
|
|
155
|
+
* @param value - the raw endpoint value.
|
|
156
|
+
* @returns the view, or the reason it is not one.
|
|
157
|
+
*/
|
|
158
|
+
export declare function parseRevealedView(value: unknown): Parsed<RevealedView>;
|
|
159
|
+
/**
|
|
160
|
+
* Validate the `{ code, message }` envelope of a failed call.
|
|
161
|
+
* @param value - the raw error value.
|
|
162
|
+
* @returns the failure, or `undefined` when the value is not one.
|
|
163
|
+
*/
|
|
164
|
+
export declare function parseErrorView(value: unknown): PanelFailure | undefined;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dialect adaptation: widening a confined argv with additional workspace roots.
|
|
3
|
+
*
|
|
4
|
+
* The upstream kernel-sandbox provider expresses `workspace-write` as a
|
|
5
|
+
* per-dialect profile built from the SINGLE policy root (plus the platform temp
|
|
6
|
+
* areas). Widening that profile is the one thing this plugin must do outside the
|
|
7
|
+
* filesystem fence, and it is deliberately done by OBSERVATION: the upstream
|
|
8
|
+
* dialect profile builders are unreachable in the published package (only
|
|
9
|
+
* `lib/index.js` and `lib/types/**` ship — see ADR-0002), and
|
|
10
|
+
* `@deepseek-ai/dsh-sandbox-local`'s `runnerArgv` / `landlockLauncher` /
|
|
11
|
+
* `seatbeltExec` members are TS-private, so `confine()` and the `internals` test
|
|
12
|
+
* hook are the ONLY public surface.
|
|
13
|
+
*
|
|
14
|
+
* Every dialect is therefore handled by
|
|
15
|
+
* 1. splitting the wrapped argv at the separator `confine` itself inserted,
|
|
16
|
+
* 2. recognizing the dialect from STRUCTURAL markers in the profile arguments,
|
|
17
|
+
* 3. cloning the grant spelling — and the insertion point — from the arguments
|
|
18
|
+
* the upstream provider actually produced, and
|
|
19
|
+
* 4. failing loudly (never silently confining to the primary root alone) when
|
|
20
|
+
* the shape is not one this module knows.
|
|
21
|
+
*
|
|
22
|
+
* The per-dialect profile shapes this recognizes (verified against dsh
|
|
23
|
+
* `0.1.5-rc.2`, recorded in `docs/reference/multi-root-workspace-research.md`
|
|
24
|
+
* §10) are:
|
|
25
|
+
*
|
|
26
|
+
* ```text
|
|
27
|
+
* seatbelt [sandbox-exec, -p, "<SBPL>" ] SBPL allow-forms
|
|
28
|
+
* bwrap [bwrap, --ro-bind / /, …, --bind <root> <root>]
|
|
29
|
+
* landlock [<launcher>, --ro /, --rw /dev/null, --rw <root>]
|
|
30
|
+
* windows-acl [node, <runner>, --workspace …, --mode <mode>]
|
|
31
|
+
* runnerCommand is spelled exactly like bwrap (the upstream config contract
|
|
32
|
+
* appends bwrap-compatible profile arguments to the operator's runner).
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/dialects
|
|
36
|
+
*/
|
|
37
|
+
import type { SandboxPolicy } from '@deepseek-ai/dsh-sandbox';
|
|
38
|
+
/** The kernel runner dialects a confined argv can speak. */
|
|
39
|
+
export type RunnerDialect = 'seatbelt' | 'bwrap' | 'landlock' | 'windows-acl';
|
|
40
|
+
/**
|
|
41
|
+
* Raised when a confined argv cannot be recognized or widened. The provider
|
|
42
|
+
* converts this into the fail-closed `SandboxUnavailableError`: an unrecognized
|
|
43
|
+
* dialect must never degrade into "the primary root was granted after all".
|
|
44
|
+
*/
|
|
45
|
+
export declare class DialectUnrecognizedError extends Error {
|
|
46
|
+
constructor(message: string);
|
|
47
|
+
}
|
|
48
|
+
/** One wrapped argv split into its runner/profile part and the caller's argv. */
|
|
49
|
+
export interface ConfinedShape {
|
|
50
|
+
/** The recognized dialect. */
|
|
51
|
+
dialect: RunnerDialect;
|
|
52
|
+
/** Everything before the separator: runner program plus profile arguments. */
|
|
53
|
+
profileArgs: string[];
|
|
54
|
+
/** Index of the `--` separator `confine` inserted. */
|
|
55
|
+
separator: number;
|
|
56
|
+
/** The caller's argv, verbatim, after the separator. */
|
|
57
|
+
commandArgs: string[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Split a `confine()` result at the separator by arithmetic, then VERIFY the
|
|
61
|
+
* split: `confine` builds `[...profileArgs, '--', ...argv]`, so the separator
|
|
62
|
+
* sits exactly one element before the caller's argv. A mismatch means the
|
|
63
|
+
* provider no longer wraps argv the way this module assumes.
|
|
64
|
+
* @param confinedArgv - the argv `confine` returned.
|
|
65
|
+
* @param commandArgv - the argv the caller passed to `confine`.
|
|
66
|
+
* @returns the recognized dialect and the split parts.
|
|
67
|
+
*/
|
|
68
|
+
export declare function splitConfined(confinedArgv: readonly string[], commandArgv: readonly string[]): ConfinedShape;
|
|
69
|
+
/**
|
|
70
|
+
* Recognize the runner dialect from the profile arguments alone. Exactly one
|
|
71
|
+
* marker must match; zero or several are both unrecognized.
|
|
72
|
+
* @param profileArgs - everything before the separator.
|
|
73
|
+
* @returns the dialect.
|
|
74
|
+
*/
|
|
75
|
+
export declare function detectDialect(profileArgs: readonly string[]): RunnerDialect;
|
|
76
|
+
/**
|
|
77
|
+
* Widen one dialect's profile arguments with the additional roots.
|
|
78
|
+
*
|
|
79
|
+
* Only `workspace-write` grants roots, mirroring the upstream mode meaning and
|
|
80
|
+
* the filesystem fence: `read-only` grants nothing, and `danger-full-access`
|
|
81
|
+
* never confines at all (bash and the PTY backend skip `confine` in that mode).
|
|
82
|
+
*
|
|
83
|
+
* A root the dialect ALREADY grants is not granted twice — that keeps this
|
|
84
|
+
* function aligned with the fence's own deduplication and, on bwrap, avoids
|
|
85
|
+
* binding the real `/tmp` over the ephemeral `--tmpfs /tmp` mount.
|
|
86
|
+
* @param dialect - the recognized dialect.
|
|
87
|
+
* @param profileArgs - the profile arguments to widen.
|
|
88
|
+
* @param policy - the per-call policy (its root is the policy root, never a new grant).
|
|
89
|
+
* @param additionalRoots - canonical additional roots, in scope order.
|
|
90
|
+
* @returns the widened profile arguments.
|
|
91
|
+
*/
|
|
92
|
+
export declare function widenProfileArgs(dialect: RunnerDialect, profileArgs: readonly string[], policy: SandboxPolicy, additionalRoots: readonly string[]): string[];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `MultiRootFileSystem`: the multi-root filesystem provider mounted as `ctx.fs`.
|
|
3
|
+
*
|
|
4
|
+
* It extends the local backend so every text-storage mechanic — resolve, stat,
|
|
5
|
+
* read/stream, listing, the atomic write and the read-match-write edit critical
|
|
6
|
+
* section — stays the upstream implementation's, verbatim; this class adds only
|
|
7
|
+
* the per-call POLICY fence on the two mutations, exactly as the upstream
|
|
8
|
+
* `SandboxedFileSystem` does, widened from one workspace root to the scope's
|
|
9
|
+
* root set.
|
|
10
|
+
*
|
|
11
|
+
* Why not `extends SandboxedFileSystem`: its `checkedTarget` is TS-private, so a
|
|
12
|
+
* cross-package subclass can neither reuse nor override it in a type-safe way.
|
|
13
|
+
* Why the fence is implemented here rather than delegated: with zero additional
|
|
14
|
+
* roots this class must behave exactly like the upstream provider, and the
|
|
15
|
+
* differential suite in `tests/fs-parity.spec.ts` pins that equality against the
|
|
16
|
+
* real upstream class for every mode and path class.
|
|
17
|
+
*
|
|
18
|
+
* Reads are untouched: no mode confines reading, upstream or here.
|
|
19
|
+
*
|
|
20
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/fs
|
|
21
|
+
*/
|
|
22
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
23
|
+
import type { FsEditOutcome, FsEditRequest, FsTarget, FsVersion, FsWriteIntent, FsWriteOutcome } from '@deepseek-ai/dsh-fs';
|
|
24
|
+
import { LocalFileSystem } from '@deepseek-ai/dsh-fs-local';
|
|
25
|
+
import type { Config as LocalConfig } from '@deepseek-ai/dsh-fs-local';
|
|
26
|
+
import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox';
|
|
27
|
+
/** Plugin config: the local backend's knobs verbatim (see `dsh-fs-local`). */
|
|
28
|
+
export type Config = LocalConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Sandbox-enforcing filesystem backend over the multi-root scope. Registers as
|
|
31
|
+
* `ctx.fs`; `ctx.sandboxPolicy` still owns the mode and the primary root, and
|
|
32
|
+
* this class only widens the writable root set with the scope's additional
|
|
33
|
+
* roots.
|
|
34
|
+
*/
|
|
35
|
+
export declare class MultiRootFileSystem extends LocalFileSystem {
|
|
36
|
+
static inject: string[];
|
|
37
|
+
private readonly defaultMode;
|
|
38
|
+
constructor(ctx: Context, config: Config);
|
|
39
|
+
/** The deployment default mode — the capability fact the tool layer reads to advertise escalation. */
|
|
40
|
+
get sandboxMode(): SandboxMode;
|
|
41
|
+
/**
|
|
42
|
+
* Fence the write by the per-call policy, then delegate to the inherited
|
|
43
|
+
* atomic write.
|
|
44
|
+
* @param target - the resolved target to write.
|
|
45
|
+
* @param content - the full new file content.
|
|
46
|
+
* @param expected - the write intent guarding the write; omit for unconditional.
|
|
47
|
+
* @param signal - aborts before atomic publication takes effect.
|
|
48
|
+
* @param sandboxPolicy - the per-call mode and workspace root; omit to use
|
|
49
|
+
* the deployment fallback.
|
|
50
|
+
* @returns the write outcome from the inherited backend.
|
|
51
|
+
*/
|
|
52
|
+
writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsWriteOutcome>;
|
|
53
|
+
/**
|
|
54
|
+
* Fence the edit by the per-call policy, then delegate to the inherited
|
|
55
|
+
* atomic edit.
|
|
56
|
+
* @param target - the resolved target to edit.
|
|
57
|
+
* @param edit - the literal search/replace request.
|
|
58
|
+
* @param expected - the version guard; omit for an unconditional edit.
|
|
59
|
+
* @param signal - aborts before atomic publication takes effect.
|
|
60
|
+
* @param sandboxPolicy - the per-call mode and workspace root; omit to use
|
|
61
|
+
* the deployment fallback.
|
|
62
|
+
* @returns the edit outcome from the inherited backend.
|
|
63
|
+
*/
|
|
64
|
+
editText(target: FsTarget, edit: FsEditRequest, expected?: {
|
|
65
|
+
version: FsVersion;
|
|
66
|
+
}, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsEditOutcome>;
|
|
67
|
+
/**
|
|
68
|
+
* The writable roots of one workspace-write call: the upstream derivation
|
|
69
|
+
* (primary root plus the platform temp areas, canonical and deduplicated)
|
|
70
|
+
* widened by the scope's additional roots, in scope order.
|
|
71
|
+
* @param policy - the per-call policy.
|
|
72
|
+
* @param scope - the scope resolved once for this call; both the fence and
|
|
73
|
+
* the denial message below share it instead of re-resolving.
|
|
74
|
+
* @returns the canonical writable roots; empty under `read-only`.
|
|
75
|
+
*/
|
|
76
|
+
private rootsFor;
|
|
77
|
+
/**
|
|
78
|
+
* Enforce the per-call policy against `target` and return the EXACT target the
|
|
79
|
+
* mutation must use, so the checked identity is the mutated one (no
|
|
80
|
+
* check-here-write-there TOCTOU). `read-only` denies; `workspace-write`
|
|
81
|
+
* re-canonicalizes NOW (reflecting a concurrently swapped symlink ancestor),
|
|
82
|
+
* requires containment under one of the scope's writable roots, and returns
|
|
83
|
+
* THAT fresh target; `danger-full-access` returns the caller's target unfenced.
|
|
84
|
+
* @param target - the resolved target about to be mutated.
|
|
85
|
+
* @param sandboxPolicy - the per-call policy; omit for the deployment fallback.
|
|
86
|
+
* @returns the fresh canonical target the mutation must use.
|
|
87
|
+
*/
|
|
88
|
+
private checkedTarget;
|
|
89
|
+
}
|
|
90
|
+
export default MultiRootFileSystem;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Barrel for the multi-root workspace bundle's host half.
|
|
3
|
+
*
|
|
4
|
+
* The loader mounts the plugin's responsibilities through the subpath entries
|
|
5
|
+
* declared in `package.json` and `cordis.patch.yml` (`./fs`, `./sandbox`,
|
|
6
|
+
* `./scope`, `./registry`, `./command`); this entry carries only the no-op
|
|
7
|
+
* `apply` below. The patch still inserts a row with THIS specifier (the bare
|
|
8
|
+
* package name) because the web client-module scan reads a package's
|
|
9
|
+
* `dsh.client` declaration solely from a loader row mounted at its package
|
|
10
|
+
* root — subpath rows are never client rows — so without that row the browser
|
|
11
|
+
* is never served `lib/client.js` and the sidebar footer action never
|
|
12
|
+
* registers. The barrel itself stays side-effect free so tests can import the
|
|
13
|
+
* whole public surface from a single specifier.
|
|
14
|
+
*
|
|
15
|
+
* The two facts worth remembering about this surface: a registration carries the
|
|
16
|
+
* canonical directory it was GRANTED for (`recordedPath`), and the panel channel
|
|
17
|
+
* has one declared response shape per endpoint (`PanelResponseMap`).
|
|
18
|
+
*
|
|
19
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace
|
|
20
|
+
*/
|
|
21
|
+
export { MultiRootFileSystem } from './fs.ts';
|
|
22
|
+
export type { Config as FileSystemConfig } from './fs.ts';
|
|
23
|
+
export { MultiRootSandboxProvider } from './sandbox.ts';
|
|
24
|
+
export type { Config as SandboxConfig } from './sandbox.ts';
|
|
25
|
+
export { MultiRootScopeService, sanitizeAdditionalRoots, renderWorkspaceRootsContext } from './scope.ts';
|
|
26
|
+
export type { AdditionalWorkspaceRoot, FilesystemScope } from './scope.ts';
|
|
27
|
+
export { MultiRootRegistry, DOMAIN_NAME, MAX_ALIAS_LENGTH, multiRootDomainSpec } from './registry.ts';
|
|
28
|
+
export type { AddRootInput, PersistedPrimaryRoot } from './registry.ts';
|
|
29
|
+
export { availableRoots, canonicalRoot, classifyStoredRoots, expandRootInput, indexedStatuses, isCanonicallyUnder, additionalRootId, removeStatusAt, resolveRootRef, RootValidationError, validateRootCandidate, } from './roots.ts';
|
|
30
|
+
export type { AdditionalRootId, RegisteredRoot, RootRef, RootState, RootStatus, RootValidationCode, } from './roots.ts';
|
|
31
|
+
export { COMMAND_NAME, parseFoldersCommand, renderRootsReport, revealArgv } from './command.ts';
|
|
32
|
+
export type { FoldersCommand } from './command.ts';
|
|
33
|
+
export { PANEL_CHANNEL, PANEL_ENDPOINTS, parsePanelCall, parseRevealedView, parseRootsView } from './contract.ts';
|
|
34
|
+
export type { PanelCall, PanelEndpoint, PanelFailure, PanelRequest, PanelResponseMap, RevealedView, RootView, RootsView, } from './contract.ts';
|
|
35
|
+
/**
|
|
36
|
+
* Carrier plugin face for the bare-package-name loader row (see the module
|
|
37
|
+
* doc). It deliberately provides nothing: every host responsibility is owned
|
|
38
|
+
* by a subpath entry, and this row exists only so the web client-module scan
|
|
39
|
+
* can locate the package root and read its `dsh.client` declaration.
|
|
40
|
+
*/
|
|
41
|
+
export declare const inject: string[];
|
|
42
|
+
export declare function apply(): void;
|