@dsh-electron/dsh-plugin-multi-root-workspace 0.1.10 → 0.1.12
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 +25 -1
- package/CHANGELOG.md +25 -1
- package/README.en.md +11 -9
- package/README.md +11 -9
- package/cordis.patch.yml +3 -2
- package/lib/auto-review.js +1 -1
- package/lib/client.js +252 -129
- package/lib/client.js.map +1 -1
- package/lib/{command-BGdz7VBH.js → command-CmLekG1M.js} +3 -2
- package/lib/command.js +1 -1
- package/lib/{compat-D-MljsPV.js → compat-Bg2HFVMX.js} +6 -1
- package/lib/compat.js +1 -1
- package/lib/{sandbox-CXk5h-ct.js → dialects-Dr4rDR-H.js} +6 -264
- package/lib/{fs-BTXySwSG.js → fs-CfzJq2wd.js} +23 -8
- package/lib/fs.js +1 -1
- package/lib/index.js +7 -6
- package/lib/{instructions-MePoRigy.js → instructions-KsUwUFE0.js} +53 -37
- package/lib/instructions.js +1 -1
- package/lib/lsp.js +19 -16
- package/lib/native-win32-2waCRkPI.js +312 -0
- package/lib/process-fence.js +62 -12
- package/lib/protocol-4zdwV7u4.js +641 -0
- package/lib/{registry-KSsmU393.js → registry-YTUOjmVu.js} +368 -25
- package/lib/registry-operation-C2ZV3Jhw.js +116 -0
- package/lib/registry.js +3 -2
- package/lib/{review-context-AH-SXHmj.js → review-context-NDpKeMCc.js} +1 -1
- package/lib/review-context.js +1 -1
- package/lib/sandbox-C-vCJCp3.js +278 -0
- package/lib/sandbox.js +1 -1
- package/lib/scope.js +70 -10
- package/lib/skills.js +48 -29
- package/lib/types/authority/native-win32.d.ts +7 -0
- package/lib/types/authority/native.d.ts +23 -0
- package/lib/types/authority/protocol.d.ts +70 -0
- package/lib/types/client/open-in-app/OpenInAppAction.d.ts +5 -3
- package/lib/types/client/open-in-app/OpenTargetButton.d.ts +16 -10
- package/lib/types/client/open-in-app/adapter.d.ts +5 -1
- package/lib/types/client/open-in-app/controller.d.ts +5 -2
- package/lib/types/client/open-in-app/device.d.ts +11 -0
- package/lib/types/client/open-in-app/locales.d.ts +1 -1
- package/lib/types/client/open-in-app/open-path.d.ts +6 -5
- package/lib/types/client/open-in-app/open-toast.d.ts +39 -0
- package/lib/types/client/open-in-app/outcome.d.ts +23 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/compat/authority-storage.d.ts +6 -0
- package/lib/types/compat/dsh-version.d.ts +4 -4
- package/lib/types/compat/open-in-app-device.d.ts +23 -0
- package/lib/types/compat/process-entrypoints.d.ts +2 -0
- package/lib/types/compat/process-profile.d.ts +3 -0
- package/lib/types/compat/sandbox-confine.d.ts +2 -0
- package/lib/types/fs.d.ts +4 -1
- package/lib/types/instructions.d.ts +0 -47
- package/lib/types/registry-operation.d.ts +31 -0
- package/lib/types/registry.d.ts +47 -6
- package/lib/types/scope.d.ts +12 -0
- package/lib/types/skills/catalog.d.ts +3 -0
- package/lib/types/skills/pool.d.ts +1 -1
- package/lib/workspace-files.js +63 -7
- package/package.json +87 -80
- package/lib/types/client/open-in-app/open-failure-toast.d.ts +0 -11
|
@@ -2,6 +2,7 @@ import { t as effectiveDirectory } from "./session-directory-BLOstut1.js";
|
|
|
2
2
|
import { r as canonicalPath$1 } from "./windows-runner-contract-B5R2K3mM.js";
|
|
3
3
|
import { i as canonicalRoot, o as entryRootRef, p as resolveRootRef, r as availableRoots, t as RootValidationError } from "./roots-Ca_W1S9n.js";
|
|
4
4
|
import { c as skillsRequestSchema, i as parsePanelCall, r as effectiveRootAccess, s as SKILLS_ENDPOINTS, t as PANEL_CHANNEL } from "./contract-CStSEOcK.js";
|
|
5
|
+
import { n as AuthorityRpcError } from "./protocol-4zdwV7u4.js";
|
|
5
6
|
import { closeSync, lstatSync, openSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
6
7
|
import { isAbsolute, join } from "node:path";
|
|
7
8
|
import "@deepseek-ai/cordis";
|
|
@@ -878,7 +879,7 @@ async function report(registry, primaryRoot, mode) {
|
|
|
878
879
|
}
|
|
879
880
|
/** Render a failure the way the composer displays it. */
|
|
880
881
|
function failureText(error) {
|
|
881
|
-
if (error instanceof RootValidationError) return `/${COMMAND_NAME}: ${error.code}: ${error.message}`;
|
|
882
|
+
if (error instanceof RootValidationError || error instanceof AuthorityRpcError) return `/${COMMAND_NAME}: ${error.code}: ${error.message}`;
|
|
882
883
|
return `/${COMMAND_NAME}: ${error instanceof Error ? error.message : String(error)}`;
|
|
883
884
|
}
|
|
884
885
|
/**
|
|
@@ -1268,7 +1269,7 @@ async function dispatchPanelRequest(ctx, endpoint, payload, signal) {
|
|
|
1268
1269
|
}
|
|
1269
1270
|
}
|
|
1270
1271
|
} catch (error) {
|
|
1271
|
-
if (error instanceof RootValidationError) return {
|
|
1272
|
+
if (error instanceof RootValidationError || error instanceof AuthorityRpcError) return {
|
|
1272
1273
|
ok: false,
|
|
1273
1274
|
error: {
|
|
1274
1275
|
code: error.code,
|
package/lib/command.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as renderRootsReport, c as revealArgv, i as parseFoldersCommand, n as apply, o as resolvePanelPrimaryRoot, r as inject, s as revealAccepted, t as COMMAND_NAME } from "./command-
|
|
1
|
+
import { a as renderRootsReport, c as revealArgv, i as parseFoldersCommand, n as apply, o as resolvePanelPrimaryRoot, r as inject, s as revealAccepted, t as COMMAND_NAME } from "./command-CmLekG1M.js";
|
|
2
2
|
export { COMMAND_NAME, apply, inject, parseFoldersCommand, renderRootsReport, resolvePanelPrimaryRoot, revealAccepted, revealArgv };
|
|
@@ -51,7 +51,10 @@ const SUPPORTED_DSH_RELEASES = [
|
|
|
51
51
|
"0.2.1-alpha.5",
|
|
52
52
|
"0.2.1-rc.1",
|
|
53
53
|
"0.2.1-rc.2",
|
|
54
|
-
"0.2.1-rc.3"
|
|
54
|
+
"0.2.1-rc.3",
|
|
55
|
+
"0.2.1-rc.4",
|
|
56
|
+
"0.2.1-rc.5",
|
|
57
|
+
"0.2.2-alpha.2"
|
|
55
58
|
];
|
|
56
59
|
/**
|
|
57
60
|
* Packages whose absence means this plugin cannot function at all: every one of
|
|
@@ -72,6 +75,7 @@ const REQUIRED_CORE_PACKAGES = [
|
|
|
72
75
|
* that is the mixed-installation failure this contract exists to catch.
|
|
73
76
|
*/
|
|
74
77
|
const OPTIONAL_CORE_PACKAGES = [
|
|
78
|
+
"@deepseek-ai/dsh-storage-json",
|
|
75
79
|
"@deepseek-ai/dsh-skill",
|
|
76
80
|
"@deepseek-ai/dsh-skill-filesystem",
|
|
77
81
|
"@deepseek-ai/dsh-settings",
|
|
@@ -101,6 +105,7 @@ const OPTIONAL_CORE_PACKAGES = [
|
|
|
101
105
|
* that disagrees with the host is a real mixed installation, not a phantom.
|
|
102
106
|
*/
|
|
103
107
|
const RUNTIME_OPTIONAL_PACKAGES = [
|
|
108
|
+
"@deepseek-ai/dsh-storage-json",
|
|
104
109
|
"@deepseek-ai/dsh-skill",
|
|
105
110
|
"@deepseek-ai/dsh-skill-filesystem",
|
|
106
111
|
"@deepseek-ai/dsh-agent-instructions",
|
package/lib/compat.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as inject, i as assertSupportedInstallation, n as MultiRootCompatService, r as apply, t as DshCompatUnsupportedError } from "./compat-
|
|
1
|
+
import { a as inject, i as assertSupportedInstallation, n as MultiRootCompatService, r as apply, t as DshCompatUnsupportedError } from "./compat-Bg2HFVMX.js";
|
|
2
2
|
export { DshCompatUnsupportedError, MultiRootCompatService, apply, assertSupportedInstallation, inject };
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as DialectUnrecognizedError } from "./windows-runner-contract-B5R2K3mM.js";
|
|
2
2
|
import { l as isCanonicallyUnder } from "./roots-Ca_W1S9n.js";
|
|
3
|
-
import { brandMultiRootProvider } from "./providers.js";
|
|
4
3
|
import { posix } from "node:path";
|
|
5
|
-
import { SandboxUnavailableError, canonicalPath } from "@deepseek-ai/dsh-sandbox";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { LocalSandboxProvider } from "@deepseek-ai/dsh-sandbox-local";
|
|
8
4
|
//#region src/compat/sandbox-confine.ts
|
|
9
5
|
/** Whether a value is a thenable, i.e. whether the installed `confine` is async. */
|
|
10
6
|
function isThenable(value) {
|
|
@@ -30,6 +26,10 @@ function widenConfined(base, widen, argv, policy, signal) {
|
|
|
30
26
|
const confined = base(argv, policy, signal);
|
|
31
27
|
return isThenable(confined) ? confined.then(widen) : widen(confined);
|
|
32
28
|
}
|
|
29
|
+
/** Public consumer call with the installed provider's arity and return shape. */
|
|
30
|
+
function confineInstalled(provider, argv, policy, signal) {
|
|
31
|
+
return provider.confine.call(provider, argv, policy, signal);
|
|
32
|
+
}
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/dialects.ts
|
|
35
35
|
/**
|
|
@@ -482,262 +482,4 @@ function restrictProfileArgs(dialect, profileArgs, deniedRoots) {
|
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
484
|
//#endregion
|
|
485
|
-
|
|
486
|
-
/** Windows runner argv and capability identity. No Win32 calls at module load. */
|
|
487
|
-
/** Recognize the upstream runner, then select our ambient deny-token path.
|
|
488
|
-
*
|
|
489
|
-
* `protectedHome` is a diagnostics label only: when it names one of the deny
|
|
490
|
-
* roots it is forwarded as `--protected-home` so the runner can word its
|
|
491
|
-
* hardlink/scan remediation for the protected `$DSH_HOME`. It never changes
|
|
492
|
-
* which roots are denied or how.
|
|
493
|
-
*/
|
|
494
|
-
function restrictWindowsProfile(profile, deniedRoots, protectedHome) {
|
|
495
|
-
assertWindowsDenyCapacity(deniedRoots.length);
|
|
496
|
-
if (profile.length < 2 || profile[0] === void 0 || profile[1]?.startsWith("--")) throw new DialectUnrecognizedError("Windows ACL runner invocation is not [node, runner, ...flags]");
|
|
497
|
-
const parsed = parseWindowsProfile(profile.slice(2));
|
|
498
|
-
if (deniedRoots.length === 0) throw new DialectUnrecognizedError("Windows ambient restriction requires at least one deny root");
|
|
499
|
-
for (const root of [parsed.workspace, ...deniedRoots]) if (isWindowsNetworkOrDevicePath(root)) throw new DialectUnrecognizedError(`Windows ACL confinement cannot cover network or device paths: ${root}`);
|
|
500
|
-
const label = protectedHome !== void 0 && deniedRoots.some((root) => root.toLowerCase() === protectedHome.toLowerCase()) ? ["--protected-home", protectedHome] : [];
|
|
501
|
-
return [
|
|
502
|
-
profile[0],
|
|
503
|
-
fileURLToPath(new URL("./windows-runner.js", import.meta.url)),
|
|
504
|
-
"--upstream-runner",
|
|
505
|
-
profile[1],
|
|
506
|
-
"--workspace",
|
|
507
|
-
parsed.workspace,
|
|
508
|
-
"--temp",
|
|
509
|
-
parsed.temp,
|
|
510
|
-
"--mode",
|
|
511
|
-
"danger-full-access",
|
|
512
|
-
...deniedRoots.flatMap((root) => ["--deny-root", root]),
|
|
513
|
-
...label
|
|
514
|
-
];
|
|
515
|
-
}
|
|
516
|
-
function widenWindowsProfile(profile, roots, deniedRoots, primaryRoot) {
|
|
517
|
-
if (profile.length < 2 || profile[0] === void 0 || profile[1]?.startsWith("--")) throw new DialectUnrecognizedError("Windows ACL runner invocation is not [node, runner, ...flags]");
|
|
518
|
-
const parsed = parseWindowsProfile(profile.slice(2));
|
|
519
|
-
for (const root of [parsed.workspace, ...roots]) if (isWindowsNetworkOrDevicePath(root)) throw new DialectUnrecognizedError(`Windows ACL confinement cannot cover network or device paths: ${root}`);
|
|
520
|
-
if (primaryRoot !== void 0 && canonicalPath(parsed.workspace) !== primaryRoot) throw new DialectUnrecognizedError("Windows ACL profile workspace does not match the policy root");
|
|
521
|
-
{
|
|
522
|
-
const granted = parsed.mode === "workspace-write" ? [
|
|
523
|
-
parsed.workspace,
|
|
524
|
-
parsed.temp,
|
|
525
|
-
...roots
|
|
526
|
-
] : roots;
|
|
527
|
-
const covered = deniedRoots.filter((root) => granted.some((target) => windowsContained(root, target) || windowsContained(target, root)));
|
|
528
|
-
if (covered.length > 0) throw new DialectUnrecognizedError(`Windows ACL cannot deny [${covered.join(", ")}] inside a writable grant — the restricted-token model only grants`);
|
|
529
|
-
}
|
|
530
|
-
if (roots.length === 0) return [...profile];
|
|
531
|
-
return [
|
|
532
|
-
profile[0],
|
|
533
|
-
fileURLToPath(new URL("./windows-runner.js", import.meta.url)),
|
|
534
|
-
"--upstream-runner",
|
|
535
|
-
profile[1],
|
|
536
|
-
...profile.slice(2),
|
|
537
|
-
...roots.flatMap((root) => ["--additional-root", root])
|
|
538
|
-
];
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Containment over Windows SPELLINGS, not the host OS: the profile this
|
|
542
|
-
* function rewrites may be produced for a Windows host while the check runs
|
|
543
|
-
* in tests on POSIX, so the comparison cannot borrow the host's separator or
|
|
544
|
-
* case rules.
|
|
545
|
-
*/
|
|
546
|
-
function windowsContained(candidate, root) {
|
|
547
|
-
const normalize = (path) => path.replaceAll("/", "\\").replace(/\\+$/, "").toLowerCase();
|
|
548
|
-
const target = normalize(candidate);
|
|
549
|
-
const base = normalize(root);
|
|
550
|
-
return target === base || target.startsWith(`${base}\\`);
|
|
551
|
-
}
|
|
552
|
-
//#endregion
|
|
553
|
-
//#region src/sandbox.ts
|
|
554
|
-
/**
|
|
555
|
-
* Local process-sandbox provider over the multi-root scope. Registers as
|
|
556
|
-
* `ctx.sandbox`; the runner chain, probing, denial dialects, and Windows ACL
|
|
557
|
-
* grant mechanics stay the upstream implementation's.
|
|
558
|
-
*/
|
|
559
|
-
var MultiRootSandboxProvider = class extends LocalSandboxProvider {
|
|
560
|
-
static inject = ["sandboxPolicy", "multiRootScope"];
|
|
561
|
-
constructor(ctx, config) {
|
|
562
|
-
super(ctx, config);
|
|
563
|
-
brandMultiRootProvider(this, "sandbox");
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* Wrap `argv` so it executes confined under `policy` on this host, granting
|
|
567
|
-
* the scope's additional roots inside the SAME dialect profile.
|
|
568
|
-
*
|
|
569
|
-
* Under `read-only` nothing is added (the mode denies every write, additional
|
|
570
|
-
* roots included), and `danger-full-access` never reaches here at all: the
|
|
571
|
-
* bash executor and the PTY backend both hand their argv straight to the local
|
|
572
|
-
* runtime in that mode. Widening therefore only ever ADDS the scope's
|
|
573
|
-
* additional roots to an upstream `workspace-write` profile.
|
|
574
|
-
*
|
|
575
|
-
* The return shape is the INSTALLED upstream provider's: synchronous on a
|
|
576
|
-
* release with a synchronous `confine`, a promise on a release with an
|
|
577
|
-
* asynchronous one. `widenConfined` preserves whichever it is — see
|
|
578
|
-
* `./compat/sandbox-confine.ts`.
|
|
579
|
-
* @param argv - the exact argv the caller is about to spawn.
|
|
580
|
-
* @param policy - the file-effect policy this execution runs under.
|
|
581
|
-
* @param signal - cancellation, forwarded to releases that accept it.
|
|
582
|
-
* @returns the argv to spawn instead, plus the selected backend's facts.
|
|
583
|
-
*/
|
|
584
|
-
confine(argv, policy, signal) {
|
|
585
|
-
const scope = this.ctx.multiRootScope.resolve(policy);
|
|
586
|
-
if (policy.mode === "workspace-write" && scope.authority === "unavailable") {
|
|
587
|
-
const prefix = this.clampedExecution(policy, scope.deniedRoots, signal);
|
|
588
|
-
return widenConfined(() => prefix, (facts) => ({
|
|
589
|
-
...facts,
|
|
590
|
-
argv: [...facts.argv, ...argv]
|
|
591
|
-
}), argv, policy, signal);
|
|
592
|
-
}
|
|
593
|
-
const base = super.confine;
|
|
594
|
-
return widenConfined(base.bind(this), (confined) => this.widenForScope(confined, argv, policy, scope), argv, policy, signal);
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Graft the scope's effective grants and denies onto one upstream `confine`
|
|
598
|
-
* result.
|
|
599
|
-
*
|
|
600
|
-
* Pure with respect to the upstream call: it only ever reads the scope and
|
|
601
|
-
* rewrites `argv`. `enforcement`, `denialSignatures` and `runnerFailureRules`
|
|
602
|
-
* are passed through untouched, because the bash executor derives its denial
|
|
603
|
-
* and enforcement reporting from them.
|
|
604
|
-
*
|
|
605
|
-
* Mode behavior (B9, R2): `workspace-write` widens the grant with the
|
|
606
|
-
* effective writable roots AND denies any restricted root the upstream
|
|
607
|
-
* grants could reach (a `read-only` root registered under the platform
|
|
608
|
-
* temp). `read-only` grafts the fixed `read-write` roots back onto the
|
|
609
|
-
* deny-all baseline — the three-state matrix's standout cell — and then
|
|
610
|
-
* applies the SAME deny pass: a grafted writable parent must not silently
|
|
611
|
-
* swallow a denied child (Seatbelt appends the deny after the allow, bwrap
|
|
612
|
-
* adds a mandatory `--ro-bind`, Landlock / windows-acl refuse the
|
|
613
|
-
* unrepresentable subtraction). `danger-full-access` never reaches
|
|
614
|
-
* here (consumers bypass `confine`); its deny semantics live in
|
|
615
|
-
* {@link restrictedArgvPrefix}.
|
|
616
|
-
* @param confined - the upstream result for this call.
|
|
617
|
-
* @param argv - the caller's argv, needed to re-split the wrapped form.
|
|
618
|
-
* @param policy - the per-call policy.
|
|
619
|
-
* @param scope - the authorization snapshot taken at dispatch.
|
|
620
|
-
* @returns the upstream result element for element, or one with a rewritten argv.
|
|
621
|
-
*/
|
|
622
|
-
widenForScope(confined, argv, policy, scope) {
|
|
623
|
-
if (scope.authority === "unavailable" || policy.mode !== "workspace-write" && policy.mode !== "read-only") return confined;
|
|
624
|
-
const writable = scope.writableRoots;
|
|
625
|
-
const denied = scope.deniedRoots;
|
|
626
|
-
if (writable.length === 0 && (denied.length === 0 || policy.mode === "read-only")) return confined;
|
|
627
|
-
try {
|
|
628
|
-
const shape = splitConfined(confined.argv, argv);
|
|
629
|
-
if (shape.dialect === "windows-acl") return {
|
|
630
|
-
...confined,
|
|
631
|
-
argv: [
|
|
632
|
-
...widenWindowsProfile(shape.profileArgs, writable, denied, scope.primaryRoot),
|
|
633
|
-
"--",
|
|
634
|
-
...argv
|
|
635
|
-
]
|
|
636
|
-
};
|
|
637
|
-
const widened = policy.mode === "workspace-write" ? widenProfileArgs(shape.dialect, shape.profileArgs, policy, writable) : graftProfileArgs(shape.dialect, shape.profileArgs, writable);
|
|
638
|
-
const profileArgs = denyProfileArgs(shape.dialect, widened, denied);
|
|
639
|
-
return {
|
|
640
|
-
...confined,
|
|
641
|
-
argv: [
|
|
642
|
-
...profileArgs,
|
|
643
|
-
"--",
|
|
644
|
-
...argv
|
|
645
|
-
]
|
|
646
|
-
};
|
|
647
|
-
} catch (error) {
|
|
648
|
-
if (!(error instanceof DialectUnrecognizedError)) throw error;
|
|
649
|
-
throw new SandboxUnavailableError(policy.mode, `multi-root workspace: cannot apply the additional workspace roots (writable: [${writable.join(", ")}], denied: [${denied.join(", ")}]) under the primary root ${scope.primaryRoot} — ${error.message}`);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
* Build the runner-prefix that confines an ambient-writable execution to
|
|
654
|
-
* everything EXCEPT `deniedRoots` — the `danger-full-access` + explicit
|
|
655
|
-
* `read-only` cell, which the shell, PTY and PTC consumers never route
|
|
656
|
-
* through `confine()` at all.
|
|
657
|
-
*
|
|
658
|
-
* The restricted profile does not depend on the callee's argv, so the prefix
|
|
659
|
-
* is computed once per call here and the synchronous `ctx.subprocess.spawn`
|
|
660
|
-
* seam only has to prepend it. The upstream profile builders stay private:
|
|
661
|
-
* this probes `confine` under `read-only` for the runner's argument skeleton
|
|
662
|
-
* and rewrites the file-effect part per dialect. Windows selects the
|
|
663
|
-
* standalone ambient deny-token runner. Landlock cannot express
|
|
664
|
-
* "everything except", so this combination selects bubblewrap; unusable
|
|
665
|
-
* runners fail without spawning an unconfined command.
|
|
666
|
-
*
|
|
667
|
-
* The return preserves the installed `confine` shape: a synchronous result
|
|
668
|
-
* on a synchronous release, a promise on an asynchronous one.
|
|
669
|
-
* @param policy - the caller's policy (mode must be `danger-full-access`).
|
|
670
|
-
* @param deniedRoots - canonical roots this execution must not write.
|
|
671
|
-
* @param signal - cancellation, forwarded to releases that accept it.
|
|
672
|
-
* @param protectedHome - diagnostics label: which deny root is the
|
|
673
|
-
* protected `$DSH_HOME`. Forwarded to the Windows runner only when it is
|
|
674
|
-
* a member of `deniedRoots`; it never changes authorization.
|
|
675
|
-
* @returns the argv prefix, ending at the `--` separator.
|
|
676
|
-
*/
|
|
677
|
-
restrictedArgvPrefix(policy, deniedRoots, signal, protectedHome) {
|
|
678
|
-
return mapConfined(this.restrictedExecution(policy, deniedRoots, signal, protectedHome), (confined) => confined.argv);
|
|
679
|
-
}
|
|
680
|
-
/** Full-access restriction and the actual selected backend's diagnostics. */
|
|
681
|
-
restrictedExecution(policy, deniedRoots, signal, protectedHome) {
|
|
682
|
-
const probePolicy = {
|
|
683
|
-
mode: "read-only",
|
|
684
|
-
workspaceRoot: policy.workspaceRoot,
|
|
685
|
-
...policy.sessionId === void 0 ? {} : { sessionId: policy.sessionId }
|
|
686
|
-
};
|
|
687
|
-
const probe = super.confine.call(this, ["true"], probePolicy, signal);
|
|
688
|
-
const restrict = (confined) => {
|
|
689
|
-
try {
|
|
690
|
-
const shape = splitConfined(confined.argv, ["true"]);
|
|
691
|
-
const argv = [...shape.dialect === "windows-acl" ? restrictWindowsProfile(shape.profileArgs, deniedRoots, protectedHome) : restrictProfileArgs(shape.dialect, shape.profileArgs, deniedRoots), "--"];
|
|
692
|
-
return shape.dialect === "landlock" ? {
|
|
693
|
-
argv,
|
|
694
|
-
enforcement: "full",
|
|
695
|
-
denialSignatures: ["read-only file system"],
|
|
696
|
-
runnerFailureRules: [{ fatalSignatures: ["bwrap: "] }]
|
|
697
|
-
} : {
|
|
698
|
-
...confined,
|
|
699
|
-
argv
|
|
700
|
-
};
|
|
701
|
-
} catch (error) {
|
|
702
|
-
if (!(error instanceof DialectUnrecognizedError)) throw error;
|
|
703
|
-
throw new SandboxUnavailableError(policy.mode, `multi-root workspace: cannot confine an ambient execution away from the denied roots [${deniedRoots.join(", ")}] — ${error.message}`);
|
|
704
|
-
}
|
|
705
|
-
};
|
|
706
|
-
return widenConfined(() => probe, restrict, ["true"], probePolicy, signal);
|
|
707
|
-
}
|
|
708
|
-
/**
|
|
709
|
-
* Limit an execution with unknown registry authority to the primary root.
|
|
710
|
-
* Shared temp grants are unsafe: another process may have registered a
|
|
711
|
-
* read-only root beneath them. Harvest the upstream read-only skeleton and
|
|
712
|
-
* graft only the primary root, retaining diagnostics and the sync/async shape.
|
|
713
|
-
* Explicit denies still win; an unrepresentable overlap refuses launch.
|
|
714
|
-
* @param policy - the caller's execution policy.
|
|
715
|
-
* @param deniedRoots - known negative boundaries, including protected home.
|
|
716
|
-
* @param signal - cancellation forwarded to upstream.
|
|
717
|
-
* @returns the confined prefix ending at `--`, without the caller's command.
|
|
718
|
-
*/
|
|
719
|
-
clampedExecution(policy, deniedRoots, signal) {
|
|
720
|
-
const probePolicy = {
|
|
721
|
-
mode: "read-only",
|
|
722
|
-
workspaceRoot: policy.workspaceRoot,
|
|
723
|
-
...policy.sessionId === void 0 ? {} : { sessionId: policy.sessionId }
|
|
724
|
-
};
|
|
725
|
-
const probe = super.confine.call(this, ["true"], probePolicy, signal);
|
|
726
|
-
const clamp = (confined) => {
|
|
727
|
-
try {
|
|
728
|
-
const shape = splitConfined(confined.argv, ["true"]);
|
|
729
|
-
const profileArgs = shape.dialect === "windows-acl" ? widenWindowsProfile(shape.profileArgs, [canonicalPath(policy.workspaceRoot)], deniedRoots, canonicalPath(policy.workspaceRoot)) : denyProfileArgs(shape.dialect, graftProfileArgs(shape.dialect, shape.profileArgs, [canonicalPath(policy.workspaceRoot)]), deniedRoots);
|
|
730
|
-
return {
|
|
731
|
-
...confined,
|
|
732
|
-
argv: [...profileArgs, "--"]
|
|
733
|
-
};
|
|
734
|
-
} catch (error) {
|
|
735
|
-
if (!(error instanceof DialectUnrecognizedError)) throw error;
|
|
736
|
-
throw new SandboxUnavailableError(policy.mode, `multi-root workspace: cannot limit an execution to the primary root while the registry authority is unavailable — ${error.message}`);
|
|
737
|
-
}
|
|
738
|
-
};
|
|
739
|
-
return widenConfined(() => probe, clamp, ["true"], probePolicy, signal);
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
//#endregion
|
|
743
|
-
export { widenConfined as n, MultiRootSandboxProvider as t };
|
|
485
|
+
export { splitConfined as a, mapConfined as c, restrictProfileArgs as i, widenConfined as l, detectDialect as n, widenProfileArgs as o, graftProfileArgs as r, confineInstalled as s, denyProfileArgs as t };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { brandMultiRootProvider } from "./providers.js";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
2
3
|
import { dirname, sep } from "node:path";
|
|
3
|
-
import { writableRoots } from "@deepseek-ai/dsh-sandbox";
|
|
4
|
+
import { canonicalPath, writableRoots } from "@deepseek-ai/dsh-sandbox";
|
|
4
5
|
import { stat } from "node:fs/promises";
|
|
5
6
|
import { FsError } from "@deepseek-ai/dsh-fs";
|
|
6
7
|
import { LocalFileSystem } from "@deepseek-ai/dsh-fs-local";
|
|
@@ -88,7 +89,8 @@ var MultiRootFileSystem = class extends LocalFileSystem {
|
|
|
88
89
|
* @returns the write outcome from the inherited backend.
|
|
89
90
|
*/
|
|
90
91
|
async writeText(target, content, expected, signal, sandboxPolicy) {
|
|
91
|
-
|
|
92
|
+
const policy = structuredClone(sandboxPolicy ?? this.ctx.sandboxPolicy.resolve());
|
|
93
|
+
return this.withOperation(policy, "fs-write", async (scope) => super.writeText(await this.checkedTarget(target, policy, scope), content, expected, signal));
|
|
92
94
|
}
|
|
93
95
|
/**
|
|
94
96
|
* Fence the edit by the per-call policy, then delegate to the inherited
|
|
@@ -102,7 +104,14 @@ var MultiRootFileSystem = class extends LocalFileSystem {
|
|
|
102
104
|
* @returns the edit outcome from the inherited backend.
|
|
103
105
|
*/
|
|
104
106
|
async editText(target, edit, expected, signal, sandboxPolicy) {
|
|
105
|
-
|
|
107
|
+
const policy = structuredClone(sandboxPolicy ?? this.ctx.sandboxPolicy.resolve());
|
|
108
|
+
return this.withOperation(policy, "fs-edit", async (scope) => super.editText(await this.checkedTarget(target, policy, scope), edit, expected, signal));
|
|
109
|
+
}
|
|
110
|
+
/** The provider must also work without the gated registry (ADR-0009). */
|
|
111
|
+
async withOperation(policy, kind, body) {
|
|
112
|
+
const registry = this.ctx.get("multiRootRegistry");
|
|
113
|
+
if (registry !== void 0) return registry.withOperation(policy, kind, (operation) => body(operation.scope));
|
|
114
|
+
return body(this.ctx.multiRootScope.resolve(policy));
|
|
106
115
|
}
|
|
107
116
|
/**
|
|
108
117
|
* The writable roots of one confined call: the upstream derivation (primary
|
|
@@ -121,7 +130,14 @@ var MultiRootFileSystem = class extends LocalFileSystem {
|
|
|
121
130
|
rootsFor(policy, scope) {
|
|
122
131
|
if (scope.authority === "unavailable") return policy.mode === "read-only" ? [] : [scope.primaryRoot];
|
|
123
132
|
const roots = writableRoots(policy);
|
|
124
|
-
for (const root of scope.writableRoots)
|
|
133
|
+
for (const root of scope.writableRoots) {
|
|
134
|
+
try {
|
|
135
|
+
if (canonicalPath(root) !== root || !statSync(root).isDirectory()) continue;
|
|
136
|
+
} catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (!roots.includes(root)) roots.push(root);
|
|
140
|
+
}
|
|
125
141
|
return roots;
|
|
126
142
|
}
|
|
127
143
|
/**
|
|
@@ -149,12 +165,11 @@ var MultiRootFileSystem = class extends LocalFileSystem {
|
|
|
149
165
|
* to primary-root-only writes (no shared temp or additional-root grants)
|
|
150
166
|
* until the authority returns.
|
|
151
167
|
* @param target - the resolved target about to be mutated.
|
|
152
|
-
* @param
|
|
168
|
+
* @param policy - the per-call policy captured before admission.
|
|
169
|
+
* @param scope - the admission snapshot shared by every fence check.
|
|
153
170
|
* @returns the fresh canonical target the mutation must use.
|
|
154
171
|
*/
|
|
155
|
-
async checkedTarget(target,
|
|
156
|
-
const policy = sandboxPolicy ?? this.ctx.sandboxPolicy.resolve();
|
|
157
|
-
const scope = this.ctx.multiRootScope.resolve(policy);
|
|
172
|
+
async checkedTarget(target, policy, scope) {
|
|
158
173
|
const effectiveMode = scope.authority === "unavailable" && policy.mode === "danger-full-access" ? "workspace-write" : policy.mode;
|
|
159
174
|
if (effectiveMode === "danger-full-access" && scope.deniedRoots.length === 0) return target;
|
|
160
175
|
const fresh = await this.resolve(target.displayPath);
|
package/lib/fs.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { i as renderInstructions, n as instructionsApi, t as createInstructionMessage } from "./llm-message-fYORacvh.js";
|
|
2
|
-
import { a as composeInstructionMessage, r as PLUGIN_SOURCE, t as DEFAULT_MAX_BYTES } from "./instructions-
|
|
2
|
+
import { a as composeInstructionMessage, r as PLUGIN_SOURCE, t as DEFAULT_MAX_BYTES } from "./instructions-KsUwUFE0.js";
|
|
3
3
|
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-Ca_W1S9n.js";
|
|
4
|
-
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-
|
|
5
|
-
import {
|
|
4
|
+
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-Bg2HFVMX.js";
|
|
5
|
+
import { l as widenConfined } from "./dialects-Dr4rDR-H.js";
|
|
6
6
|
import { MULTI_ROOT_PROVIDER_BRAND, MultiRootProviders, brandMultiRootProvider, isMultiRootProvider } from "./providers.js";
|
|
7
|
-
import { t as MultiRootFileSystem } from "./fs-
|
|
7
|
+
import { t as MultiRootFileSystem } from "./fs-CfzJq2wd.js";
|
|
8
|
+
import { t as MultiRootSandboxProvider } from "./sandbox-C-vCJCp3.js";
|
|
8
9
|
import { a as parseRevealedView, i as parsePanelCall, n as PANEL_ENDPOINTS, o as parseRootsView, t as PANEL_CHANNEL } from "./contract-CStSEOcK.js";
|
|
9
10
|
import { MultiRootScopeService, renderWorkspaceRootsContext, sanitizeAdditionalRoots } from "./scope.js";
|
|
10
|
-
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-
|
|
11
|
-
import { a as renderRootsReport, c as revealArgv, i as parseFoldersCommand, o as resolvePanelPrimaryRoot, t as COMMAND_NAME } from "./command-
|
|
11
|
+
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-YTUOjmVu.js";
|
|
12
|
+
import { a as renderRootsReport, c as revealArgv, i as parseFoldersCommand, o as resolvePanelPrimaryRoot, t as COMMAND_NAME } from "./command-CmLekG1M.js";
|
|
12
13
|
//#region src/index.ts
|
|
13
14
|
/**
|
|
14
15
|
* Carrier plugin face for the bare-package-name loader row (see the module
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as effectiveDirectory } from "./session-directory-BLOstut1.js";
|
|
2
|
+
import { c as withRegistryRead, s as withRegistryAdmission } from "./registry-operation-C2ZV3Jhw.js";
|
|
2
3
|
import { n as instructionsApi, t as createInstructionMessage } from "./llm-message-fYORacvh.js";
|
|
3
4
|
import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
|
|
4
5
|
import { l as isCanonicallyUnder } from "./roots-Ca_W1S9n.js";
|
|
@@ -6,8 +7,8 @@ import { createHash } from "node:crypto";
|
|
|
6
7
|
import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
7
8
|
import "@deepseek-ai/cordis";
|
|
8
9
|
import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
|
|
9
|
-
import { stat } from "node:fs/promises";
|
|
10
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
|
+
import { stat } from "node:fs/promises";
|
|
11
12
|
//#region src/compat/tool-result.ts
|
|
12
13
|
/**
|
|
13
14
|
* Whether a tool-result message reports failure, on every supported release.
|
|
@@ -367,39 +368,43 @@ function apply(ctx, config = {}) {
|
|
|
367
368
|
return [...states.get(session)?.provenanceRoots ?? []];
|
|
368
369
|
},
|
|
369
370
|
async snapshot(agent, roots, target, signal) {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
371
|
+
return withRegistryRead(scope, scope.sandboxPolicy.resolve({ session: agent.session }).workspaceRoot, "instructions", async () => {
|
|
372
|
+
const allowed = new Set(scope.multiRootScope.scopeOf(scope.sandboxPolicy.resolve({ session: agent.session }).workspaceRoot));
|
|
373
|
+
roots = roots.filter((root) => allowed.has(root));
|
|
374
|
+
signal.throwIfAborted();
|
|
375
|
+
if (roots.length === 0) return [];
|
|
376
|
+
const api = await instructionsApi();
|
|
377
|
+
if (api === void 0) throw new Error("review-context: instruction discovery unavailable");
|
|
378
|
+
const existing = states.get(agent.session);
|
|
379
|
+
if (existing?.overflow) throw new Error("review-context: successful work index exceeded");
|
|
380
|
+
const state = {
|
|
381
|
+
scopes: new Map([...existing?.scopes ?? []].map(([key, value]) => [key, {
|
|
382
|
+
...value,
|
|
383
|
+
digest: void 0
|
|
384
|
+
}])),
|
|
385
|
+
provenanceRoots: new Set(existing?.provenanceRoots),
|
|
386
|
+
touched: /* @__PURE__ */ new Set([...existing?.touched ?? [], ...existing?.worked ?? []]),
|
|
387
|
+
worked: /* @__PURE__ */ new Set()
|
|
388
|
+
};
|
|
389
|
+
for (const path of replayedInstructionTargets(agent.session.snapshotEvents(), agent.session.header.cwd)) state.touched.add(path);
|
|
390
|
+
if (target !== void 0) state.touched.add(target);
|
|
391
|
+
const cwd = effectiveDirectory(scope, agent.session);
|
|
392
|
+
const reviewCwd = cwd === void 0 ? void 0 : canonicalPath(cwd);
|
|
393
|
+
const result = [];
|
|
394
|
+
for (const root of roots) {
|
|
395
|
+
const plan = await planRoot(scope, api, root, config, state, signal, true, reviewCwd);
|
|
396
|
+
for (const { file } of plan.deliveries) result.push({
|
|
397
|
+
root,
|
|
398
|
+
path: file.absolutePath,
|
|
399
|
+
relativeDirectory: relativeDirectoryOf(root, dirname(file.absolutePath)),
|
|
400
|
+
digest: digestOf(file.content),
|
|
401
|
+
text: file.content
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
signal.throwIfAborted();
|
|
405
|
+
if (Buffer.byteLength(JSON.stringify(result), "utf8") > maxBytes) throw new Error("review-context: instruction budget exceeded");
|
|
406
|
+
return result;
|
|
407
|
+
});
|
|
403
408
|
}
|
|
404
409
|
});
|
|
405
410
|
scope.on("fs/observed", (target, _observation, actor) => {
|
|
@@ -412,7 +417,7 @@ function apply(ctx, config = {}) {
|
|
|
412
417
|
scope.on("agent/pre-step", async ({ agent, messages, signal }, next) => {
|
|
413
418
|
const decision = await next();
|
|
414
419
|
if (decision.kind !== "enter") return decision;
|
|
415
|
-
const seeded = await pending(scope, states, agent, config, maxBytes, signal, decision.messages);
|
|
420
|
+
const seeded = await withRegistryAdmission(scope, scope.sandboxPolicy.resolve({ session: agent.session }), "instructions", () => pending(scope, states, agent, config, maxBytes, signal, decision.messages));
|
|
416
421
|
if (seeded === void 0) return decision;
|
|
417
422
|
signal.throwIfAborted();
|
|
418
423
|
const lastClaimed = decision.messages.findLastIndex((message) => messages.includes(message));
|
|
@@ -436,8 +441,9 @@ function apply(ctx, config = {}) {
|
|
|
436
441
|
* @param signal - the turn's cancellation signal.
|
|
437
442
|
* @returns the message to inject, or `undefined`.
|
|
438
443
|
*/
|
|
439
|
-
async function pending(ctx, states, agent, config, maxBytes, signal, messages) {
|
|
444
|
+
async function pending(ctx, states, agent, config, maxBytes, signal, messages, retried = false) {
|
|
440
445
|
const session = agent.session;
|
|
446
|
+
const sourceEpoch = ctx.get("multiRootRegistry")?.epoch;
|
|
441
447
|
const state = states.get(session) ?? {
|
|
442
448
|
scopes: /* @__PURE__ */ new Map(),
|
|
443
449
|
provenanceRoots: /* @__PURE__ */ new Set(),
|
|
@@ -508,7 +514,7 @@ async function pending(ctx, states, agent, config, maxBytes, signal, messages) {
|
|
|
508
514
|
}
|
|
509
515
|
}
|
|
510
516
|
}
|
|
511
|
-
const current = new Set(ctx.multiRootScope.resolve(ctx.sandboxPolicy.resolve({ session })).additionalRoots);
|
|
517
|
+
const current = new Set(await withRegistryAdmission(ctx, ctx.sandboxPolicy.resolve({ session }), "instructions", () => ctx.multiRootScope.resolve(ctx.sandboxPolicy.resolve({ session })).additionalRoots));
|
|
512
518
|
const revoked = [...new Set([...state.scopes.values()].map((entry) => entry.root))].filter((root) => !current.has(root));
|
|
513
519
|
const liveUpdates = updates.filter((entry) => current.has(entry.scope.root));
|
|
514
520
|
const text = composeInstructionMessage(rendered.filter((entry) => current.has(entry.root)), revoked, gone.filter((entry) => current.has(entry.scope.root)).map((entry) => entry.scope));
|
|
@@ -517,6 +523,16 @@ async function pending(ctx, states, agent, config, maxBytes, signal, messages) {
|
|
|
517
523
|
plugin: PLUGIN_SOURCE
|
|
518
524
|
});
|
|
519
525
|
signal.throwIfAborted();
|
|
526
|
+
if (ctx.get("multiRootRegistry")?.shared) {
|
|
527
|
+
const final = await withRegistryAdmission(ctx, ctx.sandboxPolicy.resolve({ session }), "instructions", () => ({
|
|
528
|
+
roots: ctx.multiRootScope.resolve(ctx.sandboxPolicy.resolve({ session })).additionalRoots,
|
|
529
|
+
epoch: ctx.get("multiRootRegistry")?.epoch
|
|
530
|
+
}));
|
|
531
|
+
if (sourceEpoch !== final.epoch || final.roots.length !== current.size || final.roots.some((root) => !current.has(root))) {
|
|
532
|
+
if (retried) return void 0;
|
|
533
|
+
return withRegistryAdmission(ctx, ctx.sandboxPolicy.resolve({ session }), "instructions", () => pending(ctx, states, agent, config, maxBytes, signal, messages, true));
|
|
534
|
+
}
|
|
535
|
+
}
|
|
520
536
|
if (!retryTouches) for (const touch of evaluatedTouches) state.touched.delete(touch);
|
|
521
537
|
if (text !== void 0 || liveUpdates.length > 0) {
|
|
522
538
|
for (const root of revoked) for (const [key, entry] of state.scopes) if (entry.root === root) state.scopes.delete(key);
|
package/lib/instructions.js
CHANGED
|
@@ -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-
|
|
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-KsUwUFE0.js";
|
|
2
2
|
export { DEFAULT_MAX_BYTES, DEFAULT_MAX_SOURCE_BYTES, PLUGIN_SOURCE, apply, composeInstructionMessage, inject, touchedPathOfToolCall };
|
package/lib/lsp.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as wrapMethod } from "./method-wrapper-CFY3p3j2.js";
|
|
2
|
+
import { c as withRegistryRead } from "./registry-operation-C2ZV3Jhw.js";
|
|
2
3
|
import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
|
|
3
4
|
import { t as routeWorkspacePath } from "./workspace-routing-YPxaQ4V3.js";
|
|
4
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -17,25 +18,27 @@ function apply(ctx) {
|
|
|
17
18
|
const session = callers.getStore();
|
|
18
19
|
const primary = session === void 0 ? request.workspaceRoot : session.header.cwd ?? scope.get("sandboxPolicy")?.resolve({ session }).workspaceRoot;
|
|
19
20
|
if (primary === void 0) throw new Error("multi-root workspace: LSP caller has no session origin or deployment policy");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
return await withRegistryRead(scope, primary, "lsp", async () => {
|
|
22
|
+
if (scope.multiRootScope.scopeOf(primary).length === 0 && session === void 0) return original.call(this, request, signal);
|
|
23
|
+
const route = await routeWorkspacePath(scope, primary, request.filePath, signal, request.workspaceRoot);
|
|
24
|
+
if (route === void 0) {
|
|
25
|
+
const target = await scope.fs.resolve(request.filePath, {
|
|
26
|
+
cwd: request.workspaceRoot,
|
|
27
|
+
...signal === void 0 ? {} : { signal }
|
|
28
|
+
});
|
|
29
|
+
return original.call(this, {
|
|
30
|
+
...request,
|
|
31
|
+
workspaceRoot: primary,
|
|
32
|
+
filePath: scope.fs.processPath(target)
|
|
33
|
+
}, signal);
|
|
34
|
+
}
|
|
35
|
+
if (session === void 0 && route.workspaceRoot === route.primaryRoot) return original.call(this, request, signal);
|
|
27
36
|
return original.call(this, {
|
|
28
37
|
...request,
|
|
29
|
-
workspaceRoot:
|
|
30
|
-
filePath:
|
|
38
|
+
workspaceRoot: route.workspaceRoot,
|
|
39
|
+
filePath: route.absolutePath
|
|
31
40
|
}, signal);
|
|
32
|
-
}
|
|
33
|
-
if (session === void 0 && route.workspaceRoot === route.primaryRoot) return original.call(this, request, signal);
|
|
34
|
-
return original.call(this, {
|
|
35
|
-
...request,
|
|
36
|
-
workspaceRoot: route.workspaceRoot,
|
|
37
|
-
filePath: route.absolutePath
|
|
38
|
-
}, signal);
|
|
41
|
+
});
|
|
39
42
|
}), "multi-root:lsp routing");
|
|
40
43
|
});
|
|
41
44
|
}
|