windows-development-sandbox 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.example.json +2 -1
- package/dist/cli/commands/launch/launch.js +2 -0
- package/dist/cli/commands/vpn.js +1 -0
- package/dist/cli/commands/web.d.ts +5 -0
- package/dist/cli/commands/web.js +38 -0
- package/dist/core/config/defaults.js +1 -1
- package/dist/core/schema/config.d.ts +1 -0
- package/dist/core/schema/vpn.js +1 -1
- package/dist/core/schema/web.d.ts +1 -0
- package/dist/core/schema/web.js +4 -1
- package/dist/guest/boot/boot.js +3 -1
- package/dist/guest/governor/decide.d.ts +11 -1
- package/dist/guest/governor/decide.js +30 -1
- package/dist/guest/governor/governor.d.ts +3 -0
- package/dist/guest/governor/governor.js +18 -2
- package/dist/guest/network/firewall.d.ts +1 -0
- package/dist/guest/network/firewall.js +65 -23
- package/dist/guest/runtime/process.js +53 -5
- package/dist/guest/setup/claude-mem.js +12 -4
- package/dist/guest/toolchains/languages/node.js +29 -3
- package/dist/host/life/host-memory.d.ts +1 -0
- package/dist/host/life/host-memory.js +4 -1
- package/dist/host/life/watchdog.d.ts +2 -0
- package/dist/host/life/watchdog.js +19 -3
- package/dist/runtime/agent.js +14 -10
- package/dist/runtime/daemon.js +861 -711
- package/dist/runtime/db.js +14 -10
- package/dist/runtime/main.js +159 -41
- package/dist/runtime/netproxy.js +4 -3
- package/dist/runtime/view.js +4 -3
- package/dist/selftest/guest-boot.test.js +47 -1
- package/dist/selftest/heavy-load.test.js +27 -1
- package/dist/selftest/network.test.js +20 -1
- package/dist/selftest/support/fixtures.d.ts +1 -0
- package/dist/shared/io/copy-tree.d.ts +7 -0
- package/dist/shared/io/copy-tree.js +45 -0
- package/dist/shared/io/index.d.ts +2 -0
- package/dist/shared/io/index.js +2 -0
- package/dist/shared/io/robocopy-result.d.ts +6 -0
- package/dist/shared/io/robocopy-result.js +23 -0
- package/dist/shared/memory/policy.d.ts +5 -0
- package/dist/shared/memory/policy.js +8 -0
- package/dist/shared/network/firewall-rules.d.ts +8 -0
- package/dist/shared/network/firewall-rules.js +28 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/MemoryStatus.cs +128 -107
- package/native/scripts/memory-status.ps1 +10 -2
- package/package.json +1 -1
- package/sandbox/csharp/MemGov.cs +466 -398
- package/sandbox/scripts/new-shortcuts.ps1 +3 -1
- package/schemas/config.schema.json +6 -2
|
@@ -10,6 +10,7 @@ export declare const HostMemorySchema: z.ZodObject<{
|
|
|
10
10
|
fixed: "fixed";
|
|
11
11
|
}>>;
|
|
12
12
|
pageFileMaxMb: z.ZodCatch<z.ZodNumber>;
|
|
13
|
+
diskQueue: z.ZodCatch<z.ZodOptional<z.ZodNumber>>;
|
|
13
14
|
}, z.core.$strip>;
|
|
14
15
|
export type HostMemory = z.output<typeof HostMemorySchema>;
|
|
15
16
|
/** The parsed answer of memory-status, or null (not Windows, unreadable, nonsense). */
|
|
@@ -19,6 +19,8 @@ export const HostMemorySchema = z.object({
|
|
|
19
19
|
pageFile: z.enum(['auto', 'fixed', 'none']).catch('auto'),
|
|
20
20
|
/** Fixed: the total of its maximum sizes (MB). */
|
|
21
21
|
pageFileMaxMb: z.number().int().nonnegative().catch(0),
|
|
22
|
+
/** The disks' queue length now (all disks together); absent when this PC has no such counter. */
|
|
23
|
+
diskQueue: z.number().nonnegative().max(100000).optional().catch(undefined),
|
|
22
24
|
});
|
|
23
25
|
const TIMEOUT_MS = 20000;
|
|
24
26
|
/** The parsed answer of memory-status, or null (not Windows, unreadable, nonsense). */
|
|
@@ -91,7 +93,8 @@ export function hostMemoryLine(memory, at = new Date()) {
|
|
|
91
93
|
'/' +
|
|
92
94
|
memory.commitLimitMb +
|
|
93
95
|
' | page file ' +
|
|
94
|
-
memory.pageFile
|
|
96
|
+
memory.pageFile +
|
|
97
|
+
(memory.diskQueue === undefined ? '' : ' | disk queue ' + memory.diskQueue));
|
|
95
98
|
}
|
|
96
99
|
/**
|
|
97
100
|
* Whether Windows Sandbox could push this PC past its commit limit (pure): the paging file is fixed or off and the
|
|
@@ -6,6 +6,8 @@ export interface WatchdogState {
|
|
|
6
6
|
readonly calm: number;
|
|
7
7
|
/** Seconds the CPU has been above the limit. */
|
|
8
8
|
readonly cpuHighSeconds: number;
|
|
9
|
+
/** Seconds the disk queue has been above the limit. */
|
|
10
|
+
readonly diskHighSeconds: number;
|
|
9
11
|
/** Time (ms) the last request went out. */
|
|
10
12
|
readonly lastSentAt: number;
|
|
11
13
|
}
|
|
@@ -3,7 +3,13 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { HOST_THRESHOLDS } from '../../shared/memory/index.js';
|
|
5
5
|
import { hostMemoryLine } from './host-memory.js';
|
|
6
|
-
export const WATCHDOG_START = {
|
|
6
|
+
export const WATCHDOG_START = {
|
|
7
|
+
low: false,
|
|
8
|
+
calm: 0,
|
|
9
|
+
cpuHighSeconds: 0,
|
|
10
|
+
diskHighSeconds: 0,
|
|
11
|
+
lastSentAt: 0,
|
|
12
|
+
};
|
|
7
13
|
/** The request is repeated this often while the PC stays low, and each one lasts a bit longer than that. */
|
|
8
14
|
export const RESEND_MS = 30000;
|
|
9
15
|
export const REQUEST_SECONDS = 90;
|
|
@@ -30,6 +36,10 @@ export function watchdogStep(prev, input) {
|
|
|
30
36
|
const cpuHigh = input.cpuPercent !== null && input.cpuPercent >= t.cpuPercent ? prev.cpuHighSeconds + input.intervalSeconds : 0;
|
|
31
37
|
if (!reason && cpuHigh >= t.cpuSeconds)
|
|
32
38
|
reason = "this PC's CPU has been above " + t.cpuPercent + '% for ' + cpuHigh + ' seconds';
|
|
39
|
+
const diskQueue = input.memory?.diskQueue;
|
|
40
|
+
const diskHigh = diskQueue !== undefined && diskQueue >= t.diskQueue ? prev.diskHighSeconds + input.intervalSeconds : 0;
|
|
41
|
+
if (!reason && diskHigh >= t.diskSeconds)
|
|
42
|
+
reason = "this PC's disks have had a queue of " + diskQueue + ' for ' + diskHigh + ' seconds';
|
|
33
43
|
const calmNow = input.memory ? lowReason(input.memory, input.reserveHostMb, t, 1.25) === '' : true;
|
|
34
44
|
let low = prev.low;
|
|
35
45
|
let calm = prev.calm;
|
|
@@ -38,7 +48,7 @@ export function watchdogStep(prev, input) {
|
|
|
38
48
|
calm = 0;
|
|
39
49
|
}
|
|
40
50
|
else if (prev.low) {
|
|
41
|
-
calm = calmNow && cpuHigh === 0 ? prev.calm + 1 : 0;
|
|
51
|
+
calm = calmNow && cpuHigh === 0 && diskHigh === 0 ? prev.calm + 1 : 0;
|
|
42
52
|
if (calm >= t.calmSamples) {
|
|
43
53
|
low = false;
|
|
44
54
|
calm = 0;
|
|
@@ -46,7 +56,13 @@ export function watchdogStep(prev, input) {
|
|
|
46
56
|
}
|
|
47
57
|
const send = low && input.nowMs - prev.lastSentAt >= RESEND_MS;
|
|
48
58
|
return {
|
|
49
|
-
state: {
|
|
59
|
+
state: {
|
|
60
|
+
low,
|
|
61
|
+
calm,
|
|
62
|
+
cpuHighSeconds: cpuHigh,
|
|
63
|
+
diskHighSeconds: diskHigh,
|
|
64
|
+
lastSentAt: send ? input.nowMs : prev.lastSentAt,
|
|
65
|
+
},
|
|
50
66
|
send,
|
|
51
67
|
reason: reason || (low ? 'this PC is still low' : ''),
|
|
52
68
|
changed: low !== prev.low,
|
package/dist/runtime/agent.js
CHANGED
|
@@ -26562,16 +26562,17 @@ var ResumeSchema = external_exports.strictObject({
|
|
|
26562
26562
|
// src/core/schema/web.ts
|
|
26563
26563
|
var WebSchema = external_exports.strictObject({
|
|
26564
26564
|
enabled: external_exports.boolean().describe(
|
|
26565
|
-
"(Beta)
|
|
26565
|
+
"(Beta) The web UI: your sandbox sessions in a browser on this PC (http://127.0.0.1:<port>, this PC only). On: every sandbox start also starts it in the background (it keeps running until sandbox web stop or a restart of the PC). Off: only sandbox web start runs it. Open it signed in with sandbox web open."
|
|
26566
26566
|
),
|
|
26567
|
-
port: external_exports.number().int().min(1024).max(65535).describe("Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken.")
|
|
26567
|
+
port: external_exports.number().int().min(1024).max(65535).describe("Port of the web UI on 127.0.0.1 (this PC only). Pick another when it is taken."),
|
|
26568
|
+
openOnLaunch: external_exports.boolean().describe("(Beta) With the web UI on: open it in your browser, already signed in, every time a sandbox starts.")
|
|
26568
26569
|
});
|
|
26569
26570
|
|
|
26570
26571
|
// src/core/schema/vpn.ts
|
|
26571
26572
|
var VPN_PROVIDERS = ["nordvpn", "openvpn-file", "wireguard-file"];
|
|
26572
26573
|
var VpnSchema = external_exports.strictObject({
|
|
26573
26574
|
enabled: external_exports.boolean().describe(
|
|
26574
|
-
"Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
|
|
26575
|
+
"(Alpha: not yet tried on a real PC) Send the sandbox's traffic through a VPN. Only the sandbox: your PC's own connection is untouched. Needs a saved login first (sandbox vpn login). The agent in the sandbox can read that login and can turn the tunnel off (it is the administrator there)."
|
|
26575
26576
|
),
|
|
26576
26577
|
provider: external_exports.enum(VPN_PROVIDERS).describe(
|
|
26577
26578
|
"nordvpn: a recommended NordVPN server is picked at every launch. openvpn-file: your own .ovpn file (configFile). wireguard-file: your own WireGuard .conf (configFile), e.g. from your company."
|
|
@@ -27359,12 +27360,6 @@ var githubAssetFromPage = async (repo, pattern, searchOlder) => {
|
|
|
27359
27360
|
};
|
|
27360
27361
|
|
|
27361
27362
|
// src/guest/runtime/process.ts
|
|
27362
|
-
function exec(file2, args, options = {}) {
|
|
27363
|
-
const result = spawnSync(file2, args, { stdio: "inherit", windowsHide: true, ...options });
|
|
27364
|
-
if (result.error) throw result.error;
|
|
27365
|
-
if (result.status !== 0)
|
|
27366
|
-
throw new Error(path11.basename(file2) + " " + args.slice(0, 3).join(" ") + " failed with exit code " + result.status);
|
|
27367
|
-
}
|
|
27368
27363
|
async function execAsync(file2, args, options = {}) {
|
|
27369
27364
|
const code = await spawnAsync(file2, args, { stdio: "inherit", ...options });
|
|
27370
27365
|
if (code !== 0)
|
|
@@ -27375,7 +27370,16 @@ function execOutput(file2, args, options = {}) {
|
|
|
27375
27370
|
return result.status === 0 ? String(result.stdout ?? "").trim() : "";
|
|
27376
27371
|
}
|
|
27377
27372
|
function runScript(name, args = []) {
|
|
27378
|
-
|
|
27373
|
+
const result = spawnSync(SYSTEM.powershell(), scriptArgs(name, args), {
|
|
27374
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
27375
|
+
encoding: "utf8",
|
|
27376
|
+
windowsHide: true
|
|
27377
|
+
});
|
|
27378
|
+
if (result.error) throw result.error;
|
|
27379
|
+
const errors = String(result.stderr ?? "").trim();
|
|
27380
|
+
if (errors) process.stderr.write(errors + "\n");
|
|
27381
|
+
if (result.status !== 0)
|
|
27382
|
+
throw new Error(name + " failed with exit code " + result.status + (errors ? ": " + errors.slice(0, 400) : ""));
|
|
27379
27383
|
}
|
|
27380
27384
|
function runScriptWithJson(name, param, data, args = []) {
|
|
27381
27385
|
const dir = fs10.mkdtempSync(path11.join(os3.tmpdir(), "sbx-"));
|