dsh-over-ssh 0.1.0 → 0.2.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 (250) hide show
  1. package/README.md +19 -17
  2. package/agents/agent-manifest.json +6 -6
  3. package/agents/linux-amd64/dsh-over-ssh-agent +0 -0
  4. package/agents/linux-arm64/dsh-over-ssh-agent +0 -0
  5. package/lib/client.js +422 -337
  6. package/lib/file-references.js +92 -35
  7. package/lib/fs.js +295 -113
  8. package/lib/index.js +6912 -4330
  9. package/lib/terminal-wrapper.js +9 -4
  10. package/lib/types/src/config.d.ts +156 -9
  11. package/lib/types/src/file-references.d.ts +0 -1
  12. package/lib/types/src/host/app/backend.d.ts +44 -3
  13. package/lib/types/src/host/app/recycle-bin/recycle-bin-contract.d.ts +0 -1
  14. package/lib/types/src/host/app/recycle-bin/recycle-bin-service.d.ts +0 -1
  15. package/lib/types/src/host/app/session-admin/session-admin-contract.d.ts +12 -1
  16. package/lib/types/src/host/app/session-admin/session-admin-service.d.ts +0 -1
  17. package/lib/types/src/host/app/transport/transport-selector.d.ts +0 -1
  18. package/lib/types/src/host/app/transport/transport-service.d.ts +0 -1
  19. package/lib/types/src/host/domain/capability.d.ts +0 -1
  20. package/lib/types/src/host/domain/errors.d.ts +0 -1
  21. package/lib/types/src/host/domain/roots/connection.d.ts +0 -1
  22. package/lib/types/src/host/domain/roots/root.d.ts +24 -9
  23. package/lib/types/src/host/domain/roots/session-roots.d.ts +23 -1
  24. package/lib/types/src/host/domain/roots/ssh-config.d.ts +0 -1
  25. package/lib/types/src/host/domain/session/session-admin.d.ts +0 -1
  26. package/lib/types/src/host/domain/transfer/recycle-bin.d.ts +0 -1
  27. package/lib/types/src/host/domain/transfer/transfer.d.ts +0 -1
  28. package/lib/types/src/host/infra/transport/agent/agent-installer.d.ts +0 -1
  29. package/lib/types/src/host/infra/transport/forward.d.ts +75 -0
  30. package/lib/types/src/host/infra/transport/ssh/ssh2-transport.d.ts +5 -1
  31. package/lib/types/src/host/infra/transport/transport-base.d.ts +0 -1
  32. package/lib/types/src/host/infra/transport/transport.d.ts +42 -2
  33. package/lib/types/src/host/integration/agent/agent-preflight.d.ts +0 -1
  34. package/lib/types/src/host/integration/fs/file-reference-provider.d.ts +0 -1
  35. package/lib/types/src/host/integration/fs/fs-provider.d.ts +18 -3
  36. package/lib/types/src/host/integration/transfer/transfer-service.d.ts +0 -1
  37. package/lib/types/src/index.d.ts +23 -1
  38. package/lib/types/src/local-bridge-refs.d.ts +0 -1
  39. package/lib/types/src/local-bridge.d.ts +0 -1
  40. package/lib/types/src/shared/root-keys.d.ts +120 -0
  41. package/lib/types/src/wiring/helpers.d.ts +0 -1
  42. package/package.json +5 -3
  43. package/lib/types/src/client/controls.d.ts +0 -131
  44. package/lib/types/src/client/core/card-focus-trap.d.ts +0 -45
  45. package/lib/types/src/client/core/controls.d.ts +0 -164
  46. package/lib/types/src/client/core/latest.d.ts +0 -48
  47. package/lib/types/src/client/core/locale.d.ts +0 -38
  48. package/lib/types/src/client/core/message.d.ts +0 -37
  49. package/lib/types/src/client/core/panel-model.d.ts +0 -134
  50. package/lib/types/src/client/core/portal.d.ts +0 -266
  51. package/lib/types/src/client/core/remote.d.ts +0 -84
  52. package/lib/types/src/client/core/styles.d.ts +0 -458
  53. package/lib/types/src/client/file-tree-io.d.ts +0 -19
  54. package/lib/types/src/client/file-tree.d.ts +0 -271
  55. package/lib/types/src/client/flows/directory-browser.d.ts +0 -587
  56. package/lib/types/src/client/flows/session-directory.d.ts +0 -415
  57. package/lib/types/src/client/flows/workspace-directory-flow.d.ts +0 -480
  58. package/lib/types/src/client/locale.d.ts +0 -31
  59. package/lib/types/src/client/panel-model.d.ts +0 -37
  60. package/lib/types/src/client/panel.d.ts +0 -77
  61. package/lib/types/src/client/roots/connection-test.d.ts +0 -69
  62. package/lib/types/src/client/roots/roots-panel-state.d.ts +0 -307
  63. package/lib/types/src/client/roots/roots-panel-view.d.ts +0 -280
  64. package/lib/types/src/client/roots/roots-panel.d.ts +0 -364
  65. package/lib/types/src/client/roots/transfer-panel-view.d.ts +0 -35
  66. package/lib/types/src/client/roots/transfer-panel.d.ts +0 -241
  67. package/lib/types/src/client/roots/transfer-progress.d.ts +0 -67
  68. package/lib/types/src/client/roots-panel-view.d.ts +0 -236
  69. package/lib/types/src/client/roots-panel.d.ts +0 -347
  70. package/lib/types/src/client/session/session-panel-view.d.ts +0 -336
  71. package/lib/types/src/client/session/session-panel.d.ts +0 -322
  72. package/lib/types/src/client/session/session-remote-mark.d.ts +0 -110
  73. package/lib/types/src/client/session/session-row-actions.d.ts +0 -398
  74. package/lib/types/src/client/session-panel.d.ts +0 -152
  75. package/lib/types/src/client/styles.d.ts +0 -252
  76. package/lib/types/src/client/workspace-directory-flow.d.ts +0 -342
  77. package/lib/types/src/fs.d.ts +0 -46
  78. package/lib/types/src/host/app/recycle-bin/recycle-bin-move.d.ts +0 -18
  79. package/lib/types/src/host/app/recycle-bin/recycle-bin-world.d.ts +0 -38
  80. package/lib/types/src/host/app/recycle-bin-contract.d.ts +0 -215
  81. package/lib/types/src/host/app/recycle-bin-move.d.ts +0 -18
  82. package/lib/types/src/host/app/recycle-bin-service.d.ts +0 -45
  83. package/lib/types/src/host/app/recycle-bin-world.d.ts +0 -35
  84. package/lib/types/src/host/app/roots/roots-api-connections.d.ts +0 -49
  85. package/lib/types/src/host/app/roots/roots-api-contract.d.ts +0 -369
  86. package/lib/types/src/host/app/roots/roots-api-directories.d.ts +0 -13
  87. package/lib/types/src/host/app/roots/roots-api-http.d.ts +0 -77
  88. package/lib/types/src/host/app/roots/roots-api-long-poll.d.ts +0 -130
  89. package/lib/types/src/host/app/roots/roots-api-projections.d.ts +0 -102
  90. package/lib/types/src/host/app/roots/roots-api-roots.d.ts +0 -13
  91. package/lib/types/src/host/app/roots/roots-api-state.d.ts +0 -22
  92. package/lib/types/src/host/app/roots/roots-api-transfers.d.ts +0 -26
  93. package/lib/types/src/host/app/roots/roots-api.d.ts +0 -55
  94. package/lib/types/src/host/app/roots/user-roots.d.ts +0 -552
  95. package/lib/types/src/host/app/roots-api-connections.d.ts +0 -49
  96. package/lib/types/src/host/app/roots-api-contract.d.ts +0 -339
  97. package/lib/types/src/host/app/roots-api-directories.d.ts +0 -13
  98. package/lib/types/src/host/app/roots-api-http.d.ts +0 -77
  99. package/lib/types/src/host/app/roots-api-projections.d.ts +0 -102
  100. package/lib/types/src/host/app/roots-api-roots.d.ts +0 -13
  101. package/lib/types/src/host/app/roots-api-state.d.ts +0 -22
  102. package/lib/types/src/host/app/roots-api-support.d.ts +0 -182
  103. package/lib/types/src/host/app/roots-api-transfers.d.ts +0 -13
  104. package/lib/types/src/host/app/roots-api.d.ts +0 -55
  105. package/lib/types/src/host/app/routed-fs.d.ts +0 -239
  106. package/lib/types/src/host/app/serialize.d.ts +0 -37
  107. package/lib/types/src/host/app/session-admin/session-admin-context.d.ts +0 -36
  108. package/lib/types/src/host/app/session-admin/session-admin-delete.d.ts +0 -34
  109. package/lib/types/src/host/app/session-admin-context.d.ts +0 -36
  110. package/lib/types/src/host/app/session-admin-contract.d.ts +0 -214
  111. package/lib/types/src/host/app/session-admin-delete.d.ts +0 -34
  112. package/lib/types/src/host/app/session-admin-service.d.ts +0 -38
  113. package/lib/types/src/host/app/takeover/takeover-plan.d.ts +0 -227
  114. package/lib/types/src/host/app/takeover/takeover-rows.d.ts +0 -55
  115. package/lib/types/src/host/app/transport-selector.d.ts +0 -98
  116. package/lib/types/src/host/app/transport-service.d.ts +0 -75
  117. package/lib/types/src/host/app/user-roots.d.ts +0 -461
  118. package/lib/types/src/host/domain/bin-location.d.ts +0 -79
  119. package/lib/types/src/host/domain/connection.d.ts +0 -95
  120. package/lib/types/src/host/domain/glob-pattern.d.ts +0 -62
  121. package/lib/types/src/host/domain/literal-text.d.ts +0 -63
  122. package/lib/types/src/host/domain/path-grammar.d.ts +0 -84
  123. package/lib/types/src/host/domain/recycle-bin.d.ts +0 -337
  124. package/lib/types/src/host/domain/root.d.ts +0 -74
  125. package/lib/types/src/host/domain/roots/bin-location.d.ts +0 -91
  126. package/lib/types/src/host/domain/roots/route-table.d.ts +0 -102
  127. package/lib/types/src/host/domain/route-table.d.ts +0 -80
  128. package/lib/types/src/host/domain/session/terminal-target.d.ts +0 -136
  129. package/lib/types/src/host/domain/session-admin.d.ts +0 -330
  130. package/lib/types/src/host/domain/shell.d.ts +0 -47
  131. package/lib/types/src/host/domain/ssh-config.d.ts +0 -73
  132. package/lib/types/src/host/domain/terminal-target.d.ts +0 -132
  133. package/lib/types/src/host/domain/tool-requests.d.ts +0 -369
  134. package/lib/types/src/host/domain/transfer.d.ts +0 -260
  135. package/lib/types/src/host/infra/backend/local-backend.d.ts +0 -84
  136. package/lib/types/src/host/infra/backend/local-version.d.ts +0 -43
  137. package/lib/types/src/host/infra/backend/platform-local-backend.d.ts +0 -89
  138. package/lib/types/src/host/infra/backend/remote-backend.d.ts +0 -239
  139. package/lib/types/src/host/infra/cache/lru.d.ts +0 -52
  140. package/lib/types/src/host/infra/cache/versioned.d.ts +0 -77
  141. package/lib/types/src/host/infra/temp-name.d.ts +0 -19
  142. package/lib/types/src/host/infra/transport/agent/agent-protocol-client.d.ts +0 -132
  143. package/lib/types/src/host/infra/transport/agent/agent-protocol-codec.d.ts +0 -140
  144. package/lib/types/src/host/infra/transport/agent/agent-protocol-errors.d.ts +0 -41
  145. package/lib/types/src/host/infra/transport/agent/agent-protocol-frames.d.ts +0 -197
  146. package/lib/types/src/host/infra/transport/agent/agent-protocol-types.d.ts +0 -564
  147. package/lib/types/src/host/infra/transport/agent/agent-transport.d.ts +0 -418
  148. package/lib/types/src/host/infra/transport/agent-installer.d.ts +0 -121
  149. package/lib/types/src/host/infra/transport/agent-protocol-client.d.ts +0 -123
  150. package/lib/types/src/host/infra/transport/agent-protocol-codec.d.ts +0 -131
  151. package/lib/types/src/host/infra/transport/agent-protocol-errors.d.ts +0 -41
  152. package/lib/types/src/host/infra/transport/agent-protocol-frames.d.ts +0 -197
  153. package/lib/types/src/host/infra/transport/agent-protocol-types.d.ts +0 -509
  154. package/lib/types/src/host/infra/transport/agent-transport.d.ts +0 -353
  155. package/lib/types/src/host/infra/transport/alias-transport.d.ts +0 -206
  156. package/lib/types/src/host/infra/transport/askpass-fs.d.ts +0 -20
  157. package/lib/types/src/host/infra/transport/askpass.d.ts +0 -133
  158. package/lib/types/src/host/infra/transport/command-pool.d.ts +0 -61
  159. package/lib/types/src/host/infra/transport/fs-commands.d.ts +0 -140
  160. package/lib/types/src/host/infra/transport/git-status-route.d.ts +0 -63
  161. package/lib/types/src/host/infra/transport/git-status.d.ts +0 -101
  162. package/lib/types/src/host/infra/transport/node-spawn.d.ts +0 -26
  163. package/lib/types/src/host/infra/transport/session-window.d.ts +0 -51
  164. package/lib/types/src/host/infra/transport/shell-quote.d.ts +0 -59
  165. package/lib/types/src/host/infra/transport/ssh/alias-transport.d.ts +0 -206
  166. package/lib/types/src/host/infra/transport/ssh/askpass-fs.d.ts +0 -20
  167. package/lib/types/src/host/infra/transport/ssh/askpass.d.ts +0 -133
  168. package/lib/types/src/host/infra/transport/ssh/shell-quote.d.ts +0 -62
  169. package/lib/types/src/host/infra/transport/ssh/ssh-argv.d.ts +0 -43
  170. package/lib/types/src/host/infra/transport/ssh-argv.d.ts +0 -43
  171. package/lib/types/src/host/infra/transport/ssh2-transport.d.ts +0 -302
  172. package/lib/types/src/host/integration/agent/agent-install-io.d.ts +0 -33
  173. package/lib/types/src/host/integration/agent/askpass-registry.d.ts +0 -66
  174. package/lib/types/src/host/integration/agent-install-io.d.ts +0 -33
  175. package/lib/types/src/host/integration/agent-preflight.d.ts +0 -56
  176. package/lib/types/src/host/integration/anchor-directory.d.ts +0 -56
  177. package/lib/types/src/host/integration/askpass-registry.d.ts +0 -59
  178. package/lib/types/src/host/integration/bin-root-resolver.d.ts +0 -81
  179. package/lib/types/src/host/integration/connection-test.d.ts +0 -73
  180. package/lib/types/src/host/integration/file-reference-provider.d.ts +0 -115
  181. package/lib/types/src/host/integration/fs/git-status-wiring.d.ts +0 -21
  182. package/lib/types/src/host/integration/fs/platform-errors.d.ts +0 -94
  183. package/lib/types/src/host/integration/fs/remote-file-tools.d.ts +0 -369
  184. package/lib/types/src/host/integration/fs/remote-index.d.ts +0 -177
  185. package/lib/types/src/host/integration/fs-provider.d.ts +0 -226
  186. package/lib/types/src/host/integration/lsp/lsp-framing.d.ts +0 -38
  187. package/lib/types/src/host/integration/lsp/lsp-registry.d.ts +0 -67
  188. package/lib/types/src/host/integration/lsp/lsp-session.d.ts +0 -130
  189. package/lib/types/src/host/integration/management-tools.d.ts +0 -64
  190. package/lib/types/src/host/integration/recycle-bin-service.d.ts +0 -247
  191. package/lib/types/src/host/integration/remote/connection-test.d.ts +0 -73
  192. package/lib/types/src/host/integration/remote/remote-face.d.ts +0 -127
  193. package/lib/types/src/host/integration/remote/remote-tool-backend.d.ts +0 -108
  194. package/lib/types/src/host/integration/remote-face.d.ts +0 -127
  195. package/lib/types/src/host/integration/remote-file-tools.d.ts +0 -241
  196. package/lib/types/src/host/integration/remote-home.d.ts +0 -69
  197. package/lib/types/src/host/integration/remote-index.d.ts +0 -165
  198. package/lib/types/src/host/integration/remote-job-tools.d.ts +0 -295
  199. package/lib/types/src/host/integration/remote-tool-backend.d.ts +0 -97
  200. package/lib/types/src/host/integration/remote-tools.d.ts +0 -206
  201. package/lib/types/src/host/integration/root-registry.d.ts +0 -115
  202. package/lib/types/src/host/integration/roots/anchor-directory.d.ts +0 -56
  203. package/lib/types/src/host/integration/roots/bin-root-resolver.d.ts +0 -81
  204. package/lib/types/src/host/integration/roots/remote-home.d.ts +0 -69
  205. package/lib/types/src/host/integration/roots/root-registry.d.ts +0 -144
  206. package/lib/types/src/host/integration/roots/roots-wiring.d.ts +0 -219
  207. package/lib/types/src/host/integration/roots/session-root-index.d.ts +0 -52
  208. package/lib/types/src/host/integration/roots-api.d.ts +0 -407
  209. package/lib/types/src/host/integration/roots-wiring.d.ts +0 -211
  210. package/lib/types/src/host/integration/session/session-api.d.ts +0 -88
  211. package/lib/types/src/host/integration/session/session-bin-lock.d.ts +0 -80
  212. package/lib/types/src/host/integration/session/session-header.d.ts +0 -151
  213. package/lib/types/src/host/integration/session/session-labels.d.ts +0 -56
  214. package/lib/types/src/host/integration/session/session-route-wiring.d.ts +0 -50
  215. package/lib/types/src/host/integration/session-admin-service.d.ts +0 -236
  216. package/lib/types/src/host/integration/session-api.d.ts +0 -81
  217. package/lib/types/src/host/integration/session-bin-lock.d.ts +0 -80
  218. package/lib/types/src/host/integration/session-header.d.ts +0 -118
  219. package/lib/types/src/host/integration/session-labels.d.ts +0 -56
  220. package/lib/types/src/host/integration/session-route-wiring.d.ts +0 -50
  221. package/lib/types/src/host/integration/session-scope.d.ts +0 -113
  222. package/lib/types/src/host/integration/session-tools.d.ts +0 -44
  223. package/lib/types/src/host/integration/strict-arguments.d.ts +0 -79
  224. package/lib/types/src/host/integration/takeover/takeover-api.d.ts +0 -62
  225. package/lib/types/src/host/integration/takeover/takeover-route-wiring.d.ts +0 -60
  226. package/lib/types/src/host/integration/takeover/takeover-service.d.ts +0 -167
  227. package/lib/types/src/host/integration/terminal-manifest.d.ts +0 -94
  228. package/lib/types/src/host/integration/tools/management-tools.d.ts +0 -245
  229. package/lib/types/src/host/integration/tools/remote-job-tools.d.ts +0 -316
  230. package/lib/types/src/host/integration/tools/remote-lsp-tools.d.ts +0 -43
  231. package/lib/types/src/host/integration/tools/remote-tools.d.ts +0 -236
  232. package/lib/types/src/host/integration/tools/session-target.d.ts +0 -52
  233. package/lib/types/src/host/integration/tools/session-tools.d.ts +0 -46
  234. package/lib/types/src/host/integration/tools/strict-arguments.d.ts +0 -79
  235. package/lib/types/src/host/integration/tools/terminal-manifest.d.ts +0 -94
  236. package/lib/types/src/host/integration/transfer/remote-copy.d.ts +0 -66
  237. package/lib/types/src/host/integration/transfer/transfer-adapters.d.ts +0 -48
  238. package/lib/types/src/host/integration/transfer/transfer-tracker.d.ts +0 -106
  239. package/lib/types/src/host/integration/transfer-adapters.d.ts +0 -44
  240. package/lib/types/src/host/integration/transfer-service.d.ts +0 -164
  241. package/lib/types/src/host/integration/transfer-tracker.d.ts +0 -106
  242. package/lib/types/src/host/integration/user-roots.d.ts +0 -461
  243. package/lib/types/src/wiring/connections.d.ts +0 -189
  244. package/lib/types/src/wiring/fs.d.ts +0 -13
  245. package/lib/types/src/wiring/install-memo.d.ts +0 -32
  246. package/lib/types/src/wiring/legacy-dirs.d.ts +0 -62
  247. package/lib/types/src/wiring/package-paths.d.ts +0 -35
  248. package/lib/types/src/wiring/roots.d.ts +0 -21
  249. package/lib/types/src/wiring/state-dir.d.ts +0 -29
  250. package/lib/types/src/wiring/tools.d.ts +0 -35
