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
@@ -0,0 +1,129 @@
1
+ // Remote access's work (docs/design/remote-access.md): the access list in <storage>\web\access.json (shared with the
2
+ // running web server, which reads it again when it changes and closes the pages of whoever was signed out), the
3
+ // remote settings, the firewall rule and the network check of LAN mode. The one-time code is returned once and only
4
+ // its hash is kept.
5
+ import { requireOnPc } from '../../../cli/commands/context.js';
6
+ import { fail } from '../../../core/util/index.js';
7
+ import { AccessStore, addRuleRequest, applyFirewall, chooseLanAddress, lanUrl, networkProblem, networkProfile, removeRuleRequest, showCode, } from '../../../host/remote/index.js';
8
+ import { SecretStore } from '../../../host/secrets/index.js';
9
+ import { protectPrivateFolder } from '../../../host/sharing/index.js';
10
+ import { selfTestRunning } from '../../../host/test-guard.js';
11
+ import { WebStore } from '../../../host/web/index.js';
12
+ import { implement } from '../../context.js';
13
+ import { ConfigFile } from '../settings/index.js';
14
+ import { accessStatus, allowDevice, lanOff, lanOn, revokeAccess, revokeAllAccess } from './access.def.js';
15
+ /** The access list of this user (the folder is the web state's private one). */
16
+ export function accessStoreOf(ctx) {
17
+ return AccessStore.at(ctx.storageRoot, SecretStore.standard(), {
18
+ // The self-test never changes folder permissions; its storage is a temp folder.
19
+ protect: selfTestRunning() ? undefined : (dir) => protectPrivateFolder(dir),
20
+ });
21
+ }
22
+ function lanStateOf(ctx) {
23
+ const lan = new WebStore(ctx.storageRoot).read()?.lan;
24
+ return { url: lan?.url ?? null, fingerprint: lan?.fingerprint ?? null, problem: lan?.problem ?? null };
25
+ }
26
+ function setLan(ctx, enabled) {
27
+ const outcome = ConfigFile.user(ctx.loaded.configPath).set(['web', 'remote', 'lan', 'enabled'], enabled);
28
+ if (typeof outcome === 'object')
29
+ fail('Could not change web.remote.lan.enabled: ' + outcome.problems.join('; '));
30
+ }
31
+ export const accessStatusRun = implement(accessStatus, (ctx) => {
32
+ requireOnPc('web');
33
+ const remote = ctx.loaded.config.web.remote;
34
+ const data = accessStoreOf(ctx).read();
35
+ const now = Date.now();
36
+ const alive = (iso) => Date.parse(iso) > now;
37
+ const lan = lanStateOf(ctx);
38
+ return {
39
+ lan: {
40
+ enabled: remote.lan.enabled,
41
+ running: remote.lan.enabled && lan.url !== null,
42
+ address: remote.lan.enabled ? lan.url : null,
43
+ fingerprint: remote.lan.enabled ? lan.fingerprint : null,
44
+ problem: remote.lan.enabled ? lan.problem : null,
45
+ network: data.network,
46
+ },
47
+ windowsSignIn: remote.windowsSignIn,
48
+ users: remote.users.map((u) => ({ name: u.name, role: u.role })),
49
+ rememberDays: remote.rememberDays,
50
+ devices: data.devices
51
+ .filter((d) => alive(d.expiresAt))
52
+ .map((d) => ({
53
+ id: d.id,
54
+ name: d.name,
55
+ role: d.role,
56
+ address: d.address,
57
+ createdAt: d.createdAt,
58
+ expiresAt: d.expiresAt,
59
+ lastSeen: d.lastSeen ?? null,
60
+ })),
61
+ windows: data.windows
62
+ .filter((w) => alive(w.expiresAt))
63
+ .map((w) => ({ id: w.id, user: w.user, createdAt: w.createdAt, expiresAt: w.expiresAt })),
64
+ pending: data.code && alive(data.code.expiresAt) ? { role: data.code.role, expiresAt: data.code.expiresAt } : null,
65
+ codeVoided: data.codeVoided,
66
+ };
67
+ });
68
+ export const allowDeviceRun = implement(allowDevice, (ctx, input) => {
69
+ requireOnPc('web');
70
+ if (!ctx.loaded.config.web.remote.lan.enabled)
71
+ fail('LAN mode is off, so no device on your network can reach the web UI.', 'Turn it on first: sandbox web lan-on');
72
+ const { code, expiresAt } = accessStoreOf(ctx).newDeviceCode(input.role);
73
+ const lan = lanStateOf(ctx);
74
+ return { code: showCode(code), expiresAt, role: input.role, address: lan.url, fingerprint: lan.fingerprint };
75
+ });
76
+ export const revokeAccessRun = implement(revokeAccess, (ctx, input) => {
77
+ requireOnPc('web');
78
+ if (!accessStoreOf(ctx).revoke(input.id))
79
+ fail('There is no device or sign-in ' + input.id + '.', 'See sandbox web devices.');
80
+ return { message: 'Signed out. Its open pages close within half a minute.' };
81
+ });
82
+ export const revokeAllAccessRun = implement(revokeAllAccess, async (ctx, _input, io) => {
83
+ requireOnPc('web');
84
+ const ok = await io.confirm({
85
+ title: 'Sign out every device and Windows user now?',
86
+ danger: true,
87
+ yes: 'Sign out all',
88
+ });
89
+ if (!ok)
90
+ return { message: 'Nothing changed.' };
91
+ accessStoreOf(ctx).revokeAll('everything');
92
+ return { message: 'Everyone is signed out, and a code not used yet is void.' };
93
+ });
94
+ export const lanOnRun = implement(lanOn, async (ctx, _input, io) => {
95
+ requireOnPc('web');
96
+ const lan = ctx.loaded.config.web.remote.lan;
97
+ const bound = chooseLanAddress(lan.address);
98
+ io.progress('Checking the network');
99
+ const profile = await networkProfile(bound.address);
100
+ const problem = networkProblem(profile, null);
101
+ if (problem)
102
+ fail(problem, 'LAN mode only runs on a network you marked Private (Windows Settings > Network > your network).');
103
+ io.progress('Adding the firewall rule (Windows asks for permission)');
104
+ await applyFirewall(addRuleRequest(lan.port, bound.address));
105
+ accessStoreOf(ctx).setNetwork(profile.name);
106
+ setLan(ctx, true);
107
+ const address = lanUrl(bound.address, lan.port);
108
+ return {
109
+ address,
110
+ message: 'LAN mode is on for the network "' +
111
+ profile.name +
112
+ '": devices open ' +
113
+ address +
114
+ ' (the running web UI starts listening within half a minute). Next: Allow a new device.',
115
+ };
116
+ });
117
+ export const lanOffRun = implement(lanOff, async (ctx, _input, io) => {
118
+ requireOnPc('web');
119
+ const ok = await io.confirm({ title: 'Turn off LAN mode and sign out every device?', danger: true, yes: 'Turn off' });
120
+ if (!ok)
121
+ return { message: 'Nothing changed.' };
122
+ setLan(ctx, false);
123
+ const store = accessStoreOf(ctx);
124
+ store.revokeAll('devices');
125
+ store.setNetwork(null);
126
+ io.progress('Removing the firewall rule (Windows asks for permission)');
127
+ await applyFirewall(removeRuleRequest());
128
+ return { message: 'LAN mode is off: the firewall rule is gone and every device is signed out.' };
129
+ });
@@ -0,0 +1,2 @@
1
+ export * from './access.def.js';
2
+ export * from './access.run.js';
@@ -0,0 +1,3 @@
1
+ // Remote access: devices on your network and other Windows users of this PC (docs/design/remote-access.md).
2
+ export * from './access.def.js';
3
+ export * from './access.run.js';
@@ -76,6 +76,7 @@ export declare const useAccount: import("../../kernel/define.js").OperationDef<z
76
76
  export declare const defaultAccount: import("../../kernel/define.js").OperationDef<z.ZodObject<{
77
77
  agent: z.ZodDefault<z.ZodString>;
78
78
  name: z.ZodOptional<z.ZodString>;
79
+ noRestart: z.ZodDefault<z.ZodBoolean>;
79
80
  }, z.core.$strip>, z.ZodObject<{
80
81
  message: z.ZodString;
81
82
  }, z.core.$strip>, "accounts.default">;
