windows-development-sandbox 1.0.5 → 1.4.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/LICENSE +21 -0
- package/README.md +25 -8
- package/config.example.json +55 -5
- package/dist/api.js +2 -1
- package/dist/cli/args.d.ts +23 -0
- package/dist/cli/args.js +38 -4
- package/dist/cli/colors.d.ts +24 -0
- package/dist/cli/colors.js +42 -0
- package/dist/cli/commands/accounts.js +2 -2
- package/dist/cli/commands/agent-commands.d.ts +6 -0
- package/dist/cli/commands/agent-commands.js +61 -0
- package/dist/cli/commands/context.d.ts +2 -0
- package/dist/cli/commands/context.js +5 -1
- package/dist/cli/commands/data/clean.d.ts +15 -0
- package/dist/cli/commands/data/clean.js +106 -0
- package/dist/cli/commands/data/collect.d.ts +11 -0
- package/dist/cli/commands/data/collect.js +54 -0
- package/dist/cli/commands/data/index.d.ts +4 -0
- package/dist/cli/commands/data/index.js +45 -0
- package/dist/cli/commands/data/remove.d.ts +2 -0
- package/dist/cli/commands/data/remove.js +30 -0
- package/dist/cli/commands/index.d.ts +6 -4
- package/dist/cli/commands/index.js +6 -4
- package/dist/cli/commands/launch.d.ts +26 -2
- package/dist/cli/commands/launch.js +256 -42
- package/dist/cli/commands/maintenance.d.ts +2 -0
- package/dist/cli/commands/maintenance.js +67 -5
- package/dist/cli/commands/project.d.ts +29 -0
- package/dist/cli/commands/project.js +63 -0
- package/dist/cli/commands/projects.d.ts +14 -0
- package/dist/cli/commands/projects.js +146 -0
- package/dist/cli/commands/repair/checks.d.ts +2 -0
- package/dist/cli/commands/{repair.js → repair/checks.js} +19 -181
- package/dist/cli/commands/{repair.d.ts → repair/finders.d.ts} +0 -29
- package/dist/cli/commands/repair/finders.js +108 -0
- package/dist/cli/commands/repair/index.d.ts +12 -0
- package/dist/cli/commands/repair/index.js +61 -0
- package/dist/cli/commands/repair/types.d.ts +26 -0
- package/dist/cli/commands/repair/types.js +3 -0
- package/dist/cli/commands/restart.d.ts +6 -0
- package/dist/cli/commands/restart.js +85 -0
- package/dist/cli/commands/sessions.d.ts +2 -1
- package/dist/cli/commands/sessions.js +189 -45
- package/dist/cli/commands/setup/checks.d.ts +13 -0
- package/dist/cli/commands/setup/checks.js +71 -0
- package/dist/cli/commands/{setup.d.ts → setup/facts.d.ts} +1 -15
- package/dist/cli/commands/setup/facts.js +60 -0
- package/dist/cli/commands/setup/index.d.ts +2 -0
- package/dist/cli/commands/setup/index.js +43 -0
- package/dist/cli/commands/user-config.d.ts +8 -0
- package/dist/cli/commands/user-config.js +41 -0
- package/dist/cli/history.d.ts +11 -0
- package/dist/cli/history.js +21 -0
- package/dist/cli/index.d.ts +7 -1
- package/dist/cli/index.js +42 -15
- package/dist/cli/manifest.d.ts +8 -0
- package/dist/cli/manifest.js +40 -15
- package/dist/cli/menu/apps.d.ts +21 -0
- package/dist/cli/menu/apps.js +122 -0
- package/dist/cli/menu/command-form.d.ts +28 -0
- package/dist/cli/menu/command-form.js +219 -0
- package/dist/cli/menu/index.d.ts +26 -0
- package/dist/cli/menu/index.js +180 -0
- package/dist/cli/menu/settings/categories.d.ts +9 -0
- package/dist/cli/menu/settings/categories.js +28 -0
- package/dist/cli/menu/settings/config-file.d.ts +40 -0
- package/dist/cli/menu/settings/config-file.js +71 -0
- package/dist/cli/menu/settings/editors.d.ts +30 -0
- package/dist/cli/menu/settings/editors.js +305 -0
- package/dist/cli/menu/settings/index.d.ts +32 -0
- package/dist/cli/menu/settings/index.js +136 -0
- package/dist/cli/menu/settings/schema-node.d.ts +62 -0
- package/dist/cli/menu/settings/schema-node.js +104 -0
- package/dist/cli/menu/several.d.ts +20 -0
- package/dist/cli/menu/several.js +102 -0
- package/dist/cli/progress.d.ts +9 -0
- package/dist/cli/progress.js +49 -0
- package/dist/cli/tui/app.d.ts +39 -0
- package/dist/cli/tui/app.js +52 -0
- package/dist/cli/tui/dialogs.d.ts +57 -0
- package/dist/cli/tui/dialogs.js +162 -0
- package/dist/cli/tui/frame.d.ts +18 -0
- package/dist/cli/tui/frame.js +27 -0
- package/dist/cli/tui/index.d.ts +7 -0
- package/dist/cli/tui/index.js +8 -0
- package/dist/cli/tui/list-screen.d.ts +101 -0
- package/dist/cli/tui/list-screen.js +299 -0
- package/dist/cli/tui/terminal.d.ts +37 -0
- package/dist/cli/tui/terminal.js +89 -0
- package/dist/cli/tui/text.d.ts +20 -0
- package/dist/cli/tui/text.js +105 -0
- package/dist/cli/tui/theme.d.ts +45 -0
- package/dist/cli/tui/theme.js +30 -0
- package/dist/cli/validate.d.ts +17 -0
- package/dist/cli/validate.js +89 -0
- package/dist/core/config.js +12 -6
- package/dist/core/disk.d.ts +16 -0
- package/dist/core/disk.js +55 -0
- package/dist/core/local-config.d.ts +23 -0
- package/dist/core/local-config.js +79 -7
- package/dist/core/project-policy.d.ts +15 -0
- package/dist/core/project-policy.js +35 -0
- package/dist/core/prompt.d.ts +4 -0
- package/dist/core/prompt.js +15 -0
- package/dist/core/safe-paths.d.ts +4 -0
- package/dist/core/safe-paths.js +37 -0
- package/dist/core/schema/apps.d.ts +40 -0
- package/dist/core/schema/apps.js +27 -0
- package/dist/core/schema/common.d.ts +17 -0
- package/dist/core/schema/common.js +15 -0
- package/dist/core/schema/config.d.ts +659 -0
- package/dist/core/schema/config.js +75 -0
- package/dist/core/schema/databases.d.ts +33 -0
- package/dist/core/schema/databases.js +35 -0
- package/dist/core/schema/harness.d.ts +12 -0
- package/dist/core/schema/harness.js +17 -0
- package/dist/core/schema/json-schema.d.ts +5 -0
- package/dist/core/schema/json-schema.js +25 -0
- package/dist/core/schema/profile.d.ts +32 -0
- package/dist/core/schema/profile.js +31 -0
- package/dist/core/schema/projects.d.ts +9 -0
- package/dist/core/schema/projects.js +11 -0
- package/dist/core/schema/sandbox.d.ts +78 -0
- package/dist/core/schema/sandbox.js +64 -0
- package/dist/core/schema/toolchains.d.ts +96 -0
- package/dist/core/schema/toolchains.js +88 -0
- package/dist/core/schema.d.ts +6 -604
- package/dist/core/schema.js +8 -264
- package/dist/core/types.d.ts +35 -1
- package/dist/core/util.d.ts +9 -0
- package/dist/core/util.js +14 -3
- package/dist/core/workspace.d.ts +0 -5
- package/dist/core/workspace.js +33 -50
- package/dist/guest/apps/index.d.ts +10 -0
- package/dist/guest/apps/index.js +206 -0
- package/dist/guest/apps/resolvers.d.ts +8 -0
- package/dist/guest/apps/resolvers.js +90 -0
- package/dist/guest/audit-parse.d.ts +7 -0
- package/dist/guest/audit-parse.js +24 -0
- package/dist/guest/audit.d.ts +4 -0
- package/dist/guest/audit.js +47 -0
- package/dist/guest/boot-env.d.ts +4 -0
- package/dist/guest/boot-env.js +25 -0
- package/dist/guest/cmdline.d.ts +12 -0
- package/dist/guest/cmdline.js +23 -0
- package/dist/guest/daemon/exec.d.ts +5 -0
- package/dist/guest/daemon/exec.js +32 -0
- package/dist/guest/daemon/project.d.ts +14 -0
- package/dist/guest/daemon/project.js +132 -0
- package/dist/guest/daemon/relays.d.ts +1 -0
- package/dist/guest/daemon/relays.js +18 -0
- package/dist/guest/daemon/session.d.ts +13 -0
- package/dist/guest/daemon/session.js +139 -0
- package/dist/guest/daemon/shutdown.d.ts +1 -0
- package/dist/guest/daemon/shutdown.js +21 -0
- package/dist/guest/daemon/state.d.ts +17 -0
- package/dist/guest/daemon/state.js +31 -0
- package/dist/guest/daemon.js +12 -141
- package/dist/guest/db.js +18 -3
- package/dist/guest/env.d.ts +3 -0
- package/dist/guest/env.js +7 -3
- package/dist/guest/guide.d.ts +6 -2
- package/dist/guest/guide.js +5 -4
- package/dist/guest/helpers.d.ts +3 -0
- package/dist/guest/helpers.js +26 -0
- package/dist/guest/main.js +31 -8
- package/dist/guest/netproxy.d.ts +1 -0
- package/dist/guest/netproxy.js +100 -0
- package/dist/guest/ports.d.ts +6 -0
- package/dist/guest/ports.js +22 -0
- package/dist/guest/project-context.d.ts +7 -0
- package/dist/guest/project-context.js +10 -0
- package/dist/guest/project-env.d.ts +20 -0
- package/dist/guest/project-env.js +20 -0
- package/dist/guest/project-status.d.ts +5 -0
- package/dist/guest/project-status.js +17 -0
- package/dist/guest/ptyhost.d.ts +0 -18
- package/dist/guest/ptyhost.js +17 -65
- package/dist/guest/setup/agents.d.ts +5 -2
- package/dist/guest/setup/agents.js +22 -8
- package/dist/guest/setup/claude.d.ts +0 -4
- package/dist/guest/setup/claude.js +59 -5
- package/dist/guest/setup/environment.d.ts +13 -3
- package/dist/guest/setup/environment.js +14 -10
- package/dist/guest/setup/hooks.d.ts +9 -1
- package/dist/guest/setup/hooks.js +28 -14
- package/dist/guest/setup/network.d.ts +9 -0
- package/dist/guest/setup/network.js +97 -4
- package/dist/guest/setup/user.js +4 -0
- package/dist/guest/toolchains/catalogue.d.ts +4 -0
- package/dist/guest/toolchains/catalogue.js +2 -2
- package/dist/guest/toolchains/cli.js +25 -17
- package/dist/guest/toolchains/common.d.ts +18 -1
- package/dist/guest/toolchains/common.js +34 -11
- package/dist/guest/toolchains/databases/dynamodb.d.ts +8 -0
- package/dist/guest/toolchains/databases/dynamodb.js +52 -0
- package/dist/guest/toolchains/{databases.d.ts → databases/index.d.ts} +2 -3
- package/dist/guest/toolchains/databases/index.js +62 -0
- package/dist/guest/toolchains/databases/mongodb.d.ts +3 -0
- package/dist/guest/toolchains/databases/mongodb.js +31 -0
- package/dist/guest/toolchains/databases/mysql.d.ts +3 -0
- package/dist/guest/toolchains/databases/mysql.js +38 -0
- package/dist/guest/toolchains/databases/postgres.d.ts +5 -0
- package/dist/guest/toolchains/databases/postgres.js +38 -0
- package/dist/guest/toolchains/databases/redis.d.ts +3 -0
- package/dist/guest/toolchains/databases/redis.js +16 -0
- package/dist/guest/toolchains/databases/server.d.ts +14 -0
- package/dist/guest/toolchains/databases/server.js +52 -0
- package/dist/guest/toolchains/git.js +25 -16
- package/dist/guest/toolchains/go.js +1 -1
- package/dist/guest/toolchains/index.d.ts +13 -9
- package/dist/guest/toolchains/index.js +40 -82
- package/dist/guest/toolchains/java.js +5 -5
- package/dist/guest/toolchains/leftovers.d.ts +2 -0
- package/dist/guest/toolchains/leftovers.js +26 -0
- package/dist/guest/toolchains/managers.js +12 -10
- package/dist/guest/toolchains/{binstall.js → native/binstall.js} +6 -9
- package/dist/guest/toolchains/native/cpp.d.ts +4 -0
- package/dist/guest/toolchains/native/cpp.js +38 -0
- package/dist/guest/toolchains/native/dotnet.d.ts +4 -0
- package/dist/guest/toolchains/native/dotnet.js +103 -0
- package/dist/guest/toolchains/native/mesa.d.ts +7 -0
- package/dist/guest/toolchains/native/mesa.js +56 -0
- package/dist/guest/toolchains/native/msvc/environment.d.ts +16 -0
- package/dist/guest/toolchains/native/msvc/environment.js +57 -0
- package/dist/guest/toolchains/native/msvc/index.d.ts +6 -0
- package/dist/guest/toolchains/native/msvc/index.js +48 -0
- package/dist/guest/toolchains/native/msvc/packages.d.ts +6 -0
- package/dist/guest/toolchains/native/msvc/packages.js +156 -0
- package/dist/guest/toolchains/native/msvc/tree.d.ts +15 -0
- package/dist/guest/toolchains/native/msvc/tree.js +21 -0
- package/dist/guest/toolchains/native/rust.d.ts +3 -0
- package/dist/guest/toolchains/native/rust.js +45 -0
- package/dist/guest/toolchains/node.js +26 -6
- package/dist/guest/toolchains/plan.d.ts +24 -0
- package/dist/guest/toolchains/plan.js +140 -0
- package/dist/guest/toolchains/pwsh.js +1 -1
- package/dist/guest/toolchains/python.js +43 -12
- package/dist/guest/toolchains/runtimes.d.ts +2 -0
- package/dist/guest/toolchains/runtimes.js +6 -8
- package/dist/guest/toolchains/scripting/php.d.ts +3 -0
- package/dist/guest/toolchains/scripting/php.js +71 -0
- package/dist/guest/toolchains/scripting/ruby.d.ts +3 -0
- package/dist/guest/toolchains/scripting/ruby.js +47 -0
- package/dist/guest/toolchains/scripting/vcruntime.d.ts +7 -0
- package/dist/guest/toolchains/scripting/vcruntime.js +45 -0
- package/dist/guest/toolchains/vscode-profile.d.ts +30 -0
- package/dist/guest/toolchains/vscode-profile.js +69 -0
- package/dist/guest/toolchains/vscode.d.ts +17 -0
- package/dist/guest/toolchains/vscode.js +87 -1
- package/dist/guest/view.js +21 -1
- package/dist/host/accounts.js +14 -5
- package/dist/host/agent-commands.d.ts +25 -0
- package/dist/host/agent-commands.js +145 -0
- package/dist/host/attach.d.ts +17 -0
- package/dist/host/attach.js +70 -0
- package/dist/host/audit/collect.d.ts +34 -0
- package/dist/host/audit/collect.js +126 -0
- package/dist/host/audit/log.d.ts +46 -0
- package/dist/host/audit/log.js +143 -0
- package/dist/host/channel.d.ts +23 -22
- package/dist/host/channel.js +66 -84
- package/dist/host/claude-profile.js +7 -3
- package/dist/host/cleanup.js +2 -11
- package/dist/host/database-plan.d.ts +12 -0
- package/dist/host/database-plan.js +52 -0
- package/dist/host/generate.d.ts +10 -12
- package/dist/host/generate.js +58 -135
- package/dist/host/join.d.ts +28 -0
- package/dist/host/join.js +76 -0
- package/dist/host/launch/mappings.d.ts +3 -0
- package/dist/host/launch/mappings.js +54 -0
- package/dist/host/launch/projects.d.ts +15 -0
- package/dist/host/launch/projects.js +56 -0
- package/dist/host/launch/stage.d.ts +11 -0
- package/dist/host/launch/stage.js +66 -0
- package/dist/host/launch/wsb.d.ts +10 -0
- package/dist/host/launch/wsb.js +34 -0
- package/dist/host/motw.d.ts +17 -0
- package/dist/host/motw.js +74 -0
- package/dist/host/pc-scan.d.ts +6 -0
- package/dist/host/pc-scan.js +37 -0
- package/dist/host/platform.d.ts +2 -0
- package/dist/host/platform.js +16 -1
- package/dist/host/port-forward.d.ts +8 -0
- package/dist/host/port-forward.js +37 -0
- package/dist/host/project-scan.d.ts +1 -17
- package/dist/host/project-scan.js +2 -86
- package/dist/host/projects.d.ts +100 -0
- package/dist/host/projects.js +147 -0
- package/dist/host/repo-guard.d.ts +25 -5
- package/dist/host/repo-guard.js +242 -23
- package/dist/host/stops.d.ts +67 -0
- package/dist/host/stops.js +126 -0
- package/dist/host/terminal.d.ts +8 -0
- package/dist/host/terminal.js +48 -1
- package/dist/host/test-guard.d.ts +6 -0
- package/dist/host/test-guard.js +15 -0
- package/dist/host/window.js +7 -3
- package/dist/host/workspace-view/index.d.ts +20 -0
- package/dist/host/workspace-view/index.js +53 -0
- package/dist/host/workspace-view/rules.d.ts +26 -0
- package/dist/host/workspace-view/rules.js +93 -0
- package/dist/host/workspace-view/view.d.ts +50 -0
- package/dist/host/workspace-view/view.js +281 -0
- package/dist/host/wsb.d.ts +37 -0
- package/dist/host/wsb.js +101 -0
- package/dist/runtime/daemon.js +11791 -2821
- package/dist/runtime/db.js +6585 -466
- package/dist/runtime/main.js +10238 -1724
- package/dist/runtime/netproxy.js +25936 -0
- package/dist/runtime/view.js +6183 -59
- package/dist/selftest/accounts.test.d.ts +2 -0
- package/dist/selftest/accounts.test.js +44 -0
- package/dist/selftest/agent-commands.test.d.ts +2 -0
- package/dist/selftest/agent-commands.test.js +47 -0
- package/dist/selftest/audit.test.d.ts +2 -0
- package/dist/selftest/audit.test.js +57 -0
- package/dist/selftest/channel.test.d.ts +2 -0
- package/dist/selftest/channel.test.js +44 -0
- package/dist/selftest/cli.test.d.ts +2 -2
- package/dist/selftest/cli.test.js +145 -27
- package/dist/selftest/cmdline.test.d.ts +2 -0
- package/dist/selftest/cmdline.test.js +45 -0
- package/dist/selftest/config.test.d.ts +2 -3
- package/dist/selftest/config.test.js +36 -72
- package/dist/selftest/data.test.d.ts +2 -2
- package/dist/selftest/data.test.js +77 -70
- package/dist/selftest/detect.test.d.ts +2 -2
- package/dist/selftest/detect.test.js +54 -38
- package/dist/selftest/fixtures.d.ts +89 -4
- package/dist/selftest/fixtures.js +43 -24
- package/dist/selftest/generate.test.d.ts +2 -0
- package/dist/selftest/generate.test.js +68 -0
- package/dist/selftest/git-access.test.d.ts +2 -0
- package/dist/selftest/git-access.test.js +26 -0
- package/dist/selftest/guest-boot.test.d.ts +2 -0
- package/dist/selftest/guest-boot.test.js +76 -0
- package/dist/selftest/harness.d.ts +44 -7
- package/dist/selftest/harness.js +62 -21
- package/dist/selftest/host-sim.test.d.ts +2 -0
- package/dist/selftest/host-sim.test.js +93 -0
- package/dist/selftest/hostile-input.test.d.ts +2 -0
- package/dist/selftest/hostile-input.test.js +54 -0
- package/dist/selftest/index.d.ts +8 -1
- package/dist/selftest/index.js +137 -35
- package/dist/selftest/links.test.d.ts +2 -0
- package/dist/selftest/links.test.js +50 -0
- package/dist/selftest/live-daemon.test.d.ts +2 -0
- package/dist/selftest/live-daemon.test.js +91 -0
- package/dist/selftest/live-git.test.d.ts +2 -0
- package/dist/selftest/live-git.test.js +60 -0
- package/dist/selftest/live-network.test.d.ts +2 -0
- package/dist/selftest/live-network.test.js +63 -0
- package/dist/selftest/live-projects.test.d.ts +2 -0
- package/dist/selftest/live-projects.test.js +127 -0
- package/dist/selftest/live.d.ts +65 -0
- package/dist/selftest/live.js +109 -0
- package/dist/selftest/local-config.test.d.ts +2 -0
- package/dist/selftest/local-config.test.js +120 -0
- package/dist/selftest/mirror.test.d.ts +2 -3
- package/dist/selftest/mirror.test.js +92 -65
- package/dist/selftest/network.test.d.ts +2 -0
- package/dist/selftest/network.test.js +40 -0
- package/dist/selftest/personalization.test.d.ts +2 -0
- package/dist/selftest/personalization.test.js +53 -0
- package/dist/selftest/projects.test.d.ts +2 -0
- package/dist/selftest/projects.test.js +254 -0
- package/dist/selftest/repair.test.d.ts +2 -0
- package/dist/selftest/repair.test.js +42 -0
- package/dist/selftest/repo-guard.test.d.ts +2 -0
- package/dist/selftest/repo-guard.test.js +121 -0
- package/dist/selftest/secrets.test.d.ts +2 -0
- package/dist/selftest/secrets.test.js +71 -0
- package/dist/selftest/setup.test.d.ts +2 -2
- package/dist/selftest/setup.test.js +45 -22
- package/dist/selftest/suite.d.ts +13 -0
- package/dist/selftest/suite.js +1 -0
- package/dist/selftest/sync.test.d.ts +2 -3
- package/dist/selftest/sync.test.js +130 -78
- package/dist/selftest/test-guard.test.d.ts +2 -0
- package/dist/selftest/test-guard.test.js +49 -0
- package/dist/selftest/toolchains.test.d.ts +2 -0
- package/dist/selftest/toolchains.test.js +133 -0
- package/dist/selftest/workspace-view.test.d.ts +2 -0
- package/dist/selftest/workspace-view.test.js +89 -0
- package/dist/selftest/workspace.test.d.ts +2 -0
- package/dist/selftest/workspace.test.js +53 -0
- package/dist/shared/apps.d.ts +49 -0
- package/dist/shared/apps.js +114 -0
- package/dist/shared/download.d.ts +3 -1
- package/dist/shared/download.js +19 -4
- package/dist/shared/netpolicy.d.ts +27 -0
- package/dist/shared/netpolicy.js +51 -0
- package/dist/shared/paths.d.ts +5 -0
- package/dist/shared/paths.js +6 -0
- package/dist/shared/projects.d.ts +53 -0
- package/dist/shared/projects.js +67 -0
- package/dist/shared/pty-client.d.ts +9 -4
- package/dist/shared/pty-client.js +139 -17
- package/dist/shared/rundir.d.ts +12 -1
- package/dist/shared/rundir.js +14 -4
- package/dist/shared/safe-remove.js +11 -0
- package/dist/shared/schema.d.ts +453 -0
- package/dist/shared/schema.js +43 -2
- package/dist/shared/system.d.ts +1 -0
- package/dist/shared/system.js +1 -0
- package/dist/shared/test-guard.d.ts +4 -0
- package/dist/shared/test-guard.js +37 -0
- package/dist/sync/claude-mem.js +6 -3
- package/dist/sync/history.d.ts +29 -12
- package/dist/sync/history.js +72 -25
- package/dist/sync/watcher.d.ts +8 -0
- package/dist/sync/watcher.js +99 -8
- package/package.json +7 -6
- package/sandbox/bootstrap.ps1 +258 -258
- package/sandbox/cargoshim.cs +56 -0
- package/sandbox/cpucap.cs +33 -0
- package/sandbox/cpucap.ps1 +20 -0
- package/sandbox/logon.cmd +24 -16
- package/sandbox/memlog.ps1 +34 -0
- package/sandbox/openssl.cs +42 -0
- package/sandbox/pagefile.cs +31 -0
- package/sandbox/pagefile.ps1 +21 -0
- package/sandbox/ptyhost.cs +120 -11
- package/sandbox/trust.cmd +35 -35
- package/schemas/config.schema.json +403 -3
- package/schemas/sandbox-config.schema.json +143 -13
- package/dist/cli/commands/data.d.ts +0 -46
- package/dist/cli/commands/data.js +0 -249
- package/dist/cli/commands/setup.js +0 -152
- package/dist/cli/menu.d.ts +0 -22
- package/dist/cli/menu.js +0 -187
- package/dist/cli/settings.d.ts +0 -11
- package/dist/cli/settings.js +0 -156
- package/dist/guest/toolchains/databases.js +0 -226
- package/dist/guest/toolchains/msvc.d.ts +0 -10
- package/dist/guest/toolchains/msvc.js +0 -216
- package/dist/guest/toolchains/native.d.ts +0 -12
- package/dist/guest/toolchains/native.js +0 -220
- package/dist/guest/toolchains/scripting.d.ts +0 -10
- package/dist/guest/toolchains/scripting.js +0 -137
- package/dist/selftest/guest.test.d.ts +0 -3
- package/dist/selftest/guest.test.js +0 -61
- package/dist/selftest/helpers.test.d.ts +0 -2
- package/dist/selftest/helpers.test.js +0 -125
- package/dist/selftest/host.test.d.ts +0 -2
- package/dist/selftest/host.test.js +0 -71
- package/dist/selftest/live.test.d.ts +0 -7
- package/dist/selftest/live.test.js +0 -127
- package/dist/selftest/security.test.d.ts +0 -3
- package/dist/selftest/security.test.js +0 -143
- /package/dist/guest/toolchains/{binstall.d.ts → native/binstall.d.ts} +0 -0
package/dist/core/schema.js
CHANGED
|
@@ -1,264 +1,8 @@
|
|
|
1
|
-
// Every setting, defined once with zod
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export
|
|
9
|
-
const Name = z.string().regex(/^[A-Za-z0-9_-]+$/, 'letters, numbers, - and _ only');
|
|
10
|
-
const Strings = z.array(z.string());
|
|
11
|
-
const toggle = (description) => z.strictObject({ enabled: z.boolean().describe(description) });
|
|
12
|
-
const SchemaRef = z.string().describe('Path or URL of the JSON Schema for editor autocomplete and docs.');
|
|
13
|
-
export const GitAccess = z.enum(['full', 'readonly', 'none'])
|
|
14
|
-
.describe('full: normal git. readonly: status/log/diff/show/blame only (no commit, push, checkout, ...). none: no git at all; .git is hidden from the agent.');
|
|
15
|
-
const GuestWorkspace = z.union([z.literal('auto'), z.literal('mirror'), GuestPath]).describe('Where the workspace appears inside the sandbox. "auto" = C:\\Workspace\\<folder name>. "mirror" = the same path as on this PC, so absolute paths in configs and build caches match (another drive letter such as F: is a subst drive onto C:\\Mirror\\F); paths the sandbox reserves (C:\\Users\\..., C:\\Program Files\\...) fall back to "auto".');
|
|
16
|
-
export const Mapping = z.strictObject({
|
|
17
|
-
host: z.string().min(1).describe('Folder on this PC (relative paths are relative to the config file).'),
|
|
18
|
-
guest: GuestPath.describe('Where it appears inside the sandbox, e.g. C:\\Assets, or on another drive letter (D: to Z:) such as F:\\SteamLibrary\\steamapps\\common\\Game: mapped to C:\\Mirror\\F\\... and shown as F: (subst) at boot.'),
|
|
19
|
-
readOnly: z.boolean().describe('true = the agent can only read it.'),
|
|
20
|
-
optional: z.boolean().optional().describe('true = skip it quietly when the host folder does not exist.'),
|
|
21
|
-
});
|
|
22
|
-
export const Harness = z.strictObject({
|
|
23
|
-
hostExecutable: z.string().optional().describe('Executable copied from this PC when installed here (e.g. claude.exe).'),
|
|
24
|
-
hostDir: z.string().optional().describe('Folder of hostExecutable on this PC, or "auto" to search PATH and ~/.local/bin.'),
|
|
25
|
-
npmPackage: z.string().optional().describe('npm package installed inside the sandbox when there is no host copy.'),
|
|
26
|
-
npmBin: z.string().optional().describe('Command the npm package provides.'),
|
|
27
|
-
uvPackage: z.string().optional().describe('Python package installed with `uv tool install` inside the sandbox (e.g. aider-chat).'),
|
|
28
|
-
uvBin: z.string().optional().describe('Command the uv package provides.'),
|
|
29
|
-
arguments: Strings.describe('Arguments always passed to the agent.'),
|
|
30
|
-
environment: z.record(z.string(), z.string()).describe('Environment variables for the agent.'),
|
|
31
|
-
resumeArguments: Strings.optional().describe('Arguments used when the agent is restarted in place (e.g. after an account switch) so it resumes the conversation.'),
|
|
32
|
-
})
|
|
33
|
-
.refine((h) => h.hostExecutable || h.npmPackage || h.uvPackage, 'needs hostExecutable, npmPackage or uvPackage')
|
|
34
|
-
.refine((h) => !h.uvPackage || h.uvBin, 'needs uvBin when uvPackage is set')
|
|
35
|
-
.refine((h) => !h.npmPackage || h.npmBin, 'needs npmBin when npmPackage is set');
|
|
36
|
-
const Sandbox = z.strictObject({
|
|
37
|
-
memoryMb: z.union([z.literal('auto'), z.number().int().min(2048)]).describe('Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb.'),
|
|
38
|
-
maxMemoryMb: z.number().int().positive().describe('Upper limit for memoryMb "auto".'),
|
|
39
|
-
reserveHostMb: z.number().int().nonnegative().describe('RAM always left for this PC when memoryMb is "auto".'),
|
|
40
|
-
vGpu: z.boolean().describe('Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface.'),
|
|
41
|
-
networking: z.boolean().describe('Internet access. false is the only hard network isolation Windows Sandbox offers.'),
|
|
42
|
-
clipboard: z.boolean().describe('Shared clipboard between this PC and the sandbox.'),
|
|
43
|
-
audioInput: z.boolean().describe('Microphone access.'),
|
|
44
|
-
videoInput: z.boolean().describe('Camera access.'),
|
|
45
|
-
printerRedirection: z.boolean().describe('Printers from this PC.'),
|
|
46
|
-
protectedClient: z.boolean().describe('Run the sandbox window in Protected Client mode (recommended).'),
|
|
47
|
-
headless: z.boolean().describe('Hide the sandbox window (sbx-show brings it back). A headless sandbox shuts down when its last session ends.'),
|
|
48
|
-
});
|
|
49
|
-
const Git = z.strictObject({ enabled: z.boolean().describe('Provide Git for Windows (and Git Bash, which Claude Code needs).'), access: GitAccess });
|
|
50
|
-
const Provisioning = z.strictObject({
|
|
51
|
-
copyFromHost: z.boolean().describe('Copy Node, Git, nvm and the agent from this PC when they are installed here.'),
|
|
52
|
-
fallbackToInstall: z.boolean().describe('Download anything that cannot be copied from this PC.'),
|
|
53
|
-
refresh: z.boolean().describe('Re-copy / re-download everything on the next launch.'),
|
|
54
|
-
git: Git,
|
|
55
|
-
terminal: toggle('Windows Terminal as the sandbox window (downloaded once).'),
|
|
56
|
-
});
|
|
57
|
-
/** true, false, or "auto": only when the project uses it (found from files like go.mod in the workspace or one level down). */
|
|
58
|
-
export const Enabled = z.union([z.boolean(), z.literal('auto')]);
|
|
59
|
-
const enabled = (what, markers) => Enabled.describe(what + ' true, false, or "auto" = only when the project has ' + markers + '.');
|
|
60
|
-
const Packages = (what, example) => Strings.describe(what + ', installed once and kept (e.g. ' + example + ').');
|
|
61
|
-
const Toolchains = z.strictObject({
|
|
62
|
-
node: z.strictObject({
|
|
63
|
-
version: z.string().min(1).describe('Default Node version for nvm. "host" = the Node on this PC. A project\'s .nvmrc / .node-version wins.'),
|
|
64
|
-
extraVersions: Strings.describe('More Node versions to install (switch with nvm use). On top of the up to 3 versions copied from this PC\'s nvm, not counted towards that limit.'),
|
|
65
|
-
corepack: z.boolean().describe('pnpm and yarn through corepack (a project\'s "packageManager" in package.json picks the version).'),
|
|
66
|
-
volta: Enabled.describe('Volta: true, false, or "auto" = when the project\'s package.json has "volta" pins or this PC uses Volta. With pins, Volta\'s node/npm/yarn/pnpm come first on PATH.'),
|
|
67
|
-
globalPackages: Packages('npm packages installed globally into the default Node version', '["typescript", "npm-check-updates"]'),
|
|
68
|
-
}),
|
|
69
|
-
python: z.strictObject({
|
|
70
|
-
enabled: enabled('Python 3 (CPython with pip).', 'pyproject.toml, requirements.txt, setup.py, Pipfile or .python-version'),
|
|
71
|
-
version: z.string().min(1).describe('Python 3 version prefix, e.g. "3" or "3.12". A project\'s .python-version wins.'),
|
|
72
|
-
python2: z.boolean().describe('Also install Python 2.7 as python2 / pip2.'),
|
|
73
|
-
pyenv: Enabled.describe('pyenv-win (pyenv install / local / global): true, false, or "auto" = when this PC uses pyenv. .python-version is honoured either way, and `uv python install` always works.'),
|
|
74
|
-
tools: Packages('Python command-line tools installed with `uv tool install` (needs uv)', '["poetry", "ruff", "pre-commit"]'),
|
|
75
|
-
}),
|
|
76
|
-
rust: z.strictObject({
|
|
77
|
-
enabled: enabled('Rust via rustup (cargo, rustc).', 'Cargo.toml or rust-toolchain(.toml)'),
|
|
78
|
-
toolchain: z.string().min(1).describe('Default toolchain, e.g. "stable". rust-toolchain.toml in a project wins.'),
|
|
79
|
-
host: z.string().min(1).describe('Host triple, or "auto": x86_64-pc-windows-msvc when the MSVC toolchain is on (like most PCs), else x86_64-pc-windows-gnu (MinGW is its linker).'),
|
|
80
|
-
components: Packages('Extra rustup components', '["rust-src", "llvm-tools"]'),
|
|
81
|
-
targets: Packages('Extra rustup targets', '["wasm32-unknown-unknown"]'),
|
|
82
|
-
crates: Packages('Binaries for cargo: prebuilt via cargo-binstall when the crate publishes a Windows build, else compiled with `cargo install --locked` (slow the first time)', '["sccache", "cargo-nextest", "cargo-deny"]'),
|
|
83
|
-
targetDir: z.string().min(1).describe('"shared": cargo\'s default target\\ (shared with builds on this PC, so builds on either side invalidate the other), "separate": <workspace>\\target\\sandbox (kept, no cross-talk), "local": on the sandbox\'s own disk (fastest, lost every boot), or a guest path.'),
|
|
84
|
-
}),
|
|
85
|
-
msvc: z.strictObject({
|
|
86
|
-
enabled: enabled('MSVC (cl, link) and the Windows SDK, portable from Microsoft\'s Visual Studio manifest (~1-2 GB once), with vcvars64.bat and vswhere.', 'a .vcxproj, CMakePresets.json, a script calling vcvars/vswhere, or a Rust project when this PC builds Rust with MSVC'),
|
|
87
|
-
acceptLicense: z.boolean().describe('Required to install MSVC: you accept the Visual Studio licence terms (https://visualstudio.microsoft.com/license-terms/), which need a Visual Studio licence.'),
|
|
88
|
-
msvcVersion: z.string().min(1).describe('"latest" or an MSVC tools version prefix, e.g. "14.44".'),
|
|
89
|
-
sdkVersion: z.string().min(1).describe('"latest" or a Windows SDK build, e.g. "26100" or "10.0.22621".'),
|
|
90
|
-
}),
|
|
91
|
-
cpp: z.strictObject({
|
|
92
|
-
enabled: enabled('MinGW-w64 GCC with CMake, Ninja, premake5 and mingw32-make (also Rust\'s linker).', 'CMakeLists.txt, Makefile, meson.build, premake5.lua or Cargo.toml'),
|
|
93
|
-
flexBison: z.boolean().describe('win_flex / win_bison, the parser generators many C/C++ projects (game engines among them) need; CMake finds them.'),
|
|
94
|
-
}),
|
|
95
|
-
dotnet: z.strictObject({
|
|
96
|
-
enabled: enabled('.NET SDK (C#, F#).', 'a .sln, .slnx, .csproj, .fsproj or global.json'),
|
|
97
|
-
channels: Strings.describe('SDK channels, e.g. ["LTS", "8.0"]. A project\'s global.json is installed too.'),
|
|
98
|
-
tools: Packages('Global .NET tools (`dotnet tool install -g`)', '["dotnet-ef", "csharpier"]'),
|
|
99
|
-
workloads: Packages('SDK workloads (`dotnet workload install`)', '["aspire", "wasm-tools"]'),
|
|
100
|
-
frameworkTargets: Strings.describe('.NET Framework reference assemblies (targeting packs) from NuGet, so net4x and old-style .csproj projects build without Visual Studio, e.g. ["net48", "net472", "net462"]. The 4.8 runtime itself ships with Windows.'),
|
|
101
|
-
netfx35: z.boolean().describe('.NET Framework 3.5 runtime (a Windows feature, enabled from Windows Update on every boot; a few minutes).'),
|
|
102
|
-
}),
|
|
103
|
-
go: z.strictObject({
|
|
104
|
-
enabled: enabled('Go.', 'go.mod or go.work'),
|
|
105
|
-
version: z.string().min(1).describe('"stable" or a version prefix such as "1.23". A go.mod asking for newer fetches it itself (GOTOOLCHAIN=auto).'),
|
|
106
|
-
tools: Packages('Go tools (`go install <path>@<version>`)', '["golang.org/x/tools/gopls@latest"]'),
|
|
107
|
-
}),
|
|
108
|
-
java: z.strictObject({
|
|
109
|
-
enabled: enabled('Java: Eclipse Temurin JDK.', 'pom.xml, build.gradle(.kts), settings.gradle(.kts), mvnw, gradlew or .java-version'),
|
|
110
|
-
version: z.string().min(1).describe('"lts" (newest LTS) or a major version such as "21". A project\'s .java-version or .sdkmanrc wins.'),
|
|
111
|
-
maven: z.boolean().describe('Apache Maven (mvn). A project\'s mvnw works either way.'),
|
|
112
|
-
gradle: z.boolean().describe('Gradle (gradle). A project\'s gradlew works either way.'),
|
|
113
|
-
}),
|
|
114
|
-
ruby: z.strictObject({
|
|
115
|
-
enabled: enabled('Ruby (RubyInstaller, with gem and bundler). Gems with C extensions need MSYS2, which is not included.', 'Gemfile, a .gemspec or .ruby-version'),
|
|
116
|
-
version: z.string().min(1).describe('Version prefix, e.g. "3" or "3.3". A project\'s .ruby-version wins.'),
|
|
117
|
-
gems: Packages('Gems installed globally', '["rubocop"]'),
|
|
118
|
-
}),
|
|
119
|
-
php: z.strictObject({
|
|
120
|
-
enabled: enabled('PHP (with the Visual C++ runtime it needs, installed on every boot).', 'composer.json, artisan or .php-version'),
|
|
121
|
-
version: z.string().min(1).describe('Version prefix, e.g. "8" or "8.3". A project\'s .php-version wins.'),
|
|
122
|
-
composer: z.boolean().describe('Composer.'),
|
|
123
|
-
}),
|
|
124
|
-
deno: z.strictObject({ enabled: enabled('Deno.', 'deno.json, deno.jsonc or deno.lock') }),
|
|
125
|
-
pwsh: z.strictObject({ enabled: Enabled.describe('PowerShell 7 (pwsh), portable (~110 MB once); `powershell` stays Windows PowerShell 5.1. true, false, or "auto" = when a .ps1 at the root or one folder down has #Requires -Version 7 / -PSEdition Core or a `pwsh ...` usage line, or, in a folder that is no project yet, when this PC has PowerShell 7.') }),
|
|
126
|
-
cli: z.strictObject({
|
|
127
|
-
gh: Enabled.describe('GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR). "auto" = when the project has a .github folder.'),
|
|
128
|
-
zstd: Enabled.describe('Zstandard (zstd). "auto" = off; set true to get it.'),
|
|
129
|
-
openssl: Enabled.describe('`openssl` on PATH, from the copy Git for Windows ships (its mingw64\\bin is not put on PATH, so it cannot shadow MinGW\'s gcc). "auto" = on.'),
|
|
130
|
-
}).describe('Small portable command-line tools from their GitHub releases, installed once into tools\\cli.'),
|
|
131
|
-
bun: toggle('Bun runtime (claude-mem needs it).'),
|
|
132
|
-
uv: toggle('uv, the Python package manager (claude-mem needs it).'),
|
|
133
|
-
vcRuntime: toggle('Microsoft Visual C++ runtime for tools that need it (a real installer, so it runs on every boot, ~15 s). PHP installs it regardless.'),
|
|
134
|
-
mesa: z.strictObject({
|
|
135
|
-
enabled: z.boolean().describe('Mesa 3D (llvmpipe): OpenGL 4.5 in software for games and apps when there is no GPU (sandbox.vGpu off). Copy opengl32.dll and libgallium_wgl.dll from %MESA_DIR% next to the program\'s .exe.'),
|
|
136
|
-
vulkan: z.boolean().describe('Also software Vulkan 1.4 (Mesa lavapipe) with the Khronos loader, registered for every program; for wgpu set WGPU_BACKEND=vulkan.'),
|
|
137
|
-
}),
|
|
138
|
-
vscode: toggle('Portable VS Code inside the sandbox (code on PATH, desktop shortcut); its settings and extensions persist.'),
|
|
139
|
-
environment: z.record(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, 'letters, digits and _ only'), z.string()).describe('Extra environment variables for the agent and every terminal, e.g. registry mirrors: {"NPM_CONFIG_REGISTRY": "https://...", "PIP_INDEX_URL": "https://..."}.'),
|
|
140
|
-
});
|
|
141
|
-
const Port = z.number().int().min(1024).max(65535);
|
|
142
|
-
const dbEnabled = (name) => Enabled.describe(name + ': true, false, or "auto" = only when the project needs it (found from compose files, dependencies of every language, Prisma/ORM config and connection strings).');
|
|
143
|
-
const Databases = z.strictObject({
|
|
144
|
-
postgres: z.strictObject({
|
|
145
|
-
enabled: dbEnabled('PostgreSQL (with psql, pg_dump). User postgres, no password, localhost only'),
|
|
146
|
-
version: z.string().min(1).describe('"latest" or a major version such as "16". A compose file pinning postgres:<major> wins.'),
|
|
147
|
-
port: Port.describe('Port inside the sandbox.'),
|
|
148
|
-
}),
|
|
149
|
-
mysql: z.strictObject({
|
|
150
|
-
enabled: dbEnabled('MySQL-compatible database (MariaDB). User root, no password, localhost only'),
|
|
151
|
-
version: z.string().min(1).describe('"lts" (newest MariaDB LTS) or a MariaDB series such as "11.4".'),
|
|
152
|
-
port: Port.describe('Port inside the sandbox.'),
|
|
153
|
-
}),
|
|
154
|
-
mongodb: z.strictObject({
|
|
155
|
-
enabled: dbEnabled('MongoDB with mongosh, localhost only'),
|
|
156
|
-
version: z.string().min(1).describe('"latest" or a version prefix such as "8.0".'),
|
|
157
|
-
port: Port.describe('Port inside the sandbox.'),
|
|
158
|
-
}),
|
|
159
|
-
redis: z.strictObject({
|
|
160
|
-
enabled: dbEnabled('Redis (community Windows build), localhost only'),
|
|
161
|
-
port: Port.describe('Port inside the sandbox.'),
|
|
162
|
-
}),
|
|
163
|
-
dynamodb: z.strictObject({
|
|
164
|
-
enabled: dbEnabled('DynamoDB Local (Amazon\'s official emulator, on the Java toolchain) with dynamodb-admin, a web UI to browse and edit tables'),
|
|
165
|
-
port: Port.describe('DynamoDB endpoint port inside the sandbox (http://localhost:<port>).'),
|
|
166
|
-
adminPort: Port.describe('dynamodb-admin web UI port (open http://localhost:<adminPort> in the sandbox\'s browser).'),
|
|
167
|
-
admin: z.boolean().describe('Run dynamodb-admin next to DynamoDB Local.'),
|
|
168
|
-
}),
|
|
169
|
-
sqlserver: z.strictObject({
|
|
170
|
-
enabled: dbEnabled('SQL Server. It cannot run inside Windows Sandbox; when a project needs it you get a hint to reach the one on this PC through hostAccess.forwards'),
|
|
171
|
-
}),
|
|
172
|
-
});
|
|
173
|
-
const Secrets = z.strictObject({
|
|
174
|
-
strip: z.boolean().describe('Remove credentials from everything copied into the sandbox (your Claude settings.json "env" and credential helpers, MCP servers\' env, headers and arguments): AWS, Azure, Google Cloud, Cloudflare, hosting, CI, registries, payment, AI API keys, database URLs, anything named *_TOKEN / *_SECRET / *PASSWORD* / *_KEY or *PROD*, and values that look like keys.'),
|
|
175
|
-
allow: Strings.describe('Variable names that may go in anyway; * matches anything, e.g. ["AWS_REGION", "AWS_PROFILE", "MY_APP_*"].'),
|
|
176
|
-
patterns: Strings.describe('More variable names to treat as secrets; * matches anything, e.g. ["ACME_*", "*_INTERNAL_URL"].'),
|
|
177
|
-
warnFiles: z.boolean().describe('Warn at launch about files in the workspace that usually hold secrets (.env, *.pem, credentials.json, ...). The agent CAN read them: Windows Sandbox maps the whole folder.'),
|
|
178
|
-
});
|
|
179
|
-
const Attach = z.strictObject({
|
|
180
|
-
enabled: z.boolean().describe('Allow sandbox claude --terminal / sandbox attach from this PC.'),
|
|
181
|
-
reuseSession: z.boolean().describe('sandbox claude -t in a running sandbox reattaches to this folder\'s session when no terminal on this PC is attached to it (--new always starts another).'),
|
|
182
|
-
auto: z.boolean().describe('Starting an agent attaches this terminal automatically, as if you passed -t (only in an interactive terminal).'),
|
|
183
|
-
autoHide: z.boolean().describe('Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back).'),
|
|
184
|
-
});
|
|
185
|
-
const ClaudeProfile = z.strictObject({
|
|
186
|
-
enabled: z.boolean().describe('Copy selected Claude settings from this PC into the sandbox.'),
|
|
187
|
-
hostDir: z.string().describe('Your Claude folder, or "auto" (~/.claude or CLAUDE_CONFIG_DIR).'),
|
|
188
|
-
include: z.array(z.string().regex(/^[A-Za-z0-9._-]+$/)).describe('Files and folders copied from it.'),
|
|
189
|
-
globalStateFile: z.string().describe('Your .claude.json, or "auto". Empty string = do not copy.'),
|
|
190
|
-
copyCredentials: z.boolean().describe('Copy your Claude LOGIN into the sandbox. Prefer sandbox account instead.'),
|
|
191
|
-
overwrite: z.boolean().describe('Refresh these settings from this PC on every launch.'),
|
|
192
|
-
syncHistory: z.boolean().describe('Bring all conversation history in, and sync new history back (path-translated).'),
|
|
193
|
-
syncClaudeMem: z.boolean().describe('Bring claude-mem data in, and its database back when the sandbox closes.'),
|
|
194
|
-
});
|
|
195
|
-
export const Config = z.strictObject({
|
|
196
|
-
$schema: SchemaRef.optional(),
|
|
197
|
-
defaultHarness: Name.describe('Agent started by `sandbox launch` (sandbox claude always runs claude).'),
|
|
198
|
-
guestWorkspace: GuestWorkspace,
|
|
199
|
-
readOnly: z.boolean().describe('Map the workspace read-only.'),
|
|
200
|
-
mappings: z.array(Mapping).describe('Extra folders from this PC.'),
|
|
201
|
-
sandbox: Sandbox,
|
|
202
|
-
storage: z.strictObject({
|
|
203
|
-
root: z.string().min(1).describe('Where everything is kept on this PC (tools, databases, logins, launches).'),
|
|
204
|
-
persistAgentState: z.boolean().describe('Keep agent logins and history between sandboxes.'),
|
|
205
|
-
dataName: Name.describe('Name of the persistent data set (C:\\AgentData) shared by all workspaces.'),
|
|
206
|
-
}),
|
|
207
|
-
network: z.strictObject({ blockPrivateRanges: z.boolean().describe('Block your LAN (10/8, 172.16/12, 192.168/16, SMB) from inside the sandbox.') }),
|
|
208
|
-
provisioning: Provisioning,
|
|
209
|
-
toolchains: Toolchains,
|
|
210
|
-
databases: Databases.describe('Databases running inside the sandbox. Data persists in C:\\AgentData\\databases; each one starts at boot.'),
|
|
211
|
-
attach: Attach,
|
|
212
|
-
secrets: Secrets,
|
|
213
|
-
personalization: toggle('Copy your desktop look (theme, accent, taskbar, wallpaper, ...) into the sandbox.'),
|
|
214
|
-
claudeProfile: ClaudeProfile,
|
|
215
|
-
harnesses: z.record(Name, Harness).describe('Agents that can run in the sandbox.'),
|
|
216
|
-
hooks: z.strictObject({ failFast: z.boolean().describe('Stop when a hook script fails.') }),
|
|
217
|
-
}).refine((c) => c.harnesses[c.defaultHarness] !== undefined, { message: 'defaultHarness must be one of the configured harnesses', path: ['defaultHarness'] });
|
|
218
|
-
/**
|
|
219
|
-
* What a project's .sandbox-config.json may change. A repo can ship this file, so it can NOT touch storage, agent
|
|
220
|
-
* executables, host folders for tools or Claude settings, or anything else outside this list.
|
|
221
|
-
*/
|
|
222
|
-
export const LocalOverrides = z.strictObject({
|
|
223
|
-
$schema: SchemaRef,
|
|
224
|
-
harness: Name.describe('Agent for this project.'),
|
|
225
|
-
guestWorkspace: GuestWorkspace,
|
|
226
|
-
readOnly: z.boolean().describe('Map this project read-only.'),
|
|
227
|
-
mappings: z.array(Mapping).describe('Extra folders (relative to this file).'),
|
|
228
|
-
scripts: Strings.describe('Scripts (.ps1 / .mjs / .cmd, relative to this file) run inside the sandbox before the agent.'),
|
|
229
|
-
sandbox: Sandbox.partial(),
|
|
230
|
-
network: z.strictObject({ blockPrivateRanges: z.boolean() }).partial(),
|
|
231
|
-
provisioning: Provisioning.pick({ copyFromHost: true, fallbackToInstall: true, refresh: true }).extend({ git: Git.partial(), terminal: toggle('Windows Terminal as the sandbox window.').partial() }).partial(),
|
|
232
|
-
// Every toolchain setting, each one optional (a project usually only switches languages on or pins a version).
|
|
233
|
-
toolchains: z.strictObject({
|
|
234
|
-
..._.mapValues(_.omit(Toolchains.shape, 'environment'), (shape) => shape.partial()),
|
|
235
|
-
environment: Toolchains.shape.environment,
|
|
236
|
-
}).partial(),
|
|
237
|
-
databases: z.strictObject(_.mapValues(Databases.shape, (shape) => shape.partial())).partial(),
|
|
238
|
-
attach: Attach.partial(),
|
|
239
|
-
personalization: toggle('Copy your desktop look into the sandbox.').partial(),
|
|
240
|
-
claudeProfile: ClaudeProfile.pick({ enabled: true, include: true, overwrite: true, copyCredentials: true, syncHistory: true, syncClaudeMem: true }).partial(),
|
|
241
|
-
hooks: z.strictObject({ failFast: z.boolean() }).partial(),
|
|
242
|
-
}).partial();
|
|
243
|
-
/** One readable line per problem: "sandbox.memoryMb: Too small: expected number to be >=2048". */
|
|
244
|
-
export const describeIssues = (error) => error.issues.map((issue) => {
|
|
245
|
-
const at = issue.path.join('.');
|
|
246
|
-
if (issue.code === 'unrecognized_keys')
|
|
247
|
-
return issue.keys.map((k) => (at ? at + '.' : '') + k + ' is not allowed here').join('; ');
|
|
248
|
-
return (at || 'value') + ': ' + issue.message;
|
|
249
|
-
});
|
|
250
|
-
/** JSON Schema documents for editors. The user config only lists what it changes, so nothing in it is required. */
|
|
251
|
-
export const jsonSchemas = () => {
|
|
252
|
-
const dropRequired = (node) => {
|
|
253
|
-
if (Array.isArray(node))
|
|
254
|
-
return node.map(dropRequired);
|
|
255
|
-
if (typeof node !== 'object' || node === null)
|
|
256
|
-
return node;
|
|
257
|
-
return Object.fromEntries(Object.entries(node).filter(([k]) => k !== 'required').map(([k, v]) => [k, dropRequired(v)]));
|
|
258
|
-
};
|
|
259
|
-
const toSchema = (schema, title) => ({ title, ...z.toJSONSchema(schema, { io: 'input', unrepresentable: 'any' }) });
|
|
260
|
-
return {
|
|
261
|
-
'config.schema.json': dropRequired(toSchema(Config, 'windows-development-sandbox user config (~/.agent-sandbox/config.json)')),
|
|
262
|
-
'sandbox-config.schema.json': toSchema(LocalOverrides, 'windows-development-sandbox project config (.sandbox-config.json)'),
|
|
263
|
-
};
|
|
264
|
-
};
|
|
1
|
+
// Every setting, defined once with zod, split by area in schema/. This file is the one place the rest of the code (and
|
|
2
|
+
// scripts/schemas.mjs, which generates the JSON Schema files) imports them from.
|
|
3
|
+
export { GitAccess } from './schema/common.js';
|
|
4
|
+
export { Config, LocalOverrides } from './schema/config.js';
|
|
5
|
+
export { Harness } from './schema/harness.js';
|
|
6
|
+
export { describeIssues, jsonSchemas } from './schema/json-schema.js';
|
|
7
|
+
export { Mapping } from './schema/sandbox.js';
|
|
8
|
+
export { Toolchains } from './schema/toolchains.js';
|
package/dist/core/types.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export interface ResolvedRun {
|
|
|
50
50
|
localConfigPath: string | null;
|
|
51
51
|
notes: string[];
|
|
52
52
|
versions: ToolVersions;
|
|
53
|
+
/** Your config asks for guestWorkspace "mirror" (project roots then appear at their PC paths too). */
|
|
54
|
+
mirror?: boolean;
|
|
53
55
|
}
|
|
54
56
|
/** A requested version plus where the request came from (shown to the user). */
|
|
55
57
|
export interface VersionSpec {
|
|
@@ -84,7 +86,6 @@ export interface DatabasePlan {
|
|
|
84
86
|
port: number;
|
|
85
87
|
adminPort?: number;
|
|
86
88
|
}
|
|
87
|
-
/** databases: the plan to use instead of scanning the workspace (tests). */
|
|
88
89
|
/** databases / pcLanguages: use these instead of scanning (tests). */
|
|
89
90
|
export interface GenerateOptions {
|
|
90
91
|
packageRoot: string;
|
|
@@ -94,6 +95,11 @@ export interface GenerateOptions {
|
|
|
94
95
|
freeMemoryBytes?: number;
|
|
95
96
|
databases?: DatabasePlan[];
|
|
96
97
|
pcLanguages?: import('./detect-toolchains.js').AutoToolchain[];
|
|
98
|
+
/** More projects to map (a restart that adds one keeps the ones in use); knownProjects: instead of known-projects.json (tests). */
|
|
99
|
+
extraProjects?: string[];
|
|
100
|
+
knownProjects?: string[];
|
|
101
|
+
/** false: no agent session at boot. */
|
|
102
|
+
autoSession?: boolean;
|
|
97
103
|
}
|
|
98
104
|
export interface Generated {
|
|
99
105
|
wsbPath: string;
|
|
@@ -104,6 +110,18 @@ export interface Generated {
|
|
|
104
110
|
mappings: ResolvedMapping[];
|
|
105
111
|
profile: ProfileResult;
|
|
106
112
|
databases: DatabasePlan[];
|
|
113
|
+
/** Project roots and other projects mapped with the launch folder. */
|
|
114
|
+
projects: {
|
|
115
|
+
roots: {
|
|
116
|
+
host: string;
|
|
117
|
+
guest: string;
|
|
118
|
+
}[];
|
|
119
|
+
projects: {
|
|
120
|
+
host: string;
|
|
121
|
+
guest: string;
|
|
122
|
+
}[];
|
|
123
|
+
notes: string[];
|
|
124
|
+
};
|
|
107
125
|
toolchains: Record<import('./detect-toolchains.js').AutoToolchain, import('./detect-toolchains.js').ToolchainDecision>;
|
|
108
126
|
}
|
|
109
127
|
/** secretsRemoved: what secrets.strip kept on this PC, e.g. "settings.json env.AWS_SECRET_ACCESS_KEY". */
|
|
@@ -120,6 +138,13 @@ export interface GuestSession {
|
|
|
120
138
|
project: string;
|
|
121
139
|
workspace: string;
|
|
122
140
|
workspaceHost: string;
|
|
141
|
+
/** The launch folder's project id (file-name safe; status files and sessions use it). Older launch folders lack it. */
|
|
142
|
+
projectId?: string;
|
|
143
|
+
/** Where other projects appear (C:\Projects), and the project roots' guest folders. Older launch folders lack them. */
|
|
144
|
+
projectsDir?: string;
|
|
145
|
+
roots?: string[];
|
|
146
|
+
/** false: start no agent session at boot (a restart that adds a project opens its sessions itself). */
|
|
147
|
+
autoSession?: boolean;
|
|
123
148
|
harnessName: string;
|
|
124
149
|
harness: Harness | null;
|
|
125
150
|
harnessArguments: string[];
|
|
@@ -135,6 +160,7 @@ export interface GuestSession {
|
|
|
135
160
|
databaseCatalog?: DatabasePlan[];
|
|
136
161
|
attach: Config['attach'];
|
|
137
162
|
hooks: Config['hooks'];
|
|
163
|
+
downloads: Config['downloads'];
|
|
138
164
|
/** nodeVersion: this PC's Node (e.g. 22.11.0), found under nvm\v<version> when nvm is mapped, else under node. */
|
|
139
165
|
/** volta / pyenv: this PC uses them (their "auto" settings turn them on in the sandbox too). */
|
|
140
166
|
hostTools: {
|
|
@@ -159,4 +185,12 @@ export interface GuestSession {
|
|
|
159
185
|
letter: string;
|
|
160
186
|
target: string;
|
|
161
187
|
}[];
|
|
188
|
+
/** sandbox.cpuLimit as a number (null = no cap); sandbox\cpucap.ps1 applies it before anything starts. */
|
|
189
|
+
cpuLimitPercent?: number | null;
|
|
190
|
+
/** sandbox.pageFileMb (0 = Windows' own); sandbox\pagefile.ps1 applies it at logon. */
|
|
191
|
+
pageFileMb?: number;
|
|
192
|
+
/** Apps to install (catalogue ids and your own programs); missing in launch folders of older versions. */
|
|
193
|
+
apps?: Config['apps'];
|
|
194
|
+
/** audit.enabled and audit.processes: the sandbox reports the programs it starts (host keeps the log). */
|
|
195
|
+
auditProcesses?: boolean;
|
|
162
196
|
}
|
package/dist/core/util.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare const dirExists: (p: string) => boolean;
|
|
|
18
18
|
export declare const fileExists: (p: string) => boolean;
|
|
19
19
|
export declare const readJson: <T>(p: string) => T;
|
|
20
20
|
export declare const tryReadJson: <T>(p: string) => T | null;
|
|
21
|
+
/** Atomic (a crash or a second command never leaves half a file); refused outside temp during the self-test. */
|
|
21
22
|
export declare const writeJson: (p: string, value: unknown) => void;
|
|
22
23
|
export declare const realPath: (p: string) => string;
|
|
23
24
|
export declare const xmlEscape: (v: string) => string;
|
|
@@ -33,6 +34,8 @@ export declare const isInsideOrEqual: (parent: string, child: string) => boolean
|
|
|
33
34
|
* plain colours (SGR), so nothing written by the sandbox can drive your terminal (titles, clipboard, cursor tricks).
|
|
34
35
|
*/
|
|
35
36
|
export declare const safeText: (text: string) => string;
|
|
37
|
+
/** safeText without colours either: for text you are asked to approve, which must not be able to hide parts of itself. */
|
|
38
|
+
export declare const plainText: (text: string) => string;
|
|
36
39
|
export declare const findOnPath: (names: string[]) => string | null;
|
|
37
40
|
/** True if `p` itself is a symlink or junction (lstat; never follows it). */
|
|
38
41
|
export declare const isLink: (p: string) => boolean;
|
|
@@ -49,5 +52,11 @@ export declare const runPowerShell: (script: string, capture?: boolean) => {
|
|
|
49
52
|
status: number;
|
|
50
53
|
stdout: string;
|
|
51
54
|
};
|
|
55
|
+
/** Runs a program (an absolute path: `SYSTEM.*`, never a bare name) and returns its stdout, or '' if it failed or timed out. */
|
|
56
|
+
export declare const captureOutput: (file: string, args: string[], options?: {
|
|
57
|
+
timeout?: number;
|
|
58
|
+
cwd?: string;
|
|
59
|
+
maxBuffer?: number;
|
|
60
|
+
}) => string;
|
|
52
61
|
/** Async variant (does not block the event loop), resolving with stdout. */
|
|
53
62
|
export declare const runPowerShellAsync: (script: string) => Promise<string>;
|
package/dist/core/util.js
CHANGED
|
@@ -3,6 +3,8 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { spawn, spawnSync } from 'node:child_process';
|
|
5
5
|
import { SYSTEM } from '../shared/system.js';
|
|
6
|
+
import { writeJsonAtomic } from '../shared/rundir.js';
|
|
7
|
+
import { assertTestWritable } from '../shared/test-guard.js';
|
|
6
8
|
import { parse as parseJsoncText, printParseErrorCode } from 'jsonc-parser';
|
|
7
9
|
export const isWin = process.platform === 'win32';
|
|
8
10
|
/** An expected problem the user can act on: what went wrong, and (optionally) how to fix it. */
|
|
@@ -52,7 +54,8 @@ export const tryReadJson = (p) => { try {
|
|
|
52
54
|
catch {
|
|
53
55
|
return null;
|
|
54
56
|
} };
|
|
55
|
-
|
|
57
|
+
/** Atomic (a crash or a second command never leaves half a file); refused outside temp during the self-test. */
|
|
58
|
+
export const writeJson = (p, value) => writeJsonAtomic(p, value);
|
|
56
59
|
export const realPath = (p) => { try {
|
|
57
60
|
return fs.realpathSync(p);
|
|
58
61
|
}
|
|
@@ -78,6 +81,8 @@ export const isInsideOrEqual = (parent, child) => {
|
|
|
78
81
|
* plain colours (SGR), so nothing written by the sandbox can drive your terminal (titles, clipboard, cursor tricks).
|
|
79
82
|
*/
|
|
80
83
|
export const safeText = (text) => text.replace(/\x1b\[[0-9;]*m|\x1b(\[[0-9;?]*[ -\/]*[@-~]|\][^\x07\x1b]*(\x07|\x1b\\)|[@-Z\\-_])|[\x00-\x08\x0b-\x1f\x7f-\x9f]/g, (m) => (/^\x1b\[[0-9;]*m$/.test(m) ? m : ''));
|
|
84
|
+
/** safeText without colours either: for text you are asked to approve, which must not be able to hide parts of itself. */
|
|
85
|
+
export const plainText = (text) => safeText(text).replace(/\x1b\[[0-9;]*m/g, '');
|
|
81
86
|
export const findOnPath = (names) => {
|
|
82
87
|
const dirs = (process.env.PATH ?? process.env.Path ?? '').split(path.delimiter).filter((d) => d !== '');
|
|
83
88
|
for (const name of names)
|
|
@@ -96,7 +101,7 @@ catch {
|
|
|
96
101
|
return false;
|
|
97
102
|
} };
|
|
98
103
|
/** Removes a symlink or junction itself (never its target). Junctions need rmdir on Windows. */
|
|
99
|
-
export const removeLink = (p) => { try {
|
|
104
|
+
export const removeLink = (p) => { assertTestWritable(p); try {
|
|
100
105
|
fs.unlinkSync(p);
|
|
101
106
|
}
|
|
102
107
|
catch {
|
|
@@ -126,7 +131,8 @@ export const assertNoLinks = (root, target) => {
|
|
|
126
131
|
const powerShellArgs = (script) => {
|
|
127
132
|
const prelude = "[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding $false\n$ProgressPreference = 'SilentlyContinue'\n";
|
|
128
133
|
const encoded = Buffer.from(prelude + script, 'utf16le').toString('base64');
|
|
129
|
-
|
|
134
|
+
// -OutputFormat Text: with redirected output PowerShell would otherwise print its progress stream as "#< CLIXML" XML.
|
|
135
|
+
return ['-NoLogo', '-NoProfile', '-NonInteractive', '-OutputFormat', 'Text', '-ExecutionPolicy', 'Bypass', '-EncodedCommand', encoded];
|
|
130
136
|
};
|
|
131
137
|
/** Runs a PowerShell script and returns its exit code (and stdout when `capture`). */
|
|
132
138
|
export const runPowerShell = (script, capture = false) => {
|
|
@@ -135,6 +141,11 @@ export const runPowerShell = (script, capture = false) => {
|
|
|
135
141
|
throw result.error;
|
|
136
142
|
return { status: result.status ?? 1, stdout: result.stdout ?? '' };
|
|
137
143
|
};
|
|
144
|
+
/** Runs a program (an absolute path: `SYSTEM.*`, never a bare name) and returns its stdout, or '' if it failed or timed out. */
|
|
145
|
+
export const captureOutput = (file, args, options = {}) => {
|
|
146
|
+
const result = spawnSync(file, args, { encoding: 'utf8', windowsHide: true, timeout: 60000, ...options });
|
|
147
|
+
return result.status === 0 ? result.stdout ?? '' : '';
|
|
148
|
+
};
|
|
138
149
|
/** Async variant (does not block the event loop), resolving with stdout. */
|
|
139
150
|
export const runPowerShellAsync = (script) => new Promise((resolve, reject) => {
|
|
140
151
|
const child = spawn(SYSTEM.powershell(), powerShellArgs(script), { stdio: ['ignore', 'pipe', 'inherit'], windowsHide: true });
|
package/dist/core/workspace.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import type { Config, Overrides, ResolvedRun, RunRequest, ToolVersions } from './types.js';
|
|
2
|
-
export declare const askYesNo: (question: string) => Promise<boolean>;
|
|
3
|
-
/** A read/write folder mapped into the sandbox must not contain, or sit inside, any protected folder. */
|
|
4
|
-
export declare const assertSafeMapping: (folder: string, packageRoot: string, storageRoot: string) => void;
|
|
5
|
-
/** The agent gets read/write access to the workspace, so refuse folders that would let it reach the tool itself, its storage, or the OS. */
|
|
6
|
-
export declare const assertSafeWorkspace: (workspace: string, packageRoot: string, storageRoot: string) => void;
|
|
7
2
|
/**
|
|
8
3
|
* 'auto' guest workspace: C:\Workspace\<folder name>. Keeping the real folder name means Claude's per-project history
|
|
9
4
|
* and claude-mem's project name match this PC instead of every project being "Workspace".
|
package/dist/core/workspace.js
CHANGED
|
@@ -1,53 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import readline from 'node:readline';
|
|
4
3
|
import { z } from 'zod';
|
|
5
|
-
import { userDir } from './config.js';
|
|
6
4
|
import { planMirrorWorkspace } from '../shared/guest-paths.js';
|
|
7
5
|
import { DATABASES } from './detect-databases.js';
|
|
8
|
-
import { applyOverrides, describeOverrides, isTrusted, normalizeOverrides, readLocalConfig, saveTrust, trustStorePath } from './local-config.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
if (!process.stdin.isTTY)
|
|
12
|
-
return false;
|
|
13
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
14
|
-
const answer = await new Promise((resolve) => rl.question(question + ' [y/N] ', resolve));
|
|
15
|
-
rl.close();
|
|
16
|
-
return /^y(es)?$/i.test(answer.trim());
|
|
17
|
-
};
|
|
18
|
-
/** Folders the agent must never be able to write: the tool itself, its storage and your settings for it. */
|
|
19
|
-
const protectedFolders = (packageRoot, storageRoot) => [
|
|
20
|
-
['this tool\'s install folder', packageRoot],
|
|
21
|
-
['the sandbox storage folder', storageRoot],
|
|
22
|
-
['your sandbox settings folder', userDir()],
|
|
23
|
-
];
|
|
24
|
-
/** A read/write folder mapped into the sandbox must not contain, or sit inside, any protected folder. */
|
|
25
|
-
export const assertSafeMapping = (folder, packageRoot, storageRoot) => {
|
|
26
|
-
if (isRootPath(folder) || isUserProfile(folder))
|
|
27
|
-
fail('A whole drive or user profile cannot be mapped into the sandbox: ' + folder, 'Map a specific folder instead.');
|
|
28
|
-
for (const [label, dir] of protectedFolders(packageRoot, storageRoot)) {
|
|
29
|
-
if (isInsideOrEqual(dir, folder) || isInsideOrEqual(folder, dir))
|
|
30
|
-
fail(folder + ' cannot be mapped into the sandbox: it overlaps ' + label + ' (' + dir + ').', 'Map a folder that is not inside (and does not contain) ' + dir + '.');
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
/** The agent gets read/write access to the workspace, so refuse folders that would let it reach the tool itself, its storage, or the OS. */
|
|
34
|
-
export const assertSafeWorkspace = (workspace, packageRoot, storageRoot) => {
|
|
35
|
-
if (isRootPath(workspace))
|
|
36
|
-
fail('A whole drive cannot be the workspace: ' + workspace, 'Run sandbox claude from a project folder (or pass --workspace <folder>).');
|
|
37
|
-
if (isUserProfile(workspace))
|
|
38
|
-
fail('Your whole user profile cannot be the workspace: ' + workspace, 'Run sandbox claude from a project folder (or pass --workspace <folder>).');
|
|
39
|
-
for (const [label, dir] of protectedFolders(packageRoot, storageRoot)) {
|
|
40
|
-
if (isInsideOrEqual(dir, workspace))
|
|
41
|
-
fail(workspace + ' cannot be the workspace: it is inside ' + label + ' (' + dir + '), so the agent could change the code that runs on this PC.', dir === packageRoot ? 'Developing windows-development-sandbox itself? Install it as a copy instead of a link: run `npm run install:global` in the repository, then sandbox claude works there.' : 'Run sandbox claude from a project folder somewhere else.');
|
|
42
|
-
if (isInsideOrEqual(workspace, dir))
|
|
43
|
-
fail(workspace + ' cannot be the workspace: it contains ' + label + ' (' + dir + '), which the agent must not be able to change.', 'Run sandbox claude from a project folder that does not contain it.');
|
|
44
|
-
}
|
|
45
|
-
for (const name of ['WINDIR', 'ProgramFiles', 'ProgramFiles(x86)', 'ProgramData']) {
|
|
46
|
-
const dir = process.env[name];
|
|
47
|
-
if (dir && isInsideOrEqual(dir, workspace))
|
|
48
|
-
fail('A system folder cannot be the workspace: ' + workspace, 'Run sandbox claude from a project folder.');
|
|
49
|
-
}
|
|
50
|
-
};
|
|
6
|
+
import { allowedAnswer, allowRequests, allowStorePath, applyOverrides, describeOverrides, isTrusted, loosenedRequests, saveAllowed, normalizeOverrides, readLocalConfig, saveTrust, trustStorePath } from './local-config.js';
|
|
7
|
+
import { assertSafeWorkspace } from './safe-paths.js';
|
|
8
|
+
import { dirExists, expandPath, fail, fileExists, plainText } from './util.js';
|
|
51
9
|
/**
|
|
52
10
|
* 'auto' guest workspace: C:\Workspace\<folder name>. Keeping the real folder name means Claude's per-project history
|
|
53
11
|
* and claude-mem's project name match this PC instead of every project being "Workspace".
|
|
@@ -104,7 +62,14 @@ export const resolveVersions = (config, workspace, local, req, hostNodeVersion)
|
|
|
104
62
|
export const resolveRun = async (req, hostNodeVersion = process.version) => {
|
|
105
63
|
const notes = [];
|
|
106
64
|
// Mappings from the user config are relative to that config file; expand them before anything else uses them.
|
|
107
|
-
|
|
65
|
+
const expand = (list) => list.map((p) => expandPath(p, req.loaded.base));
|
|
66
|
+
const projects = req.loaded.config.projects;
|
|
67
|
+
let config = {
|
|
68
|
+
...req.loaded.config,
|
|
69
|
+
mappings: req.loaded.config.mappings.map((m) => ({ ...m, host: expandPath(m.host, req.loaded.base) })),
|
|
70
|
+
projects: { ...projects, roots: expand(projects.roots), exclude: expand(projects.exclude), declinedRoots: expand(projects.declinedRoots) },
|
|
71
|
+
};
|
|
72
|
+
const mirror = config.guestWorkspace === 'mirror';
|
|
108
73
|
const storageRoot = expandPath(config.storage.root, req.loaded.base);
|
|
109
74
|
const workspaceHost = path.resolve(req.workspace ?? req.cwd);
|
|
110
75
|
if (!dirExists(workspaceHost))
|
|
@@ -123,15 +88,32 @@ export const resolveRun = async (req, hostNodeVersion = process.version) => {
|
|
|
123
88
|
if (!trusted && req.ask) {
|
|
124
89
|
console.log('\nFound ' + local.path + ' which is not trusted yet. It would apply:');
|
|
125
90
|
for (const line of summary)
|
|
126
|
-
console.log(' ' + line);
|
|
91
|
+
console.log(' ' + plainText(line));
|
|
127
92
|
trusted = await req.ask('Trust and use this file?');
|
|
128
93
|
}
|
|
129
94
|
if (!trusted)
|
|
130
|
-
fail(local.path + ' has not been approved yet (a repo can ship this file, so it needs your OK). It would apply:\n ' + (summary.join('\n ') || '(no changes)'), 'Review it, then run again in an interactive terminal and answer y, or add --trust-config. To ignore the file: --no-local-config');
|
|
95
|
+
fail(local.path + ' has not been approved yet (a repo can ship this file, so it needs your OK). It would apply:\n ' + (summary.map(plainText).join('\n ') || '(no changes)'), 'Review it, then run again in an interactive terminal and answer y, or add --trust-config. To ignore the file: --no-local-config');
|
|
131
96
|
saveTrust(store, local.path, local.hash);
|
|
132
97
|
notes.push('Trusted ' + local.path + ' (you will only be asked again if the file changes).');
|
|
133
98
|
}
|
|
134
|
-
|
|
99
|
+
// A project may only tighten. What it asks for beyond that is used only if you allowed it for this project (asked
|
|
100
|
+
// once, interactively, never by --trust-config); otherwise it is named here instead of dropped silently.
|
|
101
|
+
const allowStore = allowStorePath(storageRoot);
|
|
102
|
+
const allowed = [];
|
|
103
|
+
for (const ask of loosenedRequests(config, overrides)) {
|
|
104
|
+
let ok = allowedAnswer(allowStore, local.path, ask.key, ask.wanted);
|
|
105
|
+
if (ok === null && req.ask && process.stdin.isTTY) {
|
|
106
|
+
ok = await req.ask('This project asks for ' + ask.key + ' = ' + JSON.stringify(ask.wanted) + ', which is looser than your settings (' + JSON.stringify(ask.yours) + '). Allow it for this project only?');
|
|
107
|
+
saveAllowed(allowStore, local.path, ask.key, ask.wanted, ok);
|
|
108
|
+
}
|
|
109
|
+
if (ok) {
|
|
110
|
+
allowed.push(ask);
|
|
111
|
+
notes.push('Allowed for this project: ' + ask.key + ' = ' + JSON.stringify(ask.wanted) + ' (your answer is kept in ' + allowStore + ').');
|
|
112
|
+
}
|
|
113
|
+
else
|
|
114
|
+
notes.push('The project asks for ' + ask.key + ' = ' + JSON.stringify(ask.wanted) + ', but your settings say ' + JSON.stringify(ask.yours) + ', so it is not used. ' + (ok === false ? 'You said no (kept in ' + allowStore + ').' : 'Start it from an interactive terminal to allow it for this project.') + ' Or set ' + ask.key + ' in your own settings (sandbox, then Settings > All projects).');
|
|
115
|
+
}
|
|
116
|
+
config = applyOverrides(allowRequests(config, allowed), overrides);
|
|
135
117
|
scripts.push(...(overrides.scripts ?? []));
|
|
136
118
|
localConfigPath = local.path;
|
|
137
119
|
notes.push('Using ' + local.path);
|
|
@@ -158,5 +140,6 @@ export const resolveRun = async (req, hostNodeVersion = process.version) => {
|
|
|
158
140
|
fail('Unknown agent "' + harnessName + '".', 'Configured agents: ' + Object.keys(config.harnesses).join(', ') + ' (add more under "harnesses" in your config).');
|
|
159
141
|
const versions = resolveVersions(config, workspaceHost, overrides, req, hostNodeVersion);
|
|
160
142
|
const dataPath = path.join(storageRoot, 'data', config.storage.dataName);
|
|
161
|
-
|
|
143
|
+
// A project file may ask for "mirror" too (it decides only its own path); project roots follow the user's choice.
|
|
144
|
+
return { config, storageRoot, dataPath, workspaceHost, harnessName, scripts, localConfigPath, notes, versions, mirror };
|
|
162
145
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Config, GitAccess } from '../../core/types.js';
|
|
2
|
+
import { type ToolEnv } from '../toolchains/common.js';
|
|
3
|
+
export { appsNeedMesa } from '../../shared/apps.js';
|
|
4
|
+
export interface AppsOptions {
|
|
5
|
+
gitAccess: GitAccess;
|
|
6
|
+
refresh: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** The program in an installed folder (breadth first, bounded: big apps have tens of thousands of files). */
|
|
9
|
+
export declare const findExe: (root: string, exe: string) => string | null;
|
|
10
|
+
export declare const setupApps: (env: ToolEnv, apps: Config["apps"], o: AppsOptions) => Promise<void>;
|