windows-development-sandbox 1.15.0 → 1.17.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 +6 -0
- package/dist/app/features/access/access.run.js +1 -1
- package/dist/app/features/accounts/accounts.def.js +4 -3
- package/dist/app/features/defs.d.ts +3 -1
- package/dist/app/features/defs.js +26 -12
- package/dist/app/features/sandbox/sandbox.def.js +9 -5
- package/dist/app/features/sessions/sessions.def.js +1 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-HTQT5SBY.js → chunk-QLGGAG3D.js} +98 -79
- package/dist/bin/{chunk-D7CM63BS.js → chunk-REE3EMHD.js} +105 -41
- package/dist/bin/{chunk-RQ4BWBYX.js → chunk-XYUVIVJT.js} +1 -1
- package/dist/bin/claude-host.js +2 -2
- package/dist/bin/claude-sbx.js +2 -2
- package/dist/bin/codex-sbx.js +2 -2
- package/dist/bin/gemini-sbx.js +2 -2
- package/dist/bin/sandbox.js +2 -2
- package/dist/bin/sbx-hide.js +2 -2
- package/dist/bin/sbx-show.js +2 -2
- package/dist/cli/commands/web.js +1 -1
- package/dist/cli/index.js +4 -1
- package/dist/cli/report.d.ts +7 -0
- package/dist/cli/report.js +31 -0
- package/dist/core/config/defaults.js +1 -0
- package/dist/core/detect/toolchains.d.ts +1 -0
- package/dist/core/detect/toolchains.js +7 -0
- package/dist/core/schema/config.d.ts +21 -0
- package/dist/core/schema/sandbox.js +1 -1
- package/dist/core/schema/toolchains.d.ts +6 -0
- package/dist/core/schema/toolchains.js +10 -0
- package/dist/guest/boot/boot.js +2 -0
- package/dist/guest/setup/browser-gpu.d.ts +1 -0
- package/dist/guest/setup/browser-gpu.js +18 -0
- package/dist/guest/toolchains/native/rust-extras.js +3 -1
- package/dist/guest/toolchains/native/unreal.d.ts +9 -0
- package/dist/guest/toolchains/native/unreal.js +186 -0
- package/dist/guest/toolchains/native/vcruntime.d.ts +3 -0
- package/dist/guest/toolchains/native/vcruntime.js +2 -2
- package/dist/guest/toolchains/plan.js +10 -2
- package/dist/host/engines/hcs/live-folders.js +1 -1
- package/dist/host/github/token.js +1 -1
- package/dist/host/profile/accounts.js +1 -1
- package/dist/host/profile/agent-accounts.js +1 -1
- package/dist/host/profile/plugin-share.d.ts +5 -0
- package/dist/host/profile/plugin-share.js +22 -1
- package/dist/host/secrets/secret-store.d.ts +3 -3
- package/dist/host/secrets/secret-store.js +37 -10
- package/dist/host/vpn/login.js +1 -1
- package/dist/runtime/agent.js +16 -1
- package/dist/runtime/daemon.js +522 -337
- package/dist/runtime/db.js +17 -1
- package/dist/runtime/main.js +669 -472
- package/dist/runtime/netproxy.js +16 -1
- package/dist/runtime/view.js +16 -1
- package/dist/selftest/accounts.test.js +29 -0
- package/dist/selftest/app.test.js +2 -2
- package/dist/selftest/detect.test.js +7 -0
- package/dist/selftest/live-network.test.js +5 -0
- package/dist/selftest/support/fixtures.d.ts +6 -0
- package/dist/shared/channel/schema.d.ts +18 -0
- package/dist/web/index.html +2 -2
- package/dist/web/main-JTH3FT4O.js +221 -0
- package/dist/web/{main-UAQPI5XD.css → main-XT7T6ODM.css} +1 -1
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +6 -1
- package/native/csharp/HostTools/Protect.cs +41 -0
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/package.json +1 -1
- package/schemas/config.schema.json +34 -1
- package/schemas/sandbox-config.schema.json +34 -1
- package/dist/web/main-7DJZ2M27.js +0 -221
package/dist/runtime/netproxy.js
CHANGED
|
@@ -25515,7 +25515,7 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
25515
25515
|
"When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
|
|
25516
25516
|
),
|
|
25517
25517
|
vGpu: external_exports.boolean().describe(
|
|
25518
|
-
"Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
|
|
25518
|
+
"Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it). Browsers in the sandbox never use it (they draw in software)."
|
|
25519
25519
|
),
|
|
25520
25520
|
networking: external_exports.boolean().describe("Internet access. false is the only hard network isolation Windows Sandbox offers."),
|
|
25521
25521
|
clipboard: external_exports.boolean().describe(
|
|
@@ -25677,6 +25677,21 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
25677
25677
|
msvcVersion: external_exports.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
|
|
25678
25678
|
sdkVersion: external_exports.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".')
|
|
25679
25679
|
}),
|
|
25680
|
+
unreal: external_exports.strictObject({
|
|
25681
|
+
enabled: enabled(
|
|
25682
|
+
"Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. A real installer: it runs every boot (~10 GB on the sandbox disk). The engine itself comes from the Epic Games Launcher or its source.",
|
|
25683
|
+
"a .uproject or .uplugin"
|
|
25684
|
+
),
|
|
25685
|
+
acceptLicense: external_exports.boolean().describe(
|
|
25686
|
+
"Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence."
|
|
25687
|
+
),
|
|
25688
|
+
components: StringsSchema.describe(
|
|
25689
|
+
'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
|
|
25690
|
+
),
|
|
25691
|
+
keepInstallFiles: external_exports.boolean().describe(
|
|
25692
|
+
"Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room."
|
|
25693
|
+
)
|
|
25694
|
+
}),
|
|
25680
25695
|
cpp: external_exports.strictObject({
|
|
25681
25696
|
enabled: enabled(
|
|
25682
25697
|
"MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).",
|
package/dist/runtime/view.js
CHANGED
|
@@ -26090,7 +26090,7 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
26090
26090
|
"When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
|
|
26091
26091
|
),
|
|
26092
26092
|
vGpu: external_exports.boolean().describe(
|
|
26093
|
-
"Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
|
|
26093
|
+
"Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it). Browsers in the sandbox never use it (they draw in software)."
|
|
26094
26094
|
),
|
|
26095
26095
|
networking: external_exports.boolean().describe("Internet access. false is the only hard network isolation Windows Sandbox offers."),
|
|
26096
26096
|
clipboard: external_exports.boolean().describe(
|
|
@@ -26252,6 +26252,21 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
26252
26252
|
msvcVersion: external_exports.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
|
|
26253
26253
|
sdkVersion: external_exports.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".')
|
|
26254
26254
|
}),
|
|
26255
|
+
unreal: external_exports.strictObject({
|
|
26256
|
+
enabled: enabled(
|
|
26257
|
+
"Unreal Engine development: Visual Studio Community 2022 with the C++ game workload (MSVC, a Windows 11 SDK, .NET Framework targeting packs, Unreal integration and the Epic Games Launcher) and the DirectX End-User Runtime. A real installer: it runs every boot (~10 GB on the sandbox disk). The engine itself comes from the Epic Games Launcher or its source.",
|
|
26258
|
+
"a .uproject or .uplugin"
|
|
26259
|
+
),
|
|
26260
|
+
acceptLicense: external_exports.boolean().describe(
|
|
26261
|
+
"Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence."
|
|
26262
|
+
),
|
|
26263
|
+
components: StringsSchema.describe(
|
|
26264
|
+
'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
|
|
26265
|
+
),
|
|
26266
|
+
keepInstallFiles: external_exports.boolean().describe(
|
|
26267
|
+
"Keep an offline copy of the Visual Studio install files in tools\\visualstudio (~10 GB, made once), so later boots install without downloading them again. Skipped while that disk has too little room."
|
|
26268
|
+
)
|
|
26269
|
+
}),
|
|
26255
26270
|
cpp: external_exports.strictObject({
|
|
26256
26271
|
enabled: enabled(
|
|
26257
26272
|
"MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).",
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { AccountStore } from '../host/profile/index.js';
|
|
5
|
+
import { DEFAULTS } from '../core/config/index.js';
|
|
6
|
+
import { defaultAccount } from '../app/features/accounts/index.js';
|
|
7
|
+
import { MenuOperations } from '../cli/menu/io-menu.js';
|
|
5
8
|
export const accountsSuite = {
|
|
6
9
|
name: 'accounts',
|
|
7
10
|
title: 'Claude accounts (save, switch, remove, safe names)',
|
|
@@ -32,6 +35,25 @@ export const accountsSuite = {
|
|
|
32
35
|
stateAfter.other === 1 &&
|
|
33
36
|
new AccountStore(storage).activeFor(dataA) === 'work', 'switching swaps in the other credentials and account, keeps the rest of the sandbox state, and marks it active');
|
|
34
37
|
t.includes(JSON.stringify(new AccountStore(storage).read('personal')?.credentials), 'personal-2', "the outgoing account's refreshed tokens are saved back before switching");
|
|
38
|
+
t.section('make default, as the menu runs it');
|
|
39
|
+
const menuCtx = {
|
|
40
|
+
packageRoot: t.dir('acct-menu', 'package'),
|
|
41
|
+
options: {},
|
|
42
|
+
loaded: { config: structuredClone(DEFAULTS), configPath: null, base: t.temp },
|
|
43
|
+
storageRoot: storage,
|
|
44
|
+
dataPath: dataA,
|
|
45
|
+
};
|
|
46
|
+
let said;
|
|
47
|
+
let error = null;
|
|
48
|
+
try {
|
|
49
|
+
said = await new MenuOperations({}, menuCtx).run(defaultAccount, { agent: 'claude', name: 'personal', noRestart: false }, []);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
error = e;
|
|
53
|
+
}
|
|
54
|
+
t.check(error === null &&
|
|
55
|
+
new AccountStore(storage).defaultName() === 'personal' &&
|
|
56
|
+
new AccountStore(storage).activeFor(dataA) === 'personal', 'make default from the menu sets the default and switches the sandbox to it', String(error instanceof Error ? error.stack : (error ?? said)));
|
|
35
57
|
t.section('sharing plugins between data sets');
|
|
36
58
|
const plugA = path.join(storage, 'data', 'p1', 'state', 'claude');
|
|
37
59
|
const plugB = path.join(storage, 'data', 'p2', 'state', 'claude');
|
|
@@ -57,6 +79,13 @@ export const accountsSuite = {
|
|
|
57
79
|
settingsB.enabledPlugins['p@m'] === true &&
|
|
58
80
|
settingsB.enabledPlugins['q@m'] === false &&
|
|
59
81
|
!fs.existsSync(path.join(storage, 'accounts', 'shared-plugins', '.credentials.json')), 'on: plugins and enabledPlugins reach the other data set; its own settings win and no login travels');
|
|
82
|
+
const sentinel = path.join(storage, 'accounts', 'shared-plugins', 'plugins', 'cache', 'kept.js');
|
|
83
|
+
t.write(sentinel, 'k');
|
|
84
|
+
on.activate(dataP('p1'), 'one');
|
|
85
|
+
t.check(fs.existsSync(sentinel), 'switching with the same plugins does not copy the plugins folder again');
|
|
86
|
+
t.write(path.join(plugA, 'plugins', 'installed_plugins.json'), '{"version":2,"plugins":{"p@m":[]}}');
|
|
87
|
+
on.activate(dataP('p1'), 'one');
|
|
88
|
+
t.check(!fs.existsSync(sentinel), 'once a plugin changed, the switch refreshes the shared set');
|
|
60
89
|
t.write(path.join(plugC, 'plugins', 'installed_plugins.json'), '{}');
|
|
61
90
|
const outside = t.dir('plugin-victim');
|
|
62
91
|
t.write(path.join(outside, 'secret.txt'), 's');
|
|
@@ -319,9 +319,9 @@ export const appSuite = {
|
|
|
319
319
|
!sessionLines.some((l) => l.includes('--wide')), 'sessions on the command line: the table with the folder column (--wide), the marker and its note', sessionLines.join('\n'));
|
|
320
320
|
const statusLines = pageLines(statusPage);
|
|
321
321
|
t.check(statusLines.some((l) => /^State\s+\S/.test(l)) &&
|
|
322
|
-
statusLines.some((l) => /^Helper\s+
|
|
322
|
+
statusLines.some((l) => /^Helper\s+Responding$/.test(l)) &&
|
|
323
323
|
statusLines.includes('* api C:\\Projects\\api -> C:\\Projects\\api (started from here)') &&
|
|
324
|
-
statusLines.some((l) => l.startsWith('Repo guard 1 folder
|
|
324
|
+
statusLines.some((l) => l.startsWith('Repo guard Watching 1 folder.')), 'status on the command line: facts as rows, projects with their details, the repo guard', statusLines.join('\n'));
|
|
325
325
|
t.equal(pageLines(sessionsPage({ ...list, sessions: [] })).at(-1), 'No sessions. Start one with: sandbox claude', 'an empty page prints its command-line text');
|
|
326
326
|
const menu = menuView(sessions);
|
|
327
327
|
const chosen = menu.resolve({ kind: 'pick', value: 'new' });
|
|
@@ -66,6 +66,13 @@ export const detectSuite = {
|
|
|
66
66
|
t.check(fresh.python.on && fresh.dotnet.on && !fresh.go.on && fresh.python.reason.includes('this PC'), 'a folder that is no project yet gets the languages this PC has, and the reason names this PC');
|
|
67
67
|
const rusty = decideToolchains({ ...tc, python: { ...tc.python, enabled: true } }, ['Cargo.toml'], []);
|
|
68
68
|
t.check(rusty.rust.on && rusty.cpp.on && rusty.python.on && rusty.python.reason === 'enabled in config', 'Rust brings its C/C++ linker; true in config always wins');
|
|
69
|
+
const game = ['ZombieGame.uproject', 'Source/ZombieGame.Target.cs'];
|
|
70
|
+
const accepted = { ...tc, unreal: { ...tc.unreal, acceptLicense: true } };
|
|
71
|
+
t.check(decideToolchains(accepted, game, []).unreal.on &&
|
|
72
|
+
decideToolchains(accepted, ['Plugins/Kit.uplugin'], []).unreal.on &&
|
|
73
|
+
!decideToolchains(accepted, ['go.mod'], []).unreal.on, 'Unreal: "auto" follows a .uproject or .uplugin');
|
|
74
|
+
const unaccepted = decideToolchains(tc, game, []).unreal;
|
|
75
|
+
t.check(!unaccepted.on && unaccepted.reason.includes('toolchains.unreal.acceptLicense'), 'Unreal is not installed until its licence is accepted, and the reason says how');
|
|
69
76
|
const resolved = resolveToolchains(tc, goProject);
|
|
70
77
|
t.check(resolved.go.enabled === true && resolved.python.enabled === false, 'the sandbox gets plain decisions instead of "auto"');
|
|
71
78
|
t.section('optional tools: Bun, uv, VS Code');
|
|
@@ -122,6 +122,11 @@ export const liveNetworkSuite = {
|
|
|
122
122
|
typeof e.id === 'number' &&
|
|
123
123
|
typeof e.provider === 'string' &&
|
|
124
124
|
typeof e.process === 'string'), 'HostTools stop-events prints a JSON list of { at, id, provider, process }', events.stdout.slice(0, 500) + events.stderr);
|
|
125
|
+
const plain = Buffer.from('a saved login').toString('base64');
|
|
126
|
+
const sealed = spawnSync(hostTools, ['protect'], { encoding: 'utf8', input: plain });
|
|
127
|
+
const opened = spawnSync(hostTools, ['unprotect'], { encoding: 'utf8', input: sealed.stdout });
|
|
128
|
+
t.check(sealed.status === 0 && sealed.stdout !== plain && opened.status === 0 && opened.stdout === plain, 'HostTools protect and unprotect round-trip through DPAPI', sealed.stderr + opened.stderr);
|
|
129
|
+
t.equal(spawnSync(hostTools, ['unprotect'], { encoding: 'utf8', input: 'not base64!' }).status, 1, 'HostTools unprotect refuses bad input');
|
|
125
130
|
t.equal(spawnSync(hostTools, ['stop-events'], { encoding: 'utf8' }).status, 2, 'HostTools without --since prints its usage');
|
|
126
131
|
},
|
|
127
132
|
};
|
|
@@ -157,6 +157,12 @@ export declare function createFixtures(t: Harness): {
|
|
|
157
157
|
msvcVersion: string;
|
|
158
158
|
sdkVersion: string;
|
|
159
159
|
};
|
|
160
|
+
unreal: {
|
|
161
|
+
enabled: boolean | "auto";
|
|
162
|
+
acceptLicense: boolean;
|
|
163
|
+
components: string[];
|
|
164
|
+
keepInstallFiles: boolean;
|
|
165
|
+
};
|
|
160
166
|
cpp: {
|
|
161
167
|
enabled: boolean | "auto";
|
|
162
168
|
flexBison: boolean;
|
|
@@ -88,6 +88,12 @@ export declare const ProjectSpecSchema: z.ZodObject<{
|
|
|
88
88
|
msvcVersion: z.ZodString;
|
|
89
89
|
sdkVersion: z.ZodString;
|
|
90
90
|
}, z.core.$strict>;
|
|
91
|
+
unreal: z.ZodObject<{
|
|
92
|
+
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
93
|
+
acceptLicense: z.ZodBoolean;
|
|
94
|
+
components: z.ZodArray<z.ZodString>;
|
|
95
|
+
keepInstallFiles: z.ZodBoolean;
|
|
96
|
+
}, z.core.$strict>;
|
|
91
97
|
cpp: z.ZodObject<{
|
|
92
98
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
93
99
|
flexBison: z.ZodBoolean;
|
|
@@ -254,6 +260,12 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
254
260
|
msvcVersion: z.ZodString;
|
|
255
261
|
sdkVersion: z.ZodString;
|
|
256
262
|
}, z.core.$strict>;
|
|
263
|
+
unreal: z.ZodObject<{
|
|
264
|
+
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
265
|
+
acceptLicense: z.ZodBoolean;
|
|
266
|
+
components: z.ZodArray<z.ZodString>;
|
|
267
|
+
keepInstallFiles: z.ZodBoolean;
|
|
268
|
+
}, z.core.$strict>;
|
|
257
269
|
cpp: z.ZodObject<{
|
|
258
270
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
259
271
|
flexBison: z.ZodBoolean;
|
|
@@ -440,6 +452,12 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
440
452
|
msvcVersion: z.ZodString;
|
|
441
453
|
sdkVersion: z.ZodString;
|
|
442
454
|
}, z.core.$strict>;
|
|
455
|
+
unreal: z.ZodObject<{
|
|
456
|
+
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
457
|
+
acceptLicense: z.ZodBoolean;
|
|
458
|
+
components: z.ZodArray<z.ZodString>;
|
|
459
|
+
keepInstallFiles: z.ZodBoolean;
|
|
460
|
+
}, z.core.$strict>;
|
|
443
461
|
cpp: z.ZodObject<{
|
|
444
462
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
445
463
|
flexBison: z.ZodBoolean;
|
package/dist/web/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>Sandbox</title>
|
|
7
7
|
<link rel="icon" href="data:," />
|
|
8
|
-
<link rel="stylesheet" href="/main-
|
|
9
|
-
<script type="module" src="/main-
|
|
8
|
+
<link rel="stylesheet" href="/main-XT7T6ODM.css" />
|
|
9
|
+
<script type="module" src="/main-JTH3FT4O.js"></script>
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|