windows-development-sandbox 1.27.3 → 1.28.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.
Files changed (68) hide show
  1. package/dist/bin/agent-sandbox.js +2 -2
  2. package/dist/bin/{chunk-RU7XRN62.js → chunk-CB44HTTN.js} +196 -75
  3. package/dist/bin/{chunk-FA5VWLP4.js → chunk-UZ5S3EMB.js} +1 -1
  4. package/dist/bin/{chunk-4M5SZZ5P.js → chunk-ZMZI3625.js} +1 -1
  5. package/dist/bin/claude-host.js +2 -2
  6. package/dist/bin/claude-sbx.js +2 -2
  7. package/dist/bin/codex-sbx.js +2 -2
  8. package/dist/bin/gemini-sbx.js +2 -2
  9. package/dist/bin/sandbox.js +2 -2
  10. package/dist/bin/sbx-hide.js +2 -2
  11. package/dist/bin/sbx-show.js +2 -2
  12. package/dist/core/schema/sandbox.js +1 -1
  13. package/dist/guest/daemon/heartbeat.js +1 -0
  14. package/dist/guest/governor/core.d.ts +53 -1
  15. package/dist/guest/governor/core.js +95 -1
  16. package/dist/guest/governor/decide.d.ts +4 -0
  17. package/dist/guest/governor/decide.js +2 -0
  18. package/dist/guest/governor/governor.js +23 -9
  19. package/dist/guest/toolchains/native/unreal.js +22 -3
  20. package/dist/guest/toolchains/runtimes.js +7 -6
  21. package/dist/host/life/crash-report.d.ts +4 -0
  22. package/dist/host/life/crash-report.js +30 -1
  23. package/dist/host/life/last-end.js +1 -0
  24. package/dist/host/tools/windows-terminal.d.ts +4 -1
  25. package/dist/host/tools/windows-terminal.js +25 -9
  26. package/dist/runtime/agent.js +5 -1
  27. package/dist/runtime/daemon.js +183 -70
  28. package/dist/runtime/db.js +5 -1
  29. package/dist/runtime/main.js +242 -56
  30. package/dist/runtime/netproxy.js +5 -1
  31. package/dist/runtime/tool.js +5 -1
  32. package/dist/runtime/view.js +125 -27
  33. package/dist/selftest/agent-paths.test.js +3 -1
  34. package/dist/selftest/channel.test.js +33 -0
  35. package/dist/selftest/heavy-load.test.js +116 -4
  36. package/dist/selftest/live-terminal.test.js +103 -0
  37. package/dist/selftest/personalization.test.js +2 -1
  38. package/dist/selftest/support/engine-golden.js +2 -0
  39. package/dist/shared/channel/schema.d.ts +2 -0
  40. package/dist/shared/channel/schema.js +4 -0
  41. package/dist/shared/memory/index.d.ts +1 -0
  42. package/dist/shared/memory/index.js +1 -0
  43. package/dist/shared/memory/policy.d.ts +12 -0
  44. package/dist/shared/memory/policy.js +4 -0
  45. package/dist/shared/memory/unreal-build.d.ts +2 -0
  46. package/dist/shared/memory/unreal-build.js +21 -0
  47. package/dist/shared/pty/clipboard-watch.d.ts +4 -0
  48. package/dist/shared/pty/clipboard-watch.js +40 -0
  49. package/dist/shared/pty/ctrl-c.d.ts +13 -7
  50. package/dist/shared/pty/ctrl-c.js +35 -19
  51. package/dist/shared/pty/index.d.ts +1 -0
  52. package/dist/shared/pty/index.js +1 -0
  53. package/dist/shared/pty/terminal.d.ts +1 -1
  54. package/dist/shared/pty/terminal.js +16 -13
  55. package/dist/shared/web/ctrl-c.d.ts +26 -0
  56. package/dist/shared/web/ctrl-c.js +64 -0
  57. package/dist/shared/web/index.d.ts +1 -0
  58. package/dist/shared/web/index.js +1 -0
  59. package/dist/web/index.html +1 -1
  60. package/dist/web/{main-NKM7ECSB.js → main-7NY4X6YU.js} +67 -67
  61. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  62. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  63. package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
  64. package/package.json +1 -1
  65. package/sandbox/csharp/ClipboardWatch.cs +59 -0
  66. package/sandbox/csharp/MemGov.cs +752 -7
  67. package/sandbox/scripts/watch-clipboard.ps1 +8 -0
  68. package/schemas/config.schema.json +1 -1
