apex-code 0.0.1-alpha.1 → 0.0.1-alpha.11
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/CHANGELOG.md +482 -0
- package/README.md +75 -680
- package/dist/cli/args.d.ts +21 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +119 -15
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +3 -3
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/concurrent-session.d.ts +3 -0
- package/dist/cli/concurrent-session.d.ts.map +1 -0
- package/dist/cli/concurrent-session.js +13 -0
- package/dist/cli/concurrent-session.js.map +1 -0
- package/dist/cli/cost-command.d.ts +19 -0
- package/dist/cli/cost-command.d.ts.map +1 -0
- package/dist/cli/cost-command.js +107 -0
- package/dist/cli/cost-command.js.map +1 -0
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -2
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +99 -16
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +58 -24
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +2 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +28 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +140 -4
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +147 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +440 -123
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +17 -14
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +18 -10
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/checkpoints/git-checkpoints.d.ts +33 -0
- package/dist/core/checkpoints/git-checkpoints.d.ts.map +1 -0
- package/dist/core/checkpoints/git-checkpoints.js +230 -0
- package/dist/core/checkpoints/git-checkpoints.js.map +1 -0
- package/dist/core/checkpoints/session-checkpoints.d.ts +23 -0
- package/dist/core/checkpoints/session-checkpoints.d.ts.map +1 -0
- package/dist/core/checkpoints/session-checkpoints.js +29 -0
- package/dist/core/checkpoints/session-checkpoints.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +41 -32
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/context/deferred-schemas.d.ts +92 -0
- package/dist/core/context/deferred-schemas.d.ts.map +1 -0
- package/dist/core/context/deferred-schemas.js +74 -0
- package/dist/core/context/deferred-schemas.js.map +1 -0
- package/dist/core/context/eviction.d.ts +47 -0
- package/dist/core/context/eviction.d.ts.map +1 -0
- package/dist/core/context/eviction.js +83 -0
- package/dist/core/context/eviction.js.map +1 -0
- package/dist/core/context/pipeline.d.ts +90 -0
- package/dist/core/context/pipeline.d.ts.map +1 -0
- package/dist/core/context/pipeline.js +109 -0
- package/dist/core/context/pipeline.js.map +1 -0
- package/dist/core/credential-failover.d.ts +30 -0
- package/dist/core/credential-failover.d.ts.map +1 -0
- package/dist/core/credential-failover.js +46 -0
- package/dist/core/credential-failover.js.map +1 -0
- package/dist/core/credential-pool.d.ts +60 -0
- package/dist/core/credential-pool.d.ts.map +1 -0
- package/dist/core/credential-pool.js +84 -0
- package/dist/core/credential-pool.js.map +1 -0
- package/dist/core/defaults.d.ts +1 -0
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js +9 -0
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/delegation/agents.d.ts +15 -0
- package/dist/core/delegation/agents.d.ts.map +1 -0
- package/dist/core/delegation/agents.js +55 -0
- package/dist/core/delegation/agents.js.map +1 -0
- package/dist/core/delegation/ceiling.d.ts +29 -0
- package/dist/core/delegation/ceiling.d.ts.map +1 -0
- package/dist/core/delegation/ceiling.js +34 -0
- package/dist/core/delegation/ceiling.js.map +1 -0
- package/dist/core/delegation/runtime.d.ts +94 -0
- package/dist/core/delegation/runtime.d.ts.map +1 -0
- package/dist/core/delegation/runtime.js +117 -0
- package/dist/core/delegation/runtime.js.map +1 -0
- package/dist/core/durable-state/daemon.d.ts +37 -0
- package/dist/core/durable-state/daemon.d.ts.map +1 -0
- package/dist/core/durable-state/daemon.js +62 -0
- package/dist/core/durable-state/daemon.js.map +1 -0
- package/dist/core/durable-state/provenance.d.ts +7 -0
- package/dist/core/durable-state/provenance.d.ts.map +1 -0
- package/dist/core/durable-state/provenance.js +24 -0
- package/dist/core/durable-state/provenance.js.map +1 -0
- package/dist/core/durable-state/sqlite.d.ts +84 -0
- package/dist/core/durable-state/sqlite.d.ts.map +1 -0
- package/dist/core/durable-state/sqlite.js +355 -0
- package/dist/core/durable-state/sqlite.js.map +1 -0
- package/dist/core/environment.d.ts +12 -0
- package/dist/core/environment.d.ts.map +1 -0
- package/dist/core/environment.js +69 -0
- package/dist/core/environment.js.map +1 -0
- package/dist/core/evidence-policy.d.ts +17 -0
- package/dist/core/evidence-policy.d.ts.map +1 -0
- package/dist/core/evidence-policy.js +25 -0
- package/dist/core/evidence-policy.js.map +1 -0
- package/dist/core/evidence.d.ts +16 -0
- package/dist/core/evidence.d.ts.map +1 -0
- package/dist/core/evidence.js +51 -0
- package/dist/core/evidence.js.map +1 -0
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +5 -2
- package/dist/core/exec.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +6 -1
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +122 -49
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +44 -9
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +3 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +1 -2
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -17
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/http-idle-timeout.d.ts +12 -0
- package/dist/core/http-idle-timeout.d.ts.map +1 -0
- package/dist/core/http-idle-timeout.js +27 -0
- package/dist/core/http-idle-timeout.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +38 -13
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +26 -5
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/lsp/client.d.ts +78 -0
- package/dist/core/lsp/client.d.ts.map +1 -0
- package/dist/core/lsp/client.js +494 -0
- package/dist/core/lsp/client.js.map +1 -0
- package/dist/core/lsp/diagnostics.d.ts +47 -0
- package/dist/core/lsp/diagnostics.d.ts.map +1 -0
- package/dist/core/lsp/diagnostics.js +224 -0
- package/dist/core/lsp/diagnostics.js.map +1 -0
- package/dist/core/lsp/pool.d.ts +48 -0
- package/dist/core/lsp/pool.d.ts.map +1 -0
- package/dist/core/lsp/pool.js +150 -0
- package/dist/core/lsp/pool.js.map +1 -0
- package/dist/core/lsp/registry.d.ts +49 -0
- package/dist/core/lsp/registry.d.ts.map +1 -0
- package/dist/core/lsp/registry.js +215 -0
- package/dist/core/lsp/registry.js.map +1 -0
- package/dist/core/lsp/status.d.ts +23 -0
- package/dist/core/lsp/status.d.ts.map +1 -0
- package/dist/core/lsp/status.js +35 -0
- package/dist/core/lsp/status.js.map +1 -0
- package/dist/core/lsp/sync.d.ts +13 -0
- package/dist/core/lsp/sync.d.ts.map +1 -0
- package/dist/core/lsp/sync.js +71 -0
- package/dist/core/lsp/sync.js.map +1 -0
- package/dist/core/mcp/config.d.ts +16 -0
- package/dist/core/mcp/config.d.ts.map +1 -0
- package/dist/core/mcp/config.js +152 -0
- package/dist/core/mcp/config.js.map +1 -0
- package/dist/core/mcp/connector.d.ts +10 -0
- package/dist/core/mcp/connector.d.ts.map +1 -0
- package/dist/core/mcp/connector.js +70 -0
- package/dist/core/mcp/connector.js.map +1 -0
- package/dist/core/mcp/contract.d.ts +19 -0
- package/dist/core/mcp/contract.d.ts.map +1 -0
- package/dist/core/mcp/contract.js +89 -0
- package/dist/core/mcp/contract.js.map +1 -0
- package/dist/core/mcp/mcp-tool.d.ts +32 -0
- package/dist/core/mcp/mcp-tool.d.ts.map +1 -0
- package/dist/core/mcp/mcp-tool.js +165 -0
- package/dist/core/mcp/mcp-tool.js.map +1 -0
- package/dist/core/mcp/metadata-cache.d.ts +29 -0
- package/dist/core/mcp/metadata-cache.d.ts.map +1 -0
- package/dist/core/mcp/metadata-cache.js +99 -0
- package/dist/core/mcp/metadata-cache.js.map +1 -0
- package/dist/core/mcp/runtime.d.ts +18 -0
- package/dist/core/mcp/runtime.d.ts.map +1 -0
- package/dist/core/mcp/runtime.js +35 -0
- package/dist/core/mcp/runtime.js.map +1 -0
- package/dist/core/mcp/schema.d.ts +22 -0
- package/dist/core/mcp/schema.d.ts.map +1 -0
- package/dist/core/mcp/schema.js +20 -0
- package/dist/core/mcp/schema.js.map +1 -0
- package/dist/core/mcp/server-manager.d.ts +43 -0
- package/dist/core/mcp/server-manager.d.ts.map +1 -0
- package/dist/core/mcp/server-manager.js +142 -0
- package/dist/core/mcp/server-manager.js.map +1 -0
- package/dist/core/mcp/types.d.ts +98 -0
- package/dist/core/mcp/types.d.ts.map +1 -0
- package/dist/core/mcp/types.js +8 -0
- package/dist/core/mcp/types.js.map +1 -0
- package/dist/core/model-config.d.ts +18 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +25 -6
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver.d.ts +21 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +73 -8
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +73 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +225 -8
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +2 -1
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/observability/aggregate.d.ts +21 -0
- package/dist/core/observability/aggregate.d.ts.map +1 -0
- package/dist/core/observability/aggregate.js +36 -0
- package/dist/core/observability/aggregate.js.map +1 -0
- package/dist/core/observability/otlp.d.ts +66 -0
- package/dist/core/observability/otlp.d.ts.map +1 -0
- package/dist/core/observability/otlp.js +95 -0
- package/dist/core/observability/otlp.js.map +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +40 -16
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/permissions/gate.d.ts +42 -0
- package/dist/core/permissions/gate.d.ts.map +1 -0
- package/dist/core/permissions/gate.js +72 -0
- package/dist/core/permissions/gate.js.map +1 -0
- package/dist/core/permissions/modes.d.ts +18 -0
- package/dist/core/permissions/modes.d.ts.map +1 -0
- package/dist/core/permissions/modes.js +57 -0
- package/dist/core/permissions/modes.js.map +1 -0
- package/dist/core/permissions/responder.d.ts +30 -0
- package/dist/core/permissions/responder.d.ts.map +1 -0
- package/dist/core/permissions/responder.js +32 -0
- package/dist/core/permissions/responder.js.map +1 -0
- package/dist/core/permissions/rules.d.ts +34 -0
- package/dist/core/permissions/rules.d.ts.map +1 -0
- package/dist/core/permissions/rules.js +74 -0
- package/dist/core/permissions/rules.js.map +1 -0
- package/dist/core/permissions/startup.d.ts +45 -0
- package/dist/core/permissions/startup.d.ts.map +1 -0
- package/dist/core/permissions/startup.js +63 -0
- package/dist/core/permissions/startup.js.map +1 -0
- package/dist/core/permissions/store.d.ts +114 -0
- package/dist/core/permissions/store.d.ts.map +1 -0
- package/dist/core/permissions/store.js +229 -0
- package/dist/core/permissions/store.js.map +1 -0
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js +2 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js +6 -7
- package/dist/core/provider-attribution.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +2 -2
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +22 -17
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sandbox/bwrap-arguments.d.ts +52 -0
- package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
- package/dist/core/sandbox/bwrap-arguments.js +86 -0
- package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
- package/dist/core/sandbox/child-entry.d.ts +2 -0
- package/dist/core/sandbox/child-entry.d.ts.map +1 -0
- package/dist/core/sandbox/child-entry.js +22 -0
- package/dist/core/sandbox/child-entry.js.map +1 -0
- package/dist/core/sandbox/cli-launch.d.ts +88 -0
- package/dist/core/sandbox/cli-launch.d.ts.map +1 -0
- package/dist/core/sandbox/cli-launch.js +272 -0
- package/dist/core/sandbox/cli-launch.js.map +1 -0
- package/dist/core/sandbox/cli-supervisor.d.ts +30 -0
- package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -0
- package/dist/core/sandbox/cli-supervisor.js +123 -0
- package/dist/core/sandbox/cli-supervisor.js.map +1 -0
- package/dist/core/sandbox/default-hosts.d.ts +28 -0
- package/dist/core/sandbox/default-hosts.d.ts.map +1 -0
- package/dist/core/sandbox/default-hosts.js +69 -0
- package/dist/core/sandbox/default-hosts.js.map +1 -0
- package/dist/core/sandbox/full-access.d.ts +28 -0
- package/dist/core/sandbox/full-access.d.ts.map +1 -0
- package/dist/core/sandbox/full-access.js +63 -0
- package/dist/core/sandbox/full-access.js.map +1 -0
- package/dist/core/sandbox/git-identity.d.ts +57 -0
- package/dist/core/sandbox/git-identity.d.ts.map +1 -0
- package/dist/core/sandbox/git-identity.js +78 -0
- package/dist/core/sandbox/git-identity.js.map +1 -0
- package/dist/core/sandbox/host-approval.d.ts +42 -0
- package/dist/core/sandbox/host-approval.d.ts.map +1 -0
- package/dist/core/sandbox/host-approval.js +99 -0
- package/dist/core/sandbox/host-approval.js.map +1 -0
- package/dist/core/sandbox/linux-backend.d.ts +46 -0
- package/dist/core/sandbox/linux-backend.d.ts.map +1 -0
- package/dist/core/sandbox/linux-backend.js +304 -0
- package/dist/core/sandbox/linux-backend.js.map +1 -0
- package/dist/core/sandbox/macos-backend.d.ts +28 -0
- package/dist/core/sandbox/macos-backend.d.ts.map +1 -0
- package/dist/core/sandbox/macos-backend.js +313 -0
- package/dist/core/sandbox/macos-backend.js.map +1 -0
- package/dist/core/sandbox/network-proxy.d.ts +38 -0
- package/dist/core/sandbox/network-proxy.d.ts.map +1 -0
- package/dist/core/sandbox/network-proxy.js +153 -0
- package/dist/core/sandbox/network-proxy.js.map +1 -0
- package/dist/core/sandbox/network-refusal.d.ts +24 -0
- package/dist/core/sandbox/network-refusal.d.ts.map +1 -0
- package/dist/core/sandbox/network-refusal.js +72 -0
- package/dist/core/sandbox/network-refusal.js.map +1 -0
- package/dist/core/sandbox/policy.d.ts +40 -0
- package/dist/core/sandbox/policy.d.ts.map +1 -0
- package/dist/core/sandbox/policy.js +55 -0
- package/dist/core/sandbox/policy.js.map +1 -0
- package/dist/core/sandbox/profiles.d.ts +25 -0
- package/dist/core/sandbox/profiles.d.ts.map +1 -0
- package/dist/core/sandbox/profiles.js +23 -0
- package/dist/core/sandbox/profiles.js.map +1 -0
- package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
- package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/command-client.js +86 -0
- package/dist/core/sandbox/rpc/command-client.js.map +1 -0
- package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
- package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/command-proxy.js +120 -0
- package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
- package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
- package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/credential-client.js +170 -0
- package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
- package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
- package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/credential-proxy.js +287 -0
- package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
- package/dist/core/sandbox/rpc/framing.d.ts +35 -0
- package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/framing.js +114 -0
- package/dist/core/sandbox/rpc/framing.js.map +1 -0
- package/dist/core/sandbox/rpc/git-credential-helper.d.ts +40 -0
- package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/git-credential-helper.js +152 -0
- package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
- package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +48 -0
- package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/git-credential-proxy.js +142 -0
- package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
- package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
- package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
- package/dist/core/sandbox/supervisor-temp.js +21 -0
- package/dist/core/sandbox/supervisor-temp.js.map +1 -0
- package/dist/core/sandbox/supervisor.d.ts +51 -0
- package/dist/core/sandbox/supervisor.d.ts.map +1 -0
- package/dist/core/sandbox/supervisor.js +18 -0
- package/dist/core/sandbox/supervisor.js.map +1 -0
- package/dist/core/sandbox/terminal-handoff.d.ts +45 -0
- package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
- package/dist/core/sandbox/terminal-handoff.js +176 -0
- package/dist/core/sandbox/terminal-handoff.js.map +1 -0
- package/dist/core/sandbox/terminal-size.d.ts +40 -0
- package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
- package/dist/core/sandbox/terminal-size.js +105 -0
- package/dist/core/sandbox/terminal-size.js.map +1 -0
- package/dist/core/sandbox/violations.d.ts +23 -0
- package/dist/core/sandbox/violations.d.ts.map +1 -0
- package/dist/core/sandbox/violations.js +30 -0
- package/dist/core/sandbox/violations.js.map +1 -0
- package/dist/core/sdk.d.ts +32 -41
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +174 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +4 -0
- package/dist/core/session-export.d.ts.map +1 -0
- package/dist/core/session-export.js +32 -0
- package/dist/core/session-export.js.map +1 -0
- package/dist/core/session-lease.d.ts +31 -0
- package/dist/core/session-lease.d.ts.map +1 -0
- package/dist/core/session-lease.js +138 -0
- package/dist/core/session-lease.js.map +1 -0
- package/dist/core/session-manager.d.ts +58 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +92 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-share.d.ts +31 -0
- package/dist/core/session-share.d.ts.map +1 -0
- package/dist/core/session-share.js +45 -0
- package/dist/core/session-share.js.map +1 -0
- package/dist/core/settings-diagnostics.d.ts +9 -0
- package/dist/core/settings-diagnostics.d.ts.map +1 -0
- package/dist/core/settings-diagnostics.js +21 -0
- package/dist/core/settings-diagnostics.js.map +1 -0
- package/dist/core/settings-manager.d.ts +99 -9
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +141 -36
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +19 -7
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +128 -52
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +6 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +2 -2
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +59 -68
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/timings.d.ts +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +3 -2
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/ask-user.d.ts +25 -0
- package/dist/core/tools/ask-user.d.ts.map +1 -0
- package/dist/core/tools/ask-user.js +49 -0
- package/dist/core/tools/ask-user.js.map +1 -0
- package/dist/core/tools/bash-command-segments.d.ts +22 -0
- package/dist/core/tools/bash-command-segments.d.ts.map +1 -0
- package/dist/core/tools/bash-command-segments.js +128 -0
- package/dist/core/tools/bash-command-segments.js.map +1 -0
- package/dist/core/tools/bash.d.ts +40 -4
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +183 -32
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/contract-snapshot.d.ts +58 -0
- package/dist/core/tools/contract-snapshot.d.ts.map +1 -0
- package/dist/core/tools/contract-snapshot.js +51 -0
- package/dist/core/tools/contract-snapshot.js.map +1 -0
- package/dist/core/tools/contract.d.ts +185 -0
- package/dist/core/tools/contract.d.ts.map +1 -0
- package/dist/core/tools/contract.js +50 -0
- package/dist/core/tools/contract.js.map +1 -0
- package/dist/core/tools/delegate.d.ts +38 -0
- package/dist/core/tools/delegate.d.ts.map +1 -0
- package/dist/core/tools/delegate.js +90 -0
- package/dist/core/tools/delegate.js.map +1 -0
- package/dist/core/tools/diagnostics.d.ts +39 -0
- package/dist/core/tools/diagnostics.d.ts.map +1 -0
- package/dist/core/tools/diagnostics.js +62 -0
- package/dist/core/tools/diagnostics.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +0 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +2 -5
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +12 -2
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +61 -10
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts +2 -2
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +13 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +4 -2
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +47 -10
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +60 -6
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +148 -2
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +4 -2
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +17 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/lsp.d.ts +62 -0
- package/dist/core/tools/lsp.d.ts.map +1 -0
- package/dist/core/tools/lsp.js +216 -0
- package/dist/core/tools/lsp.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +1 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-permission.d.ts +18 -0
- package/dist/core/tools/path-permission.d.ts.map +1 -0
- package/dist/core/tools/path-permission.js +28 -0
- package/dist/core/tools/path-permission.js.map +1 -0
- package/dist/core/tools/plan-present.d.ts +27 -0
- package/dist/core/tools/plan-present.d.ts.map +1 -0
- package/dist/core/tools/plan-present.js +55 -0
- package/dist/core/tools/plan-present.js.map +1 -0
- package/dist/core/tools/powershell.d.ts +16 -0
- package/dist/core/tools/powershell.d.ts.map +1 -0
- package/dist/core/tools/powershell.js +39 -0
- package/dist/core/tools/powershell.js.map +1 -0
- package/dist/core/tools/read.d.ts +2 -2
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +14 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/skill-search.d.ts +32 -0
- package/dist/core/tools/skill-search.d.ts.map +1 -0
- package/dist/core/tools/skill-search.js +56 -0
- package/dist/core/tools/skill-search.js.map +1 -0
- package/dist/core/tools/test.d.ts +34 -0
- package/dist/core/tools/test.d.ts.map +1 -0
- package/dist/core/tools/test.js +75 -0
- package/dist/core/tools/test.js.map +1 -0
- package/dist/core/tools/todo-write.d.ts +31 -0
- package/dist/core/tools/todo-write.d.ts.map +1 -0
- package/dist/core/tools/todo-write.js +51 -0
- package/dist/core/tools/todo-write.js.map +1 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +13 -2
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +11 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-schema.d.ts +22 -0
- package/dist/core/tools/tool-schema.d.ts.map +1 -0
- package/dist/core/tools/tool-schema.js +45 -0
- package/dist/core/tools/tool-schema.js.map +1 -0
- package/dist/core/tools/web-fetch.d.ts +26 -0
- package/dist/core/tools/web-fetch.d.ts.map +1 -0
- package/dist/core/tools/web-fetch.js +62 -0
- package/dist/core/tools/web-fetch.js.map +1 -0
- package/dist/core/tools/web-search-exa.d.ts +33 -0
- package/dist/core/tools/web-search-exa.d.ts.map +1 -0
- package/dist/core/tools/web-search-exa.js +128 -0
- package/dist/core/tools/web-search-exa.js.map +1 -0
- package/dist/core/tools/web-search.d.ts +26 -0
- package/dist/core/tools/web-search.d.ts.map +1 -0
- package/dist/core/tools/web-search.js +53 -0
- package/dist/core/tools/web-search.js.map +1 -0
- package/dist/core/tools/write.d.ts +16 -2
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +48 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +2 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/usage-performance-store.d.ts +56 -0
- package/dist/core/usage-performance-store.d.ts.map +1 -0
- package/dist/core/usage-performance-store.js +85 -0
- package/dist/core/usage-performance-store.js.map +1 -0
- package/dist/core/web-search-provider.d.ts +64 -0
- package/dist/core/web-search-provider.d.ts.map +1 -0
- package/dist/core/web-search-provider.js +149 -0
- package/dist/core/web-search-provider.js.map +1 -0
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +2 -0
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -2
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +87 -22
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +6 -5
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +29 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +182 -23
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +7 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +20 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +9 -6
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +72 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +338 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +11 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +24 -6
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts +1 -4
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +17 -41
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
- package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/first-use-hints.js +22 -0
- package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +31 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +205 -24
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +2 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +2 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +31 -9
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +236 -96
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +25 -5
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +226 -58
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.js +165 -0
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
- package/dist/modes/interactive/components/splash-header.d.ts +66 -0
- package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
- package/dist/modes/interactive/components/splash-header.js +180 -0
- package/dist/modes/interactive/components/splash-header.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +74 -17
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +28 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +144 -35
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
- package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-panel.js +130 -0
- package/dist/modes/interactive/components/tool-panel.js.map +1 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +60 -10
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +90 -5
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +729 -206
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +34 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/theme/apex.json +93 -0
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +3 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +25 -11
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +11 -3
- package/dist/modes/interactive/theme/theme.d.ts +14 -3
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +65 -10
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +18 -12
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +22 -5
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +210 -19
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js +2 -1
- package/dist/rpc-entry.js.map +1 -1
- package/dist/testing/replay/metrics.d.ts +24 -0
- package/dist/testing/replay/metrics.d.ts.map +1 -0
- package/dist/testing/replay/metrics.js +35 -0
- package/dist/testing/replay/metrics.js.map +1 -0
- package/dist/testing/replay/recorded-provider.d.ts +10 -0
- package/dist/testing/replay/recorded-provider.d.ts.map +1 -0
- package/dist/testing/replay/recorded-provider.js +108 -0
- package/dist/testing/replay/recorded-provider.js.map +1 -0
- package/dist/testing/replay/runner.d.ts +56 -0
- package/dist/testing/replay/runner.d.ts.map +1 -0
- package/dist/testing/replay/runner.js +406 -0
- package/dist/testing/replay/runner.js.map +1 -0
- package/dist/themes/apex-logo.d.ts +41 -0
- package/dist/themes/apex-logo.d.ts.map +1 -0
- package/dist/themes/apex-logo.js +35 -0
- package/dist/themes/apex-logo.js.map +1 -0
- package/dist/utils/apex-code-user-agent.d.ts +2 -0
- package/dist/utils/apex-code-user-agent.d.ts.map +1 -0
- package/dist/utils/apex-code-user-agent.js +5 -0
- package/dist/utils/apex-code-user-agent.js.map +1 -0
- package/dist/utils/changelog.d.ts +7 -2
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +82 -13
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +2 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/management-http.d.ts +5 -3
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js +14 -10
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/shell.d.ts +3 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +17 -5
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +1 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +60 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/text.d.ts +8 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +70 -2
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +280 -124
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +7 -5
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +27 -14
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts.map +1 -1
- package/dist/utils/windows-self-update.js +1 -1
- package/dist/utils/windows-self-update.js.map +1 -1
- package/docs/compaction.md +41 -24
- package/docs/containerization.md +24 -21
- package/docs/custom-provider.md +15 -12
- package/docs/development.md +11 -11
- package/docs/environment-variables.md +37 -77
- package/docs/extensions.md +68 -54
- package/docs/index.md +12 -24
- package/docs/json.md +18 -11
- package/docs/keybindings.md +18 -12
- package/docs/llama-cpp.md +9 -7
- package/docs/models.md +17 -11
- package/docs/packages.md +47 -43
- package/docs/prompt-templates.md +3 -3
- package/docs/providers.md +10 -10
- package/docs/quickstart.md +49 -32
- package/docs/rpc.md +35 -18
- package/docs/sdk.md +20 -6
- package/docs/security.md +18 -18
- package/docs/session-format.md +9 -9
- package/docs/sessions.md +13 -13
- package/docs/settings.md +83 -16
- package/docs/shell-aliases.md +1 -1
- package/docs/skills.md +66 -15
- package/docs/terminal-setup.md +44 -19
- package/docs/termux.md +4 -4
- package/docs/themes.md +32 -11
- package/docs/tmux.md +4 -4
- package/docs/tui.md +5 -5
- package/docs/usage.md +61 -53
- package/docs/windows.md +24 -2
- package/examples/extensions/border-status-editor.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/git-checkpoint.ts +24 -36
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/notify.ts +3 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/README.md +3 -1
- package/examples/extensions/subagent/agents.ts +40 -9
- package/examples/extensions/subagent/index.ts +27 -4
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +1 -1
- package/examples/sdk/06-extensions.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +435 -452
- package/package.json +17 -18
- package/dist/core/telemetry.d.ts +0 -3
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js +0 -9
- package/dist/core/telemetry.js.map +0 -1
- package/dist/server/create-harness.d.ts +0 -26
- package/dist/server/create-harness.d.ts.map +0 -1
- package/dist/server/create-harness.js +0 -104
- package/dist/server/create-harness.js.map +0 -1
- package/dist/utils/pi-user-agent.d.ts +0 -2
- package/dist/utils/pi-user-agent.d.ts.map +0 -1
- package/dist/utils/pi-user-agent.js +0 -5
- package/dist/utils/pi-user-agent.js.map +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { HostToolBinary } from "../../utils/tools-manager.ts";
|
|
2
|
+
import type { SandboxLaunch } from "./supervisor.ts";
|
|
3
|
+
/**
|
|
4
|
+
* OS containment is the normal startup path for every command that can construct an
|
|
5
|
+
* agent session. Commands that only inspect or maintain host configuration do not
|
|
6
|
+
* create a runtime and therefore remain outside this child boundary.
|
|
7
|
+
*/
|
|
8
|
+
export declare function requiresSandboxedChild(args: readonly string[]): boolean;
|
|
9
|
+
export interface SandboxedCliLaunch extends SandboxLaunch {
|
|
10
|
+
readonly environment: NodeJS.ProcessEnv;
|
|
11
|
+
}
|
|
12
|
+
export declare function getSandboxSessionDirectory(workspace: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Read supervisor policy only from global settings; project settings are untrusted here.
|
|
15
|
+
*
|
|
16
|
+
* The built-in provider hosts are added unless explicitly refused, because a deny-all
|
|
17
|
+
* default made a fresh install unable to reach any model while giving the user no way to
|
|
18
|
+
* learn which host to permit. Configured hosts are additive on top, and
|
|
19
|
+
* `allowDefaultHosts: false` restores the strict behaviour for anyone who wants it.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveSupervisorAllowedHosts(cwd: string, agentDir: string): readonly string[] | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The host's two user-scope skill roots, each present only when it exists on the
|
|
24
|
+
* host. Kept as two named slots rather than one list because
|
|
25
|
+
* `core/package-manager.ts` discovers them in different modes -- root `.md` files
|
|
26
|
+
* count as skills under `agentSkills` ("pi" mode) and are ignored under
|
|
27
|
+
* `agentsHomeSkills` ("agents" mode), per `docs/skills.md` -- and a flat list of 0-2
|
|
28
|
+
* paths cannot tell the child which root a lone survivor was.
|
|
29
|
+
*/
|
|
30
|
+
export interface HostSkillPaths {
|
|
31
|
+
/** Host `<agentDir>/skills`. */
|
|
32
|
+
readonly agentSkills?: string;
|
|
33
|
+
/** Host `<home>/.agents/skills`. */
|
|
34
|
+
readonly agentsHomeSkills?: string;
|
|
35
|
+
}
|
|
36
|
+
/** A candidate skill root that exists but was excluded, and why. */
|
|
37
|
+
export interface HostSkillPathRefusal {
|
|
38
|
+
readonly root: keyof HostSkillPaths;
|
|
39
|
+
readonly path: string;
|
|
40
|
+
readonly reason: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ResolvedHostSkillPaths {
|
|
43
|
+
readonly paths: HostSkillPaths;
|
|
44
|
+
readonly refusals: readonly HostSkillPathRefusal[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the host's user-scope skill directories, before the sandbox exists to hide
|
|
48
|
+
* them. Read only from the runtime environment and the host agent directory --
|
|
49
|
+
* never from project files -- matching ADR 0016's rule that supervisor policy is
|
|
50
|
+
* trust-first. Mirrors `core/package-manager.ts`'s own user-scope roots so the two
|
|
51
|
+
* sides agree on where a skill lives. A candidate that resolves (directly or via a
|
|
52
|
+
* symlink) onto the host home or an ancestor of it is refused rather than mounted --
|
|
53
|
+
* see `isHomeOrAncestorOfHome` -- and reported so the caller can surface a startup
|
|
54
|
+
* diagnostic instead of silently mounting or silently skipping it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveHostSkillPaths(agentDir: string, homeDir: string): ResolvedHostSkillPaths;
|
|
57
|
+
/**
|
|
58
|
+
* Allocate agent-owned state under the sole writable workspace mount. The child does
|
|
59
|
+
* not inherit a host home or a host session/config directory, preventing the sandbox
|
|
60
|
+
* from presenting a write boundary while its own state quietly escapes it.
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildSandboxedCliLaunch(options: {
|
|
63
|
+
workspace: string;
|
|
64
|
+
command: string;
|
|
65
|
+
args: readonly string[];
|
|
66
|
+
environment: NodeJS.ProcessEnv;
|
|
67
|
+
allowedHosts?: readonly string[];
|
|
68
|
+
additionalWritableRoots?: readonly string[];
|
|
69
|
+
readOnlyPaths?: readonly string[];
|
|
70
|
+
authPath?: string;
|
|
71
|
+
/**
|
|
72
|
+
* A synthesized two-key git config, projected read-only so the child can author a
|
|
73
|
+
* commit as the user. Absent when the host had no global identity to resolve.
|
|
74
|
+
*/
|
|
75
|
+
gitConfigPath?: string;
|
|
76
|
+
toolBinaries?: readonly HostToolBinary[];
|
|
77
|
+
/**
|
|
78
|
+
* Host user-scope skill directories, pre-filtered by the caller to those that
|
|
79
|
+
* exist and pass the host-home escape check (SKILL.4). Mounted read-only at their
|
|
80
|
+
* original host location -- Seatbelt cannot remap a path, so this must hold for
|
|
81
|
+
* both backends -- and named to the child via `APEX_CODE_SKILL_PATH_*` so its
|
|
82
|
+
* discovery can find them under the sandbox's own repointed `HOME`/agent dir.
|
|
83
|
+
*/
|
|
84
|
+
skillPaths?: HostSkillPaths;
|
|
85
|
+
/** The supervisor-owned credential write channel, when one was opened. */
|
|
86
|
+
credentialChannel?: SandboxLaunch["credentialChannel"];
|
|
87
|
+
}): SandboxedCliLaunch;
|
|
88
|
+
//# sourceMappingURL=cli-launch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-launch.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/cli-launch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAInE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAKrD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAKvE;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;CACxC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAW1G;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,oEAAoE;AACpE,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,cAAc,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACnD;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAY/F;AA0GD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACzC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CACvD,GAAG,kBAAkB,CAiErB","sourcesContent":["import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from \"node:fs\";\nimport { join, sep } from \"node:path\";\nimport type { HostToolBinary } from \"../../utils/tools-manager.ts\";\nimport { SettingsManager } from \"../settings-manager.ts\";\nimport { resolveWebSearchHost } from \"../web-search-provider.ts\";\nimport { resolveDefaultAllowedHosts } from \"./default-hosts.ts\";\nimport type { SandboxLaunch } from \"./supervisor.ts\";\n\nconst NON_SESSION_COMMANDS = new Set([\"auth\", \"config\", \"install\", \"remove\", \"uninstall\", \"update\", \"list\"]);\nconst METADATA_FLAGS = new Set([\"--version\", \"-v\", \"--export\", \"--list-models\"]);\n\n/**\n * OS containment is the normal startup path for every command that can construct an\n * agent session. Commands that only inspect or maintain host configuration do not\n * create a runtime and therefore remain outside this child boundary.\n */\nexport function requiresSandboxedChild(args: readonly string[]): boolean {\n\tif (NON_SESSION_COMMANDS.has(args[0] ?? \"\")) return false;\n\tif (args.some((argument) => METADATA_FLAGS.has(argument))) return false;\n\tif (args.includes(\"--help\") || args.includes(\"-h\")) return false;\n\treturn true;\n}\n\nexport interface SandboxedCliLaunch extends SandboxLaunch {\n\treadonly environment: NodeJS.ProcessEnv;\n}\n\nexport function getSandboxSessionDirectory(workspace: string): string {\n\treturn join(workspace, \".apex-code\", \"sandbox-sessions\");\n}\n\n/**\n * Read supervisor policy only from global settings; project settings are untrusted here.\n *\n * The built-in provider hosts are added unless explicitly refused, because a deny-all\n * default made a fresh install unable to reach any model while giving the user no way to\n * learn which host to permit. Configured hosts are additive on top, and\n * `allowDefaultHosts: false` restores the strict behaviour for anyone who wants it.\n */\nexport function resolveSupervisorAllowedHosts(cwd: string, agentDir: string): readonly string[] | undefined {\n\tconst settings = SettingsManager.create(cwd, agentDir, { projectTrusted: false });\n\tconst network = settings.getNetworkSettings();\n\tconst configured = network?.allowedHosts ?? [];\n\tif (network?.allowDefaultHosts === false) return configured;\n\t// The configured `web_search` backend's host, added only when a credential for it\n\t// is present. Without this the tool would be configured and still unreachable,\n\t// which reads as a broken search rather than a missing allowlist entry. Nothing is\n\t// opened for a user who never set the key.\n\tconst webSearchHost = resolveWebSearchHost(settings.getWebSearchSettings());\n\treturn [...new Set([...resolveDefaultAllowedHosts(), ...configured, ...(webSearchHost ? [webSearchHost] : [])])];\n}\n\n/**\n * The host's two user-scope skill roots, each present only when it exists on the\n * host. Kept as two named slots rather than one list because\n * `core/package-manager.ts` discovers them in different modes -- root `.md` files\n * count as skills under `agentSkills` (\"pi\" mode) and are ignored under\n * `agentsHomeSkills` (\"agents\" mode), per `docs/skills.md` -- and a flat list of 0-2\n * paths cannot tell the child which root a lone survivor was.\n */\nexport interface HostSkillPaths {\n\t/** Host `<agentDir>/skills`. */\n\treadonly agentSkills?: string;\n\t/** Host `<home>/.agents/skills`. */\n\treadonly agentsHomeSkills?: string;\n}\n\n/** A candidate skill root that exists but was excluded, and why. */\nexport interface HostSkillPathRefusal {\n\treadonly root: keyof HostSkillPaths;\n\treadonly path: string;\n\treadonly reason: string;\n}\n\nexport interface ResolvedHostSkillPaths {\n\treadonly paths: HostSkillPaths;\n\treadonly refusals: readonly HostSkillPathRefusal[];\n}\n\n/**\n * True when `candidate` is the host home directory itself, or an ancestor of it.\n * Both paths must already be resolved (`realpathSync`), so a symlink can't disguise\n * either side. Mounting such a candidate read-only would re-expose the entire home\n * tree the sandbox's `--tmpfs /home` (Linux) / `(deny file-read* USER_HOME)` (macOS)\n * deliberately hides -- SSH keys, cloud credentials, other projects -- not just a\n * skills subtree.\n */\nfunction isHomeOrAncestorOfHome(candidate: string, home: string): boolean {\n\tif (candidate === home) return true;\n\tconst prefix = candidate.endsWith(sep) ? candidate : candidate + sep;\n\treturn home.startsWith(prefix);\n}\n\n/** Resolve one candidate root: absent, refused (symlinked onto the host home), or usable. */\nfunction resolveHostSkillRoot(\n\troot: keyof HostSkillPaths,\n\tcandidate: string,\n\thomeDir: string,\n): { path?: string; refusal?: HostSkillPathRefusal } {\n\tif (!existsSync(candidate)) return {};\n\tlet realCandidate: string;\n\tlet realHome: string;\n\ttry {\n\t\trealCandidate = realpathSync(candidate);\n\t\trealHome = realpathSync(homeDir);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { refusal: { root, path: candidate, reason: `could not resolve real path: ${message}` } };\n\t}\n\tif (isHomeOrAncestorOfHome(realCandidate, realHome)) {\n\t\treturn {\n\t\t\trefusal: {\n\t\t\t\troot,\n\t\t\t\tpath: candidate,\n\t\t\t\treason: \"resolves to the host home directory or an ancestor of it\",\n\t\t\t},\n\t\t};\n\t}\n\treturn { path: candidate };\n}\n\n/**\n * Resolve the host's user-scope skill directories, before the sandbox exists to hide\n * them. Read only from the runtime environment and the host agent directory --\n * never from project files -- matching ADR 0016's rule that supervisor policy is\n * trust-first. Mirrors `core/package-manager.ts`'s own user-scope roots so the two\n * sides agree on where a skill lives. A candidate that resolves (directly or via a\n * symlink) onto the host home or an ancestor of it is refused rather than mounted --\n * see `isHomeOrAncestorOfHome` -- and reported so the caller can surface a startup\n * diagnostic instead of silently mounting or silently skipping it.\n */\nexport function resolveHostSkillPaths(agentDir: string, homeDir: string): ResolvedHostSkillPaths {\n\tconst agentSkills = resolveHostSkillRoot(\"agentSkills\", join(agentDir, \"skills\"), homeDir);\n\tconst agentsHomeSkills = resolveHostSkillRoot(\"agentsHomeSkills\", join(homeDir, \".agents\", \"skills\"), homeDir);\n\treturn {\n\t\tpaths: {\n\t\t\t...(agentSkills.path ? { agentSkills: agentSkills.path } : {}),\n\t\t\t...(agentsHomeSkills.path ? { agentsHomeSkills: agentsHomeSkills.path } : {}),\n\t\t},\n\t\trefusals: [agentSkills.refusal, agentsHomeSkills.refusal].filter(\n\t\t\t(refusal): refusal is HostSkillPathRefusal => refusal !== undefined,\n\t\t),\n\t};\n}\n\nconst SAFE_CHILD_ENVIRONMENT_KEYS = new Set([\n\t\"PATH\",\n\t\"LANG\",\n\t\"LC_ALL\",\n\t\"LC_CTYPE\",\n\t\"TERM\",\n\t\"COLORTERM\",\n\t\"NO_COLOR\",\n\t\"FORCE_COLOR\",\n\t\"TSX_TSCONFIG_PATH\",\n\t\"APEX_CODE_OFFLINE\",\n\t\"APEX_CODE_SKIP_VERSION_CHECK\",\n\t\"APEX_CODE_EXPERIMENTAL\",\n\t\"APEX_CODE_STARTUP_BENCHMARK\",\n\t\"APEX_CODE_TIMING\",\n\t\"APEX_CODE_CLEAR_ON_SHRINK\",\n\t\"APEX_CODE_HARDWARE_CURSOR\",\n\t\"APEX_CODE_MODEL_CATALOG_URL\",\n\t\"APEX_CODE_SHARE_VIEWER_URL\",\n\t\"VISUAL\",\n\t\"EDITOR\",\n]);\n\n// Provider API keys are explicit credential inputs, unlike arbitrary ambient variables.\n// Keep this list in sync with the documented provider environment-variable reference.\nconst SAFE_PROVIDER_CREDENTIAL_KEYS = new Set([\n\t\"ANTHROPIC_API_KEY\",\n\t\"ANTHROPIC_AUTH_TOKEN\",\n\t\"ANTHROPIC_OAUTH_TOKEN\",\n\t\"ANT_LING_API_KEY\",\n\t\"OPENAI_API_KEY\",\n\t\"AZURE_OPENAI_API_KEY\",\n\t\"AZURE_OPENAI_BASE_URL\",\n\t\"AZURE_OPENAI_RESOURCE_NAME\",\n\t\"AZURE_OPENAI_API_VERSION\",\n\t\"AZURE_OPENAI_DEPLOYMENT_NAME_MAP\",\n\t\"DEEPSEEK_API_KEY\",\n\t\"NVIDIA_API_KEY\",\n\t\"GEMINI_API_KEY\",\n\t\"GROQ_API_KEY\",\n\t\"CEREBRAS_API_KEY\",\n\t\"XAI_API_KEY\",\n\t\"FIREWORKS_API_KEY\",\n\t\"TOGETHER_API_KEY\",\n\t\"BASETEN_API_KEY\",\n\t\"OPENROUTER_API_KEY\",\n\t\"AI_GATEWAY_API_KEY\",\n\t\"ZAI_API_KEY\",\n\t\"ZAI_CODING_CN_API_KEY\",\n\t\"MISTRAL_API_KEY\",\n\t\"MINIMAX_API_KEY\",\n\t\"MOONSHOT_API_KEY\",\n\t\"OPENCODE_API_KEY\",\n\t\"KIMI_API_KEY\",\n\t\"CLOUDFLARE_API_KEY\",\n\t\"CLOUDFLARE_ACCOUNT_ID\",\n\t\"CLOUDFLARE_GATEWAY_ID\",\n\t\"QWEN_TOKEN_PLAN_API_KEY\",\n\t\"QWEN_TOKEN_PLAN_CN_API_KEY\",\n\t\"XIAOMI_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\"AWS_PROFILE\",\n\t\"AWS_ACCESS_KEY_ID\",\n\t\"AWS_SECRET_ACCESS_KEY\",\n\t\"AWS_BEARER_TOKEN_BEDROCK\",\n\t\"AWS_REGION\",\n]);\n\n// Credentials for tools rather than model providers. Separate from the provider set\n// above so the provider list stays a mirror of the documented provider reference.\nconst SAFE_TOOL_CREDENTIAL_KEYS = new Set([\"EXA_API_KEY\"]);\n\nfunction buildChildEnvironment(environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n\treturn Object.fromEntries(\n\t\tObject.entries(environment).filter(\n\t\t\t([key]) =>\n\t\t\t\tSAFE_CHILD_ENVIRONMENT_KEYS.has(key) ||\n\t\t\t\tSAFE_PROVIDER_CREDENTIAL_KEYS.has(key) ||\n\t\t\t\tSAFE_TOOL_CREDENTIAL_KEYS.has(key),\n\t\t),\n\t);\n}\n\n/**\n * Drop empty files left in the child's tools directory by a previous launch.\n *\n * A projected tool is bind-mounted over a file there, and bwrap materialises that\n * mountpoint as an empty file on the host which outlives the namespace. If the host\n * tool later disappears, nothing is projected over the stub and the child would\n * otherwise find a 0-byte file where its binary should be. A real downloaded binary\n * is never empty, so size is a safe discriminator.\n */\nfunction clearStaleToolMountpoints(toolsDirectory: string): void {\n\tfor (const entry of readdirSync(toolsDirectory, { withFileTypes: true })) {\n\t\tif (!entry.isFile()) continue;\n\t\tconst entryPath = join(toolsDirectory, entry.name);\n\t\tif (statSync(entryPath).size === 0) {\n\t\t\trmSync(entryPath, { force: true });\n\t\t}\n\t}\n}\n\n/**\n * Allocate agent-owned state under the sole writable workspace mount. The child does\n * not inherit a host home or a host session/config directory, preventing the sandbox\n * from presenting a write boundary while its own state quietly escapes it.\n */\nexport function buildSandboxedCliLaunch(options: {\n\tworkspace: string;\n\tcommand: string;\n\targs: readonly string[];\n\tenvironment: NodeJS.ProcessEnv;\n\tallowedHosts?: readonly string[];\n\tadditionalWritableRoots?: readonly string[];\n\treadOnlyPaths?: readonly string[];\n\tauthPath?: string;\n\t/**\n\t * A synthesized two-key git config, projected read-only so the child can author a\n\t * commit as the user. Absent when the host had no global identity to resolve.\n\t */\n\tgitConfigPath?: string;\n\ttoolBinaries?: readonly HostToolBinary[];\n\t/**\n\t * Host user-scope skill directories, pre-filtered by the caller to those that\n\t * exist and pass the host-home escape check (SKILL.4). Mounted read-only at their\n\t * original host location -- Seatbelt cannot remap a path, so this must hold for\n\t * both backends -- and named to the child via `APEX_CODE_SKILL_PATH_*` so its\n\t * discovery can find them under the sandbox's own repointed `HOME`/agent dir.\n\t */\n\tskillPaths?: HostSkillPaths;\n\t/** The supervisor-owned credential write channel, when one was opened. */\n\tcredentialChannel?: SandboxLaunch[\"credentialChannel\"];\n}): SandboxedCliLaunch {\n\tconst stateDirectory = join(options.workspace, \".apex-code\", \"sandbox-state\");\n\tconst agentDirectory = join(options.workspace, \".apex-code\", \"sandbox-agent\");\n\tconst sessionDirectory = getSandboxSessionDirectory(options.workspace);\n\t// Mirrors getBinDir() as the child will compute it from APEX_CODE_CODING_AGENT_DIR,\n\t// so a projected tool lands exactly where the child's own lookup already checks.\n\tconst toolsDirectory = join(agentDirectory, \"bin\");\n\tconst xdgDirectories = {\n\t\tXDG_CONFIG_HOME: join(stateDirectory, \"config\"),\n\t\tXDG_CACHE_HOME: join(stateDirectory, \"cache\"),\n\t\tXDG_DATA_HOME: join(stateDirectory, \"data\"),\n\t\tXDG_STATE_HOME: join(stateDirectory, \"state\"),\n\t};\n\tfor (const directory of [\n\t\tstateDirectory,\n\t\tagentDirectory,\n\t\tsessionDirectory,\n\t\ttoolsDirectory,\n\t\t...Object.values(xdgDirectories),\n\t]) {\n\t\tmkdirSync(directory, { recursive: true });\n\t}\n\tclearStaleToolMountpoints(toolsDirectory);\n\tconst childEnvironment = buildChildEnvironment(options.environment);\n\tconst { agentSkills, agentsHomeSkills } = options.skillPaths ?? {};\n\tconst skillMountPaths = [agentSkills, agentsHomeSkills].filter((path): path is string => path !== undefined);\n\tconst readOnlyPaths = [...(options.readOnlyPaths ?? []), ...skillMountPaths];\n\tconst readOnlyFiles = [options.authPath, options.gitConfigPath].filter((path): path is string => path !== undefined);\n\tconst readOnlyBinaries = (options.toolBinaries ?? []).map((binary) => ({\n\t\tsource: binary.path,\n\t\tdestination: join(toolsDirectory, binary.name),\n\t}));\n\treturn {\n\t\tcommand: options.command,\n\t\targs: [...options.args],\n\t\tpolicy: {\n\t\t\tworkspace: options.workspace,\n\t\t\tallowedHosts: options.allowedHosts ?? [],\n\t\t\tadditionalWritableRoots: options.additionalWritableRoots ?? [],\n\t\t},\n\t\treadOnlyPaths,\n\t\treadOnlyFiles,\n\t\treadOnlyBinaries,\n\t\t// Travels on the launch contract so the platform backend projects the socket;\n\t\t// the environment entry above is what tells the child where to find it.\n\t\t...(options.credentialChannel ? { credentialChannel: options.credentialChannel } : {}),\n\t\tenvironment: {\n\t\t\t...childEnvironment,\n\t\t\t...(options.authPath ? { APEX_CODE_AUTH_PATH: options.authPath } : {}),\n\t\t\t...(options.credentialChannel\n\t\t\t\t? { APEX_CREDENTIAL_PROXY_PATH: options.credentialChannel.childSocketPath }\n\t\t\t\t: {}),\n\t\t\t// After childEnvironment: these come only from the supervisor's own\n\t\t\t// resolution, never from the invoking shell, so their value always wins over\n\t\t\t// anything of the same name that childEnvironment's allowlist let through.\n\t\t\t...(options.gitConfigPath ? { GIT_CONFIG_GLOBAL: options.gitConfigPath } : {}),\n\t\t\t...(agentSkills ? { APEX_CODE_SKILL_PATH_AGENT: agentSkills } : {}),\n\t\t\t...(agentsHomeSkills ? { APEX_CODE_SKILL_PATH_AGENTS_HOME: agentsHomeSkills } : {}),\n\t\t\tAPEX_CODE_CODING_AGENT_DIR: agentDirectory,\n\t\t\tAPEX_CODE_CODING_AGENT_SESSION_DIR: sessionDirectory,\n\t\t\tHOME: stateDirectory,\n\t\t\tTMPDIR: stateDirectory,\n\t\t\t...xdgDirectories,\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
2
|
+
import { join, sep } from "node:path";
|
|
3
|
+
import { SettingsManager } from "../settings-manager.js";
|
|
4
|
+
import { resolveWebSearchHost } from "../web-search-provider.js";
|
|
5
|
+
import { resolveDefaultAllowedHosts } from "./default-hosts.js";
|
|
6
|
+
const NON_SESSION_COMMANDS = new Set(["auth", "config", "install", "remove", "uninstall", "update", "list"]);
|
|
7
|
+
const METADATA_FLAGS = new Set(["--version", "-v", "--export", "--list-models"]);
|
|
8
|
+
/**
|
|
9
|
+
* OS containment is the normal startup path for every command that can construct an
|
|
10
|
+
* agent session. Commands that only inspect or maintain host configuration do not
|
|
11
|
+
* create a runtime and therefore remain outside this child boundary.
|
|
12
|
+
*/
|
|
13
|
+
export function requiresSandboxedChild(args) {
|
|
14
|
+
if (NON_SESSION_COMMANDS.has(args[0] ?? ""))
|
|
15
|
+
return false;
|
|
16
|
+
if (args.some((argument) => METADATA_FLAGS.has(argument)))
|
|
17
|
+
return false;
|
|
18
|
+
if (args.includes("--help") || args.includes("-h"))
|
|
19
|
+
return false;
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
export function getSandboxSessionDirectory(workspace) {
|
|
23
|
+
return join(workspace, ".apex-code", "sandbox-sessions");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read supervisor policy only from global settings; project settings are untrusted here.
|
|
27
|
+
*
|
|
28
|
+
* The built-in provider hosts are added unless explicitly refused, because a deny-all
|
|
29
|
+
* default made a fresh install unable to reach any model while giving the user no way to
|
|
30
|
+
* learn which host to permit. Configured hosts are additive on top, and
|
|
31
|
+
* `allowDefaultHosts: false` restores the strict behaviour for anyone who wants it.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveSupervisorAllowedHosts(cwd, agentDir) {
|
|
34
|
+
const settings = SettingsManager.create(cwd, agentDir, { projectTrusted: false });
|
|
35
|
+
const network = settings.getNetworkSettings();
|
|
36
|
+
const configured = network?.allowedHosts ?? [];
|
|
37
|
+
if (network?.allowDefaultHosts === false)
|
|
38
|
+
return configured;
|
|
39
|
+
// The configured `web_search` backend's host, added only when a credential for it
|
|
40
|
+
// is present. Without this the tool would be configured and still unreachable,
|
|
41
|
+
// which reads as a broken search rather than a missing allowlist entry. Nothing is
|
|
42
|
+
// opened for a user who never set the key.
|
|
43
|
+
const webSearchHost = resolveWebSearchHost(settings.getWebSearchSettings());
|
|
44
|
+
return [...new Set([...resolveDefaultAllowedHosts(), ...configured, ...(webSearchHost ? [webSearchHost] : [])])];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* True when `candidate` is the host home directory itself, or an ancestor of it.
|
|
48
|
+
* Both paths must already be resolved (`realpathSync`), so a symlink can't disguise
|
|
49
|
+
* either side. Mounting such a candidate read-only would re-expose the entire home
|
|
50
|
+
* tree the sandbox's `--tmpfs /home` (Linux) / `(deny file-read* USER_HOME)` (macOS)
|
|
51
|
+
* deliberately hides -- SSH keys, cloud credentials, other projects -- not just a
|
|
52
|
+
* skills subtree.
|
|
53
|
+
*/
|
|
54
|
+
function isHomeOrAncestorOfHome(candidate, home) {
|
|
55
|
+
if (candidate === home)
|
|
56
|
+
return true;
|
|
57
|
+
const prefix = candidate.endsWith(sep) ? candidate : candidate + sep;
|
|
58
|
+
return home.startsWith(prefix);
|
|
59
|
+
}
|
|
60
|
+
/** Resolve one candidate root: absent, refused (symlinked onto the host home), or usable. */
|
|
61
|
+
function resolveHostSkillRoot(root, candidate, homeDir) {
|
|
62
|
+
if (!existsSync(candidate))
|
|
63
|
+
return {};
|
|
64
|
+
let realCandidate;
|
|
65
|
+
let realHome;
|
|
66
|
+
try {
|
|
67
|
+
realCandidate = realpathSync(candidate);
|
|
68
|
+
realHome = realpathSync(homeDir);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
return { refusal: { root, path: candidate, reason: `could not resolve real path: ${message}` } };
|
|
73
|
+
}
|
|
74
|
+
if (isHomeOrAncestorOfHome(realCandidate, realHome)) {
|
|
75
|
+
return {
|
|
76
|
+
refusal: {
|
|
77
|
+
root,
|
|
78
|
+
path: candidate,
|
|
79
|
+
reason: "resolves to the host home directory or an ancestor of it",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { path: candidate };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the host's user-scope skill directories, before the sandbox exists to hide
|
|
87
|
+
* them. Read only from the runtime environment and the host agent directory --
|
|
88
|
+
* never from project files -- matching ADR 0016's rule that supervisor policy is
|
|
89
|
+
* trust-first. Mirrors `core/package-manager.ts`'s own user-scope roots so the two
|
|
90
|
+
* sides agree on where a skill lives. A candidate that resolves (directly or via a
|
|
91
|
+
* symlink) onto the host home or an ancestor of it is refused rather than mounted --
|
|
92
|
+
* see `isHomeOrAncestorOfHome` -- and reported so the caller can surface a startup
|
|
93
|
+
* diagnostic instead of silently mounting or silently skipping it.
|
|
94
|
+
*/
|
|
95
|
+
export function resolveHostSkillPaths(agentDir, homeDir) {
|
|
96
|
+
const agentSkills = resolveHostSkillRoot("agentSkills", join(agentDir, "skills"), homeDir);
|
|
97
|
+
const agentsHomeSkills = resolveHostSkillRoot("agentsHomeSkills", join(homeDir, ".agents", "skills"), homeDir);
|
|
98
|
+
return {
|
|
99
|
+
paths: {
|
|
100
|
+
...(agentSkills.path ? { agentSkills: agentSkills.path } : {}),
|
|
101
|
+
...(agentsHomeSkills.path ? { agentsHomeSkills: agentsHomeSkills.path } : {}),
|
|
102
|
+
},
|
|
103
|
+
refusals: [agentSkills.refusal, agentsHomeSkills.refusal].filter((refusal) => refusal !== undefined),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const SAFE_CHILD_ENVIRONMENT_KEYS = new Set([
|
|
107
|
+
"PATH",
|
|
108
|
+
"LANG",
|
|
109
|
+
"LC_ALL",
|
|
110
|
+
"LC_CTYPE",
|
|
111
|
+
"TERM",
|
|
112
|
+
"COLORTERM",
|
|
113
|
+
"NO_COLOR",
|
|
114
|
+
"FORCE_COLOR",
|
|
115
|
+
"TSX_TSCONFIG_PATH",
|
|
116
|
+
"APEX_CODE_OFFLINE",
|
|
117
|
+
"APEX_CODE_SKIP_VERSION_CHECK",
|
|
118
|
+
"APEX_CODE_EXPERIMENTAL",
|
|
119
|
+
"APEX_CODE_STARTUP_BENCHMARK",
|
|
120
|
+
"APEX_CODE_TIMING",
|
|
121
|
+
"APEX_CODE_CLEAR_ON_SHRINK",
|
|
122
|
+
"APEX_CODE_HARDWARE_CURSOR",
|
|
123
|
+
"APEX_CODE_MODEL_CATALOG_URL",
|
|
124
|
+
"APEX_CODE_SHARE_VIEWER_URL",
|
|
125
|
+
"VISUAL",
|
|
126
|
+
"EDITOR",
|
|
127
|
+
]);
|
|
128
|
+
// Provider API keys are explicit credential inputs, unlike arbitrary ambient variables.
|
|
129
|
+
// Keep this list in sync with the documented provider environment-variable reference.
|
|
130
|
+
const SAFE_PROVIDER_CREDENTIAL_KEYS = new Set([
|
|
131
|
+
"ANTHROPIC_API_KEY",
|
|
132
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
133
|
+
"ANTHROPIC_OAUTH_TOKEN",
|
|
134
|
+
"ANT_LING_API_KEY",
|
|
135
|
+
"OPENAI_API_KEY",
|
|
136
|
+
"AZURE_OPENAI_API_KEY",
|
|
137
|
+
"AZURE_OPENAI_BASE_URL",
|
|
138
|
+
"AZURE_OPENAI_RESOURCE_NAME",
|
|
139
|
+
"AZURE_OPENAI_API_VERSION",
|
|
140
|
+
"AZURE_OPENAI_DEPLOYMENT_NAME_MAP",
|
|
141
|
+
"DEEPSEEK_API_KEY",
|
|
142
|
+
"NVIDIA_API_KEY",
|
|
143
|
+
"GEMINI_API_KEY",
|
|
144
|
+
"GROQ_API_KEY",
|
|
145
|
+
"CEREBRAS_API_KEY",
|
|
146
|
+
"XAI_API_KEY",
|
|
147
|
+
"FIREWORKS_API_KEY",
|
|
148
|
+
"TOGETHER_API_KEY",
|
|
149
|
+
"BASETEN_API_KEY",
|
|
150
|
+
"OPENROUTER_API_KEY",
|
|
151
|
+
"AI_GATEWAY_API_KEY",
|
|
152
|
+
"ZAI_API_KEY",
|
|
153
|
+
"ZAI_CODING_CN_API_KEY",
|
|
154
|
+
"MISTRAL_API_KEY",
|
|
155
|
+
"MINIMAX_API_KEY",
|
|
156
|
+
"MOONSHOT_API_KEY",
|
|
157
|
+
"OPENCODE_API_KEY",
|
|
158
|
+
"KIMI_API_KEY",
|
|
159
|
+
"CLOUDFLARE_API_KEY",
|
|
160
|
+
"CLOUDFLARE_ACCOUNT_ID",
|
|
161
|
+
"CLOUDFLARE_GATEWAY_ID",
|
|
162
|
+
"QWEN_TOKEN_PLAN_API_KEY",
|
|
163
|
+
"QWEN_TOKEN_PLAN_CN_API_KEY",
|
|
164
|
+
"XIAOMI_API_KEY",
|
|
165
|
+
"XIAOMI_TOKEN_PLAN_CN_API_KEY",
|
|
166
|
+
"XIAOMI_TOKEN_PLAN_AMS_API_KEY",
|
|
167
|
+
"XIAOMI_TOKEN_PLAN_SGP_API_KEY",
|
|
168
|
+
"AWS_PROFILE",
|
|
169
|
+
"AWS_ACCESS_KEY_ID",
|
|
170
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
171
|
+
"AWS_BEARER_TOKEN_BEDROCK",
|
|
172
|
+
"AWS_REGION",
|
|
173
|
+
]);
|
|
174
|
+
// Credentials for tools rather than model providers. Separate from the provider set
|
|
175
|
+
// above so the provider list stays a mirror of the documented provider reference.
|
|
176
|
+
const SAFE_TOOL_CREDENTIAL_KEYS = new Set(["EXA_API_KEY"]);
|
|
177
|
+
function buildChildEnvironment(environment) {
|
|
178
|
+
return Object.fromEntries(Object.entries(environment).filter(([key]) => SAFE_CHILD_ENVIRONMENT_KEYS.has(key) ||
|
|
179
|
+
SAFE_PROVIDER_CREDENTIAL_KEYS.has(key) ||
|
|
180
|
+
SAFE_TOOL_CREDENTIAL_KEYS.has(key)));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Drop empty files left in the child's tools directory by a previous launch.
|
|
184
|
+
*
|
|
185
|
+
* A projected tool is bind-mounted over a file there, and bwrap materialises that
|
|
186
|
+
* mountpoint as an empty file on the host which outlives the namespace. If the host
|
|
187
|
+
* tool later disappears, nothing is projected over the stub and the child would
|
|
188
|
+
* otherwise find a 0-byte file where its binary should be. A real downloaded binary
|
|
189
|
+
* is never empty, so size is a safe discriminator.
|
|
190
|
+
*/
|
|
191
|
+
function clearStaleToolMountpoints(toolsDirectory) {
|
|
192
|
+
for (const entry of readdirSync(toolsDirectory, { withFileTypes: true })) {
|
|
193
|
+
if (!entry.isFile())
|
|
194
|
+
continue;
|
|
195
|
+
const entryPath = join(toolsDirectory, entry.name);
|
|
196
|
+
if (statSync(entryPath).size === 0) {
|
|
197
|
+
rmSync(entryPath, { force: true });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Allocate agent-owned state under the sole writable workspace mount. The child does
|
|
203
|
+
* not inherit a host home or a host session/config directory, preventing the sandbox
|
|
204
|
+
* from presenting a write boundary while its own state quietly escapes it.
|
|
205
|
+
*/
|
|
206
|
+
export function buildSandboxedCliLaunch(options) {
|
|
207
|
+
const stateDirectory = join(options.workspace, ".apex-code", "sandbox-state");
|
|
208
|
+
const agentDirectory = join(options.workspace, ".apex-code", "sandbox-agent");
|
|
209
|
+
const sessionDirectory = getSandboxSessionDirectory(options.workspace);
|
|
210
|
+
// Mirrors getBinDir() as the child will compute it from APEX_CODE_CODING_AGENT_DIR,
|
|
211
|
+
// so a projected tool lands exactly where the child's own lookup already checks.
|
|
212
|
+
const toolsDirectory = join(agentDirectory, "bin");
|
|
213
|
+
const xdgDirectories = {
|
|
214
|
+
XDG_CONFIG_HOME: join(stateDirectory, "config"),
|
|
215
|
+
XDG_CACHE_HOME: join(stateDirectory, "cache"),
|
|
216
|
+
XDG_DATA_HOME: join(stateDirectory, "data"),
|
|
217
|
+
XDG_STATE_HOME: join(stateDirectory, "state"),
|
|
218
|
+
};
|
|
219
|
+
for (const directory of [
|
|
220
|
+
stateDirectory,
|
|
221
|
+
agentDirectory,
|
|
222
|
+
sessionDirectory,
|
|
223
|
+
toolsDirectory,
|
|
224
|
+
...Object.values(xdgDirectories),
|
|
225
|
+
]) {
|
|
226
|
+
mkdirSync(directory, { recursive: true });
|
|
227
|
+
}
|
|
228
|
+
clearStaleToolMountpoints(toolsDirectory);
|
|
229
|
+
const childEnvironment = buildChildEnvironment(options.environment);
|
|
230
|
+
const { agentSkills, agentsHomeSkills } = options.skillPaths ?? {};
|
|
231
|
+
const skillMountPaths = [agentSkills, agentsHomeSkills].filter((path) => path !== undefined);
|
|
232
|
+
const readOnlyPaths = [...(options.readOnlyPaths ?? []), ...skillMountPaths];
|
|
233
|
+
const readOnlyFiles = [options.authPath, options.gitConfigPath].filter((path) => path !== undefined);
|
|
234
|
+
const readOnlyBinaries = (options.toolBinaries ?? []).map((binary) => ({
|
|
235
|
+
source: binary.path,
|
|
236
|
+
destination: join(toolsDirectory, binary.name),
|
|
237
|
+
}));
|
|
238
|
+
return {
|
|
239
|
+
command: options.command,
|
|
240
|
+
args: [...options.args],
|
|
241
|
+
policy: {
|
|
242
|
+
workspace: options.workspace,
|
|
243
|
+
allowedHosts: options.allowedHosts ?? [],
|
|
244
|
+
additionalWritableRoots: options.additionalWritableRoots ?? [],
|
|
245
|
+
},
|
|
246
|
+
readOnlyPaths,
|
|
247
|
+
readOnlyFiles,
|
|
248
|
+
readOnlyBinaries,
|
|
249
|
+
// Travels on the launch contract so the platform backend projects the socket;
|
|
250
|
+
// the environment entry above is what tells the child where to find it.
|
|
251
|
+
...(options.credentialChannel ? { credentialChannel: options.credentialChannel } : {}),
|
|
252
|
+
environment: {
|
|
253
|
+
...childEnvironment,
|
|
254
|
+
...(options.authPath ? { APEX_CODE_AUTH_PATH: options.authPath } : {}),
|
|
255
|
+
...(options.credentialChannel
|
|
256
|
+
? { APEX_CREDENTIAL_PROXY_PATH: options.credentialChannel.childSocketPath }
|
|
257
|
+
: {}),
|
|
258
|
+
// After childEnvironment: these come only from the supervisor's own
|
|
259
|
+
// resolution, never from the invoking shell, so their value always wins over
|
|
260
|
+
// anything of the same name that childEnvironment's allowlist let through.
|
|
261
|
+
...(options.gitConfigPath ? { GIT_CONFIG_GLOBAL: options.gitConfigPath } : {}),
|
|
262
|
+
...(agentSkills ? { APEX_CODE_SKILL_PATH_AGENT: agentSkills } : {}),
|
|
263
|
+
...(agentsHomeSkills ? { APEX_CODE_SKILL_PATH_AGENTS_HOME: agentsHomeSkills } : {}),
|
|
264
|
+
APEX_CODE_CODING_AGENT_DIR: agentDirectory,
|
|
265
|
+
APEX_CODE_CODING_AGENT_SESSION_DIR: sessionDirectory,
|
|
266
|
+
HOME: stateDirectory,
|
|
267
|
+
TMPDIR: stateDirectory,
|
|
268
|
+
...xdgDirectories,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=cli-launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-launch.js","sourceRoot":"","sources":["../../../src/core/sandbox/cli-launch.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readdirSync, realpathSync, rmSync, statSync } from \"node:fs\";\nimport { join, sep } from \"node:path\";\nimport type { HostToolBinary } from \"../../utils/tools-manager.ts\";\nimport { SettingsManager } from \"../settings-manager.ts\";\nimport { resolveWebSearchHost } from \"../web-search-provider.ts\";\nimport { resolveDefaultAllowedHosts } from \"./default-hosts.ts\";\nimport type { SandboxLaunch } from \"./supervisor.ts\";\n\nconst NON_SESSION_COMMANDS = new Set([\"auth\", \"config\", \"install\", \"remove\", \"uninstall\", \"update\", \"list\"]);\nconst METADATA_FLAGS = new Set([\"--version\", \"-v\", \"--export\", \"--list-models\"]);\n\n/**\n * OS containment is the normal startup path for every command that can construct an\n * agent session. Commands that only inspect or maintain host configuration do not\n * create a runtime and therefore remain outside this child boundary.\n */\nexport function requiresSandboxedChild(args: readonly string[]): boolean {\n\tif (NON_SESSION_COMMANDS.has(args[0] ?? \"\")) return false;\n\tif (args.some((argument) => METADATA_FLAGS.has(argument))) return false;\n\tif (args.includes(\"--help\") || args.includes(\"-h\")) return false;\n\treturn true;\n}\n\nexport interface SandboxedCliLaunch extends SandboxLaunch {\n\treadonly environment: NodeJS.ProcessEnv;\n}\n\nexport function getSandboxSessionDirectory(workspace: string): string {\n\treturn join(workspace, \".apex-code\", \"sandbox-sessions\");\n}\n\n/**\n * Read supervisor policy only from global settings; project settings are untrusted here.\n *\n * The built-in provider hosts are added unless explicitly refused, because a deny-all\n * default made a fresh install unable to reach any model while giving the user no way to\n * learn which host to permit. Configured hosts are additive on top, and\n * `allowDefaultHosts: false` restores the strict behaviour for anyone who wants it.\n */\nexport function resolveSupervisorAllowedHosts(cwd: string, agentDir: string): readonly string[] | undefined {\n\tconst settings = SettingsManager.create(cwd, agentDir, { projectTrusted: false });\n\tconst network = settings.getNetworkSettings();\n\tconst configured = network?.allowedHosts ?? [];\n\tif (network?.allowDefaultHosts === false) return configured;\n\t// The configured `web_search` backend's host, added only when a credential for it\n\t// is present. Without this the tool would be configured and still unreachable,\n\t// which reads as a broken search rather than a missing allowlist entry. Nothing is\n\t// opened for a user who never set the key.\n\tconst webSearchHost = resolveWebSearchHost(settings.getWebSearchSettings());\n\treturn [...new Set([...resolveDefaultAllowedHosts(), ...configured, ...(webSearchHost ? [webSearchHost] : [])])];\n}\n\n/**\n * The host's two user-scope skill roots, each present only when it exists on the\n * host. Kept as two named slots rather than one list because\n * `core/package-manager.ts` discovers them in different modes -- root `.md` files\n * count as skills under `agentSkills` (\"pi\" mode) and are ignored under\n * `agentsHomeSkills` (\"agents\" mode), per `docs/skills.md` -- and a flat list of 0-2\n * paths cannot tell the child which root a lone survivor was.\n */\nexport interface HostSkillPaths {\n\t/** Host `<agentDir>/skills`. */\n\treadonly agentSkills?: string;\n\t/** Host `<home>/.agents/skills`. */\n\treadonly agentsHomeSkills?: string;\n}\n\n/** A candidate skill root that exists but was excluded, and why. */\nexport interface HostSkillPathRefusal {\n\treadonly root: keyof HostSkillPaths;\n\treadonly path: string;\n\treadonly reason: string;\n}\n\nexport interface ResolvedHostSkillPaths {\n\treadonly paths: HostSkillPaths;\n\treadonly refusals: readonly HostSkillPathRefusal[];\n}\n\n/**\n * True when `candidate` is the host home directory itself, or an ancestor of it.\n * Both paths must already be resolved (`realpathSync`), so a symlink can't disguise\n * either side. Mounting such a candidate read-only would re-expose the entire home\n * tree the sandbox's `--tmpfs /home` (Linux) / `(deny file-read* USER_HOME)` (macOS)\n * deliberately hides -- SSH keys, cloud credentials, other projects -- not just a\n * skills subtree.\n */\nfunction isHomeOrAncestorOfHome(candidate: string, home: string): boolean {\n\tif (candidate === home) return true;\n\tconst prefix = candidate.endsWith(sep) ? candidate : candidate + sep;\n\treturn home.startsWith(prefix);\n}\n\n/** Resolve one candidate root: absent, refused (symlinked onto the host home), or usable. */\nfunction resolveHostSkillRoot(\n\troot: keyof HostSkillPaths,\n\tcandidate: string,\n\thomeDir: string,\n): { path?: string; refusal?: HostSkillPathRefusal } {\n\tif (!existsSync(candidate)) return {};\n\tlet realCandidate: string;\n\tlet realHome: string;\n\ttry {\n\t\trealCandidate = realpathSync(candidate);\n\t\trealHome = realpathSync(homeDir);\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { refusal: { root, path: candidate, reason: `could not resolve real path: ${message}` } };\n\t}\n\tif (isHomeOrAncestorOfHome(realCandidate, realHome)) {\n\t\treturn {\n\t\t\trefusal: {\n\t\t\t\troot,\n\t\t\t\tpath: candidate,\n\t\t\t\treason: \"resolves to the host home directory or an ancestor of it\",\n\t\t\t},\n\t\t};\n\t}\n\treturn { path: candidate };\n}\n\n/**\n * Resolve the host's user-scope skill directories, before the sandbox exists to hide\n * them. Read only from the runtime environment and the host agent directory --\n * never from project files -- matching ADR 0016's rule that supervisor policy is\n * trust-first. Mirrors `core/package-manager.ts`'s own user-scope roots so the two\n * sides agree on where a skill lives. A candidate that resolves (directly or via a\n * symlink) onto the host home or an ancestor of it is refused rather than mounted --\n * see `isHomeOrAncestorOfHome` -- and reported so the caller can surface a startup\n * diagnostic instead of silently mounting or silently skipping it.\n */\nexport function resolveHostSkillPaths(agentDir: string, homeDir: string): ResolvedHostSkillPaths {\n\tconst agentSkills = resolveHostSkillRoot(\"agentSkills\", join(agentDir, \"skills\"), homeDir);\n\tconst agentsHomeSkills = resolveHostSkillRoot(\"agentsHomeSkills\", join(homeDir, \".agents\", \"skills\"), homeDir);\n\treturn {\n\t\tpaths: {\n\t\t\t...(agentSkills.path ? { agentSkills: agentSkills.path } : {}),\n\t\t\t...(agentsHomeSkills.path ? { agentsHomeSkills: agentsHomeSkills.path } : {}),\n\t\t},\n\t\trefusals: [agentSkills.refusal, agentsHomeSkills.refusal].filter(\n\t\t\t(refusal): refusal is HostSkillPathRefusal => refusal !== undefined,\n\t\t),\n\t};\n}\n\nconst SAFE_CHILD_ENVIRONMENT_KEYS = new Set([\n\t\"PATH\",\n\t\"LANG\",\n\t\"LC_ALL\",\n\t\"LC_CTYPE\",\n\t\"TERM\",\n\t\"COLORTERM\",\n\t\"NO_COLOR\",\n\t\"FORCE_COLOR\",\n\t\"TSX_TSCONFIG_PATH\",\n\t\"APEX_CODE_OFFLINE\",\n\t\"APEX_CODE_SKIP_VERSION_CHECK\",\n\t\"APEX_CODE_EXPERIMENTAL\",\n\t\"APEX_CODE_STARTUP_BENCHMARK\",\n\t\"APEX_CODE_TIMING\",\n\t\"APEX_CODE_CLEAR_ON_SHRINK\",\n\t\"APEX_CODE_HARDWARE_CURSOR\",\n\t\"APEX_CODE_MODEL_CATALOG_URL\",\n\t\"APEX_CODE_SHARE_VIEWER_URL\",\n\t\"VISUAL\",\n\t\"EDITOR\",\n]);\n\n// Provider API keys are explicit credential inputs, unlike arbitrary ambient variables.\n// Keep this list in sync with the documented provider environment-variable reference.\nconst SAFE_PROVIDER_CREDENTIAL_KEYS = new Set([\n\t\"ANTHROPIC_API_KEY\",\n\t\"ANTHROPIC_AUTH_TOKEN\",\n\t\"ANTHROPIC_OAUTH_TOKEN\",\n\t\"ANT_LING_API_KEY\",\n\t\"OPENAI_API_KEY\",\n\t\"AZURE_OPENAI_API_KEY\",\n\t\"AZURE_OPENAI_BASE_URL\",\n\t\"AZURE_OPENAI_RESOURCE_NAME\",\n\t\"AZURE_OPENAI_API_VERSION\",\n\t\"AZURE_OPENAI_DEPLOYMENT_NAME_MAP\",\n\t\"DEEPSEEK_API_KEY\",\n\t\"NVIDIA_API_KEY\",\n\t\"GEMINI_API_KEY\",\n\t\"GROQ_API_KEY\",\n\t\"CEREBRAS_API_KEY\",\n\t\"XAI_API_KEY\",\n\t\"FIREWORKS_API_KEY\",\n\t\"TOGETHER_API_KEY\",\n\t\"BASETEN_API_KEY\",\n\t\"OPENROUTER_API_KEY\",\n\t\"AI_GATEWAY_API_KEY\",\n\t\"ZAI_API_KEY\",\n\t\"ZAI_CODING_CN_API_KEY\",\n\t\"MISTRAL_API_KEY\",\n\t\"MINIMAX_API_KEY\",\n\t\"MOONSHOT_API_KEY\",\n\t\"OPENCODE_API_KEY\",\n\t\"KIMI_API_KEY\",\n\t\"CLOUDFLARE_API_KEY\",\n\t\"CLOUDFLARE_ACCOUNT_ID\",\n\t\"CLOUDFLARE_GATEWAY_ID\",\n\t\"QWEN_TOKEN_PLAN_API_KEY\",\n\t\"QWEN_TOKEN_PLAN_CN_API_KEY\",\n\t\"XIAOMI_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\"AWS_PROFILE\",\n\t\"AWS_ACCESS_KEY_ID\",\n\t\"AWS_SECRET_ACCESS_KEY\",\n\t\"AWS_BEARER_TOKEN_BEDROCK\",\n\t\"AWS_REGION\",\n]);\n\n// Credentials for tools rather than model providers. Separate from the provider set\n// above so the provider list stays a mirror of the documented provider reference.\nconst SAFE_TOOL_CREDENTIAL_KEYS = new Set([\"EXA_API_KEY\"]);\n\nfunction buildChildEnvironment(environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n\treturn Object.fromEntries(\n\t\tObject.entries(environment).filter(\n\t\t\t([key]) =>\n\t\t\t\tSAFE_CHILD_ENVIRONMENT_KEYS.has(key) ||\n\t\t\t\tSAFE_PROVIDER_CREDENTIAL_KEYS.has(key) ||\n\t\t\t\tSAFE_TOOL_CREDENTIAL_KEYS.has(key),\n\t\t),\n\t);\n}\n\n/**\n * Drop empty files left in the child's tools directory by a previous launch.\n *\n * A projected tool is bind-mounted over a file there, and bwrap materialises that\n * mountpoint as an empty file on the host which outlives the namespace. If the host\n * tool later disappears, nothing is projected over the stub and the child would\n * otherwise find a 0-byte file where its binary should be. A real downloaded binary\n * is never empty, so size is a safe discriminator.\n */\nfunction clearStaleToolMountpoints(toolsDirectory: string): void {\n\tfor (const entry of readdirSync(toolsDirectory, { withFileTypes: true })) {\n\t\tif (!entry.isFile()) continue;\n\t\tconst entryPath = join(toolsDirectory, entry.name);\n\t\tif (statSync(entryPath).size === 0) {\n\t\t\trmSync(entryPath, { force: true });\n\t\t}\n\t}\n}\n\n/**\n * Allocate agent-owned state under the sole writable workspace mount. The child does\n * not inherit a host home or a host session/config directory, preventing the sandbox\n * from presenting a write boundary while its own state quietly escapes it.\n */\nexport function buildSandboxedCliLaunch(options: {\n\tworkspace: string;\n\tcommand: string;\n\targs: readonly string[];\n\tenvironment: NodeJS.ProcessEnv;\n\tallowedHosts?: readonly string[];\n\tadditionalWritableRoots?: readonly string[];\n\treadOnlyPaths?: readonly string[];\n\tauthPath?: string;\n\t/**\n\t * A synthesized two-key git config, projected read-only so the child can author a\n\t * commit as the user. Absent when the host had no global identity to resolve.\n\t */\n\tgitConfigPath?: string;\n\ttoolBinaries?: readonly HostToolBinary[];\n\t/**\n\t * Host user-scope skill directories, pre-filtered by the caller to those that\n\t * exist and pass the host-home escape check (SKILL.4). Mounted read-only at their\n\t * original host location -- Seatbelt cannot remap a path, so this must hold for\n\t * both backends -- and named to the child via `APEX_CODE_SKILL_PATH_*` so its\n\t * discovery can find them under the sandbox's own repointed `HOME`/agent dir.\n\t */\n\tskillPaths?: HostSkillPaths;\n\t/** The supervisor-owned credential write channel, when one was opened. */\n\tcredentialChannel?: SandboxLaunch[\"credentialChannel\"];\n}): SandboxedCliLaunch {\n\tconst stateDirectory = join(options.workspace, \".apex-code\", \"sandbox-state\");\n\tconst agentDirectory = join(options.workspace, \".apex-code\", \"sandbox-agent\");\n\tconst sessionDirectory = getSandboxSessionDirectory(options.workspace);\n\t// Mirrors getBinDir() as the child will compute it from APEX_CODE_CODING_AGENT_DIR,\n\t// so a projected tool lands exactly where the child's own lookup already checks.\n\tconst toolsDirectory = join(agentDirectory, \"bin\");\n\tconst xdgDirectories = {\n\t\tXDG_CONFIG_HOME: join(stateDirectory, \"config\"),\n\t\tXDG_CACHE_HOME: join(stateDirectory, \"cache\"),\n\t\tXDG_DATA_HOME: join(stateDirectory, \"data\"),\n\t\tXDG_STATE_HOME: join(stateDirectory, \"state\"),\n\t};\n\tfor (const directory of [\n\t\tstateDirectory,\n\t\tagentDirectory,\n\t\tsessionDirectory,\n\t\ttoolsDirectory,\n\t\t...Object.values(xdgDirectories),\n\t]) {\n\t\tmkdirSync(directory, { recursive: true });\n\t}\n\tclearStaleToolMountpoints(toolsDirectory);\n\tconst childEnvironment = buildChildEnvironment(options.environment);\n\tconst { agentSkills, agentsHomeSkills } = options.skillPaths ?? {};\n\tconst skillMountPaths = [agentSkills, agentsHomeSkills].filter((path): path is string => path !== undefined);\n\tconst readOnlyPaths = [...(options.readOnlyPaths ?? []), ...skillMountPaths];\n\tconst readOnlyFiles = [options.authPath, options.gitConfigPath].filter((path): path is string => path !== undefined);\n\tconst readOnlyBinaries = (options.toolBinaries ?? []).map((binary) => ({\n\t\tsource: binary.path,\n\t\tdestination: join(toolsDirectory, binary.name),\n\t}));\n\treturn {\n\t\tcommand: options.command,\n\t\targs: [...options.args],\n\t\tpolicy: {\n\t\t\tworkspace: options.workspace,\n\t\t\tallowedHosts: options.allowedHosts ?? [],\n\t\t\tadditionalWritableRoots: options.additionalWritableRoots ?? [],\n\t\t},\n\t\treadOnlyPaths,\n\t\treadOnlyFiles,\n\t\treadOnlyBinaries,\n\t\t// Travels on the launch contract so the platform backend projects the socket;\n\t\t// the environment entry above is what tells the child where to find it.\n\t\t...(options.credentialChannel ? { credentialChannel: options.credentialChannel } : {}),\n\t\tenvironment: {\n\t\t\t...childEnvironment,\n\t\t\t...(options.authPath ? { APEX_CODE_AUTH_PATH: options.authPath } : {}),\n\t\t\t...(options.credentialChannel\n\t\t\t\t? { APEX_CREDENTIAL_PROXY_PATH: options.credentialChannel.childSocketPath }\n\t\t\t\t: {}),\n\t\t\t// After childEnvironment: these come only from the supervisor's own\n\t\t\t// resolution, never from the invoking shell, so their value always wins over\n\t\t\t// anything of the same name that childEnvironment's allowlist let through.\n\t\t\t...(options.gitConfigPath ? { GIT_CONFIG_GLOBAL: options.gitConfigPath } : {}),\n\t\t\t...(agentSkills ? { APEX_CODE_SKILL_PATH_AGENT: agentSkills } : {}),\n\t\t\t...(agentsHomeSkills ? { APEX_CODE_SKILL_PATH_AGENTS_HOME: agentsHomeSkills } : {}),\n\t\t\tAPEX_CODE_CODING_AGENT_DIR: agentDirectory,\n\t\t\tAPEX_CODE_CODING_AGENT_SESSION_DIR: sessionDirectory,\n\t\t\tHOME: stateDirectory,\n\t\t\tTMPDIR: stateDirectory,\n\t\t\t...xdgDirectories,\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { HostToolBinary } from "../../utils/tools-manager.ts";
|
|
2
|
+
import { type HostSkillPaths } from "./cli-launch.ts";
|
|
3
|
+
import { type SandboxBackend } from "./supervisor.ts";
|
|
4
|
+
import { SandboxViolationStore } from "./violations.ts";
|
|
5
|
+
export interface CliSandboxDependencies {
|
|
6
|
+
createBackend: (options: {
|
|
7
|
+
violationStore: SandboxViolationStore;
|
|
8
|
+
}) => SandboxBackend;
|
|
9
|
+
stderr: {
|
|
10
|
+
write(message: string): boolean;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Start a normal CLI runtime beneath the whole-process boundary. The caller returns
|
|
15
|
+
* the result directly so the outer process never continues into `main()` afterward.
|
|
16
|
+
*/
|
|
17
|
+
export declare function launchSandboxedCli(options: {
|
|
18
|
+
command: string;
|
|
19
|
+
args: readonly string[];
|
|
20
|
+
environment: NodeJS.ProcessEnv;
|
|
21
|
+
workspace: string;
|
|
22
|
+
allowedHosts?: readonly string[];
|
|
23
|
+
additionalWritableRoots?: readonly string[];
|
|
24
|
+
readOnlyPaths?: readonly string[];
|
|
25
|
+
authPath?: string;
|
|
26
|
+
toolBinaries?: readonly HostToolBinary[];
|
|
27
|
+
skillPaths?: HostSkillPaths;
|
|
28
|
+
dependencies?: Partial<CliSandboxDependencies>;
|
|
29
|
+
}): Promise<number>;
|
|
30
|
+
//# sourceMappingURL=cli-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-supervisor.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/cli-supervisor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAuD,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAO3G,OAAO,EAA2B,KAAK,cAAc,EAAsB,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACtC,aAAa,EAAE,CAAC,OAAO,EAAE;QAAE,cAAc,EAAE,qBAAqB,CAAA;KAAE,KAAK,cAAc,CAAC;IACtF,MAAM,EAAE;QAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAC5C;AAeD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACzC,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC/C,GAAG,OAAO,CAAC,MAAM,CAAC,CAgGlB","sourcesContent":["import { rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"../../cli/args.ts\";\nimport { reportConcurrentSessionRefusal } from \"../../cli/concurrent-session.ts\";\nimport type { HostToolBinary } from \"../../utils/tools-manager.ts\";\nimport { acquireSessionLease, readLiveSessionLeases } from \"../session-lease.ts\";\nimport { buildSandboxedCliLaunch, getSandboxSessionDirectory, type HostSkillPaths } from \"./cli-launch.ts\";\nimport { createProjectedGitConfig, resolveHostGitIdentity } from \"./git-identity.ts\";\nimport { createLinuxSandboxBackend } from \"./linux-backend.ts\";\nimport { createMacosSandboxBackend } from \"./macos-backend.ts\";\nimport { createSandboxPolicy } from \"./policy.ts\";\nimport { createCredentialProxy, resolveCredentialChannelPaths } from \"./rpc/credential-proxy.ts\";\nimport { gitCredentialHelperCommand } from \"./rpc/git-credential-helper.ts\";\nimport { createSandboxSupervisor, type SandboxBackend, type SandboxLaunch } from \"./supervisor.ts\";\nimport { SandboxViolationStore } from \"./violations.ts\";\n\nexport interface CliSandboxDependencies {\n\tcreateBackend: (options: { violationStore: SandboxViolationStore }) => SandboxBackend;\n\tstderr: { write(message: string): boolean };\n}\n\n/** Routes to the platform adapter for the running OS; each adapter self-reports\n * `unavailable` on any other platform, so this only needs to pick the one whose\n * enforcement is actually reachable here. */\nfunction createDefaultSandboxBackend(options: { violationStore: SandboxViolationStore }): SandboxBackend {\n\tif (process.platform === \"darwin\") return createMacosSandboxBackend(options);\n\treturn createLinuxSandboxBackend(options);\n}\n\nconst defaultDependencies: CliSandboxDependencies = {\n\tcreateBackend: createDefaultSandboxBackend,\n\tstderr: process.stderr,\n};\n\n/**\n * Start a normal CLI runtime beneath the whole-process boundary. The caller returns\n * the result directly so the outer process never continues into `main()` afterward.\n */\nexport async function launchSandboxedCli(options: {\n\tcommand: string;\n\targs: readonly string[];\n\tenvironment: NodeJS.ProcessEnv;\n\tworkspace: string;\n\tallowedHosts?: readonly string[];\n\tadditionalWritableRoots?: readonly string[];\n\treadOnlyPaths?: readonly string[];\n\tauthPath?: string;\n\ttoolBinaries?: readonly HostToolBinary[];\n\tskillPaths?: HostSkillPaths;\n\tdependencies?: Partial<CliSandboxDependencies>;\n}): Promise<number> {\n\tconst dependencies = { ...defaultDependencies, ...options.dependencies };\n\tconst policyResult = createSandboxPolicy({\n\t\tworkspace: options.workspace,\n\t\tallowedHosts: options.allowedHosts,\n\t\tadditionalWritableRoots: options.additionalWritableRoots,\n\t});\n\tif (policyResult.kind === \"invalid\") {\n\t\tdependencies.stderr.write(`Error: OS sandbox is not enforcing this agent session: ${policyResult.reason}\\n`);\n\t\treturn 1;\n\t}\n\tconst violationStore = new SandboxViolationStore();\n\tconst backend = dependencies.createBackend({ violationStore });\n\n\tconst supervisor = createSandboxSupervisor({ backend, policy: policyResult.policy });\n\tlet credentialProxy: Awaited<ReturnType<typeof createCredentialProxy>> | undefined;\n\tlet lease: ReturnType<typeof acquireSessionLease> | undefined;\n\tlet projectedGitConfig: ReturnType<typeof createProjectedGitConfig> | undefined;\n\ttry {\n\t\tconst parsed = parseArgs(options.args);\n\t\tconst wantsPersistentSession = !parsed.noSession && !parsed.help && parsed.listModels === undefined;\n\t\tconst sessionDirectory = getSandboxSessionDirectory(policyResult.policy.workspace);\n\t\tif (wantsPersistentSession && !parsed.allowConcurrent) {\n\t\t\tconst liveSessions = readLiveSessionLeases(sessionDirectory, policyResult.policy.workspace);\n\t\t\tif (liveSessions.length > 0) {\n\t\t\t\treportConcurrentSessionRefusal(liveSessions, policyResult.policy.workspace);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\tlease = wantsPersistentSession\n\t\t\t? acquireSessionLease(sessionDirectory, policyResult.policy.workspace, `supervisor-${process.pid}`)\n\t\t\t: undefined;\n\n\t\t// Open the host-owned credential channel only after startup checks that can\n\t\t// return early. AuthStorage creates a missing canonical file as 0600, so a\n\t\t// first-run credential writes get the same channel and read-only projection as later runs.\n\t\tlet credentialChannel: SandboxLaunch[\"credentialChannel\"];\n\t\tif (options.authPath && backend.status.kind === \"enforced\") {\n\t\t\tconst paths = resolveCredentialChannelPaths();\n\t\t\tcredentialProxy = await createCredentialProxy({\n\t\t\t\tauthPath: options.authPath,\n\t\t\t\tviolationStore,\n\t\t\t\tsocketPath: paths.hostSocketPath,\n\t\t\t\tcleanupDirectory: paths.hostSocketDirectory,\n\t\t\t});\n\t\t\tcredentialChannel = paths;\n\t\t}\n\n\t\t// Resolved here rather than in the caller because this function owns the teardown\n\t\t// that removes the directory again. The supervisor is unsandboxed, so the host home\n\t\t// is still visible at this point; inside the child it is not.\n\t\tconst identity = resolveHostGitIdentity({ environment: options.environment });\n\t\t// The helper command is derived from the state directory rather than handed back by\n\t\t// the backend, because the config has to name it before any backend exists. Both\n\t\t// sides derive the same path, so the config never names a file nothing created.\n\t\tprojectedGitConfig = identity\n\t\t\t? createProjectedGitConfig(identity, {\n\t\t\t\t\tcredentialHelper: gitCredentialHelperCommand(\n\t\t\t\t\t\tjoin(policyResult.policy.workspace, \".apex-code\", \"sandbox-state\"),\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t: undefined;\n\n\t\tconst launch = buildSandboxedCliLaunch({\n\t\t\tworkspace: policyResult.policy.workspace,\n\t\t\tcommand: options.command,\n\t\t\targs: options.args,\n\t\t\tenvironment: options.environment,\n\t\t\tallowedHosts: options.allowedHosts,\n\t\t\treadOnlyPaths: options.readOnlyPaths,\n\t\t\tauthPath: options.authPath,\n\t\t\tgitConfigPath: projectedGitConfig?.path,\n\t\t\ttoolBinaries: options.toolBinaries,\n\t\t\tskillPaths: options.skillPaths,\n\t\t\tcredentialChannel,\n\t\t});\n\t\treturn await supervisor.launch(launch);\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : \"Failed to start OS sandbox.\";\n\t\tdependencies.stderr.write(`Error: ${message}\\n`);\n\t\treturn 1;\n\t} finally {\n\t\tlease?.release();\n\t\tif (projectedGitConfig) rmSync(projectedGitConfig.directory, { force: true, recursive: true });\n\t\tconst cleanupResults = await Promise.allSettled([supervisor.close(), credentialProxy?.close()]);\n\t\tfor (const violation of violationStore.list()) {\n\t\t\tdependencies.stderr.write(\n\t\t\t\t`Sandbox violation (${violation.kind}): ${violation.command} — ${violation.detail}\\n`,\n\t\t\t);\n\t\t}\n\t\tfor (const result of cleanupResults) {\n\t\t\tif (result.status === \"rejected\") {\n\t\t\t\tdependencies.stderr.write(\"Warning: sandbox cleanup did not complete cleanly.\\n\");\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseArgs } from "../../cli/args.js";
|
|
4
|
+
import { reportConcurrentSessionRefusal } from "../../cli/concurrent-session.js";
|
|
5
|
+
import { acquireSessionLease, readLiveSessionLeases } from "../session-lease.js";
|
|
6
|
+
import { buildSandboxedCliLaunch, getSandboxSessionDirectory } from "./cli-launch.js";
|
|
7
|
+
import { createProjectedGitConfig, resolveHostGitIdentity } from "./git-identity.js";
|
|
8
|
+
import { createLinuxSandboxBackend } from "./linux-backend.js";
|
|
9
|
+
import { createMacosSandboxBackend } from "./macos-backend.js";
|
|
10
|
+
import { createSandboxPolicy } from "./policy.js";
|
|
11
|
+
import { createCredentialProxy, resolveCredentialChannelPaths } from "./rpc/credential-proxy.js";
|
|
12
|
+
import { gitCredentialHelperCommand } from "./rpc/git-credential-helper.js";
|
|
13
|
+
import { createSandboxSupervisor } from "./supervisor.js";
|
|
14
|
+
import { SandboxViolationStore } from "./violations.js";
|
|
15
|
+
/** Routes to the platform adapter for the running OS; each adapter self-reports
|
|
16
|
+
* `unavailable` on any other platform, so this only needs to pick the one whose
|
|
17
|
+
* enforcement is actually reachable here. */
|
|
18
|
+
function createDefaultSandboxBackend(options) {
|
|
19
|
+
if (process.platform === "darwin")
|
|
20
|
+
return createMacosSandboxBackend(options);
|
|
21
|
+
return createLinuxSandboxBackend(options);
|
|
22
|
+
}
|
|
23
|
+
const defaultDependencies = {
|
|
24
|
+
createBackend: createDefaultSandboxBackend,
|
|
25
|
+
stderr: process.stderr,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Start a normal CLI runtime beneath the whole-process boundary. The caller returns
|
|
29
|
+
* the result directly so the outer process never continues into `main()` afterward.
|
|
30
|
+
*/
|
|
31
|
+
export async function launchSandboxedCli(options) {
|
|
32
|
+
const dependencies = { ...defaultDependencies, ...options.dependencies };
|
|
33
|
+
const policyResult = createSandboxPolicy({
|
|
34
|
+
workspace: options.workspace,
|
|
35
|
+
allowedHosts: options.allowedHosts,
|
|
36
|
+
additionalWritableRoots: options.additionalWritableRoots,
|
|
37
|
+
});
|
|
38
|
+
if (policyResult.kind === "invalid") {
|
|
39
|
+
dependencies.stderr.write(`Error: OS sandbox is not enforcing this agent session: ${policyResult.reason}\n`);
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
const violationStore = new SandboxViolationStore();
|
|
43
|
+
const backend = dependencies.createBackend({ violationStore });
|
|
44
|
+
const supervisor = createSandboxSupervisor({ backend, policy: policyResult.policy });
|
|
45
|
+
let credentialProxy;
|
|
46
|
+
let lease;
|
|
47
|
+
let projectedGitConfig;
|
|
48
|
+
try {
|
|
49
|
+
const parsed = parseArgs(options.args);
|
|
50
|
+
const wantsPersistentSession = !parsed.noSession && !parsed.help && parsed.listModels === undefined;
|
|
51
|
+
const sessionDirectory = getSandboxSessionDirectory(policyResult.policy.workspace);
|
|
52
|
+
if (wantsPersistentSession && !parsed.allowConcurrent) {
|
|
53
|
+
const liveSessions = readLiveSessionLeases(sessionDirectory, policyResult.policy.workspace);
|
|
54
|
+
if (liveSessions.length > 0) {
|
|
55
|
+
reportConcurrentSessionRefusal(liveSessions, policyResult.policy.workspace);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
lease = wantsPersistentSession
|
|
60
|
+
? acquireSessionLease(sessionDirectory, policyResult.policy.workspace, `supervisor-${process.pid}`)
|
|
61
|
+
: undefined;
|
|
62
|
+
// Open the host-owned credential channel only after startup checks that can
|
|
63
|
+
// return early. AuthStorage creates a missing canonical file as 0600, so a
|
|
64
|
+
// first-run credential writes get the same channel and read-only projection as later runs.
|
|
65
|
+
let credentialChannel;
|
|
66
|
+
if (options.authPath && backend.status.kind === "enforced") {
|
|
67
|
+
const paths = resolveCredentialChannelPaths();
|
|
68
|
+
credentialProxy = await createCredentialProxy({
|
|
69
|
+
authPath: options.authPath,
|
|
70
|
+
violationStore,
|
|
71
|
+
socketPath: paths.hostSocketPath,
|
|
72
|
+
cleanupDirectory: paths.hostSocketDirectory,
|
|
73
|
+
});
|
|
74
|
+
credentialChannel = paths;
|
|
75
|
+
}
|
|
76
|
+
// Resolved here rather than in the caller because this function owns the teardown
|
|
77
|
+
// that removes the directory again. The supervisor is unsandboxed, so the host home
|
|
78
|
+
// is still visible at this point; inside the child it is not.
|
|
79
|
+
const identity = resolveHostGitIdentity({ environment: options.environment });
|
|
80
|
+
// The helper command is derived from the state directory rather than handed back by
|
|
81
|
+
// the backend, because the config has to name it before any backend exists. Both
|
|
82
|
+
// sides derive the same path, so the config never names a file nothing created.
|
|
83
|
+
projectedGitConfig = identity
|
|
84
|
+
? createProjectedGitConfig(identity, {
|
|
85
|
+
credentialHelper: gitCredentialHelperCommand(join(policyResult.policy.workspace, ".apex-code", "sandbox-state")),
|
|
86
|
+
})
|
|
87
|
+
: undefined;
|
|
88
|
+
const launch = buildSandboxedCliLaunch({
|
|
89
|
+
workspace: policyResult.policy.workspace,
|
|
90
|
+
command: options.command,
|
|
91
|
+
args: options.args,
|
|
92
|
+
environment: options.environment,
|
|
93
|
+
allowedHosts: options.allowedHosts,
|
|
94
|
+
readOnlyPaths: options.readOnlyPaths,
|
|
95
|
+
authPath: options.authPath,
|
|
96
|
+
gitConfigPath: projectedGitConfig?.path,
|
|
97
|
+
toolBinaries: options.toolBinaries,
|
|
98
|
+
skillPaths: options.skillPaths,
|
|
99
|
+
credentialChannel,
|
|
100
|
+
});
|
|
101
|
+
return await supervisor.launch(launch);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const message = error instanceof Error ? error.message : "Failed to start OS sandbox.";
|
|
105
|
+
dependencies.stderr.write(`Error: ${message}\n`);
|
|
106
|
+
return 1;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
lease?.release();
|
|
110
|
+
if (projectedGitConfig)
|
|
111
|
+
rmSync(projectedGitConfig.directory, { force: true, recursive: true });
|
|
112
|
+
const cleanupResults = await Promise.allSettled([supervisor.close(), credentialProxy?.close()]);
|
|
113
|
+
for (const violation of violationStore.list()) {
|
|
114
|
+
dependencies.stderr.write(`Sandbox violation (${violation.kind}): ${violation.command} — ${violation.detail}\n`);
|
|
115
|
+
}
|
|
116
|
+
for (const result of cleanupResults) {
|
|
117
|
+
if (result.status === "rejected") {
|
|
118
|
+
dependencies.stderr.write("Warning: sandbox cleanup did not complete cleanly.\n");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=cli-supervisor.js.map
|