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
|
@@ -25938,6 +25938,7 @@ var DEFAULTS = {
|
|
|
25938
25938
|
linkSlots: "auto"
|
|
25939
25939
|
},
|
|
25940
25940
|
msvc: { enabled: "auto", acceptLicense: false, msvcVersion: "latest", sdkVersion: "latest" },
|
|
25941
|
+
unreal: { enabled: "auto", acceptLicense: false, components: [], keepInstallFiles: true },
|
|
25941
25942
|
cpp: { enabled: "auto", flexBison: true },
|
|
25942
25943
|
dotnet: {
|
|
25943
25944
|
enabled: "auto",
|
|
@@ -46053,7 +46054,7 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
46053
46054
|
"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."
|
|
46054
46055
|
),
|
|
46055
46056
|
vGpu: external_exports.boolean().describe(
|
|
46056
|
-
"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)."
|
|
46057
|
+
"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)."
|
|
46057
46058
|
),
|
|
46058
46059
|
networking: external_exports.boolean().describe("Internet access. false is the only hard network isolation Windows Sandbox offers."),
|
|
46059
46060
|
clipboard: external_exports.boolean().describe(
|
|
@@ -46215,6 +46216,21 @@ var ToolchainsSchema = external_exports.strictObject({
|
|
|
46215
46216
|
msvcVersion: external_exports.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
|
|
46216
46217
|
sdkVersion: external_exports.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".')
|
|
46217
46218
|
}),
|
|
46219
|
+
unreal: external_exports.strictObject({
|
|
46220
|
+
enabled: enabled(
|
|
46221
|
+
"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.",
|
|
46222
|
+
"a .uproject or .uplugin"
|
|
46223
|
+
),
|
|
46224
|
+
acceptLicense: external_exports.boolean().describe(
|
|
46225
|
+
"Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence."
|
|
46226
|
+
),
|
|
46227
|
+
components: StringsSchema.describe(
|
|
46228
|
+
'More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'
|
|
46229
|
+
),
|
|
46230
|
+
keepInstallFiles: external_exports.boolean().describe(
|
|
46231
|
+
"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."
|
|
46232
|
+
)
|
|
46233
|
+
}),
|
|
46218
46234
|
cpp: external_exports.strictObject({
|
|
46219
46235
|
enabled: enabled(
|
|
46220
46236
|
"MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).",
|
|
@@ -54689,7 +54705,23 @@ import { spawn as spawn8 } from "node:child_process";
|
|
|
54689
54705
|
// src/host/secrets/secret-store.ts
|
|
54690
54706
|
import { spawnSync as spawnSync19 } from "node:child_process";
|
|
54691
54707
|
var TIMEOUT_MS2 = 6e4;
|
|
54708
|
+
var toolsFor = /* @__PURE__ */ new Map();
|
|
54709
|
+
function dpapiTool(storageRoot) {
|
|
54710
|
+
if (!toolsFor.has(storageRoot)) {
|
|
54711
|
+
let exe = null;
|
|
54712
|
+
try {
|
|
54713
|
+
exe = hostToolsExe(storageRoot);
|
|
54714
|
+
} catch {
|
|
54715
|
+
}
|
|
54716
|
+
toolsFor.set(storageRoot, exe);
|
|
54717
|
+
}
|
|
54718
|
+
return toolsFor.get(storageRoot) ?? null;
|
|
54719
|
+
}
|
|
54692
54720
|
var DpapiBox = class {
|
|
54721
|
+
constructor(storageRoot) {
|
|
54722
|
+
this.storageRoot = storageRoot;
|
|
54723
|
+
}
|
|
54724
|
+
storageRoot;
|
|
54693
54725
|
kind = "dpapi1";
|
|
54694
54726
|
seal(plain2) {
|
|
54695
54727
|
return this.run("protect", plain2.toString("base64"));
|
|
@@ -54698,7 +54730,9 @@ var DpapiBox = class {
|
|
|
54698
54730
|
return Buffer.from(this.run("unprotect", sealed), "base64");
|
|
54699
54731
|
}
|
|
54700
54732
|
run(mode, input2) {
|
|
54701
|
-
const
|
|
54733
|
+
const tools = this.storageRoot ? dpapiTool(this.storageRoot) : null;
|
|
54734
|
+
const [exe, args] = tools ? [tools, [mode]] : [SYSTEM.powershell(), nativeScript("protect-data.ps1", ["-Mode", mode])];
|
|
54735
|
+
const result = spawnSync19(exe, args, {
|
|
54702
54736
|
input: input2,
|
|
54703
54737
|
encoding: "utf8",
|
|
54704
54738
|
windowsHide: true,
|
|
@@ -54726,17 +54760,17 @@ var SecretStore = class _SecretStore {
|
|
|
54726
54760
|
this.box = box;
|
|
54727
54761
|
}
|
|
54728
54762
|
box;
|
|
54729
|
-
/** Windows DPAPI, current user. */
|
|
54730
|
-
static dpapi() {
|
|
54731
|
-
return new _SecretStore(new DpapiBox());
|
|
54763
|
+
/** Windows DPAPI, current user; with a storage folder, through its HostTools.exe (much faster than PowerShell). */
|
|
54764
|
+
static dpapi(storageRoot = null) {
|
|
54765
|
+
return new _SecretStore(new DpapiBox(storageRoot));
|
|
54732
54766
|
}
|
|
54733
54767
|
/** The test stand-in (not secure). */
|
|
54734
54768
|
static memory() {
|
|
54735
54769
|
return new _SecretStore(new MemoryBox());
|
|
54736
54770
|
}
|
|
54737
54771
|
/** What the program uses: DPAPI, except during the self-test (it never spawns Windows for this). */
|
|
54738
|
-
static standard() {
|
|
54739
|
-
return selfTestRunning() ? _SecretStore.memory() : _SecretStore.dpapi();
|
|
54772
|
+
static standard(storageRoot = null) {
|
|
54773
|
+
return selfTestRunning() ? _SecretStore.memory() : _SecretStore.dpapi(storageRoot);
|
|
54740
54774
|
}
|
|
54741
54775
|
/** True when `value` looks like something seal() made (any box). */
|
|
54742
54776
|
static isSealed(value) {
|
|
@@ -55134,7 +55168,7 @@ function realLiveFolders(storageRoot, dataPath) {
|
|
|
55134
55168
|
return new LiveFolders({
|
|
55135
55169
|
storageRoot,
|
|
55136
55170
|
dataPath,
|
|
55137
|
-
secrets: SecretStore.standard(),
|
|
55171
|
+
secrets: SecretStore.standard(storageRoot),
|
|
55138
55172
|
elevated: new ScriptLivePort(),
|
|
55139
55173
|
userSid: currentUserSid,
|
|
55140
55174
|
isAlive: isSandboxRunning
|
|
@@ -56008,6 +56042,8 @@ var MAX_PLUGIN_BYTES = 1024 * 1024 * 1024;
|
|
|
56008
56042
|
var MAX_SETTINGS_BYTES = 4 * 1024 * 1024;
|
|
56009
56043
|
var MAX_DEPTH = 24;
|
|
56010
56044
|
var INSTALLED = "installed_plugins.json";
|
|
56045
|
+
var RECORDS = [INSTALLED, "known_marketplaces.json"];
|
|
56046
|
+
var MAX_RECORD_BYTES2 = 4 * 1024 * 1024;
|
|
56011
56047
|
function isObject2(value) {
|
|
56012
56048
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56013
56049
|
}
|
|
@@ -56054,7 +56090,7 @@ var PluginShare = class _PluginShare {
|
|
|
56054
56090
|
/** When a sandbox ends: its plugins refresh the shared set. Never throws; returns the problem, if any. */
|
|
56055
56091
|
saveQuietly(dataPath, claudeDir) {
|
|
56056
56092
|
try {
|
|
56057
|
-
if (_PluginShare.hasPlugins(claudeDir)) this.save(dataPath, claudeDir);
|
|
56093
|
+
if (_PluginShare.hasPlugins(claudeDir) && !this.matches(claudeDir)) this.save(dataPath, claudeDir);
|
|
56058
56094
|
return null;
|
|
56059
56095
|
} catch (e) {
|
|
56060
56096
|
return errMsg(e);
|
|
@@ -56108,9 +56144,24 @@ var PluginShare = class _PluginShare {
|
|
|
56108
56144
|
if (isObject2(shared[key3])) merged[key3] = { ...shared[key3], ...isObject2(merged[key3]) ? merged[key3] : {} };
|
|
56109
56145
|
writeSandboxJson(file2, merged);
|
|
56110
56146
|
}
|
|
56147
|
+
/**
|
|
56148
|
+
* Whether the shared set already holds this Claude folder's plugins: the same plugin records and plugin settings.
|
|
56149
|
+
* Copying a big plugins folder takes seconds, so a switch between accounts with the same plugins skips it.
|
|
56150
|
+
*/
|
|
56151
|
+
matches(claudeDir) {
|
|
56152
|
+
if (!this.hasShared()) return false;
|
|
56153
|
+
const same3 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
56154
|
+
for (const name2 of RECORDS) {
|
|
56155
|
+
const own2 = readUntrusted(path67.join(claudeDir, "plugins", name2), MAX_RECORD_BYTES2);
|
|
56156
|
+
if (!same3(own2, readUntrusted(path67.join(this.pluginsDir, name2), MAX_RECORD_BYTES2))) return false;
|
|
56157
|
+
}
|
|
56158
|
+
const shared = readUntrusted(this.settingsFile, MAX_SETTINGS_BYTES);
|
|
56159
|
+
return same3(pluginSettings(claudeDir), isObject2(shared) ? shared : {});
|
|
56160
|
+
}
|
|
56111
56161
|
/** One step when an account is switched to. */
|
|
56112
56162
|
sync(dataPath, claudeDir) {
|
|
56113
56163
|
if (_PluginShare.hasPlugins(claudeDir)) {
|
|
56164
|
+
if (this.matches(claudeDir)) return "nothing";
|
|
56114
56165
|
this.save(dataPath, claudeDir);
|
|
56115
56166
|
return "saved";
|
|
56116
56167
|
}
|
|
@@ -56170,7 +56221,7 @@ function assertName(name2) {
|
|
|
56170
56221
|
}
|
|
56171
56222
|
var AccountStore = class {
|
|
56172
56223
|
/** @param sharePlugins claudeProfile.sharePluginsAcrossAccounts: carry Claude plugins to the account switched to */
|
|
56173
|
-
constructor(storageRoot, sharePlugins = false, secrets = SecretStore.standard()) {
|
|
56224
|
+
constructor(storageRoot, sharePlugins = false, secrets = SecretStore.standard(storageRoot)) {
|
|
56174
56225
|
this.storageRoot = storageRoot;
|
|
56175
56226
|
this.sharePlugins = sharePlugins;
|
|
56176
56227
|
this.secrets = secrets;
|
|
@@ -56345,7 +56396,7 @@ var AgentAccountStore = class {
|
|
|
56345
56396
|
/**
|
|
56346
56397
|
* @param loginFiles files of the login, relative to the folder they are read from and written to
|
|
56347
56398
|
*/
|
|
56348
|
-
constructor(storageRoot, agent, loginFiles, secrets = SecretStore.standard()) {
|
|
56399
|
+
constructor(storageRoot, agent, loginFiles, secrets = SecretStore.standard(storageRoot)) {
|
|
56349
56400
|
this.storageRoot = storageRoot;
|
|
56350
56401
|
this.agent = agent;
|
|
56351
56402
|
this.loginFiles = loginFiles;
|
|
@@ -56508,7 +56559,7 @@ function checkGithubToken(token) {
|
|
|
56508
56559
|
return githubTokenKind(token) ?? fail("That is not a GitHub personal access token.", "Run: sandbox github login");
|
|
56509
56560
|
}
|
|
56510
56561
|
var GithubToken = class {
|
|
56511
|
-
constructor(storageRoot, secrets = SecretStore.standard()) {
|
|
56562
|
+
constructor(storageRoot, secrets = SecretStore.standard(storageRoot)) {
|
|
56512
56563
|
this.storageRoot = storageRoot;
|
|
56513
56564
|
this.secrets = secrets;
|
|
56514
56565
|
}
|
|
@@ -57191,6 +57242,7 @@ var MARKERS = {
|
|
|
57191
57242
|
],
|
|
57192
57243
|
rust: ["Cargo.toml", "rust-toolchain", "rust-toolchain.toml"],
|
|
57193
57244
|
msvc: ["*.vcxproj", "CMakePresets.json", "CMakeUserPresets.json"],
|
|
57245
|
+
unreal: ["*.uproject", "*.uplugin"],
|
|
57194
57246
|
cpp: [
|
|
57195
57247
|
"CMakeLists.txt",
|
|
57196
57248
|
"Makefile",
|
|
@@ -57249,6 +57301,11 @@ function decideToolchains(settings, entries, pcHas, hints = {}) {
|
|
|
57249
57301
|
on: false,
|
|
57250
57302
|
reason: "would be used (" + result.msvc.reason + "); set toolchains.msvc.acceptLicense to install it"
|
|
57251
57303
|
};
|
|
57304
|
+
if (settings.unreal.enabled === "auto" && result.unreal.on && !settings.unreal.acceptLicense)
|
|
57305
|
+
result.unreal = {
|
|
57306
|
+
on: false,
|
|
57307
|
+
reason: "would be used (" + result.unreal.reason + "); set toolchains.unreal.acceptLicense to install it"
|
|
57308
|
+
};
|
|
57252
57309
|
if (result.rust.on && !result.msvc.on && !result.cpp.on && settings.cpp.enabled !== false)
|
|
57253
57310
|
result.cpp = { on: true, reason: "the linker for Rust" };
|
|
57254
57311
|
if (result.python.on && settings.uv.enabled === "auto" && settings.python.tools.length > 0 && !result.uv.on)
|
|
@@ -59144,7 +59201,7 @@ function loginProblem(c2) {
|
|
|
59144
59201
|
return null;
|
|
59145
59202
|
}
|
|
59146
59203
|
var VpnLogin = class {
|
|
59147
|
-
constructor(storageRoot, secrets = SecretStore.standard()) {
|
|
59204
|
+
constructor(storageRoot, secrets = SecretStore.standard(storageRoot)) {
|
|
59148
59205
|
this.storageRoot = storageRoot;
|
|
59149
59206
|
this.secrets = secrets;
|
|
59150
59207
|
}
|
|
@@ -70288,7 +70345,7 @@ var TlsStore = class {
|
|
|
70288
70345
|
|
|
70289
70346
|
// src/app/features/access/access.run.ts
|
|
70290
70347
|
function accessStoreOf(ctx) {
|
|
70291
|
-
return AccessStore.at(ctx.storageRoot, SecretStore.standard(), {
|
|
70348
|
+
return AccessStore.at(ctx.storageRoot, SecretStore.standard(ctx.storageRoot), {
|
|
70292
70349
|
// The self-test never changes folder permissions; its storage is a temp folder.
|
|
70293
70350
|
protect: selfTestRunning() ? void 0 : (dir) => protectPrivateFolder(dir)
|
|
70294
70351
|
});
|
|
@@ -71073,9 +71130,10 @@ function loginItem(a, r) {
|
|
|
71073
71130
|
...r.isActive ? [{ text: "in the sandbox", tone: "ok" }] : [],
|
|
71074
71131
|
...r.isDefault ? [{ text: "default", tone: "accent" }] : []
|
|
71075
71132
|
],
|
|
71076
|
-
description: "Choose it to make the sandbox use this login.",
|
|
71133
|
+
description: r.isActive ? "The sandbox uses this login now." : "Choose it to make the sandbox use this login.",
|
|
71077
71134
|
details: ["Agent " + a.name, "Email " + (r.email ?? "-"), "Saved " + r.savedAt.slice(0, 16).replace("T", " ")],
|
|
71078
|
-
|
|
71135
|
+
// The login in use already offers nothing to switch to.
|
|
71136
|
+
...r.isActive ? {} : { primary: action(useAccount, { agent: a.name, name: r.name }, { verb: "use" }) },
|
|
71079
71137
|
actions: [
|
|
71080
71138
|
action(defaultAccount, { agent: a.name, name: r.name }, { key: "d", verb: "make default", importance: 1 }),
|
|
71081
71139
|
action(renameAccount, { agent: a.name, name: r.name }, { key: "r", verb: "rename", importance: 2 }),
|
|
@@ -71123,7 +71181,7 @@ function agentPage(a) {
|
|
|
71123
71181
|
var accountsView = defineView({
|
|
71124
71182
|
id: "accounts",
|
|
71125
71183
|
title: "Accounts",
|
|
71126
|
-
summary:
|
|
71184
|
+
summary: 'Logins saved on this PC for each agent. Every launch starts with the default; "Use this login" switches now.',
|
|
71127
71185
|
queries: { accounts: listAccounts },
|
|
71128
71186
|
operations: [saveAccount, useAccount, defaultAccount, renameAccount, removeAccount],
|
|
71129
71187
|
build: ({ accounts }) => accountsPage(accounts)
|
|
@@ -75578,11 +75636,6 @@ var SandboxStatusSchema2 = external_exports.object({
|
|
|
75578
75636
|
repoGuard: external_exports.object({ guarded: external_exports.number(), findings: external_exports.array(external_exports.string()) })
|
|
75579
75637
|
});
|
|
75580
75638
|
var MessageSchema4 = external_exports.object({ message: external_exports.string().describe("What happened") });
|
|
75581
|
-
function helperText(answer) {
|
|
75582
|
-
const sessions = /^pong \((\d+) session/.exec(answer);
|
|
75583
|
-
if (!sessions) return answer;
|
|
75584
|
-
return "responding, " + plural2(Number(sessions[1]), "session") + " running";
|
|
75585
|
-
}
|
|
75586
75639
|
function uptime(s) {
|
|
75587
75640
|
return s.running && s.startedAt ? ago(s.startedAt).replace(" ago", "") : null;
|
|
75588
75641
|
}
|
|
@@ -75694,7 +75747,8 @@ function facts(o) {
|
|
|
75694
75747
|
...s.running ? [
|
|
75695
75748
|
fact("window", "Window", s.headless ? "hidden (sandbox show opens it)" : "shown"),
|
|
75696
75749
|
fact("uptime", "Uptime", uptime(s) ?? "-"),
|
|
75697
|
-
|
|
75750
|
+
// The session count is its own fact: the helper only says whether it answers.
|
|
75751
|
+
fact("helper", "Helper", s.daemon === "-" ? "-" : s.daemon.startsWith("pong") ? "Responding" : s.daemon),
|
|
75698
75752
|
fact("sessions", "Sessions", String(sessions))
|
|
75699
75753
|
] : [],
|
|
75700
75754
|
fact("account", "Account", s.account ?? "none selected (sandbox account use)"),
|
|
@@ -75723,7 +75777,7 @@ function guardSection(o) {
|
|
|
75723
75777
|
return {
|
|
75724
75778
|
id: "guard",
|
|
75725
75779
|
title: "Repo guard",
|
|
75726
|
-
summary: o.repoGuard.guarded
|
|
75780
|
+
summary: "Watching " + plural2(o.repoGuard.guarded, "folder") + ". " + (findings.length ? plural2(findings.length, "change") + " from the sandbox were blocked:" : "Nothing from the sandbox needed blocking."),
|
|
75727
75781
|
items: findings.slice(-10).map((f, i) => ({ id: "guard:" + i, label: f, tone: "warn" }))
|
|
75728
75782
|
};
|
|
75729
75783
|
}
|
|
@@ -75767,7 +75821,7 @@ function sandboxPage(o) {
|
|
|
75767
75821
|
var sandboxView = defineView({
|
|
75768
75822
|
id: "sandbox",
|
|
75769
75823
|
title: "Sandbox",
|
|
75770
|
-
summary: "
|
|
75824
|
+
summary: "Status, projects and controls of the running sandbox.",
|
|
75771
75825
|
queries: { status: sandboxStatus },
|
|
75772
75826
|
operations: [showWindow, hideWindow, stopSandbox],
|
|
75773
75827
|
build: ({ status }) => sandboxPage(status)
|
|
@@ -76703,7 +76757,7 @@ function sessionsPage(o) {
|
|
|
76703
76757
|
var sessionsView = defineView({
|
|
76704
76758
|
id: "sessions",
|
|
76705
76759
|
title: "Sessions",
|
|
76706
|
-
summary: "
|
|
76760
|
+
summary: "Agent and shell sessions in the running sandbox.",
|
|
76707
76761
|
queries: { sessions: listSessions },
|
|
76708
76762
|
operations: [restartSessions, startShell, closeSession],
|
|
76709
76763
|
build: ({ sessions }) => sessionsPage(sessions)
|
|
@@ -78020,27 +78074,37 @@ function navViews(nav) {
|
|
|
78020
78074
|
return navSections(nav).flatMap((n) => [...n.view ? [n.view] : [], ...(n.embeds ?? []).map((e) => e.view)]);
|
|
78021
78075
|
}
|
|
78022
78076
|
var NAV = [
|
|
78023
|
-
{
|
|
78024
|
-
|
|
78025
|
-
|
|
78077
|
+
{
|
|
78078
|
+
label: "Workspace",
|
|
78079
|
+
children: [
|
|
78080
|
+
{ label: "Agents", view: "agents" },
|
|
78081
|
+
{ label: "Sessions", view: "sessions" },
|
|
78082
|
+
{ label: "Activity", view: "audit" }
|
|
78083
|
+
]
|
|
78084
|
+
},
|
|
78026
78085
|
{
|
|
78027
78086
|
label: "Sandbox",
|
|
78028
78087
|
children: [
|
|
78029
|
-
{ label: "
|
|
78030
|
-
{ label: "Projects", view: "projects" }
|
|
78088
|
+
{ label: "Overview", view: "sandbox" },
|
|
78089
|
+
{ label: "Projects", view: "projects" },
|
|
78090
|
+
{ label: "Apps", view: "apps" }
|
|
78031
78091
|
]
|
|
78032
78092
|
},
|
|
78033
|
-
{ label: "Apps", view: "apps" },
|
|
78034
78093
|
{
|
|
78035
|
-
label: "
|
|
78036
|
-
|
|
78037
|
-
|
|
78038
|
-
|
|
78039
|
-
|
|
78094
|
+
label: "Configuration",
|
|
78095
|
+
children: [
|
|
78096
|
+
{
|
|
78097
|
+
label: "Settings",
|
|
78098
|
+
view: "settings",
|
|
78099
|
+
embeds: [
|
|
78100
|
+
{ label: "VPN", view: "vpn" },
|
|
78101
|
+
{ label: "GitHub", view: "github" }
|
|
78102
|
+
]
|
|
78103
|
+
},
|
|
78104
|
+
{ label: "Accounts", view: "accounts" },
|
|
78105
|
+
{ label: "Remote access", view: "access" }
|
|
78040
78106
|
]
|
|
78041
78107
|
},
|
|
78042
|
-
{ label: "Accounts", view: "accounts" },
|
|
78043
|
-
{ label: "Remote access", view: "access" },
|
|
78044
78108
|
{
|
|
78045
78109
|
label: "Maintenance",
|
|
78046
78110
|
children: [
|
|
@@ -78290,7 +78354,7 @@ async function attachOpened(ctx, session) {
|
|
|
78290
78354
|
nextStep("sandbox attach " + session);
|
|
78291
78355
|
return 0;
|
|
78292
78356
|
}
|
|
78293
|
-
const { attach: attach2 } = await import("./chunk-
|
|
78357
|
+
const { attach: attach2 } = await import("./chunk-XYUVIVJT.js");
|
|
78294
78358
|
return attach2({ ...ctx, options: { ...ctx.options, positionals: [session] } });
|
|
78295
78359
|
}
|
|
78296
78360
|
function definitionHandler(def) {
|
|
@@ -78382,7 +78446,7 @@ function remoteAudit(ctx) {
|
|
|
78382
78446
|
};
|
|
78383
78447
|
}
|
|
78384
78448
|
function remoteGate(ctx) {
|
|
78385
|
-
const secrets = SecretStore.standard();
|
|
78449
|
+
const secrets = SecretStore.standard(ctx.storageRoot);
|
|
78386
78450
|
let ownerSid = "";
|
|
78387
78451
|
try {
|
|
78388
78452
|
ownerSid = currentUserSid();
|
package/dist/bin/claude-host.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-host.ts
|
|
9
9
|
var args = process.argv.slice(2);
|
package/dist/bin/claude-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "claude" });
|
package/dist/bin/codex-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/codex-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "codex" });
|
package/dist/bin/gemini-sbx.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/gemini-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "gemini" });
|
package/dist/bin/sandbox.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sandbox.ts
|
|
9
9
|
run(process.argv.slice(2));
|
package/dist/bin/sbx-hide.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-hide.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "hide" });
|
package/dist/bin/sbx-show.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-QLGGAG3D.js";
|
|
6
|
+
import "./chunk-REE3EMHD.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-show.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "show" });
|
package/dist/cli/commands/web.js
CHANGED
|
@@ -95,7 +95,7 @@ function remoteAudit(ctx) {
|
|
|
95
95
|
* served (it refuses everyone while web.remote.windowsSignIn is off).
|
|
96
96
|
*/
|
|
97
97
|
function remoteGate(ctx) {
|
|
98
|
-
const secrets = SecretStore.standard();
|
|
98
|
+
const secrets = SecretStore.standard(ctx.storageRoot);
|
|
99
99
|
let ownerSid = '';
|
|
100
100
|
try {
|
|
101
101
|
ownerSid = currentUserSid();
|
package/dist/cli/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { takeHiddenInstallNotice } from '../host/install/index.js';
|
|
|
12
12
|
import { c } from './output/index.js';
|
|
13
13
|
import { dropInheritedModulePath } from '../shared/system.js';
|
|
14
14
|
import { withConfig, hoistConfig, withoutConfig } from './argv.js';
|
|
15
|
-
import { report } from './report.js';
|
|
15
|
+
import { recordUnexpected, report } from './report.js';
|
|
16
16
|
import { versionText } from './version.js';
|
|
17
17
|
import { HANDLERS } from './commands/index.js';
|
|
18
18
|
import { definitionHandler, operationHandler } from './operations/index.js';
|
|
@@ -121,6 +121,9 @@ export async function main(rawArgv, preset = {}) {
|
|
|
121
121
|
}
|
|
122
122
|
export function run(argv, preset) {
|
|
123
123
|
dropInheritedModulePath();
|
|
124
|
+
// Background work that throws must not end the menu or the web server: the error is kept with its stack instead.
|
|
125
|
+
process.on('unhandledRejection', (e) => recordUnexpected(e, 'unhandled rejection'));
|
|
126
|
+
process.on('uncaughtException', (e) => recordUnexpected(e, 'uncaught exception'));
|
|
124
127
|
main(argv, preset).then((code) => {
|
|
125
128
|
process.exitCode = code;
|
|
126
129
|
}, (e) => {
|
package/dist/cli/report.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
/** Where errors nobody caught are written in full (this user's temp folder; kept under 1 MB). */
|
|
2
|
+
export declare const UNEXPECTED_LOG: string;
|
|
3
|
+
/**
|
|
4
|
+
* An error thrown by background work (a timer, a promise nobody awaited): written in full to UNEXPECTED_LOG and named
|
|
5
|
+
* in one line, instead of ending the menu, the web server or a command half-way.
|
|
6
|
+
*/
|
|
7
|
+
export declare function recordUnexpected(e: unknown, kind: string): void;
|
|
1
8
|
/** Prints a problem the way a user can act on it: what happened, how to fix it; stack traces only for real bugs. */
|
|
2
9
|
export declare function report(e: unknown): number;
|
package/dist/cli/report.js
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
1
4
|
import { CommanderError } from 'commander';
|
|
2
5
|
import { c } from './output/index.js';
|
|
3
6
|
import { UserError, errMsg, plainText } from '../core/util/index.js';
|
|
7
|
+
/** Where errors nobody caught are written in full (this user's temp folder; kept under 1 MB). */
|
|
8
|
+
export const UNEXPECTED_LOG = path.join(os.tmpdir(), 'windows-development-sandbox-errors.log');
|
|
9
|
+
const UNEXPECTED_LOG_MAX = 1024 * 1024;
|
|
10
|
+
/**
|
|
11
|
+
* An error thrown by background work (a timer, a promise nobody awaited): written in full to UNEXPECTED_LOG and named
|
|
12
|
+
* in one line, instead of ending the menu, the web server or a command half-way.
|
|
13
|
+
*/
|
|
14
|
+
export function recordUnexpected(e, kind) {
|
|
15
|
+
const text = new Date().toISOString() +
|
|
16
|
+
' ' +
|
|
17
|
+
kind +
|
|
18
|
+
' (pid ' +
|
|
19
|
+
process.pid +
|
|
20
|
+
', ' +
|
|
21
|
+
process.argv.slice(2).join(' ') +
|
|
22
|
+
')\n' +
|
|
23
|
+
(e instanceof Error && e.stack ? e.stack : errMsg(e)) +
|
|
24
|
+
'\n\n';
|
|
25
|
+
try {
|
|
26
|
+
if (fs.existsSync(UNEXPECTED_LOG) && fs.statSync(UNEXPECTED_LOG).size > UNEXPECTED_LOG_MAX)
|
|
27
|
+
fs.rmSync(UNEXPECTED_LOG, { force: true });
|
|
28
|
+
fs.appendFileSync(UNEXPECTED_LOG, text);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Nowhere to write it: the line below still says what happened.
|
|
32
|
+
}
|
|
33
|
+
console.error(c.red('Unexpected error (kept running): ') + plainText(errMsg(e)) + c.dim(' Details: ' + UNEXPECTED_LOG));
|
|
34
|
+
}
|
|
4
35
|
/** Prints a problem the way a user can act on it: what happened, how to fix it; stack traces only for real bugs. */
|
|
5
36
|
export function report(e) {
|
|
6
37
|
if (e instanceof CommanderError)
|
|
@@ -62,6 +62,7 @@ export const DEFAULTS = {
|
|
|
62
62
|
linkSlots: 'auto',
|
|
63
63
|
},
|
|
64
64
|
msvc: { enabled: 'auto', acceptLicense: false, msvcVersion: 'latest', sdkVersion: 'latest' },
|
|
65
|
+
unreal: { enabled: 'auto', acceptLicense: false, components: [], keepInstallFiles: true },
|
|
65
66
|
cpp: { enabled: 'auto', flexBison: true },
|
|
66
67
|
dotnet: {
|
|
67
68
|
enabled: 'auto',
|
|
@@ -4,6 +4,7 @@ export declare const MARKERS: {
|
|
|
4
4
|
readonly python: readonly ["pyproject.toml", "requirements.txt", "setup.py", "setup.cfg", "Pipfile", "uv.lock", "poetry.lock", ".python-version", "*.py", "*.ipynb"];
|
|
5
5
|
readonly rust: readonly ["Cargo.toml", "rust-toolchain", "rust-toolchain.toml"];
|
|
6
6
|
readonly msvc: readonly ["*.vcxproj", "CMakePresets.json", "CMakeUserPresets.json"];
|
|
7
|
+
readonly unreal: readonly ["*.uproject", "*.uplugin"];
|
|
7
8
|
readonly cpp: readonly ["CMakeLists.txt", "Makefile", "meson.build", "premake5.lua", "Cargo.toml", "*.vcxproj", "*.c", "*.cpp", "*.cc", "*.h", "*.hpp"];
|
|
8
9
|
readonly dotnet: readonly ["*.sln", "*.slnx", "*.csproj", "*.fsproj", "*.vbproj", "global.json", "*.cs"];
|
|
9
10
|
readonly go: readonly ["go.mod", "go.work", "*.go"];
|
|
@@ -15,6 +15,7 @@ export const MARKERS = {
|
|
|
15
15
|
],
|
|
16
16
|
rust: ['Cargo.toml', 'rust-toolchain', 'rust-toolchain.toml'],
|
|
17
17
|
msvc: ['*.vcxproj', 'CMakePresets.json', 'CMakeUserPresets.json'],
|
|
18
|
+
unreal: ['*.uproject', '*.uplugin'],
|
|
18
19
|
cpp: [
|
|
19
20
|
'CMakeLists.txt',
|
|
20
21
|
'Makefile',
|
|
@@ -86,6 +87,12 @@ export function decideToolchains(settings, entries, pcHas, hints = {}) {
|
|
|
86
87
|
on: false,
|
|
87
88
|
reason: 'would be used (' + result.msvc.reason + '); set toolchains.msvc.acceptLicense to install it',
|
|
88
89
|
};
|
|
90
|
+
// Unreal is a ~10 GB licensed install every boot: "auto" only installs it once its licence is accepted.
|
|
91
|
+
if (settings.unreal.enabled === 'auto' && result.unreal.on && !settings.unreal.acceptLicense)
|
|
92
|
+
result.unreal = {
|
|
93
|
+
on: false,
|
|
94
|
+
reason: 'would be used (' + result.unreal.reason + '); set toolchains.unreal.acceptLicense to install it',
|
|
95
|
+
};
|
|
89
96
|
if (result.rust.on && !result.msvc.on && !result.cpp.on && settings.cpp.enabled !== false)
|
|
90
97
|
result.cpp = { on: true, reason: 'the linker for Rust' };
|
|
91
98
|
// uv installs the Python tools (`uv tool install`), so Python tools turn an "auto" uv on.
|
|
@@ -153,6 +153,12 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
153
153
|
msvcVersion: z.ZodString;
|
|
154
154
|
sdkVersion: z.ZodString;
|
|
155
155
|
}, z.core.$strict>;
|
|
156
|
+
unreal: z.ZodObject<{
|
|
157
|
+
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
158
|
+
acceptLicense: z.ZodBoolean;
|
|
159
|
+
components: z.ZodArray<z.ZodString>;
|
|
160
|
+
keepInstallFiles: z.ZodBoolean;
|
|
161
|
+
}, z.core.$strict>;
|
|
156
162
|
cpp: z.ZodObject<{
|
|
157
163
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
158
164
|
flexBison: z.ZodBoolean;
|
|
@@ -506,6 +512,21 @@ export declare const LocalOverridesSchema: z.ZodObject<{
|
|
|
506
512
|
zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
507
513
|
openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
508
514
|
}, z.core.$strict>>;
|
|
515
|
+
unreal: z.ZodOptional<z.ZodObject<{
|
|
516
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
517
|
+
}, z.core.$strict> | z.ZodObject<{
|
|
518
|
+
version: z.ZodOptional<z.ZodString>;
|
|
519
|
+
extraVersions: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
520
|
+
corepack: z.ZodOptional<z.ZodBoolean>;
|
|
521
|
+
volta: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
522
|
+
globalPackages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
523
|
+
}, z.core.$strict> | z.ZodObject<{
|
|
524
|
+
enabled: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
525
|
+
}, z.core.$strict> | z.ZodObject<{
|
|
526
|
+
gh: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
527
|
+
zstd: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
528
|
+
openssl: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>>;
|
|
529
|
+
}, z.core.$strict>>;
|
|
509
530
|
cpp: z.ZodOptional<z.ZodObject<{
|
|
510
531
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
511
532
|
}, z.core.$strict> | z.ZodObject<{
|
|
@@ -51,7 +51,7 @@ export const SandboxSchema = z.strictObject({
|
|
|
51
51
|
.describe('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.'),
|
|
52
52
|
vGpu: z
|
|
53
53
|
.boolean()
|
|
54
|
-
.describe("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)."),
|
|
54
|
+
.describe("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)."),
|
|
55
55
|
networking: z.boolean().describe('Internet access. false is the only hard network isolation Windows Sandbox offers.'),
|
|
56
56
|
clipboard: z
|
|
57
57
|
.boolean()
|
|
@@ -34,6 +34,12 @@ export declare const ToolchainsSchema: z.ZodObject<{
|
|
|
34
34
|
msvcVersion: z.ZodString;
|
|
35
35
|
sdkVersion: z.ZodString;
|
|
36
36
|
}, z.core.$strict>;
|
|
37
|
+
unreal: z.ZodObject<{
|
|
38
|
+
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
39
|
+
acceptLicense: z.ZodBoolean;
|
|
40
|
+
components: z.ZodArray<z.ZodString>;
|
|
41
|
+
keepInstallFiles: z.ZodBoolean;
|
|
42
|
+
}, z.core.$strict>;
|
|
37
43
|
cpp: z.ZodObject<{
|
|
38
44
|
enabled: z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"auto">]>;
|
|
39
45
|
flexBison: z.ZodBoolean;
|
|
@@ -53,6 +53,16 @@ export const ToolchainsSchema = z.strictObject({
|
|
|
53
53
|
msvcVersion: z.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
|
|
54
54
|
sdkVersion: z.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".'),
|
|
55
55
|
}),
|
|
56
|
+
unreal: z.strictObject({
|
|
57
|
+
enabled: enabled('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.', 'a .uproject or .uplugin'),
|
|
58
|
+
acceptLicense: z
|
|
59
|
+
.boolean()
|
|
60
|
+
.describe('Required to install: you accept the Visual Studio Community licence terms (https://visualstudio.microsoft.com/license-terms/) and the DirectX End-User Runtime licence.'),
|
|
61
|
+
components: StringsSchema.describe('More Visual Studio workload or component IDs to add, e.g. ["Microsoft.VisualStudio.Component.VC.Llvm.Clang"].'),
|
|
62
|
+
keepInstallFiles: z
|
|
63
|
+
.boolean()
|
|
64
|
+
.describe('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.'),
|
|
65
|
+
}),
|
|
56
66
|
cpp: z.strictObject({
|
|
57
67
|
enabled: enabled("MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust's linker).", 'CMakeLists.txt, Makefile, meson.build, premake5.lua or Cargo.toml'),
|
|
58
68
|
flexBison: z
|