@@ -1,133 +0,0 @@
1
- /**
2
- * Non-interactive **password** authentication for the system `ssh` client, via `SSH_ASKPASS`.
3
- *
4
- * Why this module exists: the Tier 2 agent is launched by spawning `ssh` (`ssh <alias> <agent> --stdio`),
5
- * and the alias transport runs every command the same way. System `ssh` cannot read a password from a pipe,
6
- * so a password-only connection used to be impossible on any transport that goes through `ssh` — which made
7
- * "default to Tier 2" silently false for password connections (they were downgraded to `ssh2`). That was
8
- * never a property of SSH: OpenSSH ≥ 8.4 supports `SSH_ASKPASS_REQUIRE=force`, which runs a helper program
9
- * to obtain the secret **even with no tty**, exactly the situation a background plugin is in.
10
- *
11
- * Two rules make this safe:
12
- *
13
- * 1. **The secret never touches the disk.** The helper program carries no secret; it forwards the value of
14
- * an environment variable (`DSH_SSH_ASKPASS_SECRET`) that the ssh child process inherits. A leftover
15
- * helper file therefore leaks nothing: with the variable absent it prints an empty line and ssh fails
16
- * the authentication instead of succeeding with a stale credential.
17
- * 2. **The secret is never interpolated into a shell or command line.** It travels only as an environment
18
- * value, so characters like `&`, `|`, `%`, `^` and quotes need no escaping (a `cmd`-based helper that
19
- * echoed the secret would break on those, and its argv would be visible in the process list).
20
- *
21
- * Verified on the real host (Windows, OpenSSH_for_Windows_9.5p1): password auth succeeds through a spawned
22
- * `ssh` whose stdio are pipes, and a **wrong** secret fails — so the helper is genuinely what authenticates.
23
- *
24
- * @module dsh-remote-workspace/infra/transport/askpass
25
- */
26
- /** The interpreter that runs the helper script. */
27
- export interface AskpassInterpreter {
28
- /** Absolute path of the executable (`node`/Electron). */
29
- readonly execPath: string;
30
- /** `'win32'` or a POSIX platform id; decides which shim shape is written. */
31
- readonly platform: string;
32
- }
33
- /** The two files a helper is made of, and the exact text written to each. */
34
- export interface AskpassFiles {
35
- /** The program `SSH_ASKPASS` points at. */
36
- readonly helperPath: string;
37
- /** The script the helper delegates to. */
38
- readonly scriptPath: string;
39
- /** Contents of {@link scriptPath}; carries no secret. */
40
- readonly script: string;
41
- /** Contents of {@link helperPath}; carries no secret. */
42
- readonly helper: string;
43
- /** Mode to create the files with (POSIX needs the helper executable). */
44
- readonly mode: number;
45
- }
46
- /**
47
- * The helper script: print the secret from the environment, then a newline.
48
- *
49
- * A trailing newline is required — an ssh askpass program whose output lacks one is rejected
50
- * (measured: `<nul set /p =` without a newline failed while `echo` succeeded).
51
- */
52
- export declare function askpassScript(): string;
53
- /**
54
- * The program `SSH_ASKPASS` names.
55
- *
56
- * Windows: a `cmd` shim, because ssh executes the path directly and a `.mjs` is not executable there.
57
- * POSIX: a `sh` script. Both only *launch* the interpreter with the script path, so the secret is never
58
- * quoted into a command line.
59
- *
60
- * @param interpreter - interpreter and platform.
61
- * @param scriptPath - absolute path of {@link askpassScript}'s file.
62
- * @returns the shim text.
63
- */
64
- export declare function askpassHelper(interpreter: AskpassInterpreter, scriptPath: string): string;
65
- /**
66
- * Build the files for one helper directory.
67
- *
68
- * @param dir - directory to place the helper in.
69
- * @param interpreter - interpreter and platform.
70
- * @returns the file plan (paths plus contents).
71
- */
72
- export declare function planAskpassFiles(dir: string, interpreter: AskpassInterpreter): AskpassFiles;
73
- /**
74
- * The environment that makes the system `ssh` ask {@link AskpassFiles.helperPath} for the password.
75
- *
76
- * `ELECTRON_RUN_AS_NODE=1` is set unconditionally: this plugin normally runs inside the Electron desktop
77
- * app, where `process.execPath` is the Electron binary and would otherwise open a GUI instead of running
78
- * the script. Real `node` ignores the variable, so one code path covers both hosts.
79
- *
80
- * `DISPLAY` is set because pre-8.4 OpenSSH only consults `SSH_ASKPASS` when it is non-empty, and
81
- * `SSH_ASKPASS_REQUIRE=force` because ≥ 8.4 additionally requires it when a tty might exist. Setting both
82
- * makes the helper work on either generation.
83
- *
84
- * @param files - the helper plan.
85
- * @param secret - the password; only ever passed here, never written to a file.
86
- * @returns environment entries to merge into the `ssh` child's environment.
87
- */
88
- export declare function askpassEnvironment(files: AskpassFiles, secret: string): Record<string, string>;
89
- /** Filesystem surface this module needs; injected so tests never touch a real disk. */
90
- export interface AskpassIo {
91
- /** Create `dir` (and parents). */
92
- mkdir(dir: string): Promise<void>;
93
- /** Write `content` to `path`, optionally with a POSIX mode. */
94
- writeFile(path: string, content: string, mode: number): Promise<void>;
95
- /** Remove `dir` recursively; never throws when it is already gone. */
96
- remove(dir: string): Promise<void>;
97
- /** Create a private directory to hold one helper. */
98
- makeTempDir(): Promise<string>;
99
- }
100
- /** A live helper: the environment to hand `ssh`, plus a way to take it away again. */
101
- export interface AskpassHandle {
102
- /** Environment entries for the `ssh` child process. */
103
- readonly env: Record<string, string>;
104
- /** Delete the helper directory. Safe to call more than once. */
105
- dispose(): Promise<void>;
106
- }
107
- /** Options for {@link createAskpass}. */
108
- export interface AskpassOptions {
109
- /** The password. Held in memory only. */
110
- readonly secret: string;
111
- /** Interpreter facts; defaults to this process. */
112
- readonly interpreter?: AskpassInterpreter;
113
- /** Injected filesystem. */
114
- readonly io: AskpassIo;
115
- }
116
- /**
117
- * Create a password helper and the environment that uses it.
118
- *
119
- * @param options - secret, interpreter and injected filesystem.
120
- * @returns the handle; call {@link AskpassHandle.dispose} when the connection goes away.
121
- */
122
- export declare function createAskpass(options: AskpassOptions): Promise<AskpassHandle>;
123
- /**
124
- * Whether a connection's password can be handed to the system `ssh` at all.
125
- *
126
- * Only `authKind: 'password'` needs the helper: key and agent connections never prompt, and forcing
127
- * `BatchMode=no` for them would let a misconfigured host block on an interactive prompt forever.
128
- *
129
- * @param authKind - the connection's authentication mode.
130
- * @returns true when the askpass helper must be wired in.
131
- */
132
- export declare function needsAskpass(authKind: 'agent' | 'key' | 'password'): boolean;
133
- //# sourceMappingURL=askpass.d.ts.map
@@ -1,61 +0,0 @@
1
- /**
2
- * Per-connection command session pool.
3
- *
4
- * Reusing one established session is what turns "one TCP + SSH handshake per command" into the
5
- * ≈15× speedup the requirements ask for. The pool owns three concerns:
6
- * - single-flight connection establishment per connection id;
7
- * - a FIFO concurrency limit per connection;
8
- * - idle eviction, so a forgotten connection does not hold a remote session forever.
9
- *
10
- * @module dsh-remote-workspace/infra/transport/command-pool
11
- */
12
- /** A pooled connection handle; the pool never inspects it. */
13
- export interface PooledConnection {
14
- close(): Promise<void>;
15
- }
16
- /** Pool configuration. */
17
- export interface CommandPoolOptions {
18
- /** Maximum commands in flight on one connection. */
19
- readonly maxConcurrentPerConnection: number;
20
- /** Close a connection that has been idle for this long. */
21
- readonly idleTtlMs: number;
22
- /** Establish a connection on first use. */
23
- readonly open: (connectionId: string) => Promise<PooledConnection>;
24
- /** Injectable clock for deterministic tests. */
25
- readonly now?: () => number;
26
- }
27
- /** Per-connection counters. */
28
- export interface PoolStats {
29
- readonly opens: number;
30
- readonly reuses: number;
31
- readonly active: number;
32
- readonly queued: number;
33
- readonly idleClosed: number;
34
- readonly failures: number;
35
- }
36
- /** Bounded, idle-evicting pool of remote command sessions. */
37
- export declare class CommandPool {
38
- #private;
39
- constructor(options: CommandPoolOptions);
40
- /** Connection ids currently tracked. */
41
- get connectionIds(): readonly string[];
42
- /**
43
- * Run one task against the pooled connection, opening it on first use.
44
- *
45
- * @param connectionId - pool key (a connection profile id).
46
- * @param task - receives the pooled connection; its rejection propagates to the caller.
47
- * @returns the task result.
48
- */
49
- run<T>(connectionId: string, task: (connection: PooledConnection) => Promise<T>): Promise<T>;
50
- /**
51
- * Close connections that have been idle past the TTL.
52
- *
53
- * @returns the number of connections closed.
54
- */
55
- sweep(): Promise<number>;
56
- /** Close every connection; safe to call during plugin disposal. */
57
- closeAll(): Promise<void>;
58
- /** Counters for one connection, or zeros when it is not tracked. */
59
- stats(connectionId: string): PoolStats;
60
- }
61
- //# sourceMappingURL=command-pool.d.ts.map
@@ -1,140 +0,0 @@
1
- /**
2
- * Shell commands for the file-write primitives: offset read, positioned write, rename, remove.
3
- *
4
- * These live in one module because three transports (alias, agent) execute them and the ssh2 transport
5
- * deliberately does the same operations through SFTP instead — if the two paths disagree, one of them is
6
- * wrong and nobody notices until a user's file is truncated.
7
- *
8
- * Two guarantees worth naming, because both are easy to get wrong with shell tools:
9
- *
10
- * - **rename must not degrade into a copy.** Coreutils `mv` silently copies and unlinks when `rename(2)`
11
- * fails on another filesystem, which would break "move first, confirm, then delete" recycle semantics
12
- * (the copy is not atomic and the source may survive). The command therefore compares device ids and
13
- * fails loudly instead.
14
- * - **removing a directory without `recursive` must fail, not half-succeed.** `rm -f` on a directory does
15
- * nothing while reporting success on some platforms.
16
- *
17
- * @module dsh-over-ssh/infra/transport/fs-commands
18
- */
19
- /** Marker printed when a command refuses to do something the caller must know about. */
20
- export declare const DSH_COMMAND_ERROR = "DSH_ERROR=";
21
- /**
22
- * Read `[offset, offset+maxBytes)` of a file as base64, with the file's size and mtime as a header.
23
- *
24
- * `tail -c +N` is 1-based, hence the `+1`. `head -c` bounds the payload before it crosses the wire.
25
- *
26
- * @param path - absolute remote path.
27
- * @param offset - 0-based start offset.
28
- * @param maxBytes - maximum bytes to return.
29
- * @returns the shell script (stdout: `DSH_SIZE=`/`DSH_MTIME=` lines, then base64).
30
- */
31
- export declare function readRangeCommand(path: string, offset: number, maxBytes: number): string;
32
- /**
33
- * Write `bytes` (fed on stdin as base64) at `offset`, leaving earlier bytes untouched.
34
- *
35
- * The aligned fast path matters: `dd bs=1` is one syscall per byte, so a 4 MiB chunk at a 4 KiB-aligned
36
- * offset (the normal case for chunked uploads) would be ~4000× slower than it needs to be.
37
- *
38
- * @param path - absolute remote path.
39
- * @param offset - 0-based offset to write at.
40
- * @param createParents - create missing parent directories first.
41
- * @returns the shell script (stdin: base64 payload).
42
- */
43
- export declare function writeRangeCommand(path: string, offset: number, createParents: boolean): string;
44
- /**
45
- * Create a directory.
46
- *
47
- * `recursive: false` **fails** on an existing target (`mkdir` without `-p` reports `EEXIST`), which is the
48
- * behaviour a 「新建目录」 dialog needs: silently succeeding on a name that is already taken would look like a
49
- * successful creation and then show the user someone else's folder.
50
- *
51
- * @param path - absolute remote path.
52
- * @param recursive - create parents and tolerate an existing directory.
53
- * @returns the shell script.
54
- */
55
- export declare function mkdirCommand(path: string, recursive: boolean): string;
56
- /**
57
- * Print the **device id** of one path, so a caller can tell whether a `rename` between two paths stays on one
58
- * filesystem.
59
- *
60
- * Why this exists: the recycle bin's guarantee is "move first, then confirm", and `renameCommand` refuses a
61
- * cross-device move rather than degrading to a copy. Choosing a bin location therefore requires knowing whether
62
- * the candidate directory shares the root's filesystem — the plugin's own `$HOME` looks like the tidy answer and
63
- * is usually a **different mount** on the sites this runs on (NFS/automount homes), which would make every
64
- * delete fail. Measured here, never guessed.
65
- *
66
- * Both `stat` spellings are tried (GNU `-c %d`, BSD/macOS `-f %d`), and the answer is printed under a header so
67
- * a shell banner or a warning on stdout cannot be mistaken for it. A path that cannot be stat'ed prints nothing
68
- * — the caller treats that as "unknown", which is a different answer from "different device".
69
- *
70
- * @param path - absolute path to inspect.
71
- * @returns the shell script.
72
- */
73
- export declare function deviceIdCommand(path: string): string;
74
- /**
75
- * Parse the device id printed by {@link deviceIdCommand}.
76
- *
77
- * @param stdout - the command's stdout.
78
- * @returns the device id, or `undefined` when the command could not answer.
79
- */
80
- export declare function parseDeviceId(stdout: string): string | undefined;
81
- /**
82
- * Change one path's permission bits.
83
- *
84
- * `mode` is an **octal digit string** (`"755"`, `"0644"`, `"4755"`), never a number: a decimal `755` is
85
- * meaningless to `chmod`, and the tool layer normalises both spellings to this one so nothing downstream has
86
- * to guess. The digits are re-validated here rather than trusted — this function's output is a shell script,
87
- * and a caller that forgot its own check must not be able to inject one.
88
- *
89
- * Both tiers run this through their own `exec` (the agent has no `fs.chmod`), so `remote_write`'s `mode` needs
90
- * no protocol change and behaves identically on Tier 1 and Tier 2.
91
- *
92
- * @param path - absolute remote path.
93
- * @param mode - 3- or 4-digit octal permission string.
94
- * @returns the shell script.
95
- * @throws Error when `mode` is not an octal string.
96
- */
97
- export declare function chmodCommand(path: string, mode: string): string;
98
- /**
99
- * Rename/move a path, refusing to copy across devices and refusing to clobber.
100
- *
101
- * **The no-clobber guard is not optional.** `mv -f` replaces a file, and `mv -f src dst` where `dst` is an
102
- * existing *directory* moves `src` **inside** it — two completely different outcomes from the same command,
103
- * both silent. A rename dialog must not be able to produce either: it asks to rename A to B, so B existing is
104
- * a refusal, not a merge. `-n` (no-clobber) is not portable enough to rely on alone, so the check is explicit.
105
- *
106
- * @param from - source path.
107
- * @param to - destination path.
108
- * @param createParents - create the destination's parent directories.
109
- * @returns the shell script.
110
- */
111
- export declare function renameCommand(from: string, to: string, createParents: boolean): string;
112
- /**
113
- * Remove a file, or a directory tree when `recursive` is set.
114
- *
115
- * @param path - absolute remote path.
116
- * @param recursive - allow removing directories and their contents.
117
- * @returns the shell script.
118
- */
119
- export declare function removeCommand(path: string, recursive: boolean): string;
120
- /** Header cap callers should pass when executing these commands. */
121
- export declare const FS_COMMAND_MAX_BYTES: number;
122
- /**
123
- * Parse a `DSH_ERROR=…` refusal out of a command's output.
124
- *
125
- * @param stdout - captured stdout.
126
- * @param stderr - captured stderr.
127
- * @returns the code after `DSH_ERROR=`, or `undefined` when the command did not refuse.
128
- */
129
- export declare function commandRefusal(stdout: string, stderr: string): string | undefined;
130
- /**
131
- * Read one `PREFIX<number>` header line.
132
- *
133
- * @param stdout - command output.
134
- * @param prefix - header prefix, including `=`.
135
- * @returns the number, or `undefined` when absent or not finite.
136
- */
137
- export declare function parseHeaderNumber(stdout: string, prefix: string): number | undefined;
138
- /** The payload after the last header line, for commands that print base64 last. */
139
- export declare function payloadAfterHeaders(stdout: string, lastHeader: string): string;
140
- //# sourceMappingURL=fs-commands.d.ts.map
@@ -1,63 +0,0 @@
1
- /**
2
- * The same-origin HTTP route the directory browser uses to read remote git status.
3
- *
4
- * A separate route rather than another action on the roots route: the roots route's actions are the panel's
5
- * **state machine** (add/remove/list/edit), while this is a read-only observation with its own TTL cache and
6
- * its own failure vocabulary ("no badges" is not a listing failure). Keeping them apart means a git hiccup can
7
- * never make a directory listing look failed, which is exactly the degradation the UI promises.
8
- *
9
- * Same carrier pattern as the roots/session routes (`ctx.inject(['webServer'], …)`): the packaged runtime
10
- * constructs the browser carrier after the plugin entries activate, so a bare `ctx.get('webServer')` would miss
11
- * it and the browser would show `http-404` with the plugin looking healthy.
12
- *
13
- * Trust is the **same fence** as the other mutating/observing routes: same-origin only (`Host` vs `Origin`,
14
- * `Sec-Fetch-Site`), reused from the roots route rather than re-implemented, so the two cannot drift apart.
15
- *
16
- * @module dsh-over-ssh/infra/transport/git-status-route
17
- */
18
- import { type RootsApiRequest, type RootsApiResponse } from '../../app/roots/roots-api-contract.ts';
19
- import type { GitStatusService, GitStatusSnapshot } from './git-status.ts';
20
- /** The exact path this route is served at. The client duplicates it (it cannot import host modules). */
21
- export declare const GIT_STATUS_API_PATH = "/api/over-ssh/git-status";
22
- /** The browser HTTP carrier, narrowed to the one method this route needs. */
23
- export interface GitStatusRouteHost {
24
- register(route: {
25
- readonly kind: 'exact';
26
- readonly path: string;
27
- readonly handler: (req: never, res: never) => Promise<void>;
28
- }): () => void;
29
- }
30
- /** A provider that hands the carrier over when it appears (the real one is `ctx`). */
31
- export interface GitStatusRouteHostProvider {
32
- inject(names: readonly string[], callback: (scoped: {
33
- get(name: string): unknown;
34
- }) => void | (() => void)): unknown;
35
- }
36
- /** The handler factory's dependencies. */
37
- export interface GitStatusApiDeps {
38
- readonly service: Pick<GitStatusService, 'status'>;
39
- }
40
- /** One answer: the snapshot, projected for the browser (no backend/transport details leave the host). */
41
- export declare function toPublicAnswer(snapshot: GitStatusSnapshot): Record<string, unknown>;
42
- /**
43
- * Build the route handler (decoupled from cordis, so tests drive it with fake req/res).
44
- *
45
- * @param deps - the git status service.
46
- * @returns the handler pair.
47
- */
48
- export declare function createGitStatusApi(deps: GitStatusApiDeps): {
49
- readonly handle: (req: RootsApiRequest, res: RootsApiResponse) => Promise<void>;
50
- };
51
- /**
52
- * Register the route on the browser carrier, whenever that carrier appears.
53
- *
54
- * Best effort by construction: a composition without `webServer` (headless) has no browser, so losing this route
55
- * must not fail activation. Registration errors (an exact-path collision with another plugin) are swallowed on
56
- * purpose — the route is a convenience for a panel, not a contract the plugin depends on.
57
- *
58
- * @param provider - the deferred carrier (`ctx` in the composition).
59
- * @param deps - the git status service.
60
- * @returns nothing; the registration lives and dies with the plugin fiber.
61
- */
62
- export declare function registerGitStatusRoute(provider: GitStatusRouteHostProvider, deps: GitStatusApiDeps): void;
63
- //# sourceMappingURL=git-status-route.d.ts.map
@@ -1,101 +0,0 @@
1
- /**
2
- * Remote git status: one thin service with a **bounded** cache, in front of `git.status`.
3
- *
4
- * Why a service instead of putting this on {@link RemoteBackend}: the caller (the directory browser) asks about
5
- * a *browsed directory*, not about a root, and it asks once per level; the resolution root→(connection, path)
6
- * and the TTL cache are the same for every backend. `@deepseek-ai/dsh-api-workspace-files`-style consumers poll
7
- * far more often than a human navigates, so an uncached round trip per listing would be one git process per
8
- * keystroke-adjacent event.
9
- *
10
- * Cache discipline follows the repository's rule (count cap + byte cap + TTL, all named):
11
- * - **TTL 5 s** — the UI shows a badge set that is one navigation old; 5 s is short enough that a save is
12
- * visible on the next level change, long enough that a back-and-forth navigation costs no git process;
13
- * - **entries cap 64** — one entry per (connection, root); more roots than that is not a browsing session;
14
- * - **bytes cap 4 MiB** — the retained snapshots are capped too (2000 changes / 512 KiB of paths each), so the
15
- * cache cannot grow with a repository's size.
16
- *
17
- * Tier 1 has **no** fallback by decision: there is no protocol frame, and shelling out `git status` from the
18
- * host would reintroduce command assembly/quoting into the browser's data path while Tier 1 cannot even probe
19
- * whether the directory is a work tree. The service answers `available: false` and the UI draws no badges.
20
- *
21
- * @module dsh-over-ssh/infra/transport/git-status
22
- */
23
- import type { AgentGitChangeStatus } from './agent/agent-protocol-types.ts';
24
- import { type VersionedCacheStats } from '../cache/versioned.ts';
25
- /** One normalized change status (the agent normalizes porcelain's XY columns into exactly these). */
26
- export type GitChangeStatus = AgentGitChangeStatus;
27
- /** One changed path, relative to the queried root. */
28
- export interface GitStatusChange {
29
- readonly path: string;
30
- readonly status: GitChangeStatus;
31
- }
32
- /**
33
- * What one browser level needs to draw badges.
34
- *
35
- * `available: false` is a **normal** answer (Tier 1, an old agent, a non-work-tree root): the browser draws no
36
- * badges and keeps browsing. `reason` is diagnostics only — never shown as a listing failure.
37
- */
38
- export interface GitStatusSnapshot {
39
- readonly available: boolean;
40
- readonly reason?: string;
41
- /** Root the answer belongs to, when there is one. */
42
- readonly root?: string;
43
- /** The browsed directory, relative to {@link root} ('' when the browsed path *is* the root). */
44
- readonly directory?: string;
45
- /** Branch name; absent for a detached HEAD (the UI must not substitute one). */
46
- readonly branch?: string;
47
- /** Changes **relative to {@link root}** (the UI joins them with {@link directory}). */
48
- readonly changes: readonly GitStatusChange[];
49
- /** One of the agent's/this service's caps fired, so the list is a prefix. */
50
- readonly truncated: boolean;
51
- }
52
- /** One query: which connection, which browsed remote path. */
53
- export interface GitStatusQuery {
54
- readonly connectionId: string;
55
- readonly path: string;
56
- }
57
- /** Everything {@link createGitStatusService} needs, injected so tests need no transport and no clock. */
58
- export interface GitStatusServiceDeps {
59
- /** Resolve one connection's transport; `undefined` means Tier 1 / not configured. */
60
- readonly transportFor: (connectionId: string) => Promise<unknown> | unknown;
61
- /**
62
- * The remote root that contains `path`, or `undefined` when no registered root covers it.
63
- *
64
- * Root-local rather than global: `git status` paths are relative to the repository root, and the browser
65
- * matches them against the level it listed, so the service must know which root the answer belongs to.
66
- */
67
- readonly resolveRoot: (connectionId: string, path: string) => string | undefined;
68
- readonly now?: () => number;
69
- /** Freshness window; default {@link DEFAULT_GIT_STATUS_TTL_MS}. */
70
- readonly ttlMs?: number;
71
- readonly maxEntries?: number;
72
- readonly maxBytes?: number;
73
- /** Per-snapshot caps (independent of the cache caps): more changes than this are cut with `truncated`. */
74
- readonly maxChanges?: number;
75
- readonly maxPathBytes?: number;
76
- }
77
- /** Defaults, all named (repository rule: a cache names a count cap, a byte cap and a TTL). */
78
- export declare const DEFAULT_GIT_STATUS_TTL_MS = 5000;
79
- export declare const DEFAULT_GIT_STATUS_MAX_ENTRIES = 64;
80
- export declare const DEFAULT_GIT_STATUS_MAX_BYTES: number;
81
- export declare const DEFAULT_GIT_STATUS_MAX_CHANGES = 2000;
82
- export declare const DEFAULT_GIT_STATUS_MAX_PATH_BYTES: number;
83
- /** The status→(code, UI) table is owned by the agent; this service only caps and caches. */
84
- export interface GitStatusService {
85
- /** Read one browsed directory's badge data (cached). */
86
- status(query: GitStatusQuery, signal?: AbortSignal): Promise<GitStatusSnapshot>;
87
- /** Drop the cached snapshot of one connection (its transport was retired or edited). */
88
- invalidate(connectionId?: string): void;
89
- /** Cache counters, for diagnostics and tests. */
90
- readonly cacheStats: VersionedCacheStats;
91
- }
92
- export declare function createGitStatusService(deps: GitStatusServiceDeps): GitStatusService;
93
- /**
94
- * The browsed directory, relative to the root ('' when they are the same).
95
- *
96
- * Both sides are normalized first: the caller's path may carry a trailing slash, and the root comes from the
97
- * registry. A path outside the root cannot happen (`resolveRoot` only answers covering roots) but returns the
98
- * empty string rather than a bogus relative path.
99
- */
100
- export declare function relativeDirectory(root: string, path: string): string;
101
- //# sourceMappingURL=git-status.d.ts.map
@@ -1,26 +0,0 @@
1
- /**
2
- * The real process spawner behind {@link AliasTransport}.
3
- *
4
- * The transport itself never touches `node:child_process`, which is what keeps its tests
5
- * deterministic; this module is the thin, deliberately boring adapter that runs the system `ssh`.
6
- *
7
- * Bounded everywhere: stdout/stderr are capped (a chatty remote command must not grow memory),
8
- * a deadline kills the child, and an abort signal kills it too. `stdin` is written once and then
9
- * closed, so a command that reads input does not hang the plugin.
10
- *
11
- * @module dsh-over-ssh/infra/transport/node-spawn
12
- */
13
- import type { SpawnFn, SpawnOptions, SpawnResult } from './ssh/alias-transport.ts';
14
- /**
15
- * Build the spawner used in production.
16
- *
17
- * @param options - optional binary overrides for tests and non-default installations.
18
- * @returns a `SpawnFn` compatible with the alias transport.
19
- */
20
- export declare function createNodeSpawner(options?: {
21
- readonly defaultTimeoutMs?: number;
22
- readonly maxBytes?: number;
23
- }): SpawnFn;
24
- /** Narrow view of the spawner's options, re-exported for callers that build their own. */
25
- export type { SpawnFn, SpawnOptions, SpawnResult };
26
- //# sourceMappingURL=node-spawn.d.ts.map
@@ -1,51 +0,0 @@
1
- /**
2
- * 客户端侧的在飞窗口记账(镜像代理的 `sessionTable`,见 protocol.md §9.3)。
3
- *
4
- * 为什么单独成类:这段逻辑有**自己的状态**(连接级在飞数、每会话在飞/排队计数、等待者队列)
5
- * 和**自己的不变量**(预留名额只给"一个都没占"的会话;取消与名额释放必须都能唤醒等待者),
6
- * 却和"帧编解码 / RPC 关联 / blob 通道"挤在同一个 3.4k 行文件里。抽出来之后:
7
- *
8
- * 1. 它**不依赖**任何传输细节,可以脱离 ssh 与协议单独测(`tests/session-window.test.ts`);
9
- * 2. `AgentProtocolClient` 只剩"发请求 / 收响应"的编排;
10
- * 3. 代理侧的 `sessionTable` 与它是同一个模型的两种实现,两边的注释可以互相对照。
11
- *
12
- * 三条规则与代理侧 `takeLocked` 逐条对应:
13
- * ① 每会话上限 = `window / 参与会话数`(至少 1);
14
- * ② 总在飞不得超过 `window + 1`;
15
- * ③ 超出 `window` 的那一个名额只发给当前 `in-flight == 0` 的会话("留给新会话的门")。
16
- *
17
- * @module dsh-over-ssh/infra/transport/session-window
18
- */
19
- export declare class SessionWindow {
20
- #private;
21
- constructor(maxInFlight: number);
22
- /** Slots held right now (diagnostics and tests). */
23
- get inFlight(): number;
24
- /** The configured connection-wide window. */
25
- get max(): number;
26
- /**
27
- * Wait for a slot of `session`'s share and commit it.
28
- *
29
- * `isLost` lets the owner abort the wait when the connection is declared dead: the loop condition
30
- * mirrors the pre-extraction behaviour exactly (wake up, re-check, then either throw `CANCELLED`
31
- * or admit).
32
- */
33
- acquire(session: string, signal?: AbortSignal, isLost?: () => boolean): Promise<void>;
34
- /** Release one slot of `session` and wake every parked caller (they re-check their own share). */
35
- release(session: string): void;
36
- /** Sessions that currently hold a slot or are parked; used for the per-session cap. */
37
- engagedSessions(): number;
38
- /** Per-session in-flight cap, mirroring the agent's `window / engagedSessions` (at least 1). */
39
- sessionCap(): number;
40
- /** Whether `session` may take a slot right now (same three rules as the agent's `takeLocked`). */
41
- canAdmit(session: string): boolean;
42
- /** Commit the slot {@link canAdmit} promised. */
43
- admit(session: string): void;
44
- /** Register a parked caller for `session` (so it counts as engaged while it waits). */
45
- park(session: string): void;
46
- /** Unregister a parked caller (it is about to proceed or give up). */
47
- unpark(session: string): void;
48
- /** Wake every parked caller (a slot freed up, or the connection died). */
49
- wakeAllWaiters(): void;
50
- }
51
- //# sourceMappingURL=session-window.d.ts.map
@@ -1,59 +0,0 @@
1
- /**
2
- * POSIX shell quoting for remote command construction.
3
- *
4
- * Remote commands are the plugin's one injection surface: `ssh <alias> <command>` runs the
5
- * command through the remote login shell, so every interpolated value must be quoted. The
6
- * `argv`-first design keeps quoting to the places that genuinely need a shell.
7
- *
8
- * @module dsh-remote-workspace/infra/transport/shell-quote
9
- */
10
- /**
11
- * Quote one value for a POSIX shell so it cannot be interpreted.
12
- *
13
- * Uses single quotes; an embedded single quote is closed, escaped and reopened.
14
- *
15
- * @param value - raw value.
16
- * @returns a shell-safe literal.
17
- */
18
- export declare function shellQuote(value: string): string;
19
- /** Quote several values and join them with spaces. */
20
- export declare function shellQuoteAll(values: readonly string[]): string;
21
- /** How a remote command is assembled. */
22
- export interface RemoteCommandOptions {
23
- /** Directory to `cd` into before running; omitted leaves the remote default. */
24
- readonly cwd?: string;
25
- /** Environment assignments applied to the command only. */
26
- readonly env?: Readonly<Record<string, string>>;
27
- }
28
- /**
29
- * Build a remote command string from an argv vector.
30
- *
31
- * @param argv - executable followed by arguments; never shell-interpreted as a whole.
32
- * @param options - optional `cwd` and environment.
33
- * @returns a command string safe to pass as the single `ssh` command argument.
34
- * @throws SshDevError when `argv` is empty or a value carries a NUL.
35
- */
36
- export declare function buildRemoteCommand(argv: readonly string[], options?: RemoteCommandOptions): string;
37
- /**
38
- * Prefix lines that make a **script** honour `cwd` and `env`.
39
- *
40
- * The argv path builds these into one command; the script path must apply them too, because dropping them
41
- * silently is the worst outcome — a real-host run showed `remote_exec { cwd: 'src' }` running in `$HOME` and
42
- * reporting success. Shared by every shell transport so the two paths cannot drift apart again.
43
- *
44
- * @param request - requested `cwd` and environment.
45
- * @returns prefix lines, `cd` first; empty when neither was requested.
46
- * @throws SshDevError when an environment name is not a shell identifier.
47
- */
48
- export declare function scriptPrefixes(request: RemoteCommandOptions): readonly string[];
49
- /**
50
- * Build a remote command from a raw script body.
51
- *
52
- * The caller owns the script text; values interpolated into it must already be quoted with
53
- * {@link shellQuote}.
54
- *
55
- * @param script - POSIX shell script body.
56
- * @returns the command string.
57
- */
58
- export declare function buildRemoteScript(script: string): string;
59
- //# sourceMappingURL=shell-quote.d.ts.map