@dsh-electron/dsh-plugin-multi-root-workspace 0.1.15 → 0.1.16
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/CHANGELOG.en.md +13 -1
- package/CHANGELOG.md +13 -1
- package/README.en.md +6 -6
- package/README.md +6 -6
- package/lib/auto-review.js +1 -1
- package/lib/client.js +761 -74
- package/lib/client.js.map +1 -1
- package/lib/{command-y5tfcAeC.js → command-DaVJ-mK3.js} +55 -1
- package/lib/command.js +1 -1
- package/lib/index.js +4 -4
- package/lib/{instructions-Ck9wp4J4.js → instructions-Ca80SkZq.js} +1 -1
- package/lib/instructions.js +1 -1
- package/lib/lsp.js +1 -1
- package/lib/process-fence.js +95 -12
- package/lib/{registry-DyDNDSJZ.js → registry-BibiukWk.js} +1 -1
- package/lib/{registry-operation-C2ZV3Jhw.js → registry-operation-CIlmt6_c.js} +5 -1
- package/lib/registry.js +1 -1
- package/lib/{review-context-B-oHkU6a.js → review-context-OxO-fMWR.js} +1 -1
- package/lib/review-context.js +1 -1
- package/lib/{sandbox-CZElTNPz.js → sandbox-aobdyQGi.js} +6 -3
- package/lib/sandbox.js +1 -1
- package/lib/scope.js +91 -4
- package/lib/skills.js +1 -1
- package/lib/types/client/files-tree/FilesTree.d.ts +49 -6
- package/lib/types/client/files-tree/adapter.d.ts +69 -16
- package/lib/types/client/files-tree/face.d.ts +31 -2
- package/lib/types/client/files-tree/locate.d.ts +74 -0
- package/lib/types/client/files-tree/navigator.d.ts +98 -0
- package/lib/types/client/index.d.ts +7 -0
- package/lib/types/client/locales.d.ts +2 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/compat/files-tree.d.ts +8 -1
- package/lib/types/compat/forge-entrypoints.d.ts +44 -0
- package/lib/types/compat/session-existence.d.ts +41 -0
- package/lib/types/registry-operation.d.ts +7 -0
- package/lib/types/roots.d.ts +3 -1
- package/lib/types/scope.d.ts +67 -1
- package/lib/workspace-files.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility adapter: which foreign-service entries the process fence can
|
|
3
|
+
* admit.
|
|
4
|
+
*
|
|
5
|
+
* The upstream experimental forge bundle composes `ctx.sandbox.confine` +
|
|
6
|
+
* `ctx.subprocess.spawn` on its own code paths — the panel's Git reads and the
|
|
7
|
+
* worktree service's creation/restore commands — bypassing every wrapped
|
|
8
|
+
* executor seam the admission already reaches. The fence therefore wraps each
|
|
9
|
+
* reachable async public entry with an ordered admission of its own. Which
|
|
10
|
+
* services and keys exist is a per-release shape: the verified baseline here
|
|
11
|
+
* is `@deepseek-ai/dsh-experimental-forge-bundle@0.2.2-rc.1` (which pins
|
|
12
|
+
* `dsh-experimental-worktree` and `dsh-experimental-client-ui-forge` at the
|
|
13
|
+
* same version), and the `follow`/`changeRequestStates` async generators are
|
|
14
|
+
* deliberately absent — a generator cannot hold a synchronous admission, so
|
|
15
|
+
* its detached work falls back to the minted-profile ledger.
|
|
16
|
+
*
|
|
17
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/compat/forge-entrypoints
|
|
18
|
+
*/
|
|
19
|
+
import type { Session } from '@deepseek-ai/dsh-session';
|
|
20
|
+
/** One foreign service whose public entries spawn confined processes. */
|
|
21
|
+
export interface ForeignProcessService {
|
|
22
|
+
readonly service: string;
|
|
23
|
+
readonly keys: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The forge-bundle service entries an admission can wrap, in this order.
|
|
27
|
+
* `worktrees.create`/`restore` take an `Agent` (the session rides on
|
|
28
|
+
* `agent.session`); every listed `forgePanel` entry takes the `Session` as
|
|
29
|
+
* its first argument. Entries not listed — background inspections, the
|
|
30
|
+
* isolated `forge-worktree` instance inside the panel's mount group — stay
|
|
31
|
+
* ledger-covered.
|
|
32
|
+
*/
|
|
33
|
+
export declare const FORGE_PROCESS_SERVICES: readonly ForeignProcessService[];
|
|
34
|
+
/**
|
|
35
|
+
* Read the session a foreign-service entry resolves its policy from — the
|
|
36
|
+
* first argument alone: a `Session`, or an `Agent`-shaped value carrying one.
|
|
37
|
+
* The probe is deliberately structural and narrow (`id` + `header`): it is a
|
|
38
|
+
* trust boundary over the upstream type, not a full validation — anything
|
|
39
|
+
* else runs unadmitted rather than let `sandboxPolicy.resolve` read fields a
|
|
40
|
+
* foreign argument lacks.
|
|
41
|
+
* @param first - the wrapped call's first argument.
|
|
42
|
+
* @returns the session, or `undefined` for a call that does not carry one.
|
|
43
|
+
*/
|
|
44
|
+
export declare function sessionOf(first: unknown): Session | undefined;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility adapter for "does this session exist in durable storage".
|
|
3
|
+
*
|
|
4
|
+
* The panel session anchor (ADR-0008) is a live Session in this process's
|
|
5
|
+
* `SessionStore`. A persisted session owned by another Host — or one still
|
|
6
|
+
* mid-resume — never enters that store, so `resolvePanelPrimaryRoot` and the
|
|
7
|
+
* `rootsViewOf` re-check both answer `session-not-found`. That code is true
|
|
8
|
+
* but diagnostically wrong when the session exists: the panel copy asked the
|
|
9
|
+
* user to open a session already on screen.
|
|
10
|
+
*
|
|
11
|
+
* `sessionPersistence.stat(id)` is the cheapest probe of the durable fact:
|
|
12
|
+
* it reads only the session header — never the event log, never the
|
|
13
|
+
* cross-process write lease — and reports `undefined` for an absent id.
|
|
14
|
+
* This module isolates the probe because the fact's meaning differs by
|
|
15
|
+
* outcome:
|
|
16
|
+
*
|
|
17
|
+
* - snapshot returned → the session exists (writer-held elsewhere, still
|
|
18
|
+
* resuming, or needing a format migration — `stat` reports the header in
|
|
19
|
+
* every one of those states): reclassify as `session-not-live`;
|
|
20
|
+
* - `undefined` → the session does not exist in this backend: keep
|
|
21
|
+
* `session-not-found`;
|
|
22
|
+
* - service or `stat` absent (a composition without persistence, or a
|
|
23
|
+
* runtime whose backend does not name it) → `false`: the probe cannot
|
|
24
|
+
* prove existence, so the caller keeps the code it already had;
|
|
25
|
+
* - `stat` throws → `false`, same conservatism. One imprecision survives:
|
|
26
|
+
* a session that exists but whose header cannot be read (corrupt durable
|
|
27
|
+
* state, a broken backend) is reported as not-found rather than not-live —
|
|
28
|
+
* identical to the pre-probe behavior, and preferable to claiming
|
|
29
|
+
* existence the probe failed to prove.
|
|
30
|
+
*
|
|
31
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/compat/session-existence
|
|
32
|
+
*/
|
|
33
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
34
|
+
/**
|
|
35
|
+
* Whether `sessionId` exists in the mounted persistence backend.
|
|
36
|
+
* @param ctx - the plugin fiber context; optional services read via `ctx.get`.
|
|
37
|
+
* @param sessionId - the panel request's session id.
|
|
38
|
+
* @param signal - the request's cancellation, forwarded when the backend takes options.
|
|
39
|
+
* @returns `true` only when a snapshot proves the session exists.
|
|
40
|
+
*/
|
|
41
|
+
export declare function persistedSessionExists(ctx: Context, sessionId: string, signal?: AbortSignal): Promise<boolean>;
|
|
@@ -2,6 +2,13 @@ import type { SandboxMode } from '@deepseek-ai/dsh-sandbox';
|
|
|
2
2
|
import type { FilesystemScope } from './scope.ts';
|
|
3
3
|
export type RegistryOperationKind = 'fs-write' | 'fs-edit' | 'process' | 'pty' | 'lsp' | 'files' | 'instructions' | 'skills';
|
|
4
4
|
export declare function currentRegistryOperation(proof: object): RegistryOperation | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* The enclosing admission frame's mint disposition for this proof. `expired`
|
|
7
|
+
* frames still occupy the async context of their descendants; an expired
|
|
8
|
+
* admission must never bequeath a launchable profile.
|
|
9
|
+
*/
|
|
10
|
+
export type OperationFrameState = 'active' | 'expired' | 'absent';
|
|
11
|
+
export declare function operationFrameState(proof: object): OperationFrameState;
|
|
5
12
|
export interface RegistryOperationIdentity {
|
|
6
13
|
readonly operationId: string;
|
|
7
14
|
readonly kind: RegistryOperationKind;
|
package/lib/types/roots.d.ts
CHANGED
|
@@ -202,7 +202,9 @@ export type RootRef = {
|
|
|
202
202
|
readonly addedAt: string;
|
|
203
203
|
};
|
|
204
204
|
/** Every way root handling can fail, as a stable code the surfaces localize. */
|
|
205
|
-
export type RootValidationCode = 'not-absolute' | 'missing' | 'not-a-directory' | 'equals-primary' | 'primary-overlap' | 'duplicate' | 'nested' | 'invalid-alias' | 'invalid-alias-id' | 'not-found' | 'invalid-ref' | 'storage-unavailable' | 'registry-contended' | 'root-limit-reached' | 'config-invalid' | 'reveal-unavailable' | 'session-not-found'
|
|
205
|
+
export type RootValidationCode = 'not-absolute' | 'missing' | 'not-a-directory' | 'equals-primary' | 'primary-overlap' | 'duplicate' | 'nested' | 'invalid-alias' | 'invalid-alias-id' | 'not-found' | 'invalid-ref' | 'storage-unavailable' | 'registry-contended' | 'root-limit-reached' | 'config-invalid' | 'reveal-unavailable' | 'session-not-found'
|
|
206
|
+
/** Synthesized at the panel dispatch catch — the session existed but could not resolve a root during the request (writer-held, mid-resume, or a race resolved after the throw); no RootValidationError is constructed with it. */
|
|
207
|
+
| 'session-not-live' | 'unsupported-path' | 'root-unavailable' | 'protected-path' | 'protected-boundary-unknown' | 'revive-target-changed';
|
|
206
208
|
/** A rejected root operation; `code` is the stable contract, `message` the fallback prose. */
|
|
207
209
|
export declare class RootValidationError extends Error {
|
|
208
210
|
readonly code: RootValidationCode;
|
package/lib/types/scope.d.ts
CHANGED
|
@@ -200,6 +200,24 @@ export interface Config {
|
|
|
200
200
|
*/
|
|
201
201
|
readonly dshHome?: string;
|
|
202
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* The baseline a mint resolved to. Only primary-bounded forms may join the
|
|
205
|
+
* unadmitted ledger: `clamped` (primary-root clamp) and `read-only` (the
|
|
206
|
+
* upstream read-only skeleton — never writable). `ambient` mints —
|
|
207
|
+
* `restrictedExecution`'s ambient-minus-denies profile, and any mint whose
|
|
208
|
+
* scope could not be proven unavailable — may only live bound to an
|
|
209
|
+
* admission frame, and otherwise die.
|
|
210
|
+
*/
|
|
211
|
+
export type MintForm = 'clamped' | 'read-only' | 'ambient';
|
|
212
|
+
/** The authorization basis a mint carried at its synchronous entry, stamped onto its ledger entry. */
|
|
213
|
+
export interface MintStamp {
|
|
214
|
+
/** Publication generation the mint's authorization snapshot was resolved under. */
|
|
215
|
+
readonly version: number;
|
|
216
|
+
/** Tool-cap basis at the same instant. */
|
|
217
|
+
readonly capped: boolean;
|
|
218
|
+
/** The profile form the mint produced; gates ledger admission. */
|
|
219
|
+
readonly form: MintForm;
|
|
220
|
+
}
|
|
203
221
|
/**
|
|
204
222
|
* The `ctx.multiRootScope` service. Providers ask it — never the filesystem —
|
|
205
223
|
* what the current scope is, which is what keeps the fs fence and every kernel
|
|
@@ -215,6 +233,14 @@ export declare class MultiRootScopeService extends Service {
|
|
|
215
233
|
/** True when a batched write coalesced its notification into the flush. */
|
|
216
234
|
private batchDirty;
|
|
217
235
|
private admissionProof;
|
|
236
|
+
/**
|
|
237
|
+
* The publication generation the mint ledger is keyed on: bumped when a
|
|
238
|
+
* root-table write or an authority transition changes the authorization
|
|
239
|
+
* basis (a repeat publish of identical content is not a publication), so a
|
|
240
|
+
* minted profile dies with the state it was computed from.
|
|
241
|
+
*/
|
|
242
|
+
private publicationVersion;
|
|
243
|
+
private mintedProfiles;
|
|
218
244
|
/**
|
|
219
245
|
* The registry-authority fact the registry row publishes. Defaults to
|
|
220
246
|
* `available`: a composition without a registry row can never have
|
|
@@ -258,6 +284,8 @@ export declare class MultiRootScopeService extends Service {
|
|
|
258
284
|
batch<T>(body: () => T): T;
|
|
259
285
|
/** Notify subscribers now, or coalesce into the enclosing batch's flush. */
|
|
260
286
|
private notifySubscribers;
|
|
287
|
+
/** A publication superseded the authorization basis: every outstanding minted profile dies. */
|
|
288
|
+
private bumpPublication;
|
|
261
289
|
/**
|
|
262
290
|
* The sorted names of the tools `toolAccess` caps — read-only for the
|
|
263
291
|
* prompt contribution. An invalid config is not enumerated (it caps every
|
|
@@ -288,8 +316,46 @@ export declare class MultiRootScopeService extends Service {
|
|
|
288
316
|
* @returns the canonical scope; `additionalRoots` is empty when none are registered.
|
|
289
317
|
*/
|
|
290
318
|
requireAdmission(proof: object): void;
|
|
291
|
-
|
|
319
|
+
/**
|
|
320
|
+
* The stamp an asynchronously completing mint must carry: the publication
|
|
321
|
+
* generation and tool-cap basis at the mint's synchronous entry, before any
|
|
322
|
+
* provider probe could run. An in-flight mint that crosses a real
|
|
323
|
+
* publication keeps its entry generation, so the ledger refuses it rather
|
|
324
|
+
* than re-stamping stale authorization under the current publication.
|
|
325
|
+
* @param form - the profile form the mint will produce (`clamped` and
|
|
326
|
+
* `read-only` are the only ledger-eligible forms).
|
|
327
|
+
*/
|
|
328
|
+
captureMint(form: MintForm): MintStamp;
|
|
329
|
+
/**
|
|
330
|
+
* Record a confined profile this host's provider just minted. Only
|
|
331
|
+
* meaningful under the shared Registry (`admissionProof` set; without it
|
|
332
|
+
* `permitsProfile` never refuses): a live admission binds the profile to
|
|
333
|
+
* the operation and it dies with it; an expired admission never bequeaths
|
|
334
|
+
* one — a mint that outlived its operation is dropped, not demoted into
|
|
335
|
+
* the ledger; only with NO admission frame at all does the profile join
|
|
336
|
+
* the publication-keyed ledger stamped with `mint`, and only when the
|
|
337
|
+
* mint's form is primary-bounded — an `ambient` mint that arrives without
|
|
338
|
+
* a frame is dropped the same way.
|
|
339
|
+
* @param argv - the confined argv just minted.
|
|
340
|
+
* @param mint - the {@link captureMint} stamp taken at the mint's
|
|
341
|
+
* synchronous entry.
|
|
342
|
+
*/
|
|
343
|
+
rememberProfile(argv: readonly string[], mint: MintStamp): void;
|
|
344
|
+
/**
|
|
345
|
+
* Whether a confined argv may launch now: a profile minted inside this live
|
|
346
|
+
* admission, or — for a `confine`→`spawn` composition with no wrapped entry
|
|
347
|
+
* to admit it — a profile this host minted while its authorization
|
|
348
|
+
* publication is still current. Cached argv, argv minted under a superseded
|
|
349
|
+
* publication, and argv minted elsewhere stay refused.
|
|
350
|
+
*/
|
|
292
351
|
permitsProfile(argv: readonly string[]): boolean;
|
|
352
|
+
/**
|
|
353
|
+
* The strict form: only profiles minted inside this live admission. The OPS
|
|
354
|
+
* execution domain owns its profile exclusively and never honors the
|
|
355
|
+
* unadmitted mint ledger.
|
|
356
|
+
*/
|
|
357
|
+
permitsOperationProfile(argv: readonly string[]): boolean;
|
|
358
|
+
private permitsMintedProfile;
|
|
293
359
|
get admissionRequired(): boolean;
|
|
294
360
|
admissionPathsValid(): boolean;
|
|
295
361
|
hasAdmission(): boolean;
|
package/lib/workspace-files.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as wrapMethod } from "./method-wrapper-D4oUCsEF.js";
|
|
2
|
-
import {
|
|
2
|
+
import { l as withRegistryRead } from "./registry-operation-CIlmt6_c.js";
|
|
3
3
|
import { l as isCanonicallyUnder } from "./roots-CmaWxRVy.js";
|
|
4
4
|
import { t as routeWorkspacePath } from "./workspace-routing-D_qwMUh-.js";
|
|
5
5
|
import { posix, resolve, win32 } from "node:path";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-electron/dsh-plugin-multi-root-workspace",
|
|
3
3
|
"description": "Multi-root Workspace for DeepSeek Harness: adds N additional roots to the workspace sandbox scope as an out-of-tree bundle",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.16",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|