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.
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-RU7XRN62.js → chunk-CB44HTTN.js} +196 -75
- package/dist/bin/{chunk-FA5VWLP4.js → chunk-UZ5S3EMB.js} +1 -1
- package/dist/bin/{chunk-4M5SZZ5P.js → chunk-ZMZI3625.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/core/schema/sandbox.js +1 -1
- package/dist/guest/daemon/heartbeat.js +1 -0
- package/dist/guest/governor/core.d.ts +53 -1
- package/dist/guest/governor/core.js +95 -1
- package/dist/guest/governor/decide.d.ts +4 -0
- package/dist/guest/governor/decide.js +2 -0
- package/dist/guest/governor/governor.js +23 -9
- package/dist/guest/toolchains/native/unreal.js +22 -3
- package/dist/guest/toolchains/runtimes.js +7 -6
- package/dist/host/life/crash-report.d.ts +4 -0
- package/dist/host/life/crash-report.js +30 -1
- package/dist/host/life/last-end.js +1 -0
- package/dist/host/tools/windows-terminal.d.ts +4 -1
- package/dist/host/tools/windows-terminal.js +25 -9
- package/dist/runtime/agent.js +5 -1
- package/dist/runtime/daemon.js +183 -70
- package/dist/runtime/db.js +5 -1
- package/dist/runtime/main.js +242 -56
- package/dist/runtime/netproxy.js +5 -1
- package/dist/runtime/tool.js +5 -1
- package/dist/runtime/view.js +125 -27
- package/dist/selftest/agent-paths.test.js +3 -1
- package/dist/selftest/channel.test.js +33 -0
- package/dist/selftest/heavy-load.test.js +116 -4
- package/dist/selftest/live-terminal.test.js +103 -0
- package/dist/selftest/personalization.test.js +2 -1
- package/dist/selftest/support/engine-golden.js +2 -0
- package/dist/shared/channel/schema.d.ts +2 -0
- package/dist/shared/channel/schema.js +4 -0
- package/dist/shared/memory/index.d.ts +1 -0
- package/dist/shared/memory/index.js +1 -0
- package/dist/shared/memory/policy.d.ts +12 -0
- package/dist/shared/memory/policy.js +4 -0
- package/dist/shared/memory/unreal-build.d.ts +2 -0
- package/dist/shared/memory/unreal-build.js +21 -0
- package/dist/shared/pty/clipboard-watch.d.ts +4 -0
- package/dist/shared/pty/clipboard-watch.js +40 -0
- package/dist/shared/pty/ctrl-c.d.ts +13 -7
- package/dist/shared/pty/ctrl-c.js +35 -19
- package/dist/shared/pty/index.d.ts +1 -0
- package/dist/shared/pty/index.js +1 -0
- package/dist/shared/pty/terminal.d.ts +1 -1
- package/dist/shared/pty/terminal.js +16 -13
- package/dist/shared/web/ctrl-c.d.ts +26 -0
- package/dist/shared/web/ctrl-c.js +64 -0
- package/dist/shared/web/index.d.ts +1 -0
- package/dist/shared/web/index.js +1 -0
- package/dist/web/index.html +1 -1
- package/dist/web/{main-NKM7ECSB.js → main-7NY4X6YU.js} +67 -67
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/package.json +1 -1
- package/sandbox/csharp/ClipboardWatch.cs +59 -0
- package/sandbox/csharp/MemGov.cs +752 -7
- package/sandbox/scripts/watch-clipboard.ps1 +8 -0
- package/schemas/config.schema.json +1 -1
|
@@ -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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/agent-sandbox.ts
|
|
9
9
|
run(process.argv.slice(2));
|
|
@@ -46223,7 +46223,7 @@ var SandboxSchema = external_exports.strictObject({
|
|
|
46223
46223
|
'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.'
|
|
46224
46224
|
),
|
|
46225
46225
|
pressureResponse: external_exports.boolean().describe(
|
|
46226
|
-
"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."
|
|
46226
|
+
"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."
|
|
46227
46227
|
),
|
|
46228
46228
|
vGpu: external_exports.boolean().describe(
|
|
46229
46229
|
"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)."
|
|
@@ -48941,6 +48941,8 @@ var PressureStatusSchema = external_exports.object({
|
|
|
48941
48941
|
lowered: external_exports.number().int().min(0).max(1024),
|
|
48942
48942
|
/** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
|
|
48943
48943
|
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),
|
|
48944
|
+
/** Build programs the memory gate holds right now (let go one at a time). */
|
|
48945
|
+
held: external_exports.number().int().min(0).max(1024).optional(),
|
|
48944
48946
|
/** The CPU share the compilers get together (percent; 100 = no cap). */
|
|
48945
48947
|
cpuPercent: external_exports.number().int().min(0).max(100).optional(),
|
|
48946
48948
|
/** The PC itself asked for slowing down (its memory or CPU is low). */
|
|
@@ -48961,6 +48963,8 @@ var HeartbeatSchema = external_exports.object({
|
|
|
48961
48963
|
topProcesses: external_exports.array(external_exports.object({ name: Text(64), privateMb: external_exports.number().int().min(0).max(1e7) })).max(5),
|
|
48962
48964
|
/** The disk queue this PC last reported while asking the sandbox to slow down. */
|
|
48963
48965
|
diskQueueReported: external_exports.number().min(0).max(1e5).optional(),
|
|
48966
|
+
/** Build programs the memory gate holds right now (let go one at a time). */
|
|
48967
|
+
held: external_exports.number().int().min(0).max(1024).optional(),
|
|
48964
48968
|
/** "ending": the sandbox is shutting down in order (idle shutdown, sandbox stop, Windows shutting down). */
|
|
48965
48969
|
phase: external_exports.enum(["ready", "working", "ending"])
|
|
48966
48970
|
});
|
|
@@ -53743,7 +53747,7 @@ var clock = (iso) => {
|
|
|
53743
53747
|
};
|
|
53744
53748
|
function heartbeatLine(hb) {
|
|
53745
53749
|
const top = hb.topProcesses.map((p) => safeText(p.name) + " " + p.privateMb + " MB").join(", ");
|
|
53746
|
-
return "last seen inside at " + clock(hb.at) + ": up " + Math.round(hb.uptimeS / 60) + " min, " + hb.ramFreePct + "% RAM free, " + hb.commitPct + "% commit used, builds at step " + hb.step + (hb.hostStep > 0 ? " (this PC asked for step " + hb.hostStep + ")" : "") + (hb.diskQueueReported !== void 0 ? ", this PC disk queue " + hb.diskQueueReported : "") + (top ? "; biggest: " + top : "");
|
|
53750
|
+
return "last seen inside at " + clock(hb.at) + ": up " + Math.round(hb.uptimeS / 60) + " min, " + hb.ramFreePct + "% RAM free, " + hb.commitPct + "% commit used, builds at step " + hb.step + (hb.hostStep > 0 ? " (this PC asked for step " + hb.hostStep + ")" : "") + (hb.diskQueueReported !== void 0 ? ", this PC disk queue " + hb.diskQueueReported : "") + (hb.held ? ", " + hb.held + " builds held by the memory gate" : "") + (top ? "; biggest: " + top : "");
|
|
53747
53751
|
}
|
|
53748
53752
|
function guessReason(hb) {
|
|
53749
53753
|
if (hb && hb.diskQueueReported !== void 0 && hb.hostStep > 0)
|
|
@@ -53817,7 +53821,12 @@ function findingLines(events) {
|
|
|
53817
53821
|
);
|
|
53818
53822
|
if (has2((e) => lower(e).startsWith("hyper-v")))
|
|
53819
53823
|
lines.push("Hyper-V events: the sandbox's virtual machine (or the service that runs it) reported a problem.");
|
|
53820
|
-
|
|
53824
|
+
const isAppCrash = (e) => /^(application error|windows error reporting)$/i.test(e.provider);
|
|
53825
|
+
if (has2((e) => isAppCrash(e) && /vmwp\.exe/i.test(e.process)))
|
|
53826
|
+
lines.push(
|
|
53827
|
+
"vmwp.exe, the Windows program that runs the sandbox's VM, crashed. That is a fault in Windows' Hyper-V code or a driver it uses (with vGPU on, usually the graphics driver), not a program inside the sandbox running out of memory."
|
|
53828
|
+
);
|
|
53829
|
+
else if (has2(isAppCrash))
|
|
53821
53830
|
lines.push("A crash report names vmwp.exe or vmmem, the programs that hold the sandbox's VM.");
|
|
53822
53831
|
return lines;
|
|
53823
53832
|
}
|
|
@@ -53867,6 +53876,17 @@ function hostMemoryTail(storageRoot, dataPath) {
|
|
|
53867
53876
|
return "";
|
|
53868
53877
|
}
|
|
53869
53878
|
}
|
|
53879
|
+
function memoryWasFineLine(hostMemoryLog) {
|
|
53880
|
+
const last = hostMemoryLog.split(/\r?\n/).filter((l) => l.trim() !== "").pop();
|
|
53881
|
+
if (!last) return null;
|
|
53882
|
+
const ram = /RAM free\/total MB (\d{1,9})\/(\d{1,9})/.exec(last);
|
|
53883
|
+
const commit = /commit free\/limit MB (\d{1,9})\/(\d{1,9})/.exec(last);
|
|
53884
|
+
if (!ram || !commit) return null;
|
|
53885
|
+
const freeRam = Number(ram[1]);
|
|
53886
|
+
const freeCommit = Number(commit[1]);
|
|
53887
|
+
if (freeRam < 4096 || freeCommit < 4096) return null;
|
|
53888
|
+
return "This PC still had " + Math.floor(freeRam / 1024) + " GB of RAM and " + Math.floor(freeCommit / 1024) + " GB of memory (RAM plus paging file) free just before, so it did not run out of memory.";
|
|
53889
|
+
}
|
|
53870
53890
|
function crashReportText(cause, events, memoryLog, lastSeen, extra = {}) {
|
|
53871
53891
|
const seen = /* @__PURE__ */ new Set();
|
|
53872
53892
|
const unique = events.filter((e) => {
|
|
@@ -53882,6 +53902,7 @@ function crashReportText(cause, events, memoryLog, lastSeen, extra = {}) {
|
|
|
53882
53902
|
const hostLines = (extra.hostMemoryLog ?? "").split(/\r?\n/).filter(Boolean).slice(-20).map((l) => " " + safeText(l));
|
|
53883
53903
|
const freeze = freezeLine(cause, lastSeen);
|
|
53884
53904
|
const meaning = findingLines(unique);
|
|
53905
|
+
const fine = memoryWasFineLine(extra.hostMemoryLog ?? "");
|
|
53885
53906
|
const dumps = extra.dumps ?? [];
|
|
53886
53907
|
const vgpu = extra.vgpu ? ["vGPU was on for this sandbox. " + vgpuWarning("its launch settings"), ""] : [];
|
|
53887
53908
|
return [
|
|
@@ -53895,6 +53916,7 @@ function crashReportText(cause, events, memoryLog, lastSeen, extra = {}) {
|
|
|
53895
53916
|
...vgpu,
|
|
53896
53917
|
"What that usually means:",
|
|
53897
53918
|
...meaning.length ? meaning.map((l) => " " + l) : [" (no memory, blue screen or hardware event was logged)"],
|
|
53919
|
+
...fine ? [" " + fine] : [],
|
|
53898
53920
|
"",
|
|
53899
53921
|
"Crash dumps Windows left (C:\\Windows\\Minidump, MEMORY.DMP):",
|
|
53900
53922
|
...dumps.length ? dumps.map((d) => " " + d.name + " " + d.at) : [" (none from that time)"],
|
|
@@ -65192,8 +65214,37 @@ var OutputFilter = class {
|
|
|
65192
65214
|
}
|
|
65193
65215
|
};
|
|
65194
65216
|
|
|
65195
|
-
// src/shared/pty/
|
|
65217
|
+
// src/shared/pty/clipboard-watch.ts
|
|
65196
65218
|
import { spawn as spawn11 } from "node:child_process";
|
|
65219
|
+
var MAX_PENDING = 1024;
|
|
65220
|
+
function watchClipboard(onChange) {
|
|
65221
|
+
if (process.platform !== "win32") return { stop: () => void 0 };
|
|
65222
|
+
let child = null;
|
|
65223
|
+
try {
|
|
65224
|
+
child = spawn11(SYSTEM.powershell(), scriptArgs("watch-clipboard.ps1", ["-ProcessId", String(process.pid)]), {
|
|
65225
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
65226
|
+
windowsHide: true
|
|
65227
|
+
});
|
|
65228
|
+
} catch {
|
|
65229
|
+
return { stop: () => void 0 };
|
|
65230
|
+
}
|
|
65231
|
+
let pending = "";
|
|
65232
|
+
child.stdout?.setEncoding("latin1");
|
|
65233
|
+
child.stdout?.on("data", (text) => {
|
|
65234
|
+
const lines = (pending + text).split("\n");
|
|
65235
|
+
pending = (lines.pop() ?? "").slice(-MAX_PENDING);
|
|
65236
|
+
for (const line of lines) if (line.trim() === "changed") onChange();
|
|
65237
|
+
});
|
|
65238
|
+
child.on("error", () => void 0);
|
|
65239
|
+
return {
|
|
65240
|
+
stop: () => {
|
|
65241
|
+
if (child && child.exitCode === null && child.signalCode === null) child.kill();
|
|
65242
|
+
}
|
|
65243
|
+
};
|
|
65244
|
+
}
|
|
65245
|
+
|
|
65246
|
+
// src/shared/pty/console-input.ts
|
|
65247
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
65197
65248
|
function enableVtInput() {
|
|
65198
65249
|
if (process.platform !== "win32" || !process.stdin.isTTY)
|
|
65199
65250
|
return { ready: Promise.resolve(false), stop: () => Promise.resolve() };
|
|
@@ -65201,7 +65252,7 @@ function enableVtInput() {
|
|
|
65201
65252
|
let exited = Promise.resolve();
|
|
65202
65253
|
const ready = new Promise((resolve) => {
|
|
65203
65254
|
try {
|
|
65204
|
-
child =
|
|
65255
|
+
child = spawn12(SYSTEM.powershell(), scriptArgs("enable-vt-input.ps1", ["-ProcessId", String(process.pid)]), {
|
|
65205
65256
|
stdio: "ignore",
|
|
65206
65257
|
windowsHide: true
|
|
65207
65258
|
});
|
|
@@ -65260,30 +65311,118 @@ function unfinishedSequence(data) {
|
|
|
65260
65311
|
return data.length;
|
|
65261
65312
|
}
|
|
65262
65313
|
|
|
65263
|
-
// src/shared/
|
|
65314
|
+
// src/shared/web/protocol.ts
|
|
65315
|
+
var CSRF_HEADER = "x-sandbox-web";
|
|
65316
|
+
var CSRF_VALUE = "1";
|
|
65317
|
+
var COOKIE_NAME = "sbxweb";
|
|
65318
|
+
var MIN_COLS = 10;
|
|
65319
|
+
var MAX_COLS = 500;
|
|
65320
|
+
var MIN_ROWS = 2;
|
|
65321
|
+
var MAX_ROWS = 300;
|
|
65322
|
+
var MAX_CLIENT_MESSAGE_BYTES = 256 * 1024;
|
|
65323
|
+
function parseClientMessage(text) {
|
|
65324
|
+
let value;
|
|
65325
|
+
try {
|
|
65326
|
+
value = JSON.parse(text);
|
|
65327
|
+
} catch {
|
|
65328
|
+
return null;
|
|
65329
|
+
}
|
|
65330
|
+
if (typeof value !== "object" || value === null) return null;
|
|
65331
|
+
const m = value;
|
|
65332
|
+
if (m.t !== "resize") return null;
|
|
65333
|
+
const { cols, rows } = m;
|
|
65334
|
+
if (!Number.isInteger(cols) || !Number.isInteger(rows)) return null;
|
|
65335
|
+
const c2 = cols;
|
|
65336
|
+
const r = rows;
|
|
65337
|
+
if (c2 < MIN_COLS || c2 > MAX_COLS || r < MIN_ROWS || r > MAX_ROWS) return null;
|
|
65338
|
+
return { t: "resize", cols: c2, rows: r };
|
|
65339
|
+
}
|
|
65340
|
+
|
|
65341
|
+
// src/shared/web/ctrl-c.ts
|
|
65264
65342
|
var CTRL_C_CONFIRM_MS = 1500;
|
|
65265
65343
|
var CTRL_C_HINT = "Ctrl+C again to send it to the program (Esc stops an agent)";
|
|
65266
|
-
var
|
|
65267
|
-
var
|
|
65344
|
+
var CTRL_C_COPY_HINT = "Copied: Ctrl+C after selecting text is not sent to the program (Esc stops an agent)";
|
|
65345
|
+
var CtrlCDecider = class {
|
|
65346
|
+
constructor(confirm = true) {
|
|
65347
|
+
this.confirm = confirm;
|
|
65348
|
+
}
|
|
65349
|
+
confirm;
|
|
65268
65350
|
armedAt = Number.NEGATIVE_INFINITY;
|
|
65269
|
-
|
|
65270
|
-
/**
|
|
65271
|
-
|
|
65272
|
-
|
|
65351
|
+
selected = false;
|
|
65352
|
+
/** Text was selected in the program: Ctrl+C is "copy" from now on. */
|
|
65353
|
+
selection() {
|
|
65354
|
+
this.selected = true;
|
|
65355
|
+
this.armedAt = Number.NEGATIVE_INFINITY;
|
|
65356
|
+
}
|
|
65357
|
+
/** Any other key or a click: Ctrl+C is an interrupt again. */
|
|
65358
|
+
otherInput() {
|
|
65359
|
+
this.selected = false;
|
|
65360
|
+
}
|
|
65361
|
+
/** What to do with a lone Ctrl+C pressed at `nowMs`. */
|
|
65362
|
+
ctrlC(nowMs) {
|
|
65363
|
+
if (this.selected) return "copy";
|
|
65364
|
+
if (!this.confirm) return "send";
|
|
65273
65365
|
if (nowMs - this.armedAt <= CTRL_C_CONFIRM_MS) {
|
|
65274
65366
|
this.armedAt = Number.NEGATIVE_INFINITY;
|
|
65275
|
-
return
|
|
65367
|
+
return "send";
|
|
65276
65368
|
}
|
|
65277
65369
|
this.armedAt = nowMs;
|
|
65278
|
-
return
|
|
65370
|
+
return "hold";
|
|
65371
|
+
}
|
|
65372
|
+
};
|
|
65373
|
+
var MOUSE_REPORT = /\x1b\[<(\d{1,4});\d{1,5};\d{1,5}([Mm])|\x1b\[M([\s\S])[\s\S]{2}/g;
|
|
65374
|
+
function classifyInput(text) {
|
|
65375
|
+
let drag = false;
|
|
65376
|
+
let click = false;
|
|
65377
|
+
for (const m of text.matchAll(MOUSE_REPORT)) {
|
|
65378
|
+
const sgr = m[1] !== void 0;
|
|
65379
|
+
const b = sgr ? Number(m[1]) : (m[3] ?? " ").charCodeAt(0) - 32;
|
|
65380
|
+
if (b & 64) continue;
|
|
65381
|
+
if (b & 32) {
|
|
65382
|
+
if ((b & 3) !== 3) drag = true;
|
|
65383
|
+
} else if (sgr ? m[2] === "M" : (b & 3) !== 3) click = true;
|
|
65384
|
+
}
|
|
65385
|
+
return { mouse: drag ? "drag" : click ? "click" : null, keys: text.replace(MOUSE_REPORT, "").length > 0 };
|
|
65386
|
+
}
|
|
65387
|
+
function hasClipboardWrite(text) {
|
|
65388
|
+
return /\x1b\]0{0,2}52;/.test(text) || /\u009d0{0,2}52;/.test(text);
|
|
65389
|
+
}
|
|
65390
|
+
|
|
65391
|
+
// src/shared/pty/ctrl-c.ts
|
|
65392
|
+
var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
|
|
65393
|
+
var CtrlCGuard = class {
|
|
65394
|
+
decider;
|
|
65395
|
+
lastTitle = "";
|
|
65396
|
+
constructor(options = {}) {
|
|
65397
|
+
this.decider = new CtrlCDecider(options.confirm !== false);
|
|
65398
|
+
}
|
|
65399
|
+
/** What to send for one read from the keyboard: a lone Ctrl+C only when it is not held back or taken as "copy". */
|
|
65400
|
+
push(chunk, nowMs) {
|
|
65401
|
+
if (chunk.length === 1 && chunk[0] === 3) {
|
|
65402
|
+
const action2 = this.decider.ctrlC(nowMs);
|
|
65403
|
+
if (action2 === "send") return { send: chunk, held: false, copied: false };
|
|
65404
|
+
return { send: Buffer.alloc(0), held: action2 === "hold", copied: action2 === "copy" };
|
|
65405
|
+
}
|
|
65406
|
+
const c2 = classifyInput(chunk.toString("latin1"));
|
|
65407
|
+
if (c2.keys || c2.mouse === "click") this.decider.otherInput();
|
|
65408
|
+
else if (c2.mouse === "drag") this.decider.selection();
|
|
65409
|
+
return { send: chunk, held: false, copied: false };
|
|
65410
|
+
}
|
|
65411
|
+
/** The clipboard changed since the last key: you just copied. */
|
|
65412
|
+
clipboardChanged() {
|
|
65413
|
+
this.decider.selection();
|
|
65414
|
+
}
|
|
65415
|
+
/** The program wrote to the clipboard: that is a selection too. */
|
|
65416
|
+
watchClipboard(raw) {
|
|
65417
|
+
if (hasClipboardWrite(raw)) this.decider.selection();
|
|
65279
65418
|
}
|
|
65280
65419
|
/** Remembers the title the program last set (from its output), to put it back after the hint. */
|
|
65281
65420
|
watchOutput(text) {
|
|
65282
65421
|
for (const m of text.matchAll(OSC_TITLE)) this.lastTitle = m[1];
|
|
65283
65422
|
}
|
|
65284
65423
|
/** The escape sequence that shows the hint, and the one that puts the program's title back. */
|
|
65285
|
-
hintTitle() {
|
|
65286
|
-
return "\x1B]0;" + CTRL_C_HINT + "\x07";
|
|
65424
|
+
hintTitle(kind = "hold") {
|
|
65425
|
+
return "\x1B]0;" + (kind === "copy" ? CTRL_C_COPY_HINT : CTRL_C_HINT) + "\x07";
|
|
65287
65426
|
}
|
|
65288
65427
|
restoreTitle() {
|
|
65289
65428
|
return "\x1B]0;" + this.lastTitle.replace(/[\x00-\x1f\x7f]/g, "") + "\x07";
|
|
@@ -65487,6 +65626,7 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
65487
65626
|
clearTimeout(joinTimer);
|
|
65488
65627
|
clearTimeout(hintTimer);
|
|
65489
65628
|
clearTimeout(vtTimer);
|
|
65629
|
+
clipboard.stop();
|
|
65490
65630
|
socket.destroy();
|
|
65491
65631
|
const tracked = mouse.tracking();
|
|
65492
65632
|
const reset = "\x1B[0m\x1B[?25h" + MOUSE_OFF + (mouse.has(2004) ? "\x1B[?2004l" : "") + "\r\n";
|
|
@@ -65504,23 +65644,22 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
65504
65644
|
if (data.length && !done) socket.write(encodeFrame(FrameType.Input, data));
|
|
65505
65645
|
};
|
|
65506
65646
|
const sendInput = (data) => write(keys.push(passthrough ? mouse.filter(data) : data));
|
|
65507
|
-
const guard2 = options.confirmCtrlC
|
|
65647
|
+
const guard2 = new CtrlCGuard({ confirm: options.confirmCtrlC !== false });
|
|
65508
65648
|
let hintTimer;
|
|
65649
|
+
const clipboard = watchClipboard(() => guard2.clipboardChanged());
|
|
65509
65650
|
const onInput = (chunk) => {
|
|
65510
65651
|
if (options.detachKey !== void 0 && chunk.includes(options.detachKey)) {
|
|
65511
65652
|
finish({ reason: "detach" });
|
|
65512
65653
|
return;
|
|
65513
65654
|
}
|
|
65514
|
-
|
|
65515
|
-
|
|
65516
|
-
|
|
65517
|
-
|
|
65518
|
-
|
|
65519
|
-
|
|
65520
|
-
return;
|
|
65521
|
-
}
|
|
65522
|
-
if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard2.restoreTitle());
|
|
65655
|
+
const decided = guard2.push(chunk, Date.now());
|
|
65656
|
+
clearTimeout(hintTimer);
|
|
65657
|
+
if (decided.held || decided.copied) {
|
|
65658
|
+
stdout.write(guard2.hintTitle(decided.copied ? "copy" : "hold"));
|
|
65659
|
+
hintTimer = setTimeout(() => stdout.write(guard2.restoreTitle()), CTRL_C_CONFIRM_MS);
|
|
65660
|
+
return;
|
|
65523
65661
|
}
|
|
65662
|
+
if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard2.restoreTitle());
|
|
65524
65663
|
clearTimeout(joinTimer);
|
|
65525
65664
|
sendInput(joiner.push(chunk));
|
|
65526
65665
|
if (joiner.holding()) joinTimer = setTimeout(() => sendInput(joiner.flush()), JOIN_MS);
|
|
@@ -65553,9 +65692,10 @@ function runTerminalClient(socket, token, options = {}) {
|
|
|
65553
65692
|
}
|
|
65554
65693
|
for (const frame of frames) {
|
|
65555
65694
|
if (frame.type === FrameType.Output) {
|
|
65695
|
+
guard2.watchClipboard(frame.payload.toString("latin1"));
|
|
65556
65696
|
const out = filter.push(frame.payload);
|
|
65557
65697
|
mouse.watch(out);
|
|
65558
|
-
guard2
|
|
65698
|
+
guard2.watchOutput(out.toString("latin1"));
|
|
65559
65699
|
stdout.write(out);
|
|
65560
65700
|
} else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
|
|
65561
65701
|
else if (frame.type === FrameType.Restarting) {
|
|
@@ -73033,7 +73173,7 @@ var AccessStore = class _AccessStore {
|
|
|
73033
73173
|
};
|
|
73034
73174
|
|
|
73035
73175
|
// src/host/remote/door-client.ts
|
|
73036
|
-
import { spawn as
|
|
73176
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
73037
73177
|
var NOT_OWNER = 3;
|
|
73038
73178
|
var NO_PIPE = 4;
|
|
73039
73179
|
var NO_USER = 5;
|
|
@@ -73060,7 +73200,7 @@ async function knockOnDoor(storageRoot, owner) {
|
|
|
73060
73200
|
const exe = hostToolsExe(storageRoot);
|
|
73061
73201
|
if (!exe) fail("Windows sign-in needs HostTools, which could not be built on this PC.", "Run sandbox doctor.");
|
|
73062
73202
|
return new Promise((resolve) => {
|
|
73063
|
-
const child =
|
|
73203
|
+
const child = spawn13(exe, ["door-client", "--owner", owner], { windowsHide: true });
|
|
73064
73204
|
let out = "";
|
|
73065
73205
|
child.stdout.on("data", (d) => {
|
|
73066
73206
|
if (out.length < 1024) out += d.toString("utf8");
|
|
@@ -73174,7 +73314,7 @@ import crypto22 from "node:crypto";
|
|
|
73174
73314
|
import fs119 from "node:fs";
|
|
73175
73315
|
import os23 from "node:os";
|
|
73176
73316
|
import path168 from "node:path";
|
|
73177
|
-
import { spawn as
|
|
73317
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
73178
73318
|
|
|
73179
73319
|
// src/host/remote/lan.ts
|
|
73180
73320
|
import net7 from "node:net";
|
|
@@ -73266,7 +73406,7 @@ function removeRuleRequest() {
|
|
|
73266
73406
|
return { action: "remove", ruleName: FIREWALL_RULE_NAME };
|
|
73267
73407
|
}
|
|
73268
73408
|
var spawnRunner3 = (exe, args, timeoutMs) => new Promise((resolve) => {
|
|
73269
|
-
const child =
|
|
73409
|
+
const child = spawn14(exe, [...args], { windowsHide: true });
|
|
73270
73410
|
let stdout = "";
|
|
73271
73411
|
let stderr = "";
|
|
73272
73412
|
const timer = setTimeout(() => child.kill(), timeoutMs);
|
|
@@ -73343,35 +73483,6 @@ import https from "node:https";
|
|
|
73343
73483
|
|
|
73344
73484
|
// src/host/web/auth.ts
|
|
73345
73485
|
import crypto23 from "node:crypto";
|
|
73346
|
-
|
|
73347
|
-
// src/shared/web/protocol.ts
|
|
73348
|
-
var CSRF_HEADER = "x-sandbox-web";
|
|
73349
|
-
var CSRF_VALUE = "1";
|
|
73350
|
-
var COOKIE_NAME = "sbxweb";
|
|
73351
|
-
var MIN_COLS = 10;
|
|
73352
|
-
var MAX_COLS = 500;
|
|
73353
|
-
var MIN_ROWS = 2;
|
|
73354
|
-
var MAX_ROWS = 300;
|
|
73355
|
-
var MAX_CLIENT_MESSAGE_BYTES = 256 * 1024;
|
|
73356
|
-
function parseClientMessage(text) {
|
|
73357
|
-
let value;
|
|
73358
|
-
try {
|
|
73359
|
-
value = JSON.parse(text);
|
|
73360
|
-
} catch {
|
|
73361
|
-
return null;
|
|
73362
|
-
}
|
|
73363
|
-
if (typeof value !== "object" || value === null) return null;
|
|
73364
|
-
const m = value;
|
|
73365
|
-
if (m.t !== "resize") return null;
|
|
73366
|
-
const { cols, rows } = m;
|
|
73367
|
-
if (!Number.isInteger(cols) || !Number.isInteger(rows)) return null;
|
|
73368
|
-
const c2 = cols;
|
|
73369
|
-
const r = rows;
|
|
73370
|
-
if (c2 < MIN_COLS || c2 > MAX_COLS || r < MIN_ROWS || r > MAX_ROWS) return null;
|
|
73371
|
-
return { t: "resize", cols: c2, rows: r };
|
|
73372
|
-
}
|
|
73373
|
-
|
|
73374
|
-
// src/host/web/auth.ts
|
|
73375
73486
|
var COOKIE_LIFETIME_MS = 12 * 60 * 60 * 1e3;
|
|
73376
73487
|
var MAX_COOKIES = 50;
|
|
73377
73488
|
var MAX_FAILURES = 8;
|
|
@@ -73451,17 +73562,17 @@ function cookieHeader(value) {
|
|
|
73451
73562
|
}
|
|
73452
73563
|
|
|
73453
73564
|
// src/host/web/browser.ts
|
|
73454
|
-
import { spawn as
|
|
73565
|
+
import { spawn as spawn15 } from "node:child_process";
|
|
73455
73566
|
function openBrowser(url2) {
|
|
73456
73567
|
refuseInSelfTest("open a browser");
|
|
73457
73568
|
if (!/^http:\/\/127\.0\.0\.1:\d{1,5}\/(#[kw]=[0-9a-f]{64})?$/.test(url2)) throw new Error("Not a web UI address.");
|
|
73458
|
-
|
|
73569
|
+
spawn15(SYSTEM.cmd(), ["/c", "start", "", url2], { detached: true, stdio: "ignore", windowsHide: true }).unref();
|
|
73459
73570
|
}
|
|
73460
73571
|
var ISSUE_URL = /^https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/issues\/new\?[\w%.~&=+-]*$/;
|
|
73461
73572
|
function openIssuePage(url2) {
|
|
73462
73573
|
refuseInSelfTest("open a browser");
|
|
73463
73574
|
if (!ISSUE_URL.test(url2) || url2.length > 2e3) throw new Error("Not a GitHub new-issue address.");
|
|
73464
|
-
|
|
73575
|
+
spawn15(system32("rundll32.exe"), ["url.dll,FileProtocolHandler", url2], {
|
|
73465
73576
|
detached: true,
|
|
73466
73577
|
stdio: "ignore",
|
|
73467
73578
|
windowsHide: true
|
|
@@ -74441,7 +74552,7 @@ var WebRunner = class {
|
|
|
74441
74552
|
};
|
|
74442
74553
|
|
|
74443
74554
|
// src/host/remote/windows-helper.ts
|
|
74444
|
-
import { spawn as
|
|
74555
|
+
import { spawn as spawn16 } from "node:child_process";
|
|
74445
74556
|
import readline3 from "node:readline";
|
|
74446
74557
|
var SID2 = /^S-1-[0-9-]{1,180}$/;
|
|
74447
74558
|
var MEDIUM_INTEGRITY = 8192;
|
|
@@ -74480,7 +74591,7 @@ var HostToolsHelper = class _HostToolsHelper {
|
|
|
74480
74591
|
answer = async () => "refused Windows sign-in is off.";
|
|
74481
74592
|
problem = () => void 0;
|
|
74482
74593
|
constructor(exe, pipe2) {
|
|
74483
|
-
this.child =
|
|
74594
|
+
this.child = spawn16(exe, ["web-helper", "--pipe", pipe2 ?? "", "--server-pid", String(process.pid)], {
|
|
74484
74595
|
windowsHide: true,
|
|
74485
74596
|
stdio: ["pipe", "pipe", "pipe"]
|
|
74486
74597
|
});
|
|
@@ -80151,6 +80262,9 @@ var SETTINGS = {
|
|
|
80151
80262
|
theme: "dark",
|
|
80152
80263
|
firstWindowPreference: "defaultProfile",
|
|
80153
80264
|
confirmCloseAllTabs: false,
|
|
80265
|
+
// Copied the moment the mouse is released, so an agent's redraw cannot clear the selection first.
|
|
80266
|
+
copyOnSelect: true,
|
|
80267
|
+
copyFormatting: "none",
|
|
80154
80268
|
// New tabs pick up the PATH and variables the runner writes machine-wide after the window opened.
|
|
80155
80269
|
compatibility: { reloadEnvironmentVariables: true },
|
|
80156
80270
|
warning: { confirmCloseAllTabs: false, largePaste: false, multiLinePaste: false },
|
|
@@ -80189,6 +80303,10 @@ function withReloadEnvironment(settings) {
|
|
|
80189
80303
|
if (compatibility?.reloadEnvironmentVariables === true) return null;
|
|
80190
80304
|
return { ...settings, compatibility: { ...compatibility, reloadEnvironmentVariables: true } };
|
|
80191
80305
|
}
|
|
80306
|
+
function withCopyOnSelect(settings) {
|
|
80307
|
+
if ("copyOnSelect" in settings) return null;
|
|
80308
|
+
return { ...settings, copyOnSelect: true };
|
|
80309
|
+
}
|
|
80192
80310
|
function syncPwshProfile(dataPath, allowed) {
|
|
80193
80311
|
const file2 = path185.join(terminalDir(dataPath), "settings", "settings.json");
|
|
80194
80312
|
assertTestWritable2(file2);
|
|
@@ -80206,15 +80324,18 @@ function syncPwshProfile(dataPath, allowed) {
|
|
|
80206
80324
|
}
|
|
80207
80325
|
const withProfile = withPwshProfile(parsed, visible);
|
|
80208
80326
|
if (withProfile) {
|
|
80209
|
-
|
|
80327
|
+
const reloaded = withReloadEnvironment(withProfile) ?? withProfile;
|
|
80328
|
+
writeJson(file2, withCopyOnSelect(reloaded) ?? reloaded);
|
|
80210
80329
|
return;
|
|
80211
80330
|
}
|
|
80212
|
-
|
|
80213
|
-
|
|
80214
|
-
|
|
80215
|
-
|
|
80216
|
-
|
|
80217
|
-
|
|
80331
|
+
const missing = [];
|
|
80332
|
+
if (withReloadEnvironment(parsed)) missing.push([["compatibility", "reloadEnvironmentVariables"], true]);
|
|
80333
|
+
if (withCopyOnSelect(parsed)) missing.push([["copyOnSelect"], true]);
|
|
80334
|
+
if (missing.length === 0) return;
|
|
80335
|
+
let edited = text;
|
|
80336
|
+
for (const [at, value] of missing)
|
|
80337
|
+
edited = applyEdits(edited, modify(edited, at, value, { formattingOptions: { insertSpaces: true, tabSize: 4 } }));
|
|
80338
|
+
writeFileAtomic(file2, edited);
|
|
80218
80339
|
}
|
|
80219
80340
|
async function ensureTerminal(dataPath, refresh, options = {}) {
|
|
80220
80341
|
const result = await installTerminal(dataPath, refresh);
|
|
@@ -85335,7 +85456,7 @@ async function attachOpened(ctx, session) {
|
|
|
85335
85456
|
nextStep("sandbox attach " + session);
|
|
85336
85457
|
return 0;
|
|
85337
85458
|
}
|
|
85338
|
-
const { attach: attach2 } = await import("./chunk-
|
|
85459
|
+
const { attach: attach2 } = await import("./chunk-UZ5S3EMB.js");
|
|
85339
85460
|
return attach2({ ...ctx, options: { ...ctx.options, positionals: [session] } });
|
|
85340
85461
|
}
|
|
85341
85462
|
function definitionHandler(def) {
|
|
@@ -86295,6 +86416,8 @@ export {
|
|
|
86295
86416
|
NAV,
|
|
86296
86417
|
withOperationCommands,
|
|
86297
86418
|
SandboxChannel,
|
|
86419
|
+
CSRF_HEADER,
|
|
86420
|
+
CSRF_VALUE,
|
|
86298
86421
|
reloadSettings,
|
|
86299
86422
|
esm_default4 as esm_default,
|
|
86300
86423
|
esm_default11 as esm_default2,
|
|
@@ -86354,8 +86477,6 @@ export {
|
|
|
86354
86477
|
settingRow,
|
|
86355
86478
|
ProjectsService,
|
|
86356
86479
|
StorageService,
|
|
86357
|
-
CSRF_HEADER,
|
|
86358
|
-
CSRF_VALUE,
|
|
86359
86480
|
openBrowser,
|
|
86360
86481
|
import_websocket,
|
|
86361
86482
|
INSTALL,
|
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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.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-ZMZI3625.js";
|
|
6
|
+
import "./chunk-CB44HTTN.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-show.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "show" });
|
|
@@ -48,7 +48,7 @@ export const SandboxSchema = z.strictObject({
|
|
|
48
48
|
.describe('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.'),
|
|
49
49
|
pressureResponse: z
|
|
50
50
|
.boolean()
|
|
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.'),
|
|
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. 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.'),
|
|
52
52
|
vGpu: z
|
|
53
53
|
.boolean()
|
|
54
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)."),
|
|
@@ -23,6 +23,7 @@ export function buildHeartbeat(snapshot, sessionCount, uptimeSeconds, freeBytes,
|
|
|
23
23
|
...(snapshot?.diskQueue !== null && snapshot?.diskQueue !== undefined
|
|
24
24
|
? { diskQueueReported: snapshot.diskQueue }
|
|
25
25
|
: {}),
|
|
26
|
+
...(snapshot && snapshot.held > 0 ? { held: Math.min(1024, snapshot.held) } : {}),
|
|
26
27
|
phase: ending ? 'ending' : sessionCount > 0 ? 'working' : 'ready',
|
|
27
28
|
};
|
|
28
29
|
}
|