@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.
Files changed (689) hide show
  1. package/CHANGELOG.md +14 -42
  2. package/README.md +166 -115
  3. package/dist/src/bridge/bridge-connection-remote.test.d.ts +7 -0
  4. package/dist/src/bridge/bridge-connection-remote.test.d.ts.map +1 -0
  5. package/dist/src/bridge/bridge-connection-remote.test.js +144 -0
  6. package/dist/src/bridge/bridge-connection-remote.test.js.map +1 -0
  7. package/dist/src/bridge/bridge-connection.d.ts +112 -0
  8. package/dist/src/bridge/bridge-connection.d.ts.map +1 -0
  9. package/dist/src/bridge/bridge-connection.js +528 -0
  10. package/dist/src/bridge/bridge-connection.js.map +1 -0
  11. package/dist/src/bridge/bridge-connection.test.d.ts +6 -0
  12. package/dist/src/bridge/bridge-connection.test.d.ts.map +1 -0
  13. package/dist/src/bridge/bridge-connection.test.js +773 -0
  14. package/dist/src/bridge/bridge-connection.test.js.map +1 -0
  15. package/dist/src/bridge/bridge-session.d.ts +38 -0
  16. package/dist/src/bridge/bridge-session.d.ts.map +1 -0
  17. package/dist/src/bridge/bridge-session.js +259 -0
  18. package/dist/src/bridge/bridge-session.js.map +1 -0
  19. package/dist/src/bridge/bridge-session.test.d.ts +6 -0
  20. package/dist/src/bridge/bridge-session.test.d.ts.map +1 -0
  21. package/dist/src/bridge/bridge-session.test.js +264 -0
  22. package/dist/src/bridge/bridge-session.test.js.map +1 -0
  23. package/dist/src/bridge/index.d.ts +13 -0
  24. package/dist/src/bridge/index.d.ts.map +1 -0
  25. package/dist/src/bridge/index.js +13 -0
  26. package/dist/src/bridge/index.js.map +1 -0
  27. package/dist/src/bridge/internal/__tests__/failover-crash.test.d.ts +9 -0
  28. package/dist/src/bridge/internal/__tests__/failover-crash.test.d.ts.map +1 -0
  29. package/dist/src/bridge/internal/__tests__/failover-crash.test.js +159 -0
  30. package/dist/src/bridge/internal/__tests__/failover-crash.test.js.map +1 -0
  31. package/dist/src/bridge/internal/__tests__/failover-graceful.test.d.ts +9 -0
  32. package/dist/src/bridge/internal/__tests__/failover-graceful.test.d.ts.map +1 -0
  33. package/dist/src/bridge/internal/__tests__/failover-graceful.test.js +218 -0
  34. package/dist/src/bridge/internal/__tests__/failover-graceful.test.js.map +1 -0
  35. package/dist/src/bridge/internal/__tests__/failover-inflight.test.d.ts +9 -0
  36. package/dist/src/bridge/internal/__tests__/failover-inflight.test.d.ts.map +1 -0
  37. package/dist/src/bridge/internal/__tests__/failover-inflight.test.js +246 -0
  38. package/dist/src/bridge/internal/__tests__/failover-inflight.test.js.map +1 -0
  39. package/dist/src/bridge/internal/__tests__/host-client-integration.test.d.ts +10 -0
  40. package/dist/src/bridge/internal/__tests__/host-client-integration.test.d.ts.map +1 -0
  41. package/dist/src/bridge/internal/__tests__/host-client-integration.test.js +298 -0
  42. package/dist/src/bridge/internal/__tests__/host-client-integration.test.js.map +1 -0
  43. package/dist/src/bridge/internal/bridge-client.d.ts +70 -0
  44. package/dist/src/bridge/internal/bridge-client.d.ts.map +1 -0
  45. package/dist/src/bridge/internal/bridge-client.js +344 -0
  46. package/dist/src/bridge/internal/bridge-client.js.map +1 -0
  47. package/dist/src/bridge/internal/bridge-client.test.d.ts +7 -0
  48. package/dist/src/bridge/internal/bridge-client.test.d.ts.map +1 -0
  49. package/dist/src/bridge/internal/bridge-client.test.js +301 -0
  50. package/dist/src/bridge/internal/bridge-client.test.js.map +1 -0
  51. package/dist/src/bridge/internal/bridge-host.d.ts +78 -0
  52. package/dist/src/bridge/internal/bridge-host.d.ts.map +1 -0
  53. package/dist/src/bridge/internal/bridge-host.js +383 -0
  54. package/dist/src/bridge/internal/bridge-host.js.map +1 -0
  55. package/dist/src/bridge/internal/bridge-host.test.d.ts +7 -0
  56. package/dist/src/bridge/internal/bridge-host.test.d.ts.map +1 -0
  57. package/dist/src/bridge/internal/bridge-host.test.js +377 -0
  58. package/dist/src/bridge/internal/bridge-host.test.js.map +1 -0
  59. package/dist/src/bridge/internal/environment-detection.d.ts +44 -0
  60. package/dist/src/bridge/internal/environment-detection.d.ts.map +1 -0
  61. package/dist/src/bridge/internal/environment-detection.js +91 -0
  62. package/dist/src/bridge/internal/environment-detection.js.map +1 -0
  63. package/dist/src/bridge/internal/environment-detection.test.d.ts +7 -0
  64. package/dist/src/bridge/internal/environment-detection.test.d.ts.map +1 -0
  65. package/dist/src/bridge/internal/environment-detection.test.js +150 -0
  66. package/dist/src/bridge/internal/environment-detection.test.js.map +1 -0
  67. package/dist/src/bridge/internal/hand-off.d.ts +69 -0
  68. package/dist/src/bridge/internal/hand-off.d.ts.map +1 -0
  69. package/dist/src/bridge/internal/hand-off.js +178 -0
  70. package/dist/src/bridge/internal/hand-off.js.map +1 -0
  71. package/dist/src/bridge/internal/hand-off.test.d.ts +7 -0
  72. package/dist/src/bridge/internal/hand-off.test.d.ts.map +1 -0
  73. package/dist/src/bridge/internal/hand-off.test.js +325 -0
  74. package/dist/src/bridge/internal/hand-off.test.js.map +1 -0
  75. package/dist/src/bridge/internal/health-endpoint.d.ts +32 -0
  76. package/dist/src/bridge/internal/health-endpoint.d.ts.map +1 -0
  77. package/dist/src/bridge/internal/health-endpoint.js +73 -0
  78. package/dist/src/bridge/internal/health-endpoint.js.map +1 -0
  79. package/dist/src/bridge/internal/health-endpoint.test.d.ts +6 -0
  80. package/dist/src/bridge/internal/health-endpoint.test.d.ts.map +1 -0
  81. package/dist/src/bridge/internal/health-endpoint.test.js +122 -0
  82. package/dist/src/bridge/internal/health-endpoint.test.js.map +1 -0
  83. package/dist/src/bridge/internal/host-protocol.d.ts +60 -0
  84. package/dist/src/bridge/internal/host-protocol.d.ts.map +1 -0
  85. package/dist/src/bridge/internal/host-protocol.js +184 -0
  86. package/dist/src/bridge/internal/host-protocol.js.map +1 -0
  87. package/dist/src/bridge/internal/host-protocol.test.d.ts +6 -0
  88. package/dist/src/bridge/internal/host-protocol.test.d.ts.map +1 -0
  89. package/dist/src/bridge/internal/host-protocol.test.js +307 -0
  90. package/dist/src/bridge/internal/host-protocol.test.js.map +1 -0
  91. package/dist/src/bridge/internal/session-tracker.d.ts +67 -0
  92. package/dist/src/bridge/internal/session-tracker.d.ts.map +1 -0
  93. package/dist/src/bridge/internal/session-tracker.js +138 -0
  94. package/dist/src/bridge/internal/session-tracker.js.map +1 -0
  95. package/dist/src/bridge/internal/session-tracker.test.d.ts +6 -0
  96. package/dist/src/bridge/internal/session-tracker.test.d.ts.map +1 -0
  97. package/dist/src/bridge/internal/session-tracker.test.js +342 -0
  98. package/dist/src/bridge/internal/session-tracker.test.js.map +1 -0
  99. package/dist/src/bridge/internal/transport-client.d.ts +43 -0
  100. package/dist/src/bridge/internal/transport-client.d.ts.map +1 -0
  101. package/dist/src/bridge/internal/transport-client.js +146 -0
  102. package/dist/src/bridge/internal/transport-client.js.map +1 -0
  103. package/dist/src/bridge/internal/transport-client.test.d.ts +6 -0
  104. package/dist/src/bridge/internal/transport-client.test.d.ts.map +1 -0
  105. package/dist/src/bridge/internal/transport-client.test.js +176 -0
  106. package/dist/src/bridge/internal/transport-client.test.js.map +1 -0
  107. package/dist/src/bridge/internal/transport-server.d.ts +59 -0
  108. package/dist/src/bridge/internal/transport-server.d.ts.map +1 -0
  109. package/dist/src/bridge/internal/transport-server.js +189 -0
  110. package/dist/src/bridge/internal/transport-server.js.map +1 -0
  111. package/dist/src/bridge/internal/transport-server.test.d.ts +6 -0
  112. package/dist/src/bridge/internal/transport-server.test.d.ts.map +1 -0
  113. package/dist/src/bridge/internal/transport-server.test.js +171 -0
  114. package/dist/src/bridge/internal/transport-server.test.js.map +1 -0
  115. package/dist/src/bridge/types.d.ts +117 -0
  116. package/dist/src/bridge/types.d.ts.map +1 -0
  117. package/dist/src/bridge/types.js +68 -0
  118. package/dist/src/bridge/types.js.map +1 -0
  119. package/dist/src/cli/adapters/cli-command-adapter-handler.test.d.ts +6 -0
  120. package/dist/src/cli/adapters/cli-command-adapter-handler.test.d.ts.map +1 -0
  121. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js +260 -0
  122. package/dist/src/cli/adapters/cli-command-adapter-handler.test.js.map +1 -0
  123. package/dist/src/cli/adapters/cli-command-adapter.d.ts +39 -0
  124. package/dist/src/cli/adapters/cli-command-adapter.d.ts.map +1 -0
  125. package/dist/src/cli/adapters/cli-command-adapter.js +241 -0
  126. package/dist/src/cli/adapters/cli-command-adapter.js.map +1 -0
  127. package/dist/src/cli/adapters/cli-command-adapter.test.d.ts +5 -0
  128. package/dist/src/cli/adapters/cli-command-adapter.test.d.ts.map +1 -0
  129. package/dist/src/cli/adapters/cli-command-adapter.test.js +188 -0
  130. package/dist/src/cli/adapters/cli-command-adapter.test.js.map +1 -0
  131. package/dist/src/cli/adapters/group-builder.d.ts +29 -0
  132. package/dist/src/cli/adapters/group-builder.d.ts.map +1 -0
  133. package/dist/src/cli/adapters/group-builder.js +54 -0
  134. package/dist/src/cli/adapters/group-builder.js.map +1 -0
  135. package/dist/src/cli/adapters/group-builder.test.d.ts +5 -0
  136. package/dist/src/cli/adapters/group-builder.test.d.ts.map +1 -0
  137. package/dist/src/cli/adapters/group-builder.test.js +108 -0
  138. package/dist/src/cli/adapters/group-builder.test.js.map +1 -0
  139. package/dist/src/cli/adapters/help-formatter.d.ts +11 -0
  140. package/dist/src/cli/adapters/help-formatter.d.ts.map +1 -0
  141. package/dist/src/cli/adapters/help-formatter.js +78 -0
  142. package/dist/src/cli/adapters/help-formatter.js.map +1 -0
  143. package/dist/src/cli/adapters/help-formatter.test.d.ts +5 -0
  144. package/dist/src/cli/adapters/help-formatter.test.d.ts.map +1 -0
  145. package/dist/src/cli/adapters/help-formatter.test.js +79 -0
  146. package/dist/src/cli/adapters/help-formatter.test.js.map +1 -0
  147. package/dist/src/cli/adapters/target-resolver.d.ts +54 -0
  148. package/dist/src/cli/adapters/target-resolver.d.ts.map +1 -0
  149. package/dist/src/cli/adapters/target-resolver.js +90 -0
  150. package/dist/src/cli/adapters/target-resolver.js.map +1 -0
  151. package/dist/src/cli/adapters/target-resolver.test.d.ts +5 -0
  152. package/dist/src/cli/adapters/target-resolver.test.d.ts.map +1 -0
  153. package/dist/src/cli/adapters/target-resolver.test.js +169 -0
  154. package/dist/src/cli/adapters/target-resolver.test.js.map +1 -0
  155. package/dist/src/cli/args/global-args.d.ts +2 -0
  156. package/dist/src/cli/args/global-args.d.ts.map +1 -1
  157. package/dist/src/cli/cli.d.ts +6 -3
  158. package/dist/src/cli/cli.d.ts.map +1 -1
  159. package/dist/src/cli/cli.js +82 -20
  160. package/dist/src/cli/cli.js.map +1 -1
  161. package/dist/src/cli/resolve-script-content.d.ts +19 -0
  162. package/dist/src/cli/resolve-script-content.d.ts.map +1 -0
  163. package/dist/src/cli/resolve-script-content.js +22 -0
  164. package/dist/src/cli/resolve-script-content.js.map +1 -0
  165. package/dist/src/cli/resolve-session.d.ts +21 -0
  166. package/dist/src/cli/resolve-session.d.ts.map +1 -0
  167. package/dist/src/cli/resolve-session.js +40 -0
  168. package/dist/src/cli/resolve-session.js.map +1 -0
  169. package/dist/src/cli/resolve-session.test.d.ts +5 -0
  170. package/dist/src/cli/resolve-session.test.d.ts.map +1 -0
  171. package/dist/src/cli/resolve-session.test.js +112 -0
  172. package/dist/src/cli/resolve-session.test.js.map +1 -0
  173. package/dist/src/cli/script-executor.d.ts +1 -0
  174. package/dist/src/cli/script-executor.d.ts.map +1 -1
  175. package/dist/src/cli/script-executor.js +7 -1
  176. package/dist/src/cli/script-executor.js.map +1 -1
  177. package/dist/src/cli/types.d.ts +11 -0
  178. package/dist/src/cli/types.d.ts.map +1 -0
  179. package/dist/src/cli/types.js +5 -0
  180. package/dist/src/cli/types.js.map +1 -0
  181. package/dist/src/commands/connect.d.ts +16 -0
  182. package/dist/src/commands/connect.d.ts.map +1 -0
  183. package/dist/src/commands/connect.js +15 -0
  184. package/dist/src/commands/connect.js.map +1 -0
  185. package/dist/src/commands/connect.test.d.ts +5 -0
  186. package/dist/src/commands/connect.test.d.ts.map +1 -0
  187. package/dist/src/commands/connect.test.js +46 -0
  188. package/dist/src/commands/connect.test.js.map +1 -0
  189. package/dist/src/commands/console/exec/exec.d.ts +43 -0
  190. package/dist/src/commands/console/exec/exec.d.ts.map +1 -0
  191. package/dist/src/commands/console/exec/exec.js +79 -0
  192. package/dist/src/commands/console/exec/exec.js.map +1 -0
  193. package/dist/src/commands/console/exec/exec.test.d.ts +5 -0
  194. package/dist/src/commands/console/exec/exec.test.d.ts.map +1 -0
  195. package/dist/src/commands/console/exec/exec.test.js +191 -0
  196. package/dist/src/commands/console/exec/exec.test.js.map +1 -0
  197. package/dist/src/commands/console/logs/logs.d.ts +23 -0
  198. package/dist/src/commands/console/logs/logs.d.ts.map +1 -0
  199. package/dist/src/commands/console/logs/logs.js +80 -0
  200. package/dist/src/commands/console/logs/logs.js.map +1 -0
  201. package/dist/src/commands/console/logs/logs.test.d.ts +5 -0
  202. package/dist/src/commands/console/logs/logs.test.d.ts.map +1 -0
  203. package/dist/src/commands/console/logs/logs.test.js +111 -0
  204. package/dist/src/commands/console/logs/logs.test.js.map +1 -0
  205. package/dist/src/commands/disconnect.d.ts +9 -0
  206. package/dist/src/commands/disconnect.d.ts.map +1 -0
  207. package/dist/src/commands/disconnect.js +8 -0
  208. package/dist/src/commands/disconnect.js.map +1 -0
  209. package/dist/src/commands/disconnect.test.d.ts +5 -0
  210. package/dist/src/commands/disconnect.test.d.ts.map +1 -0
  211. package/dist/src/commands/disconnect.test.js +17 -0
  212. package/dist/src/commands/disconnect.test.js.map +1 -0
  213. package/dist/src/commands/explorer/query/query.d.ts +31 -0
  214. package/dist/src/commands/explorer/query/query.d.ts.map +1 -0
  215. package/dist/src/commands/explorer/query/query.js +106 -0
  216. package/dist/src/commands/explorer/query/query.js.map +1 -0
  217. package/dist/src/commands/explorer/query/query.test.d.ts +5 -0
  218. package/dist/src/commands/explorer/query/query.test.d.ts.map +1 -0
  219. package/dist/src/commands/explorer/query/query.test.js +228 -0
  220. package/dist/src/commands/explorer/query/query.test.js.map +1 -0
  221. package/dist/src/commands/formatters.test.d.ts +6 -0
  222. package/dist/src/commands/formatters.test.d.ts.map +1 -0
  223. package/dist/src/commands/formatters.test.js +211 -0
  224. package/dist/src/commands/formatters.test.js.map +1 -0
  225. package/dist/src/commands/framework/action-loader.d.ts +25 -0
  226. package/dist/src/commands/framework/action-loader.d.ts.map +1 -0
  227. package/dist/src/commands/framework/action-loader.js +46 -0
  228. package/dist/src/commands/framework/action-loader.js.map +1 -0
  229. package/dist/src/commands/framework/action-loader.test.d.ts +5 -0
  230. package/dist/src/commands/framework/action-loader.test.d.ts.map +1 -0
  231. package/dist/src/commands/framework/action-loader.test.js +89 -0
  232. package/dist/src/commands/framework/action-loader.test.js.map +1 -0
  233. package/dist/src/commands/framework/arg-builder.d.ts +92 -0
  234. package/dist/src/commands/framework/arg-builder.d.ts.map +1 -0
  235. package/dist/src/commands/framework/arg-builder.js +137 -0
  236. package/dist/src/commands/framework/arg-builder.js.map +1 -0
  237. package/dist/src/commands/framework/arg-builder.test.d.ts +5 -0
  238. package/dist/src/commands/framework/arg-builder.test.d.ts.map +1 -0
  239. package/dist/src/commands/framework/arg-builder.test.js +246 -0
  240. package/dist/src/commands/framework/arg-builder.test.js.map +1 -0
  241. package/dist/src/commands/framework/command-registry.d.ts +23 -0
  242. package/dist/src/commands/framework/command-registry.d.ts.map +1 -0
  243. package/dist/src/commands/framework/command-registry.js +42 -0
  244. package/dist/src/commands/framework/command-registry.js.map +1 -0
  245. package/dist/src/commands/framework/command-registry.test.d.ts +5 -0
  246. package/dist/src/commands/framework/command-registry.test.d.ts.map +1 -0
  247. package/dist/src/commands/framework/command-registry.test.js +158 -0
  248. package/dist/src/commands/framework/command-registry.test.js.map +1 -0
  249. package/dist/src/commands/framework/define-command.d.ts +76 -0
  250. package/dist/src/commands/framework/define-command.d.ts.map +1 -0
  251. package/dist/src/commands/framework/define-command.js +28 -0
  252. package/dist/src/commands/framework/define-command.js.map +1 -0
  253. package/dist/src/commands/framework/define-command.test.d.ts +5 -0
  254. package/dist/src/commands/framework/define-command.test.d.ts.map +1 -0
  255. package/dist/src/commands/framework/define-command.test.js +135 -0
  256. package/dist/src/commands/framework/define-command.test.js.map +1 -0
  257. package/dist/src/commands/framework/index.d.ts +8 -0
  258. package/dist/src/commands/framework/index.d.ts.map +1 -0
  259. package/dist/src/commands/framework/index.js +8 -0
  260. package/dist/src/commands/framework/index.js.map +1 -0
  261. package/dist/src/commands/index.d.ts +20 -0
  262. package/dist/src/commands/index.d.ts.map +1 -0
  263. package/dist/src/commands/index.js +20 -0
  264. package/dist/src/commands/index.js.map +1 -0
  265. package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts +15 -0
  266. package/dist/src/commands/linux/inject-credentials/inject-credentials.d.ts.map +1 -0
  267. package/dist/src/commands/linux/inject-credentials/inject-credentials.js +88 -0
  268. package/dist/src/commands/linux/inject-credentials/inject-credentials.js.map +1 -0
  269. package/dist/src/commands/linux/setup/setup.d.ts +19 -0
  270. package/dist/src/commands/linux/setup/setup.d.ts.map +1 -0
  271. package/dist/src/commands/linux/setup/setup.js +107 -0
  272. package/dist/src/commands/linux/setup/setup.js.map +1 -0
  273. package/dist/src/commands/linux/status/status.d.ts +34 -0
  274. package/dist/src/commands/linux/status/status.d.ts.map +1 -0
  275. package/dist/src/commands/linux/status/status.js +134 -0
  276. package/dist/src/commands/linux/status/status.js.map +1 -0
  277. package/dist/src/commands/plugin/install/install.d.ts +10 -0
  278. package/dist/src/commands/plugin/install/install.d.ts.map +1 -0
  279. package/dist/src/commands/plugin/install/install.js +23 -0
  280. package/dist/src/commands/plugin/install/install.js.map +1 -0
  281. package/dist/src/commands/plugin/uninstall/uninstall.d.ts +9 -0
  282. package/dist/src/commands/plugin/uninstall/uninstall.d.ts.map +1 -0
  283. package/dist/src/commands/plugin/uninstall/uninstall.js +41 -0
  284. package/dist/src/commands/plugin/uninstall/uninstall.js.map +1 -0
  285. package/dist/src/commands/process/close/close.d.ts +22 -0
  286. package/dist/src/commands/process/close/close.d.ts.map +1 -0
  287. package/dist/src/commands/process/close/close.js +34 -0
  288. package/dist/src/commands/process/close/close.js.map +1 -0
  289. package/dist/src/commands/process/format-state.d.ts +7 -0
  290. package/dist/src/commands/process/format-state.d.ts.map +1 -0
  291. package/dist/src/commands/process/format-state.js +19 -0
  292. package/dist/src/commands/process/format-state.js.map +1 -0
  293. package/dist/src/commands/process/info/info.d.ts +17 -0
  294. package/dist/src/commands/process/info/info.d.ts.map +1 -0
  295. package/dist/src/commands/process/info/info.js +38 -0
  296. package/dist/src/commands/process/info/info.js.map +1 -0
  297. package/dist/src/commands/process/info/info.test.d.ts +5 -0
  298. package/dist/src/commands/process/info/info.test.d.ts.map +1 -0
  299. package/dist/src/commands/process/info/info.test.js +58 -0
  300. package/dist/src/commands/process/info/info.test.js.map +1 -0
  301. package/dist/src/commands/process/launch/launch.d.ts +17 -0
  302. package/dist/src/commands/process/launch/launch.d.ts.map +1 -0
  303. package/dist/src/commands/process/launch/launch.js +26 -0
  304. package/dist/src/commands/process/launch/launch.js.map +1 -0
  305. package/dist/src/commands/process/launch/launch.test.d.ts +5 -0
  306. package/dist/src/commands/process/launch/launch.test.d.ts.map +1 -0
  307. package/dist/src/commands/process/launch/launch.test.js +49 -0
  308. package/dist/src/commands/process/launch/launch.test.js.map +1 -0
  309. package/dist/src/commands/process/list/list.d.ts +16 -0
  310. package/dist/src/commands/process/list/list.d.ts.map +1 -0
  311. package/dist/src/commands/process/list/list.js +56 -0
  312. package/dist/src/commands/process/list/list.js.map +1 -0
  313. package/dist/src/commands/process/list/list.test.d.ts +5 -0
  314. package/dist/src/commands/process/list/list.test.d.ts.map +1 -0
  315. package/dist/src/commands/process/list/list.test.js +71 -0
  316. package/dist/src/commands/process/list/list.test.js.map +1 -0
  317. package/dist/src/commands/process/run/run.d.ts +31 -0
  318. package/dist/src/commands/process/run/run.d.ts.map +1 -0
  319. package/dist/src/commands/process/run/run.js +63 -0
  320. package/dist/src/commands/process/run/run.js.map +1 -0
  321. package/dist/src/commands/rgba-to-png.d.ts +17 -0
  322. package/dist/src/commands/rgba-to-png.d.ts.map +1 -0
  323. package/dist/src/commands/rgba-to-png.js +85 -0
  324. package/dist/src/commands/rgba-to-png.js.map +1 -0
  325. package/dist/src/commands/serve/serve.d.ts +17 -0
  326. package/dist/src/commands/serve/serve.d.ts.map +1 -0
  327. package/dist/src/commands/serve/serve.js +128 -0
  328. package/dist/src/commands/serve/serve.js.map +1 -0
  329. package/dist/src/commands/serve/serve.test.d.ts +5 -0
  330. package/dist/src/commands/serve/serve.test.d.ts.map +1 -0
  331. package/dist/src/commands/serve/serve.test.js +100 -0
  332. package/dist/src/commands/serve/serve.test.js.map +1 -0
  333. package/dist/src/commands/viewport/screenshot/screenshot.d.ts +17 -0
  334. package/dist/src/commands/viewport/screenshot/screenshot.d.ts.map +1 -0
  335. package/dist/src/commands/viewport/screenshot/screenshot.js +45 -0
  336. package/dist/src/commands/viewport/screenshot/screenshot.js.map +1 -0
  337. package/dist/src/commands/viewport/screenshot/screenshot.test.d.ts +5 -0
  338. package/dist/src/commands/viewport/screenshot/screenshot.test.d.ts.map +1 -0
  339. package/dist/src/commands/viewport/screenshot/screenshot.test.js +143 -0
  340. package/dist/src/commands/viewport/screenshot/screenshot.test.js.map +1 -0
  341. package/dist/src/docker/docker-delegator.d.ts +30 -0
  342. package/dist/src/docker/docker-delegator.d.ts.map +1 -0
  343. package/dist/src/docker/docker-delegator.js +201 -0
  344. package/dist/src/docker/docker-delegator.js.map +1 -0
  345. package/dist/src/docker/docker-delegator.test.d.ts +2 -0
  346. package/dist/src/docker/docker-delegator.test.d.ts.map +1 -0
  347. package/dist/src/docker/docker-delegator.test.js +132 -0
  348. package/dist/src/docker/docker-delegator.test.js.map +1 -0
  349. package/dist/src/index.d.ts +9 -2
  350. package/dist/src/index.d.ts.map +1 -1
  351. package/dist/src/index.js +6 -1
  352. package/dist/src/index.js.map +1 -1
  353. package/dist/src/index.test.d.ts +2 -0
  354. package/dist/src/index.test.d.ts.map +1 -0
  355. package/dist/src/index.test.js +51 -0
  356. package/dist/src/index.test.js.map +1 -0
  357. package/dist/src/linux/index.d.ts +12 -0
  358. package/dist/src/linux/index.d.ts.map +1 -0
  359. package/dist/src/linux/index.js +11 -0
  360. package/dist/src/linux/index.js.map +1 -0
  361. package/dist/src/linux/linux-config.d.ts +37 -0
  362. package/dist/src/linux/linux-config.d.ts.map +1 -0
  363. package/dist/src/linux/linux-config.js +70 -0
  364. package/dist/src/linux/linux-config.js.map +1 -0
  365. package/dist/src/linux/linux-config.test.d.ts +2 -0
  366. package/dist/src/linux/linux-config.test.d.ts.map +1 -0
  367. package/dist/src/linux/linux-config.test.js +54 -0
  368. package/dist/src/linux/linux-config.test.js.map +1 -0
  369. package/dist/src/linux/linux-credential-writer.d.ts +35 -0
  370. package/dist/src/linux/linux-credential-writer.d.ts.map +1 -0
  371. package/dist/src/linux/linux-credential-writer.js +300 -0
  372. package/dist/src/linux/linux-credential-writer.js.map +1 -0
  373. package/dist/src/linux/linux-display-manager.d.ts +24 -0
  374. package/dist/src/linux/linux-display-manager.d.ts.map +1 -0
  375. package/dist/src/linux/linux-display-manager.js +92 -0
  376. package/dist/src/linux/linux-display-manager.js.map +1 -0
  377. package/dist/src/linux/linux-env-guard.d.ts +13 -0
  378. package/dist/src/linux/linux-env-guard.d.ts.map +1 -0
  379. package/dist/src/linux/linux-env-guard.js +31 -0
  380. package/dist/src/linux/linux-env-guard.js.map +1 -0
  381. package/dist/src/linux/linux-env-guard.test.d.ts +2 -0
  382. package/dist/src/linux/linux-env-guard.test.d.ts.map +1 -0
  383. package/dist/src/linux/linux-env-guard.test.js +48 -0
  384. package/dist/src/linux/linux-env-guard.test.js.map +1 -0
  385. package/dist/src/linux/linux-fflags.d.ts +17 -0
  386. package/dist/src/linux/linux-fflags.d.ts.map +1 -0
  387. package/dist/src/linux/linux-fflags.js +33 -0
  388. package/dist/src/linux/linux-fflags.js.map +1 -0
  389. package/dist/src/linux/linux-fflags.test.d.ts +2 -0
  390. package/dist/src/linux/linux-fflags.test.d.ts.map +1 -0
  391. package/dist/src/linux/linux-fflags.test.js +55 -0
  392. package/dist/src/linux/linux-fflags.test.js.map +1 -0
  393. package/dist/src/linux/linux-prerequisites.d.ts +24 -0
  394. package/dist/src/linux/linux-prerequisites.d.ts.map +1 -0
  395. package/dist/src/linux/linux-prerequisites.js +118 -0
  396. package/dist/src/linux/linux-prerequisites.js.map +1 -0
  397. package/dist/src/linux/linux-shader-patcher.d.ts +17 -0
  398. package/dist/src/linux/linux-shader-patcher.d.ts.map +1 -0
  399. package/dist/src/linux/linux-shader-patcher.js +48 -0
  400. package/dist/src/linux/linux-shader-patcher.js.map +1 -0
  401. package/dist/src/linux/linux-shader-patcher.test.d.ts +2 -0
  402. package/dist/src/linux/linux-shader-patcher.test.d.ts.map +1 -0
  403. package/dist/src/linux/linux-shader-patcher.test.js +55 -0
  404. package/dist/src/linux/linux-shader-patcher.test.js.map +1 -0
  405. package/dist/src/linux/linux-studio-installer.d.ts +10 -0
  406. package/dist/src/linux/linux-studio-installer.d.ts.map +1 -0
  407. package/dist/src/linux/linux-studio-installer.js +79 -0
  408. package/dist/src/linux/linux-studio-installer.js.map +1 -0
  409. package/dist/src/linux/linux-studio-launcher.d.ts +10 -0
  410. package/dist/src/linux/linux-studio-launcher.d.ts.map +1 -0
  411. package/dist/src/linux/linux-studio-launcher.js +73 -0
  412. package/dist/src/linux/linux-studio-launcher.js.map +1 -0
  413. package/dist/src/linux/linux-version-resolver.d.ts +18 -0
  414. package/dist/src/linux/linux-version-resolver.d.ts.map +1 -0
  415. package/dist/src/linux/linux-version-resolver.js +49 -0
  416. package/dist/src/linux/linux-version-resolver.js.map +1 -0
  417. package/dist/src/linux/linux-wine-env.d.ts +11 -0
  418. package/dist/src/linux/linux-wine-env.d.ts.map +1 -0
  419. package/dist/src/linux/linux-wine-env.js +33 -0
  420. package/dist/src/linux/linux-wine-env.js.map +1 -0
  421. package/dist/src/linux/linux-wine-env.test.d.ts +2 -0
  422. package/dist/src/linux/linux-wine-env.test.d.ts.map +1 -0
  423. package/dist/src/linux/linux-wine-env.test.js +47 -0
  424. package/dist/src/linux/linux-wine-env.test.js.map +1 -0
  425. package/dist/src/plugin/persistent-plugin-installer.d.ts +21 -0
  426. package/dist/src/plugin/persistent-plugin-installer.d.ts.map +1 -0
  427. package/dist/src/plugin/persistent-plugin-installer.js +69 -0
  428. package/dist/src/plugin/persistent-plugin-installer.js.map +1 -0
  429. package/dist/src/plugin/persistent-plugin-installer.test.d.ts +5 -0
  430. package/dist/src/plugin/persistent-plugin-installer.test.d.ts.map +1 -0
  431. package/dist/src/plugin/persistent-plugin-installer.test.js +119 -0
  432. package/dist/src/plugin/persistent-plugin-installer.test.js.map +1 -0
  433. package/dist/src/plugin/plugin-discovery.d.ts +7 -0
  434. package/dist/src/plugin/plugin-discovery.d.ts.map +1 -0
  435. package/dist/src/plugin/plugin-discovery.js +18 -0
  436. package/dist/src/plugin/plugin-discovery.js.map +1 -0
  437. package/dist/src/plugin/plugin-discovery.test.d.ts +5 -0
  438. package/dist/src/plugin/plugin-discovery.test.d.ts.map +1 -0
  439. package/dist/src/plugin/plugin-discovery.test.js +55 -0
  440. package/dist/src/plugin/plugin-discovery.test.js.map +1 -0
  441. package/dist/src/plugin/plugin-injector.js +1 -1
  442. package/dist/src/plugin/plugin-injector.js.map +1 -1
  443. package/dist/src/process/studio-process-manager.d.ts +7 -3
  444. package/dist/src/process/studio-process-manager.d.ts.map +1 -1
  445. package/dist/src/process/studio-process-manager.js +40 -11
  446. package/dist/src/process/studio-process-manager.js.map +1 -1
  447. package/dist/src/process/studio-process-manager.test.js +18 -1
  448. package/dist/src/process/studio-process-manager.test.js.map +1 -1
  449. package/dist/src/server/action-dispatcher.d.ts +35 -0
  450. package/dist/src/server/action-dispatcher.d.ts.map +1 -0
  451. package/dist/src/server/action-dispatcher.js +67 -0
  452. package/dist/src/server/action-dispatcher.js.map +1 -0
  453. package/dist/src/server/action-dispatcher.test.d.ts +6 -0
  454. package/dist/src/server/action-dispatcher.test.d.ts.map +1 -0
  455. package/dist/src/server/action-dispatcher.test.js +173 -0
  456. package/dist/src/server/action-dispatcher.test.js.map +1 -0
  457. package/dist/src/server/index.d.ts +1 -1
  458. package/dist/src/server/index.d.ts.map +1 -1
  459. package/dist/src/server/pending-request-map.d.ts +33 -0
  460. package/dist/src/server/pending-request-map.d.ts.map +1 -0
  461. package/dist/src/server/pending-request-map.js +69 -0
  462. package/dist/src/server/pending-request-map.js.map +1 -0
  463. package/dist/src/server/pending-request-map.test.d.ts +2 -0
  464. package/dist/src/server/pending-request-map.test.d.ts.map +1 -0
  465. package/dist/src/server/pending-request-map.test.js +192 -0
  466. package/dist/src/server/pending-request-map.test.js.map +1 -0
  467. package/dist/src/server/plugin-detection.test.d.ts +7 -0
  468. package/dist/src/server/plugin-detection.test.d.ts.map +1 -0
  469. package/dist/src/server/plugin-detection.test.js +154 -0
  470. package/dist/src/server/plugin-detection.test.js.map +1 -0
  471. package/dist/src/server/studio-bridge-server.d.ts +44 -7
  472. package/dist/src/server/studio-bridge-server.d.ts.map +1 -1
  473. package/dist/src/server/studio-bridge-server.js +341 -91
  474. package/dist/src/server/studio-bridge-server.js.map +1 -1
  475. package/dist/src/server/studio-bridge-server.test.js +231 -207
  476. package/dist/src/server/studio-bridge-server.test.js.map +1 -1
  477. package/dist/src/server/web-socket-protocol-basic.test.d.ts +2 -0
  478. package/dist/src/server/web-socket-protocol-basic.test.d.ts.map +1 -0
  479. package/dist/src/server/web-socket-protocol-basic.test.js +98 -0
  480. package/dist/src/server/web-socket-protocol-basic.test.js.map +1 -0
  481. package/dist/src/server/web-socket-protocol.d.ts +218 -20
  482. package/dist/src/server/web-socket-protocol.d.ts.map +1 -1
  483. package/dist/src/server/web-socket-protocol.js +346 -20
  484. package/dist/src/server/web-socket-protocol.js.map +1 -1
  485. package/dist/src/server/web-socket-protocol.test.js +572 -146
  486. package/dist/src/server/web-socket-protocol.test.js.map +1 -1
  487. package/dist/src/test/e2e/hand-off.test.d.ts +9 -0
  488. package/dist/src/test/e2e/hand-off.test.d.ts.map +1 -0
  489. package/dist/src/test/e2e/hand-off.test.js +274 -0
  490. package/dist/src/test/e2e/hand-off.test.js.map +1 -0
  491. package/dist/src/test/e2e/persistent-session.test.d.ts +11 -0
  492. package/dist/src/test/e2e/persistent-session.test.d.ts.map +1 -0
  493. package/dist/src/test/e2e/persistent-session.test.js +367 -0
  494. package/dist/src/test/e2e/persistent-session.test.js.map +1 -0
  495. package/dist/src/test/e2e/split-server.test.d.ts +14 -0
  496. package/dist/src/test/e2e/split-server.test.d.ts.map +1 -0
  497. package/dist/src/test/e2e/split-server.test.js +230 -0
  498. package/dist/src/test/e2e/split-server.test.js.map +1 -0
  499. package/dist/src/test/helpers/mock-plugin-client.d.ts +69 -0
  500. package/dist/src/test/helpers/mock-plugin-client.d.ts.map +1 -0
  501. package/dist/src/test/helpers/mock-plugin-client.js +213 -0
  502. package/dist/src/test/helpers/mock-plugin-client.js.map +1 -0
  503. package/dist/tsconfig.tsbuildinfo +1 -1
  504. package/docker/.dockerignore +2 -0
  505. package/docker/Dockerfile +113 -0
  506. package/docker/docker-compose.yml +20 -0
  507. package/docker/entrypoint.sh +19 -0
  508. package/package.json +8 -6
  509. package/src/bridge/bridge-connection-remote.test.ts +189 -0
  510. package/src/bridge/bridge-connection.test.ts +1076 -0
  511. package/src/bridge/bridge-connection.ts +718 -0
  512. package/src/bridge/bridge-session.test.ts +336 -0
  513. package/src/bridge/bridge-session.ts +365 -0
  514. package/src/bridge/index.ts +42 -0
  515. package/src/bridge/internal/__tests__/failover-crash.test.ts +191 -0
  516. package/src/bridge/internal/__tests__/failover-graceful.test.ts +268 -0
  517. package/src/bridge/internal/__tests__/failover-inflight.test.ts +329 -0
  518. package/src/bridge/internal/__tests__/host-client-integration.test.ts +387 -0
  519. package/src/bridge/internal/bridge-client.test.ts +399 -0
  520. package/src/bridge/internal/bridge-client.ts +434 -0
  521. package/src/bridge/internal/bridge-host.test.ts +501 -0
  522. package/src/bridge/internal/bridge-host.ts +531 -0
  523. package/src/bridge/internal/environment-detection.test.ts +180 -0
  524. package/src/bridge/internal/environment-detection.ts +119 -0
  525. package/src/bridge/internal/hand-off.test.ts +408 -0
  526. package/src/bridge/internal/hand-off.ts +275 -0
  527. package/src/bridge/internal/health-endpoint.test.ts +147 -0
  528. package/src/bridge/internal/health-endpoint.ts +100 -0
  529. package/src/bridge/internal/host-protocol.test.ts +415 -0
  530. package/src/bridge/internal/host-protocol.ts +255 -0
  531. package/src/bridge/internal/session-tracker.test.ts +535 -0
  532. package/src/bridge/internal/session-tracker.ts +198 -0
  533. package/src/bridge/internal/transport-client.test.ts +241 -0
  534. package/src/bridge/internal/transport-client.ts +194 -0
  535. package/src/bridge/internal/transport-server.test.ts +220 -0
  536. package/src/bridge/internal/transport-server.ts +242 -0
  537. package/src/bridge/types.ts +161 -0
  538. package/src/cli/adapters/cli-command-adapter-handler.test.ts +318 -0
  539. package/src/cli/adapters/cli-command-adapter.test.ts +221 -0
  540. package/src/cli/adapters/cli-command-adapter.ts +342 -0
  541. package/src/cli/adapters/group-builder.test.ts +146 -0
  542. package/src/cli/adapters/group-builder.ts +81 -0
  543. package/src/cli/adapters/help-formatter.test.ts +97 -0
  544. package/src/cli/adapters/help-formatter.ts +86 -0
  545. package/src/cli/adapters/target-resolver.test.ts +222 -0
  546. package/src/cli/adapters/target-resolver.ts +144 -0
  547. package/src/cli/args/global-args.ts +2 -0
  548. package/src/cli/cli.ts +100 -21
  549. package/src/cli/resolve-script-content.ts +36 -0
  550. package/src/cli/resolve-session.test.ts +141 -0
  551. package/src/cli/resolve-session.ts +66 -0
  552. package/src/cli/script-executor.ts +22 -4
  553. package/src/cli/types.ts +11 -0
  554. package/src/commands/connect.test.ts +61 -0
  555. package/src/commands/connect.ts +32 -0
  556. package/src/commands/console/exec/exec.test.ts +258 -0
  557. package/src/commands/console/exec/exec.ts +130 -0
  558. package/src/commands/console/exec/execute.luau +202 -0
  559. package/src/commands/console/logs/logs.test.ts +138 -0
  560. package/src/commands/console/logs/logs.ts +115 -0
  561. package/src/commands/console/logs/query-logs.luau +76 -0
  562. package/src/commands/disconnect.test.ts +21 -0
  563. package/src/commands/disconnect.ts +12 -0
  564. package/src/commands/explorer/query/query-data-model.luau +206 -0
  565. package/src/commands/explorer/query/query.test.ts +297 -0
  566. package/src/commands/explorer/query/query.ts +157 -0
  567. package/src/commands/formatters.test.ts +237 -0
  568. package/src/commands/framework/action-loader.test.ts +118 -0
  569. package/src/commands/framework/action-loader.ts +65 -0
  570. package/src/commands/framework/arg-builder.test.ts +298 -0
  571. package/src/commands/framework/arg-builder.ts +203 -0
  572. package/src/commands/framework/command-registry.test.ts +204 -0
  573. package/src/commands/framework/command-registry.ts +51 -0
  574. package/src/commands/framework/define-command.test.ts +161 -0
  575. package/src/commands/framework/define-command.ts +114 -0
  576. package/src/commands/framework/index.ts +33 -0
  577. package/src/commands/index.ts +72 -0
  578. package/src/commands/linux/inject-credentials/inject-credentials.ts +118 -0
  579. package/src/commands/linux/setup/setup.ts +145 -0
  580. package/src/commands/linux/status/status.ts +180 -0
  581. package/src/commands/plugin/install/install.ts +31 -0
  582. package/src/commands/plugin/uninstall/uninstall.ts +54 -0
  583. package/src/commands/process/close/close.ts +52 -0
  584. package/src/commands/process/format-state.ts +21 -0
  585. package/src/commands/process/info/info.test.ts +76 -0
  586. package/src/commands/process/info/info.ts +54 -0
  587. package/src/commands/process/info/query-state.luau +48 -0
  588. package/src/commands/process/launch/launch.test.ts +65 -0
  589. package/src/commands/process/launch/launch.ts +45 -0
  590. package/src/commands/process/list/list.test.ts +82 -0
  591. package/src/commands/process/list/list.ts +75 -0
  592. package/src/commands/process/run/run.ts +98 -0
  593. package/src/commands/rgba-to-png.ts +98 -0
  594. package/src/commands/serve/serve.test.ts +139 -0
  595. package/src/commands/serve/serve.ts +161 -0
  596. package/src/commands/viewport/screenshot/capture-screenshot.luau +247 -0
  597. package/src/commands/viewport/screenshot/screenshot.test.ts +181 -0
  598. package/src/commands/viewport/screenshot/screenshot.ts +71 -0
  599. package/src/docker/docker-delegator.test.ts +159 -0
  600. package/src/docker/docker-delegator.ts +240 -0
  601. package/src/index.test.ts +58 -0
  602. package/src/index.ts +104 -3
  603. package/src/linux/README.md +130 -0
  604. package/src/linux/index.ts +25 -0
  605. package/src/linux/linux-config.test.ts +66 -0
  606. package/src/linux/linux-config.ts +102 -0
  607. package/src/linux/linux-credential-writer.ts +421 -0
  608. package/src/linux/linux-display-manager.ts +106 -0
  609. package/src/linux/linux-env-guard.test.ts +62 -0
  610. package/src/linux/linux-env-guard.ts +38 -0
  611. package/src/linux/linux-fflags.test.ts +78 -0
  612. package/src/linux/linux-fflags.ts +48 -0
  613. package/src/linux/linux-prerequisites.ts +152 -0
  614. package/src/linux/linux-shader-patcher.test.ts +76 -0
  615. package/src/linux/linux-shader-patcher.ts +56 -0
  616. package/src/linux/linux-studio-installer.ts +113 -0
  617. package/src/linux/linux-studio-launcher.ts +90 -0
  618. package/src/linux/linux-version-resolver.ts +74 -0
  619. package/src/linux/linux-wine-env.test.ts +56 -0
  620. package/src/linux/linux-wine-env.ts +38 -0
  621. package/src/linux/write-cred.c +48 -0
  622. package/src/plugin/persistent-plugin-installer.test.ts +171 -0
  623. package/src/plugin/persistent-plugin-installer.ts +90 -0
  624. package/src/plugin/plugin-discovery.test.ts +70 -0
  625. package/src/plugin/plugin-discovery.ts +21 -0
  626. package/src/plugin/plugin-injector.ts +1 -1
  627. package/src/process/studio-process-manager.test.ts +22 -1
  628. package/src/process/studio-process-manager.ts +59 -18
  629. package/src/server/action-dispatcher.test.ts +240 -0
  630. package/src/server/action-dispatcher.ts +89 -0
  631. package/src/server/index.ts +0 -3
  632. package/src/server/pending-request-map.test.ts +261 -0
  633. package/src/server/pending-request-map.ts +87 -0
  634. package/src/server/plugin-detection.test.ts +195 -0
  635. package/src/server/studio-bridge-server.test.ts +321 -283
  636. package/src/server/studio-bridge-server.ts +469 -111
  637. package/src/server/web-socket-protocol-basic.test.ts +131 -0
  638. package/src/server/web-socket-protocol.test.ts +658 -159
  639. package/src/server/web-socket-protocol.ts +668 -58
  640. package/src/test/e2e/hand-off.test.ts +338 -0
  641. package/src/test/e2e/persistent-session.test.ts +442 -0
  642. package/src/test/e2e/split-server.test.ts +290 -0
  643. package/src/test/helpers/mock-plugin-client.ts +276 -0
  644. package/templates/studio-bridge-plugin/src/Shared/ActionRouter.luau +245 -0
  645. package/templates/studio-bridge-plugin/src/Shared/DiscoveryStateMachine.luau +203 -0
  646. package/templates/studio-bridge-plugin/src/Shared/MessageBuffer.luau +144 -0
  647. package/templates/studio-bridge-plugin/src/Shared/Protocol.luau +132 -0
  648. package/templates/studio-bridge-plugin/src/StudioBridgePlugin.server.lua +364 -133
  649. package/templates/studio-bridge-plugin/src/Vendor/png.luau +1247 -0
  650. package/templates/studio-bridge-plugin-test/test/actions.test.luau +580 -0
  651. package/templates/studio-bridge-plugin-test/test/discovery.test.luau +622 -0
  652. package/templates/studio-bridge-plugin-test/test/execute-handler.test.luau +406 -0
  653. package/templates/studio-bridge-plugin-test/test/hash-lifecycle.test.luau +814 -0
  654. package/templates/studio-bridge-plugin-test/test/integration.test.luau +1020 -0
  655. package/templates/studio-bridge-plugin-test/test/new-actions.test.luau +339 -0
  656. package/templates/studio-bridge-plugin-test/test/plugin-entry.test.luau +493 -0
  657. package/templates/studio-bridge-plugin-test/test/protocol.test.luau +506 -0
  658. package/templates/studio-bridge-plugin-test/test/roblox-mocks.luau +108 -0
  659. package/templates/studio-bridge-plugin-test/test/test-runner.luau +112 -0
  660. package/dist/src/cli/commands/exec-command.d.ts +0 -15
  661. package/dist/src/cli/commands/exec-command.d.ts.map +0 -1
  662. package/dist/src/cli/commands/exec-command.js +0 -35
  663. package/dist/src/cli/commands/exec-command.js.map +0 -1
  664. package/dist/src/cli/commands/run-command.d.ts +0 -15
  665. package/dist/src/cli/commands/run-command.d.ts.map +0 -1
  666. package/dist/src/cli/commands/run-command.js +0 -47
  667. package/dist/src/cli/commands/run-command.js.map +0 -1
  668. package/dist/src/cli/commands/terminal/terminal-command.d.ts +0 -17
  669. package/dist/src/cli/commands/terminal/terminal-command.d.ts.map +0 -1
  670. package/dist/src/cli/commands/terminal/terminal-command.js +0 -41
  671. package/dist/src/cli/commands/terminal/terminal-command.js.map +0 -1
  672. package/dist/src/cli/commands/terminal/terminal-editor.d.ts +0 -43
  673. package/dist/src/cli/commands/terminal/terminal-editor.d.ts.map +0 -1
  674. package/dist/src/cli/commands/terminal/terminal-editor.js +0 -430
  675. package/dist/src/cli/commands/terminal/terminal-editor.js.map +0 -1
  676. package/dist/src/cli/commands/terminal/terminal-mode.d.ts +0 -13
  677. package/dist/src/cli/commands/terminal/terminal-mode.d.ts.map +0 -1
  678. package/dist/src/cli/commands/terminal/terminal-mode.js +0 -141
  679. package/dist/src/cli/commands/terminal/terminal-mode.js.map +0 -1
  680. package/dist/src/server/web-socket-protocol.smoke.test.d.ts +0 -6
  681. package/dist/src/server/web-socket-protocol.smoke.test.d.ts.map +0 -1
  682. package/dist/src/server/web-socket-protocol.smoke.test.js +0 -196
  683. package/dist/src/server/web-socket-protocol.smoke.test.js.map +0 -1
  684. package/src/cli/commands/exec-command.ts +0 -48
  685. package/src/cli/commands/run-command.ts +0 -63
  686. package/src/cli/commands/terminal/terminal-command.ts +0 -54
  687. package/src/cli/commands/terminal/terminal-editor.ts +0 -500
  688. package/src/cli/commands/terminal/terminal-mode.ts +0 -184
  689. package/src/server/web-socket-protocol.smoke.test.ts +0 -255
