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,182 +0,0 @@
1
- /**
2
- * roots-api-support
3
- *
4
- * 请求/响应工具、公共投影与 body 读取——被分发器与三个 handler 家族共用。
5
- *
6
- * 从 `roots-api.ts` 的 `serveAction`(543 行 / 15 个 case)拆出(审计 0076):
7
- * case 体逐字搬移,只把 `return;` 改成 `return true;`,未命中时返回 `false` 由分发器报 400。
8
- *
9
- * @module dsh-remote-workspace/app/roots-api-support
10
- */
11
- import { type ConnectionPatch, type UserRootEntry, type UserRootsState } from './user-roots.ts';
12
- import type { RootsApiRequest, RootsApiResponse, RootsApiDeps } from './roots-api-contract.ts';
13
- export declare function readBody(req: RootsApiRequest): Promise<string>;
14
- export declare function toBytes(chunk: unknown): Uint8Array;
15
- /**
16
- * Whitelist one live root, dropping everything else it carries (argv, anchor paths, transports).
17
- *
18
- * Both spellings the Lead may hand over are accepted: a bare `RootRef` and a `RootRecord`
19
- * (`{ key, root, backend }` — what `RootRegistry.records` returns). Reading the nested `root` here is what
20
- * keeps a wiring mistake from showing every root as `location: "unknown", path: ""`.
21
- */
22
- export declare function publicRoot(raw: unknown): PublicRoot;
23
- /**
24
- * The live registry's own key for one persisted entry, or `undefined` when it is not live.
25
- *
26
- * The comparison goes through `sameUserRootKey` rather than `===`: the registry lower-cases Windows local
27
- * paths (`domain/root.ts`'s `rootKey`), the persisted file keeps the caller's case, and the client rebuilds
28
- * the key from the `path` the answer carried. Comparing them verbatim made a Windows local root impossible to
29
- * remove - the file entry went, the live root stayed, and the row then had no delete button because it was no
30
- * longer in the file.
31
- *
32
- * @param deps - the injected seams (only `listRoots` is read).
33
- * @param entry - the entry to look for.
34
- * @returns the key the registry holds it under, or `undefined`.
35
- */
36
- export declare function matchedLiveKey(deps: RootsApiDeps, entry: UserRootEntry): Promise<string | undefined>;
37
- /**
38
- * Read one live record as a root key, matching it against `entry`.
39
- *
40
- * @param raw - a `RootRecord` (key + root) or a bare `RootRef`.
41
- * @param entry - the entry to match.
42
- * @returns the record's own key when it names `entry`, else `undefined`.
43
- */
44
- export declare function liveKeyOfRecord(raw: unknown, entry: UserRootEntry): string | undefined;
45
- /**
46
- * Whitelist one live connection.
47
- *
48
- * This is the only place the host's connection profiles are turned into wire data, so it is the one place
49
- * that must never copy a field it was not explicitly told to copy: `auth`, `keyPath`, `credentialKey`,
50
- * `password`, `alias`, `proxyJump` and everything added later stay behind.
51
- */
52
- export declare function publicConnection(raw: unknown): PublicConnection;
53
- /** The machine-readable reason for one local listing failure, or `undefined` when it is not the caller's fault. */
54
- export declare function localFailureReason(error: unknown): LocalFailureReason | undefined;
55
- /** The human text for one {@link LocalFailureReason}; the path is always named so the message is actionable. */
56
- export declare function localFailureMessage(reason: LocalFailureReason, path: string): string;
57
- /**
58
- * Narrow a whitelisted body down to the fields of a {@link ConnectionPatch} (never the id: see
59
- * {@link UPDATE_CONNECTION_FIELDS}).
60
- *
61
- * **Absent means "keep what is there"** for every field, and this function is what makes that true rather than
62
- * accidental: only keys the body actually carries are copied, so a body that names three fields cannot blank
63
- * the four it did not mention.
64
- *
65
- * `port: ''`/`null` becomes `null`, which is the one value that means **drop the field** (back to the ssh
66
- * default). Every other value is passed through untouched and judged by `normalizeConnectionEntry`; nothing is
67
- * coerced here, because a bad port must be reported, not silently rounded.
68
- *
69
- * @param source - the whitelisted fields of the request body.
70
- * @returns the patch.
71
- */
72
- export declare function connectionPatchOf(source: Record<string, unknown>): Omit<ConnectionPatch, 'id'>;
73
- /**
74
- * The one body field this route refuses outright, whatever the action.
75
- *
76
- * `passphrase` has no representation anywhere in this feature, so accepting it would be a lie — and silently
77
- * dropping it would tell the user their passphrase was stored.
78
- *
79
- * `password` is **not** refused any more: `add-connection` and `update-connection` take it, write it into the
80
- * credential store and keep only the reference (FR-2.1.2). `credentialKey` is a *name*, not a secret, and
81
- * travels normally.
82
- */
83
- export declare function firstCredentialField(body: Record<string, unknown>, action: string): string | undefined;
84
- /** One required non-empty string field of a body. */
85
- export declare function requiredString(value: unknown, field: string): string;
86
- export declare function asRecord(value: unknown): Record<string, unknown> | undefined;
87
- export declare function isValidationFailure(error: unknown): boolean;
88
- export declare function messageOf(error: unknown): string;
89
- /** The machine-readable reason a refusal carries in its details, when it has one. */
90
- export declare function reasonOf(error: unknown): string | undefined;
91
- export declare function send(req: RootsApiRequest, res: RootsApiResponse, status: number, value: unknown): void;
92
- /**
93
- * The wire shape of one tracked transfer.
94
- *
95
- * Whitelisted field by field, like every other projection on this route: the tracker's own object is a
96
- * host-side value, and a field added there must be a deliberate decision to publish, not a leak.
97
- *
98
- * @param value - one entry from the tracker.
99
- * @returns the row the client may see.
100
- */
101
- export declare function publicTransfer(value: unknown): Record<string, unknown>;
102
- /**
103
- * Turn an alias into a connection id that passes {@link isValidConnectionId}.
104
- *
105
- * `~/.ssh/config` aliases routinely contain characters this plugin's ids reject (`@`, `:`, `/`, spaces) —
106
- * `deploy@bastion` is a perfectly normal alias. Importing one verbatim would be refused by
107
- * {@link normalizeConnectionEntry} with a message about id grammar, which reads as "the import is broken".
108
- * The alias is therefore **kept as the ssh target** (`alias`), and only the *id* is sanitised.
109
- *
110
- * @param alias - the literal alias from the config.
111
- * @returns a valid id, or `undefined` when sanitising leaves nothing usable.
112
- */
113
- export declare function connectionIdFromAlias(alias: string): string | undefined;
114
- /** The persisted state as the panel may see it: same connection projection, so `keyPath` never travels. */
115
- export declare function publicUserState(state: UserRootsState): {
116
- readonly version: number;
117
- readonly roots: readonly UserRootEntry[];
118
- readonly connections: readonly PublicConnection[];
119
- };
120
- /**
121
- * The optional `path` field of a `list-local` body.
122
- *
123
- * Absent and empty (or blank) both mean "the host default", which is the user's home directory. Anything else
124
- * that is not a string — `null` included — is the caller's fault and is refused before a directory is chosen:
125
- * silently browsing the home directory because a client sent `null` would look like the request succeeded.
126
- */
127
- export declare function optionalPath(value: unknown): string | undefined;
128
- /** One root as the panel may see it: no credential can appear in a root, but the shape is still fixed. */
129
- export interface PublicRoot {
130
- readonly key?: string;
131
- readonly location: string;
132
- readonly connectionId?: string;
133
- readonly path: string;
134
- readonly label?: string;
135
- readonly writable?: boolean;
136
- }
137
- /**
138
- * One connection as the panel may see it. **Deliberately without `keyPath`.**
139
- *
140
- * `transport` **is** projected, and it has to be: the edit form is filled from this answer and submits what it
141
- * was filled with, so omitting the field silently rewrote every `alias`/`ssh2` connection to the default
142
- * (`agent`) on the next save - even when the operator only changed the host.
143
- */
144
- export interface PublicConnection {
145
- readonly id: string;
146
- readonly host: string;
147
- readonly user: string;
148
- readonly port?: number;
149
- readonly authKind: string;
150
- /** The transport this connection asks for; absent only for a record that names none. */
151
- readonly transport?: string;
152
- }
153
- /** The reasons a local listing of a syntactically valid path can be refused with. */
154
- type LocalFailureReason = 'not-found' | 'not-a-directory' | 'unreadable';
155
- /**
156
- * The absolute chain from the filesystem root down to `absolute`, inclusive.
157
- *
158
- * The client renders "up" and "home" from this instead of composing a parent path itself: drive letters, UNC
159
- * shares and `/` are exactly the dialects a web client gets wrong, and one wrong guess sends `list-local` to a
160
- * directory the user never asked for. Every element is an ancestor of the path the answer already carries, so
161
- * the field discloses nothing the `path` field did not.
162
- *
163
- * @param absolute - an absolute, resolved path (what the handler answers with).
164
- * @returns the chain, root first; empty when the platform reports no root (impossible for a resolved path).
165
- */
166
- export declare function localPathCrumbs(absolute: string): readonly string[];
167
- /** The persisted state, read fresh for every check (the file is the source of truth, not a cache). */
168
- export declare function currentUserState(deps: RootsApiDeps): Promise<UserRootsState>;
169
- /**
170
- * Converge the persisted state on a target shape and return it.
171
- *
172
- * The handler never assumes who persisted what: it consults the file **after** the live seam ran, computes
173
- * the state the request implies, and writes only when that differs. So a wiring whose `registerRoot` already
174
- * persists produces no second write, and a wiring that only touches the live registry still ends with a file
175
- * that matches reality.
176
- */
177
- export declare function reconcile(deps: RootsApiDeps, transition: (state: UserRootsState) => UserRootsState): Promise<UserRootsState>;
178
- /** Take only the named fields from a body; the body itself is never handed to a seam. */
179
- export declare function pick(source: Record<string, unknown>, fields: readonly string[]): Record<string, unknown>;
180
- export declare function requiredKey(value: unknown): string;
181
- export {};
182
- //# sourceMappingURL=roots-api-support.d.ts.map
@@ -1,13 +0,0 @@
1
- /**
2
- * roots-api-transfers
3
- *
4
- * 传输面板的 2 个 action:列表与清空。
5
- *
6
- * 从 `roots-api.ts` 的 `serveAction`(543 行 / 15 个 case)拆出(审计 0076):
7
- * case 体逐字搬移,只把 `return;` 改成 `return true;`,未命中时返回 `false` 由分发器报 400。
8
- *
9
- * @module dsh-remote-workspace/app/roots-api-transfers
10
- */
11
- import type { RootsApiRequest, RootsApiResponse, RootsApiDeps } from './roots-api-contract.ts';
12
- export declare function handleTransferActions(action: string, body: Record<string, unknown>, req: RootsApiRequest, res: RootsApiResponse, deps: RootsApiDeps): Promise<boolean>;
13
- //# sourceMappingURL=roots-api-transfers.d.ts.map
@@ -1,55 +0,0 @@
1
- /**
2
- * The same-origin HTTP route a client panel uses to **edit** roots and connections.
3
- *
4
- * Why a plain HTTP route instead of a Typert `@Remote` service (the shape audit 0021 used for reads):
5
- *
6
- * - every action here carries **parameters**, and a Client Remote descriptor with parameters requires a
7
- * generated strict codec that this repository cannot produce (`doc/02-platform/client-plugin.md` §4);
8
- * - the panel is served from the GUI's own origin, so a relative `fetch` is same-origin: no CORS
9
- * concession, no code generation, no `@Remote` registration — exactly the shape the third-party
10
- * `dsh-plugin-stock-market` uses (`ctx.webServer.register({ kind: 'exact', path, handler })`).
11
- *
12
- * This module is a **handler factory decoupled from cordis**: everything it needs arrives through
13
- * {@link RootsApiDeps}, so it can be unit-tested with fake dependencies and fake request/response objects.
14
- * The Lead performs the actual registration:
15
- *
16
- * ```ts
17
- * const api = createRootsApi({ ... })
18
- * disposers.push(webServer.register({ kind: 'exact', path: ROOTS_API_PATH, handler: api.handle }))
19
- * ```
20
- *
21
- * Contract:
22
- *
23
- * | Request | Answer |
24
- * |---|---|
25
- * | `GET` | `200 { ok: true, roots, connections, userRoots, warnings }` |
26
- * | `POST` `{ action: 'add-root' \| 'remove-root' \| 'add-connection' \| 'update-connection' \| 'remove-connection', ... }` | `200 { ok: true, action, state }` |
27
- * | `POST` `{ action: 'add-root', location, path, connectionId?, workspaces?, reuseExisting? }` | `200 { ok: true, action, state, anchorPath? }` — `reuseExisting: true` makes an already-persisted root idempotent and answers its anchor instead of `400 该根已存在` |
28
- * | `POST` `{ action: 'remove-root', key, workspace? }` | `200 { ok: true, action, state }` — `workspace` removes the root from that workspace only; the root disappears when the last one drops it |
29
- * | `POST` `{ action: 'update-connection', id, newId?, host?, user?, port?, authKind?, keyPath?, credentialKey?, transport?, password? }` | `200 { ok: true, action, state }` — absent fields keep their value; `newId` renames and migrates the connection's roots (keeping their anchors) |
30
- * | `POST` `{ action: 'list-remote', connectionId, path }` | `200 { ok: true, action, connectionId, path, entries: [{ name, kind }], truncated }` |
31
- * | `POST` `{ action: 'list-local', path? }` | `200 { ok: true, action, path, entries: [{ name, kind }], crumbs, truncated }` |
32
- * | `POST` `{ action: 'list-ssh-config' }` | `200 { ok: true, action, candidates: [{ alias, host, user?, port?, hasIdentityFile, hasProxyJump, suggestedId }], skipped: [{ pattern, reason, line }] }` (FR-2.1.4) |
33
- * | `POST` `{ action: 'import-ssh-config', aliases: [alias, …] }` | `200 { ok: true, action, imported: [id, …], refused: [{ alias, reason }], state }` — the body names **aliases**, never ids/hosts/paths: every field is re-derived from the config |
34
- * | any validation / trust / body failure | `400`/`403` `{ ok: false, error, reason? }` |
35
- * | any other method | `405` `{ ok: false, error }` + `Allow: GET, HEAD, POST` |
36
- *
37
- * Two invariants this layer owns:
38
- *
39
- * 1. **Credentials never come back out.** `connections` (live and persisted), the `state` echoed by
40
- * `POST` and every directory row (`list-remote` and `list-local`) are whitelist projections:
41
- * `{ id, host, user, port, authKind, transport? }` and `{ name, kind }` respectively. `keyPath`, `password`,
42
- * `passphrase`, `credentialKey`, `alias`, `proxyJump`, sizes, times, modes and symlink targets are
43
- * never serialised, and no file content is readable through this route at all.
44
- * 2. **Parameters are taken from a whitelist, one field at a time** — the body is never spread into a
45
- * call. A field the UI does not own cannot reach the seam, however the body is shaped.
46
- *
47
- * @module dsh-remote-workspace/integration/roots-api
48
- */
49
- import type { RootsApiDeps, RootsApi } from './roots-api-contract.ts';
50
- export * from './roots-api-contract.ts';
51
- export { localPathCrumbs } from './roots-api-projections.ts';
52
- export { connectionIdFromAlias } from './roots-api-http.ts';
53
- export type { PublicRoot, PublicConnection } from './roots-api-projections.ts';
54
- export declare function createRootsApi(deps: RootsApiDeps): RootsApi;
55
- //# sourceMappingURL=roots-api.d.ts.map
@@ -1,239 +0,0 @@
1
- /**
2
- * The routed file system: one workspace, many roots, local and remote side by side.
3
- *
4
- * Responsibilities, in order:
5
- *
6
- * 1. **Resolve** a model-facing path to exactly one root plus a backend-absolute path
7
- * (all rules live in `domain/route-table.ts`; this module only applies the result).
8
- * One addition lives here rather than in the table: the **implicit session root**, so the session's own
9
- * working directory is always usable even when no registered root covers it (see {@link
10
- * RoutedFileSystem.tryResolve}).
11
- * 2. **Namespace** target keys as `{backendId}\0{absolute path}` — the same file spelled locally
12
- * and remotely must never collide, because core components key their state by target key.
13
- * 3. **Fence writes**: resolution already rejects paths outside every root, so `workspace-write`
14
- * means "inside the roots"; `read-only` denies every write; `danger-full-access` allows.
15
- * This is the plugin's own multi-root confinement (the core's single-root fence cannot express
16
- * several roots, see `doc/02-platform/fs-seam.md` §4).
17
- * 4. Keep the operations the model's tools need: stat / list / read / write / edit.
18
- *
19
- * @module dsh-over-ssh/app/routed-fs
20
- */
21
- import type { Backend, BackendEntry, BackendRead, BackendSandboxMode, BackendStat, BackendText } from './backend.ts';
22
- import { SshDevError } from '../domain/errors.ts';
23
- import { type RootRef } from '../domain/roots/root.ts';
24
- import { type RouteOptions } from '../domain/roots/route-table.ts';
25
- /** A resolved path: one root, one backend, one backend-absolute location. */
26
- export interface RoutedTarget {
27
- readonly root: RootRef;
28
- readonly backend: Backend;
29
- /** Key of the root, also the router's backend key. */
30
- readonly backendKey: string;
31
- /** Absolute path in the backend's own spelling. */
32
- readonly absolute: string;
33
- /** Namespaced identity: `{backendId}\0{absolute}`. */
34
- readonly targetKey: string;
35
- readonly relativePath: string;
36
- /** Model-facing spelling (`ssh://…` for remote roots). */
37
- readonly displayPath: string;
38
- }
39
- /** Resolution outcome with a resolved target, or the reason it failed. */
40
- export type RoutedResolution = {
41
- readonly ok: true;
42
- readonly target: RoutedTarget;
43
- } | {
44
- readonly ok: false;
45
- readonly error: SshDevError;
46
- };
47
- /** A directory entry with its resolved identity. */
48
- export interface RoutedEntry extends BackendEntry {
49
- readonly targetKey: string;
50
- readonly displayPath: string;
51
- }
52
- /** Options for {@link RoutedFileSystem}. */
53
- export interface RoutedFileSystemOptions {
54
- readonly roots: readonly RootRef[];
55
- /** Backends keyed by `rootKey(root)`. */
56
- readonly backends: ReadonlyMap<string, Backend>;
57
- readonly caseInsensitive?: boolean;
58
- /** Cap for a single read; defaults to 8 MiB. */
59
- readonly maxReadBytes?: number;
60
- /**
61
- * Builds the backend for the **implicit session root** — the session's own cwd (see {@link
62
- * RoutedFileSystem.tryResolve}).
63
- *
64
- * Injected rather than imported because building a local backend needs `node:fs`, and this layer must not
65
- * reach a concrete adapter (架构测试: `app` only depends on `infra` port modules). Omitting it **disables**
66
- * the implicit root, which is the honest default: a router that was given no way to serve host paths keeps
67
- * reporting `ROOT_OUTSIDE` for them.
68
- */
69
- readonly createLocalBackend?: (root: RootRef) => Backend;
70
- }
71
- /** Write options. */
72
- export interface RoutedWriteOptions {
73
- readonly cwd?: string;
74
- /** Version token that must match before the write proceeds. */
75
- readonly expectedVersion?: string;
76
- /** Policy the caller is operating under. */
77
- readonly sandbox?: BackendSandboxMode;
78
- readonly signal?: AbortSignal;
79
- }
80
- /** Literal edit request, mirroring the core's `editText` semantics. */
81
- export interface RoutedEdit {
82
- readonly find: string;
83
- readonly replace: string;
84
- /** Replace every occurrence instead of requiring a unique one. */
85
- readonly all?: boolean;
86
- }
87
- /** Multi-root file system over a set of backends. */
88
- export declare class RoutedFileSystem {
89
- #private;
90
- constructor(options: RoutedFileSystemOptions);
91
- /** Registered roots, in registration order. */
92
- get roots(): readonly RootRef[];
93
- /** Confinement the router enforces itself. */
94
- get sandboxMode(): BackendSandboxMode;
95
- /** Register a root together with the backend that serves it. */
96
- addRoot(root: RootRef, backend: Backend): void;
97
- /** Remove a root and its backend binding. */
98
- removeRoot(key: string): boolean;
99
- /** Replace every root and backend binding at once. */
100
- setRoots(entries: readonly {
101
- readonly root: RootRef;
102
- readonly backend: Backend;
103
- }[]): void;
104
- /**
105
- * Resolve a path.
106
- *
107
- * @param input - model-facing path (host path, `ssh://…`, or relative to `cwd`).
108
- * @param options - session cwd and case folding.
109
- * @returns the resolved target.
110
- * @throws SshDevError `ROOT_OUTSIDE` / `ROOT_AMBIGUOUS` / `ROOT_INVALID`.
111
- */
112
- resolve(input: string, options?: RouteOptions): RoutedTarget;
113
- /**
114
- * Non-throwing resolution for UI code.
115
- *
116
- * A registered root is always asked first, so it wins over the implicit session root — the implicit root only
117
- * answers paths the table refused.
118
- */
119
- tryResolve(input: string, options?: RouteOptions): RoutedResolution;
120
- /** Metadata for a path. */
121
- stat(input: string, options?: RouteOptions & {
122
- readonly signal?: AbortSignal;
123
- }): Promise<BackendStat & {
124
- readonly target: RoutedTarget;
125
- }>;
126
- /** Direct children of a directory, with resolved identities. */
127
- list(input: string, options?: RouteOptions & {
128
- readonly signal?: AbortSignal;
129
- }): Promise<readonly RoutedEntry[]>;
130
- /**
131
- * List an already-resolved directory.
132
- *
133
- * Takes the target so callers that hold one (the core `FsTarget` contract hands one to every
134
- * operation) do not pay for a second resolution.
135
- *
136
- * @param target - resolved directory.
137
- * @param signal - cancellation.
138
- * @returns direct children with resolved identities.
139
- */
140
- listTarget(target: RoutedTarget, signal?: AbortSignal): Promise<readonly RoutedEntry[]>;
141
- /**
142
- * Stat an already-resolved target.
143
- *
144
- * @param target - resolved target.
145
- * @param options - when `followSymlink` is false and the backend supports it, the link itself is
146
- * inspected instead of its target.
147
- * @returns metadata (never content).
148
- */
149
- statTarget(target: RoutedTarget, options?: {
150
- readonly followSymlink?: boolean;
151
- readonly signal?: AbortSignal;
152
- }): Promise<BackendStat>;
153
- /**
154
- * Resolve an opaque target key back to the root, backend and backend-absolute path that own it.
155
- *
156
- * Every operation after {@link resolve} arrives this way (the core hands back only the target key), so an
157
- * implicit session root must be found here too: it is not in the table, but its backend id is what its target
158
- * keys carry.
159
- */
160
- targetFromKey(targetKey: string): RoutedTarget;
161
- /** Whether a path exists. */
162
- exists(input: string, options?: RouteOptions & {
163
- readonly signal?: AbortSignal;
164
- }): Promise<boolean>;
165
- /** Read bytes, capped by the router's limit. */
166
- readBytes(input: string, options?: RouteOptions & {
167
- readonly maxBytes?: number;
168
- readonly signal?: AbortSignal;
169
- }): Promise<BackendRead & {
170
- readonly target: RoutedTarget;
171
- }>;
172
- /** Read text. */
173
- readText(input: string, options?: RouteOptions & {
174
- readonly maxBytes?: number;
175
- readonly signal?: AbortSignal;
176
- }): Promise<BackendText & {
177
- readonly target: RoutedTarget;
178
- }>;
179
- /**
180
- * Write text after enforcing the router's own confinement.
181
- *
182
- * @param input - destination path.
183
- * @param text - content to write.
184
- * @param options - policy, version guard and cancellation.
185
- * @returns the write outcome plus the resolved target.
186
- */
187
- writeText(input: string, text: string, options?: RoutedWriteOptions): Promise<{
188
- readonly bytes: number;
189
- readonly version: string;
190
- readonly target: RoutedTarget;
191
- }>;
192
- /**
193
- * Apply a unified diff to one file, atomically.
194
- *
195
- * Forwarded rather than reimplemented: the backend owns the hunk matching, and a second implementation
196
- * here would be a second set of edge cases to keep in sync.
197
- */
198
- patchText(input: string, diff: string, options?: RoutedWriteOptions): Promise<{
199
- readonly bytes: number;
200
- readonly version: string;
201
- readonly hunks: number;
202
- readonly target: RoutedTarget;
203
- }>;
204
- /**
205
- * Replace a literal string inside a file.
206
- *
207
- * Mirrors the core's semantics: an absent pattern and an ambiguous match without `all` are both
208
- * errors, and a version guard can refuse the whole edit.
209
- *
210
- * @param input - file to edit.
211
- * @param edit - find/replace plus the `all` flag.
212
- * @param options - policy, version guard, cwd and cancellation.
213
- * @returns the new version and the number of replacements.
214
- */
215
- editText(input: string, edit: RoutedEdit, options?: RoutedWriteOptions): Promise<{
216
- readonly replacements: number;
217
- readonly version: string;
218
- readonly target: RoutedTarget;
219
- }>;
220
- /**
221
- * Whether one target is inside another.
222
- *
223
- * Both targets must belong to the same backend; across backends the answer is always `false`
224
- * (a local path can never contain a remote path).
225
- */
226
- contains(parent: RoutedTarget, child: RoutedTarget): boolean;
227
- /** Host path for a child process in the target's world, when that world has one. */
228
- processPath(target: RoutedTarget): string | undefined;
229
- /** `file:` URL in the target's world. */
230
- fileUrl(target: RoutedTarget): string | undefined;
231
- }
232
- /** Namespaced identity of one file; the backend id prevents local/remote collisions. */
233
- export declare function makeTargetKey(backend: Backend, absolute: string): string;
234
- /** Split a target key back into its parts (diagnostics and tests only). */
235
- export declare function splitTargetKey(targetKey: string): {
236
- readonly backendId: string;
237
- readonly absolute: string;
238
- } | undefined;
239
- //# sourceMappingURL=routed-fs.d.ts.map
@@ -1,37 +0,0 @@
1
- /**
2
- * Run asynchronous file work one operation at a time, in call order.
3
- *
4
- * Two places needed this and each carried its own copy of the same six lines: the panel-owned root/connection
5
- * file (`app/roots/user-roots.ts`) and the session trash index (`app/session-admin/session-admin-context.ts`).
6
- * Both are read-modify-write over one document, and in both the read is asynchronous, so two overlapping
7
- * requests would read the same state and the second write would silently discard the first one's change — a
8
- * lost update with no error anywhere. The idiom is small enough to look harmless and subtle enough to get
9
- * wrong, which is exactly the case for one implementation (audit 2026-10-31 P3).
10
- *
11
- * The queue is **within one process** only. Two DSH processes writing the same file are still last-writer-wins;
12
- * that needs a cross-process lock and is out of scope here.
13
- *
14
- * @module dsh-over-ssh/app/serialize
15
- */
16
- /** A serial queue: `run` one task at a time, and `settled` to wait for what is already queued. */
17
- export interface SerialQueue {
18
- /**
19
- * Queue `task`; it starts after every earlier task has settled.
20
- *
21
- * A rejection does **not** wedge the queue: the chain continues after it, so one failed write cannot stop
22
- * every later one.
23
- *
24
- * @param task - the work to run alone.
25
- * @returns the task's own result or rejection.
26
- */
27
- run<T>(task: () => Promise<T>): Promise<T>;
28
- /** Resolves once everything queued so far has settled — how a test waits without sleeping. */
29
- settled(): Promise<void>;
30
- }
31
- /**
32
- * Create one serial queue.
33
- *
34
- * @returns the queue (see {@link SerialQueue}).
35
- */
36
- export declare function createSerialQueue(): SerialQueue;
37
- //# sourceMappingURL=serialize.d.ts.map
@@ -1,36 +0,0 @@
1
- /**
2
- * 会话管理的**上下文**:bin 根、索引读写、跨进程串行化、会话清单。
3
- *
4
- * 从 `session-admin-service.ts` 的工厂里抽出(审计 0076):所有方法族的公共底座。
5
- *
6
- * @module dsh-over-ssh/app/session-admin-context
7
- */
8
- import { type SessionRecord, type SessionTrashEntry } from '../../domain/session/session-admin.ts';
9
- import type { SessionAdminDeps, SessionAdminOptions } from './session-admin-contract.ts';
10
- /** Whether a thrown error means "the path does not exist". */
11
- export declare function isMissing(error: unknown): boolean;
12
- export declare function createSessionAdminContext(deps: SessionAdminDeps): {
13
- deps: SessionAdminDeps;
14
- sessionsRoot: string;
15
- binRoot: string;
16
- indexePath: () => string;
17
- serialized: <T>(operation: () => Promise<T>) => Promise<T>;
18
- entryDir: (segment: string) => string;
19
- readIndex: () => Promise<readonly SessionTrashEntry[]>;
20
- writeIndex: (entries: readonly SessionTrashEntry[]) => Promise<void>;
21
- inventory: (options?: SessionAdminOptions) => Promise<readonly SessionRecord[]>;
22
- };
23
- export type SessionAdminContext = ReturnType<typeof createSessionAdminContext>;
24
- /**
25
- * Fold a path to a comparison key: forward slashes, no trailing separator, lower case.
26
- *
27
- * The same fold the label resolver uses (`session-labels.ts`), duplicated here because this module must not
28
- * import the resolver: the resolver reads platform services, this one is pure. Windows paths are
29
- * case-insensitive and a header's `cwd` is the raw spawn directory while a workspace record's path is
30
- * canonicalized, so an exact compare would miss real matches.
31
- *
32
- * @param path - a path in either spelling.
33
- * @returns the comparison key.
34
- */
35
- export declare function normalizePathKey(path: string): string;
36
- //# sourceMappingURL=session-admin-context.d.ts.map
@@ -1,34 +0,0 @@
1
- /**
2
- * 会话管理的**删除族**:预览、物理删除、移入回收站、批量清理、按工作区删除。
3
- *
4
- * 从 `session-admin-service.ts` 的工厂里抽出(审计 0076):只依赖上下文,不依赖列表/恢复/清扫。
5
- *
6
- * @module dsh-over-ssh/app/session-admin-delete
7
- */
8
- import { type SessionTrashEntry, type SessionTrashEntryId } from '../../domain/session/session-admin.ts';
9
- import { type SessionAdminContext } from './session-admin-context.ts';
10
- import type { PurgeSessionResult, DeleteSessionResult } from './session-admin-contract.ts';
11
- import type { DeleteDecision } from '../../domain/session/session-admin.ts';
12
- export declare function createSessionAdminDelete(ctx: SessionAdminContext): {
13
- previewDelete: (ids: readonly string[], options?: import("./session-admin-contract.ts").SessionAdminOptions & {
14
- readonly keep?: readonly string[];
15
- }) => Promise<DeleteDecision>;
16
- deleteSession: (ids: readonly string[], options?: import("./session-admin-contract.ts").SessionAdminOptions & {
17
- readonly mode?: "recycle" | "permanent";
18
- readonly keep?: readonly string[];
19
- }) => Promise<DeleteSessionResult>;
20
- deleteWorkspaceSessions: (cwd: string, options?: import("./session-admin-contract.ts").SessionAdminOptions & {
21
- readonly mode?: "recycle" | "permanent";
22
- }) => Promise<DeleteSessionResult & {
23
- readonly matched: number;
24
- }>;
25
- purgeEntry: (entryId: string) => Promise<PurgeSessionResult>;
26
- purgeEntries: (doomed: readonly SessionTrashEntry[], known: readonly SessionTrashEntry[]) => Promise<{
27
- readonly purged: readonly PurgeSessionResult[];
28
- readonly failed: readonly {
29
- readonly id: SessionTrashEntryId;
30
- readonly reason: string;
31
- }[];
32
- }>;
33
- };
34
- //# sourceMappingURL=session-admin-delete.d.ts.map
@@ -1,36 +0,0 @@
1
- /**
2
- * 会话管理的**上下文**:bin 根、索引读写、跨进程串行化、会话清单。
3
- *
4
- * 从 `session-admin-service.ts` 的工厂里抽出(审计 0076):所有方法族的公共底座。
5
- *
6
- * @module dsh-remote-workspace/app/session-admin-context
7
- */
8
- import { type SessionRecord, type SessionTrashEntry } from '../domain/session-admin.ts';
9
- import type { SessionAdminDeps, SessionAdminOptions } from './session-admin-contract.ts';
10
- /** Whether a thrown error means "the path does not exist". */
11
- export declare function isMissing(error: unknown): boolean;
12
- export declare function createSessionAdminContext(deps: SessionAdminDeps): {
13
- deps: SessionAdminDeps;
14
- sessionsRoot: string;
15
- binRoot: string;
16
- indexePath: () => string;
17
- serialized: <T>(operation: () => Promise<T>) => Promise<T>;
18
- entryDir: (segment: string) => string;
19
- readIndex: () => Promise<readonly SessionTrashEntry[]>;
20
- writeIndex: (entries: readonly SessionTrashEntry[]) => Promise<void>;
21
- inventory: (options?: SessionAdminOptions) => Promise<readonly SessionRecord[]>;
22
- };
23
- export type SessionAdminContext = ReturnType<typeof createSessionAdminContext>;
24
- /**
25
- * Fold a path to a comparison key: forward slashes, no trailing separator, lower case.
26
- *
27
- * The same fold the label resolver uses (`session-labels.ts`), duplicated here because this module must not
28
- * import the resolver: the resolver reads platform services, this one is pure. Windows paths are
29
- * case-insensitive and a header's `cwd` is the raw spawn directory while a workspace record's path is
30
- * canonicalized, so an exact compare would miss real matches.
31
- *
32
- * @param path - a path in either spelling.
33
- * @returns the comparison key.
34
- */
35
- export declare function normalizePathKey(path: string): string;
36
- //# sourceMappingURL=session-admin-context.d.ts.map