@prestyj/cli 5.10.0 → 5.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/dist/app-sidecar-auth-broadcast.test.d.ts +2 -0
- package/dist/app-sidecar-auth-broadcast.test.d.ts.map +1 -0
- package/dist/app-sidecar-auth-broadcast.test.js +282 -0
- package/dist/app-sidecar-auth-broadcast.test.js.map +1 -0
- package/dist/app-sidecar-sessions.d.ts +5 -2
- package/dist/app-sidecar-sessions.d.ts.map +1 -1
- package/dist/app-sidecar-sessions.js +34 -8
- package/dist/app-sidecar-sessions.js.map +1 -1
- package/dist/app-sidecar-sessions.test.js +95 -0
- package/dist/app-sidecar-sessions.test.js.map +1 -1
- package/dist/app-sidecar.js +497 -128
- package/dist/app-sidecar.js.map +1 -1
- package/dist/cli/command-routing.d.ts +1 -1
- package/dist/cli/command-routing.d.ts.map +1 -1
- package/dist/cli/command-routing.js +1 -0
- package/dist/cli/command-routing.js.map +1 -1
- package/dist/cli/command-routing.test.js +1 -0
- package/dist/cli/command-routing.test.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +167 -47
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +10 -1
- package/dist/config.test.js.map +1 -1
- package/dist/core/agent-notifications.d.ts +62 -0
- package/dist/core/agent-notifications.d.ts.map +1 -0
- package/dist/core/agent-notifications.js +92 -0
- package/dist/core/agent-notifications.js.map +1 -0
- package/dist/core/agent-notifications.test.d.ts +2 -0
- package/dist/core/agent-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-notifications.test.js +97 -0
- package/dist/core/agent-notifications.test.js.map +1 -0
- package/dist/core/agent-session-checkpoint-flush.test.d.ts +2 -0
- package/dist/core/agent-session-checkpoint-flush.test.d.ts.map +1 -0
- package/dist/core/agent-session-checkpoint-flush.test.js +201 -0
- package/dist/core/agent-session-checkpoint-flush.test.js.map +1 -0
- package/dist/core/agent-session-compaction.test.js +323 -6
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-crash-durability.test.d.ts +2 -0
- package/dist/core/agent-session-crash-durability.test.d.ts.map +1 -0
- package/dist/core/agent-session-crash-durability.test.js +102 -0
- package/dist/core/agent-session-crash-durability.test.js.map +1 -0
- package/dist/core/agent-session-marker-anchors.test.js +181 -2
- package/dist/core/agent-session-marker-anchors.test.js.map +1 -1
- package/dist/core/agent-session-model-switch.test.d.ts +2 -0
- package/dist/core/agent-session-model-switch.test.d.ts.map +1 -0
- package/dist/core/agent-session-model-switch.test.js +161 -0
- package/dist/core/agent-session-model-switch.test.js.map +1 -0
- package/dist/core/agent-session-notifications.test.d.ts +2 -0
- package/dist/core/agent-session-notifications.test.d.ts.map +1 -0
- package/dist/core/agent-session-notifications.test.js +114 -0
- package/dist/core/agent-session-notifications.test.js.map +1 -0
- package/dist/core/agent-session-process-gate.test.d.ts +2 -0
- package/dist/core/agent-session-process-gate.test.d.ts.map +1 -0
- package/dist/core/agent-session-process-gate.test.js +92 -0
- package/dist/core/agent-session-process-gate.test.js.map +1 -0
- package/dist/core/agent-session-queue.test.js +65 -0
- package/dist/core/agent-session-queue.test.js.map +1 -1
- package/dist/core/agent-session-review-coverage.test.js +80 -23
- package/dist/core/agent-session-review-coverage.test.js.map +1 -1
- package/dist/core/agent-session-slash-restore.test.d.ts +2 -0
- package/dist/core/agent-session-slash-restore.test.d.ts.map +1 -0
- package/dist/core/agent-session-slash-restore.test.js +121 -0
- package/dist/core/agent-session-slash-restore.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +214 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +978 -212
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/active-context.test.js +21 -0
- package/dist/core/compaction/active-context.test.js.map +1 -1
- package/dist/core/compaction/compactor.d.ts +108 -8
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +423 -119
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +360 -8
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/compaction/policy.d.ts +17 -0
- package/dist/core/compaction/policy.d.ts.map +1 -0
- package/dist/core/compaction/policy.js +22 -0
- package/dist/core/compaction/policy.js.map +1 -0
- package/dist/core/compaction/policy.test.d.ts +2 -0
- package/dist/core/compaction/policy.test.d.ts.map +1 -0
- package/dist/core/compaction/policy.test.js +35 -0
- package/dist/core/compaction/policy.test.js.map +1 -0
- package/dist/core/compaction/query-aware-selector.d.ts +33 -0
- package/dist/core/compaction/query-aware-selector.d.ts.map +1 -0
- package/dist/core/compaction/query-aware-selector.js +202 -0
- package/dist/core/compaction/query-aware-selector.js.map +1 -0
- package/dist/core/compaction/query-aware-selector.test.d.ts +2 -0
- package/dist/core/compaction/query-aware-selector.test.d.ts.map +1 -0
- package/dist/core/compaction/query-aware-selector.test.js +96 -0
- package/dist/core/compaction/query-aware-selector.test.js.map +1 -0
- package/dist/core/compaction/tool-result-pruner.d.ts +24 -11
- package/dist/core/compaction/tool-result-pruner.d.ts.map +1 -1
- package/dist/core/compaction/tool-result-pruner.js +98 -26
- package/dist/core/compaction/tool-result-pruner.js.map +1 -1
- package/dist/core/compaction/tool-result-pruner.test.js +178 -6
- package/dist/core/compaction/tool-result-pruner.test.js.map +1 -1
- package/dist/core/event-bus.d.ts +23 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +10 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +28 -8
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/plugin-bundles.d.ts +23 -0
- package/dist/core/extensions/plugin-bundles.d.ts.map +1 -0
- package/dist/core/extensions/plugin-bundles.js +228 -0
- package/dist/core/extensions/plugin-bundles.js.map +1 -0
- package/dist/core/extensions/plugin-bundles.test.d.ts +2 -0
- package/dist/core/extensions/plugin-bundles.test.d.ts.map +1 -0
- package/dist/core/extensions/plugin-bundles.test.js +110 -0
- package/dist/core/extensions/plugin-bundles.test.js.map +1 -0
- package/dist/core/foreign-session-import.d.ts +120 -0
- package/dist/core/foreign-session-import.d.ts.map +1 -0
- package/dist/core/foreign-session-import.js +598 -0
- package/dist/core/foreign-session-import.js.map +1 -0
- package/dist/core/foreign-session-import.test.d.ts +2 -0
- package/dist/core/foreign-session-import.test.d.ts.map +1 -0
- package/dist/core/foreign-session-import.test.js +220 -0
- package/dist/core/foreign-session-import.test.js.map +1 -0
- package/dist/core/foreign-transcript-blocks.d.ts +51 -0
- package/dist/core/foreign-transcript-blocks.d.ts.map +1 -0
- package/dist/core/foreign-transcript-blocks.js +151 -0
- package/dist/core/foreign-transcript-blocks.js.map +1 -0
- package/dist/core/ideal-review.d.ts +20 -1
- package/dist/core/ideal-review.d.ts.map +1 -1
- package/dist/core/ideal-review.js +37 -2
- package/dist/core/ideal-review.js.map +1 -1
- package/dist/core/ideal-review.test.js +99 -3
- package/dist/core/ideal-review.test.js.map +1 -1
- package/dist/core/loop-breaker.d.ts.map +1 -1
- package/dist/core/loop-breaker.js +1 -0
- package/dist/core/loop-breaker.js.map +1 -1
- package/dist/core/lsp/client.d.ts +15 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +39 -1
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/manager.d.ts +47 -9
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +96 -69
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/manager.test.js +18 -0
- package/dist/core/lsp/manager.test.js.map +1 -1
- package/dist/core/lsp/pool.d.ts +113 -0
- package/dist/core/lsp/pool.d.ts.map +1 -0
- package/dist/core/lsp/pool.js +255 -0
- package/dist/core/lsp/pool.js.map +1 -0
- package/dist/core/lsp/pool.test.d.ts +2 -0
- package/dist/core/lsp/pool.test.d.ts.map +1 -0
- package/dist/core/lsp/pool.test.js +286 -0
- package/dist/core/lsp/pool.test.js.map +1 -0
- package/dist/core/lsp/servers.d.ts.map +1 -1
- package/dist/core/lsp/servers.js +43 -3
- package/dist/core/lsp/servers.js.map +1 -1
- package/dist/core/lsp/servers.test.d.ts +2 -0
- package/dist/core/lsp/servers.test.d.ts.map +1 -0
- package/dist/core/lsp/servers.test.js +67 -0
- package/dist/core/lsp/servers.test.js.map +1 -0
- package/dist/core/lsp/windows.test.js +2 -14
- package/dist/core/lsp/windows.test.js.map +1 -1
- package/dist/core/mcp/catalog-cache.d.ts +63 -0
- package/dist/core/mcp/catalog-cache.d.ts.map +1 -0
- package/dist/core/mcp/catalog-cache.js +163 -0
- package/dist/core/mcp/catalog-cache.js.map +1 -0
- package/dist/core/mcp/catalog-cache.test.d.ts +2 -0
- package/dist/core/mcp/catalog-cache.test.d.ts.map +1 -0
- package/dist/core/mcp/catalog-cache.test.js +99 -0
- package/dist/core/mcp/catalog-cache.test.js.map +1 -0
- package/dist/core/mcp/client-session-recovery.test.d.ts +2 -0
- package/dist/core/mcp/client-session-recovery.test.d.ts.map +1 -0
- package/dist/core/mcp/client-session-recovery.test.js +231 -0
- package/dist/core/mcp/client-session-recovery.test.js.map +1 -0
- package/dist/core/mcp/client.d.ts +158 -0
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +476 -35
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/elicitation-bridge.d.ts +41 -0
- package/dist/core/mcp/elicitation-bridge.d.ts.map +1 -0
- package/dist/core/mcp/elicitation-bridge.js +52 -0
- package/dist/core/mcp/elicitation-bridge.js.map +1 -0
- package/dist/core/mcp/elicitation.test.d.ts +2 -0
- package/dist/core/mcp/elicitation.test.d.ts.map +1 -0
- package/dist/core/mcp/elicitation.test.js +158 -0
- package/dist/core/mcp/elicitation.test.js.map +1 -0
- package/dist/core/mcp/index.d.ts +5 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js +2 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/mcp/legacy-negotiation.test.d.ts +2 -0
- package/dist/core/mcp/legacy-negotiation.test.d.ts.map +1 -0
- package/dist/core/mcp/legacy-negotiation.test.js +80 -0
- package/dist/core/mcp/legacy-negotiation.test.js.map +1 -0
- package/dist/core/mcp/oauth-provider.d.ts +1 -2
- package/dist/core/mcp/oauth-provider.d.ts.map +1 -1
- package/dist/core/mcp/oauth-provider.js +6 -2
- package/dist/core/mcp/oauth-provider.js.map +1 -1
- package/dist/core/mcp/oauth-store.d.ts +1 -1
- package/dist/core/mcp/oauth-store.d.ts.map +1 -1
- package/dist/core/mcp/oauth-store.js.map +1 -1
- package/dist/core/mcp/session-elicitation-wiring.test.d.ts +2 -0
- package/dist/core/mcp/session-elicitation-wiring.test.d.ts.map +1 -0
- package/dist/core/mcp/session-elicitation-wiring.test.js +138 -0
- package/dist/core/mcp/session-elicitation-wiring.test.js.map +1 -0
- package/dist/core/mcp/shared-pool.d.ts +158 -0
- package/dist/core/mcp/shared-pool.d.ts.map +1 -0
- package/dist/core/mcp/shared-pool.js +235 -0
- package/dist/core/mcp/shared-pool.js.map +1 -0
- package/dist/core/mcp/shared-pool.test.d.ts +2 -0
- package/dist/core/mcp/shared-pool.test.d.ts.map +1 -0
- package/dist/core/mcp/shared-pool.test.js +425 -0
- package/dist/core/mcp/shared-pool.test.js.map +1 -0
- package/dist/core/mcp/types.d.ts +12 -0
- package/dist/core/mcp/types.d.ts.map +1 -1
- package/dist/core/mcp/when-connected.test.d.ts +2 -0
- package/dist/core/mcp/when-connected.test.d.ts.map +1 -0
- package/dist/core/mcp/when-connected.test.js +46 -0
- package/dist/core/mcp/when-connected.test.js.map +1 -0
- package/dist/core/nolan-context.d.ts.map +1 -1
- package/dist/core/nolan-context.js +8 -0
- package/dist/core/nolan-context.js.map +1 -1
- package/dist/core/nolan-context.test.js +40 -0
- package/dist/core/nolan-context.test.js.map +1 -1
- package/dist/core/nolan-prompt.js +3 -0
- package/dist/core/nolan-prompt.js.map +1 -1
- package/dist/core/nolan-prompt.test.js +5 -0
- package/dist/core/nolan-prompt.test.js.map +1 -1
- package/dist/core/persistent-shell.d.ts +3 -2
- package/dist/core/persistent-shell.d.ts.map +1 -1
- package/dist/core/persistent-shell.js +10 -3
- package/dist/core/persistent-shell.js.map +1 -1
- package/dist/core/process-gate.d.ts +45 -0
- package/dist/core/process-gate.d.ts.map +1 -0
- package/dist/core/process-gate.js +79 -0
- package/dist/core/process-gate.js.map +1 -0
- package/dist/core/process-gate.test.d.ts +2 -0
- package/dist/core/process-gate.test.d.ts.map +1 -0
- package/dist/core/process-gate.test.js +87 -0
- package/dist/core/process-gate.test.js.map +1 -0
- package/dist/core/process-manager-notifications.test.d.ts +2 -0
- package/dist/core/process-manager-notifications.test.d.ts.map +1 -0
- package/dist/core/process-manager-notifications.test.js +217 -0
- package/dist/core/process-manager-notifications.test.js.map +1 -0
- package/dist/core/process-manager.d.ts +50 -1
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +189 -2
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-discovery.d.ts +31 -6
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +287 -31
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +124 -0
- package/dist/core/project-discovery.test.js.map +1 -1
- package/dist/core/regrounding.d.ts.map +1 -1
- package/dist/core/regrounding.js +1 -0
- package/dist/core/regrounding.js.map +1 -1
- package/dist/core/run-claim.d.ts +37 -0
- package/dist/core/run-claim.d.ts.map +1 -0
- package/dist/core/run-claim.js +46 -0
- package/dist/core/run-claim.js.map +1 -0
- package/dist/core/run-claim.test.d.ts +2 -0
- package/dist/core/run-claim.test.d.ts.map +1 -0
- package/dist/core/run-claim.test.js +107 -0
- package/dist/core/run-claim.test.js.map +1 -0
- package/dist/core/run-journal.test.d.ts +2 -0
- package/dist/core/run-journal.test.d.ts.map +1 -0
- package/dist/core/run-journal.test.js +195 -0
- package/dist/core/run-journal.test.js.map +1 -0
- package/dist/core/run-lifecycle.d.ts +22 -3
- package/dist/core/run-lifecycle.d.ts.map +1 -1
- package/dist/core/run-lifecycle.js +12 -3
- package/dist/core/run-lifecycle.js.map +1 -1
- package/dist/core/sandbox-domains.d.ts +14 -0
- package/dist/core/sandbox-domains.d.ts.map +1 -0
- package/dist/core/sandbox-domains.js +76 -0
- package/dist/core/sandbox-domains.js.map +1 -0
- package/dist/core/sandbox-feedback.d.ts +22 -0
- package/dist/core/sandbox-feedback.d.ts.map +1 -0
- package/dist/core/sandbox-feedback.js +69 -0
- package/dist/core/sandbox-feedback.js.map +1 -0
- package/dist/core/sandbox-feedback.test.d.ts +2 -0
- package/dist/core/sandbox-feedback.test.d.ts.map +1 -0
- package/dist/core/sandbox-feedback.test.js +32 -0
- package/dist/core/sandbox-feedback.test.js.map +1 -0
- package/dist/core/sandbox.d.ts +91 -0
- package/dist/core/sandbox.d.ts.map +1 -0
- package/dist/core/sandbox.js +254 -0
- package/dist/core/sandbox.js.map +1 -0
- package/dist/core/sandbox.test.d.ts +2 -0
- package/dist/core/sandbox.test.d.ts.map +1 -0
- package/dist/core/sandbox.test.js +157 -0
- package/dist/core/sandbox.test.js.map +1 -0
- package/dist/core/session-compaction.d.ts +6 -0
- package/dist/core/session-compaction.d.ts.map +1 -1
- package/dist/core/session-compaction.js +11 -1
- package/dist/core/session-compaction.js.map +1 -1
- package/dist/core/session-compaction.test.js +18 -1
- package/dist/core/session-compaction.test.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +12 -4
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-history.d.ts +95 -6
- package/dist/core/session-history.d.ts.map +1 -1
- package/dist/core/session-history.js +261 -17
- package/dist/core/session-history.js.map +1 -1
- package/dist/core/session-history.test.js +173 -2
- package/dist/core/session-history.test.js.map +1 -1
- package/dist/core/session-manager.d.ts +223 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +515 -26
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +147 -3
- package/dist/core/session-manager.test.js.map +1 -1
- package/dist/core/session-notification-visibility.test.d.ts +2 -0
- package/dist/core/session-notification-visibility.test.d.ts.map +1 -0
- package/dist/core/session-notification-visibility.test.js +113 -0
- package/dist/core/session-notification-visibility.test.js.map +1 -0
- package/dist/core/session-preview.d.ts +5 -4
- package/dist/core/session-preview.d.ts.map +1 -1
- package/dist/core/session-preview.js +12 -5
- package/dist/core/session-preview.js.map +1 -1
- package/dist/core/session-restore-display.test.js +25 -0
- package/dist/core/session-restore-display.test.js.map +1 -1
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +39 -3
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/session-storage.test.js +6 -1
- package/dist/core/session-storage.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +26 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/steering.d.ts +12 -0
- package/dist/core/steering.d.ts.map +1 -1
- package/dist/core/steering.js +16 -0
- package/dist/core/steering.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +13 -0
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +39 -1
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +43 -7
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/core/verification-evidence.d.ts +17 -0
- package/dist/core/verification-evidence.d.ts.map +1 -0
- package/dist/core/verification-evidence.js +283 -0
- package/dist/core/verification-evidence.js.map +1 -0
- package/dist/core/verification-evidence.test.d.ts +2 -0
- package/dist/core/verification-evidence.test.d.ts.map +1 -0
- package/dist/core/verification-evidence.test.js +103 -0
- package/dist/core/verification-evidence.test.js.map +1 -0
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +17 -3
- package/dist/interactive.js.map +1 -1
- package/dist/modes/acp-mode.d.ts +122 -0
- package/dist/modes/acp-mode.d.ts.map +1 -0
- package/dist/modes/acp-mode.js +1366 -0
- package/dist/modes/acp-mode.js.map +1 -0
- package/dist/modes/acp-mode.test.d.ts +2 -0
- package/dist/modes/acp-mode.test.d.ts.map +1 -0
- package/dist/modes/acp-mode.test.js +1065 -0
- package/dist/modes/acp-mode.test.js.map +1 -0
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -0
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/json-mode.d.ts +28 -0
- package/dist/modes/json-mode.d.ts.map +1 -1
- package/dist/modes/json-mode.js +37 -0
- package/dist/modes/json-mode.js.map +1 -1
- package/dist/modes/json-mode.test.d.ts +2 -0
- package/dist/modes/json-mode.test.d.ts.map +1 -0
- package/dist/modes/json-mode.test.js +84 -0
- package/dist/modes/json-mode.test.js.map +1 -0
- package/dist/modes/subagent-worker-mode.d.ts +3 -0
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
- package/dist/modes/subagent-worker-mode.js +91 -11
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.test.d.ts +2 -0
- package/dist/modes/subagent-worker-mode.test.d.ts.map +1 -0
- package/dist/modes/subagent-worker-mode.test.js +52 -0
- package/dist/modes/subagent-worker-mode.test.js.map +1 -0
- package/dist/session.d.ts +29 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +41 -0
- package/dist/session.js.map +1 -1
- package/dist/tools/bash.d.ts +2 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +55 -16
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/goals.d.ts +2 -2
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +2 -1
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/index.d.ts +13 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +20 -17
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/index.test.d.ts +2 -0
- package/dist/tools/index.test.d.ts.map +1 -0
- package/dist/tools/index.test.js +55 -0
- package/dist/tools/index.test.js.map +1 -0
- package/dist/tools/read-only-bash.d.ts +3 -0
- package/dist/tools/read-only-bash.d.ts.map +1 -1
- package/dist/tools/read-only-bash.js +7 -9
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/subagent-control.d.ts.map +1 -1
- package/dist/tools/subagent-control.js +6 -2
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent-shared.d.ts +6 -0
- package/dist/tools/subagent-shared.d.ts.map +1 -1
- package/dist/tools/subagent-shared.js +6 -0
- package/dist/tools/subagent-shared.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +43 -8
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagent.test.js +65 -3
- package/dist/tools/subagent.test.js.map +1 -1
- package/dist/tools/task-output.d.ts.map +1 -1
- package/dist/tools/task-output.js +3 -1
- package/dist/tools/task-output.js.map +1 -1
- package/dist/tools/tool-search.d.ts +12 -1
- package/dist/tools/tool-search.d.ts.map +1 -1
- package/dist/tools/tool-search.js +22 -3
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-search.test.d.ts +2 -0
- package/dist/tools/tool-search.test.d.ts.map +1 -0
- package/dist/tools/tool-search.test.js +69 -0
- package/dist/tools/tool-search.test.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +1 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +5 -2
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +27 -1
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +18 -4
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/utils/github.test.js +3 -3
- package/dist/utils/github.test.js.map +1 -1
- package/dist/utils/image.d.ts +26 -3
- package/dist/utils/image.d.ts.map +1 -1
- package/dist/utils/image.js +83 -14
- package/dist/utils/image.js.map +1 -1
- package/dist/utils/image.test.d.ts +2 -0
- package/dist/utils/image.test.d.ts.map +1 -0
- package/dist/utils/image.test.js +139 -0
- package/dist/utils/image.test.js.map +1 -0
- package/package.json +7 -6
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ShellResolution } from "./shell.js";
|
|
2
|
+
export interface SandboxPolicy {
|
|
3
|
+
/**
|
|
4
|
+
* `workspace` always isolates and fails closed. `auto` isolates wherever the
|
|
5
|
+
* OS supports it and degrades with a warning where the prerequisites are
|
|
6
|
+
* absent, because SRT needs bubblewrap/socat on Linux and an elevated
|
|
7
|
+
* `windows-install` on Windows — enforcing there would break every command.
|
|
8
|
+
*/
|
|
9
|
+
mode: "auto" | "workspace" | "off";
|
|
10
|
+
/**
|
|
11
|
+
* Extra hosts reachable while sandboxed, on top of
|
|
12
|
+
* {@link DEFAULT_ALLOWED_DOMAINS} unless {@link strictDomains} is set.
|
|
13
|
+
*/
|
|
14
|
+
allowedDomains: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Use only {@link allowedDomains}, dropping the built-in developer defaults.
|
|
17
|
+
* Set when the user has explicitly taken over network policy.
|
|
18
|
+
*/
|
|
19
|
+
strictDomains?: boolean;
|
|
20
|
+
/** Extra workspace roots (multi-root sessions), mirroring the write guard. */
|
|
21
|
+
additionalRoots?: string[];
|
|
22
|
+
/** The user consented to writes outside the workspace; do not contradict them. */
|
|
23
|
+
allowOutsideWorkspaceWrites?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface SandboxLaunch extends ShellResolution {
|
|
26
|
+
sandboxed: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Environment applied only to sandboxed commands.
|
|
30
|
+
*
|
|
31
|
+
* The sandbox permanently protects `.git/hooks`, and git's only reason to write
|
|
32
|
+
* there is copying inert `*.sample` templates during `init`/`clone` — which
|
|
33
|
+
* fails the whole command. Pointing git at an empty template directory removes
|
|
34
|
+
* that write, so cloning works with hook protection fully intact.
|
|
35
|
+
*/
|
|
36
|
+
export declare const SANDBOX_ENV_PATCH: Readonly<Record<string, string>>;
|
|
37
|
+
interface SandboxSettings {
|
|
38
|
+
network: {
|
|
39
|
+
allowedDomains: string[];
|
|
40
|
+
deniedDomains: string[];
|
|
41
|
+
strictAllowlist: boolean;
|
|
42
|
+
allowUnixSockets: string[];
|
|
43
|
+
allowLocalBinding: boolean;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* macOS only: let sandboxed processes reach `com.apple.trustd.agent`.
|
|
47
|
+
*
|
|
48
|
+
* Without it, every client that verifies certificates through Security
|
|
49
|
+
* framework fails — pip (truststore) and Go-based CLIs like gh, terraform
|
|
50
|
+
* and kubectl. We do not terminate TLS, so certificates are still validated
|
|
51
|
+
* against the real upstream and the domain allowlist still applies; this only
|
|
52
|
+
* restores certificate checking itself.
|
|
53
|
+
*/
|
|
54
|
+
enableWeakerNetworkIsolation?: boolean;
|
|
55
|
+
filesystem: {
|
|
56
|
+
denyRead: string[];
|
|
57
|
+
allowWrite: string[];
|
|
58
|
+
denyWrite: string[];
|
|
59
|
+
/** Git cannot initialise or clone a repository without writing its config. */
|
|
60
|
+
allowGitConfig: boolean;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Pure policy builder, exported so the security boundary is regression-tested. */
|
|
64
|
+
export declare function buildSandboxSettings(cwd: string, policy: SandboxPolicy, platform?: NodeJS.Platform): SandboxSettings;
|
|
65
|
+
export declare function resetSandboxSupportProbeForTests(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Known limitations when `sandboxMode` is enabled (upstream, not fixable here):
|
|
68
|
+
*
|
|
69
|
+
* - **Linux pipes/redirections**: `echo hi | grep hi` fails with "Permission
|
|
70
|
+
* denied" on /proc/self/fd/3 because bash's pipe setup clobbers the fd the
|
|
71
|
+
* seccomp filter arrives on (sandbox-runtime#261).
|
|
72
|
+
* - **git over SSH**: `git@host:` remotes fail the SOCKS handshake on macOS —
|
|
73
|
+
* the injected ProxyCommand uses `nc`, which cannot authenticate. HTTPS
|
|
74
|
+
* remotes work. `~/.ssh` is also unreadable by design.
|
|
75
|
+
* - **`git config --global`**: `~/.gitconfig` is a mandatory upstream write
|
|
76
|
+
* protection with no opt-out. Repo-local `git config` works.
|
|
77
|
+
* - **Corporate TLS interception / private registries**: need the CA and
|
|
78
|
+
* registry host configured explicitly.
|
|
79
|
+
* - **Ubuntu 24.04+**: AppArmor blocks the sandbox entirely, so `auto`
|
|
80
|
+
* degrades to no isolation (sandbox-runtime#428, #429).
|
|
81
|
+
*
|
|
82
|
+
* These are why the default is `off`; revisit when fixed upstream.
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* Wrap an already-resolved shell with Anthropic's cross-platform OS sandbox.
|
|
86
|
+
* Initialization and dependency failures remain visible and fail closed: the
|
|
87
|
+
* original command is never spawned outside the sandbox as an implicit fallback.
|
|
88
|
+
*/
|
|
89
|
+
export declare function prepareSandboxLaunch(shell: ShellResolution, cwd: string, policy: SandboxPolicy): Promise<SandboxLaunch>;
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/core/sandbox.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,CAAC;IACnC;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,kFAAkF;IAClF,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE9D,CAAC;AAEF,UAAU,eAAe;IACvB,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF;;;;;;;;OAQG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,8EAA8E;QAC9E,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;CACH;AAgED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,EACrB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,eAAe,CA+DjB;AAeD,wBAAgB,gCAAgC,IAAI,IAAI,CAGvD;AAwDD;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,CA4BxB"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import { realpathSync } from "node:fs";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { log } from "./logger.js";
|
|
9
|
+
import { getAppPaths } from "../config.js";
|
|
10
|
+
import { DEFAULT_ALLOWED_DOMAINS } from "./sandbox-domains.js";
|
|
11
|
+
/**
|
|
12
|
+
* Environment applied only to sandboxed commands.
|
|
13
|
+
*
|
|
14
|
+
* The sandbox permanently protects `.git/hooks`, and git's only reason to write
|
|
15
|
+
* there is copying inert `*.sample` templates during `init`/`clone` — which
|
|
16
|
+
* fails the whole command. Pointing git at an empty template directory removes
|
|
17
|
+
* that write, so cloning works with hook protection fully intact.
|
|
18
|
+
*/
|
|
19
|
+
export const SANDBOX_ENV_PATCH = {
|
|
20
|
+
GIT_TEMPLATE_DIR: "",
|
|
21
|
+
};
|
|
22
|
+
const SANDBOX_CONFIG_DIR = path.join(os.homedir(), ".ezcoder", "sandbox-configs");
|
|
23
|
+
const PROBE_TIMEOUT_MS = 20_000;
|
|
24
|
+
let warnedUnsupported = false;
|
|
25
|
+
function sensitiveReadPaths(home) {
|
|
26
|
+
return [
|
|
27
|
+
path.join(home, ".ssh"),
|
|
28
|
+
path.join(home, ".aws"),
|
|
29
|
+
path.join(home, ".gnupg"),
|
|
30
|
+
path.join(home, ".kube"),
|
|
31
|
+
path.join(home, ".config", "gcloud"),
|
|
32
|
+
path.join(home, ".azure"),
|
|
33
|
+
path.join(home, ".ezcoder", "auth.json"),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Package-manager caches that live outside the workspace.
|
|
38
|
+
*
|
|
39
|
+
* `npm install`, `cargo build`, `go mod download` and friends all write to a
|
|
40
|
+
* shared cache in $HOME; without these the sandbox looks like it "breaks npm".
|
|
41
|
+
* Everything here is regenerable build state — no credentials, which stay
|
|
42
|
+
* unreadable via {@link sensitiveReadPaths}.
|
|
43
|
+
*/
|
|
44
|
+
function toolCacheDirs(home) {
|
|
45
|
+
return [
|
|
46
|
+
path.join(home, ".npm"),
|
|
47
|
+
path.join(home, ".cache"),
|
|
48
|
+
path.join(home, "Library", "Caches"),
|
|
49
|
+
path.join(home, ".pnpm-store"),
|
|
50
|
+
path.join(home, ".yarn"),
|
|
51
|
+
path.join(home, ".bun"),
|
|
52
|
+
path.join(home, ".deno"),
|
|
53
|
+
path.join(home, ".cargo"),
|
|
54
|
+
path.join(home, ".rustup"),
|
|
55
|
+
path.join(home, "go", "pkg", "mod"),
|
|
56
|
+
path.join(home, ".m2"),
|
|
57
|
+
path.join(home, ".gradle"),
|
|
58
|
+
path.join(home, ".gem"),
|
|
59
|
+
path.join(home, ".bundle"),
|
|
60
|
+
path.join(home, ".nuget"),
|
|
61
|
+
path.join(home, ".composer"),
|
|
62
|
+
path.join(home, ".local", "share", "virtualenvs"),
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A path plus its symlink-resolved twin.
|
|
67
|
+
*
|
|
68
|
+
* macOS resolves /tmp to /private/tmp and /var/folders to /private/var/folders.
|
|
69
|
+
* The sandbox matches on the real path, so listing only the symlink silently
|
|
70
|
+
* denies every write to the system temp directory.
|
|
71
|
+
*/
|
|
72
|
+
function withRealPath(target) {
|
|
73
|
+
try {
|
|
74
|
+
const real = realpathSync(target);
|
|
75
|
+
return real === target ? [target] : [target, real];
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return [target];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Pure policy builder, exported so the security boundary is regression-tested. */
|
|
82
|
+
export function buildSandboxSettings(cwd, policy, platform = process.platform) {
|
|
83
|
+
const workspace = path.resolve(cwd);
|
|
84
|
+
const temp = path.resolve(os.tmpdir());
|
|
85
|
+
const home = os.homedir();
|
|
86
|
+
const allowedDomains = [
|
|
87
|
+
...new Set([...(policy.strictDomains ? [] : DEFAULT_ALLOWED_DOMAINS), ...policy.allowedDomains]
|
|
88
|
+
.map((host) => host.trim())
|
|
89
|
+
.filter(Boolean)),
|
|
90
|
+
].sort();
|
|
91
|
+
// Mirror resolveWriteGuard's roots. The sandbox must never be stricter than
|
|
92
|
+
// the write guard the user already controls, or bash silently loses
|
|
93
|
+
// multi-root workspaces and the documented outside-workspace opt-out.
|
|
94
|
+
const writeRoots = [
|
|
95
|
+
...new Set([
|
|
96
|
+
workspace,
|
|
97
|
+
...(policy.additionalRoots ?? []).map((root) => path.resolve(root)),
|
|
98
|
+
temp,
|
|
99
|
+
// The conventional scratch dir, distinct from os.tmpdir() on macOS.
|
|
100
|
+
...(platform === "win32" ? [] : ["/tmp"]),
|
|
101
|
+
path.resolve(getAppPaths().agentDir),
|
|
102
|
+
...toolCacheDirs(home),
|
|
103
|
+
...(policy.allowOutsideWorkspaceWrites ? [home] : []),
|
|
104
|
+
].flatMap(withRealPath)),
|
|
105
|
+
];
|
|
106
|
+
return {
|
|
107
|
+
network: {
|
|
108
|
+
allowedDomains,
|
|
109
|
+
deniedDomains: [],
|
|
110
|
+
strictAllowlist: true,
|
|
111
|
+
allowUnixSockets: [],
|
|
112
|
+
// Dev servers, preview servers and the screenshot tool all bind a local
|
|
113
|
+
// port. Loopback never leaves the machine, so blocking it costs core
|
|
114
|
+
// workflows without buying containment.
|
|
115
|
+
allowLocalBinding: true,
|
|
116
|
+
},
|
|
117
|
+
...(platform === "darwin" ? { enableWeakerNetworkIsolation: true } : {}),
|
|
118
|
+
filesystem: {
|
|
119
|
+
denyRead: sensitiveReadPaths(home),
|
|
120
|
+
// SRT adds its platform-required temporary paths; these are the only
|
|
121
|
+
// product-owned write roots supplied by EZ Coder.
|
|
122
|
+
allowWrite: platform === "win32" ? writeRoots : [...writeRoots, "/dev/null"],
|
|
123
|
+
// `.git/hooks` is a mandatory sandbox protection with no opt-out, which
|
|
124
|
+
// is worth keeping: it stops a command installing a hook that later runs
|
|
125
|
+
// unsandboxed. `git clone`/`git init` only write there to copy inert
|
|
126
|
+
// `.sample` files, which SANDBOX_ENV_PATCH turns off.
|
|
127
|
+
//
|
|
128
|
+
// `.git/config` must be writable or `git init`, `git remote add` and
|
|
129
|
+
// `git clone` all fail outright.
|
|
130
|
+
allowGitConfig: true,
|
|
131
|
+
// Resolve the workspace first: on macOS the sandbox matches real paths, so
|
|
132
|
+
// a deny rule built from the symlinked path (/var/... vs /private/var/...)
|
|
133
|
+
// silently never matches.
|
|
134
|
+
denyWrite: withRealPath(workspace).flatMap((root) => [
|
|
135
|
+
path.join(root, ".env"),
|
|
136
|
+
path.join(root, ".env.local"),
|
|
137
|
+
]),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function resolveSandboxCli() {
|
|
142
|
+
const packageEntry = import.meta.resolve("@anthropic-ai/sandbox-runtime");
|
|
143
|
+
return path.join(path.dirname(fileURLToPath(packageEntry)), "cli.js");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Does this machine actually support OS sandboxing? SRT reports missing
|
|
147
|
+
* bubblewrap/socat or an unprovisioned Windows sandbox user only when it
|
|
148
|
+
* initializes, so probe once per process with a trivial command instead of
|
|
149
|
+
* reimplementing its per-platform dependency matrix.
|
|
150
|
+
*/
|
|
151
|
+
let supportProbe = null;
|
|
152
|
+
export function resetSandboxSupportProbeForTests() {
|
|
153
|
+
supportProbe = null;
|
|
154
|
+
warnedUnsupported = false;
|
|
155
|
+
}
|
|
156
|
+
function probeSandboxSupport(settingsPath) {
|
|
157
|
+
supportProbe ??= new Promise((resolve) => {
|
|
158
|
+
let child;
|
|
159
|
+
try {
|
|
160
|
+
child = spawn(process.execPath, [resolveSandboxCli(), "--settings", settingsPath, "-c", "exit 0"], {
|
|
161
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
resolve({ supported: false, reason: error.message });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
let stderr = "";
|
|
169
|
+
child.stderr?.on("data", (chunk) => {
|
|
170
|
+
stderr = `${stderr}${chunk.toString("utf8")}`.slice(-500);
|
|
171
|
+
});
|
|
172
|
+
const timer = setTimeout(() => {
|
|
173
|
+
child.kill("SIGKILL");
|
|
174
|
+
resolve({ supported: false, reason: "sandbox probe timed out" });
|
|
175
|
+
}, PROBE_TIMEOUT_MS);
|
|
176
|
+
timer.unref?.();
|
|
177
|
+
child.once("error", (error) => {
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
resolve({ supported: false, reason: error.message });
|
|
180
|
+
});
|
|
181
|
+
child.once("exit", (code) => {
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
resolve({
|
|
184
|
+
supported: code === 0,
|
|
185
|
+
reason: code === 0 ? "ok" : stderr.trim() || `sandbox probe exited with code ${code}`,
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
return supportProbe;
|
|
190
|
+
}
|
|
191
|
+
async function writeStableSettings(settings) {
|
|
192
|
+
const json = `${JSON.stringify(settings, null, 2)}\n`;
|
|
193
|
+
const digest = createHash("sha256").update(json).digest("hex").slice(0, 20);
|
|
194
|
+
const settingsPath = path.join(SANDBOX_CONFIG_DIR, `${digest}.json`);
|
|
195
|
+
await fs.mkdir(SANDBOX_CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
196
|
+
try {
|
|
197
|
+
await fs.writeFile(settingsPath, json, { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
if (error.code !== "EEXIST")
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
return settingsPath;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Known limitations when `sandboxMode` is enabled (upstream, not fixable here):
|
|
207
|
+
*
|
|
208
|
+
* - **Linux pipes/redirections**: `echo hi | grep hi` fails with "Permission
|
|
209
|
+
* denied" on /proc/self/fd/3 because bash's pipe setup clobbers the fd the
|
|
210
|
+
* seccomp filter arrives on (sandbox-runtime#261).
|
|
211
|
+
* - **git over SSH**: `git@host:` remotes fail the SOCKS handshake on macOS —
|
|
212
|
+
* the injected ProxyCommand uses `nc`, which cannot authenticate. HTTPS
|
|
213
|
+
* remotes work. `~/.ssh` is also unreadable by design.
|
|
214
|
+
* - **`git config --global`**: `~/.gitconfig` is a mandatory upstream write
|
|
215
|
+
* protection with no opt-out. Repo-local `git config` works.
|
|
216
|
+
* - **Corporate TLS interception / private registries**: need the CA and
|
|
217
|
+
* registry host configured explicitly.
|
|
218
|
+
* - **Ubuntu 24.04+**: AppArmor blocks the sandbox entirely, so `auto`
|
|
219
|
+
* degrades to no isolation (sandbox-runtime#428, #429).
|
|
220
|
+
*
|
|
221
|
+
* These are why the default is `off`; revisit when fixed upstream.
|
|
222
|
+
*/
|
|
223
|
+
/**
|
|
224
|
+
* Wrap an already-resolved shell with Anthropic's cross-platform OS sandbox.
|
|
225
|
+
* Initialization and dependency failures remain visible and fail closed: the
|
|
226
|
+
* original command is never spawned outside the sandbox as an implicit fallback.
|
|
227
|
+
*/
|
|
228
|
+
export async function prepareSandboxLaunch(shell, cwd, policy) {
|
|
229
|
+
if (policy.mode === "off")
|
|
230
|
+
return { ...shell, sandboxed: false };
|
|
231
|
+
const settingsPath = await writeStableSettings(buildSandboxSettings(cwd, policy));
|
|
232
|
+
const support = await probeSandboxSupport(settingsPath);
|
|
233
|
+
if (!support.supported) {
|
|
234
|
+
if (policy.mode === "workspace") {
|
|
235
|
+
throw new Error(`${support.reason}. Install the OS sandbox prerequisites ` +
|
|
236
|
+
`(Linux: bubblewrap + socat; Windows: run \`srt windows-install\`), ` +
|
|
237
|
+
`or set sandboxMode to "auto" to run without OS isolation.`);
|
|
238
|
+
}
|
|
239
|
+
if (!warnedUnsupported) {
|
|
240
|
+
warnedUnsupported = true;
|
|
241
|
+
log("WARN", "sandbox", "OS sandbox unavailable; commands run unisolated", {
|
|
242
|
+
reason: support.reason,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return { ...shell, sandboxed: false };
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
file: process.execPath,
|
|
249
|
+
args: [resolveSandboxCli(), "--settings", settingsPath, "--", shell.file, ...shell.args],
|
|
250
|
+
isCmdFallback: shell.isCmdFallback,
|
|
251
|
+
sandboxed: true,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/core/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.test.d.ts","sourceRoot":"","sources":["../../src/core/sandbox.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { getAppPaths } from "../config.js";
|
|
6
|
+
import { DEFAULT_SETTINGS } from "./settings-manager.js";
|
|
7
|
+
import { buildSandboxSettings, prepareSandboxLaunch, resetSandboxSupportProbeForTests, } from "./sandbox.js";
|
|
8
|
+
describe("buildSandboxSettings", () => {
|
|
9
|
+
it("limits writes to the workspace and temp directory, and enforces an allowlist", () => {
|
|
10
|
+
// A real directory, so symlinked temp roots (macOS /var → /private/var) are
|
|
11
|
+
// exercised rather than silently skipped.
|
|
12
|
+
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "gg-sandbox-workspace-"));
|
|
13
|
+
const settings = buildSandboxSettings(cwd, { mode: "workspace", allowedDomains: [] }, "darwin");
|
|
14
|
+
expect(settings.filesystem.allowWrite).toEqual(expect.arrayContaining([
|
|
15
|
+
fs.realpathSync(path.resolve(cwd)),
|
|
16
|
+
fs.realpathSync(path.resolve(os.tmpdir())),
|
|
17
|
+
getAppPaths().agentDir,
|
|
18
|
+
]));
|
|
19
|
+
expect(settings.filesystem.allowWrite).not.toContain(os.homedir());
|
|
20
|
+
// The sandbox matches real paths, so a deny rule must cover the resolved
|
|
21
|
+
// workspace or it silently never fires (macOS /var → /private/var).
|
|
22
|
+
expect(settings.filesystem.denyWrite).toEqual(expect.arrayContaining([path.join(fs.realpathSync(path.resolve(cwd)), ".env")]));
|
|
23
|
+
expect(settings.filesystem.denyRead).toEqual(expect.arrayContaining([
|
|
24
|
+
path.join(os.homedir(), ".ssh"),
|
|
25
|
+
path.join(os.homedir(), ".ezcoder", "auth.json"),
|
|
26
|
+
]));
|
|
27
|
+
expect(settings.network).toMatchObject({
|
|
28
|
+
strictAllowlist: true,
|
|
29
|
+
allowUnixSockets: [],
|
|
30
|
+
// Dev servers and the screenshot tool bind loopback; blocking it would
|
|
31
|
+
// break core workflows without containing anything.
|
|
32
|
+
allowLocalBinding: true,
|
|
33
|
+
});
|
|
34
|
+
// Egress is an allowlist, never open: an unknown host stays unreachable.
|
|
35
|
+
expect(settings.network.allowedDomains).not.toContain("api.example.com");
|
|
36
|
+
});
|
|
37
|
+
it("keeps bash writable in the same roots the write guard already allows", () => {
|
|
38
|
+
const cwd = path.join(os.tmpdir(), "gg-sandbox-workspace");
|
|
39
|
+
const extraRoot = path.join(os.tmpdir(), "gg-sandbox-second-root");
|
|
40
|
+
const settings = buildSandboxSettings(cwd, { mode: "workspace", allowedDomains: [], additionalRoots: [extraRoot] }, "darwin");
|
|
41
|
+
// Multi-root sessions and ~/.ezcoder must not silently lose bash writes.
|
|
42
|
+
expect(settings.filesystem.allowWrite).toEqual(expect.arrayContaining([path.resolve(cwd), path.resolve(extraRoot), getAppPaths().agentDir]));
|
|
43
|
+
expect(settings.filesystem.allowWrite).not.toContain(os.homedir());
|
|
44
|
+
});
|
|
45
|
+
it("honors the outside-workspace opt-out instead of contradicting the user", () => {
|
|
46
|
+
const settings = buildSandboxSettings(path.join(os.tmpdir(), "gg-sandbox-workspace"), { mode: "workspace", allowedDomains: [], allowOutsideWorkspaceWrites: true }, "darwin");
|
|
47
|
+
expect(settings.filesystem.allowWrite).toContain(os.homedir());
|
|
48
|
+
// Consenting to write outside the workspace is not consent to leak secrets.
|
|
49
|
+
expect(settings.filesystem.denyRead).toContain(path.join(os.homedir(), ".ssh"));
|
|
50
|
+
});
|
|
51
|
+
it("normalizes and de-duplicates explicit network domains deterministically", () => {
|
|
52
|
+
const settings = buildSandboxSettings("/workspace", {
|
|
53
|
+
mode: "workspace",
|
|
54
|
+
allowedDomains: [" registry.npmjs.org ", "github.com", "github.com", ""],
|
|
55
|
+
strictDomains: true,
|
|
56
|
+
});
|
|
57
|
+
expect(settings.network.allowedDomains).toEqual(["github.com", "registry.npmjs.org"]);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("sandbox defaults", () => {
|
|
61
|
+
it("stays opt-in while upstream breaks core workflows", () => {
|
|
62
|
+
// Verified upstream breakage: Linux pipes/redirections fail under seccomp,
|
|
63
|
+
// macOS git-over-SSH fails the SOCKS handshake, and `git config --global`
|
|
64
|
+
// is refused. Turning this on by default would break `git push` and piped
|
|
65
|
+
// commands right after an update. Revisit when those are fixed upstream.
|
|
66
|
+
expect(DEFAULT_SETTINGS.sandboxMode).toBe("off");
|
|
67
|
+
});
|
|
68
|
+
it("reaches mainstream toolchains out of the box, so the default is invisible", () => {
|
|
69
|
+
const { network } = buildSandboxSettings("/workspace", {
|
|
70
|
+
mode: "auto",
|
|
71
|
+
allowedDomains: [],
|
|
72
|
+
});
|
|
73
|
+
// If any of these were missing, `npm install` / `pip install` / `git clone`
|
|
74
|
+
// would fail for every user the moment the sandbox shipped on.
|
|
75
|
+
for (const host of [
|
|
76
|
+
"github.com",
|
|
77
|
+
"registry.npmjs.org",
|
|
78
|
+
"pypi.org",
|
|
79
|
+
"files.pythonhosted.org",
|
|
80
|
+
"proxy.golang.org",
|
|
81
|
+
"crates.io",
|
|
82
|
+
"rubygems.org",
|
|
83
|
+
]) {
|
|
84
|
+
expect(network.allowedDomains).toContain(host);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
it("rejects patterns the sandbox itself refuses, so a bad entry cannot brick startup", () => {
|
|
88
|
+
const { network } = buildSandboxSettings("/workspace", {
|
|
89
|
+
mode: "auto",
|
|
90
|
+
allowedDomains: [],
|
|
91
|
+
});
|
|
92
|
+
for (const domain of network.allowedDomains) {
|
|
93
|
+
expect(domain).not.toBe("*");
|
|
94
|
+
// sandbox-runtime rejects overly broad wildcards like "*.com".
|
|
95
|
+
expect(domain).not.toMatch(/^\*\.[a-z]+$/);
|
|
96
|
+
expect(domain).not.toMatch(/[:/]/);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
it("adds user hosts to the defaults, and honors an explicit takeover", () => {
|
|
100
|
+
const merged = buildSandboxSettings("/workspace", {
|
|
101
|
+
mode: "auto",
|
|
102
|
+
allowedDomains: ["internal.example.com"],
|
|
103
|
+
});
|
|
104
|
+
expect(merged.network.allowedDomains).toContain("internal.example.com");
|
|
105
|
+
expect(merged.network.allowedDomains).toContain("github.com");
|
|
106
|
+
const strict = buildSandboxSettings("/workspace", {
|
|
107
|
+
mode: "auto",
|
|
108
|
+
allowedDomains: ["internal.example.com"],
|
|
109
|
+
strictDomains: true,
|
|
110
|
+
});
|
|
111
|
+
expect(strict.network.allowedDomains).toEqual(["internal.example.com"]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("prepareSandboxLaunch", () => {
|
|
115
|
+
const shell = { file: "bash", args: ["-c", "echo ok"], isCmdFallback: false };
|
|
116
|
+
beforeEach(() => resetSandboxSupportProbeForTests());
|
|
117
|
+
afterEach(() => {
|
|
118
|
+
vi.unstubAllEnvs();
|
|
119
|
+
resetSandboxSupportProbeForTests();
|
|
120
|
+
});
|
|
121
|
+
it("preserves the original shell only for explicit sandbox opt-out", async () => {
|
|
122
|
+
await expect(prepareSandboxLaunch(shell, "/workspace", { mode: "off", allowedDomains: [] })).resolves.toEqual({ ...shell, sandboxed: false });
|
|
123
|
+
});
|
|
124
|
+
it("wraps the command where isolation is available, and honors the mode contract where it is not", async () => {
|
|
125
|
+
// Whether an OS sandbox is usable is a property of the host, not of this
|
|
126
|
+
// code: CI Linux has no bwrap/socat and CI Windows has no provisioned
|
|
127
|
+
// sandbox user. `auto` never throws, so it reports which branch applies.
|
|
128
|
+
const probe = await prepareSandboxLaunch(shell, os.tmpdir(), {
|
|
129
|
+
mode: "auto",
|
|
130
|
+
allowedDomains: [],
|
|
131
|
+
});
|
|
132
|
+
if (!probe.sandboxed) {
|
|
133
|
+
// Unsupported host: `auto` degrades and `workspace` fails closed.
|
|
134
|
+
expect(probe).toEqual({ ...shell, sandboxed: false });
|
|
135
|
+
await expect(prepareSandboxLaunch(shell, os.tmpdir(), { mode: "workspace", allowedDomains: [] })).rejects.toThrow(/Install the OS sandbox prerequisites/);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const launch = await prepareSandboxLaunch(shell, os.tmpdir(), {
|
|
139
|
+
mode: "workspace",
|
|
140
|
+
allowedDomains: [],
|
|
141
|
+
});
|
|
142
|
+
expect(launch.sandboxed).toBe(true);
|
|
143
|
+
expect(launch.file).toBe(process.execPath);
|
|
144
|
+
expect(launch.args).toEqual(expect.arrayContaining(["--settings", "--", "bash", "-c", "echo ok"]));
|
|
145
|
+
});
|
|
146
|
+
it("degrades instead of breaking every command when prerequisites are missing", async () => {
|
|
147
|
+
// An unusable interpreter makes the probe child exit non-zero, standing in
|
|
148
|
+
// for bwrap-less Linux or an unprovisioned Windows sandbox user.
|
|
149
|
+
vi.spyOn(process, "execPath", "get").mockReturnValue("/nonexistent/gg-node");
|
|
150
|
+
await expect(prepareSandboxLaunch(shell, os.tmpdir(), { mode: "auto", allowedDomains: [] })).resolves.toEqual({ ...shell, sandboxed: false });
|
|
151
|
+
});
|
|
152
|
+
it("fails closed in strict workspace mode with actionable install guidance", async () => {
|
|
153
|
+
vi.spyOn(process, "execPath", "get").mockReturnValue("/nonexistent/gg-node");
|
|
154
|
+
await expect(prepareSandboxLaunch(shell, os.tmpdir(), { mode: "workspace", allowedDomains: [] })).rejects.toThrow(/bubblewrap \+ socat|windows-install/);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=sandbox.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.test.js","sourceRoot":"","sources":["../../src/core/sandbox.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Message, Provider } from "@prestyj/ai";
|
|
2
2
|
import type { SessionManager } from "./session-manager.js";
|
|
3
|
+
/** Stable identity for one compaction source, including internal provenance. */
|
|
4
|
+
export declare function sourceFingerprint(messages: readonly Message[]): string;
|
|
3
5
|
export declare function appendMessagesToSession(sessionManager: SessionManager, sessionPath: string, messages: readonly Message[], startIndex?: number): Promise<void>;
|
|
4
6
|
export declare function createCompactedSessionCheckpoint(sessionManager: SessionManager, options: {
|
|
5
7
|
cwd: string;
|
|
@@ -7,6 +9,10 @@ export declare function createCompactedSessionCheckpoint(sessionManager: Session
|
|
|
7
9
|
model: string;
|
|
8
10
|
messages: readonly Message[];
|
|
9
11
|
conversationId?: string;
|
|
12
|
+
generation?: number;
|
|
13
|
+
parentSessionId?: string;
|
|
14
|
+
sourceFingerprint?: string;
|
|
15
|
+
retainedMessageCount?: number;
|
|
10
16
|
preview?: string;
|
|
11
17
|
title?: string;
|
|
12
18
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-compaction.d.ts","sourceRoot":"","sources":["../../src/core/session-compaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"session-compaction.d.ts","sourceRoot":"","sources":["../../src/core/session-compaction.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAA4B,MAAM,sBAAsB,CAAC;AAErF,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAGtE;AAED,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,UAAU,SAAI,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,gCAAgC,CACpD,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE;IACP,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBvC;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE,CAIrF;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAK1F"}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
+
import { getHistoryMessageVisibility } from "./session-history.js";
|
|
3
|
+
/** Stable identity for one compaction source, including internal provenance. */
|
|
4
|
+
export function sourceFingerprint(messages) {
|
|
5
|
+
const source = messages.filter((message) => message.role !== "system");
|
|
6
|
+
return crypto.createHash("sha256").update(JSON.stringify(source)).digest("hex");
|
|
7
|
+
}
|
|
2
8
|
export async function appendMessagesToSession(sessionManager, sessionPath, messages, startIndex = 0) {
|
|
3
9
|
for (let i = startIndex; i < messages.length; i++) {
|
|
4
10
|
const msg = messages[i];
|
|
@@ -17,6 +23,10 @@ export async function appendMessagesToSession(sessionManager, sessionPath, messa
|
|
|
17
23
|
export async function createCompactedSessionCheckpoint(sessionManager, options) {
|
|
18
24
|
const session = await sessionManager.create(options.cwd, options.provider, options.model, {
|
|
19
25
|
conversationId: options.conversationId,
|
|
26
|
+
generation: options.generation,
|
|
27
|
+
parentSessionId: options.parentSessionId,
|
|
28
|
+
sourceFingerprint: options.sourceFingerprint,
|
|
29
|
+
retainedMessageCount: options.retainedMessageCount,
|
|
20
30
|
preview: options.preview ?? options.title,
|
|
21
31
|
});
|
|
22
32
|
await appendMessagesToSession(sessionManager, session.path, options.messages, 0);
|
|
@@ -33,7 +43,7 @@ export async function createCompactedSessionCheckpoint(sessionManager, options)
|
|
|
33
43
|
return { path: session.path, id: session.id };
|
|
34
44
|
}
|
|
35
45
|
export function getRestoredMessagesForDisplay(messages) {
|
|
36
|
-
return messages.filter((
|
|
46
|
+
return messages.filter((message) => message.role !== "system" && getHistoryMessageVisibility(message) !== "hidden");
|
|
37
47
|
}
|
|
38
48
|
export function formatRestoreInfoText(originalCount, restoredCount) {
|
|
39
49
|
if (originalCount === restoredCount) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-compaction.js","sourceRoot":"","sources":["../../src/core/session-compaction.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"session-compaction.js","sourceRoot":"","sources":["../../src/core/session-compaction.ts"],"names":[],"mappings":"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"}
|