windows-development-sandbox 1.12.0 → 1.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +11 -1
  3. package/dist/app/features/access/access.def.d.ts +190 -0
  4. package/dist/app/features/access/access.def.js +273 -0
  5. package/dist/app/features/access/access.run.d.ts +79 -0
  6. package/dist/app/features/access/access.run.js +129 -0
  7. package/dist/app/features/access/index.d.ts +2 -0
  8. package/dist/app/features/access/index.js +3 -0
  9. package/dist/app/features/accounts/accounts.def.d.ts +1 -0
  10. package/dist/app/features/accounts/accounts.def.js +12 -3
  11. package/dist/app/features/accounts/accounts.run.d.ts +1 -0
  12. package/dist/app/features/accounts/accounts.run.js +20 -11
  13. package/dist/app/features/agents/agent-entry.js +5 -0
  14. package/dist/app/features/agents/agents.def.js +1 -0
  15. package/dist/app/features/apps/apps.def.js +1 -0
  16. package/dist/app/features/audit/audit.def.d.ts +11 -2
  17. package/dist/app/features/audit/audit.def.js +7 -4
  18. package/dist/app/features/audit/audit.run.d.ts +3 -0
  19. package/dist/app/features/defs.d.ts +156 -3
  20. package/dist/app/features/defs.js +12 -1
  21. package/dist/app/features/files/files.def.js +1 -0
  22. package/dist/app/features/health/health.def.js +1 -0
  23. package/dist/app/features/sandbox/sandbox.def.js +3 -0
  24. package/dist/app/features/sessions/sessions.def.d.ts +36 -0
  25. package/dist/app/features/sessions/sessions.def.js +77 -9
  26. package/dist/app/features/sessions/sessions.run.d.ts +25 -2
  27. package/dist/app/features/sessions/sessions.run.js +71 -3
  28. package/dist/app/features/settings/settings-file.d.ts +7 -0
  29. package/dist/app/features/settings/settings-file.js +19 -2
  30. package/dist/app/features/settings/settings-rows.js +9 -1
  31. package/dist/app/features/settings/settings.def.d.ts +8 -0
  32. package/dist/app/features/settings/settings.def.js +17 -0
  33. package/dist/app/features/web/web.def.d.ts +9 -0
  34. package/dist/app/features/web/web.def.js +26 -1
  35. package/dist/app/features/web/web.run.d.ts +3 -0
  36. package/dist/app/features/web/web.run.js +11 -3
  37. package/dist/app/kernel/access.d.ts +33 -0
  38. package/dist/app/kernel/access.js +44 -0
  39. package/dist/app/kernel/define.d.ts +14 -1
  40. package/dist/app/kernel/index.d.ts +1 -0
  41. package/dist/app/kernel/index.js +1 -0
  42. package/dist/app/kernel/rpc.d.ts +5 -2
  43. package/dist/app/registry.d.ts +4 -1
  44. package/dist/app/registry.js +24 -4
  45. package/dist/bin/agent-sandbox.js +7 -1
  46. package/dist/bin/chunk-IL7BXJF2.js +7 -0
  47. package/dist/bin/chunk-K4SU3MHJ.js +10432 -0
  48. package/dist/bin/chunk-VENWSGX2.js +78437 -0
  49. package/dist/bin/claude-host.js +10 -4
  50. package/dist/bin/claude-sbx.js +8 -2
  51. package/dist/bin/codex-sbx.js +8 -2
  52. package/dist/bin/gemini-sbx.js +8 -2
  53. package/dist/bin/sandbox.js +7 -2
  54. package/dist/bin/sbx-hide.js +8 -2
  55. package/dist/bin/sbx-show.js +8 -2
  56. package/dist/cli/commands/launch/prepare.js +24 -7
  57. package/dist/cli/commands/launch/running.js +4 -0
  58. package/dist/cli/commands/registry.js +2 -0
  59. package/dist/cli/commands/remote.d.ts +2 -0
  60. package/dist/cli/commands/remote.js +49 -0
  61. package/dist/cli/commands/sessions/reopen.js +3 -0
  62. package/dist/cli/commands/storage/offer.js +1 -1
  63. package/dist/cli/commands/web.js +66 -0
  64. package/dist/cli/manifest.d.ts +63 -4
  65. package/dist/cli/manifest.js +33 -4
  66. package/dist/cli/menu/io-menu.d.ts +5 -3
  67. package/dist/cli/menu/io-menu.js +12 -5
  68. package/dist/cli/menu/live.d.ts +29 -0
  69. package/dist/cli/menu/live.js +92 -21
  70. package/dist/cli/menu/menu.d.ts +2 -1
  71. package/dist/cli/menu/menu.js +16 -2
  72. package/dist/cli/menu/pages/list-page.d.ts +5 -0
  73. package/dist/cli/menu/pages/list-page.js +19 -0
  74. package/dist/cli/menu/remote-menu.d.ts +19 -0
  75. package/dist/cli/menu/remote-menu.js +108 -0
  76. package/dist/cli/menu/shell.d.ts +2 -0
  77. package/dist/cli/menu/shell.js +1 -1
  78. package/dist/cli/menu/views.js +2 -0
  79. package/dist/cli/operations/handler.js +15 -1
  80. package/dist/cli/services/accounts-service.d.ts +7 -0
  81. package/dist/cli/services/accounts-service.js +20 -0
  82. package/dist/cli/services/remote-client.d.ts +16 -0
  83. package/dist/cli/services/remote-client.js +141 -0
  84. package/dist/cli/services/sessions-service.d.ts +5 -0
  85. package/dist/cli/services/sessions-service.js +17 -1
  86. package/dist/cli/tui/app.d.ts +4 -0
  87. package/dist/cli/tui/app.js +5 -0
  88. package/dist/cli/tui/terminal.d.ts +6 -0
  89. package/dist/cli/tui/terminal.js +8 -1
  90. package/dist/cli/validate.js +8 -4
  91. package/dist/core/config/defaults.js +11 -1
  92. package/dist/core/local-config/file.js +16 -2
  93. package/dist/core/local-config/overrides.js +7 -0
  94. package/dist/core/package-info.js +1 -1
  95. package/dist/core/run/versions.js +9 -8
  96. package/dist/core/schema/config.d.ts +22 -3
  97. package/dist/core/schema/config.js +39 -2
  98. package/dist/core/schema/web.d.ts +51 -0
  99. package/dist/core/schema/web.js +46 -1
  100. package/dist/core/util/fs.d.ts +5 -0
  101. package/dist/core/util/fs.js +23 -0
  102. package/dist/core/util/index.d.ts +1 -1
  103. package/dist/core/util/index.js +1 -1
  104. package/dist/guest/daemon/daemon.js +2 -0
  105. package/dist/guest/daemon/idle-shutdown.js +2 -1
  106. package/dist/guest/daemon/sessions.d.ts +16 -2
  107. package/dist/guest/daemon/sessions.js +126 -20
  108. package/dist/guest/git/decision.js +7 -0
  109. package/dist/guest/sessions/cmdline.d.ts +14 -0
  110. package/dist/guest/sessions/cmdline.js +10 -0
  111. package/dist/guest/toolchains/setup.js +3 -0
  112. package/dist/host/audit/log.d.ts +3 -2
  113. package/dist/host/audit/log.js +3 -3
  114. package/dist/host/channel/channel.d.ts +5 -1
  115. package/dist/host/channel/channel.js +12 -0
  116. package/dist/host/guard/agent-files.js +7 -1
  117. package/dist/host/guard/commands.js +13 -1
  118. package/dist/host/guard/git-config.js +27 -7
  119. package/dist/host/guard/git-dirs.js +78 -3
  120. package/dist/host/guard/mark-of-the-web.js +3 -1
  121. package/dist/host/guard/nested-repos.js +7 -2
  122. package/dist/host/guard/store.js +1 -0
  123. package/dist/host/guard/types.d.ts +2 -0
  124. package/dist/host/launch/mappings.js +11 -1
  125. package/dist/host/launch/project-scan.js +2 -21
  126. package/dist/host/launch/stage.js +4 -0
  127. package/dist/host/life/session-ledger.js +2 -1
  128. package/dist/host/remote/access-store.d.ts +156 -0
  129. package/dist/host/remote/access-store.js +308 -0
  130. package/dist/host/remote/cert.d.ts +20 -0
  131. package/dist/host/remote/cert.js +103 -0
  132. package/dist/host/remote/door-client.d.ts +13 -0
  133. package/dist/host/remote/door-client.js +54 -0
  134. package/dist/host/remote/firewall.d.ts +44 -0
  135. package/dist/host/remote/firewall.js +118 -0
  136. package/dist/host/remote/gate.d.ts +125 -0
  137. package/dist/host/remote/gate.js +391 -0
  138. package/dist/host/remote/index.d.ts +8 -0
  139. package/dist/host/remote/index.js +10 -0
  140. package/dist/host/remote/lan.d.ts +24 -0
  141. package/dist/host/remote/lan.js +88 -0
  142. package/dist/host/remote/tls-store.d.ts +22 -0
  143. package/dist/host/remote/tls-store.js +63 -0
  144. package/dist/host/remote/windows-helper.d.ts +67 -0
  145. package/dist/host/remote/windows-helper.js +129 -0
  146. package/dist/host/sandbox/platform.d.ts +2 -0
  147. package/dist/host/sandbox/platform.js +19 -4
  148. package/dist/host/storage/contained/state.d.ts +3 -2
  149. package/dist/host/storage/contained/state.js +5 -2
  150. package/dist/host/web/bridge.d.ts +5 -1
  151. package/dist/host/web/bridge.js +6 -2
  152. package/dist/host/web/browser.js +1 -1
  153. package/dist/host/web/control.d.ts +4 -1
  154. package/dist/host/web/control.js +28 -4
  155. package/dist/host/web/rpc.d.ts +16 -2
  156. package/dist/host/web/rpc.js +37 -4
  157. package/dist/host/web/runner.d.ts +4 -0
  158. package/dist/host/web/runner.js +12 -0
  159. package/dist/host/web/server.d.ts +18 -2
  160. package/dist/host/web/server.js +97 -24
  161. package/dist/host/web/state.d.ts +5 -0
  162. package/dist/host/web/state.js +8 -0
  163. package/dist/runtime/agent.js +74 -3
  164. package/dist/runtime/daemon.js +205 -24
  165. package/dist/runtime/db.js +74 -3
  166. package/dist/runtime/gitguard.js +6 -0
  167. package/dist/runtime/main.js +77 -3
  168. package/dist/runtime/netproxy.js +74 -3
  169. package/dist/runtime/view.js +76 -3
  170. package/dist/selftest/app.test.js +41 -6
  171. package/dist/selftest/channel.test.js +16 -0
  172. package/dist/selftest/cmdline.test.js +16 -0
  173. package/dist/selftest/git-access.test.js +8 -0
  174. package/dist/selftest/hostile-input.test.js +12 -1
  175. package/dist/selftest/index.js +2 -0
  176. package/dist/selftest/layout.test.js +10 -1
  177. package/dist/selftest/live-daemon.test.js +25 -0
  178. package/dist/selftest/local-config.test.js +30 -0
  179. package/dist/selftest/menu-perf.test.js +198 -12
  180. package/dist/selftest/menu.test.js +4 -0
  181. package/dist/selftest/remote.test.d.ts +2 -0
  182. package/dist/selftest/remote.test.js +536 -0
  183. package/dist/selftest/repo-guard.test.js +56 -2
  184. package/dist/selftest/resume.test.js +2 -1
  185. package/dist/selftest/sharing.test.js +9 -2
  186. package/dist/selftest/support/fixtures.d.ts +13 -0
  187. package/dist/selftest/support/web-preview.js +63 -0
  188. package/dist/selftest/web.test.js +2 -0
  189. package/dist/shared/channel/schema.d.ts +23 -0
  190. package/dist/shared/channel/schema.js +8 -0
  191. package/dist/shared/pty/protocol.d.ts +2 -0
  192. package/dist/shared/pty/protocol.js +2 -0
  193. package/dist/web/index.html +1 -1
  194. package/dist/web/main-NBQ3LF4E.js +221 -0
  195. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  196. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  197. package/native/csharp/HostTools/Program.cs +17 -1
  198. package/native/csharp/HostTools/WebHelper.cs +499 -0
  199. package/native/scripts/get-network-profile.ps1 +19 -0
  200. package/native/scripts/set-folder-access.ps1 +11 -0
  201. package/native/scripts/set-web-firewall.ps1 +103 -0
  202. package/package.json +1 -1
  203. package/sandbox/csharp/PtyHost.cs +20 -0
  204. package/schemas/config.schema.json +65 -0
  205. package/schemas/sandbox-config.schema.json +0 -18
  206. package/dist/web/main-UD4QCXZR.js +0 -219
