windows-development-sandbox 1.18.4 → 1.20.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/README.md +1 -1
- package/config.example.json +9 -0
- package/dist/app/features/accounts/accounts.def.d.ts +4 -0
- package/dist/app/features/accounts/accounts.run.d.ts +1 -0
- package/dist/app/features/accounts/services.def.d.ts +3 -0
- package/dist/app/features/accounts/services.def.js +4 -2
- package/dist/app/features/accounts/services.run.d.ts +1 -0
- package/dist/app/features/accounts/services.run.js +3 -1
- package/dist/app/features/agent-commands/agent-commands.def.d.ts +37 -0
- package/dist/app/features/agent-commands/agent-commands.def.js +91 -0
- package/dist/app/features/agent-commands/agent-commands.run.d.ts +28 -0
- package/dist/app/features/agent-commands/agent-commands.run.js +35 -0
- package/dist/app/features/agent-commands/index.d.ts +2 -0
- package/dist/app/features/agent-commands/index.js +3 -0
- package/dist/app/features/agents/agents.def.d.ts +14 -1
- package/dist/app/features/agents/agents.def.js +61 -6
- package/dist/app/features/agents/agents.run.d.ts +1 -0
- package/dist/app/features/agents/agents.run.js +8 -1
- package/dist/app/features/agents/claude-env.def.d.ts +36 -0
- package/dist/app/features/agents/claude-env.def.js +305 -0
- package/dist/app/features/agents/env.def.d.ts +163 -0
- package/dist/app/features/agents/env.def.js +184 -0
- package/dist/app/features/agents/env.run.d.ts +43 -0
- package/dist/app/features/agents/env.run.js +86 -0
- package/dist/app/features/agents/index.d.ts +2 -0
- package/dist/app/features/agents/index.js +2 -0
- package/dist/app/features/defs.d.ts +132 -1
- package/dist/app/features/defs.js +9 -0
- package/dist/app/features/settings/categories.def.js +5 -2
- package/dist/app/features/settings/settings-rows.js +5 -1
- package/dist/app/features/settings/settings.run.d.ts +8 -0
- package/dist/app/features/settings/settings.run.js +9 -0
- package/dist/app/features/updates/updates.run.js +12 -2
- package/dist/app/features/vpn/vpn.def.d.ts +33 -0
- package/dist/app/features/vpn/vpn.def.js +30 -6
- package/dist/app/features/vpn/vpn.run.d.ts +11 -0
- package/dist/app/features/vpn/vpn.run.js +4 -1
- package/dist/app/kernel/rpc.d.ts +1 -1
- package/dist/app/registry.js +7 -1
- package/dist/bin/agent-sandbox.js +2 -2
- package/dist/bin/{chunk-MY7NLQQY.js → chunk-2IMT7ZCT.js} +1 -1
- package/dist/bin/{chunk-N4GXYTLV.js → chunk-DK4NTBUF.js} +69 -26
- package/dist/bin/{chunk-FRPLQLSY.js → chunk-Z2P5OGKL.js} +4323 -3463
- 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/agent-commands.d.ts +0 -1
- package/dist/cli/commands/agent-commands.js +2 -32
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/launch.js +2 -2
- package/dist/cli/commands/registry.js +3 -2
- package/dist/cli/manifest.d.ts +1 -1
- package/dist/cli/manifest.js +1 -1
- package/dist/cli/menu/menu.d.ts +1 -1
- package/dist/cli/menu/menu.js +3 -3
- package/dist/cli/menu/pages/agents-page.d.ts +7 -2
- package/dist/cli/menu/pages/agents-page.js +67 -11
- package/dist/cli/menu/pages/maintenance-page.js +1 -2
- package/dist/cli/menu/pages/settings-page.js +1 -0
- package/dist/cli/menu/views.js +2 -1
- package/dist/cli/services/agent-commands-service.d.ts +2 -0
- package/dist/cli/services/agent-commands-service.js +13 -7
- package/dist/cli/services/vpn-service.d.ts +5 -1
- package/dist/cli/services/vpn-service.js +6 -1
- package/dist/cli/tui/dialogs/text-screen.js +2 -1
- package/dist/cli/tui/terminal.js +3 -1
- package/dist/core/config/defaults.js +9 -0
- package/dist/core/detect/toolchains.js +9 -0
- package/dist/core/disk.d.ts +1 -5
- package/dist/core/disk.js +1 -16
- package/dist/core/schema/codex.d.ts +29 -0
- package/dist/core/schema/codex.js +24 -0
- package/dist/core/schema/config.d.ts +46 -14
- package/dist/core/schema/config.js +2 -0
- package/dist/core/schema/index.d.ts +1 -0
- package/dist/core/schema/index.js +1 -0
- package/dist/core/schema/toolchains.d.ts +4 -0
- package/dist/core/schema/toolchains.js +3 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/guest/accounts/apply.d.ts +6 -6
- package/dist/guest/agents/agent-files.d.ts +26 -6
- package/dist/guest/agents/agent-files.js +84 -14
- package/dist/guest/agents/local-state.d.ts +5 -2
- package/dist/guest/agents/local-state.js +24 -10
- package/dist/guest/boot/boot.js +10 -5
- package/dist/guest/daemon/sessions.js +2 -1
- package/dist/guest/toolchains/installers.d.ts +6 -10
- package/dist/guest/toolchains/installers.js +4 -12
- package/dist/guest/toolchains/native/autosdk.d.ts +3 -0
- package/dist/guest/toolchains/native/autosdk.js +50 -0
- package/dist/guest/toolchains/native/unreal.js +3 -0
- package/dist/guest/toolchains/native/vcruntime.d.ts +0 -3
- package/dist/guest/toolchains/native/vcruntime.js +2 -5
- package/dist/guest/toolchains/native/visual-studio.d.ts +2 -2
- package/dist/guest/toolchains/native/visual-studio.js +100 -16
- package/dist/guest/toolchains/native/vs-request.d.ts +21 -0
- package/dist/guest/toolchains/native/vs-request.js +60 -1
- package/dist/guest/toolchains/not-yet.d.ts +1 -1
- package/dist/guest/toolchains/not-yet.js +3 -3
- package/dist/guest/toolchains/persisted.js +2 -7
- package/dist/guest/toolchains/plan.js +9 -4
- package/dist/guest/toolchains/signature.d.ts +5 -0
- package/dist/guest/toolchains/signature.js +22 -0
- package/dist/guest/vpn/tunnel.d.ts +3 -0
- package/dist/guest/vpn/tunnel.js +10 -12
- package/dist/guest/vpn/vpn.js +6 -1
- package/dist/host/accounts/leases.d.ts +3 -3
- package/dist/host/accounts/source.js +1 -1
- package/dist/host/agent-commands/commands.js +1 -1
- package/dist/host/agent-commands/forwarders.d.ts +14 -2
- package/dist/host/agent-commands/forwarders.js +31 -13
- package/dist/host/agent-commands/reconcile.d.ts +2 -1
- package/dist/host/agent-commands/reconcile.js +7 -8
- package/dist/host/agent-commands/user-path.d.ts +5 -0
- package/dist/host/agent-commands/user-path.js +13 -0
- package/dist/host/launch/session-file.js +1 -0
- package/dist/host/profile/accounts.js +2 -4
- package/dist/host/profile/claude-login.d.ts +3 -2
- package/dist/host/profile/claude-login.js +3 -13
- package/dist/host/vpn/index.d.ts +2 -1
- package/dist/host/vpn/index.js +2 -1
- package/dist/host/vpn/last.d.ts +28 -0
- package/dist/host/vpn/last.js +43 -0
- package/dist/host/vpn/login.d.ts +3 -1
- package/dist/host/vpn/login.js +17 -3
- package/dist/runtime/agent.js +28 -0
- package/dist/runtime/daemon.js +1117 -912
- package/dist/runtime/db.js +30 -0
- package/dist/runtime/main.js +1308 -1036
- package/dist/runtime/netproxy.js +22 -0
- package/dist/runtime/tool.js +238 -208
- package/dist/runtime/view.js +22 -0
- package/dist/selftest/agent-commands.test.js +45 -7
- package/dist/selftest/agent-paths.test.js +1 -12
- package/dist/selftest/agent-settings.test.d.ts +2 -0
- package/dist/selftest/agent-settings.test.js +94 -0
- package/dist/selftest/app.test.js +2 -1
- package/dist/selftest/cli.test.js +4 -0
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/menu.test.js +5 -3
- package/dist/selftest/pc-installs.test.js +5 -0
- package/dist/selftest/persisted-installs.test.js +69 -0
- package/dist/selftest/service-accounts.test.js +1 -1
- package/dist/selftest/support/engine-golden.js +1 -1
- package/dist/selftest/support/fixtures.d.ts +9 -0
- package/dist/selftest/vpn.test.js +51 -3
- package/dist/shared/accounts/anthropic.d.ts +5 -0
- package/dist/shared/accounts/anthropic.js +15 -0
- package/dist/shared/accounts/index.d.ts +1 -0
- package/dist/shared/accounts/index.js +1 -0
- package/dist/shared/channel/schema.d.ts +19 -0
- package/dist/shared/channel/schema.js +2 -0
- package/dist/shared/io/disk.d.ts +9 -0
- package/dist/shared/io/disk.js +19 -0
- package/dist/shared/io/index.d.ts +1 -0
- package/dist/shared/io/index.js +1 -0
- package/dist/shared/readiness.d.ts +9 -0
- package/dist/shared/readiness.js +11 -0
- package/dist/shared/signer.d.ts +24 -0
- package/dist/shared/signer.js +15 -0
- package/dist/shared/vpn/failure.d.ts +10 -0
- package/dist/shared/vpn/failure.js +28 -0
- package/dist/sync/watcher.js +2 -0
- package/dist/web/index.html +1 -1
- package/dist/web/{main-GVZWWP4I.js → main-OUUQYNK4.js} +75 -74
- package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +14 -1
- package/native/csharp/HostTools/UserPath.cs +17 -0
- package/native/csharp/StorageHelper/AssemblyInfo.cs +3 -3
- package/native/scripts/edit-user-path.ps1 +6 -2
- package/package.json +1 -1
- package/sandbox/scripts/get-signature.ps1 +13 -0
- package/schemas/config.schema.json +64 -0
- package/schemas/sandbox-config.schema.json +8 -0
- package/sandbox/scripts/get-signer.ps1 +0 -8
package/dist/bin/claude-host.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-host.ts
|
|
9
9
|
var args = process.argv.slice(2);
|
package/dist/bin/claude-sbx.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/claude-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "claude" });
|
package/dist/bin/codex-sbx.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/codex-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "codex" });
|
package/dist/bin/gemini-sbx.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/gemini-sbx.ts
|
|
9
9
|
run(process.argv.slice(2), { harness: "gemini" });
|
package/dist/bin/sandbox.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sandbox.ts
|
|
9
9
|
run(process.argv.slice(2));
|
package/dist/bin/sbx-hide.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-hide.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "hide" });
|
package/dist/bin/sbx-show.js
CHANGED
|
@@ -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-DK4NTBUF.js";
|
|
6
|
+
import "./chunk-Z2P5OGKL.js";
|
|
7
7
|
|
|
8
8
|
// src/bin/sbx-show.ts
|
|
9
9
|
run(process.argv.slice(2), { command: "show" });
|
|
@@ -3,4 +3,3 @@ import type { Reconciled } from '../../host/agent-commands/index.js';
|
|
|
3
3
|
import { type Context } from './context.js';
|
|
4
4
|
/** Brings this PC in line with agentCommands and says what changed (used after on/off, settings and launch). */
|
|
5
5
|
export declare function syncAgentCommands(ctx: Context, config: Config, quiet?: boolean): Reconciled | null;
|
|
6
|
-
export declare function agentCommandsCommand(ctx: Context): number;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { c, table } from '../output/index.js';
|
|
1
|
+
import { c } from '../output/index.js';
|
|
3
2
|
import { AgentCommandsService } from '../services/index.js';
|
|
4
3
|
/** Brings this PC in line with agentCommands and says what changed (used after on/off, settings and launch). */
|
|
5
4
|
export function syncAgentCommands(ctx, config, quiet = false) {
|
|
@@ -7,39 +6,10 @@ export function syncAgentCommands(ctx, config, quiet = false) {
|
|
|
7
6
|
if (!result || !result.changed || quiet)
|
|
8
7
|
return result;
|
|
9
8
|
if (result.on) {
|
|
10
|
-
console.log('Agent commands
|
|
11
|
-
(result.commands.map((a) => a.command).join(', ') || 'no installed agents found'));
|
|
9
|
+
console.log('Agent commands are on for: ' + (result.commands.map((a) => a.command).join(', ') || 'no installed agents found'));
|
|
12
10
|
console.log(c.dim('Open a new terminal, then type e.g. claude in any project folder. Run the real one: set SANDBOX_AGENT_DIRECT=1'));
|
|
13
11
|
}
|
|
14
12
|
else
|
|
15
13
|
console.log('Agent commands are off: claude, codex ... run on this PC again (open a new terminal).');
|
|
16
14
|
return result;
|
|
17
15
|
}
|
|
18
|
-
export function agentCommandsCommand(ctx) {
|
|
19
|
-
const service = new AgentCommandsService(ctx);
|
|
20
|
-
service.assertOnPc();
|
|
21
|
-
const action = ctx.options.positionals[0] ?? 'status';
|
|
22
|
-
if (action === 'status') {
|
|
23
|
-
const { enabled, dir, found } = service.status();
|
|
24
|
-
console.log('Agent commands (Beta): ' + (enabled ? c.green('on') : 'off') + c.dim(' (' + dir + ')'));
|
|
25
|
-
if (found.length)
|
|
26
|
-
table(found.map((a) => [a.command, 'sandboxed ' + a.harness + (enabled ? '' : ' when on'), c.dim('real: ' + a.real)]));
|
|
27
|
-
else
|
|
28
|
-
console.log(c.dim('No agents found on this PC (claude, codex, gemini ... on your PATH).'));
|
|
29
|
-
if (!enabled)
|
|
30
|
-
console.log(c.dim('Turn on with: sandbox agent-commands on'));
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
if (action !== 'on' && action !== 'off')
|
|
34
|
-
fail('Unknown action "' + action + '".', 'Use: sandbox agent-commands [status|on|off]');
|
|
35
|
-
const result = service.setEnabled(action === 'on');
|
|
36
|
-
if (result?.on) {
|
|
37
|
-
console.log('Agent commands (Beta) are on: ' +
|
|
38
|
-
(result.commands.map((a) => a.command).join(', ') || 'no installed agents found yet'));
|
|
39
|
-
console.log(c.dim('Open a new terminal, then type e.g. claude in a project folder: it starts in a hidden sandbox and attaches.'));
|
|
40
|
-
console.log(c.dim('Run the real one on this PC: set SANDBOX_AGENT_DIRECT=1 (PowerShell: $env:SANDBOX_AGENT_DIRECT=1). Turn off: sandbox agent-commands off'));
|
|
41
|
-
}
|
|
42
|
-
else
|
|
43
|
-
console.log('Agent commands are off: claude, codex ... run on this PC again. Open a new terminal.');
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
@@ -7,5 +7,5 @@ export { contextOrDefaults } from './context.js';
|
|
|
7
7
|
export { attach, db, exec } from './sessions/index.js';
|
|
8
8
|
export { resume } from './resume.js';
|
|
9
9
|
export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
|
|
10
|
-
export {
|
|
10
|
+
export { syncAgentCommands } from './agent-commands.js';
|
|
11
11
|
export { HANDLERS, type Handler } from './registry.js';
|
|
@@ -7,5 +7,5 @@ export { contextOrDefaults } from './context.js';
|
|
|
7
7
|
export { attach, db, exec } from './sessions/index.js';
|
|
8
8
|
export { resume } from './resume.js';
|
|
9
9
|
export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
|
|
10
|
-
export {
|
|
10
|
+
export { syncAgentCommands } from './agent-commands.js';
|
|
11
11
|
export { HANDLERS } from './registry.js';
|
|
@@ -74,13 +74,13 @@ class Launcher {
|
|
|
74
74
|
return this.launchSessions();
|
|
75
75
|
return this.launchHere();
|
|
76
76
|
}
|
|
77
|
-
/** agentCommands
|
|
77
|
+
/** agentCommands follows the config: a setting changed in the file takes effect here too. Never blocks. */
|
|
78
78
|
syncAgentCommands() {
|
|
79
79
|
try {
|
|
80
80
|
syncAgentCommands(this.ctx, this.ctx.loaded.config);
|
|
81
81
|
}
|
|
82
82
|
catch (e) {
|
|
83
|
-
console.warn('Agent commands
|
|
83
|
+
console.warn('Agent commands: ' + errMsg(e));
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
@@ -3,6 +3,7 @@ import { launch } from './launch/index.js';
|
|
|
3
3
|
import { setup } from './setup/index.js';
|
|
4
4
|
import { cleanData, showData } from '../../app/features/data/index.js';
|
|
5
5
|
import { attach, db, exec } from './sessions/index.js';
|
|
6
|
+
import { agentCommandsStatus } from '../../app/features/agent-commands/index.js';
|
|
6
7
|
import { listAccounts } from '../../app/features/accounts/index.js';
|
|
7
8
|
import { containedStatus, showStorage } from '../../app/features/storage/index.js';
|
|
8
9
|
import { listProjects } from '../../app/features/projects/index.js';
|
|
@@ -11,7 +12,6 @@ import { fail } from '../../core/util/index.js';
|
|
|
11
12
|
import { claudeHost, config, doctor, hostCommand, logs, sync, watcher } from './maintenance/index.js';
|
|
12
13
|
import { engine } from './engine.js';
|
|
13
14
|
import { resume } from './resume.js';
|
|
14
|
-
import { agentCommandsCommand } from './agent-commands.js';
|
|
15
15
|
import { vpn } from './vpn.js';
|
|
16
16
|
import { github } from './github.js';
|
|
17
17
|
import { web, webServer } from './web.js';
|
|
@@ -21,7 +21,6 @@ export const HANDLERS = {
|
|
|
21
21
|
generate: (ctx) => launch(ctx, true),
|
|
22
22
|
attach: attach,
|
|
23
23
|
exec: exec,
|
|
24
|
-
'agent-commands': agentCommandsCommand,
|
|
25
24
|
db: db,
|
|
26
25
|
resume: resume,
|
|
27
26
|
// The bare command lists; its actions (save, use ...) are the operations' hints.
|
|
@@ -52,6 +51,8 @@ export const HANDLERS = {
|
|
|
52
51
|
'host-claude': claudeHost,
|
|
53
52
|
host: hostCommand,
|
|
54
53
|
_watch: watcher,
|
|
54
|
+
// The bare command shows the status; on and off are the operations' hints (src/app/features/agent-commands).
|
|
55
|
+
'agent-commands': definitionHandler(agentCommandsStatus),
|
|
55
56
|
vpn: vpn,
|
|
56
57
|
github: github,
|
|
57
58
|
web: web,
|
package/dist/cli/manifest.d.ts
CHANGED
|
@@ -702,7 +702,7 @@ declare const COMMAND_LIST: readonly [{
|
|
|
702
702
|
readonly examples: readonly ["sandbox config set sandbox.memoryMb 8192", "sandbox config get sandbox.memoryMb", "sandbox config reset sandbox.memoryMb", "sandbox config list", "sandbox config export team-settings.json", "sandbox config import team-settings.json"];
|
|
703
703
|
}, {
|
|
704
704
|
readonly name: "agent-commands";
|
|
705
|
-
readonly summary: "
|
|
705
|
+
readonly summary: "make claude, codex ... on this PC start in a hidden sandbox and attach";
|
|
706
706
|
readonly group: "Advanced";
|
|
707
707
|
readonly args: readonly [{
|
|
708
708
|
readonly name: "action";
|
package/dist/cli/manifest.js
CHANGED
|
@@ -491,7 +491,7 @@ const COMMAND_LIST = [
|
|
|
491
491
|
},
|
|
492
492
|
{
|
|
493
493
|
name: 'agent-commands',
|
|
494
|
-
summary: '
|
|
494
|
+
summary: 'make claude, codex ... on this PC start in a hidden sandbox and attach',
|
|
495
495
|
group: 'Advanced',
|
|
496
496
|
args: [{ name: 'action', description: 'on, off or status', required: false, choices: ['status', 'on', 'off'] }],
|
|
497
497
|
options: [],
|
package/dist/cli/menu/menu.d.ts
CHANGED
|
@@ -23,6 +23,6 @@ export declare class Menu {
|
|
|
23
23
|
private execute;
|
|
24
24
|
/** Shows the end of a log on the normal screen. */
|
|
25
25
|
private view;
|
|
26
|
-
/** After a save: agent commands
|
|
26
|
+
/** After a save: agent commands may have been switched, which changes this PC. */
|
|
27
27
|
private applyAgentCommands;
|
|
28
28
|
}
|
package/dist/cli/menu/menu.js
CHANGED
|
@@ -168,7 +168,7 @@ export class Menu {
|
|
|
168
168
|
await pressAnyKey(Theme.muted('Press any key for the menu…'));
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
|
-
/** After a save: agent commands
|
|
171
|
+
/** After a save: agent commands may have been switched, which changes this PC. */
|
|
172
172
|
applyAgentCommands(saved) {
|
|
173
173
|
if (!saved.files.some((f) => !f.isProject))
|
|
174
174
|
return undefined;
|
|
@@ -177,11 +177,11 @@ export class Menu {
|
|
|
177
177
|
if (!result?.changed)
|
|
178
178
|
return undefined;
|
|
179
179
|
return result.on
|
|
180
|
-
? 'Agent commands
|
|
180
|
+
? 'Agent commands are on: open a new terminal.'
|
|
181
181
|
: 'Agent commands are off: claude, codex ... run on this PC again (open a new terminal).';
|
|
182
182
|
}
|
|
183
183
|
catch (e) {
|
|
184
|
-
return 'Agent commands
|
|
184
|
+
return 'Agent commands: ' + errMsg(e);
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AgentCommandsStatus as AgentCommandsFacts } from '../../../app/features/agent-commands/index.js';
|
|
2
|
+
import { type AgentEnv, type AgentsList } from '../../../app/features/agents/index.js';
|
|
2
3
|
import type { ConfigFile } from '../../../app/features/settings/index.js';
|
|
3
4
|
import type { Context } from '../../commands/context.js';
|
|
4
5
|
import { type App, type Category, type ListOptions, type ListResult } from '../../tui/index.js';
|
|
@@ -17,8 +18,12 @@ export interface AgentsModel {
|
|
|
17
18
|
readonly window: WindowChoice;
|
|
18
19
|
/** Agents that can be run on this PC without the sandbox (see hostAgentsToShow). */
|
|
19
20
|
readonly hostAgents: readonly string[];
|
|
21
|
+
/** Whether agent commands are on and which agents were found (the "On this PC" category). */
|
|
22
|
+
readonly agentCommands?: AgentCommandsFacts;
|
|
20
23
|
/** The agents you added yourself: only these can be removed (the built-in ones stay). */
|
|
21
24
|
readonly removable?: readonly string[];
|
|
25
|
+
/** Claude's environment variables (the Claude environment tab); missing when Claude is not an agent here. */
|
|
26
|
+
readonly claudeEnv?: AgentEnv;
|
|
22
27
|
}
|
|
23
28
|
/** The agents page's data as the agents view takes it. Pure. */
|
|
24
29
|
export declare function agentsList(m: AgentsModel): AgentsList;
|
|
@@ -34,7 +39,7 @@ export declare function startArgv(m: AgentsModel, agent: string, cwd: string): s
|
|
|
34
39
|
/** Settings has unsaved changes to the agents (their list or the default): the agent operations wait for them. */
|
|
35
40
|
export declare function agentsHaveStagedChanges(file: ConfigFile, draft: Draft): boolean;
|
|
36
41
|
/** The categories of the agents section; "On this PC" only when there is something in it. Pure. */
|
|
37
|
-
export declare function agentCategories(m: Pick<AgentsModel, 'folder' | 'hostAgents'>): Category[];
|
|
42
|
+
export declare function agentCategories(m: Pick<AgentsModel, 'folder' | 'hostAgents' | 'claudeEnv'>): Category[];
|
|
38
43
|
/** The list for the agents section. Pure. */
|
|
39
44
|
export declare function agentsOptions(m: AgentsModel, cwd?: string): ListOptions<string>;
|
|
40
45
|
export declare class AgentsPage extends ListPage<string> {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// are on.
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
-
import { agentsPage, listAgents } from '../../../app/features/agents/index.js';
|
|
7
|
+
import { agentEnv, agentEnvPage, agentsPage, listAgents, } from '../../../app/features/agents/index.js';
|
|
8
8
|
import { readQuery } from '../../../app/registry.js';
|
|
9
9
|
import { commandLine, readHistory } from '../../history.js';
|
|
10
10
|
import { AgentCommandsService } from '../../services/index.js';
|
|
@@ -16,6 +16,10 @@ import { menuView } from '../render-view.js';
|
|
|
16
16
|
import { askPath } from '../settings/ask-path.js';
|
|
17
17
|
import { SeveralAgents } from '../several.js';
|
|
18
18
|
import { ListPage } from './list-page.js';
|
|
19
|
+
/** What the agent commands section shows (before the status is read: off, nothing found). Pure. */
|
|
20
|
+
function commandsOf(m) {
|
|
21
|
+
return m.agentCommands ?? { enabled: m.hostAgents.length > 0, dir: '', found: [] };
|
|
22
|
+
}
|
|
19
23
|
/** The agents page's data as the agents view takes it. Pure. */
|
|
20
24
|
export function agentsList(m) {
|
|
21
25
|
const removable = m.removable ?? [];
|
|
@@ -32,7 +36,13 @@ export function agentsList(m) {
|
|
|
32
36
|
}
|
|
33
37
|
/** The Start category: the agents view's rows and keys, as the menu draws them. Pure. */
|
|
34
38
|
function startView(m) {
|
|
35
|
-
|
|
39
|
+
const page = agentsPage(agentsList(m), commandsOf(m));
|
|
40
|
+
return menuView({ ...page, sections: page.sections.slice(0, 1) }, { category: 'start', refresh: false });
|
|
41
|
+
}
|
|
42
|
+
/** The On this PC category: the agent commands switch and the agents it covers (the view's second section). Pure. */
|
|
43
|
+
function commandsView(m) {
|
|
44
|
+
const page = agentsPage(agentsList(m), commandsOf(m));
|
|
45
|
+
return menuView({ ...page, sections: page.sections.slice(1) }, { category: 'host', refresh: false });
|
|
36
46
|
}
|
|
37
47
|
/**
|
|
38
48
|
* The "not sandboxed" entries: only while agent commands are on (typing the agent then starts the sandbox, so a way to
|
|
@@ -65,16 +75,21 @@ export function agentCategories(m) {
|
|
|
65
75
|
label: 'Start',
|
|
66
76
|
description: 'Agents you can start in ' + m.folder + '. Add an agent at the end of the list.',
|
|
67
77
|
},
|
|
68
|
-
|
|
69
|
-
...(m.hostAgents.length
|
|
78
|
+
...(m.claudeEnv
|
|
70
79
|
? [
|
|
71
80
|
{
|
|
72
|
-
id: '
|
|
73
|
-
label: '
|
|
74
|
-
description: '
|
|
81
|
+
id: 'env',
|
|
82
|
+
label: 'Claude environment',
|
|
83
|
+
description: 'Models, limits, how many subagents run at once, and other variables of Claude.',
|
|
75
84
|
},
|
|
76
85
|
]
|
|
77
86
|
: []),
|
|
87
|
+
{ id: 'options', label: 'Options', description: 'How a start goes, and the other ways to start.' },
|
|
88
|
+
{
|
|
89
|
+
id: 'host',
|
|
90
|
+
label: 'On this PC',
|
|
91
|
+
description: 'Agent commands: typing claude, codex ... here starts them in a sandbox. The real agents are listed too.',
|
|
92
|
+
},
|
|
78
93
|
];
|
|
79
94
|
}
|
|
80
95
|
/** A Start row of the view with the menu's own lines: the default's accent and the command a start runs. Pure. */
|
|
@@ -88,9 +103,15 @@ function startRow(item, m, cwd) {
|
|
|
88
103
|
details: [Theme.muted('Command ') + commandLine(startArgv(m, name, cwd))],
|
|
89
104
|
};
|
|
90
105
|
}
|
|
106
|
+
/** The Claude environment tab: the environment view's rows and keys, as the menu draws them. Pure. */
|
|
107
|
+
function envView(m) {
|
|
108
|
+
return m.claudeEnv ? menuView(agentEnvPage(m.claudeEnv), { category: 'env', refresh: false }) : undefined;
|
|
109
|
+
}
|
|
91
110
|
/** The list for the agents section. Pure. */
|
|
92
111
|
export function agentsOptions(m, cwd = process.cwd()) {
|
|
93
112
|
const view = startView(m);
|
|
113
|
+
const env = envView(m);
|
|
114
|
+
const commands = commandsView(m);
|
|
94
115
|
return {
|
|
95
116
|
path: [],
|
|
96
117
|
categories: agentCategories(m),
|
|
@@ -108,6 +129,8 @@ export function agentsOptions(m, cwd = process.cwd()) {
|
|
|
108
129
|
]
|
|
109
130
|
: []),
|
|
110
131
|
...view.items.map((item) => startRow(item, m, cwd)),
|
|
132
|
+
...(env?.items ?? []),
|
|
133
|
+
...commands.items,
|
|
111
134
|
{
|
|
112
135
|
value: 'opt:attach',
|
|
113
136
|
label: 'Attach this terminal',
|
|
@@ -161,8 +184,21 @@ export function agentsOptions(m, cwd = process.cwd()) {
|
|
|
161
184
|
description: 'Runs the real ' + agent + ' on this PC, with no sandbox around it.',
|
|
162
185
|
})),
|
|
163
186
|
],
|
|
164
|
-
enterLabel: (
|
|
165
|
-
|
|
187
|
+
enterLabel: (category, id) => ENTER[id ?? ''] ??
|
|
188
|
+
(id?.startsWith('agent:')
|
|
189
|
+
? 'start'
|
|
190
|
+
: id?.startsWith('host:')
|
|
191
|
+
? 'run'
|
|
192
|
+
: category === 'host'
|
|
193
|
+
? commands.enterLabel(category, id)
|
|
194
|
+
: 'open'),
|
|
195
|
+
actions: (category) => category === 'start'
|
|
196
|
+
? view.actions
|
|
197
|
+
: category === 'env'
|
|
198
|
+
? (env?.actions ?? [])
|
|
199
|
+
: category === 'host'
|
|
200
|
+
? commands.actions
|
|
201
|
+
: [],
|
|
166
202
|
};
|
|
167
203
|
}
|
|
168
204
|
/** What Enter does on the rows that are not an agent. */
|
|
@@ -199,7 +235,7 @@ export class AgentsPage extends ListPage {
|
|
|
199
235
|
current() {
|
|
200
236
|
if (!this.facts)
|
|
201
237
|
throw new Error('The agents tab was not loaded');
|
|
202
|
-
const { agents, commands, last } = this.facts;
|
|
238
|
+
const { agents, commands, last, env } = this.facts;
|
|
203
239
|
return {
|
|
204
240
|
folder: this.folder,
|
|
205
241
|
defaultAgent: agents.defaultAgent,
|
|
@@ -208,7 +244,13 @@ export class AgentsPage extends ListPage {
|
|
|
208
244
|
attach: this.attach,
|
|
209
245
|
window: this.window,
|
|
210
246
|
hostAgents: hostAgentsToShow(commands.enabled, commands.found),
|
|
247
|
+
agentCommands: {
|
|
248
|
+
enabled: commands.enabled,
|
|
249
|
+
dir: commands.dir,
|
|
250
|
+
found: commands.found.map((a) => ({ command: a.command, harness: a.harness, real: a.real })),
|
|
251
|
+
},
|
|
211
252
|
removable: agents.agents.filter((a) => a.removable).map((a) => a.name),
|
|
253
|
+
...(env ? { claudeEnv: env } : {}),
|
|
212
254
|
};
|
|
213
255
|
}
|
|
214
256
|
/** The cursor starts on the default agent. */
|
|
@@ -220,6 +262,9 @@ export class AgentsPage extends ListPage {
|
|
|
220
262
|
agents: await readQuery(listAgents, this.ctx),
|
|
221
263
|
commands: await new AgentCommandsService(this.ctx).statusAsync(),
|
|
222
264
|
last: readHistory()[0]?.argv,
|
|
265
|
+
env: 'claude' in this.ctx.loaded.config.harnesses
|
|
266
|
+
? await readQuery(agentEnv, this.ctx, { agent: 'claude' })
|
|
267
|
+
: undefined,
|
|
223
268
|
};
|
|
224
269
|
this.model = this.current();
|
|
225
270
|
}
|
|
@@ -229,9 +274,20 @@ export class AgentsPage extends ListPage {
|
|
|
229
274
|
}
|
|
230
275
|
async act(result) {
|
|
231
276
|
const model = this.current();
|
|
232
|
-
const
|
|
277
|
+
const env = this.category === 'env' ? envView(model) : undefined;
|
|
278
|
+
if (env) {
|
|
279
|
+
const picked = env.resolve(result);
|
|
280
|
+
if (picked?.kind === 'action')
|
|
281
|
+
return this.operate(picked.action);
|
|
282
|
+
return {};
|
|
283
|
+
}
|
|
284
|
+
const chosen = startView(model).resolve(result) ?? commandsView(model).resolve(result);
|
|
233
285
|
if (chosen?.kind === 'action') {
|
|
234
286
|
const { action } = chosen;
|
|
287
|
+
if (action.kind === 'link' && action.target.kind === 'view') {
|
|
288
|
+
await this.selectCategory('env');
|
|
289
|
+
return {};
|
|
290
|
+
}
|
|
235
291
|
// A start keeps the options of this page (attach, window, folder), which the plain link does not know.
|
|
236
292
|
if (action.kind === 'link' && action.target.kind === 'start-agent')
|
|
237
293
|
return { exit: { kind: 'run', argv: startArgv(model, action.target.agent, process.cwd()) } };
|
|
@@ -51,7 +51,7 @@ const CATEGORIES = [
|
|
|
51
51
|
},
|
|
52
52
|
{ id: 'more', label: 'More commands', description: 'Less common commands.' },
|
|
53
53
|
];
|
|
54
|
-
const MORE_COMMANDS = ['sync', 'config', 'generate', 'exec'
|
|
54
|
+
const MORE_COMMANDS = ['sync', 'config', 'generate', 'exec'];
|
|
55
55
|
const NO_LOGS = { folder: '', files: [], crash: false };
|
|
56
56
|
/** Until the status is read: the server counts as not running. */
|
|
57
57
|
const NO_WEB = { running: false, port: null, address: null };
|
|
@@ -61,7 +61,6 @@ const MORE_LABELS = {
|
|
|
61
61
|
config: 'Your settings file',
|
|
62
62
|
generate: 'Preview a start',
|
|
63
63
|
exec: 'Run a command in the sandbox',
|
|
64
|
-
'agent-commands': 'Agent commands (Beta)',
|
|
65
64
|
};
|
|
66
65
|
/** The Data & storage category's rows and keys once measured: the data view (src/app/features/data) as menu rows. */
|
|
67
66
|
function dataMenuView(data) {
|
|
@@ -158,6 +158,7 @@ export class SettingsPage extends ListPage {
|
|
|
158
158
|
login: 'none',
|
|
159
159
|
loginSavedAt: null,
|
|
160
160
|
running: null,
|
|
161
|
+
lastFailure: null,
|
|
161
162
|
};
|
|
162
163
|
/** Whether a GitHub token is saved (never the token): the token row needs only its state. */
|
|
163
164
|
github = { shareToken: false, gitAccess: 'full', token: 'none', kind: null, savedAt: null };
|
package/dist/cli/menu/views.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The shared core's views the menu shows, and in which section (the parity self-test reads this list: an operation or
|
|
2
2
|
// query is reachable in the menu when a view here offers it). Settings is drawn by its own page over the same rows,
|
|
3
3
|
// because the menu stages changes until Ctrl+S.
|
|
4
|
-
import { agentsView } from '../../app/features/agents/index.js';
|
|
4
|
+
import { agentEnvView, agentsView } from '../../app/features/agents/index.js';
|
|
5
5
|
import { dataView } from '../../app/features/data/index.js';
|
|
6
6
|
import { accountsView } from '../../app/features/accounts/index.js';
|
|
7
7
|
import { appsView } from '../../app/features/apps/index.js';
|
|
@@ -21,6 +21,7 @@ import { githubView } from '../../app/features/github/index.js';
|
|
|
21
21
|
import { accessView } from '../../app/features/access/index.js';
|
|
22
22
|
export const MENU_VIEWS = [
|
|
23
23
|
{ view: agentsView, section: 'Agents' },
|
|
24
|
+
{ view: agentEnvView, section: 'Agents' },
|
|
24
25
|
{ view: sessionsView, section: 'Sessions' },
|
|
25
26
|
{ view: sandboxView, section: 'Sandbox' },
|
|
26
27
|
{ view: settingsView, section: 'Settings' },
|
|
@@ -14,6 +14,8 @@ export declare class AgentCommandsService {
|
|
|
14
14
|
constructor(ctx: Context);
|
|
15
15
|
/** Agent commands change this PC's PATH, so they are set up from the PC, not inside the sandbox. */
|
|
16
16
|
assertOnPc(): void;
|
|
17
|
+
/** Your settings as they are on disk now (a switch made a moment ago, here or in Settings, counts). */
|
|
18
|
+
private config;
|
|
17
19
|
status(): AgentCommandsStatus;
|
|
18
20
|
/** status() that does not block the program (the menu asks while it stays responsive). */
|
|
19
21
|
statusAsync(): Promise<AgentCommandsStatus>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// "Agent commands"
|
|
1
|
+
// "Agent commands": typing claude, codex ... on this PC starts them in a hidden sandbox. Never prints.
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
-
import path from 'node:path';
|
|
4
3
|
import { loadConfig, userConfigPath } from '../../core/config/index.js';
|
|
5
4
|
import { fail } from '../../core/util/index.js';
|
|
6
|
-
import { agentCommands, agentCommandsAsync, commandsDir, reconcileAgentCommands, } from '../../host/agent-commands/index.js';
|
|
5
|
+
import { agentCommands, agentCommandsAsync, commandsDir, forwardTarget, reconcileAgentCommands, } from '../../host/agent-commands/index.js';
|
|
6
|
+
import { InstallLayout } from '../../host/install/layout.js';
|
|
7
7
|
import { insideSandbox } from '../../host/sandbox/index.js';
|
|
8
8
|
import { writeFileAtomic } from '../../shared/io/index.js';
|
|
9
|
-
import { editConfigText } from '../../app/features/settings/
|
|
9
|
+
import { editConfigText } from '../../app/features/settings/settings-file.js';
|
|
10
10
|
export class AgentCommandsService {
|
|
11
11
|
ctx;
|
|
12
12
|
constructor(ctx) {
|
|
@@ -17,8 +17,12 @@ export class AgentCommandsService {
|
|
|
17
17
|
if (insideSandbox())
|
|
18
18
|
fail("Agent commands change your PC's PATH, so they are set up from your PC, not inside the sandbox.", 'Run sandbox agent-commands on in a terminal on your PC.');
|
|
19
19
|
}
|
|
20
|
+
/** Your settings as they are on disk now (a switch made a moment ago, here or in Settings, counts). */
|
|
21
|
+
config() {
|
|
22
|
+
return loadConfig(this.ctx.loaded.configPath ?? undefined).config;
|
|
23
|
+
}
|
|
20
24
|
status() {
|
|
21
|
-
const
|
|
25
|
+
const config = this.config();
|
|
22
26
|
return {
|
|
23
27
|
enabled: config.agentCommands.enabled,
|
|
24
28
|
dir: commandsDir(this.ctx.storageRoot),
|
|
@@ -27,7 +31,7 @@ export class AgentCommandsService {
|
|
|
27
31
|
}
|
|
28
32
|
/** status() that does not block the program (the menu asks while it stays responsive). */
|
|
29
33
|
async statusAsync() {
|
|
30
|
-
const
|
|
34
|
+
const config = this.config();
|
|
31
35
|
return {
|
|
32
36
|
enabled: config.agentCommands.enabled,
|
|
33
37
|
dir: commandsDir(this.ctx.storageRoot),
|
|
@@ -48,6 +52,8 @@ export class AgentCommandsService {
|
|
|
48
52
|
reconcile(config) {
|
|
49
53
|
if (insideSandbox())
|
|
50
54
|
return null;
|
|
51
|
-
|
|
55
|
+
// Under a managed install the forwarding files call its launcher, which keeps working after an update.
|
|
56
|
+
const installRoot = InstallLayout.detect(this.ctx.packageRoot)?.root ?? null;
|
|
57
|
+
return reconcileAgentCommands(config, this.ctx.storageRoot, forwardTarget(this.ctx.packageRoot, installRoot, process.execPath));
|
|
52
58
|
}
|
|
53
59
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Config } from '../../core/types.js';
|
|
2
2
|
import type { VpnProvider } from '../../core/schema/index.js';
|
|
3
3
|
import type { SecretStore } from '../../host/secrets/index.js';
|
|
4
|
-
import { type LoginState, type VpnCredentials, type VpnLine } from '../../host/vpn/index.js';
|
|
4
|
+
import { type VpnFailureInfo, type LoginState, type VpnCredentials, type VpnLine } from '../../host/vpn/index.js';
|
|
5
5
|
import type { Context } from '../commands/context.js';
|
|
6
6
|
export interface VpnReport {
|
|
7
7
|
readonly enabled: boolean;
|
|
@@ -13,6 +13,8 @@ export interface VpnReport {
|
|
|
13
13
|
readonly loginSavedAt: string | null;
|
|
14
14
|
/** The running sandbox's tunnel, when one runs with the VPN on. */
|
|
15
15
|
readonly running: VpnLine | null;
|
|
16
|
+
/** The last sandbox's VPN attempt, when it failed (kept after it closed). */
|
|
17
|
+
readonly lastFailure: VpnFailureInfo | null;
|
|
16
18
|
}
|
|
17
19
|
export declare class VpnService {
|
|
18
20
|
private readonly ctx;
|
|
@@ -26,5 +28,7 @@ export declare class VpnService {
|
|
|
26
28
|
}): Promise<VpnReport>;
|
|
27
29
|
loginState(): LoginState;
|
|
28
30
|
save(credentials: VpnCredentials): void;
|
|
31
|
+
/** A hint when the login does not look like it belongs to the provider (null when it looks right). */
|
|
32
|
+
warning(credentials: VpnCredentials): string | null;
|
|
29
33
|
remove(): boolean;
|
|
30
34
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isSandboxRunning } from '../../host/sandbox/index.js';
|
|
2
|
-
import { hostPublicIp, readVpnLine, VpnLogin, } from '../../host/vpn/index.js';
|
|
2
|
+
import { hostPublicIp, loginWarning, readLastFailure, readVpnLine, VpnLogin, } from '../../host/vpn/index.js';
|
|
3
3
|
export class VpnService {
|
|
4
4
|
ctx;
|
|
5
5
|
login;
|
|
@@ -25,6 +25,7 @@ export class VpnService {
|
|
|
25
25
|
killSwitch: c.killSwitch,
|
|
26
26
|
login: this.login.state(c.provider),
|
|
27
27
|
loginSavedAt: this.login.savedAt(c.provider),
|
|
28
|
+
lastFailure: readLastFailure(this.ctx.storageRoot),
|
|
28
29
|
running: running ? readVpnLine(this.ctx.dataPath, await hostPublicIp()) : null,
|
|
29
30
|
};
|
|
30
31
|
}
|
|
@@ -34,6 +35,10 @@ export class VpnService {
|
|
|
34
35
|
save(credentials) {
|
|
35
36
|
this.login.save(this.provider, credentials);
|
|
36
37
|
}
|
|
38
|
+
/** A hint when the login does not look like it belongs to the provider (null when it looks right). */
|
|
39
|
+
warning(credentials) {
|
|
40
|
+
return loginWarning(credentials, this.provider);
|
|
41
|
+
}
|
|
37
42
|
remove() {
|
|
38
43
|
return this.login.remove(this.provider);
|
|
39
44
|
}
|
|
@@ -100,7 +100,8 @@ export class TextScreen {
|
|
|
100
100
|
}
|
|
101
101
|
if (key.text) {
|
|
102
102
|
const accept = this.o.accept;
|
|
103
|
-
|
|
103
|
+
// Line breaks and the bracketed-paste markers a terminal wraps around pasted text are not part of the text.
|
|
104
|
+
const add = [...key.text.replace(/\x1b?\[20[01]~/g, '').replace(/[\r\n]/g, '')].filter((c) => !accept || accept.test(c));
|
|
104
105
|
if (!add.length)
|
|
105
106
|
return;
|
|
106
107
|
set([...chars.slice(0, this.cursor), ...add, ...chars.slice(this.cursor)], this.cursor + add.length);
|
package/dist/cli/tui/terminal.js
CHANGED
|
@@ -119,9 +119,11 @@ export class Terminal {
|
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
121
|
push(str, key) {
|
|
122
|
+
// The markers around a paste (readline names them paste-start / paste-end) carry no text.
|
|
123
|
+
const marker = key?.name === 'paste-start' || key?.name === 'paste-end';
|
|
122
124
|
const event = {
|
|
123
125
|
name: key?.name ?? '',
|
|
124
|
-
text: str && !key?.ctrl && !key?.meta && str.length >= 1 && str >= ' ' && str !== '\x7f' ? str : '',
|
|
126
|
+
text: str && !marker && !key?.ctrl && !key?.meta && str.length >= 1 && str >= ' ' && str !== '\x7f' ? str : '',
|
|
125
127
|
ctrl: Boolean(key?.ctrl),
|
|
126
128
|
meta: Boolean(key?.meta),
|
|
127
129
|
shift: Boolean(key?.shift),
|