@@ -0,0 +1,531 @@
1
+ /**
2
+ * Bridge host that manages plugin connections. Creates a TransportServer
3
+ * and registers handlers for the /plugin and /health paths. Tracks
4
+ * connected plugins by sessionId and emits events on connect/disconnect.
5
+ */
6
+
7
+ import { EventEmitter } from 'events';
8
+ import { randomUUID } from 'crypto';
9
+ import type { WebSocket, RawData } from 'ws';
10
+ import type { IncomingMessage } from 'http';
11
+ import { TransportServer } from './transport-server.js';
12
+ import { createHealthHandler } from './health-endpoint.js';
13
+ import {
14
+ decodeHostMessage,
15
+ encodeHostMessage,
16
+ type HostProtocolMessage,
17
+ type HostTransferNotice,
18
+ } from './host-protocol.js';
19
+ import {
20
+ decodePluginMessage,
21
+ encodeMessage,
22
+ type Capability,
23
+ type ServerMessage,
24
+ } from '../../server/web-socket-protocol.js';
25
+ import { PendingRequestMap } from '../../server/pending-request-map.js';
26
+ import { OutputHelper } from '@quenty/cli-output-helpers';
27
+
28
+ export interface BridgeHostOptions {
29
+ /** Port to bind on. Default: 38741. Use 0 for ephemeral (test-friendly). */
30
+ port?: number;
31
+ /** Host to bind on. Default: 'localhost'. */
32
+ host?: string;
33
+ }
34
+
35
+ export interface PluginSessionInfo {
36
+ sessionId: string;
37
+ pluginVersion?: string;
38
+ capabilities: Capability[];
39
+ /** Instance ID from register. */
40
+ instanceId?: string;
41
+ /** Place name from register. */
42
+ placeName?: string;
43
+ /** Studio state from register. */
44
+ state?: string;
45
+ /** Place file from register. */
46
+ placeFile?: string;
47
+ }
48
+
49
+ const SHUTDOWN_TIMEOUT_MS = 2_000;
50
+ const SHUTDOWN_DRAIN_MS = 250;
51
+
52
+ /**
53
+ * Per-plugin connection state. The `pendingRequests` map correlates outgoing
54
+ * requests to incoming responses by `requestId`. A single message dispatcher
55
+ * is installed per connection and routes through this map; this avoids the
56
+ * older per-call `ws.on('message', ...)` pattern, which both leaked listeners
57
+ * and could match the wrong response when ≥2 requests were in flight.
58
+ */
59
+ interface PluginConnectionState {
60
+ ws: WebSocket;
61
+ pendingRequests: PendingRequestMap<unknown>;
62
+ }
63
+
64
+ export class BridgeHost extends EventEmitter {
65
+ private _transport: TransportServer;
66
+ private _plugins: Map<string, PluginConnectionState> = new Map();
67
+ private _clients: Set<WebSocket> = new Set();
68
+ private _isRunning = false;
69
+ private _shuttingDown = false;
70
+ private _startTime = 0;
71
+ private _hostStartTime = 0;
72
+ private _lastFailoverAt: string | null = null;
73
+
74
+ constructor() {
75
+ super();
76
+ this._transport = new TransportServer();
77
+ }
78
+
79
+ /** Time (ms) since this process became the host. */
80
+ get hostUptime(): number {
81
+ if (this._hostStartTime === 0) {
82
+ return 0;
83
+ }
84
+ return Date.now() - this._hostStartTime;
85
+ }
86
+
87
+ /** ISO timestamp of the last failover event, or null if none. */
88
+ get lastFailoverAt(): string | null {
89
+ return this._lastFailoverAt;
90
+ }
91
+
92
+ markFailover(): void {
93
+ this._hostStartTime = Date.now();
94
+ this._lastFailoverAt = new Date().toISOString();
95
+ }
96
+
97
+ /** Returns the actual bound port. */
98
+ async startAsync(options?: BridgeHostOptions): Promise<number> {
99
+ if (this._isRunning) {
100
+ throw new Error('BridgeHost is already running');
101
+ }
102
+
103
+ this._startTime = Date.now();
104
+ if (this._hostStartTime === 0) {
105
+ this._hostStartTime = this._startTime;
106
+ }
107
+
108
+ // Register /plugin WebSocket handler — reject during shutdown
109
+ this._transport.onConnection('/plugin', (ws, request) => {
110
+ if (this._shuttingDown) {
111
+ ws.close(1001, 'host shutting down');
112
+ return;
113
+ }
114
+ this._handlePluginConnection(ws, request);
115
+ });
116
+
117
+ // Register /client WebSocket handler for CLI clients
118
+ this._transport.onConnection('/client', (ws) => {
119
+ this._clients.add(ws);
120
+
121
+ ws.on('message', (raw: RawData) => {
122
+ const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
123
+ const msg = decodeHostMessage(data);
124
+ if (!msg) {
125
+ return;
126
+ }
127
+ this.emit('client-message', msg, (reply: HostProtocolMessage) => {
128
+ ws.send(encodeHostMessage(reply));
129
+ });
130
+ });
131
+
132
+ ws.on('close', () => {
133
+ this._clients.delete(ws);
134
+ });
135
+ ws.on('error', () => {
136
+ // Errors are handled implicitly via close
137
+ });
138
+ });
139
+
140
+ // Register /health HTTP handler — returns 503 during shutdown so
141
+ // plugins don't rediscover a host that's about to close
142
+ this._transport.onHttpRequest('/health', (req, res) => {
143
+ if (this._shuttingDown) {
144
+ res.writeHead(503);
145
+ res.end();
146
+ return;
147
+ }
148
+ createHealthHandler(() => ({
149
+ port: this._transport.port,
150
+ sessions: this._plugins.size,
151
+ startTime: this._startTime,
152
+ hostStartTime: this._hostStartTime,
153
+ lastFailoverAt: this._lastFailoverAt,
154
+ }))(req, res);
155
+ });
156
+
157
+ const port = await this._transport.startAsync({
158
+ port: options?.port,
159
+ host: options?.host,
160
+ });
161
+
162
+ this._isRunning = true;
163
+ return port;
164
+ }
165
+
166
+ async stopAsync(): Promise<void> {
167
+ if (!this._isRunning) {
168
+ return;
169
+ }
170
+ this._isRunning = false;
171
+ this._cancelAllPending('host stopped');
172
+ this._plugins.clear();
173
+ this._clients.clear();
174
+ await this._transport.stopAsync();
175
+ }
176
+
177
+ /**
178
+ * Graceful shutdown: broadcast HostTransferNotice to all connected clients,
179
+ * wait briefly for them to process it, then close all connections and
180
+ * release the port. Idempotent — calling multiple times is safe.
181
+ *
182
+ * Wrapped in a timeout: if the graceful sequence exceeds 2 seconds, the
183
+ * transport is force-closed to ensure the port is freed.
184
+ */
185
+ async shutdownAsync(): Promise<void> {
186
+ if (this._shuttingDown) {
187
+ return;
188
+ }
189
+ this._shuttingDown = true;
190
+ OutputHelper.verbose(
191
+ `[host] shutdownAsync called (plugins: ${this._plugins.size}, clients: ${this._clients.size})`
192
+ );
193
+ OutputHelper.verbose(
194
+ `[host] shutdown stack: ${new Error().stack
195
+ ?.split('\n')
196
+ .slice(1, 5)
197
+ .map((s) => s.trim())
198
+ .join(' <- ')}`
199
+ );
200
+
201
+ const gracefulShutdown = async () => {
202
+ // Step 1: Broadcast HostTransferNotice to all CLI clients
203
+ const notice: HostTransferNotice = { type: 'host-transfer' };
204
+ const encoded = encodeHostMessage(notice);
205
+ for (const ws of this._clients) {
206
+ try {
207
+ ws.send(encoded);
208
+ } catch {
209
+ // Client may already be disconnected
210
+ }
211
+ }
212
+
213
+ // Step 1.5: Send shutdown message to all plugins so they disconnect
214
+ // cleanly instead of seeing a WebSocket error
215
+ for (const [sessionId, state] of this._plugins) {
216
+ try {
217
+ state.ws.send(
218
+ encodeMessage({
219
+ type: 'shutdown',
220
+ sessionId,
221
+ payload: {} as Record<string, never>,
222
+ })
223
+ );
224
+ } catch {
225
+ // Plugin may already be disconnected
226
+ }
227
+ }
228
+
229
+ // Step 2: Wait briefly for plugins/clients to process
230
+ await new Promise<void>((resolve) =>
231
+ setTimeout(resolve, SHUTDOWN_DRAIN_MS)
232
+ );
233
+
234
+ // Step 3: Send close frames to all plugins and clients
235
+ for (const state of this._plugins.values()) {
236
+ try {
237
+ state.ws.close(1001, 'host shutting down');
238
+ } catch {
239
+ // Ignore
240
+ }
241
+ }
242
+ for (const ws of this._clients) {
243
+ try {
244
+ ws.close(1001, 'host shutting down');
245
+ } catch {
246
+ // Ignore
247
+ }
248
+ }
249
+
250
+ // Step 4: Stop the transport
251
+ this._isRunning = false;
252
+ this._cancelAllPending('host shutting down');
253
+ this._plugins.clear();
254
+ this._clients.clear();
255
+ await this._transport.stopAsync();
256
+ };
257
+
258
+ // Wrap in timeout — force-close if graceful exceeds limit
259
+ const timeoutPromise = new Promise<'timeout'>((resolve) =>
260
+ setTimeout(() => resolve('timeout'), SHUTDOWN_TIMEOUT_MS)
261
+ );
262
+
263
+ const result = await Promise.race([
264
+ gracefulShutdown().then(() => 'done' as const),
265
+ timeoutPromise,
266
+ ]);
267
+
268
+ if (result === 'timeout') {
269
+ this._isRunning = false;
270
+ this._cancelAllPending('host force-closed');
271
+ this._plugins.clear();
272
+ this._clients.clear();
273
+ await this._transport.forceCloseAsync();
274
+ }
275
+ }
276
+
277
+ /** The actual port the server is bound to. */
278
+ get port(): number {
279
+ return this._transport.port;
280
+ }
281
+
282
+ /** Whether the host is currently running. */
283
+ get isRunning(): boolean {
284
+ return this._isRunning;
285
+ }
286
+
287
+ /** Number of connected plugin sessions. */
288
+ get pluginCount(): number {
289
+ return this._plugins.size;
290
+ }
291
+
292
+ broadcastToClients(msg: HostProtocolMessage): void {
293
+ const encoded = encodeHostMessage(msg);
294
+ for (const ws of this._clients) {
295
+ try {
296
+ ws.send(encoded);
297
+ } catch {
298
+ // Client may already be disconnected
299
+ }
300
+ }
301
+ }
302
+
303
+ async sendToPluginAsync<TResponse>(
304
+ sessionId: string,
305
+ message: ServerMessage,
306
+ timeoutMs: number
307
+ ): Promise<TResponse> {
308
+ const state = this._plugins.get(sessionId);
309
+ if (!state) {
310
+ throw new Error(`Plugin session '${sessionId}' not connected`);
311
+ }
312
+
313
+ // Every request must carry a requestId so the response can be correlated.
314
+ // All real callers (BridgeSession, BridgeClient) generate one; the fallback
315
+ // here is purely defensive.
316
+ const messageWithId = ensureRequestId(message);
317
+ const requestId = (messageWithId as { requestId: string }).requestId;
318
+ const msgType = messageWithId.type;
319
+
320
+ OutputHelper.verbose(
321
+ `[host] → plugin ${sessionId}: ${msgType} (requestId=${requestId.slice(
322
+ 0,
323
+ 8
324
+ )}, timeout ${timeoutMs}ms)`
325
+ );
326
+
327
+ const responsePromise = state.pendingRequests.addRequestAsync(
328
+ requestId,
329
+ timeoutMs
330
+ ) as Promise<TResponse>;
331
+
332
+ try {
333
+ state.ws.send(encodeMessage(messageWithId));
334
+ } catch (err) {
335
+ state.pendingRequests.rejectRequest(
336
+ requestId,
337
+ err instanceof Error ? err : new Error(String(err))
338
+ );
339
+ throw err;
340
+ }
341
+
342
+ return responsePromise;
343
+ }
344
+
345
+ /**
346
+ * Send a fire-and-forget message to a specific plugin.
347
+ */
348
+ sendToPlugin(sessionId: string, message: ServerMessage): void {
349
+ const state = this._plugins.get(sessionId);
350
+ if (!state) {
351
+ return;
352
+ }
353
+ try {
354
+ state.ws.send(encodeMessage(message));
355
+ } catch {
356
+ // Plugin may already be disconnected
357
+ }
358
+ }
359
+
360
+ private _handlePluginConnection(
361
+ ws: WebSocket,
362
+ _request: IncomingMessage
363
+ ): void {
364
+ const onMessage = (raw: RawData) => {
365
+ const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
366
+ const msg = decodePluginMessage(data);
367
+ if (!msg || msg.type !== 'register') {
368
+ return;
369
+ }
370
+
371
+ const sessionId = msg.sessionId;
372
+ const { pluginVersion, capabilities } = msg.payload;
373
+
374
+ ws.off('message', onMessage);
375
+ this._registerPlugin(ws, {
376
+ sessionId,
377
+ pluginVersion,
378
+ capabilities,
379
+ instanceId: msg.payload.instanceId,
380
+ placeName: msg.payload.placeName,
381
+ state: msg.payload.state,
382
+ placeFile: msg.payload.placeFile,
383
+ });
384
+ };
385
+
386
+ ws.on('message', onMessage);
387
+
388
+ ws.on('error', () => {
389
+ // Errors are handled implicitly via close
390
+ });
391
+ }
392
+
393
+ private _registerPlugin(ws: WebSocket, info: PluginSessionInfo): void {
394
+ // If a plugin with this sessionId is already connected, close the old
395
+ // connection first so the Map stays consistent. This can happen when a
396
+ // plugin reconnects faster than the host detects the old socket's close.
397
+ const existing = this._plugins.get(info.sessionId);
398
+ if (existing && existing.ws !== ws) {
399
+ try {
400
+ existing.ws.close(1001, 'replaced by new connection');
401
+ } catch {
402
+ // Old socket may already be dead
403
+ }
404
+ existing.pendingRequests.cancelAll(
405
+ 'plugin connection replaced by new session'
406
+ );
407
+ // Remove immediately so the old close handler doesn't delete the new entry
408
+ this._plugins.delete(info.sessionId);
409
+ }
410
+
411
+ const state: PluginConnectionState = {
412
+ ws,
413
+ pendingRequests: new PendingRequestMap<unknown>(),
414
+ };
415
+ this._plugins.set(info.sessionId, state);
416
+
417
+ // Install the persistent dispatcher on this connection. All plugin
418
+ // responses arrive through this listener; matched by requestId via the
419
+ // pending-request map.
420
+ ws.on('message', (raw: RawData) =>
421
+ this._dispatchPluginMessage(info.sessionId, state, raw)
422
+ );
423
+
424
+ OutputHelper.verbose(
425
+ `[host] Plugin connected: ${
426
+ info.sessionId
427
+ } (caps: ${info.capabilities.join(', ')})`
428
+ );
429
+ this.emit('plugin-connected', info);
430
+
431
+ ws.on('close', () => {
432
+ // Only remove if this socket is still the registered one — a newer
433
+ // connection with the same sessionId may have already replaced us.
434
+ const current = this._plugins.get(info.sessionId);
435
+ if (current && current.ws === ws) {
436
+ current.pendingRequests.cancelAll('plugin disconnected');
437
+ this._plugins.delete(info.sessionId);
438
+ OutputHelper.verbose(`[host] Plugin disconnected: ${info.sessionId}`);
439
+ this.emit('plugin-disconnected', info.sessionId);
440
+ }
441
+ });
442
+ }
443
+
444
+ /**
445
+ * Persistent per-connection message dispatcher. Routes responses to the
446
+ * pending-request map by `requestId`. Heartbeats and unsolicited messages
447
+ * are logged but otherwise ignored — there are no host-side consumers of
448
+ * push messages today.
449
+ */
450
+ private _dispatchPluginMessage(
451
+ sessionId: string,
452
+ state: PluginConnectionState,
453
+ raw: RawData
454
+ ): void {
455
+ const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
456
+
457
+ // Parse the raw JSON directly — decodePluginMessage's strict schema may
458
+ // reject valid responses we still want to surface to callers.
459
+ let parsed: { type?: unknown; requestId?: unknown; payload?: unknown };
460
+ try {
461
+ parsed = JSON.parse(data);
462
+ } catch {
463
+ return;
464
+ }
465
+
466
+ if (parsed.type === 'heartbeat') {
467
+ return;
468
+ }
469
+
470
+ const requestId =
471
+ typeof parsed.requestId === 'string' && parsed.requestId !== ''
472
+ ? parsed.requestId
473
+ : undefined;
474
+
475
+ if (requestId !== undefined) {
476
+ if (state.pendingRequests.hasPendingRequest(requestId)) {
477
+ OutputHelper.verbose(
478
+ `[host] ← plugin ${sessionId}: ${String(
479
+ parsed.type
480
+ )} (matched requestId=${requestId.slice(0, 8)})`
481
+ );
482
+ state.pendingRequests.resolveRequest(requestId, parsed);
483
+ return;
484
+ }
485
+ OutputHelper.verbose(
486
+ `[host] ← plugin ${sessionId}: dropped ${String(
487
+ parsed.type
488
+ )} for unknown requestId=${requestId.slice(0, 8)}`
489
+ );
490
+ return;
491
+ }
492
+
493
+ // No requestId: nothing to correlate against. Errors without a requestId
494
+ // mean the plugin couldn't even parse the inbound request, so there's no
495
+ // pending entry to fail. Surface as a log so failures aren't silent.
496
+ if (parsed.type === 'error') {
497
+ const payload = parsed.payload as
498
+ | { code?: string; message?: string }
499
+ | undefined;
500
+ OutputHelper.warn(
501
+ `[host] plugin ${sessionId} sent error without requestId (${
502
+ payload?.code ?? 'unknown'
503
+ }): ${payload?.message ?? ''}`
504
+ );
505
+ return;
506
+ }
507
+
508
+ OutputHelper.verbose(
509
+ `[host] ← plugin ${sessionId}: dropped unsolicited ${String(parsed.type)}`
510
+ );
511
+ }
512
+
513
+ private _cancelAllPending(reason: string): void {
514
+ for (const state of this._plugins.values()) {
515
+ state.pendingRequests.cancelAll(reason);
516
+ }
517
+ }
518
+ }
519
+
520
+ /**
521
+ * Ensure the outgoing message carries a `requestId`. All real callers
522
+ * (BridgeSession, BridgeClient) supply one; this is a defensive fallback
523
+ * so the strict-correlation path always has a key to match against.
524
+ */
525
+ function ensureRequestId(message: ServerMessage): ServerMessage {
526
+ const existing = (message as { requestId?: string }).requestId;
527
+ if (typeof existing === 'string' && existing !== '') {
528
+ return message;
529
+ }
530
+ return { ...message, requestId: randomUUID() } as ServerMessage;
531
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Unit tests for environment-detection -- validates role detection logic
3
+ * including host election on free port, client detection when host exists,
4
+ * remoteHost override, and devcontainer detection.
5
+ */
6
+
7
+ import { existsSync } from 'node:fs';
8
+ import { describe, it, expect, afterEach, beforeEach } from 'vitest';
9
+ import {
10
+ detectRoleAsync,
11
+ isDevcontainer,
12
+ getDefaultRemoteHost,
13
+ } from './environment-detection.js';
14
+ import { BridgeHost } from './bridge-host.js';
15
+
16
+ describe('detectRoleAsync', () => {
17
+ let bridgeHost: BridgeHost | undefined;
18
+
19
+ afterEach(async () => {
20
+ if (bridgeHost) {
21
+ await bridgeHost.stopAsync();
22
+ bridgeHost = undefined;
23
+ }
24
+ });
25
+
26
+ it('returns host role on a free ephemeral port', async () => {
27
+ const result = await detectRoleAsync({ port: 0 });
28
+
29
+ expect(result.role).toBe('host');
30
+ expect(result.port).toBeGreaterThan(0);
31
+ });
32
+
33
+ it('returns client role when remoteHost is specified', async () => {
34
+ const result = await detectRoleAsync({
35
+ port: 38741,
36
+ remoteHost: 'some-remote-host:38741',
37
+ });
38
+
39
+ expect(result.role).toBe('client');
40
+ expect(result.port).toBe(38741);
41
+ });
42
+
43
+ it('returns client role when a bridge host is already running', async () => {
44
+ // Start a real bridge host on an ephemeral port
45
+ bridgeHost = new BridgeHost();
46
+ const port = await bridgeHost.startAsync({ port: 0 });
47
+
48
+ const result = await detectRoleAsync({ port });
49
+
50
+ expect(result.role).toBe('client');
51
+ expect(result.port).toBe(port);
52
+ });
53
+
54
+ it('preserves the port from options in the result', async () => {
55
+ const result = await detectRoleAsync({
56
+ port: 12345,
57
+ remoteHost: 'localhost:12345',
58
+ });
59
+
60
+ expect(result.port).toBe(12345);
61
+ });
62
+
63
+ it('returns host role with the bound port when port is 0', async () => {
64
+ const result = await detectRoleAsync({ port: 0 });
65
+
66
+ // Ephemeral port should be assigned by the OS
67
+ expect(result.role).toBe('host');
68
+ expect(result.port).not.toBe(0);
69
+ expect(result.port).toBeGreaterThan(0);
70
+ });
71
+ });
72
+
73
+ const DEVCONTAINER_ENV_KEYS = [
74
+ 'REMOTE_CONTAINERS',
75
+ 'CODESPACES',
76
+ 'CONTAINER',
77
+ ] as const;
78
+ const dockerenvExists = existsSync('/.dockerenv');
79
+
80
+ describe('isDevcontainer', () => {
81
+ const savedEnv: Record<string, string | undefined> = {};
82
+
83
+ beforeEach(() => {
84
+ // Save current values so we can restore after each test
85
+ for (const key of DEVCONTAINER_ENV_KEYS) {
86
+ savedEnv[key] = process.env[key];
87
+ }
88
+ });
89
+
90
+ afterEach(() => {
91
+ // Restore original env values
92
+ for (const key of DEVCONTAINER_ENV_KEYS) {
93
+ if (savedEnv[key] === undefined) {
94
+ delete process.env[key];
95
+ } else {
96
+ process.env[key] = savedEnv[key];
97
+ }
98
+ }
99
+ });
100
+
101
+ function clearDevcontainerEnv(): void {
102
+ for (const key of DEVCONTAINER_ENV_KEYS) {
103
+ delete process.env[key];
104
+ }
105
+ }
106
+
107
+ it('returns true when REMOTE_CONTAINERS is set', () => {
108
+ clearDevcontainerEnv();
109
+ process.env.REMOTE_CONTAINERS = 'true';
110
+ expect(isDevcontainer()).toBe(true);
111
+ });
112
+
113
+ it('returns true when CODESPACES is set', () => {
114
+ clearDevcontainerEnv();
115
+ process.env.CODESPACES = 'true';
116
+ expect(isDevcontainer()).toBe(true);
117
+ });
118
+
119
+ it('returns true when CONTAINER is set', () => {
120
+ clearDevcontainerEnv();
121
+ process.env.CONTAINER = 'true';
122
+ expect(isDevcontainer()).toBe(true);
123
+ });
124
+
125
+ it('returns false when no env vars set and no /.dockerenv', () => {
126
+ clearDevcontainerEnv();
127
+ // If /.dockerenv exists on this machine, the function should still return true
128
+ expect(isDevcontainer()).toBe(dockerenvExists);
129
+ });
130
+
131
+ it('treats empty string as falsy', () => {
132
+ clearDevcontainerEnv();
133
+ process.env.REMOTE_CONTAINERS = '';
134
+ // Empty string is falsy -- result depends only on /.dockerenv
135
+ expect(isDevcontainer()).toBe(dockerenvExists);
136
+ });
137
+ });
138
+
139
+ describe('getDefaultRemoteHost', () => {
140
+ const savedEnv: Record<string, string | undefined> = {};
141
+
142
+ beforeEach(() => {
143
+ for (const key of DEVCONTAINER_ENV_KEYS) {
144
+ savedEnv[key] = process.env[key];
145
+ }
146
+ });
147
+
148
+ afterEach(() => {
149
+ for (const key of DEVCONTAINER_ENV_KEYS) {
150
+ if (savedEnv[key] === undefined) {
151
+ delete process.env[key];
152
+ } else {
153
+ process.env[key] = savedEnv[key];
154
+ }
155
+ }
156
+ });
157
+
158
+ function clearDevcontainerEnv(): void {
159
+ for (const key of DEVCONTAINER_ENV_KEYS) {
160
+ delete process.env[key];
161
+ }
162
+ }
163
+
164
+ it('returns localhost:38741 in devcontainer', () => {
165
+ clearDevcontainerEnv();
166
+ process.env.REMOTE_CONTAINERS = 'true';
167
+ expect(getDefaultRemoteHost()).toBe('localhost:38741');
168
+ });
169
+
170
+ it('returns null outside devcontainer', () => {
171
+ clearDevcontainerEnv();
172
+ // Only null if /.dockerenv doesn't exist
173
+ if (!dockerenvExists) {
174
+ expect(getDefaultRemoteHost()).toBeNull();
175
+ } else {
176
+ // If /.dockerenv exists, we're in a container, so it returns the host
177
+ expect(getDefaultRemoteHost()).toBe('localhost:38741');
178
+ }
179
+ });
180
+ });