@@ -103,11 +103,20 @@ export const useAccount = defineOperation({
103
103
  export const defaultAccount = defineOperation({
104
104
  id: 'accounts.default',
105
105
  title: 'Make default',
106
- summary: 'the login new launches start with',
107
- input: z.object({ agent: AgentSchema, name: NameSchema }),
106
+ summary: 'the login every launch starts with; the sandbox switches to it now too',
107
+ input: z.object({
108
+ agent: AgentSchema,
109
+ name: NameSchema,
110
+ noRestart: z.boolean().default(false).describe('(default) do not restart running sessions'),
111
+ }),
108
112
  output: MessageSchema,
109
113
  text: (o) => o.message,
110
- cli: { name: 'account', action: 'default', positional: ['name'], flags: { agent: { flag: '--agent' } } },
114
+ cli: {
115
+ name: 'account',
116
+ action: 'default',
117
+ positional: ['name'],
118
+ flags: { agent: { flag: '--agent' }, noRestart: { flag: '--no-restart' } },
119
+ },
111
120
  });
112
121
  export const renameAccount = defineOperation({
113
122
  id: 'accounts.rename',
@@ -33,6 +33,7 @@ export declare const useAccountRun: import("../../kernel/define.js").Implementat
33
33
  export declare const defaultAccountRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
34
34
  agent: import("zod").ZodDefault<import("zod").ZodString>;
35
35
  name: import("zod").ZodOptional<import("zod").ZodString>;
36
+ noRestart: import("zod").ZodDefault<import("zod").ZodBoolean>;
36
37
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
37
38
  message: import("zod").ZodString;
38
39
  }, import("zod/v4/core").$strip>, "accounts.default">, import("../../../cli/commands/context.js").Context>;
@@ -71,32 +71,41 @@ export const saveAccountRun = implement(saveAccount, async (ctx, input, io) => {
71
71
  const saved = service.save(name, input.fromHost, input.agent);
72
72
  return { name: saved.name, message: 'Saved account ' + label(saved) + '.' };
73
73
  });
74
- export const useAccountRun = implement(useAccount, async (ctx, input, io) => {
75
- const service = new AccountsService(ctx);
76
- const name = await accountName(io, service, 'use', input.agent, input.name);
77
- // The switch is done before the question: a "no" to the restart keeps the new login and only skips the restart.
78
- const used = service.activate(name, input.agent);
74
+ /**
75
+ * Makes the sandbox use a saved login, then offers to restart the agent's running sessions. The switch is done before
76
+ * the question: a "no" keeps the new login and only skips the restart.
77
+ */
78
+ async function switchTo(io, service, name, agent, noRestart) {
79
+ const used = service.activate(name, agent);
79
80
  const lines = ['Sandbox now uses ' + label(used) + '.'];
80
81
  if (used.note)
81
82
  lines.push(safeText(used.note));
82
- if (service.hasRunningSessions(input.agent) && !input.noRestart) {
83
+ if (service.hasRunningSessions(agent) && !noRestart) {
83
84
  const restart = await io.confirm({
84
- title: 'Restart the running ' + input.agent + ' sessions?',
85
+ title: 'Restart the running ' + agent + ' sessions?',
85
86
  lines: ['They restart and continue their conversation where the agent can, now under the new login.'],
86
87
  yes: 'Restart',
87
88
  implied: true,
88
89
  });
89
90
  if (restart)
90
- lines.push(safeText(await service.restart(input.agent)) +
91
- ' with --continue; the conversation carries on under the new account.');
91
+ lines.push(safeText(await service.restart(agent)) + ' with --continue; the conversation carries on under the new account.');
92
92
  }
93
- return { lines };
93
+ return lines;
94
+ }
95
+ export const useAccountRun = implement(useAccount, async (ctx, input, io) => {
96
+ const service = new AccountsService(ctx);
97
+ const name = await accountName(io, service, 'use', input.agent, input.name);
98
+ return { lines: await switchTo(io, service, name, input.agent, input.noRestart) };
94
99
  });
95
100
  export const defaultAccountRun = implement(defaultAccount, async (ctx, input, io) => {
96
101
  const service = new AccountsService(ctx);
97
102
  const name = await accountName(io, service, 'default', input.agent, input.name);
98
103
  service.setDefault(name, input.agent);
99
- return { message: 'Default account: ' + name };
104
+ const lines = ['Default account: ' + name];
105
+ // The sandbox follows the new default at once (not only from the next launch).
106
+ if (service.activeName(input.agent) !== name)
107
+ lines.push(...(await switchTo(io, service, name, input.agent, input.noRestart)));
108
+ return { message: lines.join('\n') };
100
109
  });
101
110
  export const renameAccountRun = implement(renameAccount, async (ctx, input, io) => {
102
111
  const service = new AccountsService(ctx);
@@ -2,6 +2,8 @@
2
2
  // adding and removing one change. Node side (it checks names with the config schema); the agents run writes them.
3
3
  import { DEFAULTS } from '../../../core/config/index.js';
4
4
  import { HarnessSchema, NameSchema, describeIssues } from '../../../core/schema/index.js';
5
+ /** Names an agent cannot have. */
6
+ const RESERVED = ['shell', 'pwsh', 'powershell', 'cmd', 'close'];
5
7
  /** Nothing wrong with the name (true), or what is wrong. Pure. */
6
8
  export function agentNameProblem(name, taken) {
7
9
  const typed = name.trim();
@@ -12,6 +14,9 @@ export function agentNameProblem(name, taken) {
12
14
  return 'Use letters, numbers, - and _ only.';
13
15
  if (taken.some((t) => t.toLowerCase() === typed.toLowerCase()))
14
16
  return typed + ' is an agent already.';
17
+ // Shell sessions are listed by these names, and sandbox shell / close are commands.
18
+ if (RESERVED.includes(typed.toLowerCase()))
19
+ return typed + ' is taken by the sandbox; choose another name.';
15
20
  return true;
16
21
  }
17
22
  /** The command a package usually provides: "@scope/my-agent@latest" gives "my-agent". Pure. */
@@ -25,6 +25,7 @@ export const listAgents = defineQuery({
25
25
  });
26
26
  export const startAgent = defineOperation({
27
27
  id: 'agents.start',
28
+ access: 'control',
28
29
  title: 'Start an agent',
29
30
  summary: 'start an agent in a project of the running sandbox',
30
31
  input: z.object({
@@ -145,6 +145,7 @@ export const setCustomApps = defineOperation({
145
145
  });
146
146
  export const requestApp = defineOperation({
147
147
  id: 'apps.request',
148
+ access: 'control',
148
149
  title: 'Request an app…',
149
150
  summary: 'open a prefilled GitHub request for an app that is not in the list',
150
151
  input: z.object({}),
@@ -1,13 +1,14 @@
1
1
  import { z } from 'zod';
2
2
  import { type Page } from '../../kernel/index.js';
3
- export declare const AUDIT_EVENT_KINDS: readonly ["proc", "file", "commit", "session", "guard", "note"];
4
- export declare const AUDIT_KIND_FILTERS: readonly ["all", "proc", "file", "commit", "session", "guard"];
3
+ export declare const AUDIT_EVENT_KINDS: readonly ["proc", "file", "commit", "session", "guard", "note", "remote"];
4
+ export declare const AUDIT_KIND_FILTERS: readonly ["all", "proc", "file", "commit", "session", "guard", "remote"];
5
5
  /** The session filter that means "not linked to any session". */
6
6
  export declare const NO_SESSION = "none";
7
7
  export declare const AuditRowSchema: z.ZodObject<{
8
8
  time: z.ZodString;
9
9
  kind: z.ZodEnum<{
10
10
  file: "file";
11
+ remote: "remote";
11
12
  session: "session";
12
13
  note: "note";
13
14
  commit: "commit";
@@ -60,6 +61,7 @@ export declare const AuditListSchema: z.ZodObject<{
60
61
  days: z.ZodNumber;
61
62
  kind: z.ZodEnum<{
62
63
  file: "file";
64
+ remote: "remote";
63
65
  all: "all";
64
66
  session: "session";
65
67
  commit: "commit";
@@ -76,6 +78,7 @@ export declare const AuditListSchema: z.ZodObject<{
76
78
  time: z.ZodString;
77
79
  kind: z.ZodEnum<{
78
80
  file: "file";
81
+ remote: "remote";
79
82
  session: "session";
80
83
  note: "note";
81
84
  commit: "commit";
@@ -134,6 +137,7 @@ export declare const listAudit: import("../../kernel/define.js").QueryDef<z.ZodO
134
137
  days: z.ZodDefault<z.ZodNumber>;
135
138
  kind: z.ZodDefault<z.ZodEnum<{
136
139
  file: "file";
140
+ remote: "remote";
137
141
  all: "all";
138
142
  session: "session";
139
143
  commit: "commit";
@@ -155,6 +159,7 @@ export declare const listAudit: import("../../kernel/define.js").QueryDef<z.ZodO
155
159
  days: z.ZodNumber;
156
160
  kind: z.ZodEnum<{
157
161
  file: "file";
162
+ remote: "remote";
158
163
  all: "all";
159
164
  session: "session";
160
165
  commit: "commit";
@@ -171,6 +176,7 @@ export declare const listAudit: import("../../kernel/define.js").QueryDef<z.ZodO
171
176
  time: z.ZodString;
172
177
  kind: z.ZodEnum<{
173
178
  file: "file";
179
+ remote: "remote";
174
180
  session: "session";
175
181
  note: "note";
176
182
  commit: "commit";
@@ -248,6 +254,7 @@ export declare const auditView: import("../../kernel/define.js").ViewDef<{
248
254
  days: z.ZodDefault<z.ZodNumber>;
249
255
  kind: z.ZodDefault<z.ZodEnum<{
250
256
  file: "file";
257
+ remote: "remote";
251
258
  all: "all";
252
259
  session: "session";
253
260
  commit: "commit";
@@ -269,6 +276,7 @@ export declare const auditView: import("../../kernel/define.js").ViewDef<{
269
276
  days: z.ZodNumber;
270
277
  kind: z.ZodEnum<{
271
278
  file: "file";
279
+ remote: "remote";
272
280
  all: "all";
273
281
  session: "session";
274
282
  commit: "commit";
@@ -285,6 +293,7 @@ export declare const auditView: import("../../kernel/define.js").ViewDef<{
285
293
  time: z.ZodString;
286
294
  kind: z.ZodEnum<{
287
295
  file: "file";
296
+ remote: "remote";
288
297
  session: "session";
289
298
  note: "note";
290
299
  commit: "commit";
@@ -5,8 +5,8 @@
5
5
  import { z } from 'zod';
6
6
  import { action, ago, bytesText, defineQuery, defineView, link, plural, } from '../../kernel/index.js';
7
7
  import { setSetting } from '../settings/settings.def.js';
8
- export const AUDIT_EVENT_KINDS = ['proc', 'file', 'commit', 'session', 'guard', 'note'];
9
- export const AUDIT_KIND_FILTERS = ['all', 'proc', 'file', 'commit', 'session', 'guard'];
8
+ export const AUDIT_EVENT_KINDS = ['proc', 'file', 'commit', 'session', 'guard', 'note', 'remote'];
9
+ export const AUDIT_KIND_FILTERS = ['all', 'proc', 'file', 'commit', 'session', 'guard', 'remote'];
10
10
  /** The days the page offers (the log keeps at most 30). */
11
11
  const PERIODS = [1, 3, 7, 14, 30];
12
12
  /** The session filter that means "not linked to any session". */
@@ -20,12 +20,13 @@ const KIND_LABEL = {
20
20
  session: 'session',
21
21
  guard: 'GUARD',
22
22
  note: 'note',
23
+ remote: 'remote',
23
24
  };
24
25
  export const AuditRowSchema = z.object({
25
26
  time: z.string().describe('When it happened (ISO time)'),
26
27
  kind: z
27
28
  .enum(AUDIT_EVENT_KINDS)
28
- .describe('proc: a program started; file: changed in a project; commit; session; guard: the repo guard; note'),
29
+ .describe('proc: a program started; file: changed in a project; commit; session; guard: the repo guard; note; remote: what another Windows user or a paired device did in the web UI'),
29
30
  what: z.string().describe('The program, the file, the commit message, the agent, or what happened'),
30
31
  command: z.string().optional().describe("A program's command line (secrets hidden)"),
31
32
  parent: z.string().optional().describe('The program that started it'),
@@ -43,7 +44,7 @@ export const AuditRowSchema = z.object({
43
44
  .describe('How it was linked: process = by the programs the session started; only-session = the only session running in that project then (likely, not proven)'),
44
45
  count: z.number().int().describe('How many times it happened in that minute'),
45
46
  sha: z.string().optional().describe("A commit's id"),
46
- author: z.string().optional().describe("A commit's author"),
47
+ author: z.string().optional().describe("A commit's author; for remote: who did it"),
47
48
  });
48
49
  const CountsSchema = z.object({
49
50
  commands: z.number().int().describe('Programs started'),
@@ -152,6 +153,8 @@ export function eventWhat(e) {
152
153
  (e.action && e.action !== 'commit' ? ' (' + e.action + ')' : ''));
153
154
  case 'session':
154
155
  return e.what + (e.action === 'end' ? ' ended' : ' started') + (e.project ? ' in ' + e.project : '');
156
+ case 'remote':
157
+ return (e.author ?? 'someone') + ': ' + e.what + (e.action && e.action !== 'ok' ? ' (' + e.action + ')' : '');
155
158
  default:
156
159
  return e.what;
157
160
  }
@@ -14,6 +14,7 @@ export declare const listAuditRun: import("../../kernel/define.js").Implementati
14
14
  days: import("zod").ZodDefault<import("zod").ZodNumber>;
15
15
  kind: import("zod").ZodDefault<import("zod").ZodEnum<{
16
16
  file: "file";
17
+ remote: "remote";
17
18
  all: "all";
18
19
  session: "session";
19
20
  commit: "commit";
@@ -35,6 +36,7 @@ export declare const listAuditRun: import("../../kernel/define.js").Implementati
35
36
  days: import("zod").ZodNumber;
36
37
  kind: import("zod").ZodEnum<{
37
38
  file: "file";
39
+ remote: "remote";
38
40
  all: "all";
39
41
  session: "session";
40
42
  commit: "commit";
@@ -51,6 +53,7 @@ export declare const listAuditRun: import("../../kernel/define.js").Implementati
51
53
  time: import("zod").ZodString;
52
54
  kind: import("zod").ZodEnum<{
53
55
  file: "file";
56
+ remote: "remote";
54
57
  session: "session";
55
58
  note: "note";
56
59
  commit: "commit";