@jingyi0605/codingns4dsh 0.1.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 (312) hide show
  1. package/README.md +1114 -0
  2. package/assets/provider-icons/claude-code.png +0 -0
  3. package/assets/provider-icons/codex.png +0 -0
  4. package/assets/provider-icons/command-code.svg +5 -0
  5. package/assets/provider-icons/deepseek-harness.svg +9 -0
  6. package/assets/provider-icons/gemini.png +0 -0
  7. package/assets/provider-icons/grok.png +0 -0
  8. package/assets/provider-icons/kimi.png +0 -0
  9. package/assets/provider-icons/opencode.png +0 -0
  10. package/assets/provider-icons/pi.svg +7 -0
  11. package/data/build/dist/bootstrap/dsh-connection-adapter.d.ts +97 -0
  12. package/data/build/dist/bootstrap/dsh-connection-adapter.js +169 -0
  13. package/data/build/dist/bootstrap/index.d.ts +38 -0
  14. package/data/build/dist/bootstrap/index.js +44 -0
  15. package/data/build/dist/client/account-bar.d.ts +9 -0
  16. package/data/build/dist/client/account-bar.js +398 -0
  17. package/data/build/dist/client/bundle.js +26167 -0
  18. package/data/build/dist/client/cli-catalog.d.ts +24 -0
  19. package/data/build/dist/client/cli-catalog.js +108 -0
  20. package/data/build/dist/client/cli-slots.d.ts +38 -0
  21. package/data/build/dist/client/cli-slots.js +297 -0
  22. package/data/build/dist/client/debug/ui.d.ts +12 -0
  23. package/data/build/dist/client/debug/ui.js +451 -0
  24. package/data/build/dist/client/dsh-h5-bootstrap.d.ts +64 -0
  25. package/data/build/dist/client/dsh-h5-bootstrap.js +293 -0
  26. package/data/build/dist/client/dsh-runtime-version.d.ts +3 -0
  27. package/data/build/dist/client/dsh-runtime-version.js +11 -0
  28. package/data/build/dist/client/external-tool-stream.d.ts +24 -0
  29. package/data/build/dist/client/external-tool-stream.js +114 -0
  30. package/data/build/dist/client/features/cli-adapters.d.ts +7 -0
  31. package/data/build/dist/client/features/cli-adapters.js +215 -0
  32. package/data/build/dist/client/features/debug.d.ts +4 -0
  33. package/data/build/dist/client/features/debug.js +24 -0
  34. package/data/build/dist/client/features/index.d.ts +33 -0
  35. package/data/build/dist/client/features/index.js +44 -0
  36. package/data/build/dist/client/features/lan-access-panel.d.ts +5 -0
  37. package/data/build/dist/client/features/lan-access-panel.js +146 -0
  38. package/data/build/dist/client/features/lan-access.d.ts +9 -0
  39. package/data/build/dist/client/features/lan-access.js +30 -0
  40. package/data/build/dist/client/features/login-protection-panel.d.ts +5 -0
  41. package/data/build/dist/client/features/login-protection-panel.js +91 -0
  42. package/data/build/dist/client/features/login-protection-session.d.ts +6 -0
  43. package/data/build/dist/client/features/login-protection-session.js +25 -0
  44. package/data/build/dist/client/features/login-protection.d.ts +4 -0
  45. package/data/build/dist/client/features/login-protection.js +23 -0
  46. package/data/build/dist/client/features/reverse-proxy-panel.d.ts +9 -0
  47. package/data/build/dist/client/features/reverse-proxy-panel.js +159 -0
  48. package/data/build/dist/client/features/reverse-proxy.d.ts +12 -0
  49. package/data/build/dist/client/features/reverse-proxy.js +112 -0
  50. package/data/build/dist/client/features/terminal-enhancement-panel.d.ts +5 -0
  51. package/data/build/dist/client/features/terminal-enhancement-panel.js +160 -0
  52. package/data/build/dist/client/features/terminal-enhancement.d.ts +4 -0
  53. package/data/build/dist/client/features/terminal-enhancement.js +24 -0
  54. package/data/build/dist/client/features/types.d.ts +58 -0
  55. package/data/build/dist/client/features/types.js +2 -0
  56. package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts +5 -0
  57. package/data/build/dist/client/features/workspace-session-enhancement-panel.js +66 -0
  58. package/data/build/dist/client/features/workspace-session-enhancement.d.ts +4 -0
  59. package/data/build/dist/client/features/workspace-session-enhancement.js +101 -0
  60. package/data/build/dist/client/h5-bootstrap-entry.d.ts +2 -0
  61. package/data/build/dist/client/h5-bootstrap-entry.js +17 -0
  62. package/data/build/dist/client/index.d.ts +31 -0
  63. package/data/build/dist/client/index.js +98 -0
  64. package/data/build/dist/client/lan-access.d.ts +28 -0
  65. package/data/build/dist/client/lan-access.js +68 -0
  66. package/data/build/dist/client/locale.d.ts +20 -0
  67. package/data/build/dist/client/locale.js +393 -0
  68. package/data/build/dist/client/provider-icon-assets.d.ts +2 -0
  69. package/data/build/dist/client/provider-icon-assets.js +23 -0
  70. package/data/build/dist/client/provider-icons.d.ts +19 -0
  71. package/data/build/dist/client/provider-icons.js +39 -0
  72. package/data/build/dist/client/remote-web-context.d.ts +57 -0
  73. package/data/build/dist/client/remote-web-context.js +939 -0
  74. package/data/build/dist/client/session-adapter-cache.d.ts +18 -0
  75. package/data/build/dist/client/session-adapter-cache.js +84 -0
  76. package/data/build/dist/client/settings-bridge.d.ts +32 -0
  77. package/data/build/dist/client/settings-bridge.js +126 -0
  78. package/data/build/dist/client/settings-section.d.ts +30 -0
  79. package/data/build/dist/client/settings-section.js +93 -0
  80. package/data/build/dist/client/subscription-slot.d.ts +18 -0
  81. package/data/build/dist/client/subscription-slot.js +223 -0
  82. package/data/build/dist/client/terminal/index.d.ts +4 -0
  83. package/data/build/dist/client/terminal/index.js +3 -0
  84. package/data/build/dist/client/terminal/model.d.ts +116 -0
  85. package/data/build/dist/client/terminal/model.js +435 -0
  86. package/data/build/dist/client/terminal/styles.d.ts +21 -0
  87. package/data/build/dist/client/terminal/styles.js +51 -0
  88. package/data/build/dist/client/terminal/ui.d.ts +19 -0
  89. package/data/build/dist/client/terminal/ui.js +257 -0
  90. package/data/build/dist/client/terminal/xterm-view.d.ts +13 -0
  91. package/data/build/dist/client/terminal/xterm-view.js +213 -0
  92. package/data/build/dist/client/theme.d.ts +56 -0
  93. package/data/build/dist/client/theme.js +186 -0
  94. package/data/build/dist/client/workspace-session-archive-dom.d.ts +29 -0
  95. package/data/build/dist/client/workspace-session-archive-dom.js +525 -0
  96. package/data/build/dist/client/workspace-session-fiber.d.ts +3 -0
  97. package/data/build/dist/client/workspace-session-fiber.js +33 -0
  98. package/data/build/dist/client/workspace-session-logo-dom.d.ts +26 -0
  99. package/data/build/dist/client/workspace-session-logo-dom.js +128 -0
  100. package/data/build/dist/features/index.d.ts +3 -0
  101. package/data/build/dist/features/index.js +2 -0
  102. package/data/build/dist/features/registry.d.ts +74 -0
  103. package/data/build/dist/features/registry.js +382 -0
  104. package/data/build/dist/features/resource-scope/index.d.ts +39 -0
  105. package/data/build/dist/features/resource-scope/index.js +161 -0
  106. package/data/build/dist/host/auth-session.d.ts +42 -0
  107. package/data/build/dist/host/auth-session.js +186 -0
  108. package/data/build/dist/host/cli-adapters/claude-driver.d.ts +14 -0
  109. package/data/build/dist/host/cli-adapters/claude-driver.js +103 -0
  110. package/data/build/dist/host/cli-adapters/codex-driver.d.ts +45 -0
  111. package/data/build/dist/host/cli-adapters/codex-driver.js +534 -0
  112. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +38 -0
  113. package/data/build/dist/host/cli-adapters/command-code-driver.js +394 -0
  114. package/data/build/dist/host/cli-adapters/command-code-subscription.d.ts +19 -0
  115. package/data/build/dist/host/cli-adapters/command-code-subscription.js +126 -0
  116. package/data/build/dist/host/cli-adapters/driver.d.ts +41 -0
  117. package/data/build/dist/host/cli-adapters/driver.js +2 -0
  118. package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +37 -0
  119. package/data/build/dist/host/cli-adapters/dsh-message-projector.js +180 -0
  120. package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts +48 -0
  121. package/data/build/dist/host/cli-adapters/dsh-tool-history.js +373 -0
  122. package/data/build/dist/host/cli-adapters/feature.d.ts +7 -0
  123. package/data/build/dist/host/cli-adapters/feature.js +335 -0
  124. package/data/build/dist/host/cli-adapters/gemini-driver.d.ts +24 -0
  125. package/data/build/dist/host/cli-adapters/gemini-driver.js +427 -0
  126. package/data/build/dist/host/cli-adapters/grok-driver.d.ts +38 -0
  127. package/data/build/dist/host/cli-adapters/grok-driver.js +372 -0
  128. package/data/build/dist/host/cli-adapters/http-sse-client.d.ts +22 -0
  129. package/data/build/dist/host/cli-adapters/http-sse-client.js +99 -0
  130. package/data/build/dist/host/cli-adapters/interaction-events.d.ts +11 -0
  131. package/data/build/dist/host/cli-adapters/interaction-events.js +80 -0
  132. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +65 -0
  133. package/data/build/dist/host/cli-adapters/json-rpc-process.js +256 -0
  134. package/data/build/dist/host/cli-adapters/kimi-driver.d.ts +21 -0
  135. package/data/build/dist/host/cli-adapters/kimi-driver.js +382 -0
  136. package/data/build/dist/host/cli-adapters/model-catalog.d.ts +22 -0
  137. package/data/build/dist/host/cli-adapters/model-catalog.js +89 -0
  138. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +55 -0
  139. package/data/build/dist/host/cli-adapters/opencode-driver.js +728 -0
  140. package/data/build/dist/host/cli-adapters/pi-driver.d.ts +43 -0
  141. package/data/build/dist/host/cli-adapters/pi-driver.js +312 -0
  142. package/data/build/dist/host/cli-adapters/process-utils.d.ts +16 -0
  143. package/data/build/dist/host/cli-adapters/process-utils.js +27 -0
  144. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +82 -0
  145. package/data/build/dist/host/cli-adapters/provider-subscription.js +610 -0
  146. package/data/build/dist/host/cli-adapters/registry.d.ts +95 -0
  147. package/data/build/dist/host/cli-adapters/registry.js +659 -0
  148. package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts +24 -0
  149. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +119 -0
  150. package/data/build/dist/host/cli-adapters/session-probe.d.ts +20 -0
  151. package/data/build/dist/host/cli-adapters/session-probe.js +139 -0
  152. package/data/build/dist/host/cli-adapters/session-store.d.ts +68 -0
  153. package/data/build/dist/host/cli-adapters/session-store.js +180 -0
  154. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +45 -0
  155. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +205 -0
  156. package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +25 -0
  157. package/data/build/dist/host/cli-adapters/stream-normalizer.js +83 -0
  158. package/data/build/dist/host/cli-adapters/tool-observation.d.ts +9 -0
  159. package/data/build/dist/host/cli-adapters/tool-observation.js +39 -0
  160. package/data/build/dist/host/control-api-client.d.ts +84 -0
  161. package/data/build/dist/host/control-api-client.js +130 -0
  162. package/data/build/dist/host/credential-store.d.ts +54 -0
  163. package/data/build/dist/host/credential-store.js +114 -0
  164. package/data/build/dist/host/debug.d.ts +79 -0
  165. package/data/build/dist/host/debug.js +295 -0
  166. package/data/build/dist/host/dsh-device-runtime.d.ts +39 -0
  167. package/data/build/dist/host/dsh-device-runtime.js +118 -0
  168. package/data/build/dist/host/dsh-gateway-feature.d.ts +5 -0
  169. package/data/build/dist/host/dsh-gateway-feature.js +55 -0
  170. package/data/build/dist/host/dsh-runtime-version.d.ts +12 -0
  171. package/data/build/dist/host/dsh-runtime-version.js +69 -0
  172. package/data/build/dist/host/features/auth.d.ts +11 -0
  173. package/data/build/dist/host/features/auth.js +273 -0
  174. package/data/build/dist/host/features/debug.d.ts +5 -0
  175. package/data/build/dist/host/features/debug.js +90 -0
  176. package/data/build/dist/host/features/host-status.d.ts +12 -0
  177. package/data/build/dist/host/features/host-status.js +54 -0
  178. package/data/build/dist/host/features/index.d.ts +19 -0
  179. package/data/build/dist/host/features/index.js +29 -0
  180. package/data/build/dist/host/features/lan-access-dsh.d.ts +8 -0
  181. package/data/build/dist/host/features/lan-access-dsh.js +45 -0
  182. package/data/build/dist/host/features/terminal-process.d.ts +5 -0
  183. package/data/build/dist/host/features/terminal-process.js +110 -0
  184. package/data/build/dist/host/features/terminal-status.d.ts +18 -0
  185. package/data/build/dist/host/features/terminal-status.js +56 -0
  186. package/data/build/dist/host/features/types.d.ts +41 -0
  187. package/data/build/dist/host/features/types.js +2 -0
  188. package/data/build/dist/host/index.d.ts +43 -0
  189. package/data/build/dist/host/index.js +135 -0
  190. package/data/build/dist/host/lan-access-dsh.d.ts +83 -0
  191. package/data/build/dist/host/lan-access-dsh.js +831 -0
  192. package/data/build/dist/host/native-session-bridge.d.ts +130 -0
  193. package/data/build/dist/host/native-session-bridge.js +317 -0
  194. package/data/build/dist/host/relay-tunnel-runtime.d.ts +97 -0
  195. package/data/build/dist/host/relay-tunnel-runtime.js +361 -0
  196. package/data/build/dist/host/remote-web-runtime.d.ts +78 -0
  197. package/data/build/dist/host/remote-web-runtime.js +559 -0
  198. package/data/build/dist/host/rpc-table.d.ts +32 -0
  199. package/data/build/dist/host/rpc-table.js +47 -0
  200. package/data/build/dist/host/rpc.d.ts +18 -0
  201. package/data/build/dist/host/rpc.js +248 -0
  202. package/data/build/dist/host/settings.d.ts +19 -0
  203. package/data/build/dist/host/settings.js +80 -0
  204. package/data/build/dist/host/terminal/attachment-registry.d.ts +17 -0
  205. package/data/build/dist/host/terminal/attachment-registry.js +49 -0
  206. package/data/build/dist/host/terminal/backends/conpty-backend.d.ts +39 -0
  207. package/data/build/dist/host/terminal/backends/conpty-backend.js +160 -0
  208. package/data/build/dist/host/terminal/backends/local-pty-backend.d.ts +36 -0
  209. package/data/build/dist/host/terminal/backends/local-pty-backend.js +178 -0
  210. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +40 -0
  211. package/data/build/dist/host/terminal/backends/tmux-backend.js +191 -0
  212. package/data/build/dist/host/terminal/broker/conpty-broker-client.d.ts +27 -0
  213. package/data/build/dist/host/terminal/broker/conpty-broker-client.js +154 -0
  214. package/data/build/dist/host/terminal/broker/conpty-broker-process.d.ts +10 -0
  215. package/data/build/dist/host/terminal/broker/conpty-broker-process.js +147 -0
  216. package/data/build/dist/host/terminal/broker/conpty-broker-protocol.d.ts +92 -0
  217. package/data/build/dist/host/terminal/broker/conpty-broker-protocol.js +134 -0
  218. package/data/build/dist/host/terminal/controller-factory.d.ts +37 -0
  219. package/data/build/dist/host/terminal/controller-factory.js +82 -0
  220. package/data/build/dist/host/terminal/index.d.ts +17 -0
  221. package/data/build/dist/host/terminal/index.js +17 -0
  222. package/data/build/dist/host/terminal/runtime-adapter.d.ts +77 -0
  223. package/data/build/dist/host/terminal/runtime-adapter.js +18 -0
  224. package/data/build/dist/host/terminal/runtime-manager.d.ts +41 -0
  225. package/data/build/dist/host/terminal/runtime-manager.js +179 -0
  226. package/data/build/dist/host/terminal/shell-detection.d.ts +23 -0
  227. package/data/build/dist/host/terminal/shell-detection.js +105 -0
  228. package/data/build/dist/host/terminal/startup.d.ts +33 -0
  229. package/data/build/dist/host/terminal/startup.js +100 -0
  230. package/data/build/dist/host/terminal/terminal-controller.d.ts +78 -0
  231. package/data/build/dist/host/terminal/terminal-controller.js +324 -0
  232. package/data/build/dist/host/terminal/terminal-process-service.d.ts +30 -0
  233. package/data/build/dist/host/terminal/terminal-process-service.js +194 -0
  234. package/data/build/dist/host/terminal/terminal-process-store.d.ts +45 -0
  235. package/data/build/dist/host/terminal/terminal-process-store.js +183 -0
  236. package/data/build/dist/host/terminal/terminal-service.d.ts +87 -0
  237. package/data/build/dist/host/terminal/terminal-service.js +528 -0
  238. package/data/build/dist/host/terminal/terminal-store.d.ts +49 -0
  239. package/data/build/dist/host/terminal/terminal-store.js +242 -0
  240. package/data/build/dist/index.d.ts +37 -0
  241. package/data/build/dist/index.js +26 -0
  242. package/data/build/dist/shared/contracts/auth.d.ts +122 -0
  243. package/data/build/dist/shared/contracts/auth.js +8 -0
  244. package/data/build/dist/shared/contracts/cli-adapter.d.ts +192 -0
  245. package/data/build/dist/shared/contracts/cli-adapter.js +2 -0
  246. package/data/build/dist/shared/contracts/command-code.d.ts +5 -0
  247. package/data/build/dist/shared/contracts/command-code.js +2 -0
  248. package/data/build/dist/shared/contracts/config.d.ts +113 -0
  249. package/data/build/dist/shared/contracts/config.js +86 -0
  250. package/data/build/dist/shared/contracts/debug-config.d.ts +28 -0
  251. package/data/build/dist/shared/contracts/debug-config.js +78 -0
  252. package/data/build/dist/shared/contracts/debug.d.ts +75 -0
  253. package/data/build/dist/shared/contracts/debug.js +121 -0
  254. package/data/build/dist/shared/contracts/dsh-device.d.ts +72 -0
  255. package/data/build/dist/shared/contracts/dsh-device.js +2 -0
  256. package/data/build/dist/shared/contracts/errors.d.ts +33 -0
  257. package/data/build/dist/shared/contracts/errors.js +41 -0
  258. package/data/build/dist/shared/contracts/feature.d.ts +71 -0
  259. package/data/build/dist/shared/contracts/feature.js +2 -0
  260. package/data/build/dist/shared/contracts/host-status.d.ts +14 -0
  261. package/data/build/dist/shared/contracts/host-status.js +2 -0
  262. package/data/build/dist/shared/contracts/lan-access-dsh.d.ts +30 -0
  263. package/data/build/dist/shared/contracts/lan-access-dsh.js +2 -0
  264. package/data/build/dist/shared/contracts/peer-host.d.ts +37 -0
  265. package/data/build/dist/shared/contracts/peer-host.js +9 -0
  266. package/data/build/dist/shared/contracts/signaling.d.ts +67 -0
  267. package/data/build/dist/shared/contracts/signaling.js +2 -0
  268. package/data/build/dist/shared/contracts/subscription.d.ts +69 -0
  269. package/data/build/dist/shared/contracts/subscription.js +2 -0
  270. package/data/build/dist/shared/contracts/terminal-process.d.ts +65 -0
  271. package/data/build/dist/shared/contracts/terminal-process.js +2 -0
  272. package/data/build/dist/shared/contracts/terminal.d.ts +127 -0
  273. package/data/build/dist/shared/contracts/terminal.js +2 -0
  274. package/data/build/dist/shared/contracts/transport.d.ts +45 -0
  275. package/data/build/dist/shared/contracts/transport.js +3 -0
  276. package/data/build/dist/shared/contracts/version.d.ts +19 -0
  277. package/data/build/dist/shared/contracts/version.js +74 -0
  278. package/data/build/dist/shared/index.d.ts +22 -0
  279. package/data/build/dist/shared/index.js +9 -0
  280. package/data/build/dist/transport/carrier.d.ts +38 -0
  281. package/data/build/dist/transport/carrier.js +268 -0
  282. package/data/build/dist/transport/debug.d.ts +22 -0
  283. package/data/build/dist/transport/debug.js +57 -0
  284. package/data/build/dist/transport/dsh-envelope.d.ts +41 -0
  285. package/data/build/dist/transport/dsh-envelope.js +107 -0
  286. package/data/build/dist/transport/dsh-gateway.d.ts +64 -0
  287. package/data/build/dist/transport/dsh-gateway.js +254 -0
  288. package/data/build/dist/transport/dsh-session.d.ts +55 -0
  289. package/data/build/dist/transport/dsh-session.js +256 -0
  290. package/data/build/dist/transport/dsh-transport.d.ts +57 -0
  291. package/data/build/dist/transport/dsh-transport.js +125 -0
  292. package/data/build/dist/transport/frame.d.ts +132 -0
  293. package/data/build/dist/transport/frame.js +168 -0
  294. package/data/build/dist/transport/index.d.ts +11 -0
  295. package/data/build/dist/transport/index.js +11 -0
  296. package/data/build/dist/transport/multiplexer.d.ts +63 -0
  297. package/data/build/dist/transport/multiplexer.js +323 -0
  298. package/data/build/dist/transport/webrtc-client.d.ts +65 -0
  299. package/data/build/dist/transport/webrtc-client.js +255 -0
  300. package/data/build/dist/transport/webrtc-host.d.ts +58 -0
  301. package/data/build/dist/transport/webrtc-host.js +252 -0
  302. package/data/build/dist/typert.host.d.ts +25 -0
  303. package/data/build/dist/typert.host.js +150 -0
  304. package/dsh.bundle.patch +12 -0
  305. package/package.json +135 -0
  306. package/profile/README.md +27 -0
  307. package/profile/cordis.patch.yml +2 -0
  308. package/profile/package.json +20 -0
  309. package/profile/scripts/check-dsh-install.mjs +71 -0
  310. package/profile/version.json +5 -0
  311. package/scripts/check-dsh-install.mjs +88 -0
  312. package/version.json +6 -0
