windows-development-sandbox 1.13.2 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.example.json +2 -1
- package/dist/app/features/defs.d.ts +1 -1
- package/dist/app/features/projects/projects.def.d.ts +1 -1
- package/dist/app/features/projects/projects.run.d.ts +1 -1
- package/dist/app/features/projects/projects.run.js +10 -2
- package/dist/app/features/sandbox/sandbox.def.js +3 -1
- package/dist/app/features/settings/categories.def.js +1 -0
- package/dist/app/features/storage/storage.run.js +1 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-VENWSGX2.js → chunk-D7CM63BS.js} +2303 -1462
- package/dist/bin/{chunk-K4SU3MHJ.js → chunk-HTQT5SBY.js} +1 -1
- package/dist/bin/{chunk-IL7BXJF2.js → chunk-RQ4BWBYX.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/launch/launch.js +1 -1
- package/dist/cli/commands/projects/here.js +2 -0
- package/dist/cli/commands/repair/checks/contained.js +1 -1
- package/dist/cli/services/health-service.js +15 -3
- package/dist/cli/services/projects-service.d.ts +8 -3
- package/dist/cli/services/projects-service.js +21 -4
- package/dist/core/config/defaults.js +1 -0
- package/dist/core/schema/config.d.ts +4 -0
- package/dist/core/schema/projects.d.ts +4 -0
- package/dist/core/schema/projects.js +3 -0
- package/dist/guest/boot/boot.js +8 -2
- package/dist/guest/daemon/daemon.js +3 -0
- package/dist/guest/daemon/live-folders.d.ts +48 -0
- package/dist/guest/daemon/live-folders.js +245 -0
- package/dist/guest/daemon/live.d.ts +4 -0
- package/dist/guest/daemon/live.js +57 -0
- package/dist/guest/daemon/sessions.d.ts +7 -0
- package/dist/guest/daemon/sessions.js +23 -2
- package/dist/guest/entries/daemon.js +5 -2
- package/dist/guest/runtime/csc.d.ts +1 -0
- package/dist/guest/runtime/csc.js +1 -0
- package/dist/guest/runtime/secrets.d.ts +5 -2
- package/dist/guest/runtime/secrets.js +12 -5
- package/dist/guest/sessions/pty-host.d.ts +10 -0
- package/dist/guest/sessions/pty-host.js +48 -3
- package/dist/host/channel/channel.js +1 -1
- package/dist/host/engines/hcs/live-folders.d.ts +117 -0
- package/dist/host/engines/hcs/live-folders.js +347 -0
- package/dist/host/engines/index.d.ts +1 -0
- package/dist/host/engines/index.js +1 -0
- package/dist/host/install/install-record.d.ts +1 -0
- package/dist/host/install/install-record.js +2 -0
- package/dist/host/launch/generate.js +8 -1
- package/dist/host/projects/join.d.ts +4 -0
- package/dist/host/projects/join.js +11 -3
- package/dist/host/projects/mapper.d.ts +34 -5
- package/dist/host/projects/mapper.js +88 -20
- package/dist/host/projects/registry.d.ts +2 -0
- package/dist/host/projects/registry.js +1 -1
- package/dist/host/sandbox/contained-deps.d.ts +2 -1
- package/dist/host/sandbox/contained-deps.js +6 -4
- package/dist/host/secrets/launch-secrets.js +2 -1
- package/dist/host/sharing/lifecycle.js +9 -1
- package/dist/host/storage/contained/contained-storage.js +13 -0
- package/dist/host/storage/contained/disk-port.d.ts +5 -0
- package/dist/host/storage/contained/helper-port.d.ts +72 -0
- package/dist/host/storage/contained/helper-port.js +162 -0
- package/dist/host/storage/contained/index.d.ts +1 -0
- package/dist/host/storage/contained/index.js +1 -0
- package/dist/host/web/bridge.d.ts +5 -0
- package/dist/host/web/bridge.js +11 -1
- package/dist/host/web/server.d.ts +2 -0
- package/dist/host/web/server.js +11 -1
- package/dist/runtime/agent.js +23 -0
- package/dist/runtime/daemon.js +523 -135
- package/dist/runtime/db.js +23 -0
- package/dist/runtime/main.js +221 -15
- package/dist/runtime/netproxy.js +23 -0
- package/dist/runtime/view.js +209 -12
- package/dist/selftest/channel.test.js +72 -1
- package/dist/selftest/contained.test.js +1 -37
- package/dist/selftest/hcs.test.js +5 -2
- package/dist/selftest/index.js +4 -0
- package/dist/selftest/install.test.js +11 -0
- package/dist/selftest/layout.test.js +1 -0
- package/dist/selftest/live-daemon.test.js +51 -1
- package/dist/selftest/live-folders.test.d.ts +2 -0
- package/dist/selftest/live-folders.test.js +588 -0
- package/dist/selftest/live-terminal.test.js +112 -4
- package/dist/selftest/projects.test.js +7 -7
- package/dist/selftest/storage-helper.test.d.ts +2 -0
- package/dist/selftest/storage-helper.test.js +493 -0
- package/dist/selftest/support/engine-golden.js +1 -0
- package/dist/selftest/support/fixtures.d.ts +1 -0
- package/dist/selftest/support/live.js +2 -0
- package/dist/selftest/support/vhdx.d.ts +14 -0
- package/dist/selftest/support/vhdx.js +72 -0
- package/dist/selftest/web.test.js +14 -2
- package/dist/shared/channel/index.d.ts +1 -0
- package/dist/shared/channel/index.js +1 -0
- package/dist/shared/channel/live.d.ts +53 -0
- package/dist/shared/channel/live.js +92 -0
- package/dist/shared/channel/run-dir.d.ts +11 -0
- package/dist/shared/channel/run-dir.js +20 -0
- package/dist/shared/channel/secrets.d.ts +1 -0
- package/dist/shared/channel/secrets.js +5 -0
- package/dist/shared/paths/projects.d.ts +6 -1
- package/dist/shared/paths/projects.js +21 -1
- package/dist/shared/pty/index.d.ts +3 -1
- package/dist/shared/pty/index.js +3 -1
- package/dist/shared/pty/key-gate.d.ts +24 -0
- package/dist/shared/pty/key-gate.js +45 -0
- package/dist/shared/pty/mouse-modes.d.ts +27 -0
- package/dist/shared/pty/mouse-modes.js +155 -0
- package/dist/shared/pty/terminal.d.ts +0 -5
- package/dist/shared/pty/terminal.js +51 -20
- package/dist/sync/watcher.js +10 -1
- package/dist/web/index.html +1 -1
- package/dist/web/{main-NBQ3LF4E.js → main-7DJZ2M27.js} +34 -34
- package/native/csharp/HcsHost/AssemblyInfo.cs +4 -4
- package/native/csharp/HcsHost/FolderAccess.cs +361 -0
- package/native/csharp/HcsHost/Hcs.cs +31 -3
- package/native/csharp/HcsHost/Program.cs +54 -6
- package/native/csharp/HcsHost/Share.cs +64 -11
- package/native/csharp/HcsHost/WsbGuard.cs +130 -0
- package/native/csharp/HcsHost/WsbShare.cs +295 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/StorageHelper/AssemblyInfo.cs +15 -0
- package/native/csharp/StorageHelper/Client.cs +297 -0
- package/native/csharp/StorageHelper/Log.cs +177 -0
- package/native/csharp/StorageHelper/MountRecords.cs +160 -0
- package/native/csharp/StorageHelper/Operations.cs +596 -0
- package/native/csharp/StorageHelper/Pins.cs +270 -0
- package/native/csharp/StorageHelper/Privileges.cs +78 -0
- package/native/csharp/StorageHelper/Program.cs +349 -0
- package/native/csharp/StorageHelper/Protocol.cs +107 -0
- package/native/csharp/StorageHelper/RateLimiter.cs +97 -0
- package/native/csharp/StorageHelper/Rules.cs +156 -0
- package/native/csharp/StorageHelper/Server.cs +656 -0
- package/native/csharp/StorageHelper/Settings.cs +297 -0
- package/native/csharp/StorageHelper/StorageService.cs +53 -0
- package/native/csharp/StorageHelper/UserSettings.cs +206 -0
- package/native/csharp/StorageHelper/Vhdx.cs +230 -0
- package/native/csharp/StorageHelper/VirtualDisk.cs +241 -0
- package/native/csharp/StorageHelper/Volumes.cs +379 -0
- package/native/csharp/StorageHelper/Watchdog.cs +128 -0
- package/native/csharp/StorageHelper/Win32.cs +250 -0
- package/native/scripts/contained-common.ps1 +4 -0
- package/native/scripts/hcs-live-share.ps1 +191 -0
- package/native/scripts/set-storage-helper.ps1 +203 -0
- package/package.json +1 -1
- package/sandbox/csharp/BindMount.cs +120 -0
- package/sandbox/csharp/PtyHost.cs +236 -1
- package/schemas/config.schema.json +8 -0
|
@@ -3,20 +3,37 @@ import { OutputFilter } from './output-filter.js';
|
|
|
3
3
|
import { enableVtInput } from './console-input.js';
|
|
4
4
|
import { InputJoiner, JOIN_MS } from './input-joiner.js';
|
|
5
5
|
import { CTRL_C_CONFIRM_MS, CtrlCGuard } from './ctrl-c.js';
|
|
6
|
+
import { KeyGate } from './key-gate.js';
|
|
7
|
+
import { MouseModes } from './mouse-modes.js';
|
|
6
8
|
/**
|
|
7
9
|
* Turns off every mouse tracking mode a program may have turned on in your terminal (normal, button, any, UTF-8, SGR,
|
|
8
10
|
* urxvt).
|
|
9
11
|
*/
|
|
10
12
|
export const MOUSE_OFF = '\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1005l\x1b[?1006l\x1b[?1015l';
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
/** After leaving: mouse reports still on their way are dropped until input is this quiet (at most SETTLE_MAX_MS). */
|
|
14
|
+
const SETTLE_QUIET_MS = 50;
|
|
15
|
+
const SETTLE_MAX_MS = 300;
|
|
16
|
+
/** Waits until `stream` has been quiet for SETTLE_QUIET_MS (or SETTLE_MAX_MS passed), dropping what it reads. */
|
|
17
|
+
function drainInput(stream) {
|
|
18
|
+
return new Promise((done) => {
|
|
19
|
+
let quiet;
|
|
20
|
+
const end = () => {
|
|
21
|
+
clearTimeout(quiet);
|
|
22
|
+
clearTimeout(cap);
|
|
23
|
+
stream.off('data', onData);
|
|
24
|
+
done();
|
|
25
|
+
};
|
|
26
|
+
const onData = () => {
|
|
27
|
+
clearTimeout(quiet);
|
|
28
|
+
quiet = setTimeout(end, SETTLE_QUIET_MS);
|
|
29
|
+
};
|
|
30
|
+
const cap = setTimeout(end, SETTLE_MAX_MS);
|
|
31
|
+
stream.on('data', onData);
|
|
32
|
+
onData();
|
|
33
|
+
});
|
|
19
34
|
}
|
|
35
|
+
/** Longest wait for the console's input mode before typed keys are sent anyway (it normally takes about 2 s). */
|
|
36
|
+
const VT_WAIT_MS = 10000;
|
|
20
37
|
/**
|
|
21
38
|
* Bridges this process's terminal to the remote program until it exits, the connection drops, or the user presses
|
|
22
39
|
* the detach key. Restores the terminal before resolving.
|
|
@@ -32,8 +49,8 @@ options = {}) {
|
|
|
32
49
|
const [c, r] = stdout.isTTY ? stdout.getWindowSize() : [0, 0];
|
|
33
50
|
return [c || 120, r || 30];
|
|
34
51
|
};
|
|
35
|
-
// Until the console
|
|
36
|
-
|
|
52
|
+
// Until the console's input mode is known (enableVtInput), what is typed waits: see KeyGate.
|
|
53
|
+
const keys = new KeyGate(process.platform === 'win32' && Boolean(stdin.isTTY));
|
|
37
54
|
return new Promise((resolve) => {
|
|
38
55
|
let done = false;
|
|
39
56
|
const reader = new FrameReader();
|
|
@@ -42,7 +59,10 @@ options = {}) {
|
|
|
42
59
|
let resizeTimer;
|
|
43
60
|
// Set once raw mode is on (below); finish() may run before that.
|
|
44
61
|
// eslint-disable-next-line prefer-const
|
|
45
|
-
let vtInput;
|
|
62
|
+
let vtInput, vtTimer;
|
|
63
|
+
// The agent's mouse modes, read from its output; only known when it is passed through (conpty.dll, see below).
|
|
64
|
+
const mouse = new MouseModes();
|
|
65
|
+
let passthrough = false;
|
|
46
66
|
const finish = (result) => {
|
|
47
67
|
if (done)
|
|
48
68
|
return;
|
|
@@ -54,11 +74,16 @@ options = {}) {
|
|
|
54
74
|
clearInterval(sizeWatch);
|
|
55
75
|
clearTimeout(joinTimer);
|
|
56
76
|
clearTimeout(hintTimer);
|
|
77
|
+
clearTimeout(vtTimer);
|
|
57
78
|
socket.destroy();
|
|
58
|
-
// The agent's mouse tracking ends with it: your terminal's wheel scrolls again (and clicks select text).
|
|
59
|
-
|
|
79
|
+
// The agent's mouse tracking ends with it: your terminal's wheel scrolls again (and clicks select text). Reports
|
|
80
|
+
// the terminal sent before it read that are dropped here, or they would reach your shell as text.
|
|
81
|
+
const tracked = mouse.tracking();
|
|
82
|
+
const reset = '\x1b[0m\x1b[?25h' + MOUSE_OFF + (mouse.has(2004) ? '\x1b[?2004l' : '') + '\r\n';
|
|
83
|
+
const flushed = new Promise((written) => stdout.write(reset, () => written()));
|
|
84
|
+
const settled = tracked ? flushed.then(() => drainInput(stdin)) : Promise.resolve();
|
|
60
85
|
// Wait for a console-mode change still in progress, then give the console back in its normal mode.
|
|
61
|
-
void (vtInput?.stop()
|
|
86
|
+
void Promise.all([settled, vtInput?.stop()]).then(() => {
|
|
62
87
|
if (stdin.isTTY)
|
|
63
88
|
stdin.setRawMode(false);
|
|
64
89
|
stdin.pause();
|
|
@@ -67,10 +92,12 @@ options = {}) {
|
|
|
67
92
|
};
|
|
68
93
|
const joiner = new InputJoiner();
|
|
69
94
|
let joinTimer;
|
|
70
|
-
const
|
|
95
|
+
const write = (data) => {
|
|
71
96
|
if (data.length && !done)
|
|
72
|
-
socket.write(encodeFrame(FrameType.Input,
|
|
97
|
+
socket.write(encodeFrame(FrameType.Input, data));
|
|
73
98
|
};
|
|
99
|
+
// Mouse reports the agent has not asked for (motion without 1002/1003 ...) are dropped: see MouseModes.
|
|
100
|
+
const sendInput = (data) => write(keys.push(passthrough ? mouse.filter(data) : data));
|
|
74
101
|
const guard = options.confirmCtrlC ? new CtrlCGuard() : null;
|
|
75
102
|
let hintTimer;
|
|
76
103
|
const onInput = (chunk) => {
|
|
@@ -99,7 +126,6 @@ options = {}) {
|
|
|
99
126
|
// repaints racing each other left the screen garbled. Wait until the size settles, clear what this terminal
|
|
100
127
|
// reflowed on its own, then let ptyhost repaint everything once at the new size. With conpty.dll (passthrough)
|
|
101
128
|
// nothing is repainted: this terminal's own reflow and scrollback stay, and the program redraws what it needs.
|
|
102
|
-
let passthrough = false;
|
|
103
129
|
const sendSize = () => {
|
|
104
130
|
const [c, r] = size();
|
|
105
131
|
if (c === sent[0] && r === sent[1])
|
|
@@ -134,13 +160,16 @@ options = {}) {
|
|
|
134
160
|
for (const frame of frames) {
|
|
135
161
|
if (frame.type === FrameType.Output) {
|
|
136
162
|
const out = filter.push(frame.payload);
|
|
163
|
+
mouse.watch(out);
|
|
137
164
|
guard?.watchOutput(out.toString('latin1'));
|
|
138
165
|
stdout.write(out);
|
|
139
166
|
}
|
|
140
167
|
else if (frame.type === FrameType.Console)
|
|
141
168
|
passthrough = frame.payload.toString('latin1') === 'conpty.dll';
|
|
142
|
-
else if (frame.type === FrameType.Restarting)
|
|
169
|
+
else if (frame.type === FrameType.Restarting) {
|
|
170
|
+
mouse.reset();
|
|
143
171
|
stdout.write(MOUSE_OFF + '\x1b[2J\x1b[3J\x1b[H');
|
|
172
|
+
}
|
|
144
173
|
else if (frame.type === FrameType.Exit)
|
|
145
174
|
finish({ reason: 'exit', exitCode: frame.payload.length >= 4 ? frame.payload.readInt32LE(0) : 1 });
|
|
146
175
|
else if (frame.type === FrameType.Error)
|
|
@@ -163,9 +192,11 @@ options = {}) {
|
|
|
163
192
|
// After setRawMode (which sets the console mode): mouse reports, focus and keys then arrive as the terminal sent
|
|
164
193
|
// them.
|
|
165
194
|
vtInput = enableVtInput();
|
|
195
|
+
// A helper that hangs must not hold the keyboard: after VT_WAIT_MS keys go as console keys until it is done.
|
|
196
|
+
vtTimer = setTimeout(() => write(keys.decide(false)), VT_WAIT_MS);
|
|
166
197
|
void vtInput.ready.then((on) => {
|
|
167
|
-
|
|
168
|
-
|
|
198
|
+
clearTimeout(vtTimer);
|
|
199
|
+
write(keys.decide(on));
|
|
169
200
|
});
|
|
170
201
|
stdin.on('data', onInput);
|
|
171
202
|
stdin.resume();
|
package/dist/sync/watcher.js
CHANGED
|
@@ -18,6 +18,7 @@ import { SandboxChannel } from '../host/channel/index.js';
|
|
|
18
18
|
import { ProjectRegistry } from '../host/projects/registry.js';
|
|
19
19
|
import { ContainedStorage, setNameOf, storageOf } from '../host/storage/index.js';
|
|
20
20
|
import { clearSecrets } from '../host/secrets/index.js';
|
|
21
|
+
import { clearLiveRecord } from '../host/engines/index.js';
|
|
21
22
|
import { endSharing, sharingDeps } from '../host/sharing/index.js';
|
|
22
23
|
import { PACKAGE_ROOT } from '../core/package-info.js';
|
|
23
24
|
import { syncBack } from './sync-cycle.js';
|
|
@@ -137,7 +138,7 @@ export class Watcher {
|
|
|
137
138
|
/** Contained storage of this data set (only when a mounted image is on record), else null. */
|
|
138
139
|
contained() {
|
|
139
140
|
try {
|
|
140
|
-
const storage = new ContainedStorage(realContainedDeps(this.storageRoot, 64), setNameOf(this.dataPath));
|
|
141
|
+
const storage = new ContainedStorage(realContainedDeps(this.storageRoot, 64, Boolean(this.resume.config)), setNameOf(this.dataPath));
|
|
141
142
|
return storage.isRecorded() ? storage : null;
|
|
142
143
|
}
|
|
143
144
|
catch {
|
|
@@ -373,6 +374,14 @@ export class Watcher {
|
|
|
373
374
|
catch (e) {
|
|
374
375
|
this.note('could not remove the one-shot secrets: ' + errMsg(e));
|
|
375
376
|
}
|
|
377
|
+
// Live folders (HCS): their shares ended with the sandbox, so their record and key go too.
|
|
378
|
+
try {
|
|
379
|
+
if (!isSandboxRunning() && clearLiveRecord(this.storageRoot, this.dataPath))
|
|
380
|
+
this.note('live folders: record cleared');
|
|
381
|
+
}
|
|
382
|
+
catch (e) {
|
|
383
|
+
this.note('could not clear the live-folder record: ' + errMsg(e));
|
|
384
|
+
}
|
|
376
385
|
// An all-users install: the record of whose sandbox this was goes, and the group loses access to the folders.
|
|
377
386
|
const sharing = sharingDeps(PACKAGE_ROOT);
|
|
378
387
|
if (sharing)
|
package/dist/web/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Sandbox</title>
|
|
7
7
|
<link rel="icon" href="data:," />
|
|
8
8
|
<link rel="stylesheet" href="/main-UAQPI5XD.css" />
|
|
9
|
-
<script type="module" src="/main-
|
|
9
|
+
<script type="module" src="/main-7DJZ2M27.js"></script>
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|