@@ -57,6 +57,7 @@ export const resumeSuite = {
57
57
  status({ id: 's2', harness: 'codex', cwd: 'C:\\Workspace\\web\\src', startedAt: minutes(20) }),
58
58
  status({ id: 's3', phase: 'exited' }),
59
59
  status({ id: 's4', cwd: 'D:\\nowhere' }),
60
+ status({ id: 's5', harness: 'pwsh', kind: 'shell' }),
60
61
  ], reg, NOW);
61
62
  const saved = ledger.read();
62
63
  t.equal([saved?.sessions.map((s) => [s.harness, s.project, s.conversation]), saved?.launch.projects], [
@@ -65,7 +66,7 @@ export const resumeSuite = {
65
66
  ['codex', 'F:\\code\\web\\src', undefined],
66
67
  ],
67
68
  ['F:\\code\\web'],
68
- ], 'running sessions are noted with their folder on this PC (ended ones and unknown folders are not), and the projects');
69
+ ], 'running sessions are noted with their folder on this PC (ended ones, unknown folders and shells are not), and the projects');
69
70
  ledger.recordSessions([
70
71
  status({ startedAt: minutes(30) }),
71
72
  status({ id: 's2', harness: 'codex', cwd: 'C:\\Workspace\\web\\src', startedAt: minutes(20) }),
@@ -142,7 +142,7 @@ async function permissionPlan(t) {
142
142
  await t.throws(() => sharingAclPlan({ storageUserDir, dataPath: t.at('elsewhere', 'default'), groupSid: GROUP_SID, on: true }), 'not under', 'a data set outside the user folder is refused');
143
143
  }
144
144
  /** The PowerShell script: it parses, changes a temp folder's permissions, and refuses links. Windows only. */
145
- function folderScript(t) {
145
+ async function folderScript(t) {
146
146
  t.section('set-folder-access.ps1');
147
147
  if (process.platform !== 'win32') {
148
148
  t.skip('the folder-permission script runs only on Windows');
@@ -223,6 +223,13 @@ function folderScript(t) {
223
223
  fs.mkdirSync(path.join(own, 'child'));
224
224
  fs.writeFileSync(path.join(own, 'child', 'a.txt'), 'x');
225
225
  t.check(fs.readFileSync(path.join(own, 'child', 'a.txt'), 'utf8') === 'x', 'the owner can still use a private folder');
226
+ // Security review 2026-10: under an all-users install another member of the group can create users\<you> first.
227
+ const theirs = t.dir('acl-someone-elses');
228
+ const given = spawnSync(SYSTEM.icacls(), [theirs, '/setowner', '*S-1-5-18'], { encoding: 'utf8', windowsHide: true });
229
+ if (given.status !== 0)
230
+ t.skip('a folder owned by someone else (cannot give a folder to SYSTEM here)');
231
+ else
232
+ await t.throws(() => runPrivateFolder(theirs), 'not to you', 'a folder someone else owns is refused, never made "private" for you (its owner could open it again)');
226
233
  }
227
234
  export const sharingSuite = {
228
235
  name: 'sharing',
@@ -236,7 +243,7 @@ export const sharingSuite = {
236
243
  recordsSection(t);
237
244
  ownership(t);
238
245
  await permissionPlan(t);
239
- folderScript(t);
246
+ await folderScript(t);
240
247
  }
241
248
  finally {
242
249
  // Later suites load the settings too: the machine file this suite wrote must not outlive it.
@@ -263,6 +263,19 @@ export declare function createFixtures(t: Harness): {
263
263
  enabled: boolean;
264
264
  port: number;
265
265
  openOnLaunch: boolean;
266
+ remote: {
267
+ windowsSignIn: boolean;
268
+ users: {
269
+ name: string;
270
+ role: "view" | "control";
271
+ }[];
272
+ rememberDays: number;
273
+ lan: {
274
+ enabled: boolean;
275
+ port: number;
276
+ address: string;
277
+ };
278
+ };
266
279
  };
267
280
  agentCommands: {
268
281
  enabled: boolean;
@@ -594,9 +594,55 @@ function sampleAuditLog(dir) {
594
594
  sv: undefined,
595
595
  },
596
596
  proc(5, node, 'node dist/bin/agent-sandbox.js self-test app', claude),
597
+ { t: at(4), k: 'remote', p: 'sessions.restart', a: 'ok', au: "device Josh's iPhone" },
598
+ { t: at(3), k: 'remote', p: 'settings.set', a: 'refused', au: 'Windows user DESKTOP-JOSH\\sam' },
597
599
  ]);
598
600
  return log;
599
601
  }
602
+ const ACCESS_FINGERPRINT = '3A:7F:01:C2:9B:44:E8:15:6D:A0:2B:93:CC:71:58:0E:F4:12:9A:BD:63:07:E5:2C:48:D9:B1:76:0A:3F:C8:E2';
603
+ /** Remote access: LAN mode on, two devices, one Windows sign-in, a code waiting. */
604
+ function sampleAccess() {
605
+ const at = (hours) => new Date(Date.now() + hours * 3_600_000).toISOString();
606
+ return {
607
+ lan: {
608
+ enabled: true,
609
+ running: true,
610
+ address: 'https://192.168.1.20:47801',
611
+ fingerprint: ACCESS_FINGERPRINT,
612
+ problem: null,
613
+ network: 'Home Wi-Fi',
614
+ },
615
+ windowsSignIn: true,
616
+ users: [
617
+ { name: 'sam', role: 'view' },
618
+ { name: 'OFFICE\\kim', role: 'control' },
619
+ ],
620
+ rememberDays: 30,
621
+ devices: [
622
+ {
623
+ id: '4f2c9a7e1b3d5f60',
624
+ name: "Josh's iPhone",
625
+ role: 'control',
626
+ address: '192.168.1.42',
627
+ createdAt: at(-24 * 6),
628
+ expiresAt: at(24 * 24),
629
+ lastSeen: at(-0.2),
630
+ },
631
+ {
632
+ id: '9d1e0b2a7c4f6e83',
633
+ name: 'Kitchen tablet',
634
+ role: 'view',
635
+ address: '192.168.1.57',
636
+ createdAt: at(-24 * 20),
637
+ expiresAt: at(24 * 10),
638
+ lastSeen: at(-30),
639
+ },
640
+ ],
641
+ windows: [{ id: '1a2b3c4d5e6f7a8b', user: 'DESKTOP-JOSH\\sam', createdAt: at(-3), expiresAt: at(24 * 30 - 3) }],
642
+ pending: { role: 'view', expiresAt: at(0.06) },
643
+ codeVoided: false,
644
+ };
645
+ }
600
646
  /** The real features where they only touch the temp folder, sample data for the rest. */
601
647
  function previewRpc(ctx, state) {
602
648
  const auditDir = path.join(ctx.storageRoot, 'audit', 'preview');
@@ -608,6 +654,16 @@ function previewRpc(ctx, state) {
608
654
  return auditListing(audit, { enabled: true, days: 7, maxMb: 100 }, listAudit.input.parse(input ?? {}), auditDir);
609
655
  case 'sandbox.status':
610
656
  return sampleStatus(state.running);
657
+ case 'access.status':
658
+ return sampleAccess();
659
+ case 'access.allowDevice':
660
+ return {
661
+ code: 'K7QD-M2XP',
662
+ expiresAt: new Date(Date.now() + 5 * 60_000).toISOString(),
663
+ role: input?.role ?? 'view',
664
+ address: 'https://192.168.1.20:47801',
665
+ fingerprint: ACCESS_FINGERPRINT,
666
+ };
611
667
  case 'vpn.status':
612
668
  return vpnStatus.output.parse({
613
669
  enabled: true,
@@ -886,9 +942,16 @@ function previewRpc(ctx, state) {
886
942
  'engine.status': 'query',
887
943
  'engine.leftovers': 'query',
888
944
  'audit.list': 'query',
945
+ 'access.status': 'query',
946
+ 'access.allowDevice': 'operation',
947
+ 'access.revoke': 'operation',
948
+ 'access.revokeAll': 'operation',
949
+ 'access.lanOn': 'operation',
950
+ 'access.lanOff': 'operation',
889
951
  };
890
952
  return {
891
953
  kind: (id) => kinds[id],
954
+ need: (id) => (kinds[id] ? 'view' : undefined),
892
955
  liveMs: (id) => (id === 'sandbox.status' || id === 'sessions.list' ? 2500 : id === 'logs.tail' ? 1000 : undefined),
893
956
  run: async (id, input, io) => id !== 'apps.request' && (id.startsWith('settings.') || id.startsWith('apps.') || id === 'files.browse')
894
957
  ? runDefinition(id, ctx, input, io)
@@ -105,6 +105,7 @@ function fakeRpc() {
105
105
  const host = {
106
106
  kind: (id) => (id === 'test.work' ? 'operation' : id === 'test.live' ? 'query' : undefined),
107
107
  liveMs: (id) => (id === 'test.live' ? 50 : undefined),
108
+ need: (id) => (id === 'test.work' ? 'control' : id === 'test.live' ? 'view' : undefined),
108
109
  run: async (id, input, io) => {
109
110
  ran.push(id);
110
111
  if (id === 'test.live')
@@ -216,6 +217,7 @@ export const webSuite = {
216
217
  let reads = 0;
217
218
  const host = {
218
219
  kind: () => 'query',
220
+ need: () => 'view',
219
221
  liveMs: () => 40,
220
222
  run: async () => {
221
223
  reads++;
@@ -200,6 +200,14 @@ export declare const ProjectSpecSchema: z.ZodObject<{
200
200
  }, z.core.$strict>>;
201
201
  hooks: z.ZodBoolean;
202
202
  }, z.core.$strict>;
203
+ /** The plain shells a session can run instead of an agent; auto: PowerShell 7 when the sandbox has it, else 5.1. */
204
+ export declare const ShellChoiceSchema: z.ZodEnum<{
205
+ pwsh: "pwsh";
206
+ auto: "auto";
207
+ powershell: "powershell";
208
+ cmd: "cmd";
209
+ }>;
210
+ export type ShellChoice = z.output<typeof ShellChoiceSchema>;
203
211
  /** C:\AgentData\run\requests\<id>.json: the ONLY things the host can ask the sandbox to do. */
204
212
  export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
205
213
  kind: z.ZodLiteral<"session">;
@@ -378,6 +386,17 @@ export declare const GuestRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
378
386
  resumeArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
379
387
  resumeOneArguments: z.ZodOptional<z.ZodArray<z.ZodString>>;
380
388
  }, z.core.$strict>>;
389
+ shell: z.ZodOptional<z.ZodEnum<{
390
+ pwsh: "pwsh";
391
+ auto: "auto";
392
+ powershell: "powershell";
393
+ cmd: "cmd";
394
+ }>>;
395
+ createdAt: z.ZodString;
396
+ }, z.core.$strict>, z.ZodObject<{
397
+ kind: z.ZodLiteral<"close">;
398
+ id: z.ZodString;
399
+ session: z.ZodString;
381
400
  createdAt: z.ZodString;
382
401
  }, z.core.$strict>, z.ZodObject<{
383
402
  kind: z.ZodLiteral<"project">;
@@ -603,6 +622,10 @@ export declare const SessionStatusSchema: z.ZodObject<{
603
622
  id: z.ZodString;
604
623
  launchId: z.ZodString;
605
624
  harness: z.ZodString;
625
+ kind: z.ZodOptional<z.ZodEnum<{
626
+ shell: "shell";
627
+ agent: "agent";
628
+ }>>;
606
629
  cwd: z.ZodString;
607
630
  project: z.ZodOptional<z.ZodString>;
608
631
  phase: z.ZodEnum<{
@@ -60,6 +60,8 @@ export const ProjectSpecSchema = z.strictObject({
60
60
  /** Its hooks were staged in C:\AgentLaunch\projects\<name>\hooks. */
61
61
  hooks: z.boolean(),
62
62
  });
63
+ /** The plain shells a session can run instead of an agent; auto: PowerShell 7 when the sandbox has it, else 5.1. */
64
+ export const ShellChoiceSchema = z.enum(['auto', 'pwsh', 'powershell', 'cmd']);
63
65
  /** C:\AgentData\run\requests\<id>.json: the ONLY things the host can ask the sandbox to do. */
64
66
  export const GuestRequestSchema = z.discriminatedUnion('kind', [
65
67
  z.strictObject({
@@ -70,8 +72,12 @@ export const GuestRequestSchema = z.discriminatedUnion('kind', [
70
72
  cwd: Text(),
71
73
  project: ProjectSpecSchema.optional(),
72
74
  harnessSpec: HarnessSchema.optional(),
75
+ /** A plain shell instead of an agent (harness is then "shell" and args are ignored). */
76
+ shell: ShellChoiceSchema.optional(),
73
77
  createdAt: TimeSchema,
74
78
  }),
79
+ /** End a running session (an agent or a shell) and everything it started. */
80
+ z.strictObject({ kind: z.literal('close'), id: IdSchema, session: IdSchema, createdAt: TimeSchema }),
75
81
  /** Provision a registered project without starting an agent (sandbox start / exec / db from its folder). */
76
82
  z.strictObject({ kind: z.literal('project'), id: IdSchema, project: ProjectSpecSchema, createdAt: TimeSchema }),
77
83
  z.strictObject({
@@ -140,6 +146,8 @@ export const SessionStatusSchema = z.object({
140
146
  id: IdSchema,
141
147
  launchId: Text(64),
142
148
  harness: Text(64),
149
+ /** A plain shell (harness is then the shell: pwsh, powershell or cmd); absent: an agent. */
150
+ kind: z.enum(['agent', 'shell']).optional(),
143
151
  cwd: Text(),
144
152
  /** The project it runs in: its hub name, or the launch folder's for the first project. */
145
153
  project: Text(64).optional(),
@@ -4,6 +4,8 @@ export declare const FrameType: {
4
4
  readonly Resize: 3;
5
5
  readonly Restart: 4;
6
6
  readonly Ping: 5;
7
+ /** Ends the program and everything it started, and with it the session. */
8
+ readonly Close: 6;
7
9
  readonly Output: 16;
8
10
  readonly Exit: 17;
9
11
  readonly Error: 18;
@@ -6,6 +6,8 @@ export const FrameType = {
6
6
  Resize: 3,
7
7
  Restart: 4,
8
8
  Ping: 5,
9
+ /** Ends the program and everything it started, and with it the session. */
10
+ Close: 6,
9
11
  Output: 16,
10
12
  Exit: 17,
11
13
  Error: 18,
@@ -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-UD4QCXZR.js"></script>
9
+ <script type="module" src="/main-NBQ3LF4E.js"></script>
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>