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.
- package/README.md +1 -0
- package/config.example.json +11 -1
- package/dist/app/features/access/access.def.d.ts +190 -0
- package/dist/app/features/access/access.def.js +273 -0
- package/dist/app/features/access/access.run.d.ts +79 -0
- package/dist/app/features/access/access.run.js +129 -0
- package/dist/app/features/access/index.d.ts +2 -0
- package/dist/app/features/access/index.js +3 -0
- package/dist/app/features/accounts/accounts.def.d.ts +1 -0
- package/dist/app/features/accounts/accounts.def.js +12 -3
- package/dist/app/features/accounts/accounts.run.d.ts +1 -0
- package/dist/app/features/accounts/accounts.run.js +20 -11
- package/dist/app/features/agents/agent-entry.js +5 -0
- package/dist/app/features/agents/agents.def.js +1 -0
- package/dist/app/features/apps/apps.def.js +1 -0
- package/dist/app/features/audit/audit.def.d.ts +11 -2
- package/dist/app/features/audit/audit.def.js +7 -4
- package/dist/app/features/audit/audit.run.d.ts +3 -0
- package/dist/app/features/defs.d.ts +156 -3
- package/dist/app/features/defs.js +12 -1
- package/dist/app/features/files/files.def.js +1 -0
- package/dist/app/features/health/health.def.js +1 -0
- package/dist/app/features/sandbox/sandbox.def.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +36 -0
- package/dist/app/features/sessions/sessions.def.js +77 -9
- package/dist/app/features/sessions/sessions.run.d.ts +25 -2
- package/dist/app/features/sessions/sessions.run.js +71 -3
- package/dist/app/features/settings/settings-file.d.ts +7 -0
- package/dist/app/features/settings/settings-file.js +19 -2
- package/dist/app/features/settings/settings-rows.js +9 -1
- package/dist/app/features/settings/settings.def.d.ts +8 -0
- package/dist/app/features/settings/settings.def.js +17 -0
- package/dist/app/features/web/web.def.d.ts +9 -0
- package/dist/app/features/web/web.def.js +26 -1
- package/dist/app/features/web/web.run.d.ts +3 -0
- package/dist/app/features/web/web.run.js +11 -3
- package/dist/app/kernel/access.d.ts +33 -0
- package/dist/app/kernel/access.js +44 -0
- package/dist/app/kernel/define.d.ts +14 -1
- package/dist/app/kernel/index.d.ts +1 -0
- package/dist/app/kernel/index.js +1 -0
- package/dist/app/kernel/rpc.d.ts +5 -2
- package/dist/app/registry.d.ts +4 -1
- package/dist/app/registry.js +24 -4
- package/dist/bin/agent-sandbox.js +7 -1
- package/dist/bin/chunk-IL7BXJF2.js +7 -0
- package/dist/bin/chunk-K4SU3MHJ.js +10432 -0
- package/dist/bin/chunk-VENWSGX2.js +78437 -0
- package/dist/bin/claude-host.js +10 -4
- package/dist/bin/claude-sbx.js +8 -2
- package/dist/bin/codex-sbx.js +8 -2
- package/dist/bin/gemini-sbx.js +8 -2
- package/dist/bin/sandbox.js +7 -2
- package/dist/bin/sbx-hide.js +8 -2
- package/dist/bin/sbx-show.js +8 -2
- package/dist/cli/commands/launch/prepare.js +24 -7
- package/dist/cli/commands/launch/running.js +4 -0
- package/dist/cli/commands/registry.js +2 -0
- package/dist/cli/commands/remote.d.ts +2 -0
- package/dist/cli/commands/remote.js +49 -0
- package/dist/cli/commands/sessions/reopen.js +3 -0
- package/dist/cli/commands/storage/offer.js +1 -1
- package/dist/cli/commands/web.js +66 -0
- package/dist/cli/manifest.d.ts +63 -4
- package/dist/cli/manifest.js +33 -4
- package/dist/cli/menu/io-menu.d.ts +5 -3
- package/dist/cli/menu/io-menu.js +12 -5
- package/dist/cli/menu/live.d.ts +29 -0
- package/dist/cli/menu/live.js +92 -21
- package/dist/cli/menu/menu.d.ts +2 -1
- package/dist/cli/menu/menu.js +16 -2
- package/dist/cli/menu/pages/list-page.d.ts +5 -0
- package/dist/cli/menu/pages/list-page.js +19 -0
- package/dist/cli/menu/remote-menu.d.ts +19 -0
- package/dist/cli/menu/remote-menu.js +108 -0
- package/dist/cli/menu/shell.d.ts +2 -0
- package/dist/cli/menu/shell.js +1 -1
- package/dist/cli/menu/views.js +2 -0
- package/dist/cli/operations/handler.js +15 -1
- package/dist/cli/services/accounts-service.d.ts +7 -0
- package/dist/cli/services/accounts-service.js +20 -0
- package/dist/cli/services/remote-client.d.ts +16 -0
- package/dist/cli/services/remote-client.js +141 -0
- package/dist/cli/services/sessions-service.d.ts +5 -0
- package/dist/cli/services/sessions-service.js +17 -1
- package/dist/cli/tui/app.d.ts +4 -0
- package/dist/cli/tui/app.js +5 -0
- package/dist/cli/tui/terminal.d.ts +6 -0
- package/dist/cli/tui/terminal.js +8 -1
- package/dist/cli/validate.js +8 -4
- package/dist/core/config/defaults.js +11 -1
- package/dist/core/local-config/file.js +16 -2
- package/dist/core/local-config/overrides.js +7 -0
- package/dist/core/package-info.js +1 -1
- package/dist/core/run/versions.js +9 -8
- package/dist/core/schema/config.d.ts +22 -3
- package/dist/core/schema/config.js +39 -2
- package/dist/core/schema/web.d.ts +51 -0
- package/dist/core/schema/web.js +46 -1
- package/dist/core/util/fs.d.ts +5 -0
- package/dist/core/util/fs.js +23 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/daemon/daemon.js +2 -0
- package/dist/guest/daemon/idle-shutdown.js +2 -1
- package/dist/guest/daemon/sessions.d.ts +16 -2
- package/dist/guest/daemon/sessions.js +126 -20
- package/dist/guest/git/decision.js +7 -0
- package/dist/guest/sessions/cmdline.d.ts +14 -0
- package/dist/guest/sessions/cmdline.js +10 -0
- package/dist/guest/toolchains/setup.js +3 -0
- package/dist/host/audit/log.d.ts +3 -2
- package/dist/host/audit/log.js +3 -3
- package/dist/host/channel/channel.d.ts +5 -1
- package/dist/host/channel/channel.js +12 -0
- package/dist/host/guard/agent-files.js +7 -1
- package/dist/host/guard/commands.js +13 -1
- package/dist/host/guard/git-config.js +27 -7
- package/dist/host/guard/git-dirs.js +78 -3
- package/dist/host/guard/mark-of-the-web.js +3 -1
- package/dist/host/guard/nested-repos.js +7 -2
- package/dist/host/guard/store.js +1 -0
- package/dist/host/guard/types.d.ts +2 -0
- package/dist/host/launch/mappings.js +11 -1
- package/dist/host/launch/project-scan.js +2 -21
- package/dist/host/launch/stage.js +4 -0
- package/dist/host/life/session-ledger.js +2 -1
- package/dist/host/remote/access-store.d.ts +156 -0
- package/dist/host/remote/access-store.js +308 -0
- package/dist/host/remote/cert.d.ts +20 -0
- package/dist/host/remote/cert.js +103 -0
- package/dist/host/remote/door-client.d.ts +13 -0
- package/dist/host/remote/door-client.js +54 -0
- package/dist/host/remote/firewall.d.ts +44 -0
- package/dist/host/remote/firewall.js +118 -0
- package/dist/host/remote/gate.d.ts +125 -0
- package/dist/host/remote/gate.js +391 -0
- package/dist/host/remote/index.d.ts +8 -0
- package/dist/host/remote/index.js +10 -0
- package/dist/host/remote/lan.d.ts +24 -0
- package/dist/host/remote/lan.js +88 -0
- package/dist/host/remote/tls-store.d.ts +22 -0
- package/dist/host/remote/tls-store.js +63 -0
- package/dist/host/remote/windows-helper.d.ts +67 -0
- package/dist/host/remote/windows-helper.js +129 -0
- package/dist/host/sandbox/platform.d.ts +2 -0
- package/dist/host/sandbox/platform.js +19 -4
- package/dist/host/storage/contained/state.d.ts +3 -2
- package/dist/host/storage/contained/state.js +5 -2
- package/dist/host/web/bridge.d.ts +5 -1
- package/dist/host/web/bridge.js +6 -2
- package/dist/host/web/browser.js +1 -1
- package/dist/host/web/control.d.ts +4 -1
- package/dist/host/web/control.js +28 -4
- package/dist/host/web/rpc.d.ts +16 -2
- package/dist/host/web/rpc.js +37 -4
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -0
- package/dist/host/web/server.d.ts +18 -2
- package/dist/host/web/server.js +97 -24
- package/dist/host/web/state.d.ts +5 -0
- package/dist/host/web/state.js +8 -0
- package/dist/runtime/agent.js +74 -3
- package/dist/runtime/daemon.js +205 -24
- package/dist/runtime/db.js +74 -3
- package/dist/runtime/gitguard.js +6 -0
- package/dist/runtime/main.js +77 -3
- package/dist/runtime/netproxy.js +74 -3
- package/dist/runtime/view.js +76 -3
- package/dist/selftest/app.test.js +41 -6
- package/dist/selftest/channel.test.js +16 -0
- package/dist/selftest/cmdline.test.js +16 -0
- package/dist/selftest/git-access.test.js +8 -0
- package/dist/selftest/hostile-input.test.js +12 -1
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/layout.test.js +10 -1
- package/dist/selftest/live-daemon.test.js +25 -0
- package/dist/selftest/local-config.test.js +30 -0
- package/dist/selftest/menu-perf.test.js +198 -12
- package/dist/selftest/menu.test.js +4 -0
- package/dist/selftest/remote.test.d.ts +2 -0
- package/dist/selftest/remote.test.js +536 -0
- package/dist/selftest/repo-guard.test.js +56 -2
- package/dist/selftest/resume.test.js +2 -1
- package/dist/selftest/sharing.test.js +9 -2
- package/dist/selftest/support/fixtures.d.ts +13 -0
- package/dist/selftest/support/web-preview.js +63 -0
- package/dist/selftest/web.test.js +2 -0
- package/dist/shared/channel/schema.d.ts +23 -0
- package/dist/shared/channel/schema.js +8 -0
- package/dist/shared/pty/protocol.d.ts +2 -0
- package/dist/shared/pty/protocol.js +2 -0
- package/dist/web/index.html +1 -1
- package/dist/web/main-NBQ3LF4E.js +221 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +17 -1
- package/native/csharp/HostTools/WebHelper.cs +499 -0
- package/native/scripts/get-network-profile.ps1 +19 -0
- package/native/scripts/set-folder-access.ps1 +11 -0
- package/native/scripts/set-web-firewall.ps1 +103 -0
- package/package.json +1 -1
- package/sandbox/csharp/PtyHost.cs +20 -0
- package/schemas/config.schema.json +65 -0
- package/schemas/sandbox-config.schema.json +0 -18
- 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
|
+
});
|
|
@@ -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
|
|
107
|
-
input: z.object({
|
|
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: {
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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(
|
|
83
|
+
if (service.hasRunningSessions(agent) && !noRestart) {
|
|
83
84
|
const restart = await io.confirm({
|
|
84
|
-
title: 'Restart the running ' +
|
|
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(
|
|
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
|
|
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
|
-
|
|
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. */
|
|
@@ -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";
|