@@ -0,0 +1,178 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { spawn as spawnPty } from '@lydell/node-pty';
3
+ import { TerminalRuntimeError, normalizeTerminalSize, } from '../runtime-adapter.js';
4
+ const MAX_REPLAY_CHARACTERS = 1024 * 1024;
5
+ /**
6
+ * 非强化模式使用的进程内 PTY。
7
+ *
8
+ * shell 由当前 DSH 进程直接持有,不承诺跨 DSH 重启恢复。浏览器 detach 只
9
+ * 释放订阅;显式关闭或 controller 销毁才结束 shell。
10
+ */
11
+ export class LocalPtyTerminalBackend {
12
+ runtimeTypes = ['local-pty'];
13
+ platform;
14
+ ptySpawner;
15
+ createAttachmentId;
16
+ processes = new Map();
17
+ attachments = new Map();
18
+ constructor(options = {}) {
19
+ this.platform = options.platform ?? process.platform;
20
+ this.ptySpawner = options.ptySpawner ?? spawnPty;
21
+ this.createAttachmentId = options.createAttachmentId ?? randomUUID;
22
+ }
23
+ async create(input) {
24
+ this.assertSupported(input.session);
25
+ const existing = this.processes.get(input.session.runtimeSessionKey);
26
+ if (existing?.alive)
27
+ return identityOf(input.session, existing.pty.pid, true);
28
+ const size = normalizeTerminalSize(input.cols ?? 120, input.rows ?? 30);
29
+ let pty;
30
+ try {
31
+ pty = this.ptySpawner(input.session.commandPath ?? input.session.shellPath, [...(input.session.commandArgs ?? input.session.shellArgs)], {
32
+ cwd: input.session.cwd,
33
+ env: { ...process.env, ...(input.session.commandEnv ?? {}), ...(input.env ?? {}) },
34
+ cols: size.cols,
35
+ rows: size.rows,
36
+ name: 'xterm-256color',
37
+ });
38
+ }
39
+ catch (error) {
40
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_CREATE_FAILED', '本机 PTY 创建失败', { cause: error });
41
+ }
42
+ let state;
43
+ const dataSubscription = pty.onData((data) => {
44
+ if (state === undefined || !state.alive)
45
+ return;
46
+ state.replay = boundedAppend(state.replay, data);
47
+ for (const attachment of this.attachments.values()) {
48
+ if (attachment.runtimeSessionKey === input.session.runtimeSessionKey)
49
+ attachment.onData(data);
50
+ }
51
+ });
52
+ const exitSubscription = pty.onExit(({ exitCode }) => {
53
+ if (state !== undefined)
54
+ this.handleExit(input.session.runtimeSessionKey, state, exitCode);
55
+ });
56
+ state = { pty, dataSubscription, exitSubscription, alive: true, replay: '' };
57
+ this.processes.set(input.session.runtimeSessionKey, state);
58
+ return identityOf(input.session, pty.pid, true);
59
+ }
60
+ async inspect(session) {
61
+ this.assertSupported(session);
62
+ const state = this.processes.get(session.runtimeSessionKey);
63
+ if (state?.alive)
64
+ return identityOf(session, state.pty.pid, true);
65
+ return {
66
+ ...identityOf(session, null, false),
67
+ detail: '本机 PTY 不存在或已退出',
68
+ };
69
+ }
70
+ async attach(input) {
71
+ this.assertSupported(input.session);
72
+ const state = this.processes.get(input.session.runtimeSessionKey);
73
+ if (state === undefined || !state.alive) {
74
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_LOST', '本机 PTY 已经丢失');
75
+ }
76
+ const size = normalizeTerminalSize(input.cols, input.rows);
77
+ state.pty.resize(size.cols, size.rows);
78
+ const attachmentId = this.createAttachmentId();
79
+ if (state.replay !== '')
80
+ input.onData(state.replay);
81
+ this.attachments.set(attachmentId, {
82
+ runtimeSessionKey: input.session.runtimeSessionKey,
83
+ onData: input.onData,
84
+ ...(input.onExit === undefined ? {} : { onExit: input.onExit }),
85
+ });
86
+ return { attachmentId, identity: identityOf(input.session, state.pty.pid, true) };
87
+ }
88
+ async write(input) {
89
+ const { process } = this.requireAttachment(input.attachmentId);
90
+ process.pty.write(input.data);
91
+ }
92
+ async resize(input) {
93
+ const { process } = this.requireAttachment(input.attachmentId);
94
+ const size = normalizeTerminalSize(input.cols, input.rows);
95
+ process.pty.resize(size.cols, size.rows);
96
+ }
97
+ async detach(attachmentId) {
98
+ this.attachments.delete(attachmentId);
99
+ }
100
+ async terminate(session) {
101
+ this.assertSupported(session);
102
+ const state = this.processes.get(session.runtimeSessionKey);
103
+ if (state === undefined)
104
+ return;
105
+ this.removeAttachments(session.runtimeSessionKey);
106
+ this.releaseProcess(session.runtimeSessionKey, state);
107
+ try {
108
+ state.pty.kill();
109
+ }
110
+ catch { /* PTY 可能已经自然退出 */ }
111
+ }
112
+ async dispose() {
113
+ this.attachments.clear();
114
+ for (const [runtimeSessionKey, state] of [...this.processes]) {
115
+ this.releaseProcess(runtimeSessionKey, state);
116
+ try {
117
+ state.pty.kill();
118
+ }
119
+ catch { /* PTY 可能已经自然退出 */ }
120
+ }
121
+ }
122
+ requireAttachment(attachmentId) {
123
+ const attachment = this.attachments.get(attachmentId);
124
+ if (attachment === undefined) {
125
+ throw new TerminalRuntimeError('TERMINAL_ATTACHMENT_NOT_FOUND', '终端 attach 不存在或已经释放');
126
+ }
127
+ const process = this.processes.get(attachment.runtimeSessionKey);
128
+ if (process === undefined || !process.alive) {
129
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_LOST', '本机 PTY 已经丢失');
130
+ }
131
+ return { process };
132
+ }
133
+ handleExit(runtimeSessionKey, state, exitCode) {
134
+ if (this.processes.get(runtimeSessionKey) !== state || !state.alive)
135
+ return;
136
+ const callbacks = [...this.attachments]
137
+ .filter(([, attachment]) => attachment.runtimeSessionKey === runtimeSessionKey)
138
+ .map(([, attachment]) => attachment.onExit);
139
+ this.removeAttachments(runtimeSessionKey);
140
+ this.releaseProcess(runtimeSessionKey, state);
141
+ for (const callback of callbacks)
142
+ callback?.(exitCode);
143
+ }
144
+ removeAttachments(runtimeSessionKey) {
145
+ for (const [attachmentId, attachment] of this.attachments) {
146
+ if (attachment.runtimeSessionKey === runtimeSessionKey)
147
+ this.attachments.delete(attachmentId);
148
+ }
149
+ }
150
+ releaseProcess(runtimeSessionKey, state) {
151
+ state.alive = false;
152
+ if (this.processes.get(runtimeSessionKey) === state)
153
+ this.processes.delete(runtimeSessionKey);
154
+ state.dataSubscription.dispose();
155
+ state.exitSubscription.dispose();
156
+ }
157
+ assertSupported(session) {
158
+ if (!['darwin', 'linux', 'win32'].includes(this.platform)) {
159
+ throw new TerminalRuntimeError('TERMINAL_PLATFORM_UNSUPPORTED', `本机 PTY 不支持 ${this.platform}`);
160
+ }
161
+ if (session.runtimeType !== 'local-pty') {
162
+ throw new TerminalRuntimeError('TERMINAL_PLATFORM_UNSUPPORTED', `本机 PTY 不支持 ${session.runtimeType}`);
163
+ }
164
+ }
165
+ }
166
+ function identityOf(session, pid, alive) {
167
+ return {
168
+ alive,
169
+ runtimeSessionKey: session.runtimeSessionKey,
170
+ runtimePid: pid,
171
+ shellPid: pid,
172
+ };
173
+ }
174
+ function boundedAppend(current, data) {
175
+ const combined = current + data;
176
+ return combined.length <= MAX_REPLAY_CHARACTERS ? combined : combined.slice(-MAX_REPLAY_CHARACTERS);
177
+ }
178
+ //# sourceMappingURL=local-pty-backend.js.map
@@ -0,0 +1,40 @@
1
+ import { spawn as spawnPty } from '@lydell/node-pty';
2
+ import { type TerminalRuntimeAdapter, type TerminalRuntimeAttachInput, type TerminalRuntimeAttachment, type TerminalRuntimeCreateInput, type TerminalRuntimeIdentity, type TerminalRuntimeResizeInput, type TerminalRuntimeSession, type TerminalRuntimeWriteInput } from '../runtime-adapter.js';
3
+ export interface TmuxCommandResult {
4
+ readonly status: number | null;
5
+ readonly stdout: string;
6
+ readonly stderr: string;
7
+ }
8
+ export interface TmuxCommandRunner {
9
+ run(command: string, args: readonly string[]): TmuxCommandResult;
10
+ }
11
+ export interface TmuxBackendOptions {
12
+ readonly tmuxPath?: string;
13
+ readonly platform?: string;
14
+ readonly commandRunner?: TmuxCommandRunner;
15
+ readonly ptySpawner?: typeof spawnPty;
16
+ readonly createAttachmentId?: () => string;
17
+ }
18
+ /** tmux 拥有持久 shell,node-pty 这里只承载可随 generation 销毁的 tmux client。 */
19
+ export declare class TmuxTerminalBackend implements TerminalRuntimeAdapter {
20
+ readonly runtimeTypes: readonly ["tmux"];
21
+ private readonly tmuxPath;
22
+ private readonly platform;
23
+ private readonly runner;
24
+ private readonly ptySpawner;
25
+ private readonly createAttachmentId;
26
+ private readonly attachments;
27
+ constructor(options?: TmuxBackendOptions);
28
+ create(input: TerminalRuntimeCreateInput): Promise<TerminalRuntimeIdentity>;
29
+ inspect(session: TerminalRuntimeSession): Promise<TerminalRuntimeIdentity>;
30
+ attach(input: TerminalRuntimeAttachInput): Promise<TerminalRuntimeAttachment>;
31
+ write(input: TerminalRuntimeWriteInput): Promise<void>;
32
+ resize(input: TerminalRuntimeResizeInput): Promise<void>;
33
+ detach(attachmentId: string): Promise<void>;
34
+ terminate(session: TerminalRuntimeSession): Promise<void>;
35
+ private getAttachment;
36
+ private assertSupported;
37
+ private requireTmuxPath;
38
+ }
39
+ export declare function tmuxSessionName(runtimeSessionKey: string): string;
40
+ //# sourceMappingURL=tmux-backend.d.ts.map
@@ -0,0 +1,191 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { accessSync, constants } from 'node:fs';
4
+ import { spawn as spawnPty } from '@lydell/node-pty';
5
+ import { TerminalRuntimeError, normalizeTerminalSize, } from '../runtime-adapter.js';
6
+ /** tmux 拥有持久 shell,node-pty 这里只承载可随 generation 销毁的 tmux client。 */
7
+ export class TmuxTerminalBackend {
8
+ runtimeTypes = ['tmux'];
9
+ tmuxPath;
10
+ platform;
11
+ runner;
12
+ ptySpawner;
13
+ createAttachmentId;
14
+ attachments = new Map();
15
+ constructor(options = {}) {
16
+ this.platform = options.platform ?? process.platform;
17
+ this.tmuxPath = options.tmuxPath ?? detectTmuxPath(this.platform);
18
+ this.runner = options.commandRunner ?? { run: runCommand };
19
+ this.ptySpawner = options.ptySpawner ?? spawnPty;
20
+ this.createAttachmentId = options.createAttachmentId ?? randomUUID;
21
+ }
22
+ async create(input) {
23
+ this.assertSupported(input.session);
24
+ const tmuxPath = this.requireTmuxPath();
25
+ const current = await this.inspect(input.session);
26
+ if (current.alive)
27
+ return current;
28
+ const name = tmuxSessionName(input.session.runtimeSessionKey);
29
+ const result = this.runner.run(tmuxPath, [
30
+ 'new-session', '-d', '-s', name,
31
+ ...Object.entries(input.session.commandEnv ?? {}).flatMap(([key, value]) => ['-e', `${key}=${value}`]),
32
+ '-c', input.session.cwd,
33
+ ...tmuxLaunchCommand(input.session),
34
+ ]);
35
+ if (result.status !== 0) {
36
+ throw new TerminalRuntimeError(result.status === null ? 'TERMINAL_RUNTIME_UNAVAILABLE' : 'TERMINAL_RUNTIME_CREATE_FAILED', sanitizeCommandError('tmux 会话创建失败', result.stderr));
37
+ }
38
+ return this.inspect(input.session);
39
+ }
40
+ async inspect(session) {
41
+ this.assertSupported(session);
42
+ if (this.tmuxPath === null)
43
+ return {
44
+ alive: false,
45
+ runtimeSessionKey: session.runtimeSessionKey,
46
+ runtimePid: null,
47
+ shellPid: null,
48
+ detail: '未找到可执行的 tmux',
49
+ };
50
+ const result = this.runner.run(this.tmuxPath, ['has-session', '-t', tmuxSessionName(session.runtimeSessionKey)]);
51
+ if (result.status === null) {
52
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_UNAVAILABLE', sanitizeCommandError('tmux 不可执行', result.stderr));
53
+ }
54
+ if (result.status !== 0 && !isMissingSession(result.stderr)) {
55
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_UNAVAILABLE', sanitizeCommandError('tmux 会话检查失败', result.stderr));
56
+ }
57
+ return {
58
+ alive: result.status === 0,
59
+ runtimeSessionKey: session.runtimeSessionKey,
60
+ runtimePid: null,
61
+ shellPid: null,
62
+ ...(result.status === 0 ? {} : { detail: sanitizeCommandError('tmux 会话不存在', result.stderr) }),
63
+ };
64
+ }
65
+ async attach(input) {
66
+ const identity = await this.inspect(input.session);
67
+ if (!identity.alive) {
68
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_LOST', 'tmux 会话已经丢失');
69
+ }
70
+ const size = normalizeTerminalSize(input.cols, input.rows);
71
+ const tmuxPath = this.requireTmuxPath();
72
+ const attachmentId = this.createAttachmentId();
73
+ const name = tmuxSessionName(input.session.runtimeSessionKey);
74
+ const pty = this.ptySpawner(tmuxPath, ['attach-session', '-t', name], {
75
+ cwd: input.session.cwd,
76
+ env: { ...process.env, ...(input.env ?? {}) },
77
+ cols: size.cols,
78
+ rows: size.rows,
79
+ name: 'xterm-256color',
80
+ });
81
+ const state = { sessionName: name, pty, detached: false };
82
+ this.attachments.set(attachmentId, state);
83
+ pty.onData((data) => {
84
+ if (!state.detached)
85
+ input.onData(data);
86
+ });
87
+ pty.onExit(({ exitCode }) => {
88
+ if (this.attachments.get(attachmentId) === state)
89
+ this.attachments.delete(attachmentId);
90
+ if (!state.detached)
91
+ input.onExit?.(exitCode);
92
+ });
93
+ return { attachmentId, identity };
94
+ }
95
+ async write(input) {
96
+ this.getAttachment(input.attachmentId).pty.write(input.data);
97
+ }
98
+ async resize(input) {
99
+ const size = normalizeTerminalSize(input.cols, input.rows);
100
+ this.getAttachment(input.attachmentId).pty.resize(size.cols, size.rows);
101
+ }
102
+ async detach(attachmentId) {
103
+ const state = this.attachments.get(attachmentId);
104
+ if (state === undefined)
105
+ return;
106
+ state.detached = true;
107
+ this.attachments.delete(attachmentId);
108
+ // 杀掉的只是 tmux client;tmux server 和其中的 shell 继续运行。
109
+ try {
110
+ state.pty.kill();
111
+ }
112
+ catch { /* attach 可能已经自然退出 */ }
113
+ }
114
+ async terminate(session) {
115
+ this.assertSupported(session);
116
+ const tmuxPath = this.requireTmuxPath();
117
+ const name = tmuxSessionName(session.runtimeSessionKey);
118
+ for (const [attachmentId, state] of this.attachments) {
119
+ if (state.sessionName === name)
120
+ await this.detach(attachmentId);
121
+ }
122
+ const result = this.runner.run(tmuxPath, ['kill-session', '-t', name]);
123
+ // tmux 的“目标不存在”视为幂等成功。
124
+ if (result.status !== 0 && !isMissingSession(result.stderr)) {
125
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_CREATE_FAILED', sanitizeCommandError('tmux 会话关闭失败', result.stderr));
126
+ }
127
+ }
128
+ getAttachment(attachmentId) {
129
+ const state = this.attachments.get(attachmentId);
130
+ if (state === undefined)
131
+ throw new TerminalRuntimeError('TERMINAL_ATTACHMENT_NOT_FOUND', '终端 attach 不存在或已经释放');
132
+ return state;
133
+ }
134
+ assertSupported(session) {
135
+ if (this.platform !== 'darwin' && this.platform !== 'linux') {
136
+ throw new TerminalRuntimeError('TERMINAL_PLATFORM_UNSUPPORTED', 'tmux backend 只支持 macOS 和 Linux');
137
+ }
138
+ if (session.runtimeType !== 'tmux') {
139
+ throw new TerminalRuntimeError('TERMINAL_PLATFORM_UNSUPPORTED', `tmux backend 不支持 ${session.runtimeType}`);
140
+ }
141
+ }
142
+ requireTmuxPath() {
143
+ if (this.tmuxPath === null)
144
+ throw new TerminalRuntimeError('TERMINAL_RUNTIME_UNAVAILABLE', '未找到可执行的 tmux');
145
+ return this.tmuxPath;
146
+ }
147
+ }
148
+ /**
149
+ * 调试命令必须是 Shell 的子进程:杀掉端口对应的业务进程后,tmux pane
150
+ * 仍然回到交互 Shell;只有显式停止才会调用 terminate 销毁整个会话。
151
+ */
152
+ function tmuxLaunchCommand(session) {
153
+ if (session.commandPath === undefined)
154
+ return [session.shellPath, ...session.shellArgs];
155
+ const command = [session.commandPath, ...(session.commandArgs ?? [])].map(shellQuote).join(' ');
156
+ const shell = [session.shellPath, ...session.shellArgs].map(shellQuote).join(' ');
157
+ return [session.shellPath, ...session.shellArgs, '-c', `${command}; exec ${shell}`];
158
+ }
159
+ function shellQuote(value) {
160
+ return `'${value.replaceAll("'", "'\\''")}'`;
161
+ }
162
+ export function tmuxSessionName(runtimeSessionKey) {
163
+ const digest = createHash('sha256').update(runtimeSessionKey).digest('hex').slice(0, 32);
164
+ return `codingns4dsh-${digest}`;
165
+ }
166
+ function runCommand(command, args) {
167
+ return spawnSync(command, args, { encoding: 'utf8', windowsHide: true, shell: false });
168
+ }
169
+ function detectTmuxPath(platform) {
170
+ const candidates = platform === 'darwin'
171
+ ? ['/opt/homebrew/bin/tmux', '/usr/local/bin/tmux', '/usr/bin/tmux']
172
+ : ['/usr/bin/tmux', '/usr/local/bin/tmux', '/bin/tmux'];
173
+ return candidates.find(isExecutable) ?? null;
174
+ }
175
+ function isExecutable(path) {
176
+ try {
177
+ accessSync(path, constants.X_OK);
178
+ return true;
179
+ }
180
+ catch {
181
+ return false;
182
+ }
183
+ }
184
+ function isMissingSession(stderr) {
185
+ return /no (server running|sessions|session)|can't find session|error connecting to .*no such file or directory/i.test(stderr);
186
+ }
187
+ function sanitizeCommandError(prefix, stderr) {
188
+ const detail = stderr.trim().replace(/[\r\n]+/g, ' ').slice(0, 300);
189
+ return detail ? `${prefix}:${detail}` : prefix;
190
+ }
191
+ //# sourceMappingURL=tmux-backend.js.map
@@ -0,0 +1,27 @@
1
+ import { type TerminalRuntimeIdentity } from '../runtime-adapter.js';
2
+ export interface ConptyBrokerAttachment {
3
+ readonly attachmentId: string;
4
+ readonly identity: TerminalRuntimeIdentity;
5
+ write(data: string): void;
6
+ resize(cols: number, rows: number): void;
7
+ detach(): Promise<void>;
8
+ }
9
+ export interface ConptyBrokerClientLike {
10
+ inspect(pipeName: string, auth: string, runtimeSessionKey: string): Promise<TerminalRuntimeIdentity>;
11
+ attach(input: {
12
+ readonly pipeName: string;
13
+ readonly auth: string;
14
+ readonly runtimeSessionKey: string;
15
+ readonly cols: number;
16
+ readonly rows: number;
17
+ readonly onData: (data: string) => void;
18
+ readonly onExit?: (exitCode: number | null) => void;
19
+ }): Promise<ConptyBrokerAttachment>;
20
+ terminate(pipeName: string, auth: string): Promise<void>;
21
+ }
22
+ export declare class ConptyBrokerClient implements ConptyBrokerClientLike {
23
+ inspect(pipeName: string, auth: string, runtimeSessionKey: string): Promise<TerminalRuntimeIdentity>;
24
+ attach(input: Parameters<ConptyBrokerClientLike['attach']>[0]): Promise<ConptyBrokerAttachment>;
25
+ terminate(pipeName: string, auth: string): Promise<void>;
26
+ }
27
+ //# sourceMappingURL=conpty-broker-client.d.ts.map
@@ -0,0 +1,154 @@
1
+ import { connect } from 'node:net';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { createJsonLineParser, parseBrokerMessage, writeBrokerMessage, } from './conpty-broker-protocol.js';
4
+ import { TerminalRuntimeError, normalizeTerminalSize } from '../runtime-adapter.js';
5
+ const BROKER_REQUEST_TIMEOUT_MS = 5_000;
6
+ export class ConptyBrokerClient {
7
+ async inspect(pipeName, auth, runtimeSessionKey) {
8
+ const message = await requestOnce(pipeName, { version: 1, auth, type: 'inspect' });
9
+ if (message.type !== 'inspect-result')
10
+ throw protocolError(message);
11
+ return {
12
+ alive: message.alive,
13
+ runtimeSessionKey,
14
+ runtimePid: message.brokerPid,
15
+ shellPid: message.shellPid,
16
+ };
17
+ }
18
+ async attach(input) {
19
+ const socket = connect(input.pipeName);
20
+ const size = normalizeTerminalSize(input.cols, input.rows);
21
+ const attachmentId = randomUUID();
22
+ let settled = false;
23
+ let detached = false;
24
+ let finished = false;
25
+ return new Promise((resolve, reject) => {
26
+ const fail = (error) => {
27
+ if (finished)
28
+ return;
29
+ finished = true;
30
+ socket.destroy();
31
+ if (!settled)
32
+ reject(new TerminalRuntimeError('TERMINAL_RUNTIME_LOST', '无法连接 ConPTY broker', { cause: error }));
33
+ else if (!detached)
34
+ input.onExit?.(null);
35
+ settled = true;
36
+ };
37
+ const parser = createJsonLineParser((value) => {
38
+ const message = parseBrokerMessage(value);
39
+ if (message === null)
40
+ return fail(new Error('broker 返回了无效协议消息'));
41
+ if (message.type === 'error')
42
+ return fail(protocolError(message));
43
+ if (message.type === 'output') {
44
+ if (!finished)
45
+ input.onData(message.data);
46
+ return;
47
+ }
48
+ if (message.type === 'exit') {
49
+ if (!finished) {
50
+ finished = true;
51
+ input.onExit?.(message.exitCode);
52
+ socket.end();
53
+ }
54
+ return;
55
+ }
56
+ if (message.type !== 'attached' || settled)
57
+ return;
58
+ settled = true;
59
+ const identity = {
60
+ alive: true,
61
+ runtimeSessionKey: input.runtimeSessionKey,
62
+ runtimePid: message.brokerPid,
63
+ shellPid: message.shellPid,
64
+ };
65
+ resolve({
66
+ attachmentId,
67
+ identity,
68
+ write(data) {
69
+ if (!detached)
70
+ writeBrokerMessage(socket, { version: 1, auth: input.auth, type: 'input', data });
71
+ },
72
+ resize(cols, rows) {
73
+ if (detached)
74
+ return;
75
+ const next = normalizeTerminalSize(cols, rows);
76
+ writeBrokerMessage(socket, { version: 1, auth: input.auth, type: 'resize', ...next });
77
+ },
78
+ async detach() {
79
+ if (detached)
80
+ return;
81
+ detached = true;
82
+ finished = true;
83
+ writeBrokerMessage(socket, { version: 1, auth: input.auth, type: 'detach' });
84
+ socket.end();
85
+ },
86
+ });
87
+ });
88
+ socket.once('connect', () => writeBrokerMessage(socket, { version: 1, auth: input.auth, type: 'attach', ...size }));
89
+ socket.setTimeout(BROKER_REQUEST_TIMEOUT_MS, () => fail(new Error('ConPTY broker attach 响应超时')));
90
+ socket.on('data', (chunk) => {
91
+ try {
92
+ parser.push(chunk);
93
+ }
94
+ catch (error) {
95
+ fail(error);
96
+ }
97
+ });
98
+ socket.once('error', fail);
99
+ socket.once('close', () => {
100
+ if (!detached)
101
+ fail(new Error('broker 连接已经关闭'));
102
+ });
103
+ });
104
+ }
105
+ async terminate(pipeName, auth) {
106
+ const message = await requestOnce(pipeName, { version: 1, auth, type: 'terminate' });
107
+ if (message.type !== 'terminated')
108
+ throw protocolError(message);
109
+ }
110
+ }
111
+ async function requestOnce(pipeName, request) {
112
+ const socket = connect(pipeName);
113
+ return new Promise((resolve, reject) => {
114
+ let settled = false;
115
+ const finish = (action) => {
116
+ if (settled)
117
+ return;
118
+ settled = true;
119
+ socket.end();
120
+ action();
121
+ };
122
+ socket.setTimeout(BROKER_REQUEST_TIMEOUT_MS, () => {
123
+ socket.destroy();
124
+ finish(() => reject(new TerminalRuntimeError('TERMINAL_RUNTIME_LOST', 'ConPTY broker 响应超时')));
125
+ });
126
+ const parser = createJsonLineParser((value) => {
127
+ const message = parseBrokerMessage(value);
128
+ if (message === null)
129
+ finish(() => reject(new TerminalRuntimeError('TERMINAL_BROKER_PROTOCOL_INVALID', 'broker 返回了无效协议消息')));
130
+ else if (message.type === 'error')
131
+ finish(() => reject(protocolError(message)));
132
+ else
133
+ finish(() => resolve(message));
134
+ });
135
+ socket.once('connect', () => writeBrokerMessage(socket, request));
136
+ socket.on('data', (chunk) => {
137
+ try {
138
+ parser.push(chunk);
139
+ }
140
+ catch (error) {
141
+ finish(() => reject(error));
142
+ }
143
+ });
144
+ socket.once('error', (error) => finish(() => reject(error)));
145
+ socket.once('close', () => finish(() => reject(new Error('broker 未返回响应'))));
146
+ });
147
+ }
148
+ function protocolError(message) {
149
+ if (message.type === 'error' && message.code === 'UNAUTHORIZED') {
150
+ return new TerminalRuntimeError('TERMINAL_BROKER_UNAUTHORIZED', message.message);
151
+ }
152
+ return new TerminalRuntimeError('TERMINAL_BROKER_PROTOCOL_INVALID', message.type === 'error' ? message.message : `broker 返回了意外消息:${message.type}`);
153
+ }
154
+ //# sourceMappingURL=conpty-broker-client.js.map
@@ -0,0 +1,10 @@
1
+ interface BrokerArguments {
2
+ readonly pipeName: string;
3
+ readonly auth: string;
4
+ readonly shellPath: string;
5
+ readonly shellArgs: readonly string[];
6
+ readonly cwd: string;
7
+ }
8
+ export declare function runConptyBroker(args: BrokerArguments): void;
9
+ export {};
10
+ //# sourceMappingURL=conpty-broker-process.d.ts.map