@@ -25494,7 +25494,7 @@ var SandboxSchema = external_exports.strictObject({
25494
25494
  'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
25495
25495
  ),
25496
25496
  pressureResponse: external_exports.boolean().describe(
25497
- "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."
25497
+ "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. A memory gate also holds new compilers and linkers for a moment when the memory of the build programs grows faster than 4 GB in 3 seconds (3 GB with vGPU), and lets them go one at a time. Yours only: a project file cannot change it."
25498
25498
  ),
25499
25499
  vGpu: external_exports.boolean().describe(
25500
25500
  "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)."
@@ -27934,6 +27934,8 @@ var PressureStatusSchema = external_exports.object({
27934
27934
  lowered: external_exports.number().int().min(0).max(1024),
27935
27935
  /** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
27936
27936
  paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
27937
+ /** Build programs the memory gate holds right now (let go one at a time). */
27938
+ held: external_exports.number().int().min(0).max(1024).optional(),
27937
27939
  /** The CPU share the compilers get together (percent; 100 = no cap). */
27938
27940
  cpuPercent: external_exports.number().int().min(0).max(100).optional(),
27939
27941
  /** The PC itself asked for slowing down (its memory or CPU is low). */
@@ -27954,6 +27956,8 @@ var HeartbeatSchema = external_exports.object({
27954
27956
  topProcesses: external_exports.array(external_exports.object({ name: Text(64), privateMb: external_exports.number().int().min(0).max(1e7) })).max(5),
27955
27957
  /** The disk queue this PC last reported while asking the sandbox to slow down. */
27956
27958
  diskQueueReported: external_exports.number().min(0).max(1e5).optional(),
27959
+ /** Build programs the memory gate holds right now (let go one at a time). */
27960
+ held: external_exports.number().int().min(0).max(1024).optional(),
27957
27961
  /** "ending": the sandbox is shutting down in order (idle shutdown, sandbox stop, Windows shutting down). */
27958
27962
  phase: external_exports.enum(["ready", "working", "ending"])
27959
27963
  });
@@ -28859,7 +28863,7 @@ function writeStatus(phase, message) {
28859
28863
  // src/guest/boot/boot.ts
28860
28864
  import fs95 from "node:fs";
28861
28865
  import path126 from "node:path";
28862
- import { spawn as spawn16 } from "node:child_process";
28866
+ import { spawn as spawn17 } from "node:child_process";
28863
28867
 
28864
28868
  // src/guest/boot/guide.ts
28865
28869
  import fs23 from "node:fs";
@@ -31396,11 +31400,10 @@ async function setupBun(env) {
31396
31400
  tool("bun", "bin"),
31397
31401
  { size: "35 MB" }
31398
31402
  );
31399
- Object.assign(env.vars, {
31400
- BUN_INSTALL: tool("bun"),
31401
- BUN_INSTALL_CACHE_DIR: path38.join(localDir, "bun-cache"),
31402
- BUN_TMPDIR: path38.join(localDir, "bun-tmp")
31403
- });
31403
+ const cache = path38.join(localDir, "bun-cache");
31404
+ const temp = path38.join(localDir, "bun-tmp");
31405
+ if (!dryRun) [cache, temp].forEach((dir) => mkdirp(dir));
31406
+ Object.assign(env.vars, { BUN_INSTALL: tool("bun"), BUN_INSTALL_CACHE_DIR: cache, BUN_TMPDIR: temp });
31404
31407
  }
31405
31408
  async function setupDeno(env) {
31406
31409
  await setupSingleExe(
@@ -34240,6 +34243,49 @@ import fs52 from "node:fs";
34240
34243
  import os9 from "node:os";
34241
34244
  import path73 from "node:path";
34242
34245
 
34246
+ // src/shared/memory/policy.ts
34247
+ function buildJobs(cpus, memoryGb) {
34248
+ return Math.max(2, Math.min(cpus, Math.floor((memoryGb - 6) / 3)));
34249
+ }
34250
+ function usableCpus(cpus, percent) {
34251
+ if (percent === null || percent >= 100) return cpus;
34252
+ return Math.max(2, Math.min(cpus, Math.floor(cpus * percent / 100)));
34253
+ }
34254
+ function cargoJobs(cpus, memoryGb, sessions) {
34255
+ const byCpu = Math.max(2, Math.min(8, Math.floor(cpus / 4)));
34256
+ const byMemory = Math.max(1, Math.floor(memoryGb / 4));
34257
+ const jobs = Math.min(byCpu, byMemory);
34258
+ return Math.max(1, Math.min(jobs, Math.floor(buildJobs(cpus, memoryGb) / Math.max(1, sessions))));
34259
+ }
34260
+ var LOCAL_TARGET_MIN_BYTES = 25 * 1024 ** 3;
34261
+ function chooseTargetDir(targetDir, freeBytes2) {
34262
+ if (targetDir !== "auto") return { targetDir };
34263
+ if (freeBytes2 >= LOCAL_TARGET_MIN_BYTES) return { targetDir: "local" };
34264
+ return {
34265
+ targetDir: "separate",
34266
+ warning: "Rust builds write through the mapped workspace; this can overload your PC's disk (C: has less than 25 GB free for a local build folder)"
34267
+ };
34268
+ }
34269
+ function cargoLinkerVar(host) {
34270
+ return "CARGO_TARGET_" + host.toUpperCase().replace(/[^A-Z0-9]/g, "_") + "_LINKER";
34271
+ }
34272
+
34273
+ // src/shared/memory/unreal-build.ts
34274
+ var NAMESPACE = "https://www.unrealengine.com/BuildConfiguration";
34275
+ function ubtBuildConfiguration(jobs) {
34276
+ const max = Math.max(1, Math.floor(jobs));
34277
+ return [
34278
+ '<?xml version="1.0" encoding="utf-8"?>',
34279
+ "<!-- Written by the sandbox at boot: compiles at once from the build budget (run\\budget.json, buildJobs). -->",
34280
+ '<Configuration xmlns="' + NAMESPACE + '">',
34281
+ " <BuildConfiguration>",
34282
+ " <MaxParallelActions>" + max + "</MaxParallelActions>",
34283
+ " </BuildConfiguration>",
34284
+ "</Configuration>",
34285
+ ""
34286
+ ].join("\r\n");
34287
+ }
34288
+
34243
34289
  // src/guest/toolchains/native/debuggers.ts
34244
34290
  import path69 from "node:path";
34245
34291
  var SDK_SETUP_URL = "https://go.microsoft.com/fwlink/?linkid=2311806";
@@ -34969,6 +35015,14 @@ async function checkVisualStudio() {
34969
35015
  fs52.rmSync(dir, { recursive: true, force: true });
34970
35016
  }
34971
35017
  }
35018
+ function capUnrealBuilds() {
35019
+ const cpus = usableCpus(os9.cpus().length, session.cpuLimitPercent ?? null);
35020
+ const jobs = buildJobs(cpus, os9.totalmem() / 1024 ** 3);
35021
+ const appData = process.env.APPDATA ?? "C:\\Users\\WDAGUtilityAccount\\AppData\\Roaming";
35022
+ const dir = mkdirp(path73.join(appData, "Unreal Engine", "UnrealBuildTool"));
35023
+ fs52.writeFileSync(path73.join(dir, "BuildConfiguration.xml"), ubtBuildConfiguration(jobs), "utf8");
35024
+ return jobs;
35025
+ }
34972
35026
  async function part(what, work, fallback) {
34973
35027
  try {
34974
35028
  return await work();
@@ -34987,6 +35041,8 @@ async function setupUnreal(env, config3, _ctx) {
34987
35041
  return;
34988
35042
  }
34989
35043
  resetUnrealStatus();
35044
+ const jobs = await part("capping parallel compiles", async () => capUnrealBuilds(), 0);
35045
+ if (jobs) log("Unreal: UnrealBuildTool runs at most " + jobs + " compiles at once (the build budget)");
34990
35046
  await part("the DirectX End-User Runtime", installDirectX, void 0);
34991
35047
  const launcher = await part("the Epic Games Launcher", ensureLauncher, null);
34992
35048
  const place = placeEngines(config3.persistEngines);
@@ -35022,7 +35078,7 @@ async function setupUnreal(env, config3, _ctx) {
35022
35078
  debugger: debuggers ? path73.join(debuggers, "cdb.exe") : null
35023
35079
  }));
35024
35080
  env.summary.push(
35025
- "unreal tools: " + (vs ? "Visual Studio " + vs.version + (check2.ok ? " (UnrealBuildTool finds it)" : " (UnrealBuildTool would NOT find it)") : "no Visual Studio") + ", DirectX End-User Runtime" + (launcher ? ", Epic Games Launcher" : "") + (debuggers ? ", cdb/windbg" : "")
35081
+ "unreal tools: " + (vs ? "Visual Studio " + vs.version + (check2.ok ? " (UnrealBuildTool finds it)" : " (UnrealBuildTool would NOT find it)") : "no Visual Studio") + (jobs ? ", at most " + jobs + " compiles at once" : "") + ", DirectX End-User Runtime" + (launcher ? ", Epic Games Launcher" : "") + (debuggers ? ", cdb/windbg" : "")
35026
35082
  );
35027
35083
  }
35028
35084
 
@@ -38349,33 +38405,69 @@ import fs67 from "node:fs";
38349
38405
  import os11 from "node:os";
38350
38406
  import path94 from "node:path";
38351
38407
 
38352
- // src/shared/memory/policy.ts
38353
- function buildJobs(cpus, memoryGb) {
38354
- return Math.max(2, Math.min(cpus, Math.floor((memoryGb - 6) / 3)));
38355
- }
38356
- function cargoJobs(cpus, memoryGb, sessions) {
38357
- const byCpu = Math.max(2, Math.min(8, Math.floor(cpus / 4)));
38358
- const byMemory = Math.max(1, Math.floor(memoryGb / 4));
38359
- const jobs = Math.min(byCpu, byMemory);
38360
- return Math.max(1, Math.min(jobs, Math.floor(buildJobs(cpus, memoryGb) / Math.max(1, sessions))));
38361
- }
38362
- var LOCAL_TARGET_MIN_BYTES = 25 * 1024 ** 3;
38363
- function chooseTargetDir(targetDir, freeBytes2) {
38364
- if (targetDir !== "auto") return { targetDir };
38365
- if (freeBytes2 >= LOCAL_TARGET_MIN_BYTES) return { targetDir: "local" };
38366
- return {
38367
- targetDir: "separate",
38368
- warning: "Rust builds write through the mapped workspace; this can overload your PC's disk (C: has less than 25 GB free for a local build folder)"
38369
- };
38370
- }
38371
- function cargoLinkerVar(host) {
38372
- return "CARGO_TARGET_" + host.toUpperCase().replace(/[^A-Z0-9]/g, "_") + "_LINKER";
38373
- }
38374
-
38375
38408
  // src/guest/governor/decide.ts
38409
+ var COMPILERS = /* @__PURE__ */ new Set([
38410
+ "rustc",
38411
+ "clippy-driver",
38412
+ "rustdoc",
38413
+ "cc1",
38414
+ "cc1plus",
38415
+ "cc1obj",
38416
+ "collect2",
38417
+ "gcc",
38418
+ "g++",
38419
+ "c++",
38420
+ "cc",
38421
+ "clang",
38422
+ "clang++",
38423
+ "clang-cl",
38424
+ "cl",
38425
+ "link",
38426
+ "lld",
38427
+ "lld-link",
38428
+ "ld",
38429
+ "ld.lld",
38430
+ "as",
38431
+ "tsc",
38432
+ "javac"
38433
+ ]);
38434
+ var NEVER2 = /* @__PURE__ */ new Set([
38435
+ "claude",
38436
+ "codex",
38437
+ "gemini",
38438
+ "opencode",
38439
+ "aider",
38440
+ "cursor-agent",
38441
+ "cmd",
38442
+ "powershell",
38443
+ "pwsh",
38444
+ "bash",
38445
+ "sh",
38446
+ "zsh",
38447
+ "git",
38448
+ "conhost",
38449
+ "openconsole",
38450
+ "windowsterminal",
38451
+ "wt",
38452
+ "ptyhost",
38453
+ "memgov",
38454
+ "sandboxtools",
38455
+ "sbx-db",
38456
+ "explorer",
38457
+ "csrss",
38458
+ "wininit",
38459
+ "winlogon",
38460
+ "services",
38461
+ "svchost",
38462
+ "lsass",
38463
+ "system",
38464
+ "smss",
38465
+ "dwm"
38466
+ ]);
38376
38467
  function linkerSlots(totalMb, cpus) {
38377
38468
  return Math.max(1, Math.min(4, Math.max(1, Math.floor(cpus)), Math.floor(totalMb / 6144)));
38378
38469
  }
38470
+ var GATE_NAMES = [...COMPILERS, "shadercompileworker"].filter((n) => !NEVER2.has(n)).sort();
38379
38471
 
38380
38472
  // src/guest/toolchains/native/rust-extras.ts
38381
38473
  function resolveTargetDir(rust, free = freeBytes((process.env.SystemDrive ?? "C:") + "\\"), note = warn) {
@@ -42395,8 +42487,37 @@ var OutputFilter = class {
42395
42487
  }
42396
42488
  };
42397
42489
 
42398
- // src/shared/pty/console-input.ts
42490
+ // src/shared/pty/clipboard-watch.ts
42399
42491
  import { spawn as spawn15 } from "node:child_process";
42492
+ var MAX_PENDING = 1024;
42493
+ function watchClipboard(onChange) {
42494
+ if (process.platform !== "win32") return { stop: () => void 0 };
42495
+ let child = null;
42496
+ try {
42497
+ child = spawn15(SYSTEM.powershell(), scriptArgs("watch-clipboard.ps1", ["-ProcessId", String(process.pid)]), {
42498
+ stdio: ["ignore", "pipe", "ignore"],
42499
+ windowsHide: true
42500
+ });
42501
+ } catch {
42502
+ return { stop: () => void 0 };
42503
+ }
42504
+ let pending = "";
42505
+ child.stdout?.setEncoding("latin1");
42506
+ child.stdout?.on("data", (text2) => {
42507
+ const lines = (pending + text2).split("\n");
42508
+ pending = (lines.pop() ?? "").slice(-MAX_PENDING);
42509
+ for (const line of lines) if (line.trim() === "changed") onChange();
42510
+ });
42511
+ child.on("error", () => void 0);
42512
+ return {
42513
+ stop: () => {
42514
+ if (child && child.exitCode === null && child.signalCode === null) child.kill();
42515
+ }
42516
+ };
42517
+ }
42518
+
42519
+ // src/shared/pty/console-input.ts
42520
+ import { spawn as spawn16 } from "node:child_process";
42400
42521
  function enableVtInput() {
42401
42522
  if (process.platform !== "win32" || !process.stdin.isTTY)
42402
42523
  return { ready: Promise.resolve(false), stop: () => Promise.resolve() };
@@ -42404,7 +42525,7 @@ function enableVtInput() {
42404
42525
  let exited2 = Promise.resolve();
42405
42526
  const ready = new Promise((resolve2) => {
42406
42527
  try {
42407
- child = spawn15(SYSTEM.powershell(), scriptArgs("enable-vt-input.ps1", ["-ProcessId", String(process.pid)]), {
42528
+ child = spawn16(SYSTEM.powershell(), scriptArgs("enable-vt-input.ps1", ["-ProcessId", String(process.pid)]), {
42408
42529
  stdio: "ignore",
42409
42530
  windowsHide: true
42410
42531
  });
@@ -42463,30 +42584,94 @@ function unfinishedSequence(data) {
42463
42584
  return data.length;
42464
42585
  }
42465
42586
 
42466
- // src/shared/pty/ctrl-c.ts
42587
+ // src/shared/web/protocol.ts
42588
+ var MAX_CLIENT_MESSAGE_BYTES = 256 * 1024;
42589
+
42590
+ // src/shared/web/ctrl-c.ts
42467
42591
  var CTRL_C_CONFIRM_MS = 1500;
42468
42592
  var CTRL_C_HINT = "Ctrl+C again to send it to the program (Esc stops an agent)";
42469
- var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
42470
- var CtrlCGuard = class {
42593
+ var CTRL_C_COPY_HINT = "Copied: Ctrl+C after selecting text is not sent to the program (Esc stops an agent)";
42594
+ var CtrlCDecider = class {
42595
+ constructor(confirm = true) {
42596
+ this.confirm = confirm;
42597
+ }
42598
+ confirm;
42471
42599
  armedAt = Number.NEGATIVE_INFINITY;
42472
- lastTitle = "";
42473
- /** What to send for one read from the keyboard: a lone Ctrl+C only when another came just before. */
42474
- push(chunk, nowMs) {
42475
- if (chunk.length !== 1 || chunk[0] !== 3) return { send: chunk, held: false };
42600
+ selected = false;
42601
+ /** Text was selected in the program: Ctrl+C is "copy" from now on. */
42602
+ selection() {
42603
+ this.selected = true;
42604
+ this.armedAt = Number.NEGATIVE_INFINITY;
42605
+ }
42606
+ /** Any other key or a click: Ctrl+C is an interrupt again. */
42607
+ otherInput() {
42608
+ this.selected = false;
42609
+ }
42610
+ /** What to do with a lone Ctrl+C pressed at `nowMs`. */
42611
+ ctrlC(nowMs) {
42612
+ if (this.selected) return "copy";
42613
+ if (!this.confirm) return "send";
42476
42614
  if (nowMs - this.armedAt <= CTRL_C_CONFIRM_MS) {
42477
42615
  this.armedAt = Number.NEGATIVE_INFINITY;
42478
- return { send: chunk, held: false };
42616
+ return "send";
42479
42617
  }
42480
42618
  this.armedAt = nowMs;
42481
- return { send: Buffer.alloc(0), held: true };
42619
+ return "hold";
42620
+ }
42621
+ };
42622
+ var MOUSE_REPORT = /\x1b\[<(\d{1,4});\d{1,5};\d{1,5}([Mm])|\x1b\[M([\s\S])[\s\S]{2}/g;
42623
+ function classifyInput(text2) {
42624
+ let drag = false;
42625
+ let click = false;
42626
+ for (const m of text2.matchAll(MOUSE_REPORT)) {
42627
+ const sgr = m[1] !== void 0;
42628
+ const b = sgr ? Number(m[1]) : (m[3] ?? " ").charCodeAt(0) - 32;
42629
+ if (b & 64) continue;
42630
+ if (b & 32) {
42631
+ if ((b & 3) !== 3) drag = true;
42632
+ } else if (sgr ? m[2] === "M" : (b & 3) !== 3) click = true;
42633
+ }
42634
+ return { mouse: drag ? "drag" : click ? "click" : null, keys: text2.replace(MOUSE_REPORT, "").length > 0 };
42635
+ }
42636
+ function hasClipboardWrite(text2) {
42637
+ return /\x1b\]0{0,2}52;/.test(text2) || /\u009d0{0,2}52;/.test(text2);
42638
+ }
42639
+
42640
+ // src/shared/pty/ctrl-c.ts
42641
+ var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
42642
+ var CtrlCGuard = class {
42643
+ decider;
42644
+ lastTitle = "";
42645
+ constructor(options = {}) {
42646
+ this.decider = new CtrlCDecider(options.confirm !== false);
42647
+ }
42648
+ /** What to send for one read from the keyboard: a lone Ctrl+C only when it is not held back or taken as "copy". */
42649
+ push(chunk, nowMs) {
42650
+ if (chunk.length === 1 && chunk[0] === 3) {
42651
+ const action = this.decider.ctrlC(nowMs);
42652
+ if (action === "send") return { send: chunk, held: false, copied: false };
42653
+ return { send: Buffer.alloc(0), held: action === "hold", copied: action === "copy" };
42654
+ }
42655
+ const c = classifyInput(chunk.toString("latin1"));
42656
+ if (c.keys || c.mouse === "click") this.decider.otherInput();
42657
+ else if (c.mouse === "drag") this.decider.selection();
42658
+ return { send: chunk, held: false, copied: false };
42659
+ }
42660
+ /** The clipboard changed since the last key: you just copied. */
42661
+ clipboardChanged() {
42662
+ this.decider.selection();
42663
+ }
42664
+ /** The program wrote to the clipboard: that is a selection too. */
42665
+ watchClipboard(raw) {
42666
+ if (hasClipboardWrite(raw)) this.decider.selection();
42482
42667
  }
42483
42668
  /** Remembers the title the program last set (from its output), to put it back after the hint. */
42484
42669
  watchOutput(text2) {
42485
42670
  for (const m of text2.matchAll(OSC_TITLE)) this.lastTitle = m[1];
42486
42671
  }
42487
42672
  /** The escape sequence that shows the hint, and the one that puts the program's title back. */
42488
- hintTitle() {
42489
- return "\x1B]0;" + CTRL_C_HINT + "\x07";
42673
+ hintTitle(kind = "hold") {
42674
+ return "\x1B]0;" + (kind === "copy" ? CTRL_C_COPY_HINT : CTRL_C_HINT) + "\x07";
42490
42675
  }
42491
42676
  restoreTitle() {
42492
42677
  return "\x1B]0;" + this.lastTitle.replace(/[\x00-\x1f\x7f]/g, "") + "\x07";
@@ -42690,6 +42875,7 @@ function runTerminalClient(socket, token, options = {}) {
42690
42875
  clearTimeout(joinTimer);
42691
42876
  clearTimeout(hintTimer);
42692
42877
  clearTimeout(vtTimer);
42878
+ clipboard.stop();
42693
42879
  socket.destroy();
42694
42880
  const tracked = mouse.tracking();
42695
42881
  const reset = "\x1B[0m\x1B[?25h" + MOUSE_OFF + (mouse.has(2004) ? "\x1B[?2004l" : "") + "\r\n";
@@ -42707,23 +42893,22 @@ function runTerminalClient(socket, token, options = {}) {
42707
42893
  if (data.length && !done) socket.write(encodeFrame2(FrameType.Input, data));
42708
42894
  };
42709
42895
  const sendInput = (data) => write(keys.push(passthrough ? mouse.filter(data) : data));
42710
- const guard = options.confirmCtrlC ? new CtrlCGuard() : null;
42896
+ const guard = new CtrlCGuard({ confirm: options.confirmCtrlC !== false });
42711
42897
  let hintTimer;
42898
+ const clipboard = watchClipboard(() => guard.clipboardChanged());
42712
42899
  const onInput = (chunk) => {
42713
42900
  if (options.detachKey !== void 0 && chunk.includes(options.detachKey)) {
42714
42901
  finish({ reason: "detach" });
42715
42902
  return;
42716
42903
  }
42717
- if (guard) {
42718
- const decided = guard.push(chunk, Date.now());
42719
- clearTimeout(hintTimer);
42720
- if (decided.held) {
42721
- stdout.write(guard.hintTitle());
42722
- hintTimer = setTimeout(() => stdout.write(guard.restoreTitle()), CTRL_C_CONFIRM_MS);
42723
- return;
42724
- }
42725
- if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard.restoreTitle());
42904
+ const decided = guard.push(chunk, Date.now());
42905
+ clearTimeout(hintTimer);
42906
+ if (decided.held || decided.copied) {
42907
+ stdout.write(guard.hintTitle(decided.copied ? "copy" : "hold"));
42908
+ hintTimer = setTimeout(() => stdout.write(guard.restoreTitle()), CTRL_C_CONFIRM_MS);
42909
+ return;
42726
42910
  }
42911
+ if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard.restoreTitle());
42727
42912
  clearTimeout(joinTimer);
42728
42913
  sendInput(joiner.push(chunk));
42729
42914
  if (joiner.holding()) joinTimer = setTimeout(() => sendInput(joiner.flush()), JOIN_MS);
@@ -42756,9 +42941,10 @@ function runTerminalClient(socket, token, options = {}) {
42756
42941
  }
42757
42942
  for (const frame of frames) {
42758
42943
  if (frame.type === FrameType.Output) {
42944
+ guard.watchClipboard(frame.payload.toString("latin1"));
42759
42945
  const out = filter.push(frame.payload);
42760
42946
  mouse.watch(out);
42761
- guard?.watchOutput(out.toString("latin1"));
42947
+ guard.watchOutput(out.toString("latin1"));
42762
42948
  stdout.write(out);
42763
42949
  } else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
42764
42950
  else if (frame.type === FrameType.Restarting) {
@@ -43851,7 +44037,7 @@ var VSCODE_LANGUAGES = [
43851
44037
  "pwsh"
43852
44038
  ];
43853
44039
  function startDaemon(env, secrets) {
43854
- spawn16(process.execPath, [path126.join(path126.dirname(process.argv[1]), "daemon.js")], {
44040
+ spawn17(process.execPath, [path126.join(path126.dirname(process.argv[1]), "daemon.js")], {
43855
44041
  detached: true,
43856
44042
  stdio: "ignore",
43857
44043
  windowsHide: true,
@@ -25530,7 +25530,7 @@ var SandboxSchema = external_exports.strictObject({
25530
25530
  'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
25531
25531
  ),
25532
25532
  pressureResponse: external_exports.boolean().describe(
25533
- "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."
25533
+ "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. A memory gate also holds new compilers and linkers for a moment when the memory of the build programs grows faster than 4 GB in 3 seconds (3 GB with vGPU), and lets them go one at a time. Yours only: a project file cannot change it."
25534
25534
  ),
25535
25535
  vGpu: external_exports.boolean().describe(
25536
25536
  "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)."
@@ -27728,6 +27728,8 @@ var PressureStatusSchema = external_exports.object({
27728
27728
  lowered: external_exports.number().int().min(0).max(1024),
27729
27729
  /** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
27730
27730
  paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
27731
+ /** Build programs the memory gate holds right now (let go one at a time). */
27732
+ held: external_exports.number().int().min(0).max(1024).optional(),
27731
27733
  /** The CPU share the compilers get together (percent; 100 = no cap). */
27732
27734
  cpuPercent: external_exports.number().int().min(0).max(100).optional(),
27733
27735
  /** The PC itself asked for slowing down (its memory or CPU is low). */
@@ -27748,6 +27750,8 @@ var HeartbeatSchema = external_exports.object({
27748
27750
  topProcesses: external_exports.array(external_exports.object({ name: Text(64), privateMb: external_exports.number().int().min(0).max(1e7) })).max(5),
27749
27751
  /** The disk queue this PC last reported while asking the sandbox to slow down. */
27750
27752
  diskQueueReported: external_exports.number().min(0).max(1e5).optional(),
27753
+ /** Build programs the memory gate holds right now (let go one at a time). */
27754
+ held: external_exports.number().int().min(0).max(1024).optional(),
27751
27755
  /** "ending": the sandbox is shutting down in order (idle shutdown, sandbox stop, Windows shutting down). */
27752
27756
  phase: external_exports.enum(["ready", "working", "ending"])
27753
27757
  });
@@ -25916,7 +25916,7 @@ var SandboxSchema = external_exports.strictObject({
25916
25916
  'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
25917
25917
  ),
25918
25918
  pressureResponse: external_exports.boolean().describe(
25919
- "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."
25919
+ "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. A memory gate also holds new compilers and linkers for a moment when the memory of the build programs grows faster than 4 GB in 3 seconds (3 GB with vGPU), and lets them go one at a time. Yours only: a project file cannot change it."
25920
25920
  ),
25921
25921
  vGpu: external_exports.boolean().describe(
25922
25922
  "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)."
@@ -28114,6 +28114,8 @@ var PressureStatusSchema = external_exports.object({
28114
28114
  lowered: external_exports.number().int().min(0).max(1024),
28115
28115
  /** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
28116
28116
  paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
28117
+ /** Build programs the memory gate holds right now (let go one at a time). */
28118
+ held: external_exports.number().int().min(0).max(1024).optional(),
28117
28119
  /** The CPU share the compilers get together (percent; 100 = no cap). */
28118
28120
  cpuPercent: external_exports.number().int().min(0).max(100).optional(),
28119
28121
  /** The PC itself asked for slowing down (its memory or CPU is low). */
@@ -28134,6 +28136,8 @@ var HeartbeatSchema = external_exports.object({
28134
28136
  topProcesses: external_exports.array(external_exports.object({ name: Text(64), privateMb: external_exports.number().int().min(0).max(1e7) })).max(5),
28135
28137
  /** The disk queue this PC last reported while asking the sandbox to slow down. */
28136
28138
  diskQueueReported: external_exports.number().min(0).max(1e5).optional(),
28139
+ /** Build programs the memory gate holds right now (let go one at a time). */
28140
+ held: external_exports.number().int().min(0).max(1024).optional(),
28137
28141
  /** "ending": the sandbox is shutting down in order (idle shutdown, sandbox stop, Windows shutting down). */
28138
28142
  phase: external_exports.enum(["ready", "working", "ending"])
28139
28143
  });