@greppleai/grip 0.1.5 → 0.1.7
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 +35 -0
- package/README.md +1 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/embedded-assets.d.ts.map +1 -1
- package/dist/bun/embedded-assets.js.map +1 -1
- package/dist/bun/register-bedrock.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.js.map +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +38 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +289 -154
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -10
- 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 +19 -23
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +9 -2
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -1
- package/dist/core/compaction/compression-detection-ledger.js.map +1 -1
- package/dist/core/compaction/compression-detector.d.ts +1 -0
- package/dist/core/compaction/compression-detector.d.ts.map +1 -1
- package/dist/core/compaction/compression-detector.js +10 -21
- package/dist/core/compaction/compression-detector.js.map +1 -1
- package/dist/core/compaction/compression-economics.d.ts.map +1 -1
- package/dist/core/compaction/compression-economics.js.map +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +40 -30
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +21 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +15 -16
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/grip-agent.d.ts.map +1 -1
- package/dist/core/grip-agent.js +7 -21
- package/dist/core/grip-agent.js.map +1 -1
- package/dist/core/grip-manifest.d.ts.map +1 -1
- package/dist/core/grip-manifest.js.map +1 -1
- package/dist/core/hooks/aggregate.d.ts.map +1 -1
- package/dist/core/hooks/aggregate.js.map +1 -1
- package/dist/core/hooks/config.d.ts.map +1 -1
- package/dist/core/hooks/config.js.map +1 -1
- package/dist/core/hooks/executor.d.ts.map +1 -1
- package/dist/core/hooks/executor.js.map +1 -1
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js.map +1 -1
- package/dist/core/hooks/matcher.d.ts.map +1 -1
- package/dist/core/hooks/matcher.js.map +1 -1
- package/dist/core/hooks/trust-store.d.ts.map +1 -1
- package/dist/core/hooks/trust-store.js +0 -3
- package/dist/core/hooks/trust-store.js.map +1 -1
- package/dist/core/hooks/types.d.ts.map +1 -1
- package/dist/core/hooks/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/instruction-resource-loader.d.ts +1 -0
- package/dist/core/instruction-resource-loader.d.ts.map +1 -1
- package/dist/core/instruction-resource-loader.js +2 -4
- package/dist/core/instruction-resource-loader.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/lsp/abort.d.ts.map +1 -1
- package/dist/core/lsp/abort.js.map +1 -1
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +8 -22
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/config-loader.d.ts.map +1 -1
- package/dist/core/lsp/config-loader.js.map +1 -1
- package/dist/core/lsp/config.d.ts.map +1 -1
- package/dist/core/lsp/config.js.map +1 -1
- package/dist/core/lsp/diagnostics.d.ts.map +1 -1
- package/dist/core/lsp/diagnostics.js.map +1 -1
- package/dist/core/lsp/file-sync.d.ts.map +1 -1
- package/dist/core/lsp/file-sync.js +7 -9
- package/dist/core/lsp/file-sync.js.map +1 -1
- package/dist/core/lsp/integration.d.ts.map +1 -1
- package/dist/core/lsp/integration.js.map +1 -1
- package/dist/core/lsp/language-map.d.ts.map +1 -1
- package/dist/core/lsp/language-map.js +2 -7
- package/dist/core/lsp/language-map.js.map +1 -1
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +18 -29
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/navigation.d.ts.map +1 -1
- package/dist/core/lsp/navigation.js.map +1 -1
- package/dist/core/lsp/portable-path.d.ts.map +1 -1
- package/dist/core/lsp/portable-path.js.map +1 -1
- package/dist/core/lsp/refactor.d.ts.map +1 -1
- package/dist/core/lsp/refactor.js.map +1 -1
- package/dist/core/lsp/transport.d.ts.map +1 -1
- package/dist/core/lsp/transport.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +30 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -7
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +0 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/contract.js +4 -2
- package/dist/core/remote-workspace-protocol/contract.js.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-client.js +1 -5
- package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +5 -10
- package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +2 -9
- package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -1
- package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -1
- package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -1
- package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/session.js +27 -65
- package/dist/core/remote-workspace-protocol/session.js.map +1 -1
- package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -1
- package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +0 -48
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/rules.d.ts.map +1 -1
- package/dist/core/rules.js.map +1 -1
- package/dist/core/sandbox/command.d.ts.map +1 -1
- package/dist/core/sandbox/command.js.map +1 -1
- package/dist/core/sandbox/config.d.ts.map +1 -1
- package/dist/core/sandbox/config.js.map +1 -1
- package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -1
- package/dist/core/sandbox/lima-guest-binary.js.map +1 -1
- package/dist/core/sandbox/lima.d.ts +2 -0
- package/dist/core/sandbox/lima.d.ts.map +1 -1
- package/dist/core/sandbox/lima.js +3 -9
- package/dist/core/sandbox/lima.js.map +1 -1
- package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -1
- package/dist/core/sandbox/shared-lima-roots.js.map +1 -1
- package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -1
- package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -1
- package/dist/core/session/constants.d.ts.map +1 -1
- package/dist/core/session/context-metadata.d.ts.map +1 -1
- package/dist/core/session/context-metadata.js.map +1 -1
- package/dist/core/session/context.d.ts.map +1 -1
- package/dist/core/session/context.js.map +1 -1
- package/dist/core/session/ids.d.ts.map +1 -1
- package/dist/core/session/ids.js.map +1 -1
- package/dist/core/session/in-memory-session-manager.d.ts.map +1 -1
- package/dist/core/session/in-memory-session-manager.js +0 -1
- package/dist/core/session/in-memory-session-manager.js.map +1 -1
- package/dist/core/session/in-memory-session.d.ts.map +1 -1
- package/dist/core/session/in-memory-session.js.map +1 -1
- package/dist/core/session/jsonl-errors.d.ts.map +1 -1
- package/dist/core/session/jsonl-errors.js +0 -11
- package/dist/core/session/jsonl-errors.js.map +1 -1
- package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
- package/dist/core/session/jsonl-helpers.js.map +1 -1
- package/dist/core/session/local-session-manager.d.ts.map +1 -1
- package/dist/core/session/local-session-manager.js +4 -6
- package/dist/core/session/local-session-manager.js.map +1 -1
- package/dist/core/session/local-session.d.ts.map +1 -1
- package/dist/core/session/local-session.js.map +1 -1
- package/dist/core/session/migrations.d.ts.map +1 -1
- package/dist/core/session/migrations.js.map +1 -1
- package/dist/core/session/remote-session-client.d.ts.map +1 -1
- package/dist/core/session/remote-session-client.js +0 -6
- package/dist/core/session/remote-session-client.js.map +1 -1
- package/dist/core/session/remote-session-manager.d.ts.map +1 -1
- package/dist/core/session/remote-session-manager.js +0 -3
- package/dist/core/session/remote-session-manager.js.map +1 -1
- package/dist/core/session/remote-session.d.ts.map +1 -1
- package/dist/core/session/remote-session.js +0 -1
- package/dist/core/session/remote-session.js.map +1 -1
- package/dist/core/session/session-manager.d.ts.map +1 -1
- package/dist/core/session/session.d.ts.map +1 -1
- package/dist/core/session/session.js +1 -5
- package/dist/core/session/session.js.map +1 -1
- package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -1
- package/dist/core/session/stores/in-memory-session-store.js +7 -6
- package/dist/core/session/stores/in-memory-session-store.js.map +1 -1
- package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
- package/dist/core/session/stores/jsonl-session-store.js +6 -14
- package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
- package/dist/core/session/stores/remote-session-store.d.ts.map +1 -1
- package/dist/core/session/stores/remote-session-store.js +3 -8
- package/dist/core/session/stores/remote-session-store.js.map +1 -1
- package/dist/core/session/stores/session-store.d.ts.map +1 -1
- package/dist/core/session/types.d.ts.map +1 -1
- package/dist/core/session/usage-ledger.d.ts.map +1 -1
- package/dist/core/session/usage-ledger.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +0 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +3 -2
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -28
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/compress-context.d.ts.map +1 -1
- package/dist/core/tools/compress-context.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/hash-store.d.ts.map +1 -1
- package/dist/core/tools/hash-store.js.map +1 -1
- package/dist/core/tools/hashline/apply.d.ts.map +1 -1
- package/dist/core/tools/hashline/apply.js.map +1 -1
- package/dist/core/tools/hashline/hash.d.ts.map +1 -1
- package/dist/core/tools/hashline/hash.js.map +1 -1
- package/dist/core/tools/hashline/parse.d.ts.map +1 -1
- package/dist/core/tools/hashline/parse.js.map +1 -1
- package/dist/core/tools/hashline/resolve.d.ts.map +1 -1
- package/dist/core/tools/hashline/resolve.js.map +1 -1
- package/dist/core/tools/hashline-utils.d.ts.map +1 -1
- package/dist/core/tools/hashline-utils.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/operations.d.ts +11 -0
- package/dist/core/tools/operations.d.ts.map +1 -1
- package/dist/core/tools/operations.js +54 -28
- package/dist/core/tools/operations.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +12 -18
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/replace-diff.d.ts.map +1 -1
- package/dist/core/tools/replace-diff.js.map +1 -1
- package/dist/core/tools/replace-normalize.d.ts.map +1 -1
- package/dist/core/tools/replace-normalize.js.map +1 -1
- package/dist/core/tools/replace-render.d.ts +1 -1
- package/dist/core/tools/replace-render.d.ts.map +1 -1
- package/dist/core/tools/replace-render.js.map +1 -1
- package/dist/core/tools/runtime.d.ts.map +1 -1
- package/dist/core/tools/runtime.js.map +1 -1
- package/dist/core/tools/session-history.d.ts.map +1 -1
- package/dist/core/tools/session-history.js.map +1 -1
- package/dist/core/tools/subagent-agents.d.ts.map +1 -1
- package/dist/core/tools/subagent-agents.js.map +1 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/core/tools/workspace-tool-host.d.ts +1 -0
- package/dist/core/tools/workspace-tool-host.d.ts.map +1 -1
- package/dist/core/tools/workspace-tool-host.js +36 -22
- package/dist/core/tools/workspace-tool-host.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +0 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/workspace-identity.d.ts.map +1 -1
- package/dist/daemon/activity-budget.d.ts.map +1 -1
- package/dist/daemon/activity-budget.js +2 -3
- package/dist/daemon/activity-budget.js.map +1 -1
- package/dist/daemon/command.d.ts.map +1 -1
- package/dist/daemon/command.js.map +1 -1
- package/dist/daemon/config.d.ts +2 -0
- package/dist/daemon/config.d.ts.map +1 -1
- package/dist/daemon/config.js +4 -0
- package/dist/daemon/config.js.map +1 -1
- package/dist/daemon/help.d.ts.map +1 -1
- package/dist/daemon/help.js +4 -3
- package/dist/daemon/help.js.map +1 -1
- package/dist/daemon/lsp-config.d.ts.map +1 -1
- package/dist/daemon/lsp-config.js.map +1 -1
- package/dist/daemon/outbound-budget.d.ts.map +1 -1
- package/dist/daemon/outbound-budget.js +2 -4
- package/dist/daemon/outbound-budget.js.map +1 -1
- package/dist/daemon/security.d.ts.map +1 -1
- package/dist/daemon/security.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/shared-connection.d.ts.map +1 -1
- package/dist/daemon/shared-connection.js +10 -15
- package/dist/daemon/shared-connection.js.map +1 -1
- package/dist/daemon/shared-revision.d.ts.map +1 -1
- package/dist/daemon/shared-revision.js +2 -1
- package/dist/daemon/shared-revision.js.map +1 -1
- package/dist/daemon/shared-roots.d.ts.map +1 -1
- package/dist/daemon/shared-roots.js +0 -1
- package/dist/daemon/shared-roots.js.map +1 -1
- package/dist/daemon/workspace-runtime.d.ts +2 -0
- package/dist/daemon/workspace-runtime.d.ts.map +1 -1
- package/dist/daemon/workspace-runtime.js +43 -15
- package/dist/daemon/workspace-runtime.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +8 -3
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +3 -10
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +0 -3
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -3
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +6 -16
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +0 -5
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +1 -8
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -6
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -7
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +2 -8
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +1 -9
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -4
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/hook-execution.js +2 -5
- package/dist/modes/interactive/components/hook-execution.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -9
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/message-card.d.ts.map +1 -1
- package/dist/modes/interactive/components/message-card.js +0 -1
- package/dist/modes/interactive/components/message-card.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +13 -28
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -12
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +9 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +33 -58
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +0 -4
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +0 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +0 -2
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +0 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +9 -24
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +18 -34
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +0 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +13 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +162 -136
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +0 -7
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +10 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +33 -2
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/binary-self-update.d.ts +25 -0
- package/dist/utils/binary-self-update.d.ts.map +1 -0
- package/dist/utils/binary-self-update.js +159 -0
- package/dist/utils/binary-self-update.js.map +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts.map +1 -1
- package/dist/utils/deprecation.js.map +1 -1
- package/dist/utils/directory-completions.d.ts +8 -0
- package/dist/utils/directory-completions.d.ts.map +1 -1
- package/dist/utils/directory-completions.js +42 -1
- package/dist/utils/directory-completions.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/grip-user-agent.d.ts.map +1 -1
- package/dist/utils/grip-user-agent.js.map +1 -1
- package/dist/utils/html.d.ts.map +1 -1
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts.map +1 -1
- package/dist/utils/image-process.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js +10 -5
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +1 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- 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.map +1 -1
- package/docs/extensions.md +31 -1
- package/docs/sandbox.md +6 -0
- package/docs/sessions.md +1 -1
- package/docs/skills.md +4 -4
- package/docs/usage.md +2 -1
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +602 -834
- package/package.json +20 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n\tcreateServer as createHttpServer,\n\ttype Server as HttpServer,\n\ttype IncomingMessage,\n\ttype ServerResponse,\n} from \"node:http\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo, Socket } from \"node:net\";\nimport WebSocket, { type RawData, WebSocketServer } from \"ws\";\nimport type { RemoteWorkspaceServerMessage } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceProtocolCloseCode,\n\ttype RemoteWorkspaceProtocolCloseReason,\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tSHARED_WORKSPACE_WEBSOCKET_PROTOCOL,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport { DAEMON_WEBSOCKET_PATH, type DaemonConfiguration } from \"./config.ts\";\nimport { DaemonOutboundBudget } from \"./outbound-budget.ts\";\nimport {\n\tcreateDaemonAuthorization,\n\trejectDaemonUpgrade,\n\tvalidateDaemonNetworkPolicy,\n\tvalidateDaemonUpgrade,\n} from \"./security.ts\";\nimport { SharedDaemonConnection } from \"./shared-connection.ts\";\nimport { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\nexport interface DaemonServerAddress {\n\treadonly host: string;\n\treadonly port: number;\n\treadonly secure: boolean;\n\treadonly url: string;\n\treadonly workspaceRoot: string;\n\treadonly workspaceId: string;\n}\n\nexport type DaemonServerState = \"created\" | \"listening\" | \"closing\" | \"closed\";\n\nexport interface DaemonServer {\n\tlisten(): Promise<DaemonServerAddress>;\n\taddress(): DaemonServerAddress | undefined;\n\tstate(): DaemonServerState;\n\treload(): Promise<void>;\n\tclose(): Promise<void>;\n\tforceClose(): Promise<void>;\n}\n\ninterface DaemonConnection {\n\treadonly websocket: WebSocket;\n\treadonly protocol: RemoteWorkspaceServerProtocol | SharedDaemonConnection;\n\tclosed: Promise<void>;\n}\n\nfunction websocketPayload(data: RawData): Uint8Array {\n\tif (Buffer.isBuffer(data)) return Uint8Array.from(data);\n\tif (Array.isArray(data)) return Uint8Array.from(Buffer.concat(data));\n\treturn Uint8Array.from(new Uint8Array(data));\n}\n\nfunction websocketCloseCode(code: RemoteWorkspaceProtocolCloseCode): number {\n\tswitch (code) {\n\t\tcase \"normal\":\n\t\t\treturn 1000;\n\t\tcase \"protocol_error\":\n\t\t\treturn 1002;\n\t\tcase \"invalid_payload\":\n\t\t\treturn 1007;\n\t\tcase \"policy_violation\":\n\t\t\treturn 1008;\n\t\tcase \"message_too_large\":\n\t\t\treturn 1009;\n\t}\n}\n\nfunction waitForWebSocketClose(websocket: WebSocket): Promise<void> {\n\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\treturn new Promise((resolve) => websocket.once(\"close\", () => resolve()));\n}\n\nfunction waitWithin(promise: Promise<unknown>, timeoutMs: number, forceSignal: AbortSignal): Promise<boolean> {\n\tif (forceSignal.aborted) return Promise.resolve(false);\n\treturn new Promise((resolve) => {\n\t\tlet settled = false;\n\t\tconst finish = (value: boolean) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tforceSignal.removeEventListener(\"abort\", onForce);\n\t\t\tresolve(value);\n\t\t};\n\t\tconst timer = setTimeout(() => finish(false), timeoutMs);\n\t\tconst onForce = () => finish(false);\n\t\tforceSignal.addEventListener(\"abort\", onForce, { once: true });\n\t\tpromise.then(\n\t\t\t() => finish(true),\n\t\t\t() => finish(false),\n\t\t);\n\t});\n}\nfunction terminateDaemonConnections(connections: Iterable<DaemonConnection>): void {\n\tfor (const connection of connections) connection.websocket.terminate();\n}\n\nfunction beginDaemonConnectionDrain(\n\tconnections: readonly DaemonConnection[],\n\thostDisposal: Promise<void>,\n): Promise<void> {\n\treturn Promise.allSettled([...connections.map((connection) => connection.protocol.beginDrain()), hostDisposal]).then(\n\t\t() => undefined,\n\t);\n}\n\nfunction disconnectDaemonConnections(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.protocol.disconnect())).then(() => undefined);\n}\n\nfunction requestDaemonConnectionClose(connections: readonly DaemonConnection[]): void {\n\tfor (const connection of connections) {\n\t\tif (connection.websocket.readyState === WebSocket.OPEN) {\n\t\t\tconnection.websocket.close(1001, \"Daemon shutting down\");\n\t\t}\n\t}\n}\n\nfunction waitForDaemonConnectionsClosed(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.closed)).then(() => undefined);\n}\n\nfunction destroyDaemonSockets(sockets: ReadonlySet<Socket>): void {\n\tfor (const socket of sockets) socket.destroy();\n}\n\nfunction formatHostForUrl(host: string): string {\n\treturn host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host;\n}\n\nexport function createDaemonServer(configuration: DaemonConfiguration): DaemonServer {\n\tvalidateDaemonNetworkPolicy(configuration);\n\tconst authorization = createDaemonAuthorization(configuration.token);\n\tconst activityBudget = new DaemonActivityBudget(configuration);\n\tconst workspaceId = randomBytes(18).toString(\"base64url\");\n\tconst workspace = Object.freeze({\n\t\tid: workspaceId,\n\t\troot: configuration.workspaceRoot,\n\t\tpathFlavor: process.platform === \"win32\" ? (\"windows\" as const) : (\"posix\" as const),\n\t});\n\tlet runtime = createDaemonWorkspaceRuntime(configuration);\n\tlet runtimeHandler = runtime.createHandler(workspace);\n\tconst handler: RemoteWorkspaceServerHandler = {\n\t\thandleRequest: (request, context) => {\n\t\t\tif (typeof request.params === \"object\" && request.params !== null && \"expectedRevision\" in request.params) {\n\t\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\t\tcode: \"invalid_request\",\n\t\t\t\t\tmessage: \"Revision preconditions require the v2 shared workspace protocol\",\n\t\t\t\t\texecutionState: \"not_started\",\n\t\t\t\t\tretryable: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn activityBudget.run(request.method, () => runtimeHandler.handleRequest(request, context));\n\t\t},\n\t\tvalidateToolArguments: (toolName, value) => runtimeHandler.validateToolArguments(toolName, value),\n\t};\n\tconst requestListener = (_request: IncomingMessage, response: ServerResponse) => {\n\t\tresponse.writeHead(404, { \"content-type\": \"text/plain\" });\n\t\tresponse.end(\"Not found\\n\");\n\t};\n\tconst server: HttpServer = configuration.tls\n\t\t? createHttpsServer(\n\t\t\t\t{\n\t\t\t\t\tcert: configuration.tls.cert,\n\t\t\t\t\tkey: configuration.tls.key,\n\t\t\t\t\tpassphrase: configuration.tls.passphrase,\n\t\t\t\t\tminVersion: \"TLSv1.2\",\n\t\t\t\t},\n\t\t\t\trequestListener,\n\t\t\t)\n\t\t: createHttpServer(requestListener);\n\tconst websocketServer = new WebSocketServer({\n\t\tnoServer: true,\n\t\tclientTracking: false,\n\t\tmaxPayload: configuration.protocolLimits.maxMessageBytes,\n\t\tperMessageDeflate: false,\n\t\tallowSynchronousEvents: false,\n\t\tskipUTF8Validation: false,\n\t});\n\tconst sockets = new Set<Socket>();\n\tconst pendingSockets = new Set<Socket>();\n\tconst pendingSocketTimers = new Map<Socket, NodeJS.Timeout>();\n\tconst pendingSocketDeadlines = new Map<Socket, number>();\n\tconst connections = new Set<DaemonConnection>();\n\tlet sharedRoots: SharedWorkspaceRoots | undefined;\n\tlet catalog = runtime.catalog;\n\tlet reloadQueue: Promise<void> = Promise.resolve();\n\tconst forceController = new AbortController();\n\tlet currentAddress: DaemonServerAddress | undefined;\n\tlet listenPromise: Promise<DaemonServerAddress> | undefined;\n\tlet rejectListen: ((error: Error) => void) | undefined;\n\tlet closePromise: Promise<void> | undefined;\n\tlet serverState: DaemonServerState = \"created\";\n\n\tconst stopListener = (): Promise<void> => {\n\t\tif (!server.listening && !listenPromise) return Promise.resolve();\n\t\treturn new Promise((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\tserver.off(\"close\", onClose);\n\t\t\t};\n\t\t\tconst finish = () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tconst closeListener = () => server.close(() => finish());\n\t\t\tconst onListening = () => closeListener();\n\t\t\tconst onError = () => finish();\n\t\t\tconst onClose = () => finish();\n\t\t\tserver.once(\"error\", onError);\n\t\t\tserver.once(\"close\", onClose);\n\t\t\tif (server.listening) closeListener();\n\t\t\telse server.once(\"listening\", onListening);\n\t\t});\n\t};\n\n\tserver.on(\"connection\", (socket: Socket) => {\n\t\tif (serverState !== \"listening\" || pendingSockets.size >= configuration.maxPendingConnections) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tsockets.add(socket);\n\t\tpendingSockets.add(socket);\n\t\tconst pendingTimer = setTimeout(() => socket.destroy(), configuration.handshakeTimeoutMs);\n\t\tpendingTimer.unref?.();\n\t\tpendingSocketTimers.set(socket, pendingTimer);\n\t\tpendingSocketDeadlines.set(socket, performance.now() + configuration.handshakeTimeoutMs);\n\t\tsocket.once(\"close\", () => {\n\t\t\tsockets.delete(socket);\n\t\t\tpendingSockets.delete(socket);\n\t\t\tconst timer = pendingSocketTimers.get(socket);\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\tpendingSocketTimers.delete(socket);\n\t\t\tpendingSocketDeadlines.delete(socket);\n\t\t});\n\t});\n\n\tserver.on(\"upgrade\", (request, socket, head) => {\n\t\tconst netSocket = socket as Socket;\n\t\tconst decision = validateDaemonUpgrade(request, configuration, authorization);\n\t\tif (!decision.accepted) {\n\t\t\trejectDaemonUpgrade(netSocket, decision);\n\t\t\treturn;\n\t\t}\n\t\tif (serverState !== \"listening\" || connections.size >= configuration.maxConnections) {\n\t\t\trejectDaemonUpgrade(netSocket, { accepted: false, status: 503, message: \"Service unavailable\" });\n\t\t\treturn;\n\t\t}\n\t\tconst handshakeDeadline = pendingSocketDeadlines.get(netSocket) ?? performance.now();\n\t\tpendingSockets.delete(netSocket);\n\t\tconst pendingTimer = pendingSocketTimers.get(netSocket);\n\t\tif (pendingTimer) clearTimeout(pendingTimer);\n\t\tpendingSocketTimers.delete(netSocket);\n\t\tpendingSocketDeadlines.delete(netSocket);\n\t\twebsocketServer.handleUpgrade(request, socket, head, (websocket) => {\n\t\t\tif (serverState !== \"listening\") {\n\t\t\t\twebsocket.terminate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst remainingHandshakeMs = Math.max(0, handshakeDeadline - performance.now());\n\t\t\tconst handshakeTimer = setTimeout(() => {\n\t\t\t\twebsocket.terminate();\n\t\t\t}, remainingHandshakeMs);\n\t\t\thandshakeTimer.unref?.();\n\t\t\tlet protocol: RemoteWorkspaceServerProtocol;\n\t\t\tconst outboundBudget = new DaemonOutboundBudget(\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundBytes,\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundMessages,\n\t\t\t);\n\t\t\tconst transport = {\n\t\t\t\tsend(message: RemoteWorkspaceServerMessage | SharedWorkspaceServerFrame): Promise<void> {\n\t\t\t\t\tif (websocket.readyState !== WebSocket.OPEN) return Promise.reject(new Error(\"WebSocket is not open\"));\n\t\t\t\t\tconst serialized = JSON.stringify(message);\n\t\t\t\t\tconst bytes = Buffer.byteLength(serialized, \"utf8\");\n\t\t\t\t\tlet release: () => void;\n\t\t\t\t\ttry {\n\t\t\t\t\t\trelease = outboundBudget.reserve(bytes, websocket.bufferedAmount);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// No channel can safely continue after a physical send is dropped.\n\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\treturn Promise.reject(error);\n\t\t\t\t\t}\n\t\t\t\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\t// A stalled callback must not pin physical reservations indefinitely. A\n\t\t\t\t\t\t// timed-out send makes the entire uplink uncertain, not just its channel.\n\t\t\t\t\t\tconst deadline = setTimeout(() => {\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(new Error(\"WebSocket outbound send timed out\"));\n\t\t\t\t\t\t}, configuration.protocolLimits.maxTransportSendMs);\n\t\t\t\t\t\tdeadline.unref?.();\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twebsocket.send(serialized, { binary: false, compress: false }, (error) => {\n\t\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t\t} else resolve();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).finally(release);\n\t\t\t\t},\n\t\t\t\tclose(reason: RemoteWorkspaceProtocolCloseReason): Promise<void> {\n\t\t\t\t\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\t\t\t\t\twebsocket.close(websocketCloseCode(reason.code), reason.message);\n\t\t\t\t\treturn waitForWebSocketClose(websocket);\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (websocket.protocol === SHARED_WORKSPACE_WEBSOCKET_PROTOCOL) {\n\t\t\t\tif (!sharedRoots) {\n\t\t\t\t\twebsocket.close(1008, \"Shared parent unavailable\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst shared = new SharedDaemonConnection(\n\t\t\t\t\tconfiguration,\n\t\t\t\t\tsharedRoots,\n\t\t\t\t\ttransport.send,\n\t\t\t\t\t(code, reason) => {\n\t\t\t\t\t\tif (websocket.readyState === WebSocket.OPEN) websocket.close(code, reason);\n\t\t\t\t\t},\n\t\t\t\t\tactivityBudget,\n\t\t\t\t);\n\t\t\t\tconst connection: DaemonConnection = { websocket, protocol: shared, closed: Promise.resolve() };\n\t\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\t\tconnections.delete(connection);\n\t\t\t\t\tawait shared.disconnect().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tconnections.add(connection);\n\t\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\t\tif (isBinary) {\n\t\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvoid shared.receive(websocketPayload(data)).then(() => {\n\t\t\t\t\t\tif (shared.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprotocol = new RemoteWorkspaceServerProtocol(transport, handler, {\n\t\t\t\tworkspace,\n\t\t\t\tcatalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-workspace-daemon\",\n\t\t\t});\n\t\t\tconst connection: DaemonConnection = {\n\t\t\t\twebsocket,\n\t\t\t\tprotocol,\n\t\t\t\tclosed: Promise.resolve(),\n\t\t\t};\n\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\tconnections.delete(connection);\n\t\t\t\tawait protocol.disconnect().catch(() => undefined);\n\t\t\t});\n\t\t\tconnections.add(connection);\n\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\tif (isBinary) {\n\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvoid protocol\n\t\t\t\t\t.receive(websocketPayload(data))\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (protocol.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t});\n\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t});\n\t});\n\n\tconst api: DaemonServer = {\n\t\tlisten(): Promise<DaemonServerAddress> {\n\t\t\tif (serverState === \"closing\" || serverState === \"closed\")\n\t\t\t\treturn Promise.reject(new Error(\"Daemon server is closing\"));\n\t\t\tif (currentAddress) return Promise.resolve(currentAddress);\n\t\t\tif (listenPromise) return listenPromise;\n\t\t\tif (configuration.sharedParentRoot && !sharedRoots) {\n\t\t\t\treturn SharedWorkspaceRoots.fromParent(configuration.sharedParentRoot).then((roots) => {\n\t\t\t\t\tsharedRoots = roots;\n\t\t\t\t\treturn api.listen();\n\t\t\t\t});\n\t\t\t}\n\t\t\tlistenPromise = new Promise((resolve, reject) => {\n\t\t\t\trejectListen = reject;\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\t\tlistenPromise = undefined;\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\treject(error);\n\t\t\t\t};\n\t\t\t\tconst onListening = () => {\n\t\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\t\tif (serverState !== \"created\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon server closed before listening completed\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst address = server.address();\n\t\t\t\t\tif (!address || typeof address === \"string\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon listener did not return a TCP address\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tserverState = \"listening\";\n\t\t\t\t\tconst port = (address as AddressInfo).port;\n\t\t\t\t\tcurrentAddress = Object.freeze({\n\t\t\t\t\t\thost: configuration.host,\n\t\t\t\t\t\tport,\n\t\t\t\t\t\tsecure: configuration.tls !== undefined,\n\t\t\t\t\t\turl: `${configuration.tls ? \"wss\" : \"ws\"}://${formatHostForUrl(configuration.host)}:${port}${DAEMON_WEBSOCKET_PATH}`,\n\t\t\t\t\t\tworkspaceRoot: configuration.workspaceRoot,\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t});\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\tresolve(currentAddress);\n\t\t\t\t};\n\t\t\t\tserver.once(\"error\", onError);\n\t\t\t\tserver.once(\"listening\", onListening);\n\t\t\t\tserver.listen(configuration.port, configuration.host);\n\t\t\t});\n\t\t\treturn listenPromise;\n\t\t},\n\t\taddress(): DaemonServerAddress | undefined {\n\t\t\treturn currentAddress ? { ...currentAddress } : undefined;\n\t\t},\n\t\tstate(): DaemonServerState {\n\t\t\treturn serverState;\n\t\t},\n\t\treload(): Promise<void> {\n\t\t\tif (serverState !== \"listening\") return Promise.reject(new Error(\"Daemon server is not listening\"));\n\t\t\treloadQueue = reloadQueue\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.then(async () => {\n\t\t\t\t\tif (serverState !== \"listening\") throw new Error(\"Daemon server is not listening\");\n\t\t\t\t\tconst candidate = createDaemonWorkspaceRuntime(configuration);\n\t\t\t\t\tconst candidateCatalog = { ...candidate.catalog, generation: catalog.generation + 1 };\n\t\t\t\t\tconst previous = runtime;\n\t\t\t\t\truntime = candidate;\n\t\t\t\t\truntimeHandler = candidate.createHandler(workspace);\n\t\t\t\t\tcatalog = candidateCatalog;\n\t\t\t\t\tconst snapshot = [...connections];\n\t\t\t\t\tconst outcomes = await Promise.allSettled(\n\t\t\t\t\t\tsnapshot.map(async (connection) => {\n\t\t\t\t\t\t\tif (connection.protocol instanceof SharedDaemonConnection) await connection.protocol.reload();\n\t\t\t\t\t\t\telse await connection.protocol.publishCatalog(catalog);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tconst failed = snapshot.filter((_connection, index) => outcomes[index]?.status === \"rejected\");\n\t\t\t\t\t// A failed publication may have been sent already. Do not roll back successful peers\n\t\t\t\t\t// to an older generation: close only transports whose catalog is uncertain.\n\t\t\t\t\tfor (const connection of failed) connection.websocket.terminate();\n\t\t\t\t\tawait previous.retire();\n\t\t\t\t\tif (failed.length > 0)\n\t\t\t\t\t\tthrow new Error(`Daemon catalog reload failed for ${failed.length} connection(s)`);\n\t\t\t\t});\n\t\t\treturn reloadQueue;\n\t\t},\n\t\tclose(): Promise<void> {\n\t\t\tif (closePromise) return closePromise;\n\t\t\tserverState = \"closing\";\n\t\t\trejectListen?.(new Error(\"Daemon server closed before listening completed\"));\n\t\t\trejectListen = undefined;\n\t\t\tconst deadline = performance.now() + configuration.shutdownTimeoutMs;\n\t\t\tconst remainingMs = () => Math.max(0, deadline - performance.now());\n\t\t\tclosePromise = (async () => {\n\t\t\t\tconst listenerClose = stopListener();\n\t\t\t\tconst snapshot = [...connections];\n\t\t\t\tawait waitWithin(\n\t\t\t\t\treloadQueue.catch(() => undefined),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tconst hostDisposal = runtime.dispose();\n\t\t\t\tconst drained = await waitWithin(\n\t\t\t\t\tbeginDaemonConnectionDrain(snapshot, hostDisposal),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!drained) terminateDaemonConnections(snapshot);\n\t\t\t\tawait waitWithin(disconnectDaemonConnections(snapshot), remainingMs(), forceController.signal);\n\t\t\t\trequestDaemonConnectionClose(snapshot);\n\t\t\t\tconst socketsClosed = await waitWithin(\n\t\t\t\t\twaitForDaemonConnectionsClosed(snapshot),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!socketsClosed) terminateDaemonConnections(snapshot);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tawait listenerClose;\n\t\t\t\tconnections.clear();\n\t\t\t})().finally(() => {\n\t\t\t\tterminateDaemonConnections(connections);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tfor (const timer of pendingSocketTimers.values()) clearTimeout(timer);\n\t\t\t\tpendingSocketTimers.clear();\n\t\t\t\tpendingSocketDeadlines.clear();\n\t\t\t\tpendingSockets.clear();\n\t\t\t\tconnections.clear();\n\t\t\t\tcurrentAddress = undefined;\n\t\t\t\tserverState = \"closed\";\n\t\t\t});\n\t\t\treturn closePromise;\n\t\t},\n\t\tforceClose(): Promise<void> {\n\t\t\tif (serverState === \"closed\") return closePromise ?? Promise.resolve();\n\t\t\tserverState = \"closing\";\n\t\t\tforceController.abort();\n\t\t\tcurrentAddress = undefined;\n\t\t\tterminateDaemonConnections(connections);\n\t\t\tdestroyDaemonSockets(sockets);\n\t\t\treturn api.close();\n\t\t},\n\t};\n\treturn api;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n\tcreateServer as createHttpServer,\n\ttype Server as HttpServer,\n\ttype IncomingMessage,\n\ttype ServerResponse,\n} from \"node:http\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo, Socket } from \"node:net\";\nimport WebSocket, { type RawData, WebSocketServer } from \"ws\";\nimport type { RemoteWorkspaceServerMessage } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceProtocolCloseCode,\n\ttype RemoteWorkspaceProtocolCloseReason,\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tSHARED_WORKSPACE_WEBSOCKET_PROTOCOL,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport { DAEMON_WEBSOCKET_PATH, type DaemonConfiguration } from \"./config.ts\";\nimport { DaemonOutboundBudget } from \"./outbound-budget.ts\";\nimport {\n\tcreateDaemonAuthorization,\n\trejectDaemonUpgrade,\n\tvalidateDaemonNetworkPolicy,\n\tvalidateDaemonUpgrade,\n} from \"./security.ts\";\nimport { SharedDaemonConnection } from \"./shared-connection.ts\";\nimport { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\nexport interface DaemonServerAddress {\n\treadonly host: string;\n\treadonly port: number;\n\treadonly secure: boolean;\n\treadonly url: string;\n\treadonly workspaceRoot: string;\n\treadonly workspaceId: string;\n}\n\nexport type DaemonServerState = \"created\" | \"listening\" | \"closing\" | \"closed\";\n\nexport interface DaemonServer {\n\tlisten(): Promise<DaemonServerAddress>;\n\taddress(): DaemonServerAddress | undefined;\n\tstate(): DaemonServerState;\n\treload(): Promise<void>;\n\tclose(): Promise<void>;\n\tforceClose(): Promise<void>;\n}\n\ninterface DaemonConnection {\n\treadonly websocket: WebSocket;\n\treadonly protocol: RemoteWorkspaceServerProtocol | SharedDaemonConnection;\n\tclosed: Promise<void>;\n}\n\nfunction websocketPayload(data: RawData): Uint8Array {\n\tif (Buffer.isBuffer(data)) return Uint8Array.from(data);\n\tif (Array.isArray(data)) return Uint8Array.from(Buffer.concat(data));\n\treturn Uint8Array.from(new Uint8Array(data));\n}\n\nfunction websocketCloseCode(code: RemoteWorkspaceProtocolCloseCode): number {\n\tswitch (code) {\n\t\tcase \"normal\":\n\t\t\treturn 1000;\n\t\tcase \"protocol_error\":\n\t\t\treturn 1002;\n\t\tcase \"invalid_payload\":\n\t\t\treturn 1007;\n\t\tcase \"policy_violation\":\n\t\t\treturn 1008;\n\t\tcase \"message_too_large\":\n\t\t\treturn 1009;\n\t}\n}\n\nfunction waitForWebSocketClose(websocket: WebSocket): Promise<void> {\n\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\treturn new Promise((resolve) => websocket.once(\"close\", () => resolve()));\n}\n\nfunction waitWithin(promise: Promise<unknown>, timeoutMs: number, forceSignal: AbortSignal): Promise<boolean> {\n\tif (forceSignal.aborted) return Promise.resolve(false);\n\treturn new Promise((resolve) => {\n\t\tlet settled = false;\n\t\tconst finish = (value: boolean) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tforceSignal.removeEventListener(\"abort\", onForce);\n\t\t\tresolve(value);\n\t\t};\n\t\tconst timer = setTimeout(() => finish(false), timeoutMs);\n\t\tconst onForce = () => finish(false);\n\t\tforceSignal.addEventListener(\"abort\", onForce, { once: true });\n\t\tpromise.then(\n\t\t\t() => finish(true),\n\t\t\t() => finish(false),\n\t\t);\n\t});\n}\nfunction terminateDaemonConnections(connections: Iterable<DaemonConnection>): void {\n\tfor (const connection of connections) connection.websocket.terminate();\n}\n\nfunction beginDaemonConnectionDrain(\n\tconnections: readonly DaemonConnection[],\n\thostDisposal: Promise<void>,\n): Promise<void> {\n\treturn Promise.allSettled([...connections.map((connection) => connection.protocol.beginDrain()), hostDisposal]).then(\n\t\t() => undefined,\n\t);\n}\n\nfunction disconnectDaemonConnections(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.protocol.disconnect())).then(() => undefined);\n}\n\nfunction requestDaemonConnectionClose(connections: readonly DaemonConnection[]): void {\n\tfor (const connection of connections) {\n\t\tif (connection.websocket.readyState === WebSocket.OPEN) {\n\t\t\tconnection.websocket.close(1001, \"Daemon shutting down\");\n\t\t}\n\t}\n}\n\nfunction waitForDaemonConnectionsClosed(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.closed)).then(() => undefined);\n}\n\nfunction destroyDaemonSockets(sockets: ReadonlySet<Socket>): void {\n\tfor (const socket of sockets) socket.destroy();\n}\n\nfunction formatHostForUrl(host: string): string {\n\treturn host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host;\n}\n\nexport function createDaemonServer(configuration: DaemonConfiguration): DaemonServer {\n\tvalidateDaemonNetworkPolicy(configuration);\n\tconst authorization = createDaemonAuthorization(configuration.token);\n\tconst activityBudget = new DaemonActivityBudget(configuration);\n\tconst workspaceId = randomBytes(18).toString(\"base64url\");\n\tconst workspace = Object.freeze({\n\t\tid: workspaceId,\n\t\troot: configuration.workspaceRoot,\n\t\tpathFlavor: process.platform === \"win32\" ? (\"windows\" as const) : (\"posix\" as const),\n\t});\n\tlet runtime = createDaemonWorkspaceRuntime(configuration);\n\tlet runtimeHandler = runtime.createHandler(workspace);\n\tconst handler: RemoteWorkspaceServerHandler = {\n\t\thandleRequest: (request, context) => {\n\t\t\tif (typeof request.params === \"object\" && request.params !== null && \"expectedRevision\" in request.params) {\n\t\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\t\tcode: \"invalid_request\",\n\t\t\t\t\tmessage: \"Revision preconditions require the v2 shared workspace protocol\",\n\t\t\t\t\texecutionState: \"not_started\",\n\t\t\t\t\tretryable: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn activityBudget.run(request.method, () => runtimeHandler.handleRequest(request, context));\n\t\t},\n\t\tvalidateToolArguments: (toolName, value) => runtimeHandler.validateToolArguments(toolName, value),\n\t};\n\tconst requestListener = (_request: IncomingMessage, response: ServerResponse) => {\n\t\tresponse.writeHead(404, { \"content-type\": \"text/plain\" });\n\t\tresponse.end(\"Not found\\n\");\n\t};\n\tconst server: HttpServer = configuration.tls\n\t\t? createHttpsServer(\n\t\t\t\t{\n\t\t\t\t\tcert: configuration.tls.cert,\n\t\t\t\t\tkey: configuration.tls.key,\n\t\t\t\t\tpassphrase: configuration.tls.passphrase,\n\t\t\t\t\tminVersion: \"TLSv1.2\",\n\t\t\t\t},\n\t\t\t\trequestListener,\n\t\t\t)\n\t\t: createHttpServer(requestListener);\n\tconst websocketServer = new WebSocketServer({\n\t\tnoServer: true,\n\t\tclientTracking: false,\n\t\tmaxPayload: configuration.protocolLimits.maxMessageBytes,\n\t\tperMessageDeflate: false,\n\t\tallowSynchronousEvents: false,\n\t\tskipUTF8Validation: false,\n\t});\n\tconst sockets = new Set<Socket>();\n\tconst pendingSockets = new Set<Socket>();\n\tconst pendingSocketTimers = new Map<Socket, NodeJS.Timeout>();\n\tconst pendingSocketDeadlines = new Map<Socket, number>();\n\tconst connections = new Set<DaemonConnection>();\n\tlet sharedRoots: SharedWorkspaceRoots | undefined;\n\tlet catalog = runtime.catalog;\n\tlet reloadQueue: Promise<void> = Promise.resolve();\n\tconst forceController = new AbortController();\n\tlet currentAddress: DaemonServerAddress | undefined;\n\tlet listenPromise: Promise<DaemonServerAddress> | undefined;\n\tlet rejectListen: ((error: Error) => void) | undefined;\n\tlet closePromise: Promise<void> | undefined;\n\tlet serverState: DaemonServerState = \"created\";\n\n\tconst stopListener = (): Promise<void> => {\n\t\tif (!server.listening && !listenPromise) return Promise.resolve();\n\t\treturn new Promise((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\tserver.off(\"close\", onClose);\n\t\t\t};\n\t\t\tconst finish = () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tconst closeListener = () => server.close(() => finish());\n\t\t\tconst onListening = () => closeListener();\n\t\t\tconst onError = () => finish();\n\t\t\tconst onClose = () => finish();\n\t\t\tserver.once(\"error\", onError);\n\t\t\tserver.once(\"close\", onClose);\n\t\t\tif (server.listening) closeListener();\n\t\t\telse server.once(\"listening\", onListening);\n\t\t});\n\t};\n\n\tserver.on(\"connection\", (socket: Socket) => {\n\t\tif (serverState !== \"listening\" || pendingSockets.size >= configuration.maxPendingConnections) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tsockets.add(socket);\n\t\tpendingSockets.add(socket);\n\t\tconst pendingTimer = setTimeout(() => socket.destroy(), configuration.handshakeTimeoutMs);\n\t\tpendingTimer.unref?.();\n\t\tpendingSocketTimers.set(socket, pendingTimer);\n\t\tpendingSocketDeadlines.set(socket, performance.now() + configuration.handshakeTimeoutMs);\n\t\tsocket.once(\"close\", () => {\n\t\t\tsockets.delete(socket);\n\t\t\tpendingSockets.delete(socket);\n\t\t\tconst timer = pendingSocketTimers.get(socket);\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\tpendingSocketTimers.delete(socket);\n\t\t\tpendingSocketDeadlines.delete(socket);\n\t\t});\n\t});\n\n\tserver.on(\"upgrade\", (request, socket, head) => {\n\t\tconst netSocket = socket as Socket;\n\t\tconst decision = validateDaemonUpgrade(request, configuration, authorization);\n\t\tif (!decision.accepted) {\n\t\t\trejectDaemonUpgrade(netSocket, decision);\n\t\t\treturn;\n\t\t}\n\t\tif (serverState !== \"listening\" || connections.size >= configuration.maxConnections) {\n\t\t\trejectDaemonUpgrade(netSocket, { accepted: false, status: 503, message: \"Service unavailable\" });\n\t\t\treturn;\n\t\t}\n\t\tconst handshakeDeadline = pendingSocketDeadlines.get(netSocket) ?? performance.now();\n\t\tpendingSockets.delete(netSocket);\n\t\tconst pendingTimer = pendingSocketTimers.get(netSocket);\n\t\tif (pendingTimer) clearTimeout(pendingTimer);\n\t\tpendingSocketTimers.delete(netSocket);\n\t\tpendingSocketDeadlines.delete(netSocket);\n\t\twebsocketServer.handleUpgrade(request, socket, head, (websocket) => {\n\t\t\tif (serverState !== \"listening\") {\n\t\t\t\twebsocket.terminate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst remainingHandshakeMs = Math.max(0, handshakeDeadline - performance.now());\n\t\t\tconst handshakeTimer = setTimeout(() => {\n\t\t\t\twebsocket.terminate();\n\t\t\t}, remainingHandshakeMs);\n\t\t\thandshakeTimer.unref?.();\n\t\t\tlet protocol: RemoteWorkspaceServerProtocol;\n\t\t\tconst outboundBudget = new DaemonOutboundBudget(\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundBytes,\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundMessages,\n\t\t\t);\n\t\t\tconst transport = {\n\t\t\t\tsend(message: RemoteWorkspaceServerMessage | SharedWorkspaceServerFrame): Promise<void> {\n\t\t\t\t\tif (websocket.readyState !== WebSocket.OPEN) return Promise.reject(new Error(\"WebSocket is not open\"));\n\t\t\t\t\tconst serialized = JSON.stringify(message);\n\t\t\t\t\tconst bytes = Buffer.byteLength(serialized, \"utf8\");\n\t\t\t\t\tlet release: () => void;\n\t\t\t\t\ttry {\n\t\t\t\t\t\trelease = outboundBudget.reserve(bytes, websocket.bufferedAmount);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// No channel can safely continue after a physical send is dropped.\n\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\treturn Promise.reject(error);\n\t\t\t\t\t}\n\t\t\t\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\t// A stalled callback must not pin physical reservations indefinitely. A\n\t\t\t\t\t\t// timed-out send makes the entire uplink uncertain, not just its channel.\n\t\t\t\t\t\tconst deadline = setTimeout(() => {\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(new Error(\"WebSocket outbound send timed out\"));\n\t\t\t\t\t\t}, configuration.protocolLimits.maxTransportSendMs);\n\t\t\t\t\t\tdeadline.unref?.();\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twebsocket.send(serialized, { binary: false, compress: false }, (error) => {\n\t\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t\t} else resolve();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).finally(release);\n\t\t\t\t},\n\t\t\t\tclose(reason: RemoteWorkspaceProtocolCloseReason): Promise<void> {\n\t\t\t\t\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\t\t\t\t\twebsocket.close(websocketCloseCode(reason.code), reason.message);\n\t\t\t\t\treturn waitForWebSocketClose(websocket);\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (websocket.protocol === SHARED_WORKSPACE_WEBSOCKET_PROTOCOL) {\n\t\t\t\tif (!sharedRoots) {\n\t\t\t\t\twebsocket.close(1008, \"Shared parent unavailable\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst shared = new SharedDaemonConnection(\n\t\t\t\t\tconfiguration,\n\t\t\t\t\tsharedRoots,\n\t\t\t\t\ttransport.send,\n\t\t\t\t\t(code, reason) => {\n\t\t\t\t\t\tif (websocket.readyState === WebSocket.OPEN) websocket.close(code, reason);\n\t\t\t\t\t},\n\t\t\t\t\tactivityBudget,\n\t\t\t\t);\n\t\t\t\tconst connection: DaemonConnection = { websocket, protocol: shared, closed: Promise.resolve() };\n\t\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\t\tconnections.delete(connection);\n\t\t\t\t\tawait shared.disconnect().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tconnections.add(connection);\n\t\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\t\tif (isBinary) {\n\t\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvoid shared.receive(websocketPayload(data)).then(() => {\n\t\t\t\t\t\tif (shared.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprotocol = new RemoteWorkspaceServerProtocol(transport, handler, {\n\t\t\t\tworkspace,\n\t\t\t\tcatalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-workspace-daemon\",\n\t\t\t});\n\t\t\tconst connection: DaemonConnection = {\n\t\t\t\twebsocket,\n\t\t\t\tprotocol,\n\t\t\t\tclosed: Promise.resolve(),\n\t\t\t};\n\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\tconnections.delete(connection);\n\t\t\t\tawait protocol.disconnect().catch(() => undefined);\n\t\t\t});\n\t\t\tconnections.add(connection);\n\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\tif (isBinary) {\n\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvoid protocol\n\t\t\t\t\t.receive(websocketPayload(data))\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (protocol.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t});\n\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t});\n\t});\n\n\tconst api: DaemonServer = {\n\t\tlisten(): Promise<DaemonServerAddress> {\n\t\t\tif (serverState === \"closing\" || serverState === \"closed\")\n\t\t\t\treturn Promise.reject(new Error(\"Daemon server is closing\"));\n\t\t\tif (currentAddress) return Promise.resolve(currentAddress);\n\t\t\tif (listenPromise) return listenPromise;\n\t\t\tif (configuration.sharedParentRoot && !sharedRoots) {\n\t\t\t\treturn SharedWorkspaceRoots.fromParent(configuration.sharedParentRoot).then((roots) => {\n\t\t\t\t\tsharedRoots = roots;\n\t\t\t\t\treturn api.listen();\n\t\t\t\t});\n\t\t\t}\n\t\t\tlistenPromise = new Promise((resolve, reject) => {\n\t\t\t\trejectListen = reject;\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\t\tlistenPromise = undefined;\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\treject(error);\n\t\t\t\t};\n\t\t\t\tconst onListening = () => {\n\t\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\t\tif (serverState !== \"created\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon server closed before listening completed\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst address = server.address();\n\t\t\t\t\tif (!address || typeof address === \"string\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon listener did not return a TCP address\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tserverState = \"listening\";\n\t\t\t\t\tconst port = (address as AddressInfo).port;\n\t\t\t\t\tcurrentAddress = Object.freeze({\n\t\t\t\t\t\thost: configuration.host,\n\t\t\t\t\t\tport,\n\t\t\t\t\t\tsecure: configuration.tls !== undefined,\n\t\t\t\t\t\turl: `${configuration.tls ? \"wss\" : \"ws\"}://${formatHostForUrl(configuration.host)}:${port}${DAEMON_WEBSOCKET_PATH}`,\n\t\t\t\t\t\tworkspaceRoot: configuration.workspaceRoot,\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t});\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\tresolve(currentAddress);\n\t\t\t\t};\n\t\t\t\tserver.once(\"error\", onError);\n\t\t\t\tserver.once(\"listening\", onListening);\n\t\t\t\tserver.listen(configuration.port, configuration.host);\n\t\t\t});\n\t\t\treturn listenPromise;\n\t\t},\n\t\taddress(): DaemonServerAddress | undefined {\n\t\t\treturn currentAddress ? { ...currentAddress } : undefined;\n\t\t},\n\t\tstate(): DaemonServerState {\n\t\t\treturn serverState;\n\t\t},\n\t\treload(): Promise<void> {\n\t\t\tif (serverState !== \"listening\") return Promise.reject(new Error(\"Daemon server is not listening\"));\n\t\t\treloadQueue = reloadQueue\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.then(async () => {\n\t\t\t\t\tif (serverState !== \"listening\") throw new Error(\"Daemon server is not listening\");\n\t\t\t\t\tconst candidate = createDaemonWorkspaceRuntime(configuration);\n\t\t\t\t\tconst candidateCatalog = { ...candidate.catalog, generation: catalog.generation + 1 };\n\t\t\t\t\tconst previous = runtime;\n\t\t\t\t\truntime = candidate;\n\t\t\t\t\truntimeHandler = candidate.createHandler(workspace);\n\t\t\t\t\tcatalog = candidateCatalog;\n\t\t\t\t\tconst snapshot = [...connections];\n\t\t\t\t\tconst outcomes = await Promise.allSettled(\n\t\t\t\t\t\tsnapshot.map(async (connection) => {\n\t\t\t\t\t\t\tif (connection.protocol instanceof SharedDaemonConnection) await connection.protocol.reload();\n\t\t\t\t\t\t\telse await connection.protocol.publishCatalog(catalog);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tconst failed = snapshot.filter((_connection, index) => outcomes[index]?.status === \"rejected\");\n\t\t\t\t\t// A failed publication may have been sent already. Do not roll back successful peers\n\t\t\t\t\t// to an older generation: close only transports whose catalog is uncertain.\n\t\t\t\t\tfor (const connection of failed) connection.websocket.terminate();\n\t\t\t\t\tawait previous.retire();\n\t\t\t\t\tif (failed.length > 0)\n\t\t\t\t\t\tthrow new Error(`Daemon catalog reload failed for ${failed.length} connection(s)`);\n\t\t\t\t});\n\t\t\treturn reloadQueue;\n\t\t},\n\t\tclose(): Promise<void> {\n\t\t\tif (closePromise) return closePromise;\n\t\t\tserverState = \"closing\";\n\t\t\trejectListen?.(new Error(\"Daemon server closed before listening completed\"));\n\t\t\trejectListen = undefined;\n\t\t\tconst deadline = performance.now() + configuration.shutdownTimeoutMs;\n\t\t\tconst remainingMs = () => Math.max(0, deadline - performance.now());\n\t\t\tclosePromise = (async () => {\n\t\t\t\tconst listenerClose = stopListener();\n\t\t\t\tconst snapshot = [...connections];\n\t\t\t\tawait waitWithin(\n\t\t\t\t\treloadQueue.catch(() => undefined),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tconst hostDisposal = runtime.dispose();\n\t\t\t\tconst drained = await waitWithin(\n\t\t\t\t\tbeginDaemonConnectionDrain(snapshot, hostDisposal),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!drained) terminateDaemonConnections(snapshot);\n\t\t\t\tawait waitWithin(disconnectDaemonConnections(snapshot), remainingMs(), forceController.signal);\n\t\t\t\trequestDaemonConnectionClose(snapshot);\n\t\t\t\tconst socketsClosed = await waitWithin(\n\t\t\t\t\twaitForDaemonConnectionsClosed(snapshot),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!socketsClosed) terminateDaemonConnections(snapshot);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tawait listenerClose;\n\t\t\t\tconnections.clear();\n\t\t\t})().finally(() => {\n\t\t\t\tterminateDaemonConnections(connections);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tfor (const timer of pendingSocketTimers.values()) clearTimeout(timer);\n\t\t\t\tpendingSocketTimers.clear();\n\t\t\t\tpendingSocketDeadlines.clear();\n\t\t\t\tpendingSockets.clear();\n\t\t\t\tconnections.clear();\n\t\t\t\tcurrentAddress = undefined;\n\t\t\t\tserverState = \"closed\";\n\t\t\t});\n\t\t\treturn closePromise;\n\t\t},\n\t\tforceClose(): Promise<void> {\n\t\t\tif (serverState === \"closed\") return closePromise ?? Promise.resolve();\n\t\t\tserverState = \"closing\";\n\t\t\tforceController.abort();\n\t\t\tcurrentAddress = undefined;\n\t\t\tterminateDaemonConnections(connections);\n\t\t\tdestroyDaemonSockets(sockets);\n\t\t\treturn api.close();\n\t\t},\n\t};\n\treturn api;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-connection.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-connection.ts"],"names":[],"mappings":"AAUA,OAAO,EAGN,KAAK,0BAA0B,EAC/B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAW9D,mGAAmG;AACnG,qBAAa,sBAAsB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyC;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAC7D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyC;IAC/D,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyD;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;IAEtE,YACC,aAAa,EAAE,mBAAmB,EAClC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,OAAO,CAAC,IAAI,CAAC,EAC5D,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,EACpD,MAAM,GAAE,oBAA8D,EAOtE;IAED,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD1C;IAED,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAED,OAAO,CAAC,oBAAoB;IAY5B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAwBtB;YAEa,QAAQ;YAkDR,IAAI;IA4ElB,OAAO,CAAC,cAAc;IAgBhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhC;CACD","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { VERSION } from \"../config.ts\";\nimport type {\n\tRemoteWorkspaceIdentity,\n\tRemoteWorkspaceServerMessage,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tparseSharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { withSharedRevisionGuard } from \"./shared-revision.ts\";\nimport type { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime, type DaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\ninterface Channel {\n\treadonly protocol: RemoteWorkspaceServerProtocol;\n\truntime: DaemonWorkspaceRuntime;\n\thandler: RemoteWorkspaceServerHandler;\n\treadonly workspace: RemoteWorkspaceIdentity;\n\tgeneration: number;\n}\n\n/** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */\nexport class SharedDaemonConnection {\n\tprivate readonly channels = new Map<string, Channel>();\n\tprivate readonly channelDisposals = new WeakMap<Channel, Promise<void>>();\n\tprivate readonly pendingDisposals = new Set<Promise<void>>();\n\tprivate readonly usedControlIds = new Set<string>();\n\tprivate readonly epoch = randomBytes(18).toString(\"base64url\");\n\tprivate hello = false;\n\tprivate closed = false;\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate pendingInboundMessages = 0;\n\tprivate pendingInboundBytes = 0;\n\tprivate readonly budget: DaemonActivityBudget;\n\n\tprivate readonly configuration: DaemonConfiguration;\n\tprivate readonly roots: SharedWorkspaceRoots;\n\tprivate readonly send: (message: SharedWorkspaceServerFrame) => Promise<void>;\n\tprivate readonly closeSocket: (code: number, message: string) => void;\n\n\tconstructor(\n\t\tconfiguration: DaemonConfiguration,\n\t\troots: SharedWorkspaceRoots,\n\t\tsend: (message: SharedWorkspaceServerFrame) => Promise<void>,\n\t\tcloseSocket: (code: number, message: string) => void,\n\t\tbudget: DaemonActivityBudget = new DaemonActivityBudget(configuration),\n\t) {\n\t\tthis.configuration = configuration;\n\t\tthis.roots = roots;\n\t\tthis.send = send;\n\t\tthis.closeSocket = closeSocket;\n\t\tthis.budget = budget;\n\t}\n\n\treceive(payload: Uint8Array): Promise<void> {\n\t\tif (this.closed) return Promise.resolve();\n\t\tconst limits = this.configuration.protocolLimits;\n\t\tif (\n\t\t\tpayload.byteLength > limits.maxMessageBytes ||\n\t\t\tthis.pendingInboundMessages >= limits.maxPendingInboundMessages ||\n\t\t\tthis.pendingInboundBytes + payload.byteLength > limits.maxPendingInboundBytes\n\t\t) {\n\t\t\tthis.closed = true;\n\t\t\tthis.closeSocket(1009, \"Shared workspace inbound queue exceeds limits\");\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t// Copy before queuing: WebSocket buffers need not remain stable after the callback returns.\n\t\tconst queuedPayload = Uint8Array.from(payload);\n\t\tthis.pendingInboundMessages++;\n\t\tthis.pendingInboundBytes += queuedPayload.byteLength;\n\t\tlet complete!: () => void;\n\t\tconst finished = new Promise<void>((resolve) => {\n\t\t\tcomplete = resolve;\n\t\t});\n\t\tlet channelPending = false;\n\t\tconst settle = () => {\n\t\t\tthis.pendingInboundMessages--;\n\t\t\tthis.pendingInboundBytes -= queuedPayload.byteLength;\n\t\t\tcomplete();\n\t\t};\n\t\tconst fail = () => {\n\t\t\tif (!this.closed) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.closeSocket(1002, \"Invalid shared workspace frame\");\n\t\t\t}\n\t\t};\n\t\tconst scheduled = this.queue.then(() => {\n\t\t\tif (this.closed) return;\n\t\t\tconst frame = parseSharedWorkspaceClientEnvelope(queuedPayload, limits);\n\t\t\tif (frame.type === \"channel\") {\n\t\t\t\t// Validate the channel before letting the control queue advance. Its own\n\t\t\t\t// protocol preserves per-channel receive order and bounds queued frames.\n\t\t\t\tif (!this.channels.has(frame.channelId)) throw new Error(\"Unknown shared workspace channel\");\n\t\t\t\tchannelPending = true;\n\t\t\t\tvoid this.dispatch(frame).catch(fail).finally(settle);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Hello, opens, closes and reloads remain serialized in control order.\n\t\t\treturn this.dispatch(frame);\n\t\t});\n\t\tthis.queue = scheduled.catch(fail).finally(() => {\n\t\t\tif (!channelPending) settle();\n\t\t});\n\t\treturn finished;\n\t}\n\n\tget handshakeComplete(): boolean {\n\t\treturn this.hello;\n\t}\n\n\tasync beginDrain(): Promise<void> {\n\t\tawait Promise.allSettled([...this.channels.values()].map((channel) => channel.protocol.beginDrain()));\n\t}\n\n\tprivate createChannelRuntime(root: string): DaemonWorkspaceRuntime {\n\t\treturn createDaemonWorkspaceRuntime({\n\t\t\t...this.configuration,\n\t\t\tworkspaceRoot: root,\n\t\t\t// Operator-wide resource files and the v1 temporary root are not channel-scoped.\n\t\t\t// Keep them available on v1, but never expose them through a child channel.\n\t\t\ttemporaryRoot: undefined,\n\t\t\tsandboxInstructionsPath: undefined,\n\t\t\tuserAgentsPath: undefined,\n\t\t});\n\t}\n\n\treload(): Promise<void> {\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Shared workspace connection is closed\");\n\t\t\tfor (const channel of this.channels.values()) {\n\t\t\t\tconst previous = channel.runtime;\n\t\t\t\tconst previousHandler = channel.handler;\n\t\t\t\tconst candidate = this.createChannelRuntime(channel.workspace.root);\n\t\t\t\tconst candidateHandler = candidate.createHandler(channel.workspace, true);\n\t\t\t\tchannel.runtime = candidate;\n\t\t\t\tchannel.handler = candidateHandler;\n\t\t\t\ttry {\n\t\t\t\t\tawait channel.protocol.publishCatalog({ ...candidate.catalog, generation: channel.generation + 1 });\n\t\t\t\t\tchannel.generation++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tchannel.runtime = previous;\n\t\t\t\t\tchannel.handler = previousHandler;\n\t\t\t\t\tawait candidate.dispose();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait previous.retire();\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\treturn operation;\n\t}\n\n\tprivate async dispatch(frame: SharedWorkspaceClientEnvelope): Promise<void> {\n\t\tif (frame.type === \"hello\") {\n\t\t\tif (this.hello) throw new Error(\"Duplicate v2 hello\");\n\t\t\tthis.hello = true;\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tawait this.send({ type: \"hello_ack\", id: frame.id, version: 2, epoch: this.epoch, daemonVersion: VERSION });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.hello) throw new Error(\"V2 hello required before opening channels\");\n\t\tif (frame.type === \"open\") {\n\t\t\tif (this.usedControlIds.has(frame.id)) throw new Error(\"Duplicate v2 control ID\");\n\t\t\tif (this.usedControlIds.size >= 65_536) throw new Error(\"V2 control ID budget exhausted\");\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tif (this.channels.size >= Math.min(this.configuration.maxConnections, 32)) {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\tmessage: \"Channel limit reached\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet root: string;\n\t\t\ttry {\n\t\t\t\troot = await this.roots.bind(frame.root);\n\t\t\t} catch {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tmessage: \"Workspace root is not an existing directory under the shared parent\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.open(frame.id, root);\n\t\t\treturn;\n\t\t}\n\t\tconst channel = this.channels.get(frame.channelId);\n\t\tif (!channel) throw new Error(\"Unknown shared workspace channel\");\n\t\tif (frame.type === \"close\") {\n\t\t\t// Do not wait on a channel's in-flight requests while blocking the socket receive queue.\n\t\t\tthis.channels.delete(frame.channelId);\n\t\t\t// Begin cancellation before acknowledging detach; track it for physical shutdown.\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tawait this.send({ type: \"closed\", channelId: frame.channelId });\n\t\t\treturn;\n\t\t}\n\t\tawait channel.protocol.receive(Buffer.from(JSON.stringify(frame.payload)));\n\t}\n\n\tprivate async open(id: string, root: string): Promise<void> {\n\t\tconst channelId = randomBytes(24).toString(\"base64url\");\n\t\tconst workspace = Object.freeze({\n\t\t\tid: randomBytes(18).toString(\"base64url\"),\n\t\t\troot,\n\t\t\tpathFlavor: \"posix\" as const,\n\t\t});\n\t\tlet runtime: DaemonWorkspaceRuntime;\n\t\ttry {\n\t\t\truntime = this.createChannelRuntime(root);\n\t\t} catch {\n\t\t\t// A bad child project configuration is an open failure, not a corrupt\n\t\t\t// physical envelope. Keep already bound sibling channels usable.\n\t\t\tawait this.send({\n\t\t\t\ttype: \"control_error\",\n\t\t\t\tid,\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"Unable to initialize shared workspace channel\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst handler = runtime.createHandler(workspace, true);\n\t\tlet channel!: Channel;\n\t\tconst protocol = new RemoteWorkspaceServerProtocol(\n\t\t\t{\n\t\t\t\tsend: (payload: RemoteWorkspaceServerMessage) =>\n\t\t\t\t\tthis.channels.has(channelId) && !this.closed\n\t\t\t\t\t\t? this.send({ type: \"channel\", channelId, payload })\n\t\t\t\t\t\t: Promise.reject(new Error(\"Shared workspace channel is closed\")),\n\t\t\t\tclose: async (reason) => {\n\t\t\t\t\tconst channel = this.channels.get(channelId);\n\t\t\t\t\tif (channel) {\n\t\t\t\t\t\tthis.channels.delete(channelId);\n\t\t\t\t\t\tvoid this.disposeChannel(channel);\n\t\t\t\t\t\tif (!this.closed) await this.send({ type: \"closed\", channelId, reason });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalidateToolArguments: (toolName, value) => channel.handler.validateToolArguments(toolName, value),\n\t\t\t\thandleRequest: (request, context) =>\n\t\t\t\t\tthis.budget.run(request.method, async () => {\n\t\t\t\t\t\tconst result = await withSharedRevisionGuard(\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\tchannel.runtime.operations,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t() => channel.handler.handleRequest(request, context),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (request.method !== \"workspace.read\") return result;\n\t\t\t\t\t\tconst read = result as { contentBase64: string };\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...read,\n\t\t\t\t\t\t\trevision: createHash(\"sha256\").update(Buffer.from(read.contentBase64, \"base64\")).digest(\"hex\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\tworkspace,\n\t\t\t\tcatalog: runtime.catalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: this.configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-shared-workspace-daemon\",\n\t\t\t},\n\t\t);\n\t\tchannel = { runtime, handler, protocol, workspace, generation: runtime.catalog.generation };\n\t\tthis.channels.set(channelId, channel);\n\t\ttry {\n\t\t\tawait this.send({ type: \"opened\", id, channelId });\n\t\t} catch (error) {\n\t\t\tthis.channels.delete(channelId);\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate disposeChannel(channel: Channel): Promise<void> {\n\t\tconst existing = this.channelDisposals.get(channel);\n\t\tif (existing) return existing;\n\t\tconst disposal = (async () => {\n\t\t\tawait channel.protocol.disconnect().catch(() => undefined);\n\t\t\tawait channel.runtime.dispose().catch(() => undefined);\n\t\t})();\n\t\tthis.channelDisposals.set(channel, disposal);\n\t\tthis.pendingDisposals.add(disposal);\n\t\tvoid disposal.then(\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t);\n\t\treturn disposal;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tthis.closed = true;\n\t\tconst channels = [...this.channels.values()];\n\t\tthis.channels.clear();\n\t\tawait Promise.allSettled([...channels.map((channel) => this.disposeChannel(channel)), ...this.pendingDisposals]);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared-connection.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-connection.ts"],"names":[],"mappings":"AAUA,OAAO,EAGN,KAAK,0BAA0B,EAC/B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAW9D,mGAAmG;AACnG,qBAAa,sBAAsB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyC;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAC7D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyC;IAC/D,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyD;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;IAEtE,YACC,aAAa,EAAE,mBAAmB,EAClC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,OAAO,CAAC,IAAI,CAAC,EAC5D,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,EACpD,MAAM,GAAE,oBAA8D,EAOtE;IAED,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD1C;IAED,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IAED,OAAO,CAAC,oBAAoB;IAY5B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAwBtB;YAEa,QAAQ;YAkDR,IAAI;IA4ElB,OAAO,CAAC,cAAc;IAgBhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAKhC;CACD"}
|
|
@@ -7,22 +7,17 @@ import { withSharedRevisionGuard } from "./shared-revision.js";
|
|
|
7
7
|
import { createDaemonWorkspaceRuntime } from "./workspace-runtime.js";
|
|
8
8
|
/** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */
|
|
9
9
|
export class SharedDaemonConnection {
|
|
10
|
-
channels = new Map();
|
|
11
|
-
channelDisposals = new WeakMap();
|
|
12
|
-
pendingDisposals = new Set();
|
|
13
|
-
usedControlIds = new Set();
|
|
14
|
-
epoch = randomBytes(18).toString("base64url");
|
|
15
|
-
hello = false;
|
|
16
|
-
closed = false;
|
|
17
|
-
queue = Promise.resolve();
|
|
18
|
-
pendingInboundMessages = 0;
|
|
19
|
-
pendingInboundBytes = 0;
|
|
20
|
-
budget;
|
|
21
|
-
configuration;
|
|
22
|
-
roots;
|
|
23
|
-
send;
|
|
24
|
-
closeSocket;
|
|
25
10
|
constructor(configuration, roots, send, closeSocket, budget = new DaemonActivityBudget(configuration)) {
|
|
11
|
+
this.channels = new Map();
|
|
12
|
+
this.channelDisposals = new WeakMap();
|
|
13
|
+
this.pendingDisposals = new Set();
|
|
14
|
+
this.usedControlIds = new Set();
|
|
15
|
+
this.epoch = randomBytes(18).toString("base64url");
|
|
16
|
+
this.hello = false;
|
|
17
|
+
this.closed = false;
|
|
18
|
+
this.queue = Promise.resolve();
|
|
19
|
+
this.pendingInboundMessages = 0;
|
|
20
|
+
this.pendingInboundBytes = 0;
|
|
26
21
|
this.configuration = configuration;
|
|
27
22
|
this.roots = roots;
|
|
28
23
|
this.send = send;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-connection.js","sourceRoot":"","sources":["../../src/daemon/shared-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { VERSION } from \"../config.ts\";\nimport type {\n\tRemoteWorkspaceIdentity,\n\tRemoteWorkspaceServerMessage,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tparseSharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { withSharedRevisionGuard } from \"./shared-revision.ts\";\nimport type { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime, type DaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\ninterface Channel {\n\treadonly protocol: RemoteWorkspaceServerProtocol;\n\truntime: DaemonWorkspaceRuntime;\n\thandler: RemoteWorkspaceServerHandler;\n\treadonly workspace: RemoteWorkspaceIdentity;\n\tgeneration: number;\n}\n\n/** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */\nexport class SharedDaemonConnection {\n\tprivate readonly channels = new Map<string, Channel>();\n\tprivate readonly channelDisposals = new WeakMap<Channel, Promise<void>>();\n\tprivate readonly pendingDisposals = new Set<Promise<void>>();\n\tprivate readonly usedControlIds = new Set<string>();\n\tprivate readonly epoch = randomBytes(18).toString(\"base64url\");\n\tprivate hello = false;\n\tprivate closed = false;\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate pendingInboundMessages = 0;\n\tprivate pendingInboundBytes = 0;\n\tprivate readonly budget: DaemonActivityBudget;\n\n\tprivate readonly configuration: DaemonConfiguration;\n\tprivate readonly roots: SharedWorkspaceRoots;\n\tprivate readonly send: (message: SharedWorkspaceServerFrame) => Promise<void>;\n\tprivate readonly closeSocket: (code: number, message: string) => void;\n\n\tconstructor(\n\t\tconfiguration: DaemonConfiguration,\n\t\troots: SharedWorkspaceRoots,\n\t\tsend: (message: SharedWorkspaceServerFrame) => Promise<void>,\n\t\tcloseSocket: (code: number, message: string) => void,\n\t\tbudget: DaemonActivityBudget = new DaemonActivityBudget(configuration),\n\t) {\n\t\tthis.configuration = configuration;\n\t\tthis.roots = roots;\n\t\tthis.send = send;\n\t\tthis.closeSocket = closeSocket;\n\t\tthis.budget = budget;\n\t}\n\n\treceive(payload: Uint8Array): Promise<void> {\n\t\tif (this.closed) return Promise.resolve();\n\t\tconst limits = this.configuration.protocolLimits;\n\t\tif (\n\t\t\tpayload.byteLength > limits.maxMessageBytes ||\n\t\t\tthis.pendingInboundMessages >= limits.maxPendingInboundMessages ||\n\t\t\tthis.pendingInboundBytes + payload.byteLength > limits.maxPendingInboundBytes\n\t\t) {\n\t\t\tthis.closed = true;\n\t\t\tthis.closeSocket(1009, \"Shared workspace inbound queue exceeds limits\");\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t// Copy before queuing: WebSocket buffers need not remain stable after the callback returns.\n\t\tconst queuedPayload = Uint8Array.from(payload);\n\t\tthis.pendingInboundMessages++;\n\t\tthis.pendingInboundBytes += queuedPayload.byteLength;\n\t\tlet complete!: () => void;\n\t\tconst finished = new Promise<void>((resolve) => {\n\t\t\tcomplete = resolve;\n\t\t});\n\t\tlet channelPending = false;\n\t\tconst settle = () => {\n\t\t\tthis.pendingInboundMessages--;\n\t\t\tthis.pendingInboundBytes -= queuedPayload.byteLength;\n\t\t\tcomplete();\n\t\t};\n\t\tconst fail = () => {\n\t\t\tif (!this.closed) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.closeSocket(1002, \"Invalid shared workspace frame\");\n\t\t\t}\n\t\t};\n\t\tconst scheduled = this.queue.then(() => {\n\t\t\tif (this.closed) return;\n\t\t\tconst frame = parseSharedWorkspaceClientEnvelope(queuedPayload, limits);\n\t\t\tif (frame.type === \"channel\") {\n\t\t\t\t// Validate the channel before letting the control queue advance. Its own\n\t\t\t\t// protocol preserves per-channel receive order and bounds queued frames.\n\t\t\t\tif (!this.channels.has(frame.channelId)) throw new Error(\"Unknown shared workspace channel\");\n\t\t\t\tchannelPending = true;\n\t\t\t\tvoid this.dispatch(frame).catch(fail).finally(settle);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Hello, opens, closes and reloads remain serialized in control order.\n\t\t\treturn this.dispatch(frame);\n\t\t});\n\t\tthis.queue = scheduled.catch(fail).finally(() => {\n\t\t\tif (!channelPending) settle();\n\t\t});\n\t\treturn finished;\n\t}\n\n\tget handshakeComplete(): boolean {\n\t\treturn this.hello;\n\t}\n\n\tasync beginDrain(): Promise<void> {\n\t\tawait Promise.allSettled([...this.channels.values()].map((channel) => channel.protocol.beginDrain()));\n\t}\n\n\tprivate createChannelRuntime(root: string): DaemonWorkspaceRuntime {\n\t\treturn createDaemonWorkspaceRuntime({\n\t\t\t...this.configuration,\n\t\t\tworkspaceRoot: root,\n\t\t\t// Operator-wide resource files and the v1 temporary root are not channel-scoped.\n\t\t\t// Keep them available on v1, but never expose them through a child channel.\n\t\t\ttemporaryRoot: undefined,\n\t\t\tsandboxInstructionsPath: undefined,\n\t\t\tuserAgentsPath: undefined,\n\t\t});\n\t}\n\n\treload(): Promise<void> {\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Shared workspace connection is closed\");\n\t\t\tfor (const channel of this.channels.values()) {\n\t\t\t\tconst previous = channel.runtime;\n\t\t\t\tconst previousHandler = channel.handler;\n\t\t\t\tconst candidate = this.createChannelRuntime(channel.workspace.root);\n\t\t\t\tconst candidateHandler = candidate.createHandler(channel.workspace, true);\n\t\t\t\tchannel.runtime = candidate;\n\t\t\t\tchannel.handler = candidateHandler;\n\t\t\t\ttry {\n\t\t\t\t\tawait channel.protocol.publishCatalog({ ...candidate.catalog, generation: channel.generation + 1 });\n\t\t\t\t\tchannel.generation++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tchannel.runtime = previous;\n\t\t\t\t\tchannel.handler = previousHandler;\n\t\t\t\t\tawait candidate.dispose();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait previous.retire();\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\treturn operation;\n\t}\n\n\tprivate async dispatch(frame: SharedWorkspaceClientEnvelope): Promise<void> {\n\t\tif (frame.type === \"hello\") {\n\t\t\tif (this.hello) throw new Error(\"Duplicate v2 hello\");\n\t\t\tthis.hello = true;\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tawait this.send({ type: \"hello_ack\", id: frame.id, version: 2, epoch: this.epoch, daemonVersion: VERSION });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.hello) throw new Error(\"V2 hello required before opening channels\");\n\t\tif (frame.type === \"open\") {\n\t\t\tif (this.usedControlIds.has(frame.id)) throw new Error(\"Duplicate v2 control ID\");\n\t\t\tif (this.usedControlIds.size >= 65_536) throw new Error(\"V2 control ID budget exhausted\");\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tif (this.channels.size >= Math.min(this.configuration.maxConnections, 32)) {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\tmessage: \"Channel limit reached\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet root: string;\n\t\t\ttry {\n\t\t\t\troot = await this.roots.bind(frame.root);\n\t\t\t} catch {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tmessage: \"Workspace root is not an existing directory under the shared parent\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.open(frame.id, root);\n\t\t\treturn;\n\t\t}\n\t\tconst channel = this.channels.get(frame.channelId);\n\t\tif (!channel) throw new Error(\"Unknown shared workspace channel\");\n\t\tif (frame.type === \"close\") {\n\t\t\t// Do not wait on a channel's in-flight requests while blocking the socket receive queue.\n\t\t\tthis.channels.delete(frame.channelId);\n\t\t\t// Begin cancellation before acknowledging detach; track it for physical shutdown.\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tawait this.send({ type: \"closed\", channelId: frame.channelId });\n\t\t\treturn;\n\t\t}\n\t\tawait channel.protocol.receive(Buffer.from(JSON.stringify(frame.payload)));\n\t}\n\n\tprivate async open(id: string, root: string): Promise<void> {\n\t\tconst channelId = randomBytes(24).toString(\"base64url\");\n\t\tconst workspace = Object.freeze({\n\t\t\tid: randomBytes(18).toString(\"base64url\"),\n\t\t\troot,\n\t\t\tpathFlavor: \"posix\" as const,\n\t\t});\n\t\tlet runtime: DaemonWorkspaceRuntime;\n\t\ttry {\n\t\t\truntime = this.createChannelRuntime(root);\n\t\t} catch {\n\t\t\t// A bad child project configuration is an open failure, not a corrupt\n\t\t\t// physical envelope. Keep already bound sibling channels usable.\n\t\t\tawait this.send({\n\t\t\t\ttype: \"control_error\",\n\t\t\t\tid,\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"Unable to initialize shared workspace channel\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst handler = runtime.createHandler(workspace, true);\n\t\tlet channel!: Channel;\n\t\tconst protocol = new RemoteWorkspaceServerProtocol(\n\t\t\t{\n\t\t\t\tsend: (payload: RemoteWorkspaceServerMessage) =>\n\t\t\t\t\tthis.channels.has(channelId) && !this.closed\n\t\t\t\t\t\t? this.send({ type: \"channel\", channelId, payload })\n\t\t\t\t\t\t: Promise.reject(new Error(\"Shared workspace channel is closed\")),\n\t\t\t\tclose: async (reason) => {\n\t\t\t\t\tconst channel = this.channels.get(channelId);\n\t\t\t\t\tif (channel) {\n\t\t\t\t\t\tthis.channels.delete(channelId);\n\t\t\t\t\t\tvoid this.disposeChannel(channel);\n\t\t\t\t\t\tif (!this.closed) await this.send({ type: \"closed\", channelId, reason });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalidateToolArguments: (toolName, value) => channel.handler.validateToolArguments(toolName, value),\n\t\t\t\thandleRequest: (request, context) =>\n\t\t\t\t\tthis.budget.run(request.method, async () => {\n\t\t\t\t\t\tconst result = await withSharedRevisionGuard(\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\tchannel.runtime.operations,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t() => channel.handler.handleRequest(request, context),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (request.method !== \"workspace.read\") return result;\n\t\t\t\t\t\tconst read = result as { contentBase64: string };\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...read,\n\t\t\t\t\t\t\trevision: createHash(\"sha256\").update(Buffer.from(read.contentBase64, \"base64\")).digest(\"hex\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\tworkspace,\n\t\t\t\tcatalog: runtime.catalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: this.configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-shared-workspace-daemon\",\n\t\t\t},\n\t\t);\n\t\tchannel = { runtime, handler, protocol, workspace, generation: runtime.catalog.generation };\n\t\tthis.channels.set(channelId, channel);\n\t\ttry {\n\t\t\tawait this.send({ type: \"opened\", id, channelId });\n\t\t} catch (error) {\n\t\t\tthis.channels.delete(channelId);\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate disposeChannel(channel: Channel): Promise<void> {\n\t\tconst existing = this.channelDisposals.get(channel);\n\t\tif (existing) return existing;\n\t\tconst disposal = (async () => {\n\t\t\tawait channel.protocol.disconnect().catch(() => undefined);\n\t\t\tawait channel.runtime.dispose().catch(() => undefined);\n\t\t})();\n\t\tthis.channelDisposals.set(channel, disposal);\n\t\tthis.pendingDisposals.add(disposal);\n\t\tvoid disposal.then(\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t);\n\t\treturn disposal;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tthis.closed = true;\n\t\tconst channels = [...this.channels.values()];\n\t\tthis.channels.clear();\n\t\tawait Promise.allSettled([...channels.map((channel) => this.disposeChannel(channel)), ...this.pendingDisposals]);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shared-connection.js","sourceRoot":"","sources":["../../src/daemon/shared-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { VERSION } from \"../config.ts\";\nimport type {\n\tRemoteWorkspaceIdentity,\n\tRemoteWorkspaceServerMessage,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tparseSharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { withSharedRevisionGuard } from \"./shared-revision.ts\";\nimport type { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime, type DaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\ninterface Channel {\n\treadonly protocol: RemoteWorkspaceServerProtocol;\n\truntime: DaemonWorkspaceRuntime;\n\thandler: RemoteWorkspaceServerHandler;\n\treadonly workspace: RemoteWorkspaceIdentity;\n\tgeneration: number;\n}\n\n/** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */\nexport class SharedDaemonConnection {\n\tprivate readonly channels = new Map<string, Channel>();\n\tprivate readonly channelDisposals = new WeakMap<Channel, Promise<void>>();\n\tprivate readonly pendingDisposals = new Set<Promise<void>>();\n\tprivate readonly usedControlIds = new Set<string>();\n\tprivate readonly epoch = randomBytes(18).toString(\"base64url\");\n\tprivate hello = false;\n\tprivate closed = false;\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate pendingInboundMessages = 0;\n\tprivate pendingInboundBytes = 0;\n\tprivate readonly budget: DaemonActivityBudget;\n\n\tprivate readonly configuration: DaemonConfiguration;\n\tprivate readonly roots: SharedWorkspaceRoots;\n\tprivate readonly send: (message: SharedWorkspaceServerFrame) => Promise<void>;\n\tprivate readonly closeSocket: (code: number, message: string) => void;\n\n\tconstructor(\n\t\tconfiguration: DaemonConfiguration,\n\t\troots: SharedWorkspaceRoots,\n\t\tsend: (message: SharedWorkspaceServerFrame) => Promise<void>,\n\t\tcloseSocket: (code: number, message: string) => void,\n\t\tbudget: DaemonActivityBudget = new DaemonActivityBudget(configuration),\n\t) {\n\t\tthis.configuration = configuration;\n\t\tthis.roots = roots;\n\t\tthis.send = send;\n\t\tthis.closeSocket = closeSocket;\n\t\tthis.budget = budget;\n\t}\n\n\treceive(payload: Uint8Array): Promise<void> {\n\t\tif (this.closed) return Promise.resolve();\n\t\tconst limits = this.configuration.protocolLimits;\n\t\tif (\n\t\t\tpayload.byteLength > limits.maxMessageBytes ||\n\t\t\tthis.pendingInboundMessages >= limits.maxPendingInboundMessages ||\n\t\t\tthis.pendingInboundBytes + payload.byteLength > limits.maxPendingInboundBytes\n\t\t) {\n\t\t\tthis.closed = true;\n\t\t\tthis.closeSocket(1009, \"Shared workspace inbound queue exceeds limits\");\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t// Copy before queuing: WebSocket buffers need not remain stable after the callback returns.\n\t\tconst queuedPayload = Uint8Array.from(payload);\n\t\tthis.pendingInboundMessages++;\n\t\tthis.pendingInboundBytes += queuedPayload.byteLength;\n\t\tlet complete!: () => void;\n\t\tconst finished = new Promise<void>((resolve) => {\n\t\t\tcomplete = resolve;\n\t\t});\n\t\tlet channelPending = false;\n\t\tconst settle = () => {\n\t\t\tthis.pendingInboundMessages--;\n\t\t\tthis.pendingInboundBytes -= queuedPayload.byteLength;\n\t\t\tcomplete();\n\t\t};\n\t\tconst fail = () => {\n\t\t\tif (!this.closed) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.closeSocket(1002, \"Invalid shared workspace frame\");\n\t\t\t}\n\t\t};\n\t\tconst scheduled = this.queue.then(() => {\n\t\t\tif (this.closed) return;\n\t\t\tconst frame = parseSharedWorkspaceClientEnvelope(queuedPayload, limits);\n\t\t\tif (frame.type === \"channel\") {\n\t\t\t\t// Validate the channel before letting the control queue advance. Its own\n\t\t\t\t// protocol preserves per-channel receive order and bounds queued frames.\n\t\t\t\tif (!this.channels.has(frame.channelId)) throw new Error(\"Unknown shared workspace channel\");\n\t\t\t\tchannelPending = true;\n\t\t\t\tvoid this.dispatch(frame).catch(fail).finally(settle);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Hello, opens, closes and reloads remain serialized in control order.\n\t\t\treturn this.dispatch(frame);\n\t\t});\n\t\tthis.queue = scheduled.catch(fail).finally(() => {\n\t\t\tif (!channelPending) settle();\n\t\t});\n\t\treturn finished;\n\t}\n\n\tget handshakeComplete(): boolean {\n\t\treturn this.hello;\n\t}\n\n\tasync beginDrain(): Promise<void> {\n\t\tawait Promise.allSettled([...this.channels.values()].map((channel) => channel.protocol.beginDrain()));\n\t}\n\n\tprivate createChannelRuntime(root: string): DaemonWorkspaceRuntime {\n\t\treturn createDaemonWorkspaceRuntime({\n\t\t\t...this.configuration,\n\t\t\tworkspaceRoot: root,\n\t\t\t// Operator-wide resource files and the v1 temporary root are not channel-scoped.\n\t\t\t// Keep them available on v1, but never expose them through a child channel.\n\t\t\ttemporaryRoot: undefined,\n\t\t\tsandboxInstructionsPath: undefined,\n\t\t\tuserAgentsPath: undefined,\n\t\t});\n\t}\n\n\treload(): Promise<void> {\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Shared workspace connection is closed\");\n\t\t\tfor (const channel of this.channels.values()) {\n\t\t\t\tconst previous = channel.runtime;\n\t\t\t\tconst previousHandler = channel.handler;\n\t\t\t\tconst candidate = this.createChannelRuntime(channel.workspace.root);\n\t\t\t\tconst candidateHandler = candidate.createHandler(channel.workspace, true);\n\t\t\t\tchannel.runtime = candidate;\n\t\t\t\tchannel.handler = candidateHandler;\n\t\t\t\ttry {\n\t\t\t\t\tawait channel.protocol.publishCatalog({ ...candidate.catalog, generation: channel.generation + 1 });\n\t\t\t\t\tchannel.generation++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tchannel.runtime = previous;\n\t\t\t\t\tchannel.handler = previousHandler;\n\t\t\t\t\tawait candidate.dispose();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait previous.retire();\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\treturn operation;\n\t}\n\n\tprivate async dispatch(frame: SharedWorkspaceClientEnvelope): Promise<void> {\n\t\tif (frame.type === \"hello\") {\n\t\t\tif (this.hello) throw new Error(\"Duplicate v2 hello\");\n\t\t\tthis.hello = true;\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tawait this.send({ type: \"hello_ack\", id: frame.id, version: 2, epoch: this.epoch, daemonVersion: VERSION });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.hello) throw new Error(\"V2 hello required before opening channels\");\n\t\tif (frame.type === \"open\") {\n\t\t\tif (this.usedControlIds.has(frame.id)) throw new Error(\"Duplicate v2 control ID\");\n\t\t\tif (this.usedControlIds.size >= 65_536) throw new Error(\"V2 control ID budget exhausted\");\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tif (this.channels.size >= Math.min(this.configuration.maxConnections, 32)) {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\tmessage: \"Channel limit reached\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet root: string;\n\t\t\ttry {\n\t\t\t\troot = await this.roots.bind(frame.root);\n\t\t\t} catch {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tmessage: \"Workspace root is not an existing directory under the shared parent\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.open(frame.id, root);\n\t\t\treturn;\n\t\t}\n\t\tconst channel = this.channels.get(frame.channelId);\n\t\tif (!channel) throw new Error(\"Unknown shared workspace channel\");\n\t\tif (frame.type === \"close\") {\n\t\t\t// Do not wait on a channel's in-flight requests while blocking the socket receive queue.\n\t\t\tthis.channels.delete(frame.channelId);\n\t\t\t// Begin cancellation before acknowledging detach; track it for physical shutdown.\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tawait this.send({ type: \"closed\", channelId: frame.channelId });\n\t\t\treturn;\n\t\t}\n\t\tawait channel.protocol.receive(Buffer.from(JSON.stringify(frame.payload)));\n\t}\n\n\tprivate async open(id: string, root: string): Promise<void> {\n\t\tconst channelId = randomBytes(24).toString(\"base64url\");\n\t\tconst workspace = Object.freeze({\n\t\t\tid: randomBytes(18).toString(\"base64url\"),\n\t\t\troot,\n\t\t\tpathFlavor: \"posix\" as const,\n\t\t});\n\t\tlet runtime: DaemonWorkspaceRuntime;\n\t\ttry {\n\t\t\truntime = this.createChannelRuntime(root);\n\t\t} catch {\n\t\t\t// A bad child project configuration is an open failure, not a corrupt\n\t\t\t// physical envelope. Keep already bound sibling channels usable.\n\t\t\tawait this.send({\n\t\t\t\ttype: \"control_error\",\n\t\t\t\tid,\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"Unable to initialize shared workspace channel\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst handler = runtime.createHandler(workspace, true);\n\t\tlet channel!: Channel;\n\t\tconst protocol = new RemoteWorkspaceServerProtocol(\n\t\t\t{\n\t\t\t\tsend: (payload: RemoteWorkspaceServerMessage) =>\n\t\t\t\t\tthis.channels.has(channelId) && !this.closed\n\t\t\t\t\t\t? this.send({ type: \"channel\", channelId, payload })\n\t\t\t\t\t\t: Promise.reject(new Error(\"Shared workspace channel is closed\")),\n\t\t\t\tclose: async (reason) => {\n\t\t\t\t\tconst channel = this.channels.get(channelId);\n\t\t\t\t\tif (channel) {\n\t\t\t\t\t\tthis.channels.delete(channelId);\n\t\t\t\t\t\tvoid this.disposeChannel(channel);\n\t\t\t\t\t\tif (!this.closed) await this.send({ type: \"closed\", channelId, reason });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalidateToolArguments: (toolName, value) => channel.handler.validateToolArguments(toolName, value),\n\t\t\t\thandleRequest: (request, context) =>\n\t\t\t\t\tthis.budget.run(request.method, async () => {\n\t\t\t\t\t\tconst result = await withSharedRevisionGuard(\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\tchannel.runtime.operations,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t() => channel.handler.handleRequest(request, context),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (request.method !== \"workspace.read\") return result;\n\t\t\t\t\t\tconst read = result as { contentBase64: string };\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...read,\n\t\t\t\t\t\t\trevision: createHash(\"sha256\").update(Buffer.from(read.contentBase64, \"base64\")).digest(\"hex\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\tworkspace,\n\t\t\t\tcatalog: runtime.catalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: this.configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-shared-workspace-daemon\",\n\t\t\t},\n\t\t);\n\t\tchannel = { runtime, handler, protocol, workspace, generation: runtime.catalog.generation };\n\t\tthis.channels.set(channelId, channel);\n\t\ttry {\n\t\t\tawait this.send({ type: \"opened\", id, channelId });\n\t\t} catch (error) {\n\t\t\tthis.channels.delete(channelId);\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate disposeChannel(channel: Channel): Promise<void> {\n\t\tconst existing = this.channelDisposals.get(channel);\n\t\tif (existing) return existing;\n\t\tconst disposal = (async () => {\n\t\t\tawait channel.protocol.disconnect().catch(() => undefined);\n\t\t\tawait channel.runtime.dispose().catch(() => undefined);\n\t\t})();\n\t\tthis.channelDisposals.set(channel, disposal);\n\t\tthis.pendingDisposals.add(disposal);\n\t\tvoid disposal.then(\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t);\n\t\treturn disposal;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tthis.closed = true;\n\t\tconst channels = [...this.channels.values()];\n\t\tthis.channels.clear();\n\t\tawait Promise.allSettled([...channels.map((channel) => this.disposeChannel(channel)), ...this.pendingDisposals]);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-revision.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,mCAAmC,EACxC,KAAK,2BAA2B,EAChC,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAmD3E,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,CAAC,EACxC,OAAO,EAAE,2BAA2B,EACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,4BAA4B,EACxC,OAAO,EAAE,mCAAmC,EAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"shared-revision.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,mCAAmC,EACxC,KAAK,2BAA2B,EAChC,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAmD3E,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,CAAC,EACxC,OAAO,EAAE,2BAA2B,EACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,4BAA4B,EACxC,OAAO,EAAE,mCAAmC,EAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,CAAC,CAAC,CAiBZ"}
|
|
@@ -55,7 +55,8 @@ export function withSharedRevisionGuard(request, root, operations, context, acti
|
|
|
55
55
|
if (!revision || (toolName === "edit" && !("sha256" in revision))) {
|
|
56
56
|
throw revisionError("invalid_request", "Shared edit requires expected SHA-256; shared write requires expected SHA-256, expected absence or explicit unsafeOverwrite");
|
|
57
57
|
}
|
|
58
|
-
const
|
|
58
|
+
const options = params.executionOptions;
|
|
59
|
+
const target = resolve(options?.cwd ?? root, args.path);
|
|
59
60
|
return withFileMutationGuard((filePath) => checkRevision(filePath, target, revision, operations, context), action);
|
|
60
61
|
}
|
|
61
62
|
//# sourceMappingURL=shared-revision.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-revision.js","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACN,2BAA2B,GAG3B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAK7E,SAAS,aAAa,CAAC,IAA6B,EAAE,OAAe
|
|
1
|
+
{"version":3,"file":"shared-revision.js","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport type { ExpectedWorkspaceRevision } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerRequestContext,\n\ttype RemoteWorkspaceTypedRequest,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport { withFileMutationGuard } from \"../core/tools/file-mutation-queue.ts\";\nimport type { ConfinedDaemonToolOperations } from \"./workspace-runtime.ts\";\n\ntype SharedRevisionErrorCode = \"invalid_request\" | \"conflict\";\n\nfunction revisionError(code: SharedRevisionErrorCode, message: string): RemoteWorkspaceRequestError {\n\treturn new RemoteWorkspaceRequestError({ code, message, executionState: \"not_started\", retryable: false });\n}\nfunction requireActiveMutation(context: RemoteWorkspaceServerRequestContext): void {\n\tif (context.signal.aborted)\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"cancelled\",\n\t\t\tmessage: \"Shared mutation was cancelled before starting\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n}\n\nfunction missing(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error.code === \"ENOENT\" || error.code === \"ENOTDIR\")\n\t);\n}\n\nasync function checkRevision(\n\tfilePath: string,\n\ttarget: string,\n\trevision: ExpectedWorkspaceRevision,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n): Promise<void> {\n\trequireActiveMutation(context);\n\tif (resolve(filePath) !== target)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation path does not match its revision precondition\");\n\tif (\"sha256\" in revision || \"absent\" in revision) {\n\t\tlet actual: Buffer | undefined;\n\t\ttry {\n\t\t\tactual = await operations.readFile(target);\n\t\t} catch (error) {\n\t\t\tif (!missing(error)) throw error;\n\t\t}\n\t\tif (\"sha256\" in revision && (!actual || createHash(\"sha256\").update(actual).digest(\"hex\") !== revision.sha256)) {\n\t\t\tthrow revisionError(\"conflict\", \"Workspace file changed since the expected revision\");\n\t\t}\n\t\tif (\"absent\" in revision && actual) throw revisionError(\"conflict\", \"Workspace file already exists\");\n\t}\n\trequireActiveMutation(context);\n\tcontext.markSideEffectStarted();\n}\n/** v2-only CAS checked inside the same process-wide per-file queue as edit/write. */\nexport function withSharedRevisionGuard<T>(\n\trequest: RemoteWorkspaceTypedRequest,\n\troot: string,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\taction: () => Promise<T>,\n): Promise<T> {\n\tconst params = request.params as Record<string, unknown>;\n\tconst toolName = request.method === \"tool.invoke\" ? params.toolName : undefined;\n\tif (request.method !== \"workspace.write\" && toolName !== \"edit\" && toolName !== \"write\") return action();\n\tconst args = toolName ? (params.arguments as { path?: unknown }) : params;\n\tif (typeof args?.path !== \"string\" || !args.path)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation requires a file path\");\n\tconst revision = params.expectedRevision as ExpectedWorkspaceRevision | undefined;\n\tif (!revision || (toolName === \"edit\" && !(\"sha256\" in revision))) {\n\t\tthrow revisionError(\n\t\t\t\"invalid_request\",\n\t\t\t\"Shared edit requires expected SHA-256; shared write requires expected SHA-256, expected absence or explicit unsafeOverwrite\",\n\t\t);\n\t}\n\tconst options = params.executionOptions as { cwd?: string } | undefined;\n\tconst target = resolve(options?.cwd ?? root, args.path);\n\treturn withFileMutationGuard((filePath) => checkRevision(filePath, target, revision, operations, context), action);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-roots.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAGA,sEAAsE;AACtE,qBAAa,oBAAoB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,eAEN;IAED,OAAa,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAIrE;IAEK,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS7C;IAED,OAAO,CAAC,YAAY;CAMpB"
|
|
1
|
+
{"version":3,"file":"shared-roots.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAGA,sEAAsE;AACtE,qBAAa,oBAAoB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,eAEN;IAED,OAAa,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAIrE;IAEK,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS7C;IAED,OAAO,CAAC,YAAY;CAMpB"}
|
|
@@ -2,7 +2,6 @@ import { realpath, stat } from "node:fs/promises";
|
|
|
2
2
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
3
|
/** The parent mount is fixed; children can be created at any time. */
|
|
4
4
|
export class SharedWorkspaceRoots {
|
|
5
|
-
parent;
|
|
6
5
|
constructor(parent) {
|
|
7
6
|
this.parent = parent;
|
|
8
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-roots.js","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE/D,sEAAsE;AACtE,MAAM,OAAO,oBAAoB;
|
|
1
|
+
{"version":3,"file":"shared-roots.js","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE/D,sEAAsE;AACtE,MAAM,OAAO,oBAAoB;IAEhC,YAAoB,MAAc;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc;QACrC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC1G,OAAO,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB;QAC3B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACxG,OAAO,SAAS,CAAC;IAClB,CAAC;IAEO,YAAY,CAAC,IAAY;QAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;IACF,CAAC;CACD","sourcesContent":["import { realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\n\n/** The parent mount is fixed; children can be created at any time. */\nexport class SharedWorkspaceRoots {\n\treadonly parent: string;\n\tprivate constructor(parent: string) {\n\t\tthis.parent = parent;\n\t}\n\n\tstatic async fromParent(parent: string): Promise<SharedWorkspaceRoots> {\n\t\tconst canonical = await realpath(parent);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace parent is not a directory\");\n\t\treturn new SharedWorkspaceRoots(canonical);\n\t}\n\n\tasync bind(requested: string): Promise<string> {\n\t\tif (!isAbsolute(requested) || requested.includes(\"\\0\"))\n\t\t\tthrow new Error(\"Shared workspace root must be an absolute path\");\n\t\tconst candidate = resolve(requested);\n\t\tthis.assertWithin(candidate);\n\t\tconst canonical = await realpath(candidate);\n\t\tthis.assertWithin(canonical);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace root is not a directory\");\n\t\treturn canonical;\n\t}\n\n\tprivate assertWithin(path: string): void {\n\t\tconst suffix = relative(this.parent, path);\n\t\tif (suffix === \"..\" || suffix.startsWith(`..${sep}`) || isAbsolute(suffix)) {\n\t\t\tthrow new Error(\"Shared workspace root escapes the parent mount\");\n\t\t}\n\t}\n}\n"]}
|
|
@@ -8,6 +8,7 @@ export declare class ConfinedDaemonToolOperations implements ToolOperations {
|
|
|
8
8
|
readonly cwd: string;
|
|
9
9
|
private readonly local;
|
|
10
10
|
private readonly allowedRoots;
|
|
11
|
+
private readonly allowFullFilesystem;
|
|
11
12
|
private readonly allowProcessExec;
|
|
12
13
|
private readonly environment;
|
|
13
14
|
private readonly maxBufferedOutputBytes;
|
|
@@ -16,6 +17,7 @@ export declare class ConfinedDaemonToolOperations implements ToolOperations {
|
|
|
16
17
|
private isWithinAllowedRoot;
|
|
17
18
|
private lexicalPath;
|
|
18
19
|
private existingPath;
|
|
20
|
+
resolveWorkingDirectory(path: string): Promise<string>;
|
|
19
21
|
private existingWritablePath;
|
|
20
22
|
private ensureConfinedWritableParent;
|
|
21
23
|
private writablePath;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-runtime.d.ts","sourceRoot":"","sources":["../../src/daemon/workspace-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir as fsMkdir, lstat, open, readFile, realpath, rename, rm } from \"node:fs/promises\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { AgentToolResult } from \"@greppleai/grip-agent-core\";\nimport { createLspRuntimeState, createLspToolDefinitions, type LspRuntimeState } from \"../core/lsp/integration.ts\";\nimport type { LspServerStatus } from \"../core/lsp/manager.ts\";\nimport { createManagedStdioConnectionFactory, resolveLspConnectionFactory } from \"../core/lsp/transport.ts\";\nimport {\n\thashRemoteWorkspaceJson,\n\ttype RemoteWorkspaceCapability,\n\ttype RemoteWorkspaceCatalog,\n\ttype RemoteWorkspaceIdentity,\n\ttype RemoteWorkspaceMethod,\n\ttype RemoteWorkspaceOperationKind,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerHandler,\n\ttype RemoteWorkspaceServerRequestContext,\n\ttype RemoteWorkspaceTypedRequest,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport { withFileMutationQueue } from \"../core/tools/file-mutation-queue.ts\";\nimport {\n\tGRIP_SESSION_ENVIRONMENT_NAMES,\n\tLocalToolOperations,\n\ttype ToolAccessMode,\n\ttype ToolBackendInfo,\n\ttype ToolExecOptions,\n\ttype ToolExecResult,\n\ttype ToolFileStat,\n\ttype ToolGlobOptions,\n\ttype ToolGrepMatch,\n\ttype ToolGrepOptions,\n\ttype ToolGrepResult,\n\ttype ToolMkdirOptions,\n\ttype ToolOperations,\n\ttype WorkspaceToolExecutionOptions,\n} from \"../core/tools/operations.ts\";\nimport { WorkspaceToolHost, type WorkspaceToolName } from \"../core/tools/workspace-tool-host.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { loadDaemonLspConfiguration } from \"./lsp-config.ts\";\nimport { redactDaemonText } from \"./security.ts\";\n\nconst PRIMITIVE_OPERATIONS: RemoteWorkspaceMethod[] = [\n\t\"workspace.access\",\n\t\"workspace.read\",\n\t\"workspace.write\",\n\t\"workspace.mkdir\",\n\t\"workspace.stat\",\n\t\"workspace.readdir\",\n\t\"workspace.glob\",\n\t\"workspace.grep\",\n\t\"workspace.detect_image_mime\",\n\t\"workspace.exec\",\n];\n\nconst SECRET_ENVIRONMENT_SUFFIX = /_(?:API_KEY|TOKEN|SECRET|PASSWORD|PRIVATE_KEY|CREDENTIALS)$/iu;\nconst BASELINE_ENVIRONMENT =\n\tprocess.platform === \"win32\"\n\t\t? [\"PATH\", \"PATHEXT\", \"SYSTEMROOT\", \"COMSPEC\", \"TEMP\", \"TMP\", \"USER\", \"USERNAME\"]\n\t\t: [\"PATH\", \"HOME\", \"USER\", \"LOGNAME\", \"SHELL\", \"LANG\", \"TERM\", \"COLORTERM\", \"NO_COLOR\", \"TMPDIR\"];\n\nfunction isSecretEnvironmentName(name: string): boolean {\n\tconst upper = name.toUpperCase();\n\treturn (\n\t\tupper === \"GRIP_DAEMON_TOKEN\" ||\n\t\tupper === \"PI_DAEMON_TOKEN\" ||\n\t\tupper === \"GRIP_REMOTE_TOKEN\" ||\n\t\tupper.startsWith(\"GRIP_DAEMON_TLS_\") ||\n\t\tupper.startsWith(\"PI_DAEMON_TLS_\") ||\n\t\tSECRET_ENVIRONMENT_SUFFIX.test(upper)\n\t);\n}\nprocess.platform === \"win32\"\n\t? [\"PATH\", \"PATHEXT\", \"SYSTEMROOT\", \"TEMP\", \"TMP\"]\n\t: [\"PATH\", \"HOME\", \"LANG\", \"LC_ALL\", \"TERM\", \"TMPDIR\"];\n\nfunction isMissingPath(error: unknown): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n\nfunction sanitizeLspStatus(\n\tstatus: LspServerStatus,\n\tconfiguration: DaemonConfiguration,\n): Omit<LspServerStatus, \"capabilities\"> {\n\tconst { capabilities: _capabilities, ...safe } = status;\n\tconst secrets = [configuration.token, configuration.tls?.passphrase];\n\tconst redact = (value: string | undefined) => (value ? redactDaemonText(value, secrets) : undefined);\n\treturn {\n\t\t...safe,\n\t\tserverId: redact(safe.serverId)!,\n\t\tlanguageIds: safe.languageIds.map((value) => redact(value)!),\n\t\ttransport: redact(safe.transport)!,\n\t\t...(safe.instanceKey ? { instanceKey: redact(safe.instanceKey) } : {}),\n\t\t...(safe.workspaceRoot ? { workspaceRoot: redact(safe.workspaceRoot) } : {}),\n\t\t...(safe.rootUri ? { rootUri: redact(safe.rootUri) } : {}),\n\t\t...(safe.endpoint ? { endpoint: redact(safe.endpoint) } : {}),\n\t\t...(safe.lastError ? { lastError: redact(safe.lastError) } : {}),\n\t\t...(safe.lastRequestError ? { lastRequestError: redact(safe.lastRequestError) } : {}),\n\t\t...(safe.stderr ? { stderr: redact(safe.stderr) } : {}),\n\t\t...(safe.synchronizationError ? { synchronizationError: redact(safe.synchronizationError) } : {}),\n\t};\n}\n\nfunction portableToolResult(result: AgentToolResult<unknown>): AgentToolResult<unknown> {\n\tconst clone = JSON.parse(JSON.stringify(result)) as AgentToolResult<unknown>;\n\tconst details = clone.details;\n\tif (!details || typeof details !== \"object\" || !(\"fullOutputPath\" in details)) return clone;\n\tconst fullOutputPath = (details as { fullOutputPath?: unknown }).fullOutputPath;\n\tif (typeof fullOutputPath !== \"string\") return clone;\n\tdelete (details as { fullOutputPath?: unknown }).fullOutputPath;\n\tfor (const content of clone.content) {\n\t\tif (content.type === \"text\") {\n\t\t\tcontent.text = content.text.replaceAll(fullOutputPath, \"[remote full output is not transferable]\");\n\t\t}\n\t}\n\treturn clone;\n}\n\nfunction operationKind(name: string): RemoteWorkspaceOperationKind {\n\tif (name.startsWith(\"lsp_\")) return \"service\";\n\tswitch (name) {\n\t\tcase \"read\":\n\t\tcase \"grep\":\n\t\tcase \"find\":\n\t\tcase \"ls\":\n\t\t\treturn \"read\";\n\t\tcase \"edit\":\n\t\tcase \"write\":\n\t\t\treturn \"mutation\";\n\t\tcase \"bash\":\n\t\t\treturn \"process\";\n\t}\n\tthrow new Error(`Unknown daemon tool: ${name}`);\n}\n\nfunction runCommand(\n\tcommand: string,\n\targs: string[],\n\tenvironment: NodeJS.ProcessEnv,\n\tmaxBufferedBytes: number,\n): Promise<Buffer> {\n\treturn new Promise((resolvePromise, reject) => {\n\t\tconst child = spawn(command, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"], windowsHide: true, env: environment });\n\t\tconst stdout: Buffer[] = [];\n\t\tconst stderr: Buffer[] = [];\n\t\tlet bufferedBytes = 0;\n\t\tlet settled = false;\n\t\tconst append = (target: Buffer[], chunk: Buffer) => {\n\t\t\tif (settled) return;\n\t\t\tbufferedBytes += chunk.byteLength;\n\t\t\tif (bufferedBytes > maxBufferedBytes) {\n\t\t\t\tsettled = true;\n\t\t\t\tchild.kill();\n\t\t\t\treject(new Error(`${command} output exceeded the daemon buffered-output limit`));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttarget.push(Buffer.from(chunk));\n\t\t};\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => append(stdout, chunk));\n\t\tchild.stderr.on(\"data\", (chunk: Buffer) => append(stderr, chunk));\n\t\tchild.once(\"error\", (error) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\treject(error);\n\t\t});\n\t\tchild.once(\"close\", (code) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tif (code === 0 || (command === \"rg\" && code === 1)) {\n\t\t\t\tresolvePromise(Buffer.concat(stdout));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treject(new Error(Buffer.concat(stderr).toString(\"utf8\").trim() || `${command} exited with code ${code}`));\n\t\t});\n\t});\n}\n\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction nestedText(record: Record<string, unknown> | undefined, key: string): string | undefined {\n\tconst nested = record?.[key];\n\treturn isUnknownRecord(nested) && typeof nested.text === \"string\" ? nested.text : undefined;\n}\n\nfunction parseDaemonGrepMatch(line: string): ToolGrepMatch | undefined {\n\tif (!line) return undefined;\n\tlet event: unknown;\n\ttry {\n\t\tevent = JSON.parse(line) as unknown;\n\t} catch {\n\t\treturn undefined;\n\t}\n\tconst eventRecord = isUnknownRecord(event) ? event : undefined;\n\tif (eventRecord?.type !== \"match\") return undefined;\n\tconst data = isUnknownRecord(eventRecord.data) ? eventRecord.data : undefined;\n\tconst filePath = nestedText(data, \"path\");\n\tconst lineNumber = data?.line_number;\n\tif (!filePath || typeof lineNumber !== \"number\") return undefined;\n\tconst lineText = nestedText(data, \"lines\");\n\treturn { filePath, lineNumber, ...(lineText === undefined ? {} : { lineText }) };\n}\n\nexport class ConfinedDaemonToolOperations implements ToolOperations {\n\treadonly cwd: string;\n\tprivate readonly local: LocalToolOperations;\n\tprivate readonly allowedRoots: readonly string[];\n\tprivate readonly allowProcessExec: boolean;\n\tprivate readonly environment: NodeJS.ProcessEnv;\n\tprivate readonly maxBufferedOutputBytes: number;\n\n\tconstructor(configuration: DaemonConfiguration) {\n\t\tthis.cwd = configuration.workspaceRoot;\n\t\tthis.local = new LocalToolOperations(this.cwd);\n\t\tthis.allowedRoots = Object.freeze([\n\t\t\tthis.cwd,\n\t\t\t...(configuration.temporaryRoot ? [configuration.temporaryRoot] : []),\n\t\t]);\n\t\tthis.allowProcessExec = configuration.allowProcessExec;\n\t\tthis.maxBufferedOutputBytes = configuration.maxBufferedOutputBytes;\n\t\tconst localeNames = Object.keys(process.env).filter((name) => /^LC_/iu.test(name));\n\t\tconst names = new Set([...BASELINE_ENVIRONMENT, ...localeNames, ...configuration.forwardedEnvironment]);\n\t\tthis.environment = {};\n\t\tfor (const name of names) {\n\t\t\tif (isSecretEnvironmentName(name)) continue;\n\t\t\tconst value = process.env[name];\n\t\t\tif (value !== undefined) this.environment[name] = value;\n\t\t}\n\t}\n\n\tcreateChildEnvironment(extra: Record<string, string> = {}): Record<string, string> {\n\t\tconst environment: Record<string, string> = {};\n\t\tfor (const [name, value] of Object.entries(this.environment)) {\n\t\t\tif (value !== undefined) environment[name] = value;\n\t\t}\n\t\tObject.assign(environment, extra);\n\t\tfor (const name of Object.keys(environment)) {\n\t\t\tif (isSecretEnvironmentName(name)) delete environment[name];\n\t\t}\n\t\treturn environment;\n\t}\n\tprivate isWithinAllowedRoot(candidate: string, root: string): boolean {\n\t\tconst pathRelative = relative(root, candidate);\n\t\treturn pathRelative !== \"..\" && !pathRelative.startsWith(`..${sep}`) && !isAbsolute(pathRelative);\n\t}\n\n\tprivate lexicalPath(path: string): string {\n\t\tconst candidate = resolve(this.cwd, path);\n\t\tif (!this.allowedRoots.some((root) => this.isWithinAllowedRoot(candidate, root))) {\n\t\t\tthrow new Error(`Path escapes the daemon workspace and allowed temporary root: ${path}`);\n\t\t}\n\t\treturn candidate;\n\t}\n\n\tprivate async existingPath(path: string): Promise<string> {\n\t\tconst candidate = this.lexicalPath(path);\n\t\tconst canonical = await realpath(candidate);\n\t\treturn this.lexicalPath(canonical);\n\t}\n\n\tprivate async existingWritablePath(candidate: string, path: string): Promise<string | undefined> {\n\t\ttry {\n\t\t\tconst stat = await lstat(candidate);\n\t\t\tif (stat.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.lexicalPath(await realpath(candidate));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isMissingPath(error)) throw new Error(`Writable path uses a broken symbolic link: ${path}`);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Writable path uses a symbolic link: ${path}`);\n\t\t\t}\n\t\t\tconst canonical = await realpath(candidate);\n\t\t\tthis.lexicalPath(canonical);\n\t\t\treturn this.lexicalPath(canonical);\n\t\t} catch (error) {\n\t\t\tif (isMissingPath(error)) return undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async ensureConfinedWritableParent(candidate: string, path: string): Promise<void> {\n\t\tlet parent = resolve(candidate, \"..\");\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\tconst parentStat = await lstat(parent);\n\t\t\t\tif (parentStat.isSymbolicLink()) {\n\t\t\t\t\tthis.lexicalPath(await realpath(parent));\n\t\t\t\t\tthrow new Error(`Writable parent uses a symbolic link: ${path}`);\n\t\t\t\t}\n\t\t\t\tconst canonicalParent = await realpath(parent);\n\t\t\t\tthis.lexicalPath(canonicalParent);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif (!isMissingPath(error)) throw error;\n\t\t\t\tconst next = resolve(parent, \"..\");\n\t\t\t\tif (next === parent) throw new Error(`No confined parent exists for path: ${path}`);\n\t\t\t\tparent = next;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async writablePath(path: string): Promise<string> {\n\t\tconst candidate = this.lexicalPath(path);\n\t\tconst existing = await this.existingWritablePath(candidate, path);\n\t\tif (existing) return existing;\n\t\tawait this.ensureConfinedWritableParent(candidate, path);\n\t\treturn candidate;\n\t}\n\n\tprivate async atomicWriteFile(path: string, content: string | Buffer): Promise<void> {\n\t\tconst target = await this.writablePath(path);\n\t\tconst parent = resolve(target, \"..\");\n\t\tconst temporary = resolve(parent, `.grip-remote-write-${process.pid}-${randomUUID()}-${basename(target)}.tmp`);\n\t\tthis.lexicalPath(temporary);\n\t\tlet wroteTemporary = false;\n\t\ttry {\n\t\t\tconst handle = await open(temporary, \"wx\", 0o600);\n\t\t\ttry {\n\t\t\t\tawait handle.writeFile(content, typeof content === \"string\" ? \"utf8\" : undefined);\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t\twroteTemporary = true;\n\t\t\tthis.lexicalPath(await realpath(temporary));\n\t\t\ttry {\n\t\t\t\tif ((await lstat(target)).isSymbolicLink()) throw new Error(`Writable path uses a symbolic link: ${path}`);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isMissingPath(error)) throw error;\n\t\t\t}\n\t\t\tawait rename(temporary, target);\n\t\t\twroteTemporary = false;\n\t\t\tthis.lexicalPath(await realpath(target));\n\t\t} finally {\n\t\t\tif (wroteTemporary) await rm(temporary, { force: true });\n\t\t}\n\t}\n\n\tasync exec(command: string, options: ToolExecOptions): Promise<ToolExecResult> {\n\t\tif (!this.allowProcessExec) throw new Error(\"Process execution is disabled by daemon policy\");\n\t\tconst cwd = await this.existingPath(options.cwd ?? this.cwd);\n\t\tconst environment = { ...this.environment };\n\t\tfor (const name of GRIP_SESSION_ENVIRONMENT_NAMES) {\n\t\t\tconst value = options.env?.[name];\n\t\t\tif (value !== undefined) environment[name] = value;\n\t\t}\n\t\treturn this.local.exec(command, { ...options, cwd, env: environment });\n\t}\n\n\tasync access(path: string, mode?: ToolAccessMode): Promise<void> {\n\t\tawait this.local.access(await this.existingPath(path), mode);\n\t}\n\n\tasync readFile(path: string): Promise<Buffer> {\n\t\treturn this.local.readFile(await this.existingPath(path));\n\t}\n\n\tasync writeFile(path: string, content: string | Buffer): Promise<void> {\n\t\tawait this.atomicWriteFile(path, content);\n\t}\n\n\tasync mkdir(path: string, options?: ToolMkdirOptions): Promise<void> {\n\t\tawait fsMkdir(await this.writablePath(path), options);\n\t}\n\n\tasync stat(path: string): Promise<ToolFileStat> {\n\t\treturn this.local.stat(await this.existingPath(path));\n\t}\n\n\tasync readdir(path: string): Promise<string[]> {\n\t\treturn this.local.readdir(await this.existingPath(path));\n\t}\n\n\tasync glob(pattern: string, cwd: string, options: ToolGlobOptions): Promise<string[]> {\n\t\tconst searchRoot = await this.existingPath(cwd);\n\t\tconst args = [\"--glob\", \"--color=never\", \"--hidden\", \"--no-require-git\", \"--max-results\", String(options.limit)];\n\t\tfor (const ignored of options.ignore) args.push(\"--exclude\", ignored);\n\t\tlet effectivePattern = pattern;\n\t\tif (pattern.includes(\"/\")) {\n\t\t\targs.push(\"--full-path\");\n\t\t\tif (!pattern.startsWith(\"/\") && !pattern.startsWith(\"**/\") && pattern !== \"**\")\n\t\t\t\teffectivePattern = `**/${pattern}`;\n\t\t}\n\t\targs.push(\"--\", effectivePattern, searchRoot);\n\t\tconst output = await runCommand(\"fd\", args, this.environment, this.maxBufferedOutputBytes);\n\t\tconst results: string[] = [];\n\t\tfor (const entry of output.toString(\"utf8\").split(\"\\n\")) {\n\t\t\tif (!entry) continue;\n\t\t\ttry {\n\t\t\t\tresults.push(await this.existingPath(entry));\n\t\t\t} catch {\n\t\t\t\t// Symlinks escaping the workspace are deliberately omitted.\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tasync grep(options: ToolGrepOptions): Promise<ToolGrepResult> {\n\t\tconst searchPath = await this.existingPath(options.path);\n\t\tconst isDirectory = (await this.local.stat(searchPath)).isDirectory();\n\t\tconst args = [\"--json\", \"--line-number\", \"--color=never\", \"--hidden\"];\n\t\tif (options.ignoreCase) args.push(\"--ignore-case\");\n\t\tif (options.literal) args.push(\"--fixed-strings\");\n\t\tif (options.glob) args.push(\"--glob\", options.glob);\n\t\targs.push(\"--\", options.pattern, searchPath);\n\t\tconst output = await runCommand(\"rg\", args, this.environment, this.maxBufferedOutputBytes);\n\t\tconst matches: ToolGrepMatch[] = [];\n\t\tfor (const line of output.toString(\"utf8\").split(\"\\n\")) {\n\t\t\tif (matches.length >= options.limit) continue;\n\t\t\tconst match = parseDaemonGrepMatch(line);\n\t\t\tif (!match) continue;\n\t\t\ttry {\n\t\t\t\tawait this.existingPath(match.filePath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmatches.push(match);\n\t\t}\n\t\treturn { isDirectory, matches };\n\t}\n\n\tasync detectImageMimeType(path: string): Promise<string | null | undefined> {\n\t\treturn this.local.detectImageMimeType(await this.existingPath(path));\n\t}\n\n\tgetBackendInfo(): ToolBackendInfo {\n\t\treturn { type: \"local\", cwd: this.cwd };\n\t}\n}\n\nexport interface DaemonWorkspaceRuntime {\n\treadonly operations: ConfinedDaemonToolOperations;\n\treadonly host: WorkspaceToolHost;\n\treadonly lspRuntime?: LspRuntimeState;\n\treadonly catalog: RemoteWorkspaceCatalog;\n\treadonly capabilities: readonly RemoteWorkspaceCapability[];\n\tcreateHandler(workspace: RemoteWorkspaceIdentity, sharedMode?: boolean): RemoteWorkspaceServerHandler;\n\tretire(): Promise<void>;\n\tdispose(): Promise<void>;\n}\n\ntype DaemonRequestInterruptionCode = \"cancelled\" | \"deadline_exceeded\";\ntype DaemonInterruptedExecutionState = \"not_started\" | \"indeterminate\";\n\nfunction requestError(code: DaemonRequestInterruptionCode, message: string, state: DaemonInterruptedExecutionState) {\n\treturn new RemoteWorkspaceRequestError({ code, message, executionState: state, retryable: false });\n}\ninterface DaemonRequestRuntime {\n\tconfiguration: DaemonConfiguration;\n\toperations: ConfinedDaemonToolOperations;\n\thost: WorkspaceToolHost;\n\tlspRuntime: LspRuntimeState | undefined;\n\tworkspace: RemoteWorkspaceIdentity;\n\tsharedMode: boolean;\n}\n\nfunction withDaemonWorkspace<T extends Record<string, unknown>>(result: T, workspace: RemoteWorkspaceIdentity) {\n\treturn { ...result, workspace };\n}\n\nasync function synchronizeDaemonToolFile(\n\ttoolName: string,\n\tinvocationArguments: unknown,\n\truntime: DaemonRequestRuntime,\n): Promise<void> {\n\tif (!runtime.lspRuntime) return;\n\tconst args = invocationArguments as { path?: unknown };\n\tif (typeof args.path !== \"string\") return;\n\ttry {\n\t\tif (toolName === \"read\") {\n\t\t\tawait runtime.lspRuntime.fileSync.handleFileRead(args.path, runtime.operations);\n\t\t} else if (toolName === \"write\" || toolName === \"edit\") {\n\t\t\tawait runtime.lspRuntime.fileSync.handleFileWrite(args.path, runtime.operations);\n\t\t}\n\t} catch {\n\t\t// Synchronization remains best-effort, matching local AgentSession behavior.\n\t}\n}\n\nfunction marksToolSideEffect(kind: RemoteWorkspaceOperationKind, toolName: string, sharedMode: boolean): boolean {\n\treturn kind !== \"read\" && !(sharedMode && (toolName === \"edit\" || toolName === \"write\"));\n}\n\nasync function invokeDaemonTool(\n\trequest: RemoteWorkspaceTypedRequest,\n\tparams: Record<string, unknown>,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<AgentToolResult<unknown>> {\n\tconst toolName = params.toolName as string;\n\tconst kind = operationKind(toolName);\n\tif (marksToolSideEffect(kind, toolName, runtime.sharedMode)) context.markSideEffectStarted();\n\tlet updateQueue = Promise.resolve();\n\ttry {\n\t\tconst result = await runtime.host.executePrepared(toolName, {\n\t\t\ttoolCallId: request.id,\n\t\t\targuments: params.arguments,\n\t\t\tsignal: context.signal,\n\t\t\texecutionOptions: params.executionOptions as WorkspaceToolExecutionOptions,\n\t\t\tonUpdate: (update) => {\n\t\t\t\tupdateQueue = updateQueue.then(() => context.sendUpdate(portableToolResult(update)));\n\t\t\t},\n\t\t});\n\t\tawait updateQueue;\n\t\tawait synchronizeDaemonToolFile(toolName, params.arguments, runtime);\n\t\tif (kind !== \"read\") context.markCommitted();\n\t\treturn portableToolResult(result);\n\t} catch (error) {\n\t\tawait updateQueue.catch(() => undefined);\n\t\tif (context.signal.aborted) {\n\t\t\tthrow requestError(\n\t\t\t\t\"cancelled\",\n\t\t\t\t\"Remote workspace tool invocation was cancelled\",\n\t\t\t\tkind === \"read\" ? \"not_started\" : \"indeterminate\",\n\t\t\t);\n\t\t}\n\t\tif (error instanceof RemoteWorkspaceRequestError) throw error;\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"internal_error\",\n\t\t\tmessage: error instanceof Error ? error.message.slice(0, 4096) : \"Workspace tool failed\",\n\t\t\texecutionState: kind === \"read\" ? \"not_started\" : \"indeterminate\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n}\n\nasync function executeDaemonWorkspaceProcess(\n\tparams: Record<string, unknown>,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<ToolExecResult> {\n\tcontext.markSideEffectStarted();\n\tlet updateQueue = Promise.resolve();\n\tlet pendingOutputBytes = 0;\n\tlet outputLimitExceeded = false;\n\tconst outputController = new AbortController();\n\tconst signal = AbortSignal.any([context.signal, outputController.signal]);\n\tlet result: ToolExecResult;\n\ttry {\n\t\tresult = await runtime.operations.exec(params.command as string, {\n\t\t\tcwd: params.cwd as string,\n\t\t\tsignal,\n\t\t\tonData: (data) => {\n\t\t\t\tif (outputLimitExceeded) return;\n\t\t\t\tconst chunk = Buffer.from(data);\n\t\t\t\tpendingOutputBytes += chunk.byteLength;\n\t\t\t\tif (pendingOutputBytes > runtime.configuration.maxBufferedOutputBytes) {\n\t\t\t\t\toutputLimitExceeded = true;\n\t\t\t\t\toutputController.abort();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateQueue = updateQueue\n\t\t\t\t\t.then(() => context.sendUpdate({ dataBase64: chunk.toString(\"base64\") }))\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tpendingOutputBytes -= chunk.byteLength;\n\t\t\t\t\t});\n\t\t\t\t// The process may run after an update fails; observe rejection until the final await.\n\t\t\t\tvoid updateQueue.catch(() => undefined);\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tif (outputLimitExceeded) throw new Error(\"Process output exceeded the daemon buffered-output limit\");\n\t\tthrow error;\n\t}\n\tawait updateQueue;\n\tcontext.markCommitted();\n\treturn result;\n}\n\nasync function readDaemonResource(\n\tparams: Record<string, unknown>,\n\truntime: DaemonRequestRuntime,\n): Promise<Record<string, unknown>> {\n\tconst path = params.path as string;\n\tconst resourcePath =\n\t\tpath === \"SANDBOX.md\"\n\t\t\t? runtime.configuration.sandboxInstructionsPath\n\t\t\t: path === \"AGENTS.md\"\n\t\t\t\t? runtime.configuration.userAgentsPath\n\t\t\t\t: undefined;\n\tif (!resourcePath) {\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"not_available\",\n\t\t\tmessage: \"Requested daemon resource is not available\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n\treturn withDaemonWorkspace({ contentBase64: (await readFile(resourcePath)).toString(\"base64\") }, runtime.workspace);\n}\n\nfunction getDaemonLspStatus(runtime: DaemonRequestRuntime): Record<string, unknown> {\n\tif (!runtime.lspRuntime) {\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"not_available\",\n\t\t\tmessage: \"Daemon LSP is not configured\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n\treturn {\n\t\tenabled: true,\n\t\tservers: runtime.lspRuntime.manager.getStatus().map((status) => sanitizeLspStatus(status, runtime.configuration)),\n\t};\n}\nasync function statDaemonWorkspace(path: string, runtime: DaemonRequestRuntime): Promise<unknown> {\n\ttry {\n\t\tconst value = await runtime.operations.stat(path);\n\t\treturn withDaemonWorkspace(\n\t\t\t{ kind: value.isDirectory() ? \"directory\" : value.isFile() ? \"file\" : \"other\" },\n\t\t\truntime.workspace,\n\t\t);\n\t} catch (error) {\n\t\tif (!runtime.sharedMode || !isMissingPath(error)) throw error;\n\t\treturn withDaemonWorkspace({ kind: \"absent\" }, runtime.workspace);\n\t}\n}\n\nasync function dispatchDaemonWorkspaceRequest(\n\trequest: RemoteWorkspaceTypedRequest,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<unknown> {\n\tconst params = request.params as Record<string, unknown>;\n\tswitch (request.method) {\n\t\tcase \"tool.invoke\":\n\t\t\treturn invokeDaemonTool(request, params, context, runtime);\n\t\tcase \"workspace.access\":\n\t\t\tawait runtime.operations.access(params.path as string, params.mode as ToolAccessMode | undefined);\n\t\t\treturn {};\n\t\tcase \"workspace.read\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ contentBase64: (await runtime.operations.readFile(params.path as string)).toString(\"base64\") },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.write\":\n\t\t\tif (!runtime.sharedMode) context.markSideEffectStarted();\n\t\t\tawait withFileMutationQueue(resolve(runtime.configuration.workspaceRoot, params.path as string), () =>\n\t\t\t\truntime.operations.writeFile(params.path as string, Buffer.from(params.contentBase64 as string, \"base64\")),\n\t\t\t);\n\t\t\tcontext.markCommitted();\n\t\t\treturn {};\n\t\tcase \"workspace.mkdir\":\n\t\t\tif (!runtime.sharedMode) context.markSideEffectStarted();\n\t\t\tawait withFileMutationQueue(resolve(runtime.configuration.workspaceRoot, params.path as string), () => {\n\t\t\t\tif (runtime.sharedMode) {\n\t\t\t\t\tif (context.signal.aborted)\n\t\t\t\t\t\tthrow requestError(\n\t\t\t\t\t\t\t\"cancelled\",\n\t\t\t\t\t\t\t\"Shared directory creation was cancelled before starting\",\n\t\t\t\t\t\t\t\"not_started\",\n\t\t\t\t\t\t);\n\t\t\t\t\tcontext.markSideEffectStarted();\n\t\t\t\t}\n\t\t\t\treturn runtime.operations.mkdir(params.path as string, { recursive: params.recursive === true });\n\t\t\t});\n\t\t\tcontext.markCommitted();\n\t\t\treturn {};\n\t\tcase \"workspace.stat\":\n\t\t\treturn statDaemonWorkspace(params.path as string, runtime);\n\t\tcase \"workspace.readdir\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ entries: await runtime.operations.readdir(params.path as string) },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.glob\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{\n\t\t\t\t\tmatches: await runtime.operations.glob(params.pattern as string, params.cwd as string, {\n\t\t\t\t\t\tignore: params.ignore as string[],\n\t\t\t\t\t\tlimit: params.limit as number,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.grep\": {\n\t\t\tconst result = await runtime.operations.grep(params as unknown as ToolGrepOptions);\n\t\t\treturn withDaemonWorkspace(result as unknown as Record<string, unknown>, runtime.workspace);\n\t\t}\n\t\tcase \"workspace.detect_image_mime\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ mimeType: (await runtime.operations.detectImageMimeType(params.path as string)) ?? null },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.exec\":\n\t\t\treturn executeDaemonWorkspaceProcess(params, context, runtime);\n\t\tcase \"resource.read\":\n\t\t\treturn readDaemonResource(params, runtime);\n\t\tcase \"lsp.status\":\n\t\t\treturn getDaemonLspStatus(runtime);\n\t\tdefault:\n\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\tcode: \"method_not_supported\",\n\t\t\t\tmessage: `Workspace operation is not implemented: ${request.method}`,\n\t\t\t\texecutionState: \"not_started\",\n\t\t\t\tretryable: false,\n\t\t\t});\n\t}\n}\n\nexport function createDaemonWorkspaceRuntime(configuration: DaemonConfiguration): DaemonWorkspaceRuntime {\n\tconst operations = new ConfinedDaemonToolOperations(configuration);\n\tconst toolNames: WorkspaceToolName[] = [\"read\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"];\n\tif (configuration.allowProcessExec) toolNames.splice(1, 0, \"bash\");\n\tconst lspConfiguration = loadDaemonLspConfiguration(configuration);\n\tconst lspRuntime = lspConfiguration.enabled\n\t\t? createLspRuntimeState(configuration.workspaceRoot, {\n\t\t\t\tconfiguration: lspConfiguration,\n\t\t\t\tgetToolBackendInfo: () => operations.getBackendInfo(),\n\t\t\t\tgetToolOperations: () => operations,\n\t\t\t\tresolveConnectionFactory: (transport) =>\n\t\t\t\t\ttransport.type === \"spawn\"\n\t\t\t\t\t\t? createManagedStdioConnectionFactory({\n\t\t\t\t\t\t\t\t...transport,\n\t\t\t\t\t\t\t\tenv: operations.createChildEnvironment(transport.env),\n\t\t\t\t\t\t\t\tinheritEnvironment: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: resolveLspConnectionFactory(transport),\n\t\t\t})\n\t\t: undefined;\n\tconst host = new WorkspaceToolHost({\n\t\tcwd: configuration.workspaceRoot,\n\t\toperations,\n\t\ttoolNames,\n\t\tadditionalDefinitions: lspRuntime\n\t\t\t? createLspToolDefinitions(\n\t\t\t\t\t() => lspRuntime,\n\t\t\t\t\t() => operations,\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tdisposeTimeoutMs: Math.min(configuration.shutdownTimeoutMs, 60_000),\n\t});\n\tconst catalog: RemoteWorkspaceCatalog = {\n\t\tgeneration: 1,\n\t\ttools: host.getCatalog().map((entry) => ({\n\t\t\tname: entry.name,\n\t\t\texecutionMode: operationKind(entry.name),\n\t\t\tparameterSchema: structuredClone(entry.parameters) as Record<string, unknown>,\n\t\t\tschemaHash: hashRemoteWorkspaceJson(entry.parameters),\n\t\t\tfeatureFlags: [],\n\t\t})),\n\t\toperations: [\n\t\t\t...PRIMITIVE_OPERATIONS.filter((method) => method !== \"workspace.exec\" || configuration.allowProcessExec),\n\t\t\t...(configuration.sandboxInstructionsPath || configuration.userAgentsPath ? ([\"resource.read\"] as const) : []),\n\t\t\t...(lspRuntime ? ([\"lsp.status\"] as const) : []),\n\t\t],\n\t};\n\tconst capabilities: RemoteWorkspaceCapability[] = [\n\t\t\"catalog_refresh\",\n\t\t\"primitive_operations\",\n\t\t\"tool_updates\",\n\t\t...(lspRuntime ? ([\"lsp_status\"] as const) : []),\n\t];\n\tlet activeRequests = 0;\n\n\treturn {\n\t\toperations,\n\t\thost,\n\t\tlspRuntime,\n\t\tcatalog,\n\t\tcapabilities,\n\t\tcreateHandler(workspace, sharedMode = false) {\n\t\t\tconst requestRuntime: DaemonRequestRuntime = {\n\t\t\t\tconfiguration,\n\t\t\t\toperations,\n\t\t\t\thost,\n\t\t\t\tlspRuntime,\n\t\t\t\tworkspace,\n\t\t\t\tsharedMode,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tvalidateToolArguments: (toolName, value) => host.validatePreparedArguments(toolName, value),\n\t\t\t\tasync handleRequest(request, context) {\n\t\t\t\t\tif (activeRequests >= configuration.maxGlobalRequests) {\n\t\t\t\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\t\t\tmessage: \"Daemon global active request limit reached\",\n\t\t\t\t\t\t\texecutionState: \"not_started\",\n\t\t\t\t\t\t\tretryable: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tactiveRequests++;\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await dispatchDaemonWorkspaceRequest(request, context, requestRuntime);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tactiveRequests--;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tretire: async () => {\n\t\t\tawait host.waitForIdle(configuration.shutdownTimeoutMs);\n\t\t\tawait lspRuntime?.manager.shutdownAll();\n\t\t\tawait host.dispose();\n\t\t},\n\t\tdispose: async () => {\n\t\t\tawait Promise.all([lspRuntime?.manager.shutdownAll(), host.dispose()]);\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workspace-runtime.d.ts","sourceRoot":"","sources":["../../src/daemon/workspace-runtime.ts"],"names":[],"mappings":"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"}
|