windows-development-sandbox 1.14.0 → 1.16.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/accounts/accounts.def.js +4 -3
- package/dist/app/features/defs.d.ts +4 -2
- package/dist/app/features/defs.js +26 -12
- 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 +12 -6
- package/dist/app/features/sessions/sessions.def.js +1 -1
- package/dist/app/features/settings/categories.def.js +1 -0
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-F7IMME5G.js → chunk-7EXDUNE7.js} +98 -79
- package/dist/bin/{chunk-BQ23GBLC.js → chunk-HIC4CUMY.js} +1925 -1430
- package/dist/bin/{chunk-LQHEUN2A.js → chunk-PXTLKIV4.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/projects/here.js +2 -0
- package/dist/cli/index.js +4 -1
- package/dist/cli/report.d.ts +7 -0
- package/dist/cli/report.js +31 -0
- 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/entries/daemon.js +4 -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/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/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/secrets/launch-secrets.js +2 -1
- package/dist/runtime/agent.js +14 -0
- package/dist/runtime/daemon.js +466 -132
- package/dist/runtime/db.js +14 -0
- package/dist/runtime/main.js +26 -3
- package/dist/runtime/netproxy.js +14 -0
- package/dist/runtime/view.js +14 -0
- package/dist/selftest/accounts.test.js +22 -0
- package/dist/selftest/app.test.js +2 -2
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/layout.test.js +1 -0
- package/dist/selftest/live-folders.test.d.ts +2 -0
- package/dist/selftest/live-folders.test.js +588 -0
- package/dist/selftest/projects.test.js +7 -7
- 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/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 +5 -0
- package/dist/shared/channel/run-dir.js +11 -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/sync/watcher.js +9 -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 +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 +3 -3
- package/native/scripts/contained-common.ps1 +4 -0
- package/native/scripts/hcs-live-share.ps1 +191 -0
- package/package.json +1 -1
- package/sandbox/csharp/BindMount.cs +120 -0
- package/schemas/config.schema.json +8 -0
- package/dist/web/main-6XNBTJLT.js +0 -221
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Joining the running sandbox from another folder. The folder's run is resolved exactly as a fresh launch would
|
|
2
2
|
// resolve it (its approved .sandbox-config.json, versions, toolchain detection, database plan), checked against the
|
|
3
3
|
// running sandbox's machine-wide protections, made visible inside (host/projects: a project root, a project
|
|
4
|
-
// mapped at boot,
|
|
4
|
+
// mapped at boot, wsb share, or HCS) and described to the guest, which provisions what is missing before its session.
|
|
5
5
|
// When none of those can make it visible, NeedsRestart reaches the caller, which offers a restart. So does a project
|
|
6
6
|
// that wants what the sandbox only gets at its start (a .wsb device, more memory, its mappings) when you choose to
|
|
7
7
|
// restart for it; otherwise it joins without them and they are named.
|
|
@@ -98,14 +98,22 @@ export async function joinRunning(o) {
|
|
|
98
98
|
if (choice === 'restart')
|
|
99
99
|
throw new NeedsRestart(root, 'it wants what the sandbox only gets at its start', missing);
|
|
100
100
|
}
|
|
101
|
-
const mapper = o.mapper ??
|
|
101
|
+
const mapper = o.mapper ??
|
|
102
|
+
projectMapper({
|
|
103
|
+
storageRoot: o.storageRoot,
|
|
104
|
+
packageRoot: o.packageRoot,
|
|
105
|
+
wsbShare: o.wsbShare,
|
|
106
|
+
liveFolders: o.liveFolders,
|
|
107
|
+
dataPath: o.dataPath,
|
|
108
|
+
});
|
|
102
109
|
// Guarded from now on. A folder the sandbox could already write (inside a root, or mapped at boot) and that has no
|
|
103
110
|
// snapshot from the launch gets an empty one: what is there now may have been planted, so it counts as new.
|
|
104
111
|
// Anything else is snapshotted before it becomes visible.
|
|
105
112
|
new RepoGuardStore(o.dataPath).add(root, {
|
|
106
113
|
empty: Boolean(here) || Boolean(registryFile.rootHere(root)),
|
|
107
114
|
});
|
|
108
|
-
|
|
115
|
+
// A live folder (HCS alpha) is always read-only until the real-PC test shows whose rights the share uses.
|
|
116
|
+
const entry = await mapper.register(root, { readOnly: true, onNote: o.onNote });
|
|
109
117
|
new KnownProjects(o.storageRoot).remember(entry.host);
|
|
110
118
|
// Your hooks in ~/.agent-sandbox/hooks ran at boot (once per sandbox); the project's own scripts ("scripts" in its
|
|
111
119
|
// .sandbox-config.json, --script) run before its first agent. The launch folder is read-only for the sandbox, but
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Missing } from '../../core/local-config/index.js';
|
|
2
2
|
import { type Wsb } from '../sandbox/index.js';
|
|
3
|
+
import { type LiveFolders } from '../engines/index.js';
|
|
3
4
|
import { type RegistryEntry } from './registry.js';
|
|
4
5
|
/**
|
|
5
6
|
* Why a folder cannot join the running sandbox without a restart (the caller offers one). With `missing`: it could
|
|
@@ -14,16 +15,44 @@ export declare class NeedsRestart extends Error {
|
|
|
14
15
|
export interface ProjectMapper {
|
|
15
16
|
/** The projects of the running sandbox (the launch folder first). */
|
|
16
17
|
list(): RegistryEntry[];
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Makes a folder of this PC a project of the running sandbox; throws NeedsRestart when that needs a restart.
|
|
20
|
+
* `readOnly`: how the project's own settings would map it (a live folder is read-only when this is not known).
|
|
21
|
+
*/
|
|
22
|
+
register(hostDir: string, o?: {
|
|
23
|
+
readOnly?: boolean;
|
|
24
|
+
onNote?: (note: string) => void;
|
|
25
|
+
}): Promise<RegistryEntry>;
|
|
26
|
+
/**
|
|
27
|
+
* Forgets a project (never the launch folder). A live folder (hcs) is hidden in the sandbox and its share removed;
|
|
28
|
+
* any other mapped folder stays visible until the next start.
|
|
29
|
+
*/
|
|
30
|
+
unregister(name: string): Promise<void>;
|
|
21
31
|
}
|
|
32
|
+
/** The parts of LiveFolders the mapper uses (a test hands in a fake). */
|
|
33
|
+
export type LivePort = Pick<LiveFolders, 'add' | 'remove' | 'unavailable' | 'shareOf'>;
|
|
22
34
|
export interface MapperOptions {
|
|
23
35
|
storageRoot: string;
|
|
24
36
|
packageRoot: string;
|
|
25
37
|
wsbShare: boolean;
|
|
38
|
+
/** projects.liveFolders: "hcs" adds folders through HCS where wsb share is missing (alpha). */
|
|
39
|
+
liveFolders?: 'off' | 'hcs';
|
|
40
|
+
/** The data folder of the running sandbox (needed for live folders). */
|
|
41
|
+
dataPath?: string;
|
|
26
42
|
detect?: () => Wsb | null;
|
|
43
|
+
live?: () => LivePort;
|
|
44
|
+
/** This Windows user started the running sandbox (not another user's, shared or not). */
|
|
45
|
+
isMine?: () => boolean;
|
|
27
46
|
}
|
|
28
|
-
/** Roots first (instant), then `wsb share` where
|
|
47
|
+
/** Roots first (instant), then `wsb share` where Windows has it, then HCS (opt-in), else NeedsRestart. */
|
|
29
48
|
export declare function projectMapper(o: MapperOptions): ProjectMapper;
|
|
49
|
+
/**
|
|
50
|
+
* The doctor's "Add folders while the sandbox runs": which way a folder outside every root would get in (wsb share, HCS
|
|
51
|
+
* or a restart) and why. `liveUnavailable`: why the running sandbox cannot take live folders (null: it can).
|
|
52
|
+
*/
|
|
53
|
+
export declare function addFoldersRow(o: {
|
|
54
|
+
wsbShare: boolean;
|
|
55
|
+
liveFolders: 'off' | 'hcs';
|
|
56
|
+
wsbHasShare: boolean;
|
|
57
|
+
liveUnavailable: string | null;
|
|
58
|
+
}): string;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { assertSafeWorkspace } from '../../core/safe-paths.js';
|
|
3
4
|
import { dirExists, fail } from '../../core/util/index.js';
|
|
4
|
-
import { guestDirFor, hubName, ownGuestFolder, projectForHostDir } from '../../shared/paths/index.js';
|
|
5
|
+
import { guestDirFor, hubName, liveGuestFolder, ownGuestFolder, projectForHostDir, } from '../../shared/paths/index.js';
|
|
5
6
|
import { detectWsb, runningSandboxId, shareFolder } from '../sandbox/index.js';
|
|
7
|
+
import { runningOwner } from '../sharing/index.js';
|
|
8
|
+
import { LIVE_FOLDERS_WARNING, realLiveFolders } from '../engines/index.js';
|
|
6
9
|
import { ProjectRegistry } from './registry.js';
|
|
7
10
|
/**
|
|
8
11
|
* Why a folder cannot join the running sandbox without a restart (the caller offers one). With `missing`: it could
|
|
@@ -19,7 +22,7 @@ export class NeedsRestart extends Error {
|
|
|
19
22
|
this.missing = missing;
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
|
-
/** Roots first (instant), then `wsb share` where
|
|
25
|
+
/** Roots first (instant), then `wsb share` where Windows has it, then HCS (opt-in), else NeedsRestart. */
|
|
23
26
|
export function projectMapper(o) {
|
|
24
27
|
const store = new ProjectRegistry(o.storageRoot);
|
|
25
28
|
const registry = () => store.read() ??
|
|
@@ -41,9 +44,40 @@ export function projectMapper(o) {
|
|
|
41
44
|
store.save({ ...latest, projects: [...latest.projects, entry] });
|
|
42
45
|
return entry;
|
|
43
46
|
};
|
|
47
|
+
const live = () => o.live
|
|
48
|
+
? o.live()
|
|
49
|
+
: realLiveFolders(o.storageRoot, o.dataPath ?? fail('Live folders need the data folder of the running sandbox.'));
|
|
50
|
+
const taken = (reg) => [...reg.projects.map((p) => p.guest), ...reg.roots.map((r) => r.guest)];
|
|
51
|
+
/** Through HCS (projects.liveFolders "hcs", alpha): any refusal or failure is a NeedsRestart with the reason. */
|
|
52
|
+
const addLive = async (reg, host, name, readOnly, note) => {
|
|
53
|
+
if (!(o.isMine ?? (() => runningOwner().kind === 'mine'))())
|
|
54
|
+
throw new NeedsRestart(host, 'the running sandbox was not started by you, so no folder is added to it through HCS');
|
|
55
|
+
const port = live();
|
|
56
|
+
const why = port.unavailable(reg.launchId);
|
|
57
|
+
if (why)
|
|
58
|
+
throw new NeedsRestart(host, 'live folders through HCS cannot be used: ' + why);
|
|
59
|
+
// The real path (a subst drive is resolved here: the elevated helper does not see this session's drives).
|
|
60
|
+
let real;
|
|
61
|
+
try {
|
|
62
|
+
real = fs.realpathSync.native(host);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new NeedsRestart(host, 'the folder cannot be read');
|
|
66
|
+
}
|
|
67
|
+
assertSafeWorkspace(real, o.packageRoot, o.storageRoot);
|
|
68
|
+
const guest = liveGuestFolder(host, taken(reg));
|
|
69
|
+
note?.(LIVE_FOLDERS_WARNING);
|
|
70
|
+
try {
|
|
71
|
+
await port.add({ launchId: reg.launchId, host: real, guest, folder: path.win32.basename(guest), readOnly });
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
throw new NeedsRestart(host, 'adding it through HCS failed (alpha): ' + (e instanceof Error ? e.message : String(e)));
|
|
75
|
+
}
|
|
76
|
+
return add(reg, host, guest, 'hcs', name);
|
|
77
|
+
};
|
|
44
78
|
return {
|
|
45
79
|
list: () => store.read()?.projects ?? [],
|
|
46
|
-
register: (hostDir) => {
|
|
80
|
+
register: async (hostDir, opts = {}) => {
|
|
47
81
|
const host = path.resolve(hostDir);
|
|
48
82
|
const reg = registry();
|
|
49
83
|
const known = reg.projects.find((p) => p.host.toLowerCase() === host.toLowerCase());
|
|
@@ -57,32 +91,66 @@ export function projectMapper(o) {
|
|
|
57
91
|
const root = projectForHostDir(reg.roots, host);
|
|
58
92
|
if (root)
|
|
59
93
|
return add(reg, host, guestDirFor(root, host), 'root', name);
|
|
94
|
+
const hcs = o.liveFolders === 'hcs';
|
|
95
|
+
const wsb = o.wsbShare || hcs ? (o.detect ?? detectWsb)() : null;
|
|
96
|
+
// The official way wins wherever it exists: HCS only where wsb share is missing.
|
|
97
|
+
if (o.wsbShare && wsb?.has('share')) {
|
|
98
|
+
const sandbox = runningSandboxId(wsb);
|
|
99
|
+
if (!sandbox.id)
|
|
100
|
+
throw new NeedsRestart(host, 'wsb share could not find the running sandbox: ' + sandbox.error);
|
|
101
|
+
// Where it is as a launch folder too (C:\Workspace\<name>), unless another project already uses that place.
|
|
102
|
+
const guest = ownGuestFolder(host, false, taken(reg));
|
|
103
|
+
const shared = shareFolder(wsb, sandbox.id, host, guest);
|
|
104
|
+
if (!shared.ok)
|
|
105
|
+
throw new NeedsRestart(host, 'wsb share failed (untested on this Windows): ' + shared.error);
|
|
106
|
+
return add(reg, host, guest, 'wsb', name);
|
|
107
|
+
}
|
|
108
|
+
if (hcs && !wsb?.has('share'))
|
|
109
|
+
return addLive(reg, host, name, opts.readOnly ?? true, opts.onNote);
|
|
60
110
|
if (!o.wsbShare)
|
|
61
111
|
throw new NeedsRestart(host, 'it is not inside a project root (projects.roots), and adding folders with wsb share is off (projects.wsbShare)');
|
|
62
|
-
|
|
63
|
-
if (!wsb?.has('share'))
|
|
64
|
-
throw new NeedsRestart(host, 'it is not inside a project root (projects.roots), and this Windows has no Windows Sandbox command line (wsb share needs Windows 11 24H2+ with the updated Windows Sandbox)');
|
|
65
|
-
const sandbox = runningSandboxId(wsb);
|
|
66
|
-
if (!sandbox.id)
|
|
67
|
-
throw new NeedsRestart(host, 'wsb share could not find the running sandbox: ' + sandbox.error);
|
|
68
|
-
// Where it is as a launch folder too (C:\Workspace\<name>), unless another project already uses that place.
|
|
69
|
-
const guest = ownGuestFolder(host, false, [
|
|
70
|
-
...reg.projects.map((p) => p.guest),
|
|
71
|
-
...reg.roots.map((r) => r.guest),
|
|
72
|
-
]);
|
|
73
|
-
const shared = shareFolder(wsb, sandbox.id, host, guest);
|
|
74
|
-
if (!shared.ok)
|
|
75
|
-
throw new NeedsRestart(host, 'wsb share failed (untested on this Windows): ' + shared.error);
|
|
76
|
-
return add(reg, host, guest, 'wsb', name);
|
|
112
|
+
throw new NeedsRestart(host, 'it is not inside a project root (projects.roots), and this Windows has no Windows Sandbox command line (wsb share needs Windows 11 24H2+ with the updated Windows Sandbox; projects.liveFolders "hcs" is an untested alpha for older Windows)');
|
|
77
113
|
},
|
|
78
|
-
unregister: (name) => {
|
|
114
|
+
unregister: async (name) => {
|
|
79
115
|
const reg = registry();
|
|
80
116
|
const entry = reg.projects.find((p) => p.name.toLowerCase() === name.toLowerCase());
|
|
81
117
|
if (!entry)
|
|
82
118
|
fail('No project "' + name + '" in the running sandbox.', 'sandbox projects lists them.');
|
|
83
119
|
if (entry.primary)
|
|
84
120
|
fail(entry.host + ' is the folder the sandbox started from; it stays until the sandbox stops.');
|
|
85
|
-
|
|
121
|
+
// A live folder: hidden in the sandbox first, then its share removed (one permission prompt); kept on failure.
|
|
122
|
+
if (entry.mechanism === 'hcs') {
|
|
123
|
+
const port = live();
|
|
124
|
+
let real = entry.host;
|
|
125
|
+
try {
|
|
126
|
+
real = fs.realpathSync.native(entry.host);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Gone from this PC: its record still names the real path it had.
|
|
130
|
+
}
|
|
131
|
+
const share = port.shareOf(real) ?? port.shareOf(entry.host);
|
|
132
|
+
if (share)
|
|
133
|
+
await port.remove(reg.launchId, share.host);
|
|
134
|
+
}
|
|
135
|
+
const latest = store.read() ?? reg;
|
|
136
|
+
store.save({ ...latest, projects: latest.projects.filter((p) => p.name !== entry.name) });
|
|
86
137
|
},
|
|
87
138
|
};
|
|
88
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* The doctor's "Add folders while the sandbox runs": which way a folder outside every root would get in (wsb share, HCS
|
|
142
|
+
* or a restart) and why. `liveUnavailable`: why the running sandbox cannot take live folders (null: it can).
|
|
143
|
+
*/
|
|
144
|
+
export function addFoldersRow(o) {
|
|
145
|
+
if (o.wsbHasShare && o.wsbShare)
|
|
146
|
+
return 'wsb share (untested; a failure offers a restart instead)';
|
|
147
|
+
if (o.liveFolders === 'hcs') {
|
|
148
|
+
if (o.wsbHasShare)
|
|
149
|
+
return 'restart: wsb share is on this Windows but switched off (projects.wsbShare); HCS is not used where wsb share exists';
|
|
150
|
+
return ('HCS (alpha, untested on a real PC): needs an administrator prompt each time' +
|
|
151
|
+
(o.liveUnavailable ? '; not for the running sandbox: ' + o.liveUnavailable : ''));
|
|
152
|
+
}
|
|
153
|
+
return o.wsbHasShare
|
|
154
|
+
? 'restart (wsb share is switched off: projects.wsbShare)'
|
|
155
|
+
: 'restart (no wsb share on this Windows; projects.liveFolders "hcs" is an untested alpha that adds folders without one)';
|
|
156
|
+
}
|
|
@@ -10,6 +10,7 @@ declare const RegistryEntrySchema: z.ZodObject<{
|
|
|
10
10
|
guest: z.ZodString;
|
|
11
11
|
primary: z.ZodBoolean;
|
|
12
12
|
mechanism: z.ZodCatch<z.ZodEnum<{
|
|
13
|
+
hcs: "hcs";
|
|
13
14
|
root: "root";
|
|
14
15
|
launch: "launch";
|
|
15
16
|
boot: "boot";
|
|
@@ -30,6 +31,7 @@ declare const RegistrySchema: z.ZodObject<{
|
|
|
30
31
|
guest: z.ZodString;
|
|
31
32
|
primary: z.ZodBoolean;
|
|
32
33
|
mechanism: z.ZodCatch<z.ZodEnum<{
|
|
34
|
+
hcs: "hcs";
|
|
33
35
|
root: "root";
|
|
34
36
|
launch: "launch";
|
|
35
37
|
boot: "boot";
|
|
@@ -22,7 +22,7 @@ const RegistryEntrySchema = z.object({
|
|
|
22
22
|
host: AbsolutePathSchema,
|
|
23
23
|
guest: z.string().max(1024),
|
|
24
24
|
primary: z.boolean(),
|
|
25
|
-
mechanism: z.enum(['launch', 'root', 'boot', 'wsb']).catch('root'),
|
|
25
|
+
mechanism: z.enum(['launch', 'root', 'boot', 'wsb', 'hcs']).catch('root'),
|
|
26
26
|
registeredAt: z.string().max(64),
|
|
27
27
|
});
|
|
28
28
|
const RegistrySchema = z.object({
|
|
@@ -13,7 +13,8 @@ export function writeSecrets(dataPath, id, secrets) {
|
|
|
13
13
|
!secrets.claudeCredentials &&
|
|
14
14
|
!secrets.vpn &&
|
|
15
15
|
!secrets.wireguardConfig &&
|
|
16
|
-
!secrets.githubToken
|
|
16
|
+
!secrets.githubToken &&
|
|
17
|
+
!secrets.liveFoldersKey;
|
|
17
18
|
if (empty)
|
|
18
19
|
return null;
|
|
19
20
|
const run = new RunDir(dataPath);
|
package/dist/runtime/agent.js
CHANGED
|
@@ -26645,6 +26645,9 @@ var ProjectsSchema = external_exports.strictObject({
|
|
|
26645
26645
|
),
|
|
26646
26646
|
wsbShare: external_exports.boolean().describe(
|
|
26647
26647
|
"On Windows 11 24H2+ with the Windows Sandbox command line (wsb), add other folders to the running sandbox with `wsb share` (untested). Otherwise starting a project outside every root offers a restart."
|
|
26648
|
+
),
|
|
26649
|
+
liveFolders: external_exports.enum(["off", "hcs"]).describe(
|
|
26650
|
+
'ALPHA, UNTESTED ON A REAL PC: "hcs" adds a project folder to the running sandbox through the Host Compute Service where `wsb share` is missing (one administrator prompt per add or remove; always read-only in this alpha). If it fails, the sandbox may close: save your work first. Turn it on before the sandbox starts. "off" (default) offers a restart instead. The real-PC tests still to pass are in docs/design/hcs-live-folders.md ("Test plan").'
|
|
26648
26651
|
)
|
|
26649
26652
|
});
|
|
26650
26653
|
|
|
@@ -27180,6 +27183,9 @@ var RunDir = class {
|
|
|
27180
27183
|
treesDir;
|
|
27181
27184
|
/** One-shot secrets the host hands over (see secrets.ts). Next to run, not in it: shared-use users can change run. */
|
|
27182
27185
|
secretsDir;
|
|
27186
|
+
/** Live folders (live.ts): signed host requests, and the daemon's replies. */
|
|
27187
|
+
liveDir;
|
|
27188
|
+
liveRepliesDir;
|
|
27183
27189
|
constructor(dataDir2) {
|
|
27184
27190
|
this.root = path5.join(dataDir2, "run");
|
|
27185
27191
|
this.sandboxFile = path5.join(this.root, "sandbox.json");
|
|
@@ -27193,6 +27199,14 @@ var RunDir = class {
|
|
|
27193
27199
|
this.auditDir = path5.join(this.root, "audit");
|
|
27194
27200
|
this.treesDir = path5.join(this.root, "trees");
|
|
27195
27201
|
this.secretsDir = path5.join(dataDir2, "secrets");
|
|
27202
|
+
this.liveDir = path5.join(this.root, "live");
|
|
27203
|
+
this.liveRepliesDir = path5.join(this.root, "live-replies");
|
|
27204
|
+
}
|
|
27205
|
+
liveFile(id) {
|
|
27206
|
+
return path5.join(this.liveDir, safeId(id) + ".json");
|
|
27207
|
+
}
|
|
27208
|
+
liveReplyFile(id) {
|
|
27209
|
+
return path5.join(this.liveRepliesDir, safeId(id) + ".json");
|
|
27196
27210
|
}
|
|
27197
27211
|
requestFile(id) {
|
|
27198
27212
|
return path5.join(this.requestsDir, safeId(id) + ".json");
|