@dsh-electron/dsh-plugin-multi-root-workspace 0.1.5 → 0.1.7
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 +56 -1
- package/CHANGELOG.md +56 -1
- package/README.en.md +157 -92
- package/README.md +158 -93
- package/cordis.patch.yml +61 -0
- package/lib/client.js +2819 -115
- package/lib/client.js.map +1 -1
- package/lib/command-CESuwlVt.js +1306 -0
- package/lib/command.js +2 -2
- package/lib/{compat-82Y27Iom.js → compat-DF_yL1bB.js} +180 -4
- package/lib/compat.js +1 -1
- package/lib/contract-DZ4zczDT.js +238 -0
- package/lib/{fs-D_Sw3o5z.js → fs-9JIzGaf3.js} +55 -19
- package/lib/fs.js +2 -1
- package/lib/index.js +10 -8
- package/lib/{instructions-Cn1Jj5Xi.js → instructions-D19jRxN0.js} +109 -28
- package/lib/instructions.js +1 -1
- package/lib/lsp.js +43 -0
- package/lib/method-wrapper-CFY3p3j2.js +26 -0
- package/lib/process-fence.js +280 -0
- package/lib/providers.js +87 -0
- package/lib/{registry-DySMbjgW.js → registry-DCxC5Lay.js} +256 -35
- package/lib/registry.js +2 -2
- package/lib/{roots-DasWEBJk.js → roots-B-0l8mNG.js} +117 -20
- package/lib/sandbox-Kup4_ZIb.js +747 -0
- package/lib/sandbox.js +2 -1
- package/lib/scope.js +240 -25
- package/lib/session-directory-BLOstut1.js +9 -0
- package/lib/tool-context-CpgIFcCB.js +6 -0
- package/lib/types/client/RootSwitcher.d.ts +63 -0
- package/lib/types/client/WorkspaceFoldersAction.d.ts +41 -0
- package/lib/types/client/files-tree/FilesBody.module.css.d.ts +24 -0
- package/lib/types/client/files-tree/FilesTree.d.ts +47 -0
- package/lib/types/client/files-tree/adapter.d.ts +94 -0
- package/lib/types/client/files-tree/directory-node.d.ts +62 -0
- package/lib/types/client/files-tree/face.d.ts +107 -0
- package/lib/types/client/files-tree/locales.d.ts +10 -0
- package/lib/types/client/files-tree/primitives.d.ts +33 -0
- package/lib/types/client/files-tree/store.d.ts +81 -0
- package/lib/types/client/index.d.ts +13 -2
- package/lib/types/client/locales.d.ts +60 -0
- package/lib/types/client/open-in-app/OpenInAppAction.d.ts +27 -0
- package/lib/types/client/open-in-app/OpenTargetButton.d.ts +52 -0
- package/lib/types/client/open-in-app/OpenTargetButton.module.css.d.ts +29 -0
- package/lib/types/client/open-in-app/adapter.d.ts +46 -0
- package/lib/types/client/open-in-app/applications.d.ts +4 -0
- package/lib/types/client/open-in-app/controller.d.ts +53 -0
- package/lib/types/client/open-in-app/locales.d.ts +10 -0
- package/lib/types/client/open-in-app/open-failure-toast.d.ts +11 -0
- package/lib/types/client/open-in-app/open-path.d.ts +13 -0
- package/lib/types/client/panel-client.d.ts +2 -1
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/command.d.ts +16 -3
- package/lib/types/compat/client-icons.d.ts +18 -0
- package/lib/types/compat/client-session.d.ts +2 -0
- package/lib/types/compat/dsh-version.d.ts +5 -3
- package/lib/types/compat/instruction-overlap.d.ts +7 -0
- package/lib/types/compat/open-in-app-routes.d.ts +38 -0
- package/lib/types/compat/process-entrypoints.d.ts +31 -0
- package/lib/types/compat/process-result.d.ts +14 -0
- package/lib/types/compat/pty-marker.d.ts +83 -0
- package/lib/types/compat/sandbox-confine.d.ts +2 -0
- package/lib/types/compat/session-directory.d.ts +4 -0
- package/lib/types/compat/storage-zod.d.ts +65 -0
- package/lib/types/compat/tool-context.d.ts +9 -0
- package/lib/types/compat/windows-deny-preflight.d.ts +21 -0
- package/lib/types/compat/windows-native.d.ts +68 -0
- package/lib/types/compat/windows-path-guard.d.ts +56 -0
- package/lib/types/compat/workspace-files.d.ts +7 -0
- package/lib/types/contract.d.ts +35 -4
- package/lib/types/dialects.d.ts +99 -3
- package/lib/types/fs.d.ts +32 -10
- package/lib/types/index.d.ts +5 -0
- package/lib/types/lsp.d.ts +4 -0
- package/lib/types/method-wrapper.d.ts +2 -0
- package/lib/types/process-fence.d.ts +54 -0
- package/lib/types/profile-isolation.d.ts +178 -0
- package/lib/types/providers.d.ts +70 -0
- package/lib/types/registry.d.ts +132 -31
- package/lib/types/roots.d.ts +100 -13
- package/lib/types/sandbox.d.ts +59 -12
- package/lib/types/scope.d.ts +203 -14
- package/lib/types/windows-broker.d.ts +17 -0
- package/lib/types/windows-deny.d.ts +1 -0
- package/lib/types/windows-profile.d.ts +10 -0
- package/lib/types/windows-runner-contract.d.ts +97 -0
- package/lib/types/windows-runner.d.ts +1 -0
- package/lib/types/workspace-files.d.ts +4 -0
- package/lib/types/workspace-routing.d.ts +11 -0
- package/lib/windows-runner-contract-CEfmZzu0.js +141 -0
- package/lib/windows-runner.js +1311 -0
- package/lib/workspace-files.js +203 -0
- package/lib/workspace-routing-YPxaQ4V3.js +26 -0
- package/package.json +116 -51
- package/scripts/windows-broker/install.ps1 +89 -0
- package/scripts/windows-broker/rights.cs +58 -0
- package/scripts/windows-broker/service.cs +323 -0
- package/scripts/windows-broker/verify-install.ps1 +80 -0
- package/lib/command-DyOWujPo.js +0 -690
- package/lib/sandbox-D8Fw95FM.js +0 -290
- package/lib/{registry-lease-win32-dy8TQMD9.js → registry-lease-win32-DTO6QpT9.js} +2 -2
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as effectiveDirectory } from "./session-directory-BLOstut1.js";
|
|
2
|
+
import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
|
|
3
|
+
import { l as isCanonicallyUnder } from "./roots-B-0l8mNG.js";
|
|
2
4
|
import { createRequire } from "node:module";
|
|
3
5
|
import "@deepseek-ai/cordis";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
6
|
import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
9
|
import { canonicalPath } from "@deepseek-ai/dsh-sandbox";
|
|
7
10
|
//#region src/compat/agent-instructions.ts
|
|
8
11
|
/**
|
|
@@ -221,6 +224,51 @@ function toolResultFailed(message) {
|
|
|
221
224
|
return block.isError === true;
|
|
222
225
|
}
|
|
223
226
|
//#endregion
|
|
227
|
+
//#region src/compat/instruction-overlap.ts
|
|
228
|
+
/** Recognize files already represented by the native instruction baseline in this step. */
|
|
229
|
+
function nativeInstructionCopies(messages, cwd) {
|
|
230
|
+
const represented = /* @__PURE__ */ new Map();
|
|
231
|
+
const removed = /* @__PURE__ */ new Set();
|
|
232
|
+
let replacesBaseline = false;
|
|
233
|
+
for (const message of messages) {
|
|
234
|
+
const source = message.source;
|
|
235
|
+
if (source.kind !== "agent-instructions" || source.changes === void 0) continue;
|
|
236
|
+
if (source.baseline === true) {
|
|
237
|
+
replacesBaseline = true;
|
|
238
|
+
represented.clear();
|
|
239
|
+
}
|
|
240
|
+
for (const change of source.changes) {
|
|
241
|
+
if (change.action !== "remove") continue;
|
|
242
|
+
removed.add(change.path);
|
|
243
|
+
for (const [path, copy] of represented) if (copy.displayPath === change.path) represented.delete(path);
|
|
244
|
+
}
|
|
245
|
+
if (cwd === void 0 || source.baselineIdentity === void 0) continue;
|
|
246
|
+
let identity;
|
|
247
|
+
try {
|
|
248
|
+
identity = JSON.parse(source.baselineIdentity);
|
|
249
|
+
} catch {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (typeof identity.projectRoot !== "string") continue;
|
|
253
|
+
const project = resolve(cwd, identity.projectRoot);
|
|
254
|
+
for (const change of source.changes) {
|
|
255
|
+
if (change.action === "remove" || typeof change.digest !== "string") continue;
|
|
256
|
+
if (/^(?:~|\$|user-global[\\/]|agents-global[\\/])/.test(change.path)) continue;
|
|
257
|
+
represented.set(resolve(project, change.path), {
|
|
258
|
+
digest: change.digest,
|
|
259
|
+
displayPath: change.path
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
pathOf: (file) => {
|
|
265
|
+
const copy = represented.get(file.absolutePath);
|
|
266
|
+
return copy?.digest === createHash("sha1").update(file.content).digest("hex") ? copy.displayPath : void 0;
|
|
267
|
+
},
|
|
268
|
+
withdraws: (displayPath) => replacesBaseline || removed.has(displayPath)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
//#endregion
|
|
224
272
|
//#region src/instructions.ts
|
|
225
273
|
/**
|
|
226
274
|
* `multi-root-instructions`: the additional roots' own instruction files, made
|
|
@@ -342,16 +390,13 @@ function touchedPathOfToolCall(name, argumentsJson) {
|
|
|
342
390
|
* The directory a touched path's instructions would live in.
|
|
343
391
|
*
|
|
344
392
|
* Tool arguments are the model's raw input, so a relative `file_path` is
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
* @param path - a touched path, absolute or relative to the session cwd.
|
|
349
|
-
* @param session - the session the touch belongs to.
|
|
393
|
+
* captured as an absolute path at the operation boundary. Mac's `realpath`
|
|
394
|
+
* spelling is applied here so it compares against the canonical roots.
|
|
395
|
+
* @param path - the absolute touched file path.
|
|
350
396
|
* @returns the canonical parent directory, or `undefined` when it cannot be named.
|
|
351
397
|
*/
|
|
352
|
-
function parentDirectoryOf(path
|
|
353
|
-
const
|
|
354
|
-
const absolute = isAbsolute(path) ? path : cwd === void 0 ? void 0 : resolve(cwd, path);
|
|
398
|
+
function parentDirectoryOf(path) {
|
|
399
|
+
const absolute = isAbsolute(path) ? path : void 0;
|
|
355
400
|
if (absolute === void 0) return void 0;
|
|
356
401
|
try {
|
|
357
402
|
return canonicalPath(dirname(absolute));
|
|
@@ -385,6 +430,7 @@ function composeInstructionMessage(rendered, revoked, removed) {
|
|
|
385
430
|
/** This row is gated on the compatibility contract like every other provider. */
|
|
386
431
|
const inject = [
|
|
387
432
|
"multiRootCompat",
|
|
433
|
+
"multiRootProviders",
|
|
388
434
|
"multiRootScope",
|
|
389
435
|
"sandboxPolicy"
|
|
390
436
|
];
|
|
@@ -407,6 +453,8 @@ function apply(ctx, config = {}) {
|
|
|
407
453
|
if (maxBytes <= 0 || !Number.isFinite(maxBytes)) return;
|
|
408
454
|
const states = /* @__PURE__ */ new WeakMap();
|
|
409
455
|
const callsBySession = /* @__PURE__ */ new WeakMap();
|
|
456
|
+
const executions = new AsyncLocalStorage();
|
|
457
|
+
aroundTool(ctx, (exec, next) => executions.run(exec, next));
|
|
410
458
|
const stateOf = (session) => {
|
|
411
459
|
const existing = states.get(session);
|
|
412
460
|
if (existing !== void 0) return existing;
|
|
@@ -427,7 +475,8 @@ function apply(ctx, config = {}) {
|
|
|
427
475
|
}
|
|
428
476
|
pendingCalls.set(event.data.callId, {
|
|
429
477
|
name: event.data.name,
|
|
430
|
-
arguments: event.data.arguments
|
|
478
|
+
arguments: event.data.arguments,
|
|
479
|
+
cwd: effectiveDirectory(ctx, session)
|
|
431
480
|
});
|
|
432
481
|
return;
|
|
433
482
|
}
|
|
@@ -437,17 +486,24 @@ function apply(ctx, config = {}) {
|
|
|
437
486
|
pendingCalls.delete(callId);
|
|
438
487
|
if (call === void 0) return;
|
|
439
488
|
if (event.data.error !== void 0 || toolResultFailed(event.data.message)) return;
|
|
440
|
-
const path = touchedPathOfToolCall(call.name, call.arguments);
|
|
489
|
+
const path = call.observedPath ?? touchedPathOfToolCall(call.name, call.arguments);
|
|
441
490
|
if (path === void 0) return;
|
|
442
491
|
const state = stateOf(session);
|
|
443
492
|
if (state.touched.size >= MAX_TOUCHED_PATHS) return;
|
|
444
|
-
state.touched.add(path);
|
|
493
|
+
if (isAbsolute(path)) state.touched.add(path);
|
|
494
|
+
else if (call.cwd !== void 0) state.touched.add(resolve(call.cwd, path));
|
|
445
495
|
});
|
|
446
496
|
ctx.inject(["fs"], (scope) => {
|
|
497
|
+
scope.on("fs/observed", (target, _observation, actor) => {
|
|
498
|
+
const exec = executions.getStore();
|
|
499
|
+
if (exec?.agent === void 0 || FILE_TOUCH_TOOL_NAMES[exec.name] !== true || actor !== exec) return;
|
|
500
|
+
const call = callsBySession.get(exec.agent.session)?.get(exec.callId);
|
|
501
|
+
if (call !== void 0) call.observedPath = scope.fs.processPath(target);
|
|
502
|
+
});
|
|
447
503
|
scope.on("agent/pre-step", async ({ agent, messages, signal }, next) => {
|
|
448
504
|
const decision = await next();
|
|
449
505
|
if (decision.kind !== "enter") return decision;
|
|
450
|
-
const seeded = await pending(scope, states, agent, config, maxBytes, signal);
|
|
506
|
+
const seeded = await pending(scope, states, agent, config, maxBytes, signal, decision.messages);
|
|
451
507
|
if (seeded === void 0) return decision;
|
|
452
508
|
signal.throwIfAborted();
|
|
453
509
|
const lastClaimed = decision.messages.findLastIndex((message) => messages.includes(message));
|
|
@@ -455,7 +511,7 @@ function apply(ctx, config = {}) {
|
|
|
455
511
|
...decision,
|
|
456
512
|
messages: decision.messages.toSpliced(lastClaimed + 1, 0, seeded)
|
|
457
513
|
};
|
|
458
|
-
});
|
|
514
|
+
}, { prepend: true });
|
|
459
515
|
});
|
|
460
516
|
}
|
|
461
517
|
/**
|
|
@@ -471,7 +527,7 @@ function apply(ctx, config = {}) {
|
|
|
471
527
|
* @param signal - the turn's cancellation signal.
|
|
472
528
|
* @returns the message to inject, or `undefined`.
|
|
473
529
|
*/
|
|
474
|
-
async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
530
|
+
async function pending(ctx, states, agent, config, maxBytes, signal, messages) {
|
|
475
531
|
const session = agent.session;
|
|
476
532
|
const state = states.get(session) ?? {
|
|
477
533
|
scopes: /* @__PURE__ */ new Map(),
|
|
@@ -481,9 +537,12 @@ async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
|
481
537
|
const evaluatedTouches = new Set(state.touched);
|
|
482
538
|
let retryTouches = false;
|
|
483
539
|
const scope = ctx.multiRootScope.resolve(ctx.sandboxPolicy.resolve({ session }));
|
|
484
|
-
const granted = new Set(scope.additionalRoots);
|
|
485
|
-
const revoked = [...new Set([...state.scopes.values()].map((entry) => entry.root))].filter((root) => !granted.has(root));
|
|
486
540
|
const rendered = [];
|
|
541
|
+
const nativeCopy = nativeInstructionCopies(messages, effectiveDirectory(ctx, session));
|
|
542
|
+
for (const [key, entry] of state.scopes) if (entry.nativePath !== void 0 && nativeCopy.withdraws(entry.nativePath)) state.scopes.set(key, {
|
|
543
|
+
...entry,
|
|
544
|
+
digest: void 0
|
|
545
|
+
});
|
|
487
546
|
const gone = [];
|
|
488
547
|
const updates = [];
|
|
489
548
|
if (scope.additionalRoots.length > 0) {
|
|
@@ -492,14 +551,29 @@ async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
|
492
551
|
let remaining = maxBytes;
|
|
493
552
|
for (const root of scope.additionalRoots) {
|
|
494
553
|
signal.throwIfAborted();
|
|
495
|
-
const plan = await planRoot(ctx, api, root, config, state,
|
|
554
|
+
const plan = await planRoot(ctx, api, root, config, state, signal);
|
|
496
555
|
gone.push(...plan.gone);
|
|
497
556
|
if (plan.deliveries.length === 0) continue;
|
|
498
557
|
if (remaining <= 0) {
|
|
499
558
|
retryTouches = true;
|
|
500
559
|
continue;
|
|
501
560
|
}
|
|
502
|
-
const
|
|
561
|
+
const deliveries = plan.deliveries.filter((entry) => {
|
|
562
|
+
const nativePath = nativeCopy.pathOf(entry.file);
|
|
563
|
+
if (nativePath === void 0) return true;
|
|
564
|
+
updates.push({
|
|
565
|
+
key: entry.key,
|
|
566
|
+
scope: {
|
|
567
|
+
root,
|
|
568
|
+
path: entry.file.absolutePath,
|
|
569
|
+
digest: digestOf(entry.file.content),
|
|
570
|
+
nativePath
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
return false;
|
|
574
|
+
});
|
|
575
|
+
if (deliveries.length === 0) continue;
|
|
576
|
+
const { text, omitted, truncated } = api.render(deliveries.map((entry) => entry.file), { maxBytes: remaining });
|
|
503
577
|
const omittedPaths = new Set(omitted.map((file) => file.absolutePath));
|
|
504
578
|
const truncatedPaths = new Set(truncated.map((file) => file.displayPath));
|
|
505
579
|
if (omitted.length > 0 || truncated.length > 0 || text === "") retryTouches = true;
|
|
@@ -509,7 +583,7 @@ async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
|
509
583
|
root,
|
|
510
584
|
text
|
|
511
585
|
});
|
|
512
|
-
for (const entry of
|
|
586
|
+
for (const entry of deliveries) {
|
|
513
587
|
if (omittedPaths.has(entry.file.absolutePath)) continue;
|
|
514
588
|
updates.push({
|
|
515
589
|
key: entry.key,
|
|
@@ -523,17 +597,20 @@ async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
|
523
597
|
}
|
|
524
598
|
}
|
|
525
599
|
}
|
|
526
|
-
const
|
|
600
|
+
const current = new Set(ctx.multiRootScope.resolve(ctx.sandboxPolicy.resolve({ session })).additionalRoots);
|
|
601
|
+
const revoked = [...new Set([...state.scopes.values()].map((entry) => entry.root))].filter((root) => !current.has(root));
|
|
602
|
+
const liveUpdates = updates.filter((entry) => current.has(entry.scope.root));
|
|
603
|
+
const text = composeInstructionMessage(rendered.filter((entry) => current.has(entry.root)), revoked, gone.filter((entry) => current.has(entry.scope.root)).map((entry) => entry.scope));
|
|
527
604
|
const message = text === void 0 ? void 0 : await createInstructionMessage({
|
|
528
605
|
text,
|
|
529
606
|
plugin: PLUGIN_SOURCE
|
|
530
607
|
});
|
|
531
608
|
signal.throwIfAborted();
|
|
532
609
|
if (!retryTouches) for (const touch of evaluatedTouches) state.touched.delete(touch);
|
|
533
|
-
if (text !== void 0) {
|
|
610
|
+
if (text !== void 0 || liveUpdates.length > 0) {
|
|
534
611
|
for (const root of revoked) for (const [key, entry] of state.scopes) if (entry.root === root) state.scopes.delete(key);
|
|
535
612
|
for (const entry of gone) state.scopes.delete(entry.key);
|
|
536
|
-
for (const entry of
|
|
613
|
+
for (const entry of liveUpdates) state.scopes.set(entry.key, entry.scope);
|
|
537
614
|
}
|
|
538
615
|
return message;
|
|
539
616
|
}
|
|
@@ -554,11 +631,10 @@ async function pending(ctx, states, agent, config, maxBytes, signal) {
|
|
|
554
631
|
* @param root - the canonical additional root.
|
|
555
632
|
* @param config - the row's configuration.
|
|
556
633
|
* @param state - the session's delivery state.
|
|
557
|
-
* @param session - the session, for the cwd a relative touch resolves against.
|
|
558
634
|
* @param signal - the turn's cancellation signal.
|
|
559
635
|
* @returns the files to send and the deliveries to withdraw.
|
|
560
636
|
*/
|
|
561
|
-
async function planRoot(ctx, api, root, config, state,
|
|
637
|
+
async function planRoot(ctx, api, root, config, state, signal) {
|
|
562
638
|
const delivered = /* @__PURE__ */ new Map();
|
|
563
639
|
for (const [key, entry] of state.scopes) if (entry.root === root) delivered.set(key, entry);
|
|
564
640
|
const dirs = /* @__PURE__ */ new Set([root]);
|
|
@@ -567,7 +643,7 @@ async function planRoot(ctx, api, root, config, state, session, signal) {
|
|
|
567
643
|
if (dir !== root) dirs.add(dir);
|
|
568
644
|
}
|
|
569
645
|
for (const touched of state.touched) {
|
|
570
|
-
const parent = parentDirectoryOf(touched
|
|
646
|
+
const parent = parentDirectoryOf(touched);
|
|
571
647
|
if (parent === void 0 || !isCanonicallyUnder(parent, root)) continue;
|
|
572
648
|
let dir = parent;
|
|
573
649
|
for (;;) {
|
|
@@ -678,16 +754,21 @@ async function loadDirectory(fs, api, root, config, signal, cwd) {
|
|
|
678
754
|
}
|
|
679
755
|
const files = [];
|
|
680
756
|
for (const candidate of candidates) {
|
|
757
|
+
if (isAbsolute(candidate.displayPath) || resolve(root, candidate.displayPath) !== resolve(candidate.absolutePath)) continue;
|
|
681
758
|
if (!isCanonicallyUnder(canonicalPath(candidate.absolutePath), root)) continue;
|
|
682
759
|
try {
|
|
683
760
|
const target = await fs.resolve(candidate.absolutePath);
|
|
761
|
+
const path = fs.processPath(target);
|
|
762
|
+
if (!isCanonicallyUnder(path, root)) continue;
|
|
684
763
|
const info = await fs.stat(target, signal);
|
|
685
764
|
if (info === void 0 || info.type !== "file") continue;
|
|
686
765
|
if (info.size !== void 0 && info.size > maxSourceBytes) continue;
|
|
766
|
+
const content = await fs.readText(target, signal);
|
|
767
|
+
if (canonicalPath(candidate.absolutePath) !== path || !isCanonicallyUnder(path, root)) continue;
|
|
687
768
|
files.push({
|
|
688
769
|
...candidate,
|
|
689
770
|
displayPath: candidate.absolutePath,
|
|
690
|
-
content
|
|
771
|
+
content
|
|
691
772
|
});
|
|
692
773
|
} catch {
|
|
693
774
|
continue;
|
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-D19jRxN0.js";
|
|
2
2
|
export { DEFAULT_MAX_BYTES, DEFAULT_MAX_SOURCE_BYTES, PLUGIN_SOURCE, apply, composeInstructionMessage, inject, touchedPathOfToolCall };
|
package/lib/lsp.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { t as aroundTool } from "./tool-context-CpgIFcCB.js";
|
|
2
|
+
import { t as routeWorkspacePath } from "./workspace-routing-YPxaQ4V3.js";
|
|
3
|
+
import { t as wrapMethod } from "./method-wrapper-CFY3p3j2.js";
|
|
4
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
+
//#region src/lsp.ts
|
|
6
|
+
const inject = [
|
|
7
|
+
"multiRootCompat",
|
|
8
|
+
"multiRootProviders",
|
|
9
|
+
"multiRootScope"
|
|
10
|
+
];
|
|
11
|
+
function apply(ctx) {
|
|
12
|
+
const callers = new AsyncLocalStorage();
|
|
13
|
+
aroundTool(ctx, (exec, next) => exec.agent === void 0 ? next() : callers.run(exec.agent.session, next));
|
|
14
|
+
ctx.inject(["lsp", "fs"], (scope) => {
|
|
15
|
+
const service = scope.get("lsp");
|
|
16
|
+
scope.effect(() => wrapMethod(service, "query", (original) => async function(request, signal) {
|
|
17
|
+
const session = callers.getStore();
|
|
18
|
+
const primary = session === void 0 ? request.workspaceRoot : session.header.cwd ?? scope.get("sandboxPolicy")?.resolve({ session }).workspaceRoot;
|
|
19
|
+
if (primary === void 0) throw new Error("multi-root workspace: LSP caller has no session origin or deployment policy");
|
|
20
|
+
if (scope.multiRootScope.scopeOf(primary).length === 0 && session === void 0) return original.call(this, request, signal);
|
|
21
|
+
const route = await routeWorkspacePath(scope, primary, request.filePath, signal, request.workspaceRoot);
|
|
22
|
+
if (route === void 0) {
|
|
23
|
+
const target = await scope.fs.resolve(request.filePath, {
|
|
24
|
+
cwd: request.workspaceRoot,
|
|
25
|
+
...signal === void 0 ? {} : { signal }
|
|
26
|
+
});
|
|
27
|
+
return original.call(this, {
|
|
28
|
+
...request,
|
|
29
|
+
workspaceRoot: primary,
|
|
30
|
+
filePath: scope.fs.processPath(target)
|
|
31
|
+
}, 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);
|
|
39
|
+
}), "multi-root:lsp routing");
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { apply, inject };
|
|
@@ -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 };
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { t as wrapMethod } from "./method-wrapper-CFY3p3j2.js";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
//#region src/compat/process-result.ts
|
|
4
|
+
const object$1 = (value) => typeof value === "object" && value !== null;
|
|
5
|
+
const thenable = (value) => typeof value?.then === "function";
|
|
6
|
+
const textOf = (value) => typeof value === "string" ? value : object$1(value) && typeof value.text === "string" ? value.text : "";
|
|
7
|
+
const stderrOf = (value) => textOf(value.stderr) + (object$1(value.error) ? textOf(value.error.message) : "") + (object$1(value.failure) ? textOf(value.failure.message) : "");
|
|
8
|
+
const exitCodeOf = (value) => typeof value.exitCode === "number" || value.exitCode === null ? value.exitCode : value.ok === false || object$1(value.error) || object$1(value.failure) ? 1 : 0;
|
|
9
|
+
/** Denial and runner-failure verdicts for one settled process — the same
|
|
10
|
+
* non-zero-exit + stderr-signature rules the sandbox executors apply: a fatal
|
|
11
|
+
* runner line is an infrastructure failure, never a policy denial. */
|
|
12
|
+
const classifyOutcome = (exitCode, stderr, facts) => {
|
|
13
|
+
const nonzero = exitCode !== null && exitCode !== 0;
|
|
14
|
+
const lines = stderr.toLowerCase().split(/\r?\n/);
|
|
15
|
+
const runnerFailed = nonzero && facts.runnerFailureRules.some((rule) => (rule.allowedExitCodes === void 0 || rule.allowedExitCodes.includes(exitCode)) && lines.some((line) => !rule.informationalLines?.some((info) => info.toLowerCase() === line) && rule.fatalSignatures.some((signature) => line.includes(signature.toLowerCase()))));
|
|
16
|
+
return {
|
|
17
|
+
denied: nonzero && !runnerFailed && facts.denialSignatures.some((signature) => stderr.toLowerCase().includes(signature.toLowerCase())),
|
|
18
|
+
runnerFailed
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/** The `sandbox` stamp one settled outcome carries, merged over any stamp the
|
|
22
|
+
* confining executor already installed. */
|
|
23
|
+
const sandboxStamp = (value, facts, policy, stderr) => {
|
|
24
|
+
const { denied, runnerFailed } = classifyOutcome(exitCodeOf(value), stderr ?? stderrOf(value), facts);
|
|
25
|
+
return {
|
|
26
|
+
...object$1(value.sandbox) ? value.sandbox : {},
|
|
27
|
+
mode: policy.mode,
|
|
28
|
+
enforcement: facts.enforcement,
|
|
29
|
+
denied,
|
|
30
|
+
...runnerFailed ? { runnerFailed: true } : {}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
function stampProcessResult(value, facts, policy) {
|
|
34
|
+
if (!object$1(value)) return value;
|
|
35
|
+
return {
|
|
36
|
+
...value,
|
|
37
|
+
sandbox: sandboxStamp(value, facts, policy)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Whether a non-thenable, non-`result()` value is a live process handle
|
|
41
|
+
* rather than settled result data: it owns a `done` settle hook or callable
|
|
42
|
+
* members, or carries a shaped prototype. Copying it would freeze
|
|
43
|
+
* `status`/`exitCode` where consumers poll them and sever `readOutput`/`kill`
|
|
44
|
+
* identity — the model-facing `proc.sandbox` read happens on this very
|
|
45
|
+
* object, so the stamp must land in place.
|
|
46
|
+
*/
|
|
47
|
+
const liveHandle = (value) => thenable(value.done) || typeof value.done === "function" || Object.values(value).some((member) => typeof member === "function") || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null;
|
|
48
|
+
function decorateProcessOutcome(value, facts, policy, diagnostics) {
|
|
49
|
+
if (object$1(value) && typeof value.then === "function") return value.then((result) => decorateProcessOutcome(result, facts, policy, diagnostics));
|
|
50
|
+
if (object$1(value) && typeof value.result === "function") {
|
|
51
|
+
let cached;
|
|
52
|
+
let settled = false;
|
|
53
|
+
wrapMethod(value, "result", (original) => function(...args) {
|
|
54
|
+
if (!settled) {
|
|
55
|
+
cached = decorateProcessOutcome(original.apply(this, args), facts, policy, diagnostics);
|
|
56
|
+
settled = true;
|
|
57
|
+
}
|
|
58
|
+
return cached;
|
|
59
|
+
});
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
if (object$1(value) && liveHandle(value)) {
|
|
63
|
+
const settle = () => {
|
|
64
|
+
try {
|
|
65
|
+
value.sandbox = sandboxStamp(value, facts, policy, diagnostics?.stderr?.());
|
|
66
|
+
} catch {}
|
|
67
|
+
};
|
|
68
|
+
if (thenable(value.done)) {
|
|
69
|
+
value.done = value.done.then((outcome) => {
|
|
70
|
+
settle();
|
|
71
|
+
return decorateProcessOutcome(outcome, facts, policy, diagnostics);
|
|
72
|
+
}, (error) => {
|
|
73
|
+
settle();
|
|
74
|
+
throw error;
|
|
75
|
+
});
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
if (typeof value.done === "function") {
|
|
79
|
+
wrapMethod(value, "done", (original) => function(...args) {
|
|
80
|
+
const outcome = original.apply(this, args);
|
|
81
|
+
return thenable(outcome) ? outcome.then((resolved) => {
|
|
82
|
+
settle();
|
|
83
|
+
return decorateProcessOutcome(resolved, facts, policy, diagnostics);
|
|
84
|
+
}, (error) => {
|
|
85
|
+
settle();
|
|
86
|
+
throw error;
|
|
87
|
+
}) : (settle(), decorateProcessOutcome(outcome, facts, policy, diagnostics));
|
|
88
|
+
});
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
settle();
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
return stampProcessResult(value, facts, policy);
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/compat/process-entrypoints.ts
|
|
98
|
+
/**
|
|
99
|
+
* The public shell executor entries present on the mounted service, in this
|
|
100
|
+
* order: `execute`, `run`, `start` (`start` existed through 0.1.6).
|
|
101
|
+
* @param shell - the mounted `ctx.shell` service.
|
|
102
|
+
* @returns the present entries — a structural probe only.
|
|
103
|
+
*/
|
|
104
|
+
function shellEntrypoints(shell) {
|
|
105
|
+
const record = shell;
|
|
106
|
+
return [
|
|
107
|
+
"execute",
|
|
108
|
+
"run",
|
|
109
|
+
"start"
|
|
110
|
+
].filter((key) => typeof record[key] === "function");
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The PTC runtime's public entry: `['run']` when it is a function; never the
|
|
114
|
+
* concrete runtime's private `execute` helper.
|
|
115
|
+
* @param runtime - the mounted `ctx.ptcRuntime` service.
|
|
116
|
+
* @returns the present entries — a structural probe only.
|
|
117
|
+
*/
|
|
118
|
+
function ptcEntrypoints(runtime) {
|
|
119
|
+
return typeof runtime.run === "function" ? ["run"] : [];
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/process-fence.ts
|
|
123
|
+
/**
|
|
124
|
+
* `multi-root-process-fence`: the B9 seam for the one cell `ctx.sandbox.confine`
|
|
125
|
+
* never sees — `danger-full-access` with explicit `read-only` additional roots.
|
|
126
|
+
*
|
|
127
|
+
* Upstream, every confined consumer routes through `ctx.sandbox.confine`, which
|
|
128
|
+
* this bundle's provider already widens (grants, the read-only fixed-write
|
|
129
|
+
* graft, and the workspace-write deny edge). But the shell executor, the PTC
|
|
130
|
+
* runtime and the PTY backend all short-circuit that mode: `policy.mode ===
|
|
131
|
+
* 'danger-full-access'` returns the bare argv, so an explicit `read-only` root
|
|
132
|
+
* would silently stay writable. This row closes the gap without touching any
|
|
133
|
+
* upstream executor:
|
|
134
|
+
*
|
|
135
|
+
* - `ctx.subprocess.spawn` is wrapped to prepend a precomputed restricted
|
|
136
|
+
* profile whenever the AsyncLocalStorage below carries one. `spawn` is
|
|
137
|
+
* synchronous, so the profile — which never depends on the callee's argv —
|
|
138
|
+
* is built by the wrapping consumer, not here.
|
|
139
|
+
* - `ctx.shell.execute` (bash and pwsh alike, and `start` where an older
|
|
140
|
+
* release still exposes it — `compat/process-entrypoints.ts` owns which
|
|
141
|
+
* entries a mounted executor actually carries) resolves the per-call policy
|
|
142
|
+
* exactly the way the executor itself does, and — under Full-access with
|
|
143
|
+
* deny roots — asks the sandbox provider for the restricted prefix and runs
|
|
144
|
+
* the call inside the store, so every subprocess the executor launches is
|
|
145
|
+
* confined.
|
|
146
|
+
* - `ctx.ptcRuntime.run` does the same for `run_code`.
|
|
147
|
+
* - `ctx.subprocess.spawnTerminal` keys on the `DSH_PTY_SESSION_ID` marker:
|
|
148
|
+
* every supported `dsh-terminal-bash` backend stamps it (alongside
|
|
149
|
+
* `DSH_SESSION_ID`) when it launches an agent's PTY, and no other caller —
|
|
150
|
+
* above all the panel's terminal controller — ever sets it. A spec without
|
|
151
|
+
* the marker is a USER terminal, passed through untouched in every mode:
|
|
152
|
+
* the sandbox protects agent behavior, and upstream never confines the
|
|
153
|
+
* user's own terminal. Because that marker is the ONLY discriminator, the
|
|
154
|
+
* `multi-root-compat` gate asserts it at boot (`compat/pty-marker.ts`):
|
|
155
|
+
* an installed backend whose emitted code no longer stamps it fails the
|
|
156
|
+
* plugin load rather than silently reclassifying agent PTYs as the user's.
|
|
157
|
+
* `ctx.terminals` itself is deliberately NOT wrapped:
|
|
158
|
+
* upstream mounts it inside `optional-persistent-terminals` with
|
|
159
|
+
* `isolate: { terminals: true }`, so the registry entry is unreachable from
|
|
160
|
+
* this row — the shared `spawnTerminal` seam plus the env discriminator
|
|
161
|
+
* covers both the un-isolated SDK mount and the isolated web mount.
|
|
162
|
+
*
|
|
163
|
+
* The same seam carries the unknown-authority downgrade: while the scope
|
|
164
|
+
* reports `authority: 'unavailable'` — a contended, storage-failed or
|
|
165
|
+
* config-invalid registry publishes an empty deny set that is NOT evidence —
|
|
166
|
+
* `danger-full-access` executions run inside a primary-root-only
|
|
167
|
+
* profile (with the deny set applied) instead of ambient.
|
|
168
|
+
*
|
|
169
|
+
* Windows uses the standalone ambient deny-token runner. Landlock cannot subtract a subtree, so that combination selects bubblewrap.
|
|
170
|
+
* An unusable mount runner fails without starting an unconfined process.
|
|
171
|
+
*
|
|
172
|
+
* @module @dsh-electron/dsh-plugin-multi-root-workspace/process-fence
|
|
173
|
+
*/
|
|
174
|
+
const inject = [
|
|
175
|
+
"multiRootCompat",
|
|
176
|
+
"multiRootProviders",
|
|
177
|
+
"multiRootScope",
|
|
178
|
+
"sandbox",
|
|
179
|
+
"sandboxPolicy"
|
|
180
|
+
];
|
|
181
|
+
const processDenyStore = new AsyncLocalStorage();
|
|
182
|
+
/** Whether a value is a thenable, i.e. whether the installed `confine` is async. */
|
|
183
|
+
function isThenable(value) {
|
|
184
|
+
return typeof value?.then === "function";
|
|
185
|
+
}
|
|
186
|
+
const object = (value) => typeof value === "object" && value !== null;
|
|
187
|
+
function apply(ctx) {
|
|
188
|
+
const policyOf = (spec) => spec?.sandboxPolicy ?? ctx.sandboxPolicy.resolve();
|
|
189
|
+
/**
|
|
190
|
+
* The confined facts for one Full-access call, or `undefined` when the call
|
|
191
|
+
* needs no confinement (not full-access, and nothing to deny while the
|
|
192
|
+
* registry is the store's authority). An `unavailable` scope authority
|
|
193
|
+
* clamps the call to a primary-root-only profile: the empty deny
|
|
194
|
+
* set a contended or failed registry publishes is not evidence that nothing
|
|
195
|
+
* is restricted. May throw synchronously — `SandboxUnavailableError` from a
|
|
196
|
+
* dialect that cannot express the confinement, which must propagate to the
|
|
197
|
+
* caller, never be swallowed.
|
|
198
|
+
*/
|
|
199
|
+
const prepare = (policy, signal) => {
|
|
200
|
+
if (policy.mode !== "danger-full-access") return void 0;
|
|
201
|
+
const scope = ctx.multiRootScope.resolve(policy);
|
|
202
|
+
if (scope.authority === "unavailable") return ctx.sandbox.clampedExecution(policy, scope.deniedRoots, signal);
|
|
203
|
+
if (scope.deniedRoots.length === 0) return void 0;
|
|
204
|
+
return ctx.sandbox.restrictedExecution(policy, scope.deniedRoots, signal, scope.protectedHome);
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Run `body` under the restricted deny context when `prepared` is a prefix —
|
|
208
|
+
* preserving the sync/async shape of the prepared value itself.
|
|
209
|
+
*/
|
|
210
|
+
const runDenied = (prepared, policy, body) => {
|
|
211
|
+
const run = (facts) => {
|
|
212
|
+
const store = { argvPrefix: facts.argv };
|
|
213
|
+
return processDenyStore.run(store, () => decorateProcessOutcome(body(), facts, policy, { stderr: () => store.stderr?.() }));
|
|
214
|
+
};
|
|
215
|
+
return isThenable(prepared) ? prepared.then(run) : run(prepared);
|
|
216
|
+
};
|
|
217
|
+
ctx.inject(["subprocess"], (scope) => {
|
|
218
|
+
scope.effect(() => wrapMethod(scope.subprocess, "spawn", (original) => function(spec) {
|
|
219
|
+
const store = processDenyStore.getStore();
|
|
220
|
+
if (store === void 0) return original.call(this, spec);
|
|
221
|
+
const handle = original.call(this, {
|
|
222
|
+
...spec,
|
|
223
|
+
argv: [...store.argvPrefix, ...spec.argv]
|
|
224
|
+
});
|
|
225
|
+
const stderr = object(handle) && object(handle.collected) && object(handle.collected.stderr) && typeof handle.collected.stderr.readFrom === "function" ? handle.collected.stderr : void 0;
|
|
226
|
+
if (stderr !== void 0) store.stderr = () => {
|
|
227
|
+
try {
|
|
228
|
+
return stderr.readFrom(0).text;
|
|
229
|
+
} catch {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
return handle;
|
|
234
|
+
}));
|
|
235
|
+
scope.effect(() => wrapMethod(scope.subprocess, "spawnTerminal", (original) => async function(spec) {
|
|
236
|
+
const ptySessionId = spec.env?.DSH_PTY_SESSION_ID;
|
|
237
|
+
if (ptySessionId === void 0 || ptySessionId === "") return await original.call(this, spec);
|
|
238
|
+
const sessionId = spec.env?.DSH_SESSION_ID;
|
|
239
|
+
const session = sessionId === void 0 || sessionId === "" ? void 0 : ctx.get("sessions")?.get(sessionId);
|
|
240
|
+
if (session === void 0) {
|
|
241
|
+
if (!ctx.multiRootScope.hasActiveDenyRoots()) return await original.call(this, spec);
|
|
242
|
+
throw new Error(`multi-root workspace: agent terminal spawn carries a session marker that does not resolve to a live session (${JSON.stringify(sessionId ?? ptySessionId)}), and explicit read-only roots are or may be registered — refusing to spawn an unconfined terminal`);
|
|
243
|
+
}
|
|
244
|
+
const policy = ctx.sandboxPolicy.resolve({ session });
|
|
245
|
+
const prepared = prepare(policy, spec.signal);
|
|
246
|
+
if (prepared === void 0) return await original.call(this, spec);
|
|
247
|
+
const argvPrefix = (await prepared).argv;
|
|
248
|
+
return await original.call(this, {
|
|
249
|
+
...spec,
|
|
250
|
+
argv: [...argvPrefix, ...spec.argv]
|
|
251
|
+
});
|
|
252
|
+
}));
|
|
253
|
+
});
|
|
254
|
+
/**
|
|
255
|
+
* The wrapper every execute-style consumer entry shares: resolve the policy
|
|
256
|
+
* the way the upstream consumer does, and when the call runs ambient under
|
|
257
|
+
* Full-access with roots to deny, execute it inside the restricted store so
|
|
258
|
+
* every subprocess it launches is confined.
|
|
259
|
+
*/
|
|
260
|
+
const deniedEntry = (scope, target, key) => {
|
|
261
|
+
scope.effect(() => wrapMethod(target, key, (original) => function(spec, ...rest) {
|
|
262
|
+
const policy = policyOf(spec);
|
|
263
|
+
const prepared = prepare(policy, spec?.signal);
|
|
264
|
+
if (prepared === void 0) return original.call(this, spec, ...rest);
|
|
265
|
+
return runDenied(prepared, policy, () => original.call(this, spec, ...rest));
|
|
266
|
+
}));
|
|
267
|
+
};
|
|
268
|
+
ctx.inject(["shell"], (scope) => {
|
|
269
|
+
const shell = scope.get("shell");
|
|
270
|
+
if (shell === void 0) return;
|
|
271
|
+
for (const key of shellEntrypoints(shell)) deniedEntry(scope, shell, key);
|
|
272
|
+
});
|
|
273
|
+
ctx.inject(["ptcRuntime"], (scope) => {
|
|
274
|
+
const runtime = scope.get("ptcRuntime");
|
|
275
|
+
if (runtime === void 0) return;
|
|
276
|
+
for (const key of ptcEntrypoints(runtime)) deniedEntry(scope, runtime, key);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
export { apply, inject };
|