@quenty/studio-bridge 0.7.0 → 0.8.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 +15 -39
  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 +109 -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 +38 -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 +168 -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 +57 -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,102 @@
1
+ /**
2
+ * Path resolution and configuration constants for running Roblox Studio
3
+ * under Wine on Linux.
4
+ */
5
+
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+
9
+ export interface LinuxStudioConfig {
10
+ /** Root directory of the Studio installation */
11
+ studioDir: string;
12
+ /** Wine prefix (usually ~/.wine) */
13
+ winePrefix: string;
14
+ /** X11 display number (e.g. ":99") */
15
+ display: string;
16
+ /** Path to the RobloxStudioBeta.exe within studioDir */
17
+ studioExe: string;
18
+ /** Path to ClientSettings/ClientAppSettings.json */
19
+ clientSettingsPath: string;
20
+ /** Path to the shaders directory */
21
+ shadersDir: string;
22
+ /** Path to the Plugins folder */
23
+ pluginsDir: string;
24
+ /** Path to write-cred.exe (compiled credential writer) */
25
+ writeCredExe: string;
26
+ }
27
+
28
+ /**
29
+ * Resolve all Linux/Wine paths from environment variables and defaults.
30
+ */
31
+ export function resolveLinuxConfig(): LinuxStudioConfig {
32
+ const studioDir =
33
+ process.env.STUDIO_DIR || path.join(os.homedir(), 'roblox-studio');
34
+
35
+ const winePrefix = process.env.WINEPREFIX || path.join(os.homedir(), '.wine');
36
+
37
+ const display = process.env.DISPLAY || ':99';
38
+
39
+ return {
40
+ studioDir,
41
+ winePrefix,
42
+ display,
43
+ studioExe: path.join(studioDir, 'RobloxStudioBeta.exe'),
44
+ clientSettingsPath: path.join(
45
+ studioDir,
46
+ 'ClientSettings',
47
+ 'ClientAppSettings.json'
48
+ ),
49
+ shadersDir: path.join(studioDir, 'shaders'),
50
+ pluginsDir: path.join(studioDir, 'Plugins'),
51
+ writeCredExe: path.join(studioDir, 'write-cred.exe'),
52
+ };
53
+ }
54
+
55
+ /** CDN base URL for Roblox Studio downloads */
56
+ export const ROBLOX_CDN_BASE = 'https://setup.rbxcdn.com';
57
+
58
+ /** Roblox API base for user info */
59
+ export const ROBLOX_USERS_API = 'https://users.roblox.com';
60
+
61
+ /**
62
+ * Package-to-directory mapping extracted from the Studio installer's
63
+ * .rdata section. Each key is a zip filename; value is the subdirectory
64
+ * within studioDir to extract into.
65
+ */
66
+ export const STUDIO_PACKAGES: Record<string, string> = {
67
+ 'ApplicationConfig.zip': 'ApplicationConfig/',
68
+ 'redist.zip': '',
69
+ 'RobloxStudio.zip': '',
70
+ 'Libraries.zip': '',
71
+ 'content-avatar.zip': 'content/avatar/',
72
+ 'content-configs.zip': 'content/configs/',
73
+ 'content-fonts.zip': 'content/fonts/',
74
+ 'content-sky.zip': 'content/sky/',
75
+ 'content-sounds.zip': 'content/sounds/',
76
+ 'content-textures2.zip': 'content/textures/',
77
+ 'content-studio_svg_textures.zip': 'content/studio_svg_textures/',
78
+ 'content-models.zip': 'content/models/',
79
+ 'content-textures3.zip': 'PlatformContent/pc/textures/',
80
+ 'content-terrain.zip': 'PlatformContent/pc/terrain/',
81
+ 'content-platform-fonts.zip': 'PlatformContent/pc/fonts/',
82
+ 'content-platform-dictionaries.zip':
83
+ 'PlatformContent/pc/shared_compression_dictionaries/',
84
+ 'content-qt_translations.zip': 'content/qt_translations/',
85
+ 'content-api-docs.zip': 'content/api_docs/',
86
+ 'extracontent-scripts.zip': 'ExtraContent/scripts/',
87
+ 'extracontent-luapackages.zip': 'ExtraContent/LuaPackages/',
88
+ 'extracontent-translations.zip': 'ExtraContent/translations/',
89
+ 'extracontent-models.zip': 'ExtraContent/models/',
90
+ 'extracontent-textures.zip': 'ExtraContent/textures/',
91
+ 'studiocontent-models.zip': 'StudioContent/models/',
92
+ 'studiocontent-textures.zip': 'StudioContent/textures/',
93
+ 'shaders.zip': 'shaders/',
94
+ 'BuiltInPlugins.zip': 'BuiltInPlugins/',
95
+ 'BuiltInStandalonePlugins.zip': 'BuiltInStandalonePlugins/',
96
+ 'LibrariesQt5.zip': '',
97
+ 'Plugins.zip': 'Plugins/',
98
+ 'StudioFonts.zip': 'StudioFonts/',
99
+ 'ssl.zip': 'ssl/',
100
+ 'WebView2.zip': '',
101
+ 'WebView2RuntimeInstaller.zip': 'WebView2RuntimeInstaller/',
102
+ };
@@ -0,0 +1,421 @@
1
+ /**
2
+ * Inject Roblox authentication credentials into Wine's Credential Manager.
3
+ *
4
+ * Studio expects three entries in Windows Credential Manager:
5
+ * 1. userid: RobloxStudioAuthuserid → numeric user ID
6
+ * 2. cookie name: RobloxStudioAuthCookies → ".ROBLOSECURITY"
7
+ * 3. cookie value: RobloxStudioAuth.ROBLOSECURITY{userId} → the actual cookie
8
+ *
9
+ * Additionally, Studio 0.710+ uses OAuth2 for startup authentication.
10
+ * Without a valid refresh token, Studio blocks on a WebView2 login dialog
11
+ * that doesn't work under Wine. This module obtains a refresh token by
12
+ * calling Roblox's first-party OAuth authorization endpoint with the
13
+ * .ROBLOSECURITY cookie, then injects it into the Credential Manager.
14
+ *
15
+ * This module:
16
+ * - Compiles write-cred.c with MinGW (if not already compiled)
17
+ * - Resolves the user ID from the cookie via Roblox API
18
+ * - Obtains an OAuth2 refresh token via Roblox's authorization endpoint
19
+ * - Runs `wine write-cred.exe` to inject all credential entries
20
+ */
21
+
22
+ import * as crypto from 'crypto';
23
+ import * as fs from 'fs/promises';
24
+ import * as path from 'path';
25
+ import { execFileSync } from 'child_process';
26
+ import { execa } from 'execa';
27
+ import { fileURLToPath } from 'url';
28
+ import { OutputHelper } from '@quenty/cli-output-helpers';
29
+ import { ROBLOX_USERS_API, type LinuxStudioConfig } from './linux-config.js';
30
+ import { buildWineEnv } from './linux-wine-env.js';
31
+ import { COOKIE_NAME } from '@quenty/nevermore-cli-helpers';
32
+
33
+ /** Studio's first-party OAuth client ID (extracted from the Studio binary) */
34
+ const STUDIO_OAUTH_CLIENT_ID = '7968549422692352298';
35
+
36
+ /** Roblox OAuth API base */
37
+ const ROBLOX_OAUTH_API = 'https://apis.roblox.com/oauth/v1';
38
+
39
+ /** Roblox Auth API base (for CSRF tokens) */
40
+ const ROBLOX_AUTH_API = 'https://auth.roblox.com';
41
+
42
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
43
+
44
+ /**
45
+ * Locate write-cred.c source file. Searches several candidate paths
46
+ * relative to __dirname, which at runtime is dist/src/linux/.
47
+ */
48
+ async function findWriteCredSourceAsync(): Promise<string> {
49
+ const candidates = [
50
+ // Alongside compiled JS (if .c was copied to dist)
51
+ path.join(__dirname, 'write-cred.c'),
52
+ // Source tree (from dist/src/linux/ → src/linux/)
53
+ path.resolve(__dirname, '../../../src/linux/write-cred.c'),
54
+ // Sibling to package root
55
+ path.resolve(__dirname, '../../linux/write-cred.c'),
56
+ ];
57
+
58
+ for (const candidate of candidates) {
59
+ try {
60
+ await fs.access(candidate);
61
+ return candidate;
62
+ } catch {
63
+ // Try next
64
+ }
65
+ }
66
+
67
+ throw new Error(
68
+ 'write-cred.c source not found. Ensure the linux module is properly installed.'
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Compile write-cred.exe from bundled C source using MinGW.
74
+ */
75
+ export async function compileWriteCredAsync(
76
+ config: LinuxStudioConfig
77
+ ): Promise<void> {
78
+ const { writeCredExe } = config;
79
+ const sourcePath = await findWriteCredSourceAsync();
80
+
81
+ OutputHelper.verbose(`Compiling ${sourcePath} → ${writeCredExe}`);
82
+
83
+ await fs.mkdir(path.dirname(writeCredExe), { recursive: true });
84
+
85
+ try {
86
+ execFileSync(
87
+ 'x86_64-w64-mingw32-gcc',
88
+ ['-o', writeCredExe, sourcePath, '-lcredui', '-ladvapi32'],
89
+ {
90
+ stdio: ['pipe', 'pipe', 'pipe'],
91
+ timeout: 30000,
92
+ }
93
+ );
94
+ } catch (error) {
95
+ throw new Error(
96
+ `Failed to compile write-cred.exe: ${
97
+ error instanceof Error ? error.message : error
98
+ }`
99
+ );
100
+ }
101
+
102
+ OutputHelper.verbose('write-cred.exe compiled successfully.');
103
+ }
104
+
105
+ interface InjectCredentialsOptions {
106
+ cookie: string;
107
+ config: LinuxStudioConfig;
108
+ }
109
+
110
+ /**
111
+ * Inject all three required credentials into Wine's Credential Manager.
112
+ */
113
+ export async function injectCredentialsAsync(
114
+ options: InjectCredentialsOptions
115
+ ): Promise<void> {
116
+ const { cookie, config } = options;
117
+
118
+ // Always recompile write-cred.exe from source to ensure it matches the
119
+ // current code (e.g. batch-mode support). A stale binary from a Docker
120
+ // image may silently ignore extra arguments.
121
+ await compileWriteCredAsync(config);
122
+
123
+ // Resolve user ID from cookie
124
+ const userId = await resolveUserIdAsync(cookie);
125
+ OutputHelper.verbose(`Resolved user ID: ${userId}`);
126
+
127
+ const env = buildWineEnv(config);
128
+ const writeCredExe = config.writeCredExe;
129
+
130
+ // Initialize or update the Wine prefix. wineboot must run before any wine
131
+ // command to create the prefix on first use, and must also run in containers
132
+ // where the prefix was pre-built at image time — the update pass refreshes
133
+ // stale registry entries and user profile paths for the current environment.
134
+ const prefixExists = await fs
135
+ .access(path.join(config.winePrefix, 'system.reg'))
136
+ .then(
137
+ () => true,
138
+ () => false
139
+ );
140
+ const winebootFlag = prefixExists ? '-u' : '-i';
141
+ OutputHelper.verbose(
142
+ prefixExists
143
+ ? 'Updating Wine prefix for current environment...'
144
+ : 'Initializing Wine prefix...'
145
+ );
146
+ const bootResult = await execa('wineboot', [winebootFlag], {
147
+ env,
148
+ reject: false,
149
+ timeout: 120000,
150
+ });
151
+ if (bootResult.exitCode !== 0) {
152
+ OutputHelper.warn(
153
+ `wineboot exited with code ${bootResult.exitCode} (non-fatal)`
154
+ );
155
+ }
156
+
157
+ // Write all three credential entries in a single Wine invocation
158
+ const entries: Array<[string, string]> = [
159
+ ['https://www.roblox.com:RobloxStudioAuthuserid', String(userId)],
160
+ ['https://www.roblox.com:RobloxStudioAuthCookies', COOKIE_NAME],
161
+ [`https://www.roblox.com:RobloxStudioAuth${COOKIE_NAME}${userId}`, cookie],
162
+ ];
163
+
164
+ OutputHelper.verbose(`Writing ${entries.length} credential entries...`);
165
+ const credArgs = entries.flatMap(([target, value]) => [target, value]);
166
+ const result = await execa('wine', [writeCredExe, ...credArgs], {
167
+ env,
168
+ reject: false,
169
+ timeout: 30000,
170
+ });
171
+
172
+ if (result.exitCode !== 0) {
173
+ const stderr = result.stderr || result.stdout || 'unknown error';
174
+ throw new Error(`Failed to write credentials: ${stderr}`);
175
+ }
176
+
177
+ // Also write to the Windows Registry path that Studio checks on startup.
178
+ await writeRegistryAuthAsync(cookie, userId, env);
179
+
180
+ // Obtain and inject an OAuth2 refresh token. Studio 0.710+ may require this
181
+ // for startup authentication — without it, Studio blocks on a WebView2
182
+ // login dialog that doesn't work under Wine. Non-fatal: cookie-based
183
+ // credentials above are sufficient for many Studio versions.
184
+ try {
185
+ await injectOAuth2RefreshTokenAsync(cookie, userId, writeCredExe, env);
186
+ } catch (error) {
187
+ OutputHelper.warn(
188
+ `OAuth2 refresh token injection failed (non-fatal): ${
189
+ error instanceof Error ? error.message : error
190
+ }`
191
+ );
192
+ }
193
+
194
+ OutputHelper.info('Credentials injected into Wine Credential Manager.');
195
+ }
196
+
197
+ /**
198
+ * Write auth data to Wine registry entries that Studio checks on startup.
199
+ * This bypasses Studio's WebView2 login dialog (which doesn't work on Wine).
200
+ */
201
+ async function writeRegistryAuthAsync(
202
+ cookie: string,
203
+ userId: number,
204
+ env: Record<string, string>
205
+ ): Promise<void> {
206
+ const regPath = 'HKCU\\Software\\Roblox\\RobloxStudioBrowser\\roblox.com';
207
+
208
+ const regEntries: Array<[string, string, string]> = [
209
+ [regPath, COOKIE_NAME, cookie],
210
+ ];
211
+
212
+ for (const [keyPath, name, value] of regEntries) {
213
+ OutputHelper.verbose(`Writing registry: ${keyPath}\\${name}`);
214
+ const result = await execa(
215
+ 'wine',
216
+ ['reg', 'add', keyPath, '/v', name, '/t', 'REG_SZ', '/d', value, '/f'],
217
+ { env, reject: false, timeout: 15000 }
218
+ );
219
+ if (result.exitCode !== 0) {
220
+ OutputHelper.warn(
221
+ `Failed to write registry entry ${name} (non-fatal): ${
222
+ result.stderr || result.stdout
223
+ }`
224
+ );
225
+ }
226
+ }
227
+
228
+ // Also set the user ID so Studio recognizes a configured user
229
+ const userRegPath = 'HKCU\\Software\\Roblox\\RobloxStudioBrowser';
230
+ const userIdResult = await execa(
231
+ 'wine',
232
+ [
233
+ 'reg',
234
+ 'add',
235
+ userRegPath,
236
+ '/v',
237
+ 'UserId',
238
+ '/t',
239
+ 'REG_SZ',
240
+ '/d',
241
+ String(userId),
242
+ '/f',
243
+ ],
244
+ { env, reject: false, timeout: 15000 }
245
+ );
246
+ if (userIdResult.exitCode !== 0) {
247
+ OutputHelper.warn(
248
+ `Failed to write UserId registry entry (non-fatal): ${
249
+ userIdResult.stderr || userIdResult.stdout
250
+ }`
251
+ );
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Obtain an OAuth2 refresh token from the .ROBLOSECURITY cookie and inject
257
+ * it into Wine's Credential Manager. This completes Studio's first-party
258
+ * OAuth PKCE flow programmatically, bypassing the WebView2 login dialog.
259
+ */
260
+ async function injectOAuth2RefreshTokenAsync(
261
+ cookie: string,
262
+ userId: number,
263
+ writeCredExe: string,
264
+ env: Record<string, string>
265
+ ): Promise<void> {
266
+ OutputHelper.verbose('Obtaining OAuth2 refresh token...');
267
+
268
+ // Step 1: Get CSRF token (Roblox requires this for mutating API calls)
269
+ const csrfToken = await getCsrfTokenAsync(cookie);
270
+
271
+ // Step 2: Generate PKCE code verifier and challenge
272
+ const codeVerifier = crypto
273
+ .randomBytes(32)
274
+ .toString('base64url')
275
+ .slice(0, 43);
276
+ const codeChallenge = crypto
277
+ .createHash('sha256')
278
+ .update(codeVerifier)
279
+ .digest('base64url');
280
+ const state = crypto.randomBytes(16).toString('hex');
281
+
282
+ // Step 3: Request authorization code
283
+ const authResponse = await fetch(`${ROBLOX_OAUTH_API}/authorizations`, {
284
+ method: 'POST',
285
+ headers: {
286
+ 'Content-Type': 'application/json',
287
+ 'X-CSRF-TOKEN': csrfToken,
288
+ Cookie: `${COOKIE_NAME}=${cookie}`,
289
+ },
290
+ body: JSON.stringify({
291
+ clientId: STUDIO_OAUTH_CLIENT_ID,
292
+ responseTypes: ['Code'],
293
+ redirectUri: 'roblox-studio-auth:/',
294
+ scopes: [
295
+ { scopeType: 'openid', operations: ['read'] },
296
+ { scopeType: 'credentials', operations: ['read'] },
297
+ { scopeType: 'profile', operations: ['read'] },
298
+ { scopeType: 'age', operations: ['read'] },
299
+ { scopeType: 'roles', operations: ['read'] },
300
+ { scopeType: 'premium', operations: ['read'] },
301
+ ],
302
+ nonce: 'id-roblox',
303
+ codeChallengeMethod: 's256',
304
+ codeChallenge,
305
+ state,
306
+ }),
307
+ });
308
+
309
+ if (!authResponse.ok) {
310
+ const body = await authResponse.text();
311
+ throw new Error(
312
+ `OAuth authorization failed: ${authResponse.status} ${body}`
313
+ );
314
+ }
315
+
316
+ const authData = (await authResponse.json()) as { location: string };
317
+ const locationUrl = new URL(authData.location);
318
+ const authCode = locationUrl.searchParams.get('code');
319
+ if (!authCode) {
320
+ throw new Error('OAuth authorization response missing code');
321
+ }
322
+
323
+ OutputHelper.verbose('OAuth authorization code obtained.');
324
+
325
+ // Step 4: Exchange authorization code for tokens
326
+ const tokenResponse = await fetch(`${ROBLOX_OAUTH_API}/token`, {
327
+ method: 'POST',
328
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
329
+ body: new URLSearchParams({
330
+ grant_type: 'authorization_code',
331
+ code: authCode,
332
+ code_verifier: codeVerifier,
333
+ client_id: STUDIO_OAUTH_CLIENT_ID,
334
+ }).toString(),
335
+ });
336
+
337
+ if (!tokenResponse.ok) {
338
+ const body = await tokenResponse.text();
339
+ throw new Error(
340
+ `OAuth token exchange failed: ${tokenResponse.status} ${body}`
341
+ );
342
+ }
343
+
344
+ const tokenData = (await tokenResponse.json()) as {
345
+ refresh_token: string;
346
+ access_token: string;
347
+ };
348
+
349
+ if (!tokenData.refresh_token) {
350
+ throw new Error('OAuth token response missing refresh_token');
351
+ }
352
+
353
+ OutputHelper.verbose(
354
+ `OAuth refresh token obtained (${tokenData.refresh_token.length} chars).`
355
+ );
356
+
357
+ // Step 5: Inject the refresh token into Wine's Credential Manager
358
+ const target = `https://www.roblox.com:RobloxStudioAuthoauth2RefreshToken${userId}`;
359
+ OutputHelper.verbose(`Writing OAuth2 credential: ${target}`);
360
+ const result = await execa(
361
+ 'wine',
362
+ [writeCredExe, target, tokenData.refresh_token],
363
+ { env, reject: false, timeout: 15000 }
364
+ );
365
+
366
+ if (result.exitCode !== 0) {
367
+ const stderr = result.stderr || result.stdout || 'unknown error';
368
+ throw new Error(
369
+ `Failed to write OAuth2 refresh token credential: ${stderr}`
370
+ );
371
+ }
372
+
373
+ OutputHelper.verbose(
374
+ 'OAuth2 refresh token injected into Wine Credential Manager.'
375
+ );
376
+ }
377
+
378
+ /**
379
+ * Get a CSRF token from Roblox's auth API. The first request returns 403
380
+ * with the token in the x-csrf-token header.
381
+ */
382
+ async function getCsrfTokenAsync(cookie: string): Promise<string> {
383
+ const response = await fetch(`${ROBLOX_AUTH_API}/v1/authentication-ticket/`, {
384
+ method: 'POST',
385
+ headers: {
386
+ 'Content-Type': 'application/json',
387
+ Cookie: `${COOKIE_NAME}=${cookie}`,
388
+ Referer: 'https://www.roblox.com/',
389
+ },
390
+ body: '{}',
391
+ });
392
+
393
+ const csrfToken = response.headers.get('x-csrf-token');
394
+ if (!csrfToken) {
395
+ throw new Error(
396
+ `Failed to obtain CSRF token: ${response.status} ${response.statusText}`
397
+ );
398
+ }
399
+
400
+ return csrfToken;
401
+ }
402
+
403
+ /**
404
+ * Resolve the authenticated user's numeric ID from a .ROBLOSECURITY cookie.
405
+ */
406
+ async function resolveUserIdAsync(cookie: string): Promise<number> {
407
+ const response = await fetch(`${ROBLOX_USERS_API}/v1/users/authenticated`, {
408
+ headers: {
409
+ Cookie: `${COOKIE_NAME}=${cookie}`,
410
+ },
411
+ });
412
+
413
+ if (!response.ok) {
414
+ throw new Error(
415
+ `Failed to resolve user ID: ${response.status} ${response.statusText}. Is your cookie valid?`
416
+ );
417
+ }
418
+
419
+ const data = (await response.json()) as { id: number };
420
+ return data.id;
421
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Manage the Xvfb virtual framebuffer and openbox window manager
3
+ * required for Studio to render under Wine.
4
+ */
5
+
6
+ import { execSync } from 'child_process';
7
+ import { execa } from 'execa';
8
+ import type { LinuxStudioConfig } from './linux-config.js';
9
+
10
+ /**
11
+ * Ensure Xvfb is running on the configured DISPLAY.
12
+ * If already running, this is a no-op.
13
+ */
14
+ export async function ensureDisplayAsync(
15
+ config: LinuxStudioConfig
16
+ ): Promise<void> {
17
+ const display = config.display;
18
+ const displayNum = display.replace(':', '');
19
+
20
+ if (isXvfbRunning(displayNum)) {
21
+ return;
22
+ }
23
+
24
+ // Start Xvfb detached with 1024x768 24-bit color
25
+ const xvfb = execa('Xvfb', [display, '-screen', '0', '1024x768x24'], {
26
+ detached: true,
27
+ stdio: 'ignore',
28
+ reject: false,
29
+ env: { ...process.env },
30
+ });
31
+ xvfb.unref?.();
32
+
33
+ // Give it a moment to start
34
+ await sleepAsync(500);
35
+
36
+ if (!isXvfbRunning(displayNum)) {
37
+ throw new Error(`Failed to start Xvfb on display ${display}`);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Ensure openbox window manager is running on the display.
43
+ * Required for Studio's modal dialogs to function.
44
+ */
45
+ export async function ensureWindowManagerAsync(
46
+ config: LinuxStudioConfig
47
+ ): Promise<void> {
48
+ if (isOpenboxRunning()) {
49
+ return;
50
+ }
51
+
52
+ const openbox = execa('openbox', [], {
53
+ detached: true,
54
+ stdio: 'ignore',
55
+ reject: false,
56
+ env: {
57
+ ...process.env,
58
+ DISPLAY: config.display,
59
+ },
60
+ });
61
+ openbox.unref?.();
62
+
63
+ await sleepAsync(500);
64
+ }
65
+
66
+ /**
67
+ * Check if Xvfb is running on a given display.
68
+ */
69
+ export function isXvfbRunning(displayNum?: string): boolean {
70
+ try {
71
+ if (displayNum) {
72
+ const output = execSync(`pgrep -a Xvfb`, {
73
+ encoding: 'utf-8',
74
+ timeout: 3000,
75
+ stdio: ['pipe', 'pipe', 'pipe'],
76
+ });
77
+ return output.includes(`:${displayNum}`);
78
+ }
79
+ execSync('pgrep -x Xvfb', {
80
+ timeout: 3000,
81
+ stdio: ['pipe', 'pipe', 'pipe'],
82
+ });
83
+ return true;
84
+ } catch {
85
+ return false;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Check if openbox is running.
91
+ */
92
+ export function isOpenboxRunning(): boolean {
93
+ try {
94
+ execSync('pgrep -x openbox', {
95
+ timeout: 3000,
96
+ stdio: ['pipe', 'pipe', 'pipe'],
97
+ });
98
+ return true;
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ function sleepAsync(ms: number): Promise<void> {
105
+ return new Promise((resolve) => setTimeout(resolve, ms));
106
+ }
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+
3
+ vi.mock('os', () => ({
4
+ platform: vi.fn(),
5
+ }));
6
+
7
+ vi.mock('child_process', () => ({
8
+ execFile: vi.fn(),
9
+ }));
10
+
11
+ vi.mock('util', () => ({
12
+ promisify: (fn: any) => fn,
13
+ }));
14
+
15
+ import { platform } from 'os';
16
+ import { execFile } from 'child_process';
17
+ import { checkLinuxEnvironmentAsync } from './linux-env-guard.js';
18
+
19
+ const mockPlatform = vi.mocked(platform);
20
+ const mockExecFile = vi.mocked(execFile);
21
+
22
+ describe('checkLinuxEnvironmentAsync', () => {
23
+ beforeEach(() => {
24
+ vi.resetAllMocks();
25
+ });
26
+
27
+ it('returns an error message on non-Linux platforms', async () => {
28
+ mockPlatform.mockReturnValue('win32');
29
+
30
+ const result = await checkLinuxEnvironmentAsync();
31
+
32
+ expect(result).toBeDefined();
33
+ expect(result).toContain('linux commands require a Linux environment');
34
+ expect(result).toContain('studio-bridge process run');
35
+ expect(mockExecFile).not.toHaveBeenCalled();
36
+ });
37
+
38
+ it('returns undefined when on Linux with Wine installed', async () => {
39
+ mockPlatform.mockReturnValue('linux');
40
+ mockExecFile.mockResolvedValue({
41
+ stdout: '/usr/bin/wine\n',
42
+ stderr: '',
43
+ } as any);
44
+
45
+ const result = await checkLinuxEnvironmentAsync();
46
+
47
+ expect(result).toBeUndefined();
48
+ expect(mockExecFile).toHaveBeenCalledWith('which', ['wine']);
49
+ });
50
+
51
+ it('returns an error message on Linux without Wine', async () => {
52
+ mockPlatform.mockReturnValue('linux');
53
+ mockExecFile.mockRejectedValue(new Error('not found'));
54
+
55
+ const result = await checkLinuxEnvironmentAsync();
56
+
57
+ expect(result).toBeDefined();
58
+ expect(result).toContain('Wine is not installed');
59
+ expect(result).toContain('studio-bridge process run');
60
+ expect(result).toContain('docker run');
61
+ });
62
+ });