@quenty/studio-bridge 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -42
- package/README.md +166 -115
- package/dist/src/bridge/bridge-connection-remote.test.d.ts +7 -0
- package/dist/src/bridge/bridge-connection-remote.test.d.ts.map +1 -0
- package/dist/src/bridge/bridge-connection-remote.test.js +144 -0
- package/dist/src/bridge/bridge-connection-remote.test.js.map +1 -0
- package/dist/src/bridge/bridge-connection.d.ts +112 -0
- package/dist/src/bridge/bridge-connection.d.ts.map +1 -0
- package/dist/src/bridge/bridge-connection.js +528 -0
- package/dist/src/bridge/bridge-connection.js.map +1 -0
- package/dist/src/bridge/bridge-connection.test.d.ts +6 -0
- package/dist/src/bridge/bridge-connection.test.d.ts.map +1 -0
- package/dist/src/bridge/bridge-connection.test.js +773 -0
- package/dist/src/bridge/bridge-connection.test.js.map +1 -0
- package/dist/src/bridge/bridge-session.d.ts +38 -0
- package/dist/src/bridge/bridge-session.d.ts.map +1 -0
- package/dist/src/bridge/bridge-session.js +259 -0
- package/dist/src/bridge/bridge-session.js.map +1 -0
- package/dist/src/bridge/bridge-session.test.d.ts +6 -0
- package/dist/src/bridge/bridge-session.test.d.ts.map +1 -0
- package/dist/src/bridge/bridge-session.test.js +264 -0
- package/dist/src/bridge/bridge-session.test.js.map +1 -0
- package/dist/src/bridge/index.d.ts +13 -0
- package/dist/src/bridge/index.d.ts.map +1 -0
- package/dist/src/bridge/index.js +13 -0
- package/dist/src/bridge/index.js.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-crash.test.d.ts +9 -0
- package/dist/src/bridge/internal/__tests__/failover-crash.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-crash.test.js +159 -0
- package/dist/src/bridge/internal/__tests__/failover-crash.test.js.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-graceful.test.d.ts +9 -0
- package/dist/src/bridge/internal/__tests__/failover-graceful.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-graceful.test.js +218 -0
- package/dist/src/bridge/internal/__tests__/failover-graceful.test.js.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-inflight.test.d.ts +9 -0
- package/dist/src/bridge/internal/__tests__/failover-inflight.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/__tests__/failover-inflight.test.js +246 -0
- package/dist/src/bridge/internal/__tests__/failover-inflight.test.js.map +1 -0
- package/dist/src/bridge/internal/__tests__/host-client-integration.test.d.ts +10 -0
- package/dist/src/bridge/internal/__tests__/host-client-integration.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/__tests__/host-client-integration.test.js +298 -0
- package/dist/src/bridge/internal/__tests__/host-client-integration.test.js.map +1 -0
- package/dist/src/bridge/internal/bridge-client.d.ts +70 -0
- package/dist/src/bridge/internal/bridge-client.d.ts.map +1 -0
- package/dist/src/bridge/internal/bridge-client.js +344 -0
- package/dist/src/bridge/internal/bridge-client.js.map +1 -0
- package/dist/src/bridge/internal/bridge-client.test.d.ts +7 -0
- package/dist/src/bridge/internal/bridge-client.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/bridge-client.test.js +301 -0
- package/dist/src/bridge/internal/bridge-client.test.js.map +1 -0
- package/dist/src/bridge/internal/bridge-host.d.ts +78 -0
- package/dist/src/bridge/internal/bridge-host.d.ts.map +1 -0
- package/dist/src/bridge/internal/bridge-host.js +383 -0
- package/dist/src/bridge/internal/bridge-host.js.map +1 -0
- package/dist/src/bridge/internal/bridge-host.test.d.ts +7 -0
- package/dist/src/bridge/internal/bridge-host.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/bridge-host.test.js +377 -0
- package/dist/src/bridge/internal/bridge-host.test.js.map +1 -0
- package/dist/src/bridge/internal/environment-detection.d.ts +44 -0
- package/dist/src/bridge/internal/environment-detection.d.ts.map +1 -0
- package/dist/src/bridge/internal/environment-detection.js +91 -0
- package/dist/src/bridge/internal/environment-detection.js.map +1 -0
- package/dist/src/bridge/internal/environment-detection.test.d.ts +7 -0
- package/dist/src/bridge/internal/environment-detection.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/environment-detection.test.js +150 -0
- package/dist/src/bridge/internal/environment-detection.test.js.map +1 -0
- package/dist/src/bridge/internal/hand-off.d.ts +69 -0
- package/dist/src/bridge/internal/hand-off.d.ts.map +1 -0
- package/dist/src/bridge/internal/hand-off.js +178 -0
- package/dist/src/bridge/internal/hand-off.js.map +1 -0
- package/dist/src/bridge/internal/hand-off.test.d.ts +7 -0
- package/dist/src/bridge/internal/hand-off.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/hand-off.test.js +325 -0
- package/dist/src/bridge/internal/hand-off.test.js.map +1 -0
- package/dist/src/bridge/internal/health-endpoint.d.ts +32 -0
- package/dist/src/bridge/internal/health-endpoint.d.ts.map +1 -0
- package/dist/src/bridge/internal/health-endpoint.js +73 -0
- package/dist/src/bridge/internal/health-endpoint.js.map +1 -0
- package/dist/src/bridge/internal/health-endpoint.test.d.ts +6 -0
- package/dist/src/bridge/internal/health-endpoint.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/health-endpoint.test.js +122 -0
- package/dist/src/bridge/internal/health-endpoint.test.js.map +1 -0
- package/dist/src/bridge/internal/host-protocol.d.ts +60 -0
- package/dist/src/bridge/internal/host-protocol.d.ts.map +1 -0
- package/dist/src/bridge/internal/host-protocol.js +184 -0
- package/dist/src/bridge/internal/host-protocol.js.map +1 -0
- package/dist/src/bridge/internal/host-protocol.test.d.ts +6 -0
- package/dist/src/bridge/internal/host-protocol.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/host-protocol.test.js +307 -0
- package/dist/src/bridge/internal/host-protocol.test.js.map +1 -0
- package/dist/src/bridge/internal/session-tracker.d.ts +67 -0
- package/dist/src/bridge/internal/session-tracker.d.ts.map +1 -0
- package/dist/src/bridge/internal/session-tracker.js +138 -0
- package/dist/src/bridge/internal/session-tracker.js.map +1 -0
- package/dist/src/bridge/internal/session-tracker.test.d.ts +6 -0
- package/dist/src/bridge/internal/session-tracker.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/session-tracker.test.js +342 -0
- package/dist/src/bridge/internal/session-tracker.test.js.map +1 -0
- package/dist/src/bridge/internal/transport-client.d.ts +43 -0
- package/dist/src/bridge/internal/transport-client.d.ts.map +1 -0
- package/dist/src/bridge/internal/transport-client.js +146 -0
- package/dist/src/bridge/internal/transport-client.js.map +1 -0
- package/dist/src/bridge/internal/transport-client.test.d.ts +6 -0
- package/dist/src/bridge/internal/transport-client.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/transport-client.test.js +176 -0
- package/dist/src/bridge/internal/transport-client.test.js.map +1 -0
- package/dist/src/bridge/internal/transport-server.d.ts +59 -0
- package/dist/src/bridge/internal/transport-server.d.ts.map +1 -0
- package/dist/src/bridge/internal/transport-server.js +189 -0
- package/dist/src/bridge/internal/transport-server.js.map +1 -0
- package/dist/src/bridge/internal/transport-server.test.d.ts +6 -0
- package/dist/src/bridge/internal/transport-server.test.d.ts.map +1 -0
- package/dist/src/bridge/internal/transport-server.test.js +171 -0
- package/dist/src/bridge/internal/transport-server.test.js.map +1 -0
- package/dist/src/bridge/types.d.ts +117 -0
- package/dist/src/bridge/types.d.ts.map +1 -0
- package/dist/src/bridge/types.js +68 -0
- package/dist/src/bridge/types.js.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.d.ts +6 -0
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.js +260 -0
- package/dist/src/cli/adapters/cli-command-adapter-handler.test.js.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter.d.ts +39 -0
- package/dist/src/cli/adapters/cli-command-adapter.d.ts.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter.js +241 -0
- package/dist/src/cli/adapters/cli-command-adapter.js.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter.test.d.ts +5 -0
- package/dist/src/cli/adapters/cli-command-adapter.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/cli-command-adapter.test.js +188 -0
- package/dist/src/cli/adapters/cli-command-adapter.test.js.map +1 -0
- package/dist/src/cli/adapters/group-builder.d.ts +29 -0
- package/dist/src/cli/adapters/group-builder.d.ts.map +1 -0
- package/dist/src/cli/adapters/group-builder.js +54 -0
- package/dist/src/cli/adapters/group-builder.js.map +1 -0
- package/dist/src/cli/adapters/group-builder.test.d.ts +5 -0
- package/dist/src/cli/adapters/group-builder.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/group-builder.test.js +108 -0
- package/dist/src/cli/adapters/group-builder.test.js.map +1 -0
- package/dist/src/cli/adapters/help-formatter.d.ts +11 -0
- package/dist/src/cli/adapters/help-formatter.d.ts.map +1 -0
- package/dist/src/cli/adapters/help-formatter.js +78 -0
- package/dist/src/cli/adapters/help-formatter.js.map +1 -0
- package/dist/src/cli/adapters/help-formatter.test.d.ts +5 -0
- package/dist/src/cli/adapters/help-formatter.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/help-formatter.test.js +79 -0
- package/dist/src/cli/adapters/help-formatter.test.js.map +1 -0
- package/dist/src/cli/adapters/target-resolver.d.ts +54 -0
- package/dist/src/cli/adapters/target-resolver.d.ts.map +1 -0
- package/dist/src/cli/adapters/target-resolver.js +90 -0
- package/dist/src/cli/adapters/target-resolver.js.map +1 -0
- package/dist/src/cli/adapters/target-resolver.test.d.ts +5 -0
- package/dist/src/cli/adapters/target-resolver.test.d.ts.map +1 -0
- package/dist/src/cli/adapters/target-resolver.test.js +169 -0
- package/dist/src/cli/adapters/target-resolver.test.js.map +1 -0
- package/dist/src/cli/args/global-args.d.ts +2 -0
- package/dist/src/cli/args/global-args.d.ts.map +1 -1
- package/dist/src/cli/cli.d.ts +6 -3
- package/dist/src/cli/cli.d.ts.map +1 -1
- package/dist/src/cli/cli.js +82 -20
- package/dist/src/cli/cli.js.map +1 -1
- package/dist/src/cli/resolve-script-content.d.ts +19 -0
- package/dist/src/cli/resolve-script-content.d.ts.map +1 -0
- package/dist/src/cli/resolve-script-content.js +22 -0
- package/dist/src/cli/resolve-script-content.js.map +1 -0
- package/dist/src/cli/resolve-session.d.ts +21 -0
- package/dist/src/cli/resolve-session.d.ts.map +1 -0
- package/dist/src/cli/resolve-session.js +40 -0
- package/dist/src/cli/resolve-session.js.map +1 -0
- package/dist/src/cli/resolve-session.test.d.ts +5 -0
- package/dist/src/cli/resolve-session.test.d.ts.map +1 -0
- package/dist/src/cli/resolve-session.test.js +112 -0
- package/dist/src/cli/resolve-session.test.js.map +1 -0
- package/dist/src/cli/script-executor.d.ts +1 -0
- package/dist/src/cli/script-executor.d.ts.map +1 -1
- package/dist/src/cli/script-executor.js +7 -1
- package/dist/src/cli/script-executor.js.map +1 -1
- package/dist/src/cli/types.d.ts +11 -0
- package/dist/src/cli/types.d.ts.map +1 -0
- package/dist/src/cli/types.js +5 -0
- package/dist/src/cli/types.js.map +1 -0
- package/dist/src/commands/connect.d.ts +16 -0
- package/dist/src/commands/connect.d.ts.map +1 -0
- package/dist/src/commands/connect.js +15 -0
- package/dist/src/commands/connect.js.map +1 -0
- package/dist/src/commands/connect.test.d.ts +5 -0
- package/dist/src/commands/connect.test.d.ts.map +1 -0
- package/dist/src/commands/connect.test.js +46 -0
- package/dist/src/commands/connect.test.js.map +1 -0
- package/dist/src/commands/console/exec/exec.d.ts +43 -0
- package/dist/src/commands/console/exec/exec.d.ts.map +1 -0
- package/dist/src/commands/console/exec/exec.js +79 -0
- package/dist/src/commands/console/exec/exec.js.map +1 -0
- package/dist/src/commands/console/exec/exec.test.d.ts +5 -0
- package/dist/src/commands/console/exec/exec.test.d.ts.map +1 -0
- package/dist/src/commands/console/exec/exec.test.js +191 -0
- package/dist/src/commands/console/exec/exec.test.js.map +1 -0
- package/dist/src/commands/console/logs/logs.d.ts +23 -0
- package/dist/src/commands/console/logs/logs.d.ts.map +1 -0
- package/dist/src/commands/console/logs/logs.js +80 -0
- package/dist/src/commands/console/logs/logs.js.map +1 -0
- package/dist/src/commands/console/logs/logs.test.d.ts +5 -0
- package/dist/src/commands/console/logs/logs.test.d.ts.map +1 -0
- package/dist/src/commands/console/logs/logs.test.js +111 -0
- package/dist/src/commands/console/logs/logs.test.js.map +1 -0
- package/dist/src/commands/disconnect.d.ts +9 -0
- package/dist/src/commands/disconnect.d.ts.map +1 -0
- package/dist/src/commands/disconnect.js +8 -0
- package/dist/src/commands/disconnect.js.map +1 -0
- package/dist/src/commands/disconnect.test.d.ts +5 -0
- package/dist/src/commands/disconnect.test.d.ts.map +1 -0
- package/dist/src/commands/disconnect.test.js +17 -0
- package/dist/src/commands/disconnect.test.js.map +1 -0
- package/dist/src/commands/explorer/query/query.d.ts +31 -0
- package/dist/src/commands/explorer/query/query.d.ts.map +1 -0
- package/dist/src/commands/explorer/query/query.js +106 -0
- package/dist/src/commands/explorer/query/query.js.map +1 -0
- package/dist/src/commands/explorer/query/query.test.d.ts +5 -0
- package/dist/src/commands/explorer/query/query.test.d.ts.map +1 -0
- package/dist/src/commands/explorer/query/query.test.js +228 -0
- package/dist/src/commands/explorer/query/query.test.js.map +1 -0
- package/dist/src/commands/formatters.test.d.ts +6 -0
- package/dist/src/commands/formatters.test.d.ts.map +1 -0
- package/dist/src/commands/formatters.test.js +211 -0
- package/dist/src/commands/formatters.test.js.map +1 -0
- package/dist/src/commands/framework/action-loader.d.ts +25 -0
- package/dist/src/commands/framework/action-loader.d.ts.map +1 -0
- package/dist/src/commands/framework/action-loader.js +46 -0
- package/dist/src/commands/framework/action-loader.js.map +1 -0
- package/dist/src/commands/framework/action-loader.test.d.ts +5 -0
- package/dist/src/commands/framework/action-loader.test.d.ts.map +1 -0
- package/dist/src/commands/framework/action-loader.test.js +89 -0
- package/dist/src/commands/framework/action-loader.test.js.map +1 -0
- package/dist/src/commands/framework/arg-builder.d.ts +92 -0
- package/dist/src/commands/framework/arg-builder.d.ts.map +1 -0
- package/dist/src/commands/framework/arg-builder.js +137 -0
- package/dist/src/commands/framework/arg-builder.js.map +1 -0
- package/dist/src/commands/framework/arg-builder.test.d.ts +5 -0
- package/dist/src/commands/framework/arg-builder.test.d.ts.map +1 -0
- package/dist/src/commands/framework/arg-builder.test.js +246 -0
- package/dist/src/commands/framework/arg-builder.test.js.map +1 -0
- package/dist/src/commands/framework/command-registry.d.ts +23 -0
- package/dist/src/commands/framework/command-registry.d.ts.map +1 -0
- package/dist/src/commands/framework/command-registry.js +42 -0
- package/dist/src/commands/framework/command-registry.js.map +1 -0
- package/dist/src/commands/framework/command-registry.test.d.ts +5 -0
- package/dist/src/commands/framework/command-registry.test.d.ts.map +1 -0
- package/dist/src/commands/framework/command-registry.test.js +158 -0
- package/dist/src/commands/framework/command-registry.test.js.map +1 -0
- package/dist/src/commands/framework/define-command.d.ts +76 -0
- package/dist/src/commands/framework/define-command.d.ts.map +1 -0
- package/dist/src/commands/framework/define-command.js +28 -0
- package/dist/src/commands/framework/define-command.js.map +1 -0
- package/dist/src/commands/framework/define-command.test.d.ts +5 -0
- package/dist/src/commands/framework/define-command.test.d.ts.map +1 -0
- package/dist/src/commands/framework/define-command.test.js +135 -0
- package/dist/src/commands/framework/define-command.test.js.map +1 -0
- package/dist/src/commands/framework/index.d.ts +8 -0
- package/dist/src/commands/framework/index.d.ts.map +1 -0
- package/dist/src/commands/framework/index.js +8 -0
- package/dist/src/commands/framework/index.js.map +1 -0
- package/dist/src/commands/index.d.ts +20 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +20 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts +15 -0
- package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts.map +1 -0
- package/dist/src/commands/linux/inject-credentials/inject-credentials.js +88 -0
- package/dist/src/commands/linux/inject-credentials/inject-credentials.js.map +1 -0
- package/dist/src/commands/linux/setup/setup.d.ts +19 -0
- package/dist/src/commands/linux/setup/setup.d.ts.map +1 -0
- package/dist/src/commands/linux/setup/setup.js +107 -0
- package/dist/src/commands/linux/setup/setup.js.map +1 -0
- package/dist/src/commands/linux/status/status.d.ts +34 -0
- package/dist/src/commands/linux/status/status.d.ts.map +1 -0
- package/dist/src/commands/linux/status/status.js +134 -0
- package/dist/src/commands/linux/status/status.js.map +1 -0
- package/dist/src/commands/plugin/install/install.d.ts +10 -0
- package/dist/src/commands/plugin/install/install.d.ts.map +1 -0
- package/dist/src/commands/plugin/install/install.js +23 -0
- package/dist/src/commands/plugin/install/install.js.map +1 -0
- package/dist/src/commands/plugin/uninstall/uninstall.d.ts +9 -0
- package/dist/src/commands/plugin/uninstall/uninstall.d.ts.map +1 -0
- package/dist/src/commands/plugin/uninstall/uninstall.js +41 -0
- package/dist/src/commands/plugin/uninstall/uninstall.js.map +1 -0
- package/dist/src/commands/process/close/close.d.ts +22 -0
- package/dist/src/commands/process/close/close.d.ts.map +1 -0
- package/dist/src/commands/process/close/close.js +34 -0
- package/dist/src/commands/process/close/close.js.map +1 -0
- package/dist/src/commands/process/format-state.d.ts +7 -0
- package/dist/src/commands/process/format-state.d.ts.map +1 -0
- package/dist/src/commands/process/format-state.js +19 -0
- package/dist/src/commands/process/format-state.js.map +1 -0
- package/dist/src/commands/process/info/info.d.ts +17 -0
- package/dist/src/commands/process/info/info.d.ts.map +1 -0
- package/dist/src/commands/process/info/info.js +38 -0
- package/dist/src/commands/process/info/info.js.map +1 -0
- package/dist/src/commands/process/info/info.test.d.ts +5 -0
- package/dist/src/commands/process/info/info.test.d.ts.map +1 -0
- package/dist/src/commands/process/info/info.test.js +58 -0
- package/dist/src/commands/process/info/info.test.js.map +1 -0
- package/dist/src/commands/process/launch/launch.d.ts +17 -0
- package/dist/src/commands/process/launch/launch.d.ts.map +1 -0
- package/dist/src/commands/process/launch/launch.js +26 -0
- package/dist/src/commands/process/launch/launch.js.map +1 -0
- package/dist/src/commands/process/launch/launch.test.d.ts +5 -0
- package/dist/src/commands/process/launch/launch.test.d.ts.map +1 -0
- package/dist/src/commands/process/launch/launch.test.js +49 -0
- package/dist/src/commands/process/launch/launch.test.js.map +1 -0
- package/dist/src/commands/process/list/list.d.ts +16 -0
- package/dist/src/commands/process/list/list.d.ts.map +1 -0
- package/dist/src/commands/process/list/list.js +56 -0
- package/dist/src/commands/process/list/list.js.map +1 -0
- package/dist/src/commands/process/list/list.test.d.ts +5 -0
- package/dist/src/commands/process/list/list.test.d.ts.map +1 -0
- package/dist/src/commands/process/list/list.test.js +71 -0
- package/dist/src/commands/process/list/list.test.js.map +1 -0
- package/dist/src/commands/process/run/run.d.ts +31 -0
- package/dist/src/commands/process/run/run.d.ts.map +1 -0
- package/dist/src/commands/process/run/run.js +63 -0
- package/dist/src/commands/process/run/run.js.map +1 -0
- package/dist/src/commands/rgba-to-png.d.ts +17 -0
- package/dist/src/commands/rgba-to-png.d.ts.map +1 -0
- package/dist/src/commands/rgba-to-png.js +85 -0
- package/dist/src/commands/rgba-to-png.js.map +1 -0
- package/dist/src/commands/serve/serve.d.ts +17 -0
- package/dist/src/commands/serve/serve.d.ts.map +1 -0
- package/dist/src/commands/serve/serve.js +128 -0
- package/dist/src/commands/serve/serve.js.map +1 -0
- package/dist/src/commands/serve/serve.test.d.ts +5 -0
- package/dist/src/commands/serve/serve.test.d.ts.map +1 -0
- package/dist/src/commands/serve/serve.test.js +100 -0
- package/dist/src/commands/serve/serve.test.js.map +1 -0
- package/dist/src/commands/viewport/screenshot/screenshot.d.ts +17 -0
- package/dist/src/commands/viewport/screenshot/screenshot.d.ts.map +1 -0
- package/dist/src/commands/viewport/screenshot/screenshot.js +45 -0
- package/dist/src/commands/viewport/screenshot/screenshot.js.map +1 -0
- package/dist/src/commands/viewport/screenshot/screenshot.test.d.ts +5 -0
- package/dist/src/commands/viewport/screenshot/screenshot.test.d.ts.map +1 -0
- package/dist/src/commands/viewport/screenshot/screenshot.test.js +143 -0
- package/dist/src/commands/viewport/screenshot/screenshot.test.js.map +1 -0
- package/dist/src/docker/docker-delegator.d.ts +30 -0
- package/dist/src/docker/docker-delegator.d.ts.map +1 -0
- package/dist/src/docker/docker-delegator.js +201 -0
- package/dist/src/docker/docker-delegator.js.map +1 -0
- package/dist/src/docker/docker-delegator.test.d.ts +2 -0
- package/dist/src/docker/docker-delegator.test.d.ts.map +1 -0
- package/dist/src/docker/docker-delegator.test.js +132 -0
- package/dist/src/docker/docker-delegator.test.js.map +1 -0
- package/dist/src/index.d.ts +9 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/index.test.d.ts +2 -0
- package/dist/src/index.test.d.ts.map +1 -0
- package/dist/src/index.test.js +51 -0
- package/dist/src/index.test.js.map +1 -0
- package/dist/src/linux/index.d.ts +12 -0
- package/dist/src/linux/index.d.ts.map +1 -0
- package/dist/src/linux/index.js +11 -0
- package/dist/src/linux/index.js.map +1 -0
- package/dist/src/linux/linux-config.d.ts +37 -0
- package/dist/src/linux/linux-config.d.ts.map +1 -0
- package/dist/src/linux/linux-config.js +70 -0
- package/dist/src/linux/linux-config.js.map +1 -0
- package/dist/src/linux/linux-config.test.d.ts +2 -0
- package/dist/src/linux/linux-config.test.d.ts.map +1 -0
- package/dist/src/linux/linux-config.test.js +54 -0
- package/dist/src/linux/linux-config.test.js.map +1 -0
- package/dist/src/linux/linux-credential-writer.d.ts +35 -0
- package/dist/src/linux/linux-credential-writer.d.ts.map +1 -0
- package/dist/src/linux/linux-credential-writer.js +300 -0
- package/dist/src/linux/linux-credential-writer.js.map +1 -0
- package/dist/src/linux/linux-display-manager.d.ts +24 -0
- package/dist/src/linux/linux-display-manager.d.ts.map +1 -0
- package/dist/src/linux/linux-display-manager.js +92 -0
- package/dist/src/linux/linux-display-manager.js.map +1 -0
- package/dist/src/linux/linux-env-guard.d.ts +13 -0
- package/dist/src/linux/linux-env-guard.d.ts.map +1 -0
- package/dist/src/linux/linux-env-guard.js +31 -0
- package/dist/src/linux/linux-env-guard.js.map +1 -0
- package/dist/src/linux/linux-env-guard.test.d.ts +2 -0
- package/dist/src/linux/linux-env-guard.test.d.ts.map +1 -0
- package/dist/src/linux/linux-env-guard.test.js +48 -0
- package/dist/src/linux/linux-env-guard.test.js.map +1 -0
- package/dist/src/linux/linux-fflags.d.ts +17 -0
- package/dist/src/linux/linux-fflags.d.ts.map +1 -0
- package/dist/src/linux/linux-fflags.js +33 -0
- package/dist/src/linux/linux-fflags.js.map +1 -0
- package/dist/src/linux/linux-fflags.test.d.ts +2 -0
- package/dist/src/linux/linux-fflags.test.d.ts.map +1 -0
- package/dist/src/linux/linux-fflags.test.js +55 -0
- package/dist/src/linux/linux-fflags.test.js.map +1 -0
- package/dist/src/linux/linux-prerequisites.d.ts +24 -0
- package/dist/src/linux/linux-prerequisites.d.ts.map +1 -0
- package/dist/src/linux/linux-prerequisites.js +118 -0
- package/dist/src/linux/linux-prerequisites.js.map +1 -0
- package/dist/src/linux/linux-shader-patcher.d.ts +17 -0
- package/dist/src/linux/linux-shader-patcher.d.ts.map +1 -0
- package/dist/src/linux/linux-shader-patcher.js +48 -0
- package/dist/src/linux/linux-shader-patcher.js.map +1 -0
- package/dist/src/linux/linux-shader-patcher.test.d.ts +2 -0
- package/dist/src/linux/linux-shader-patcher.test.d.ts.map +1 -0
- package/dist/src/linux/linux-shader-patcher.test.js +55 -0
- package/dist/src/linux/linux-shader-patcher.test.js.map +1 -0
- package/dist/src/linux/linux-studio-installer.d.ts +10 -0
- package/dist/src/linux/linux-studio-installer.d.ts.map +1 -0
- package/dist/src/linux/linux-studio-installer.js +79 -0
- package/dist/src/linux/linux-studio-installer.js.map +1 -0
- package/dist/src/linux/linux-studio-launcher.d.ts +10 -0
- package/dist/src/linux/linux-studio-launcher.d.ts.map +1 -0
- package/dist/src/linux/linux-studio-launcher.js +73 -0
- package/dist/src/linux/linux-studio-launcher.js.map +1 -0
- package/dist/src/linux/linux-version-resolver.d.ts +18 -0
- package/dist/src/linux/linux-version-resolver.d.ts.map +1 -0
- package/dist/src/linux/linux-version-resolver.js +49 -0
- package/dist/src/linux/linux-version-resolver.js.map +1 -0
- package/dist/src/linux/linux-wine-env.d.ts +11 -0
- package/dist/src/linux/linux-wine-env.d.ts.map +1 -0
- package/dist/src/linux/linux-wine-env.js +33 -0
- package/dist/src/linux/linux-wine-env.js.map +1 -0
- package/dist/src/linux/linux-wine-env.test.d.ts +2 -0
- package/dist/src/linux/linux-wine-env.test.d.ts.map +1 -0
- package/dist/src/linux/linux-wine-env.test.js +47 -0
- package/dist/src/linux/linux-wine-env.test.js.map +1 -0
- package/dist/src/plugin/persistent-plugin-installer.d.ts +21 -0
- package/dist/src/plugin/persistent-plugin-installer.d.ts.map +1 -0
- package/dist/src/plugin/persistent-plugin-installer.js +69 -0
- package/dist/src/plugin/persistent-plugin-installer.js.map +1 -0
- package/dist/src/plugin/persistent-plugin-installer.test.d.ts +5 -0
- package/dist/src/plugin/persistent-plugin-installer.test.d.ts.map +1 -0
- package/dist/src/plugin/persistent-plugin-installer.test.js +119 -0
- package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -0
- package/dist/src/plugin/plugin-discovery.d.ts +7 -0
- package/dist/src/plugin/plugin-discovery.d.ts.map +1 -0
- package/dist/src/plugin/plugin-discovery.js +18 -0
- package/dist/src/plugin/plugin-discovery.js.map +1 -0
- package/dist/src/plugin/plugin-discovery.test.d.ts +5 -0
- package/dist/src/plugin/plugin-discovery.test.d.ts.map +1 -0
- package/dist/src/plugin/plugin-discovery.test.js +55 -0
- package/dist/src/plugin/plugin-discovery.test.js.map +1 -0
- package/dist/src/plugin/plugin-injector.js +1 -1
- package/dist/src/plugin/plugin-injector.js.map +1 -1
- package/dist/src/process/studio-process-manager.d.ts +7 -3
- package/dist/src/process/studio-process-manager.d.ts.map +1 -1
- package/dist/src/process/studio-process-manager.js +40 -11
- package/dist/src/process/studio-process-manager.js.map +1 -1
- package/dist/src/process/studio-process-manager.test.js +18 -1
- package/dist/src/process/studio-process-manager.test.js.map +1 -1
- package/dist/src/server/action-dispatcher.d.ts +35 -0
- package/dist/src/server/action-dispatcher.d.ts.map +1 -0
- package/dist/src/server/action-dispatcher.js +67 -0
- package/dist/src/server/action-dispatcher.js.map +1 -0
- package/dist/src/server/action-dispatcher.test.d.ts +6 -0
- package/dist/src/server/action-dispatcher.test.d.ts.map +1 -0
- package/dist/src/server/action-dispatcher.test.js +173 -0
- package/dist/src/server/action-dispatcher.test.js.map +1 -0
- package/dist/src/server/index.d.ts +1 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/pending-request-map.d.ts +33 -0
- package/dist/src/server/pending-request-map.d.ts.map +1 -0
- package/dist/src/server/pending-request-map.js +69 -0
- package/dist/src/server/pending-request-map.js.map +1 -0
- package/dist/src/server/pending-request-map.test.d.ts +2 -0
- package/dist/src/server/pending-request-map.test.d.ts.map +1 -0
- package/dist/src/server/pending-request-map.test.js +192 -0
- package/dist/src/server/pending-request-map.test.js.map +1 -0
- package/dist/src/server/plugin-detection.test.d.ts +7 -0
- package/dist/src/server/plugin-detection.test.d.ts.map +1 -0
- package/dist/src/server/plugin-detection.test.js +154 -0
- package/dist/src/server/plugin-detection.test.js.map +1 -0
- package/dist/src/server/studio-bridge-server.d.ts +44 -7
- package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
- package/dist/src/server/studio-bridge-server.js +341 -91
- package/dist/src/server/studio-bridge-server.js.map +1 -1
- package/dist/src/server/studio-bridge-server.test.js +231 -207
- package/dist/src/server/studio-bridge-server.test.js.map +1 -1
- package/dist/src/server/web-socket-protocol-basic.test.d.ts +2 -0
- package/dist/src/server/web-socket-protocol-basic.test.d.ts.map +1 -0
- package/dist/src/server/web-socket-protocol-basic.test.js +98 -0
- package/dist/src/server/web-socket-protocol-basic.test.js.map +1 -0
- package/dist/src/server/web-socket-protocol.d.ts +218 -20
- package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
- package/dist/src/server/web-socket-protocol.js +346 -20
- package/dist/src/server/web-socket-protocol.js.map +1 -1
- package/dist/src/server/web-socket-protocol.test.js +572 -146
- package/dist/src/server/web-socket-protocol.test.js.map +1 -1
- package/dist/src/test/e2e/hand-off.test.d.ts +9 -0
- package/dist/src/test/e2e/hand-off.test.d.ts.map +1 -0
- package/dist/src/test/e2e/hand-off.test.js +274 -0
- package/dist/src/test/e2e/hand-off.test.js.map +1 -0
- package/dist/src/test/e2e/persistent-session.test.d.ts +11 -0
- package/dist/src/test/e2e/persistent-session.test.d.ts.map +1 -0
- package/dist/src/test/e2e/persistent-session.test.js +367 -0
- package/dist/src/test/e2e/persistent-session.test.js.map +1 -0
- package/dist/src/test/e2e/split-server.test.d.ts +14 -0
- package/dist/src/test/e2e/split-server.test.d.ts.map +1 -0
- package/dist/src/test/e2e/split-server.test.js +230 -0
- package/dist/src/test/e2e/split-server.test.js.map +1 -0
- package/dist/src/test/helpers/mock-plugin-client.d.ts +69 -0
- package/dist/src/test/helpers/mock-plugin-client.d.ts.map +1 -0
- package/dist/src/test/helpers/mock-plugin-client.js +213 -0
- package/dist/src/test/helpers/mock-plugin-client.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docker/.dockerignore +2 -0
- package/docker/Dockerfile +113 -0
- package/docker/docker-compose.yml +20 -0
- package/docker/entrypoint.sh +19 -0
- package/package.json +8 -6
- package/src/bridge/bridge-connection-remote.test.ts +189 -0
- package/src/bridge/bridge-connection.test.ts +1076 -0
- package/src/bridge/bridge-connection.ts +718 -0
- package/src/bridge/bridge-session.test.ts +336 -0
- package/src/bridge/bridge-session.ts +365 -0
- package/src/bridge/index.ts +42 -0
- package/src/bridge/internal/__tests__/failover-crash.test.ts +191 -0
- package/src/bridge/internal/__tests__/failover-graceful.test.ts +268 -0
- package/src/bridge/internal/__tests__/failover-inflight.test.ts +329 -0
- package/src/bridge/internal/__tests__/host-client-integration.test.ts +387 -0
- package/src/bridge/internal/bridge-client.test.ts +399 -0
- package/src/bridge/internal/bridge-client.ts +434 -0
- package/src/bridge/internal/bridge-host.test.ts +501 -0
- package/src/bridge/internal/bridge-host.ts +531 -0
- package/src/bridge/internal/environment-detection.test.ts +180 -0
- package/src/bridge/internal/environment-detection.ts +119 -0
- package/src/bridge/internal/hand-off.test.ts +408 -0
- package/src/bridge/internal/hand-off.ts +275 -0
- package/src/bridge/internal/health-endpoint.test.ts +147 -0
- package/src/bridge/internal/health-endpoint.ts +100 -0
- package/src/bridge/internal/host-protocol.test.ts +415 -0
- package/src/bridge/internal/host-protocol.ts +255 -0
- package/src/bridge/internal/session-tracker.test.ts +535 -0
- package/src/bridge/internal/session-tracker.ts +198 -0
- package/src/bridge/internal/transport-client.test.ts +241 -0
- package/src/bridge/internal/transport-client.ts +194 -0
- package/src/bridge/internal/transport-server.test.ts +220 -0
- package/src/bridge/internal/transport-server.ts +242 -0
- package/src/bridge/types.ts +161 -0
- package/src/cli/adapters/cli-command-adapter-handler.test.ts +318 -0
- package/src/cli/adapters/cli-command-adapter.test.ts +221 -0
- package/src/cli/adapters/cli-command-adapter.ts +342 -0
- package/src/cli/adapters/group-builder.test.ts +146 -0
- package/src/cli/adapters/group-builder.ts +81 -0
- package/src/cli/adapters/help-formatter.test.ts +97 -0
- package/src/cli/adapters/help-formatter.ts +86 -0
- package/src/cli/adapters/target-resolver.test.ts +222 -0
- package/src/cli/adapters/target-resolver.ts +144 -0
- package/src/cli/args/global-args.ts +2 -0
- package/src/cli/cli.ts +100 -21
- package/src/cli/resolve-script-content.ts +36 -0
- package/src/cli/resolve-session.test.ts +141 -0
- package/src/cli/resolve-session.ts +66 -0
- package/src/cli/script-executor.ts +22 -4
- package/src/cli/types.ts +11 -0
- package/src/commands/connect.test.ts +61 -0
- package/src/commands/connect.ts +32 -0
- package/src/commands/console/exec/exec.test.ts +258 -0
- package/src/commands/console/exec/exec.ts +130 -0
- package/src/commands/console/exec/execute.luau +202 -0
- package/src/commands/console/logs/logs.test.ts +138 -0
- package/src/commands/console/logs/logs.ts +115 -0
- package/src/commands/console/logs/query-logs.luau +76 -0
- package/src/commands/disconnect.test.ts +21 -0
- package/src/commands/disconnect.ts +12 -0
- package/src/commands/explorer/query/query-data-model.luau +206 -0
- package/src/commands/explorer/query/query.test.ts +297 -0
- package/src/commands/explorer/query/query.ts +157 -0
- package/src/commands/formatters.test.ts +237 -0
- package/src/commands/framework/action-loader.test.ts +118 -0
- package/src/commands/framework/action-loader.ts +65 -0
- package/src/commands/framework/arg-builder.test.ts +298 -0
- package/src/commands/framework/arg-builder.ts +203 -0
- package/src/commands/framework/command-registry.test.ts +204 -0
- package/src/commands/framework/command-registry.ts +51 -0
- package/src/commands/framework/define-command.test.ts +161 -0
- package/src/commands/framework/define-command.ts +114 -0
- package/src/commands/framework/index.ts +33 -0
- package/src/commands/index.ts +72 -0
- package/src/commands/linux/inject-credentials/inject-credentials.ts +118 -0
- package/src/commands/linux/setup/setup.ts +145 -0
- package/src/commands/linux/status/status.ts +180 -0
- package/src/commands/plugin/install/install.ts +31 -0
- package/src/commands/plugin/uninstall/uninstall.ts +54 -0
- package/src/commands/process/close/close.ts +52 -0
- package/src/commands/process/format-state.ts +21 -0
- package/src/commands/process/info/info.test.ts +76 -0
- package/src/commands/process/info/info.ts +54 -0
- package/src/commands/process/info/query-state.luau +48 -0
- package/src/commands/process/launch/launch.test.ts +65 -0
- package/src/commands/process/launch/launch.ts +45 -0
- package/src/commands/process/list/list.test.ts +82 -0
- package/src/commands/process/list/list.ts +75 -0
- package/src/commands/process/run/run.ts +98 -0
- package/src/commands/rgba-to-png.ts +98 -0
- package/src/commands/serve/serve.test.ts +139 -0
- package/src/commands/serve/serve.ts +161 -0
- package/src/commands/viewport/screenshot/capture-screenshot.luau +247 -0
- package/src/commands/viewport/screenshot/screenshot.test.ts +181 -0
- package/src/commands/viewport/screenshot/screenshot.ts +71 -0
- package/src/docker/docker-delegator.test.ts +159 -0
- package/src/docker/docker-delegator.ts +240 -0
- package/src/index.test.ts +58 -0
- package/src/index.ts +104 -3
- package/src/linux/README.md +130 -0
- package/src/linux/index.ts +25 -0
- package/src/linux/linux-config.test.ts +66 -0
- package/src/linux/linux-config.ts +102 -0
- package/src/linux/linux-credential-writer.ts +421 -0
- package/src/linux/linux-display-manager.ts +106 -0
- package/src/linux/linux-env-guard.test.ts +62 -0
- package/src/linux/linux-env-guard.ts +38 -0
- package/src/linux/linux-fflags.test.ts +78 -0
- package/src/linux/linux-fflags.ts +48 -0
- package/src/linux/linux-prerequisites.ts +152 -0
- package/src/linux/linux-shader-patcher.test.ts +76 -0
- package/src/linux/linux-shader-patcher.ts +56 -0
- package/src/linux/linux-studio-installer.ts +113 -0
- package/src/linux/linux-studio-launcher.ts +90 -0
- package/src/linux/linux-version-resolver.ts +74 -0
- package/src/linux/linux-wine-env.test.ts +56 -0
- package/src/linux/linux-wine-env.ts +38 -0
- package/src/linux/write-cred.c +48 -0
- package/src/plugin/persistent-plugin-installer.test.ts +171 -0
- package/src/plugin/persistent-plugin-installer.ts +90 -0
- package/src/plugin/plugin-discovery.test.ts +70 -0
- package/src/plugin/plugin-discovery.ts +21 -0
- package/src/plugin/plugin-injector.ts +1 -1
- package/src/process/studio-process-manager.test.ts +22 -1
- package/src/process/studio-process-manager.ts +59 -18
- package/src/server/action-dispatcher.test.ts +240 -0
- package/src/server/action-dispatcher.ts +89 -0
- package/src/server/index.ts +0 -3
- package/src/server/pending-request-map.test.ts +261 -0
- package/src/server/pending-request-map.ts +87 -0
- package/src/server/plugin-detection.test.ts +195 -0
- package/src/server/studio-bridge-server.test.ts +321 -283
- package/src/server/studio-bridge-server.ts +469 -111
- package/src/server/web-socket-protocol-basic.test.ts +131 -0
- package/src/server/web-socket-protocol.test.ts +658 -159
- package/src/server/web-socket-protocol.ts +668 -58
- package/src/test/e2e/hand-off.test.ts +338 -0
- package/src/test/e2e/persistent-session.test.ts +442 -0
- package/src/test/e2e/split-server.test.ts +290 -0
- package/src/test/helpers/mock-plugin-client.ts +276 -0
- package/templates/studio-bridge-plugin/src/Shared/ActionRouter.luau +245 -0
- package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.luau +203 -0
- package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.luau +144 -0
- package/templates/studio-bridge-plugin/src/Shared/Protocol.luau +132 -0
- package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +364 -133
- package/templates/studio-bridge-plugin/src/Vendor/png.luau +1247 -0
- package/templates/studio-bridge-plugin-test/test/actions.test.luau +580 -0
- package/templates/studio-bridge-plugin-test/test/discovery.test.luau +622 -0
- package/templates/studio-bridge-plugin-test/test/execute-handler.test.luau +406 -0
- package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.luau +814 -0
- package/templates/studio-bridge-plugin-test/test/integration.test.luau +1020 -0
- package/templates/studio-bridge-plugin-test/test/new-actions.test.luau +339 -0
- package/templates/studio-bridge-plugin-test/test/plugin-entry.test.luau +493 -0
- package/templates/studio-bridge-plugin-test/test/protocol.test.luau +506 -0
- package/templates/studio-bridge-plugin-test/test/roblox-mocks.luau +108 -0
- package/templates/studio-bridge-plugin-test/test/test-runner.luau +112 -0
- package/dist/src/cli/commands/exec-command.d.ts +0 -15
- package/dist/src/cli/commands/exec-command.d.ts.map +0 -1
- package/dist/src/cli/commands/exec-command.js +0 -35
- package/dist/src/cli/commands/exec-command.js.map +0 -1
- package/dist/src/cli/commands/run-command.d.ts +0 -15
- package/dist/src/cli/commands/run-command.d.ts.map +0 -1
- package/dist/src/cli/commands/run-command.js +0 -47
- package/dist/src/cli/commands/run-command.js.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-command.d.ts +0 -17
- package/dist/src/cli/commands/terminal/terminal-command.d.ts.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-command.js +0 -41
- package/dist/src/cli/commands/terminal/terminal-command.js.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-editor.d.ts +0 -43
- package/dist/src/cli/commands/terminal/terminal-editor.d.ts.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-editor.js +0 -430
- package/dist/src/cli/commands/terminal/terminal-editor.js.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-mode.d.ts +0 -13
- package/dist/src/cli/commands/terminal/terminal-mode.d.ts.map +0 -1
- package/dist/src/cli/commands/terminal/terminal-mode.js +0 -141
- package/dist/src/cli/commands/terminal/terminal-mode.js.map +0 -1
- package/dist/src/server/web-socket-protocol.smoke.test.d.ts +0 -6
- package/dist/src/server/web-socket-protocol.smoke.test.d.ts.map +0 -1
- package/dist/src/server/web-socket-protocol.smoke.test.js +0 -196
- package/dist/src/server/web-socket-protocol.smoke.test.js.map +0 -1
- package/src/cli/commands/exec-command.ts +0 -48
- package/src/cli/commands/run-command.ts +0 -63
- package/src/cli/commands/terminal/terminal-command.ts +0 -54
- package/src/cli/commands/terminal/terminal-editor.ts +0 -500
- package/src/cli/commands/terminal/terminal-mode.ts +0 -184
- package/src/server/web-socket-protocol.smoke.test.ts +0 -255
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { randomUUID } from 'crypto';
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as http from 'http';
|
|
13
15
|
import * as path from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
14
17
|
import { WebSocketServer, type WebSocket } from 'ws';
|
|
15
18
|
import { OutputHelper } from '@quenty/cli-output-helpers';
|
|
16
19
|
import {
|
|
@@ -20,13 +23,22 @@ import {
|
|
|
20
23
|
} from '@quenty/nevermore-template-helpers';
|
|
21
24
|
import {
|
|
22
25
|
type OutputLevel,
|
|
26
|
+
type Capability,
|
|
27
|
+
type PluginMessage,
|
|
28
|
+
type ServerMessage,
|
|
23
29
|
encodeMessage,
|
|
24
30
|
decodePluginMessage,
|
|
25
31
|
} from './web-socket-protocol.js';
|
|
32
|
+
import { ActionDispatcher } from './action-dispatcher.js';
|
|
33
|
+
import {
|
|
34
|
+
loadActionSourcesAsync,
|
|
35
|
+
type ActionSource,
|
|
36
|
+
} from '../commands/framework/action-loader.js';
|
|
26
37
|
import {
|
|
27
38
|
injectPluginAsync,
|
|
28
39
|
type InjectedPlugin,
|
|
29
40
|
} from '../plugin/plugin-injector.js';
|
|
41
|
+
import { isPersistentPluginInstalled } from '../plugin/plugin-discovery.js';
|
|
30
42
|
import {
|
|
31
43
|
launchStudioAsync,
|
|
32
44
|
type StudioProcess,
|
|
@@ -43,9 +55,20 @@ const sessionAttributeTransformScript = resolvePackagePath(
|
|
|
43
55
|
'transform-add-session-attribute.luau'
|
|
44
56
|
);
|
|
45
57
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
function readServerVersion(): string {
|
|
59
|
+
try {
|
|
60
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
61
|
+
// Walk up from src/server/ to package root
|
|
62
|
+
const pkgPath = path.resolve(thisDir, '..', '..', 'package.json');
|
|
63
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
64
|
+
const pkg = JSON.parse(raw) as { version?: string };
|
|
65
|
+
return pkg.version ?? '0.0.0';
|
|
66
|
+
} catch {
|
|
67
|
+
return '0.0.0';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const SERVER_VERSION = readServerVersion();
|
|
49
72
|
|
|
50
73
|
export type StudioBridgePhase =
|
|
51
74
|
| 'building'
|
|
@@ -64,6 +87,11 @@ export interface StudioBridgeServerOptions {
|
|
|
64
87
|
onPhase?: (phase: StudioBridgePhase) => void;
|
|
65
88
|
/** Session ID for concurrent session isolation. Auto-generated if omitted. */
|
|
66
89
|
sessionId?: string;
|
|
90
|
+
/** Whether to prefer the persistent plugin over temp injection (default: true).
|
|
91
|
+
* When true and the persistent plugin is installed, the server waits for
|
|
92
|
+
* the plugin to discover it via the health endpoint before falling back
|
|
93
|
+
* to temporary injection. Set to false in CI environments. */
|
|
94
|
+
preferPersistentPlugin?: boolean;
|
|
67
95
|
}
|
|
68
96
|
|
|
69
97
|
export interface ExecuteOptions {
|
|
@@ -80,10 +108,6 @@ export interface StudioBridgeResult {
|
|
|
80
108
|
logs: string;
|
|
81
109
|
}
|
|
82
110
|
|
|
83
|
-
// ---------------------------------------------------------------------------
|
|
84
|
-
// State machine
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
|
|
87
111
|
type BridgeState =
|
|
88
112
|
| 'idle'
|
|
89
113
|
| 'starting'
|
|
@@ -92,52 +116,156 @@ type BridgeState =
|
|
|
92
116
|
| 'stopping'
|
|
93
117
|
| 'stopped';
|
|
94
118
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
119
|
+
/** Returns the assigned port once listening. WSS uses noServer mode (manual upgrade). */
|
|
120
|
+
function startHttpAndWsServerAsync(
|
|
121
|
+
httpServer: http.Server,
|
|
122
|
+
wss: WebSocketServer,
|
|
123
|
+
sessionId: string
|
|
124
|
+
): Promise<number> {
|
|
125
|
+
httpServer.on(
|
|
126
|
+
'request',
|
|
127
|
+
(req: http.IncomingMessage, res: http.ServerResponse) => {
|
|
128
|
+
if (req.method === 'GET' && req.url === '/health') {
|
|
129
|
+
const addr = httpServer.address();
|
|
130
|
+
const port = typeof addr === 'object' && addr !== null ? addr.port : 0;
|
|
131
|
+
const body = JSON.stringify({
|
|
132
|
+
status: 'ok',
|
|
133
|
+
sessionId,
|
|
134
|
+
port,
|
|
135
|
+
serverVersion: SERVER_VERSION,
|
|
136
|
+
});
|
|
137
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
138
|
+
res.end(body);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
143
|
+
res.end('Not Found');
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// Handle WebSocket upgrades — only allow /${sessionId}
|
|
148
|
+
httpServer.on(
|
|
149
|
+
'upgrade',
|
|
150
|
+
(
|
|
151
|
+
req: http.IncomingMessage,
|
|
152
|
+
socket: import('stream').Duplex,
|
|
153
|
+
head: Buffer
|
|
154
|
+
) => {
|
|
155
|
+
const expectedPath = `/${sessionId}`;
|
|
156
|
+
if (req.url !== expectedPath) {
|
|
157
|
+
socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
|
|
158
|
+
socket.destroy();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
163
|
+
wss.emit('connection', ws, req);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
);
|
|
98
167
|
|
|
99
|
-
/**
|
|
100
|
-
* Start a WebSocket server on a random available port and return the assigned
|
|
101
|
-
* port number once listening.
|
|
102
|
-
*/
|
|
103
|
-
function startWsServerAsync(wss: WebSocketServer): Promise<number> {
|
|
104
168
|
return new Promise((resolve, reject) => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const addr =
|
|
169
|
+
httpServer.on('error', reject);
|
|
170
|
+
httpServer.listen(0, () => {
|
|
171
|
+
const addr = httpServer.address();
|
|
108
172
|
if (typeof addr === 'object' && addr !== null) {
|
|
109
173
|
resolve(addr.port);
|
|
110
174
|
} else {
|
|
111
|
-
reject(new Error('
|
|
175
|
+
reject(new Error('HTTP server address is not available'));
|
|
112
176
|
}
|
|
113
177
|
});
|
|
114
178
|
});
|
|
115
179
|
}
|
|
116
180
|
|
|
181
|
+
/** Capability required for each action type. */
|
|
182
|
+
const ACTION_CAPABILITIES: Record<string, Capability> = {
|
|
183
|
+
queryState: 'queryState',
|
|
184
|
+
captureScreenshot: 'captureScreenshot',
|
|
185
|
+
queryDataModel: 'queryDataModel',
|
|
186
|
+
queryLogs: 'queryLogs',
|
|
187
|
+
execute: 'execute',
|
|
188
|
+
};
|
|
189
|
+
|
|
117
190
|
export class StudioBridgeServer {
|
|
118
191
|
private _state: BridgeState = 'idle';
|
|
119
192
|
|
|
193
|
+
private readonly _options: StudioBridgeServerOptions;
|
|
120
194
|
private readonly _sessionId: string;
|
|
121
195
|
private readonly _defaultTimeoutMs: number;
|
|
122
196
|
private readonly _onPhase: ((phase: StudioBridgePhase) => void) | undefined;
|
|
123
197
|
private readonly _placePath: string | undefined;
|
|
124
198
|
|
|
199
|
+
private _httpServer: http.Server | undefined;
|
|
125
200
|
private _wss: WebSocketServer | undefined;
|
|
201
|
+
private _port: number = 0;
|
|
126
202
|
private _pluginHandle: InjectedPlugin | undefined;
|
|
127
203
|
private _studioProc: StudioProcess | undefined;
|
|
128
204
|
private _placeBuildContext: BuildContext | undefined;
|
|
129
205
|
private _connectedClient: WebSocket | undefined;
|
|
130
206
|
|
|
207
|
+
private _negotiatedCapabilities: Capability[] = ['execute'];
|
|
208
|
+
private _lastHeartbeatTimestamp: number | undefined;
|
|
209
|
+
private _actionDispatcher = new ActionDispatcher();
|
|
210
|
+
private _actionsReady = false;
|
|
211
|
+
private _actionSources: ActionSource[] | undefined;
|
|
212
|
+
|
|
131
213
|
constructor(options: StudioBridgeServerOptions = {}) {
|
|
214
|
+
this._options = options;
|
|
132
215
|
this._sessionId = options.sessionId ?? randomUUID();
|
|
133
216
|
this._defaultTimeoutMs = options.timeoutMs ?? 120_000;
|
|
134
217
|
this._onPhase = options.onPhase;
|
|
135
218
|
this._placePath = options.placePath;
|
|
136
219
|
}
|
|
137
220
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
221
|
+
/** The negotiated set of capabilities shared between plugin and server. */
|
|
222
|
+
get capabilities(): readonly Capability[] {
|
|
223
|
+
return this._negotiatedCapabilities;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Timestamp of the last heartbeat received from the plugin, or undefined. */
|
|
227
|
+
get lastHeartbeatTimestamp(): number | undefined {
|
|
228
|
+
return this._lastHeartbeatTimestamp;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Requires the plugin to advertise the relevant capability. */
|
|
232
|
+
async performActionAsync<T extends PluginMessage>(
|
|
233
|
+
message: Omit<ServerMessage, 'requestId' | 'sessionId'>,
|
|
234
|
+
timeoutMs?: number
|
|
235
|
+
): Promise<T> {
|
|
236
|
+
if (this._state !== 'ready') {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`Cannot perform action: expected state 'ready', got '${this._state}'`
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (!this._connectedClient) {
|
|
242
|
+
throw new Error('Cannot perform action: no connected client');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const actionType = message.type;
|
|
246
|
+
const requiredCapability = ACTION_CAPABILITIES[actionType];
|
|
247
|
+
if (
|
|
248
|
+
requiredCapability &&
|
|
249
|
+
!this._negotiatedCapabilities.includes(requiredCapability)
|
|
250
|
+
) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`Plugin does not support capability: ${requiredCapability}`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const { requestId, responsePromise } =
|
|
257
|
+
this._actionDispatcher.createRequestAsync(actionType, timeoutMs);
|
|
258
|
+
|
|
259
|
+
const fullMessage: ServerMessage = {
|
|
260
|
+
...message,
|
|
261
|
+
requestId,
|
|
262
|
+
sessionId: this._sessionId,
|
|
263
|
+
} as ServerMessage;
|
|
264
|
+
|
|
265
|
+
this._connectedClient.send(encodeMessage(fullMessage));
|
|
266
|
+
|
|
267
|
+
return responsePromise as Promise<T>;
|
|
268
|
+
}
|
|
141
269
|
|
|
142
270
|
/**
|
|
143
271
|
* Build place (if needed) → start WS server → inject plugin → launch
|
|
@@ -181,21 +309,45 @@ export class StudioBridgeServer {
|
|
|
181
309
|
);
|
|
182
310
|
placePath = transformedPlacePath;
|
|
183
311
|
|
|
184
|
-
// 1. Start WebSocket server (unique path rejects wrong connections at
|
|
185
|
-
this.
|
|
186
|
-
|
|
312
|
+
// 1. Start HTTP + WebSocket server (unique path rejects wrong connections at upgrade level)
|
|
313
|
+
this._httpServer = http.createServer();
|
|
314
|
+
this._wss = new WebSocketServer({ noServer: true });
|
|
315
|
+
const port = await startHttpAndWsServerAsync(
|
|
316
|
+
this._httpServer,
|
|
317
|
+
this._wss,
|
|
318
|
+
this._sessionId
|
|
319
|
+
);
|
|
320
|
+
this._port = port;
|
|
187
321
|
OutputHelper.verbose(
|
|
188
322
|
`[StudioBridge] WebSocket server listening on port ${port}`
|
|
189
323
|
);
|
|
190
324
|
|
|
191
|
-
// 2.
|
|
192
|
-
this.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
325
|
+
// 2. Decide between persistent plugin and temp injection
|
|
326
|
+
const preferPersistent = this._options.preferPersistentPlugin ?? true;
|
|
327
|
+
|
|
328
|
+
if (preferPersistent && isPersistentPluginInstalled()) {
|
|
329
|
+
// Persistent plugin is installed. Skip injection and wait for the
|
|
330
|
+
// plugin to discover us via the health endpoint.
|
|
331
|
+
// Start a grace period timer: if the plugin does not connect within
|
|
332
|
+
// the grace period, fall back to temporary injection.
|
|
333
|
+
OutputHelper.verbose(
|
|
334
|
+
'[StudioBridge] Persistent plugin detected, waiting for connection'
|
|
335
|
+
);
|
|
336
|
+
const graceMs = 3_000;
|
|
337
|
+
const connected = await this._waitForPluginConnectionAsync(graceMs);
|
|
338
|
+
if (!connected) {
|
|
339
|
+
// Grace period expired. Plugin may not be running in Studio.
|
|
340
|
+
// Fall back to temporary injection.
|
|
341
|
+
OutputHelper.verbose(
|
|
342
|
+
'[StudioBridge] Grace period expired, falling back to temp injection'
|
|
343
|
+
);
|
|
344
|
+
await this._injectPluginAsync();
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
// No persistent plugin or preference disabled (CI mode).
|
|
348
|
+
// Use temporary injection (legacy launch-and-execute flow).
|
|
349
|
+
await this._injectPluginAsync();
|
|
350
|
+
}
|
|
199
351
|
|
|
200
352
|
// 3. Launch Studio
|
|
201
353
|
this._onPhase?.('launching');
|
|
@@ -204,9 +356,11 @@ export class StudioBridgeServer {
|
|
|
204
356
|
`[StudioBridge] Studio launched (PID: ${this._studioProc.process.pid})`
|
|
205
357
|
);
|
|
206
358
|
|
|
207
|
-
// 4. Wait for handshake
|
|
359
|
+
// 4. Wait for handshake (only if not already connected via persistent plugin)
|
|
208
360
|
this._onPhase?.('connecting');
|
|
209
|
-
|
|
361
|
+
if (!this._connectedClient) {
|
|
362
|
+
await this._waitForHandshakeAsync();
|
|
363
|
+
}
|
|
210
364
|
|
|
211
365
|
this._state = 'ready';
|
|
212
366
|
} catch (error) {
|
|
@@ -216,14 +370,7 @@ export class StudioBridgeServer {
|
|
|
216
370
|
}
|
|
217
371
|
}
|
|
218
372
|
|
|
219
|
-
|
|
220
|
-
// Lifecycle: executeAsync
|
|
221
|
-
// -----------------------------------------------------------------------
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Send a Luau script to the connected Studio instance and wait for it to
|
|
225
|
-
* finish executing. Can be called multiple times while the bridge is ready.
|
|
226
|
-
*/
|
|
373
|
+
/** Can be called multiple times while the bridge is ready. */
|
|
227
374
|
async executeAsync(options: ExecuteOptions): Promise<StudioBridgeResult> {
|
|
228
375
|
if (this._state !== 'ready') {
|
|
229
376
|
throw new Error(
|
|
@@ -234,11 +381,14 @@ export class StudioBridgeServer {
|
|
|
234
381
|
throw new Error('Cannot execute: no connected client');
|
|
235
382
|
}
|
|
236
383
|
|
|
384
|
+
// Sync action modules before first execute (state must still be 'ready'
|
|
385
|
+
// because performActionAsync checks for it).
|
|
386
|
+
await this._ensureActionsAsync();
|
|
387
|
+
|
|
237
388
|
this._state = 'executing';
|
|
238
389
|
this._onPhase?.('executing');
|
|
239
390
|
|
|
240
391
|
try {
|
|
241
|
-
// Send execute message
|
|
242
392
|
this._connectedClient.send(
|
|
243
393
|
encodeMessage({
|
|
244
394
|
type: 'execute',
|
|
@@ -247,7 +397,6 @@ export class StudioBridgeServer {
|
|
|
247
397
|
})
|
|
248
398
|
);
|
|
249
399
|
|
|
250
|
-
// Wait for result
|
|
251
400
|
const result = await this._waitForScriptCompleteAsync(options);
|
|
252
401
|
|
|
253
402
|
this._onPhase?.('done');
|
|
@@ -263,14 +412,7 @@ export class StudioBridgeServer {
|
|
|
263
412
|
}
|
|
264
413
|
}
|
|
265
414
|
|
|
266
|
-
|
|
267
|
-
// Lifecycle: stopAsync
|
|
268
|
-
// -----------------------------------------------------------------------
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Shut down the bridge — send shutdown to client, kill Studio, clean up
|
|
272
|
-
* all resources. Idempotent on 'stopped'.
|
|
273
|
-
*/
|
|
415
|
+
/** Idempotent on 'stopped'. */
|
|
274
416
|
async stopAsync(): Promise<void> {
|
|
275
417
|
if (this._state === 'stopped') {
|
|
276
418
|
return;
|
|
@@ -278,7 +420,6 @@ export class StudioBridgeServer {
|
|
|
278
420
|
|
|
279
421
|
this._state = 'stopping';
|
|
280
422
|
|
|
281
|
-
// Send shutdown to connected client
|
|
282
423
|
if (this._connectedClient) {
|
|
283
424
|
try {
|
|
284
425
|
this._connectedClient.send(
|
|
@@ -297,11 +438,195 @@ export class StudioBridgeServer {
|
|
|
297
438
|
this._state = 'stopped';
|
|
298
439
|
}
|
|
299
440
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
441
|
+
/**
|
|
442
|
+
* Ensure action modules (like `execute.luau`) are synced to the plugin
|
|
443
|
+
* before first use. Uses `syncActions` to check which actions the plugin
|
|
444
|
+
* is missing, then registers them via `registerAction`.
|
|
445
|
+
*
|
|
446
|
+
* Loads action sources and registers them with the connected plugin.
|
|
447
|
+
*/
|
|
448
|
+
private async _ensureActionsAsync(): Promise<void> {
|
|
449
|
+
if (this._actionsReady) return;
|
|
450
|
+
|
|
451
|
+
if (!this._actionSources) {
|
|
452
|
+
this._actionSources = await loadActionSourcesAsync();
|
|
453
|
+
OutputHelper.verbose(
|
|
454
|
+
`[StudioBridge] Loaded ${
|
|
455
|
+
this._actionSources.length
|
|
456
|
+
} action source(s): ${
|
|
457
|
+
this._actionSources.map((a) => a.name).join(', ') || '(none)'
|
|
458
|
+
}`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (this._actionSources.length === 0) {
|
|
463
|
+
this._actionsReady = true;
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const actions: Record<string, string> = {};
|
|
468
|
+
for (const action of this._actionSources) {
|
|
469
|
+
actions[action.name] = action.hash;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
OutputHelper.verbose('[StudioBridge] Syncing actions with plugin');
|
|
473
|
+
const syncResult = await this.performActionAsync<PluginMessage>(
|
|
474
|
+
{
|
|
475
|
+
type: 'syncActions',
|
|
476
|
+
payload: { actions },
|
|
477
|
+
},
|
|
478
|
+
10_000
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
if (syncResult.type === 'syncActionsResult') {
|
|
482
|
+
const needed = (syncResult.payload as Record<string, unknown>)
|
|
483
|
+
.needed as string[];
|
|
484
|
+
OutputHelper.verbose(
|
|
485
|
+
`[StudioBridge] ${needed.length} action(s) need registering${
|
|
486
|
+
needed.length > 0 ? ': ' + needed.join(', ') : ''
|
|
487
|
+
}`
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
for (const actionName of needed) {
|
|
491
|
+
const action = this._actionSources.find((a) => a.name === actionName);
|
|
492
|
+
if (!action) continue;
|
|
493
|
+
|
|
494
|
+
OutputHelper.verbose(
|
|
495
|
+
`[StudioBridge] Registering action: ${actionName}`
|
|
496
|
+
);
|
|
497
|
+
await this.performActionAsync<PluginMessage>(
|
|
498
|
+
{
|
|
499
|
+
type: 'registerAction',
|
|
500
|
+
payload: {
|
|
501
|
+
name: action.name,
|
|
502
|
+
source: action.source,
|
|
503
|
+
hash: action.hash,
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
10_000
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
this._actionsReady = true;
|
|
512
|
+
OutputHelper.verbose('[StudioBridge] Action sync complete');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Inject the temporary plugin via rojo build into Studio's plugins folder.
|
|
517
|
+
*/
|
|
518
|
+
private async _injectPluginAsync(): Promise<void> {
|
|
519
|
+
this._pluginHandle = await injectPluginAsync({
|
|
520
|
+
port: this._port,
|
|
521
|
+
sessionId: this._sessionId,
|
|
522
|
+
});
|
|
523
|
+
OutputHelper.verbose(
|
|
524
|
+
`[StudioBridge] Plugin injected: ${this._pluginHandle.pluginPath}`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Wait for a persistent plugin to connect via WebSocket within the grace
|
|
530
|
+
* period. Returns true if a plugin connected (sent hello or register),
|
|
531
|
+
* false if the grace period expired.
|
|
532
|
+
*/
|
|
533
|
+
private _waitForPluginConnectionAsync(graceMs: number): Promise<boolean> {
|
|
534
|
+
return new Promise<boolean>((resolve) => {
|
|
535
|
+
let settled = false;
|
|
536
|
+
|
|
537
|
+
const timer = setTimeout(() => {
|
|
538
|
+
if (!settled) {
|
|
539
|
+
settled = true;
|
|
540
|
+
resolve(false);
|
|
541
|
+
}
|
|
542
|
+
}, graceMs);
|
|
543
|
+
|
|
544
|
+
this._wss!.on('connection', (ws: WebSocket) => {
|
|
545
|
+
if (settled) return;
|
|
546
|
+
|
|
547
|
+
const onMessage = (raw: Buffer | string) => {
|
|
548
|
+
if (settled) return;
|
|
549
|
+
const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
|
|
550
|
+
const msg = decodePluginMessage(data);
|
|
551
|
+
if (!msg) return;
|
|
552
|
+
|
|
553
|
+
if (msg.type === 'register') {
|
|
554
|
+
settled = true;
|
|
555
|
+
clearTimeout(timer);
|
|
556
|
+
ws.off('message', onMessage);
|
|
557
|
+
|
|
558
|
+
this._handlePluginHandshakeMessage(ws, msg);
|
|
559
|
+
resolve(true);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
ws.on('message', onMessage);
|
|
564
|
+
|
|
565
|
+
ws.on('error', (err) => {
|
|
566
|
+
OutputHelper.verbose(
|
|
567
|
+
`[StudioBridge] WebSocket error during grace period: ${err.message}`
|
|
568
|
+
);
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
private _handlePluginHandshakeMessage(
|
|
575
|
+
ws: WebSocket,
|
|
576
|
+
msg: PluginMessage
|
|
577
|
+
): void {
|
|
578
|
+
if (msg.type !== 'register') return;
|
|
579
|
+
|
|
580
|
+
const serverSupportedCapabilities: Capability[] = [
|
|
581
|
+
'execute',
|
|
582
|
+
'queryState',
|
|
583
|
+
'captureScreenshot',
|
|
584
|
+
'queryDataModel',
|
|
585
|
+
'queryLogs',
|
|
586
|
+
];
|
|
587
|
+
|
|
588
|
+
this._negotiatedCapabilities = msg.payload.capabilities.filter((cap) =>
|
|
589
|
+
serverSupportedCapabilities.includes(cap)
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
OutputHelper.verbose(
|
|
593
|
+
'[StudioBridge] Plugin register handshake accepted (grace period)'
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
this._connectedClient = ws;
|
|
597
|
+
|
|
598
|
+
ws.on('message', (raw: Buffer | string) => {
|
|
599
|
+
const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
|
|
600
|
+
const innerMsg = decodePluginMessage(data);
|
|
601
|
+
if (!innerMsg) return;
|
|
602
|
+
|
|
603
|
+
if (this._actionDispatcher.handleResponse(innerMsg)) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (innerMsg.type === 'heartbeat') {
|
|
608
|
+
this._lastHeartbeatTimestamp = Date.now();
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
ws.on('close', () => {
|
|
613
|
+
OutputHelper.verbose('[StudioBridge] Plugin disconnected');
|
|
614
|
+
this._connectedClient = undefined;
|
|
615
|
+
if (this._state !== 'stopping' && this._state !== 'stopped') {
|
|
616
|
+
this._state = 'stopped';
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
}
|
|
303
620
|
|
|
304
621
|
private _waitForHandshakeAsync(): Promise<void> {
|
|
622
|
+
const serverSupportedCapabilities: Capability[] = [
|
|
623
|
+
'execute',
|
|
624
|
+
'queryState',
|
|
625
|
+
'captureScreenshot',
|
|
626
|
+
'queryDataModel',
|
|
627
|
+
'queryLogs',
|
|
628
|
+
];
|
|
629
|
+
|
|
305
630
|
return new Promise<void>((resolve, reject) => {
|
|
306
631
|
let settled = false;
|
|
307
632
|
|
|
@@ -322,47 +647,23 @@ export class StudioBridgeServer {
|
|
|
322
647
|
const onMessage = (raw: Buffer | string) => {
|
|
323
648
|
const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
|
|
324
649
|
const msg = decodePluginMessage(data);
|
|
325
|
-
if (!msg
|
|
650
|
+
if (!msg) {
|
|
326
651
|
return;
|
|
327
652
|
}
|
|
328
653
|
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
) {
|
|
333
|
-
OutputHelper.verbose(
|
|
334
|
-
`[StudioBridge] Rejecting hello with wrong session ID`
|
|
654
|
+
if (msg.type === 'register') {
|
|
655
|
+
this._negotiatedCapabilities = msg.payload.capabilities.filter(
|
|
656
|
+
(cap) => serverSupportedCapabilities.includes(cap)
|
|
335
657
|
);
|
|
336
|
-
ws.close();
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
658
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
encodeMessage({
|
|
344
|
-
type: 'welcome',
|
|
345
|
-
sessionId: this._sessionId,
|
|
346
|
-
payload: { sessionId: this._sessionId },
|
|
347
|
-
})
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
ws.off('message', onMessage);
|
|
351
|
-
this._connectedClient = ws;
|
|
352
|
-
|
|
353
|
-
// Listen for unexpected disconnect
|
|
354
|
-
ws.on('close', () => {
|
|
355
|
-
OutputHelper.verbose('[StudioBridge] Plugin disconnected');
|
|
356
|
-
this._connectedClient = undefined;
|
|
357
|
-
if (this._state !== 'stopping' && this._state !== 'stopped') {
|
|
358
|
-
this._state = 'stopped';
|
|
359
|
-
}
|
|
360
|
-
});
|
|
659
|
+
OutputHelper.verbose(
|
|
660
|
+
'[StudioBridge] Plugin register handshake accepted'
|
|
661
|
+
);
|
|
361
662
|
|
|
362
|
-
|
|
663
|
+
ws.off('message', onMessage);
|
|
664
|
+
this._finishHandshake(ws, settled, timer, resolve);
|
|
363
665
|
settled = true;
|
|
364
|
-
|
|
365
|
-
resolve();
|
|
666
|
+
return;
|
|
366
667
|
}
|
|
367
668
|
};
|
|
368
669
|
|
|
@@ -385,9 +686,46 @@ export class StudioBridgeServer {
|
|
|
385
686
|
});
|
|
386
687
|
}
|
|
387
688
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
689
|
+
/**
|
|
690
|
+
* Common handshake completion: store the connected client, listen for
|
|
691
|
+
* heartbeats and disconnect events.
|
|
692
|
+
*/
|
|
693
|
+
private _finishHandshake(
|
|
694
|
+
ws: WebSocket,
|
|
695
|
+
alreadySettled: boolean,
|
|
696
|
+
timer: ReturnType<typeof setTimeout>,
|
|
697
|
+
resolve: () => void
|
|
698
|
+
): void {
|
|
699
|
+
this._connectedClient = ws;
|
|
700
|
+
|
|
701
|
+
ws.on('message', (raw: Buffer | string) => {
|
|
702
|
+
const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
|
|
703
|
+
const msg = decodePluginMessage(data);
|
|
704
|
+
if (!msg) return;
|
|
705
|
+
|
|
706
|
+
// Action dispatcher first — request/response correlation
|
|
707
|
+
if (this._actionDispatcher.handleResponse(msg)) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (msg.type === 'heartbeat') {
|
|
712
|
+
this._lastHeartbeatTimestamp = Date.now();
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
ws.on('close', () => {
|
|
717
|
+
OutputHelper.verbose('[StudioBridge] Plugin disconnected');
|
|
718
|
+
this._connectedClient = undefined;
|
|
719
|
+
if (this._state !== 'stopping' && this._state !== 'stopped') {
|
|
720
|
+
this._state = 'stopped';
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
if (!alreadySettled) {
|
|
725
|
+
clearTimeout(timer);
|
|
726
|
+
resolve();
|
|
727
|
+
}
|
|
728
|
+
}
|
|
391
729
|
|
|
392
730
|
private _waitForScriptCompleteAsync(
|
|
393
731
|
options: ExecuteOptions
|
|
@@ -439,20 +777,19 @@ export class StudioBridgeServer {
|
|
|
439
777
|
}
|
|
440
778
|
|
|
441
779
|
switch (msg.type) {
|
|
442
|
-
case 'output': {
|
|
443
|
-
for (const entry of msg.payload.messages) {
|
|
444
|
-
logLines.push(entry.body);
|
|
445
|
-
options.onOutput?.(entry.level, entry.body);
|
|
446
|
-
}
|
|
447
|
-
break;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
780
|
case 'scriptComplete': {
|
|
451
781
|
OutputHelper.verbose(
|
|
452
782
|
`[StudioBridge] Script complete: success=${msg.payload.success}` +
|
|
453
783
|
(msg.payload.error ? ` error=${msg.payload.error}` : '')
|
|
454
784
|
);
|
|
455
785
|
|
|
786
|
+
if (msg.payload.output) {
|
|
787
|
+
for (const entry of msg.payload.output) {
|
|
788
|
+
logLines.push(entry.body);
|
|
789
|
+
options.onOutput?.(entry.level as OutputLevel, entry.body);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
456
793
|
if (msg.payload.error) {
|
|
457
794
|
logLines.push(msg.payload.error);
|
|
458
795
|
}
|
|
@@ -463,6 +800,24 @@ export class StudioBridgeServer {
|
|
|
463
800
|
});
|
|
464
801
|
break;
|
|
465
802
|
}
|
|
803
|
+
|
|
804
|
+
case 'error': {
|
|
805
|
+
const errorPayload = msg.payload as {
|
|
806
|
+
code: string;
|
|
807
|
+
message: string;
|
|
808
|
+
};
|
|
809
|
+
OutputHelper.verbose(
|
|
810
|
+
`[StudioBridge] Plugin error: ${errorPayload.code} — ${errorPayload.message}`
|
|
811
|
+
);
|
|
812
|
+
logLines.push(
|
|
813
|
+
`[StudioBridge] Plugin error: ${errorPayload.code} — ${errorPayload.message}`
|
|
814
|
+
);
|
|
815
|
+
finish({
|
|
816
|
+
success: false,
|
|
817
|
+
logs: logLines.join('\n'),
|
|
818
|
+
});
|
|
819
|
+
break;
|
|
820
|
+
}
|
|
466
821
|
}
|
|
467
822
|
};
|
|
468
823
|
|
|
@@ -494,31 +849,27 @@ export class StudioBridgeServer {
|
|
|
494
849
|
});
|
|
495
850
|
}
|
|
496
851
|
|
|
497
|
-
// -----------------------------------------------------------------------
|
|
498
|
-
// Private: _cleanupResourcesAsync
|
|
499
|
-
// -----------------------------------------------------------------------
|
|
500
|
-
|
|
501
852
|
private async _cleanupResourcesAsync(): Promise<void> {
|
|
502
|
-
|
|
853
|
+
this._actionDispatcher.cancelAll('Server shutting down');
|
|
854
|
+
|
|
503
855
|
if (this._studioProc) {
|
|
504
856
|
await this._studioProc.killAsync();
|
|
505
857
|
this._studioProc = undefined;
|
|
506
858
|
}
|
|
507
859
|
|
|
508
|
-
// Remove injected plugin
|
|
509
860
|
if (this._pluginHandle) {
|
|
510
861
|
await this._pluginHandle.cleanupAsync();
|
|
511
862
|
this._pluginHandle = undefined;
|
|
512
863
|
}
|
|
513
864
|
|
|
514
|
-
// Remove auto-built place
|
|
515
865
|
if (this._placeBuildContext) {
|
|
516
866
|
await this._placeBuildContext.cleanupAsync();
|
|
517
867
|
this._placeBuildContext = undefined;
|
|
518
868
|
}
|
|
519
869
|
|
|
520
|
-
//
|
|
521
|
-
//
|
|
870
|
+
// Terminate lingering WebSocket connections first so close callbacks
|
|
871
|
+
// fire promptly, then close the HTTP server (which owns the listening
|
|
872
|
+
// socket) and finally close the WSS.
|
|
522
873
|
if (this._wss) {
|
|
523
874
|
for (const wsClient of this._wss.clients) {
|
|
524
875
|
wsClient.terminate();
|
|
@@ -529,6 +880,13 @@ export class StudioBridgeServer {
|
|
|
529
880
|
this._wss = undefined;
|
|
530
881
|
}
|
|
531
882
|
|
|
883
|
+
if (this._httpServer) {
|
|
884
|
+
await new Promise<void>((resolve) => {
|
|
885
|
+
this._httpServer!.close(() => resolve());
|
|
886
|
+
});
|
|
887
|
+
this._httpServer = undefined;
|
|
888
|
+
}
|
|
889
|
+
|
|
532
890
|
this._connectedClient = undefined;
|
|
533
891
|
}
|
|
534
892
|
}
|