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
package/config.example.json
CHANGED
|
@@ -188,9 +188,10 @@ function loginItem(a, r) {
|
|
|
188
188
|
...(r.isActive ? [{ text: 'in the sandbox', tone: 'ok' }] : []),
|
|
189
189
|
...(r.isDefault ? [{ text: 'default', tone: 'accent' }] : []),
|
|
190
190
|
],
|
|
191
|
-
description: 'Choose it to make the sandbox use this login.',
|
|
191
|
+
description: r.isActive ? 'The sandbox uses this login now.' : 'Choose it to make the sandbox use this login.',
|
|
192
192
|
details: ['Agent ' + a.name, 'Email ' + (r.email ?? '-'), 'Saved ' + r.savedAt.slice(0, 16).replace('T', ' ')],
|
|
193
|
-
|
|
193
|
+
// The login in use already offers nothing to switch to.
|
|
194
|
+
...(r.isActive ? {} : { primary: action(useAccount, { agent: a.name, name: r.name }, { verb: 'use' }) }),
|
|
194
195
|
actions: [
|
|
195
196
|
action(defaultAccount, { agent: a.name, name: r.name }, { key: 'd', verb: 'make default', importance: 1 }),
|
|
196
197
|
action(renameAccount, { agent: a.name, name: r.name }, { key: 'r', verb: 'rename', importance: 2 }),
|
|
@@ -244,7 +245,7 @@ export function agentPage(a) {
|
|
|
244
245
|
export const accountsView = defineView({
|
|
245
246
|
id: 'accounts',
|
|
246
247
|
title: 'Accounts',
|
|
247
|
-
summary: 'Logins saved on this PC
|
|
248
|
+
summary: 'Logins saved on this PC for each agent. Every launch starts with the default; "Use this login" switches now.',
|
|
248
249
|
queries: { accounts: listAccounts },
|
|
249
250
|
operations: [saveAccount, useAccount, defaultAccount, renameAccount, removeAccount],
|
|
250
251
|
build: ({ accounts }) => accountsPage(accounts),
|
|
@@ -172,9 +172,9 @@ export declare const OPERATIONS: readonly [OperationDef<import("zod").ZodObject<
|
|
|
172
172
|
message: import("zod").ZodString;
|
|
173
173
|
}, import("zod/v4/core").$strip>, "projects.all">, OperationDef<import("zod").ZodObject<{
|
|
174
174
|
change: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
175
|
-
list: "list";
|
|
176
175
|
add: "add";
|
|
177
176
|
remove: "remove";
|
|
177
|
+
list: "list";
|
|
178
178
|
}>>;
|
|
179
179
|
rootFolder: import("zod").ZodOptional<import("zod").ZodString>;
|
|
180
180
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
@@ -1606,7 +1606,7 @@ export interface NavSection {
|
|
|
1606
1606
|
readonly view?: ViewId;
|
|
1607
1607
|
/** Where the area is today when it has no view yet. */
|
|
1608
1608
|
readonly elsewhere?: string;
|
|
1609
|
-
/** Entries under this one (Sandbox:
|
|
1609
|
+
/** Entries under this one: a group of the navigation (Sandbox: Overview, Projects, Apps). */
|
|
1610
1610
|
readonly children?: readonly NavSection[];
|
|
1611
1611
|
/** Views shown as more categories inside this entry's page (Settings: VPN, GitHub), not as entries of their own. */
|
|
1612
1612
|
readonly embeds?: readonly {
|
|
@@ -1618,6 +1618,8 @@ export interface NavSection {
|
|
|
1618
1618
|
export declare function navSections(nav: readonly NavSection[]): NavSection[];
|
|
1619
1619
|
/** Every view the web's navigation opens. */
|
|
1620
1620
|
export declare function navViews(nav: readonly NavSection[]): ViewId[];
|
|
1621
|
+
/** The group of the navigation a view's entry sits in (Updates: Maintenance), for the page's breadcrumb. */
|
|
1622
|
+
export declare function navGroupOf(nav: readonly NavSection[], view: string): NavSection | undefined;
|
|
1621
1623
|
/** The entry whose page shows this view as one of its categories (VPN: Settings), if any. */
|
|
1622
1624
|
export declare function embeddingOf(nav: readonly NavSection[], view: string): NavSection | undefined;
|
|
1623
1625
|
export declare const NAV: readonly NavSection[];
|
|
@@ -140,32 +140,46 @@ export function navSections(nav) {
|
|
|
140
140
|
export function navViews(nav) {
|
|
141
141
|
return navSections(nav).flatMap((n) => [...(n.view ? [n.view] : []), ...(n.embeds ?? []).map((e) => e.view)]);
|
|
142
142
|
}
|
|
143
|
+
/** The group of the navigation a view's entry sits in (Updates: Maintenance), for the page's breadcrumb. */
|
|
144
|
+
export function navGroupOf(nav, view) {
|
|
145
|
+
return navSections(nav).find((n) => n.children?.some((c) => c.view === view));
|
|
146
|
+
}
|
|
143
147
|
/** The entry whose page shows this view as one of its categories (VPN: Settings), if any. */
|
|
144
148
|
export function embeddingOf(nav, view) {
|
|
145
149
|
return navSections(nav).find((n) => n.embeds?.some((e) => e.view === view));
|
|
146
150
|
}
|
|
147
151
|
export const NAV = [
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
152
|
+
{
|
|
153
|
+
label: 'Workspace',
|
|
154
|
+
children: [
|
|
155
|
+
{ label: 'Agents', view: 'agents' },
|
|
156
|
+
{ label: 'Sessions', view: 'sessions' },
|
|
157
|
+
{ label: 'Activity', view: 'audit' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
151
160
|
{
|
|
152
161
|
label: 'Sandbox',
|
|
153
162
|
children: [
|
|
154
|
-
{ label: '
|
|
163
|
+
{ label: 'Overview', view: 'sandbox' },
|
|
155
164
|
{ label: 'Projects', view: 'projects' },
|
|
165
|
+
{ label: 'Apps', view: 'apps' },
|
|
156
166
|
],
|
|
157
167
|
},
|
|
158
|
-
{ label: 'Apps', view: 'apps' },
|
|
159
168
|
{
|
|
160
|
-
label: '
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
label: 'Configuration',
|
|
170
|
+
children: [
|
|
171
|
+
{
|
|
172
|
+
label: 'Settings',
|
|
173
|
+
view: 'settings',
|
|
174
|
+
embeds: [
|
|
175
|
+
{ label: 'VPN', view: 'vpn' },
|
|
176
|
+
{ label: 'GitHub', view: 'github' },
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
{ label: 'Accounts', view: 'accounts' },
|
|
180
|
+
{ label: 'Remote access', view: 'access' },
|
|
165
181
|
],
|
|
166
182
|
},
|
|
167
|
-
{ label: 'Accounts', view: 'accounts' },
|
|
168
|
-
{ label: 'Remote access', view: 'access' },
|
|
169
183
|
{
|
|
170
184
|
label: 'Maintenance',
|
|
171
185
|
children: [
|
|
@@ -73,9 +73,9 @@ export declare const allProjects: import("../../kernel/define.js").OperationDef<
|
|
|
73
73
|
}, z.core.$strip>, "projects.all">;
|
|
74
74
|
export declare const projectRoots: import("../../kernel/define.js").OperationDef<z.ZodObject<{
|
|
75
75
|
change: z.ZodDefault<z.ZodEnum<{
|
|
76
|
-
list: "list";
|
|
77
76
|
add: "add";
|
|
78
77
|
remove: "remove";
|
|
78
|
+
list: "list";
|
|
79
79
|
}>>;
|
|
80
80
|
rootFolder: z.ZodOptional<z.ZodString>;
|
|
81
81
|
}, z.core.$strip>, z.ZodObject<{
|
|
@@ -46,9 +46,9 @@ export declare const allProjectsRun: import("../../kernel/define.js").Implementa
|
|
|
46
46
|
}, import("zod/v4/core").$strip>, "projects.all">, import("../../../cli/commands/context.js").Context>;
|
|
47
47
|
export declare const projectRootsRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
|
|
48
48
|
change: import("zod").ZodDefault<import("zod").ZodEnum<{
|
|
49
|
-
list: "list";
|
|
50
49
|
add: "add";
|
|
51
50
|
remove: "remove";
|
|
51
|
+
list: "list";
|
|
52
52
|
}>>;
|
|
53
53
|
rootFolder: import("zod").ZodOptional<import("zod").ZodString>;
|
|
54
54
|
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
@@ -68,14 +68,22 @@ export const removeProjectRun = implement(removeProject, async (ctx, input, io)
|
|
|
68
68
|
const dir = await pickFolder(ctx, io, input.projectFolder);
|
|
69
69
|
const yes = await io.confirm({
|
|
70
70
|
title: 'Forget ' + path.basename(dir) + '?',
|
|
71
|
-
lines: [
|
|
71
|
+
lines: [
|
|
72
|
+
'The project is dropped from your list of projects.',
|
|
73
|
+
'Nothing in ' + dir + ' is touched.',
|
|
74
|
+
...(new ProjectsService(ctx).isLive(dir)
|
|
75
|
+
? [
|
|
76
|
+
'It is a live folder: it is hidden in the running sandbox and its share removed (Windows asks for permission).',
|
|
77
|
+
]
|
|
78
|
+
: []),
|
|
79
|
+
],
|
|
72
80
|
yes: 'Forget',
|
|
73
81
|
danger: true,
|
|
74
82
|
implied: true,
|
|
75
83
|
});
|
|
76
84
|
if (!yes)
|
|
77
85
|
cancelled();
|
|
78
|
-
const { dir: forgotten, removed } = new ProjectsService(ctx).forget(dir);
|
|
86
|
+
const { dir: forgotten, removed } = await new ProjectsService(ctx).forget(dir);
|
|
79
87
|
return {
|
|
80
88
|
message: removed
|
|
81
89
|
? 'Removed ' + forgotten + ' from your projects (nothing in the folder was touched).'
|
|
@@ -6,7 +6,7 @@ const ProjectSchema = z.object({
|
|
|
6
6
|
name: z.string().describe('The project'),
|
|
7
7
|
host: z.string().describe('Its folder on this PC'),
|
|
8
8
|
guest: z.string().describe('Its folder in the sandbox'),
|
|
9
|
-
mechanism: z.string().describe('How it got into the sandbox (launch, root, boot or
|
|
9
|
+
mechanism: z.string().describe('How it got into the sandbox (launch, root, boot, wsb or hcs)'),
|
|
10
10
|
here: z.boolean().describe('The project of the current folder'),
|
|
11
11
|
setup: z.object({ phase: z.string(), message: z.string() }).describe('How far its setup is'),
|
|
12
12
|
databases: z.array(z.object({ database: z.string(), port: z.number(), state: z.string() })),
|
|
@@ -124,6 +124,8 @@ const MECHANISM_TEXT = {
|
|
|
124
124
|
launch: 'started from here',
|
|
125
125
|
root: 'in a project root',
|
|
126
126
|
boot: 'mapped at start',
|
|
127
|
+
wsb: 'wsb share',
|
|
128
|
+
hcs: 'live folder through HCS, alpha',
|
|
127
129
|
};
|
|
128
130
|
function projectItem(p) {
|
|
129
131
|
return {
|
|
@@ -161,7 +163,8 @@ function facts(o) {
|
|
|
161
163
|
? [
|
|
162
164
|
fact('window', 'Window', s.headless ? 'hidden (sandbox show opens it)' : 'shown'),
|
|
163
165
|
fact('uptime', 'Uptime', uptime(s) ?? '-'),
|
|
164
|
-
|
|
166
|
+
// The session count is its own fact: the helper only says whether it answers.
|
|
167
|
+
fact('helper', 'Helper', s.daemon === '-' ? '-' : s.daemon.startsWith('pong') ? 'Responding' : s.daemon),
|
|
165
168
|
fact('sessions', 'Sessions', String(sessions)),
|
|
166
169
|
]
|
|
167
170
|
: []),
|
|
@@ -193,9 +196,12 @@ function guardSection(o) {
|
|
|
193
196
|
return {
|
|
194
197
|
id: 'guard',
|
|
195
198
|
title: 'Repo guard',
|
|
196
|
-
summary:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
summary: 'Watching ' +
|
|
200
|
+
plural(o.repoGuard.guarded, 'folder') +
|
|
201
|
+
'. ' +
|
|
202
|
+
(findings.length
|
|
203
|
+
? plural(findings.length, 'change') + ' from the sandbox were blocked:'
|
|
204
|
+
: 'Nothing from the sandbox needed blocking.'),
|
|
199
205
|
items: findings.slice(-10).map((f, i) => ({ id: 'guard:' + i, label: f, tone: 'warn' })),
|
|
200
206
|
};
|
|
201
207
|
}
|
|
@@ -247,7 +253,7 @@ export function sandboxPage(o) {
|
|
|
247
253
|
export const sandboxView = defineView({
|
|
248
254
|
id: 'sandbox',
|
|
249
255
|
title: 'Sandbox',
|
|
250
|
-
summary: '
|
|
256
|
+
summary: 'Status, projects and controls of the running sandbox.',
|
|
251
257
|
queries: { status: sandboxStatus },
|
|
252
258
|
operations: [showWindow, hideWindow, stopSandbox],
|
|
253
259
|
build: ({ status }) => sandboxPage(status),
|
|
@@ -240,7 +240,7 @@ export function sessionsPage(o) {
|
|
|
240
240
|
export const sessionsView = defineView({
|
|
241
241
|
id: 'sessions',
|
|
242
242
|
title: 'Sessions',
|
|
243
|
-
summary: '
|
|
243
|
+
summary: 'Agent and shell sessions in the running sandbox.',
|
|
244
244
|
queries: { sessions: listSessions },
|
|
245
245
|
operations: [restartSessions, startShell, closeSession],
|
|
246
246
|
build: ({ sessions }) => sessionsPage(sessions),
|
|
@@ -123,6 +123,7 @@ const LABELS = {
|
|
|
123
123
|
'sandbox.pressureResponse': 'Slow builds down when memory runs low',
|
|
124
124
|
'network.dns': 'DNS servers',
|
|
125
125
|
'projects.wsbShare': 'Add folders while the sandbox runs',
|
|
126
|
+
'projects.liveFolders': 'Add folders through HCS (alpha, untested)',
|
|
126
127
|
'projects.all': 'Map all known projects at start',
|
|
127
128
|
'claudeProfile.hostDir': 'Claude folder on this PC',
|
|
128
129
|
'claudeProfile.globalStateFile': 'Claude state file on this PC',
|
|
@@ -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-7EXDUNE7.js";
|
|
6
|
+
import "./chunk-HIC4CUMY.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/agent-sandbox.ts
|
|
9
9
|
run(process.argv.slice(2));
|