dsh-over-ssh 0.1.0 → 0.1.1

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 (247) hide show
  1. package/README.md +10 -10
  2. package/agents/agent-manifest.json +1 -1
  3. package/lib/client.js +363 -314
  4. package/lib/file-references.js +80 -35
  5. package/lib/fs.js +158 -75
  6. package/lib/index.js +4103 -3397
  7. package/lib/terminal-wrapper.js +9 -4
  8. package/lib/types/src/config.d.ts +80 -9
  9. package/lib/types/src/file-references.d.ts +0 -1
  10. package/lib/types/src/host/app/backend.d.ts +9 -1
  11. package/lib/types/src/host/app/recycle-bin/recycle-bin-contract.d.ts +0 -1
  12. package/lib/types/src/host/app/recycle-bin/recycle-bin-service.d.ts +0 -1
  13. package/lib/types/src/host/app/session-admin/session-admin-contract.d.ts +12 -1
  14. package/lib/types/src/host/app/session-admin/session-admin-service.d.ts +0 -1
  15. package/lib/types/src/host/app/transport/transport-selector.d.ts +0 -1
  16. package/lib/types/src/host/app/transport/transport-service.d.ts +0 -1
  17. package/lib/types/src/host/domain/capability.d.ts +0 -1
  18. package/lib/types/src/host/domain/errors.d.ts +0 -1
  19. package/lib/types/src/host/domain/roots/connection.d.ts +0 -1
  20. package/lib/types/src/host/domain/roots/root.d.ts +24 -9
  21. package/lib/types/src/host/domain/roots/session-roots.d.ts +0 -1
  22. package/lib/types/src/host/domain/roots/ssh-config.d.ts +0 -1
  23. package/lib/types/src/host/domain/session/session-admin.d.ts +0 -1
  24. package/lib/types/src/host/domain/transfer/recycle-bin.d.ts +0 -1
  25. package/lib/types/src/host/domain/transfer/transfer.d.ts +0 -1
  26. package/lib/types/src/host/infra/transport/agent/agent-installer.d.ts +0 -1
  27. package/lib/types/src/host/infra/transport/ssh/ssh2-transport.d.ts +0 -1
  28. package/lib/types/src/host/infra/transport/transport-base.d.ts +0 -1
  29. package/lib/types/src/host/infra/transport/transport.d.ts +16 -2
  30. package/lib/types/src/host/integration/agent/agent-preflight.d.ts +0 -1
  31. package/lib/types/src/host/integration/fs/file-reference-provider.d.ts +0 -1
  32. package/lib/types/src/host/integration/fs/fs-provider.d.ts +0 -2
  33. package/lib/types/src/host/integration/transfer/transfer-service.d.ts +0 -1
  34. package/lib/types/src/index.d.ts +23 -1
  35. package/lib/types/src/local-bridge-refs.d.ts +0 -1
  36. package/lib/types/src/local-bridge.d.ts +0 -1
  37. package/lib/types/src/shared/root-keys.d.ts +120 -0
  38. package/lib/types/src/wiring/helpers.d.ts +0 -1
  39. package/package.json +5 -3
  40. package/lib/types/src/client/controls.d.ts +0 -131
  41. package/lib/types/src/client/core/card-focus-trap.d.ts +0 -45
  42. package/lib/types/src/client/core/controls.d.ts +0 -164
  43. package/lib/types/src/client/core/latest.d.ts +0 -48
  44. package/lib/types/src/client/core/locale.d.ts +0 -38
  45. package/lib/types/src/client/core/message.d.ts +0 -37
  46. package/lib/types/src/client/core/panel-model.d.ts +0 -134
  47. package/lib/types/src/client/core/portal.d.ts +0 -266
  48. package/lib/types/src/client/core/remote.d.ts +0 -84
  49. package/lib/types/src/client/core/styles.d.ts +0 -458
  50. package/lib/types/src/client/file-tree-io.d.ts +0 -19
  51. package/lib/types/src/client/file-tree.d.ts +0 -271
  52. package/lib/types/src/client/flows/directory-browser.d.ts +0 -587
  53. package/lib/types/src/client/flows/session-directory.d.ts +0 -415
  54. package/lib/types/src/client/flows/workspace-directory-flow.d.ts +0 -480
  55. package/lib/types/src/client/locale.d.ts +0 -31
  56. package/lib/types/src/client/panel-model.d.ts +0 -37
  57. package/lib/types/src/client/panel.d.ts +0 -77
  58. package/lib/types/src/client/roots/connection-test.d.ts +0 -69
  59. package/lib/types/src/client/roots/roots-panel-state.d.ts +0 -307
  60. package/lib/types/src/client/roots/roots-panel-view.d.ts +0 -280
  61. package/lib/types/src/client/roots/roots-panel.d.ts +0 -364
  62. package/lib/types/src/client/roots/transfer-panel-view.d.ts +0 -35
  63. package/lib/types/src/client/roots/transfer-panel.d.ts +0 -241
  64. package/lib/types/src/client/roots/transfer-progress.d.ts +0 -67
  65. package/lib/types/src/client/roots-panel-view.d.ts +0 -236
  66. package/lib/types/src/client/roots-panel.d.ts +0 -347
  67. package/lib/types/src/client/session/session-panel-view.d.ts +0 -336
  68. package/lib/types/src/client/session/session-panel.d.ts +0 -322
  69. package/lib/types/src/client/session/session-remote-mark.d.ts +0 -110
  70. package/lib/types/src/client/session/session-row-actions.d.ts +0 -398
  71. package/lib/types/src/client/session-panel.d.ts +0 -152
  72. package/lib/types/src/client/styles.d.ts +0 -252
  73. package/lib/types/src/client/workspace-directory-flow.d.ts +0 -342
  74. package/lib/types/src/fs.d.ts +0 -46
  75. package/lib/types/src/host/app/recycle-bin/recycle-bin-move.d.ts +0 -18
  76. package/lib/types/src/host/app/recycle-bin/recycle-bin-world.d.ts +0 -38
  77. package/lib/types/src/host/app/recycle-bin-contract.d.ts +0 -215
  78. package/lib/types/src/host/app/recycle-bin-move.d.ts +0 -18
  79. package/lib/types/src/host/app/recycle-bin-service.d.ts +0 -45
  80. package/lib/types/src/host/app/recycle-bin-world.d.ts +0 -35
  81. package/lib/types/src/host/app/roots/roots-api-connections.d.ts +0 -49
  82. package/lib/types/src/host/app/roots/roots-api-contract.d.ts +0 -369
  83. package/lib/types/src/host/app/roots/roots-api-directories.d.ts +0 -13
  84. package/lib/types/src/host/app/roots/roots-api-http.d.ts +0 -77
  85. package/lib/types/src/host/app/roots/roots-api-long-poll.d.ts +0 -130
  86. package/lib/types/src/host/app/roots/roots-api-projections.d.ts +0 -102
  87. package/lib/types/src/host/app/roots/roots-api-roots.d.ts +0 -13
  88. package/lib/types/src/host/app/roots/roots-api-state.d.ts +0 -22
  89. package/lib/types/src/host/app/roots/roots-api-transfers.d.ts +0 -26
  90. package/lib/types/src/host/app/roots/roots-api.d.ts +0 -55
  91. package/lib/types/src/host/app/roots/user-roots.d.ts +0 -552
  92. package/lib/types/src/host/app/roots-api-connections.d.ts +0 -49
  93. package/lib/types/src/host/app/roots-api-contract.d.ts +0 -339
  94. package/lib/types/src/host/app/roots-api-directories.d.ts +0 -13
  95. package/lib/types/src/host/app/roots-api-http.d.ts +0 -77
  96. package/lib/types/src/host/app/roots-api-projections.d.ts +0 -102
  97. package/lib/types/src/host/app/roots-api-roots.d.ts +0 -13
  98. package/lib/types/src/host/app/roots-api-state.d.ts +0 -22
  99. package/lib/types/src/host/app/roots-api-support.d.ts +0 -182
  100. package/lib/types/src/host/app/roots-api-transfers.d.ts +0 -13
  101. package/lib/types/src/host/app/roots-api.d.ts +0 -55
  102. package/lib/types/src/host/app/routed-fs.d.ts +0 -239
  103. package/lib/types/src/host/app/serialize.d.ts +0 -37
  104. package/lib/types/src/host/app/session-admin/session-admin-context.d.ts +0 -36
  105. package/lib/types/src/host/app/session-admin/session-admin-delete.d.ts +0 -34
  106. package/lib/types/src/host/app/session-admin-context.d.ts +0 -36
  107. package/lib/types/src/host/app/session-admin-contract.d.ts +0 -214
  108. package/lib/types/src/host/app/session-admin-delete.d.ts +0 -34
  109. package/lib/types/src/host/app/session-admin-service.d.ts +0 -38
  110. package/lib/types/src/host/app/takeover/takeover-plan.d.ts +0 -227
  111. package/lib/types/src/host/app/takeover/takeover-rows.d.ts +0 -55
  112. package/lib/types/src/host/app/transport-selector.d.ts +0 -98
  113. package/lib/types/src/host/app/transport-service.d.ts +0 -75
  114. package/lib/types/src/host/app/user-roots.d.ts +0 -461
  115. package/lib/types/src/host/domain/bin-location.d.ts +0 -79
  116. package/lib/types/src/host/domain/connection.d.ts +0 -95
  117. package/lib/types/src/host/domain/glob-pattern.d.ts +0 -62
  118. package/lib/types/src/host/domain/literal-text.d.ts +0 -63
  119. package/lib/types/src/host/domain/path-grammar.d.ts +0 -84
  120. package/lib/types/src/host/domain/recycle-bin.d.ts +0 -337
  121. package/lib/types/src/host/domain/root.d.ts +0 -74
  122. package/lib/types/src/host/domain/roots/bin-location.d.ts +0 -91
  123. package/lib/types/src/host/domain/roots/route-table.d.ts +0 -102
  124. package/lib/types/src/host/domain/route-table.d.ts +0 -80
  125. package/lib/types/src/host/domain/session/terminal-target.d.ts +0 -136
  126. package/lib/types/src/host/domain/session-admin.d.ts +0 -330
  127. package/lib/types/src/host/domain/shell.d.ts +0 -47
  128. package/lib/types/src/host/domain/ssh-config.d.ts +0 -73
  129. package/lib/types/src/host/domain/terminal-target.d.ts +0 -132
  130. package/lib/types/src/host/domain/tool-requests.d.ts +0 -369
  131. package/lib/types/src/host/domain/transfer.d.ts +0 -260
  132. package/lib/types/src/host/infra/backend/local-backend.d.ts +0 -84
  133. package/lib/types/src/host/infra/backend/local-version.d.ts +0 -43
  134. package/lib/types/src/host/infra/backend/platform-local-backend.d.ts +0 -89
  135. package/lib/types/src/host/infra/backend/remote-backend.d.ts +0 -239
  136. package/lib/types/src/host/infra/cache/lru.d.ts +0 -52
  137. package/lib/types/src/host/infra/cache/versioned.d.ts +0 -77
  138. package/lib/types/src/host/infra/temp-name.d.ts +0 -19
  139. package/lib/types/src/host/infra/transport/agent/agent-protocol-client.d.ts +0 -132
  140. package/lib/types/src/host/infra/transport/agent/agent-protocol-codec.d.ts +0 -140
  141. package/lib/types/src/host/infra/transport/agent/agent-protocol-errors.d.ts +0 -41
  142. package/lib/types/src/host/infra/transport/agent/agent-protocol-frames.d.ts +0 -197
  143. package/lib/types/src/host/infra/transport/agent/agent-protocol-types.d.ts +0 -564
  144. package/lib/types/src/host/infra/transport/agent/agent-transport.d.ts +0 -418
  145. package/lib/types/src/host/infra/transport/agent-installer.d.ts +0 -121
  146. package/lib/types/src/host/infra/transport/agent-protocol-client.d.ts +0 -123
  147. package/lib/types/src/host/infra/transport/agent-protocol-codec.d.ts +0 -131
  148. package/lib/types/src/host/infra/transport/agent-protocol-errors.d.ts +0 -41
  149. package/lib/types/src/host/infra/transport/agent-protocol-frames.d.ts +0 -197
  150. package/lib/types/src/host/infra/transport/agent-protocol-types.d.ts +0 -509
  151. package/lib/types/src/host/infra/transport/agent-transport.d.ts +0 -353
  152. package/lib/types/src/host/infra/transport/alias-transport.d.ts +0 -206
  153. package/lib/types/src/host/infra/transport/askpass-fs.d.ts +0 -20
  154. package/lib/types/src/host/infra/transport/askpass.d.ts +0 -133
  155. package/lib/types/src/host/infra/transport/command-pool.d.ts +0 -61
  156. package/lib/types/src/host/infra/transport/fs-commands.d.ts +0 -140
  157. package/lib/types/src/host/infra/transport/git-status-route.d.ts +0 -63
  158. package/lib/types/src/host/infra/transport/git-status.d.ts +0 -101
  159. package/lib/types/src/host/infra/transport/node-spawn.d.ts +0 -26
  160. package/lib/types/src/host/infra/transport/session-window.d.ts +0 -51
  161. package/lib/types/src/host/infra/transport/shell-quote.d.ts +0 -59
  162. package/lib/types/src/host/infra/transport/ssh/alias-transport.d.ts +0 -206
  163. package/lib/types/src/host/infra/transport/ssh/askpass-fs.d.ts +0 -20
  164. package/lib/types/src/host/infra/transport/ssh/askpass.d.ts +0 -133
  165. package/lib/types/src/host/infra/transport/ssh/shell-quote.d.ts +0 -62
  166. package/lib/types/src/host/infra/transport/ssh/ssh-argv.d.ts +0 -43
  167. package/lib/types/src/host/infra/transport/ssh-argv.d.ts +0 -43
  168. package/lib/types/src/host/infra/transport/ssh2-transport.d.ts +0 -302
  169. package/lib/types/src/host/integration/agent/agent-install-io.d.ts +0 -33
  170. package/lib/types/src/host/integration/agent/askpass-registry.d.ts +0 -66
  171. package/lib/types/src/host/integration/agent-install-io.d.ts +0 -33
  172. package/lib/types/src/host/integration/agent-preflight.d.ts +0 -56
  173. package/lib/types/src/host/integration/anchor-directory.d.ts +0 -56
  174. package/lib/types/src/host/integration/askpass-registry.d.ts +0 -59
  175. package/lib/types/src/host/integration/bin-root-resolver.d.ts +0 -81
  176. package/lib/types/src/host/integration/connection-test.d.ts +0 -73
  177. package/lib/types/src/host/integration/file-reference-provider.d.ts +0 -115
  178. package/lib/types/src/host/integration/fs/git-status-wiring.d.ts +0 -21
  179. package/lib/types/src/host/integration/fs/platform-errors.d.ts +0 -94
  180. package/lib/types/src/host/integration/fs/remote-file-tools.d.ts +0 -369
  181. package/lib/types/src/host/integration/fs/remote-index.d.ts +0 -177
  182. package/lib/types/src/host/integration/fs-provider.d.ts +0 -226
  183. package/lib/types/src/host/integration/lsp/lsp-framing.d.ts +0 -38
  184. package/lib/types/src/host/integration/lsp/lsp-registry.d.ts +0 -67
  185. package/lib/types/src/host/integration/lsp/lsp-session.d.ts +0 -130
  186. package/lib/types/src/host/integration/management-tools.d.ts +0 -64
  187. package/lib/types/src/host/integration/recycle-bin-service.d.ts +0 -247
  188. package/lib/types/src/host/integration/remote/connection-test.d.ts +0 -73
  189. package/lib/types/src/host/integration/remote/remote-face.d.ts +0 -127
  190. package/lib/types/src/host/integration/remote/remote-tool-backend.d.ts +0 -108
  191. package/lib/types/src/host/integration/remote-face.d.ts +0 -127
  192. package/lib/types/src/host/integration/remote-file-tools.d.ts +0 -241
  193. package/lib/types/src/host/integration/remote-home.d.ts +0 -69
  194. package/lib/types/src/host/integration/remote-index.d.ts +0 -165
  195. package/lib/types/src/host/integration/remote-job-tools.d.ts +0 -295
  196. package/lib/types/src/host/integration/remote-tool-backend.d.ts +0 -97
  197. package/lib/types/src/host/integration/remote-tools.d.ts +0 -206
  198. package/lib/types/src/host/integration/root-registry.d.ts +0 -115
  199. package/lib/types/src/host/integration/roots/anchor-directory.d.ts +0 -56
  200. package/lib/types/src/host/integration/roots/bin-root-resolver.d.ts +0 -81
  201. package/lib/types/src/host/integration/roots/remote-home.d.ts +0 -69
  202. package/lib/types/src/host/integration/roots/root-registry.d.ts +0 -144
  203. package/lib/types/src/host/integration/roots/roots-wiring.d.ts +0 -219
  204. package/lib/types/src/host/integration/roots/session-root-index.d.ts +0 -52
  205. package/lib/types/src/host/integration/roots-api.d.ts +0 -407
  206. package/lib/types/src/host/integration/roots-wiring.d.ts +0 -211
  207. package/lib/types/src/host/integration/session/session-api.d.ts +0 -88
  208. package/lib/types/src/host/integration/session/session-bin-lock.d.ts +0 -80
  209. package/lib/types/src/host/integration/session/session-header.d.ts +0 -151
  210. package/lib/types/src/host/integration/session/session-labels.d.ts +0 -56
  211. package/lib/types/src/host/integration/session/session-route-wiring.d.ts +0 -50
  212. package/lib/types/src/host/integration/session-admin-service.d.ts +0 -236
  213. package/lib/types/src/host/integration/session-api.d.ts +0 -81
  214. package/lib/types/src/host/integration/session-bin-lock.d.ts +0 -80
  215. package/lib/types/src/host/integration/session-header.d.ts +0 -118
  216. package/lib/types/src/host/integration/session-labels.d.ts +0 -56
  217. package/lib/types/src/host/integration/session-route-wiring.d.ts +0 -50
  218. package/lib/types/src/host/integration/session-scope.d.ts +0 -113
  219. package/lib/types/src/host/integration/session-tools.d.ts +0 -44
  220. package/lib/types/src/host/integration/strict-arguments.d.ts +0 -79
  221. package/lib/types/src/host/integration/takeover/takeover-api.d.ts +0 -62
  222. package/lib/types/src/host/integration/takeover/takeover-route-wiring.d.ts +0 -60
  223. package/lib/types/src/host/integration/takeover/takeover-service.d.ts +0 -167
  224. package/lib/types/src/host/integration/terminal-manifest.d.ts +0 -94
  225. package/lib/types/src/host/integration/tools/management-tools.d.ts +0 -245
  226. package/lib/types/src/host/integration/tools/remote-job-tools.d.ts +0 -316
  227. package/lib/types/src/host/integration/tools/remote-lsp-tools.d.ts +0 -43
  228. package/lib/types/src/host/integration/tools/remote-tools.d.ts +0 -236
  229. package/lib/types/src/host/integration/tools/session-target.d.ts +0 -52
  230. package/lib/types/src/host/integration/tools/session-tools.d.ts +0 -46
  231. package/lib/types/src/host/integration/tools/strict-arguments.d.ts +0 -79
  232. package/lib/types/src/host/integration/tools/terminal-manifest.d.ts +0 -94
  233. package/lib/types/src/host/integration/transfer/remote-copy.d.ts +0 -66
  234. package/lib/types/src/host/integration/transfer/transfer-adapters.d.ts +0 -48
  235. package/lib/types/src/host/integration/transfer/transfer-tracker.d.ts +0 -106
  236. package/lib/types/src/host/integration/transfer-adapters.d.ts +0 -44
  237. package/lib/types/src/host/integration/transfer-service.d.ts +0 -164
  238. package/lib/types/src/host/integration/transfer-tracker.d.ts +0 -106
  239. package/lib/types/src/host/integration/user-roots.d.ts +0 -461
  240. package/lib/types/src/wiring/connections.d.ts +0 -189
  241. package/lib/types/src/wiring/fs.d.ts +0 -13
  242. package/lib/types/src/wiring/install-memo.d.ts +0 -32
  243. package/lib/types/src/wiring/legacy-dirs.d.ts +0 -62
  244. package/lib/types/src/wiring/package-paths.d.ts +0 -35
  245. package/lib/types/src/wiring/roots.d.ts +0 -21
  246. package/lib/types/src/wiring/state-dir.d.ts +0 -29
  247. package/lib/types/src/wiring/tools.d.ts +0 -35
@@ -1,226 +0,0 @@
1
- /**
2
- * The `ctx.fs` provider: the core filesystem seam served by this plugin's router.
3
- *
4
- * Core components (the model's `read`/`write`/`edit` tools, the workspace file panel, agent
5
- * instructions) reach the filesystem only through `ctx.fs`, so registering this provider is what
6
- * makes remote roots usable everywhere without touching a single consumer.
7
- *
8
- * Mapping rules that matter:
9
- *
10
- * - `targetKey` is the router's namespaced key, wrapped in the core's branded type. Consumers treat
11
- * it as opaque; this provider is the owner that may parse it back.
12
- * - Core error codes are produced here, not leaked from the domain layer: `FS_STALE_VERSION`,
13
- * `FS_NOT_OBSERVED`, `FS_EDIT_NOT_FOUND`, `FS_AMBIGUOUS_EDIT`, `FS_NOT_TEXT`, `FS_TOO_LARGE`,
14
- * `FS_SANDBOX_DENIED`, `FS_IO_ERROR`.
15
- * - The fence is the plugin's own multi-root confinement (ADR-0003): `read-only` denies every
16
- * mutation, a root registered `writable: false` is denied, and `workspace-write` admits every
17
- * registered root — the core's single-root fence cannot express several roots.
18
- *
19
- * @module dsh-remote-workspace/integration/fs-provider
20
- */
21
- import { Context } from '@deepseek-ai/cordis';
22
- import { FileSystem, FsError, FsVersion } from '@deepseek-ai/dsh-fs';
23
- import type { FsDirEntry, FsEditOutcome, FsEditRequest, FsInfo, FsPathInfo, FsTarget, FsWriteIntent, FsWriteOutcome } from '@deepseek-ai/dsh-fs';
24
- import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox';
25
- import type { Backend } from '../app/backend.ts';
26
- import { SshDevError, type SshDevErrorCode } from '../domain/errors.ts';
27
- /**
28
- * One true window read: the bytes at `[offset, offset + length)`, fetched by the backend that owns
29
- * the path **without** buffering the prefix before `offset` (the defect recorded in audit 0016's Lead
30
- * list, item 1: `readByteRange` used to read `[0, end)` and slice).
31
- */
32
- export interface RangeWindow {
33
- readonly bytes: Uint8Array;
34
- /** Full size of the file when the backend can report it cheaply; `undefined` when it cannot. */
35
- readonly size?: number;
36
- /**
37
- * Whether `bytes` stops before the end of the file.
38
- *
39
- * `false` means the window reached EOF and is the **only** signal
40
- * {@link RoutedFsProvider.readByteRange} needs to stop paging: without it a window that ends exactly
41
- * at EOF would cost one extra empty round trip, and a window that ends past EOF would look identical
42
- * to one that stopped short. Every reader must report it truthfully — a reader that keeps saying
43
- * `true` makes the provider page on past the end.
44
- */
45
- readonly truncated: boolean;
46
- }
47
- /**
48
- * Offset-read seam.
49
- *
50
- * This is an **injected optional function**, not a `Backend` method: `Backend` (and
51
- * `RemoteBackend`, the only backend that could implement it) is deliberately outside this change's
52
- * write scope, so the capability arrives as a constructor dependency instead. It is handed the
53
- * resolved backend and its root-absolute path, so one injected function can serve every root.
54
- *
55
- * Return `null` — never throw — to say "this backend/transport has no offset read". The provider then
56
- * falls back to the bounded prefix read and does **not** pretend the read was chunked.
57
- */
58
- export type BackendRangeReader = (backend: Backend, request: {
59
- readonly absolute: string;
60
- readonly offset: number;
61
- readonly length: number;
62
- }, signal?: AbortSignal) => Promise<RangeWindow | null>;
63
- /** Options for {@link RoutedFsProvider}. */
64
- export interface RoutedFsProviderOptions {
65
- /**
66
- * How to read a byte window where the backend can seek.
67
- *
68
- * Omitted (the default, and what `ctx.plugin(RoutedFsProvider)` gets) means every read keeps the
69
- * old semantics. Wire it at the point the remote backend is built (`src/index.ts`
70
- * `createRemoteBackend`, currently lines 355-365), where the transport — and therefore
71
- * `Transport.readFileRange` — is reachable; see {@link createBackendRangeReader}.
72
- */
73
- readonly readBytesRange?: BackendRangeReader;
74
- /** Largest window one underlying request may ask for; the memory bound for a chunked read. */
75
- readonly rangeChunkBytes?: number;
76
- }
77
- /**
78
- * Filesystem provider over the plugin's roots.
79
- *
80
- * Registers as `ctx.fs`; the composition replaces the core `fs-sandbox` row with this one so the
81
- * model's file tools follow the router (see `cordis.patch.yml`).
82
- */
83
- export declare class RoutedFsProvider extends FileSystem {
84
- #private;
85
- static inject: string[];
86
- protected readonly rangeReader: BackendRangeReader | undefined;
87
- protected readonly rangeChunkBytes: number;
88
- constructor(ctx: Context, options?: RoutedFsProviderOptions);
89
- /** This provider confines writes to the registered roots. */
90
- get sandboxMode(): SandboxMode;
91
- /** Resolve a model-facing path to the router's target and wrap it for the core. */
92
- resolve(path: string, opts?: {
93
- cwd?: string;
94
- signal?: AbortSignal;
95
- }): Promise<FsTarget>;
96
- /** Path a subprocess in the target's world can open (the remote absolute path for remote roots). */
97
- processPath(target: FsTarget): string;
98
- /** Map a host path onto the local world when one of the registered roots covers it. */
99
- processPathFromHostPath(hostPath: string): string | undefined;
100
- /** Canonical `file:` URI in the target's world. */
101
- fileUrl(target: FsTarget): string;
102
- /** Containment; two targets in different worlds never contain one another. */
103
- contains(parent: FsTarget, child: FsTarget): boolean;
104
- /** Metadata, or `undefined` for an absent target. */
105
- stat(target: FsTarget, signal?: AbortSignal): Promise<FsInfo | undefined>;
106
- /** Path metadata without following a final symlink, where the backend can tell. */
107
- lstat(path: string, opts?: {
108
- cwd?: string;
109
- }, signal?: AbortSignal): Promise<FsPathInfo | undefined>;
110
- /** Whole-file UTF-8 text; binary and oversize files fail with typed codes. */
111
- readText(target: FsTarget, signal?: AbortSignal): Promise<string>;
112
- /**
113
- * Stream text in chunks.
114
- *
115
- * Backends currently hand back the whole bounded body, so this yields it as one chunk; a
116
- * transport-level chunked read is a follow-up, and the bound keeps memory finite meanwhile.
117
- */
118
- streamText(target: FsTarget, signal?: AbortSignal): Promise<AsyncIterable<string>>;
119
- /** Whole-file bytes, refusing oversized targets instead of truncating. */
120
- readBytes(target: FsTarget, signal: AbortSignal | undefined, maxBytes: number): Promise<Uint8Array>;
121
- /**
122
- * One byte window, bounded by the caller's window rather than the file size.
123
- *
124
- * Two paths, and they are deliberately distinguishable:
125
- *
126
- * - the backend has an offset read (the injected {@link BackendRangeReader} answers with a window):
127
- * the window is fetched as a sequence of requests of at most the configured chunk size, each
128
- * starting at the file offset it needs. Nothing before `offset` is ever transferred or held, so
129
- * the memory bound is the chunk size plus the returned window, not the file size;
130
- * - the backend has none (a local backend, a transport without `readFileRange`, or no injected
131
- * reader at all): the previous semantics are kept exactly — one bounded prefix read `[0, end)`
132
- * capped at 8 MiB, then a slice — and a window past that cap still fails with `FS_TOO_LARGE`
133
- * instead of silently buffering the file.
134
- */
135
- readByteRange(target: FsTarget, range: {
136
- offset: number;
137
- length: number;
138
- }, signal?: AbortSignal): Promise<Uint8Array>;
139
- /** Direct children, in stable name order, with resolved child targets. */
140
- listDir(target: FsTarget, signal?: AbortSignal): Promise<FsDirEntry[]>;
141
- /** Atomic write, honouring the write intent and the plugin's fence. */
142
- writeText(target: FsTarget, content: string, expected?: FsWriteIntent, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsWriteOutcome>;
143
- /** Literal edit with the core's three-state semantics and an optional version guard. */
144
- editText(target: FsTarget, edit: FsEditRequest, expected?: {
145
- version: FsVersion;
146
- }, signal?: AbortSignal, sandboxPolicy?: SandboxExecutionPolicy): Promise<FsEditOutcome>;
147
- /**
148
- * Observation is not available yet.
149
- *
150
- * Tier 1 has no remote watcher, and the router deliberately reports `watches: false` instead of
151
- * pretending: the caller (observation policy) falls back to revalidation on read.
152
- *
153
- * @param target - the target whose changes were requested.
154
- * @param _changed - invalidation callback the base class would call; unused while unsupported.
155
- * @param _signal - cancels watcher initialization; unused while unsupported.
156
- * @returns never, because no watcher can be created yet.
157
- * @throws FsError with `FS_IO_ERROR` until a watcher exists.
158
- */
159
- watch(target: FsTarget, _changed: (error?: Error) => void, _signal: AbortSignal): Promise<() => Promise<void>>;
160
- private rootsService;
161
- private router;
162
- private routedTarget;
163
- /** Enforce the per-call policy and the root's own writability. */
164
- private assertWritable;
165
- /** Previous text content, when it is readable text inside the cap; `undefined` otherwise. */
166
- private readPriorText;
167
- /** Run a backend call, translating domain errors into core codes. */
168
- private call;
169
- }
170
- /**
171
- * The plugin callback {@link createRoutedFsProvider} answers.
172
- *
173
- * `inject` is part of the shape because Cordis reads it off the plugin it is handed; typing it here keeps
174
- * the factory's contract honest instead of relying on a cast at the call site.
175
- */
176
- export interface FsProviderPlugin {
177
- (ctx: Context): void;
178
- inject: readonly string[];
179
- }
180
- /**
181
- * Build the `ctx.fs` plugin with an injected offset-read seam.
182
- *
183
- * Cordis registers a plugin by calling it with the context, so a deployment that has the range reader
184
- * available can register `createRoutedFsProvider({ readBytesRange })` instead of the bare class and
185
- * get true chunked window reads; registering the class itself keeps the old semantics. Both are the
186
- * same provider, so nothing else in the composition changes.
187
- *
188
- * Two details are load-bearing, and both were wrong before (found by loading the real `./fs` row in a
189
- * packaged host — the provider never activated, so every `fs` consumer stayed pending):
190
- *
191
- * - the callback must **not return the instance**. Cordis treats a function plugin's return value as
192
- * an effect to apply, and a provider instance is not one: `ctx.plugin(fn)` fails with
193
- * `Invalid effect` and the service is never provided. Constructing the instance inside the call is
194
- * what registers it (it extends `FileSystem`, which registers itself in the constructor).
195
- * - the callback must **carry the class's `inject`**. Cordis reads `inject` off the plugin it is
196
- * given, and a bare arrow function has none, so the provider would install before `sshDevRoots`
197
- * exists and silently read an undefined service.
198
- *
199
- * @param options - the seam plus the chunk size; see {@link RoutedFsProviderOptions}.
200
- * @returns a plugin callback that constructs the provider on registration.
201
- */
202
- export declare function createRoutedFsProvider(options: RoutedFsProviderOptions): FsProviderPlugin;
203
- /**
204
- * Build the {@link BackendRangeReader} the provider injects.
205
- *
206
- * The Lead wires the pieces that live outside this change's write scope: a store that already holds a
207
- * backend's bytes (tests), or — in production — the transport behind the backend, calling
208
- * `Transport.readFileRange({ path, offset, maxBytes })` and returning `null` when that optional method
209
- * is absent. The provider owns everything else: chunking, the memory bound, EOF short-circuiting.
210
- *
211
- * @param store - reads `[offset, offset + length)` from a backend, or `undefined` for a missing path.
212
- * @param options - `chunkSizeHint` advertises the largest window worth asking for; it is **not** how the
213
- * provider bounds memory (the provider chunks by its own `rangeChunkBytes`).
214
- * @returns a reader that answers `null` (never throws) when the store has no offset read.
215
- */
216
- export declare function createBackendRangeReader(store: (backend: Backend, offset: number, length: number) => {
217
- readonly bytes: Uint8Array;
218
- readonly size: number;
219
- } | undefined, options?: {
220
- readonly chunkSizeHint?: number;
221
- }): BackendRangeReader;
222
- /** Translate a domain failure into the core's filesystem vocabulary. */
223
- export declare function toFsError(error: SshDevError): FsError;
224
- /** Codes this provider can surface, exported for tests that assert the mapping table. */
225
- export declare const MAPPED_DOMAIN_CODES: readonly SshDevErrorCode[];
226
- //# sourceMappingURL=fs-provider.d.ts.map
@@ -1,38 +0,0 @@
1
- /**
2
- * LSP base protocol framing: `Content-Length: <bytes>\r\n\r\n<json>`.
3
- *
4
- * The agent is a **byte pipe** — it spawns the language server and moves bytes, but does not parse
5
- * JSON-RPC ([protocol.md §lsp.*](../../../../dsh-over-ssh-agent/doc/01-product/protocol.md)). Everything in
6
- * this module is therefore the plugin's job.
7
- *
8
- * `Content-Length` counts **bytes**, not characters. A parser that slices by string length passes every
9
- * ASCII test and corrupts the first frame containing a multi-byte character — which in practice means the
10
- * first diagnostic message written in Chinese. This module works on bytes throughout for that reason.
11
- *
12
- * @module dsh-over-ssh/host/integration/lsp/lsp-framing
13
- */
14
- /** A cap on one frame's declared length. A corrupt header must not make us allocate without bound. */
15
- export declare const MAX_LSP_FRAME_BYTES: number;
16
- /** Encode one JSON-RPC message as an LSP frame. */
17
- export declare function encodeLspFrame(message: unknown): Uint8Array;
18
- /** What one parsed frame carried. */
19
- export type LspMessage = Record<string, unknown>;
20
- /**
21
- * Incremental parser for a language server's stdout.
22
- *
23
- * Bytes arrive in whatever chunks the agent's ring buffer happens to hand over, so a frame routinely
24
- * straddles two reads. {@link feed} returns every message that became complete and keeps the remainder.
25
- */
26
- export declare class LspFrameParser {
27
- #private;
28
- /**
29
- * Append bytes and return every message that is now complete.
30
- *
31
- * A malformed header is **not** skipped silently: the stream is no longer parseable (we cannot know
32
- * where the next frame starts), so this throws and the caller must restart the session.
33
- */
34
- feed(chunk: Uint8Array | string): LspMessage[];
35
- /** Bytes held back waiting for the rest of a frame. Diagnostics only. */
36
- get pending(): number;
37
- }
38
- //# sourceMappingURL=lsp-framing.d.ts.map
@@ -1,67 +0,0 @@
1
- /**
2
- * Per-connection language-server sessions, shared across tool calls.
3
- *
4
- * A language server takes seconds to index a project, so starting one per tool call would make every query
5
- * useless. This keeps one session per (connection, root, language) and reuses it.
6
- *
7
- * The registry also owns the **default server table**: which executable to run for a language. Nothing is
8
- * probed here — if the executable is missing, `lsp.start` fails and the error says which command was tried.
9
- *
10
- * @module dsh-over-ssh/host/integration/lsp/lsp-registry
11
- */
12
- import { LspSession, type LspDiagnostic, type LspTransportLike } from './lsp-session.ts';
13
- /** Which remote root a session belongs to. */
14
- export interface LspTarget {
15
- readonly connectionId: string;
16
- readonly root: string;
17
- }
18
- /** One server to run for a language. */
19
- export interface LspServerCommand {
20
- readonly command: string;
21
- readonly args?: readonly string[];
22
- }
23
- /** Language id for a path, matching the LSP `languageId` convention. */
24
- export declare function languageForPath(path: string): string;
25
- /** The default server for a language, or `undefined` when the table has no entry. */
26
- export declare function defaultServerFor(language: string): LspServerCommand | undefined;
27
- /** A session as reported to a caller. */
28
- export interface LspSessionInfo {
29
- readonly connectionId: string;
30
- readonly root: string;
31
- readonly language: string;
32
- readonly command: string;
33
- readonly id: string;
34
- readonly stopped: boolean;
35
- }
36
- /**
37
- * A transport as seen by the registry: **possibly** LSP-capable.
38
- *
39
- * Tier 1 (plain `ssh host 'cmd'`) has no LSP methods at all, and the registry must say so instead of
40
- * assuming. Callers get a clear "this connection cannot run a language server" rather than a TypeError on
41
- * an undefined method.
42
- */
43
- export type MaybeLspTransport = Partial<LspTransportLike>;
44
- export interface LspRegistryDeps {
45
- /** Acquire the transport for a connection; same shape the other tools use. */
46
- acquire(connectionId: string): Promise<MaybeLspTransport>;
47
- /** Server log lines (`window/logMessage`), for the host log. */
48
- onLog?(connectionId: string, message: string): void;
49
- }
50
- export interface LspRegistry {
51
- /**
52
- * The session for this target+language, started and initialized on first use.
53
- *
54
- * `override` replaces the default executable — the escape hatch for a language not in the table, or for a
55
- * server the caller wants to run with different arguments.
56
- */
57
- session(target: LspTarget, language: string, override: LspServerCommand | undefined, signal: AbortSignal): Promise<LspSession>;
58
- list(): readonly LspSessionInfo[];
59
- /** Close one session. Returns false when there was nothing to close. */
60
- stop(target: LspTarget, language: string, signal: AbortSignal): Promise<boolean>;
61
- /** Close every session. Called on plugin teardown. */
62
- disposeAll(): Promise<void>;
63
- }
64
- export declare function createLspRegistry(deps: LspRegistryDeps): LspRegistry;
65
- /** Diagnostics grouped for rendering. Re-exported so the tool does not import the session module directly. */
66
- export type { LspDiagnostic };
67
- //# sourceMappingURL=lsp-registry.d.ts.map
@@ -1,130 +0,0 @@
1
- /**
2
- * One language-server session, driven over the agent's byte pipe.
3
- *
4
- * The agent spawns the server and moves bytes; **it does not parse JSON-RPC**
5
- * ([protocol.md §lsp.*](../../../../dsh-over-ssh-agent/doc/01-product/protocol.md), ADR-0006). Everything
6
- * LSP-aware lives here: the `initialize` handshake, request/response correlation, server→client requests,
7
- * and diagnostics collection.
8
- *
9
- * The transport is poll-based (`lsp.read` with an offset), so this class owns a pump loop. It backs off
10
- * while the server is quiet — a language server is idle most of the time, and polling it at full speed
11
- * would spend the SSH connection on nothing.
12
- *
13
- * @module dsh-over-ssh/host/integration/lsp/lsp-session
14
- */
15
- import type { AgentLspRead, AgentLspStartRequest, AgentLspStatus } from '../../infra/transport/agent/agent-protocol-types.ts';
16
- /** The slice of an agent transport one session needs. */
17
- export interface LspTransportLike {
18
- /**
19
- * Host capabilities, when the transport exposes them (`Transport.capabilities`).
20
- *
21
- * Optional because the byte pipe itself does not need them — only the registry's "is this server
22
- * installed" check does.
23
- */
24
- readonly capabilities?: {
25
- readonly lspServers?: readonly {
26
- readonly command: string;
27
- readonly language: string;
28
- readonly path: string;
29
- }[];
30
- };
31
- lspStart(request: AgentLspStartRequest, signal?: AbortSignal): Promise<AgentLspStatus>;
32
- lspWrite(id: string, bytes: Uint8Array, signal?: AbortSignal): Promise<{
33
- readonly id: string;
34
- readonly written: number;
35
- readonly state: string;
36
- }>;
37
- lspRead(id: string, offset?: number, signal?: AbortSignal): Promise<AgentLspRead>;
38
- lspStop(id: string, signal?: AbortSignal): Promise<AgentLspStatus>;
39
- /**
40
- * Release a finished session's agent-side record and output buffer.
41
- *
42
- * Optional: only the agent transport has it. Absent means the agent will evict the row by itself later,
43
- * which is correct — just slower to reclaim.
44
- */
45
- lspForget?(id: string, signal?: AbortSignal): Promise<void>;
46
- }
47
- /** One diagnostic, flattened to what a caller needs. */
48
- export interface LspDiagnostic {
49
- readonly line: number;
50
- readonly character: number;
51
- readonly endLine: number;
52
- readonly endCharacter: number;
53
- /** `error` / `warning` / `information` / `hint`. */
54
- readonly severity: string;
55
- readonly message: string;
56
- /** `file` / `warning` / `info` / `hint`, when the server sent one. */
57
- readonly source?: string;
58
- }
59
- /** A server that failed to answer in time, or exited, must not leave callers hanging. */
60
- export declare class LspSessionError extends Error {
61
- }
62
- export interface LspSessionOptions {
63
- /** Executable name on PATH or absolute path. */
64
- readonly command: string;
65
- readonly args?: readonly string[];
66
- /** Working directory; language servers use it to find project config. */
67
- readonly cwd?: string;
68
- readonly env?: Readonly<Record<string, string>>;
69
- /** Called for `window/logMessage` and similar, for diagnostics. */
70
- readonly onLog?: (message: string) => void;
71
- }
72
- /**
73
- * One running language server.
74
- *
75
- * Lifecycle: {@link start} → {@link initialize} → queries → {@link close}.
76
- */
77
- export declare class LspSession {
78
- #private;
79
- constructor(transport: LspTransportLike, options: LspSessionOptions);
80
- /** The agent's session id. Empty until {@link start}. */
81
- get id(): string;
82
- /** True once the server has exited or the session was stopped. */
83
- get stopped(): boolean;
84
- /** Start the server process and begin pumping its output. */
85
- start(signal: AbortSignal): Promise<void>;
86
- /** The `initialize` / `initialized` handshake. */
87
- initialize(rootPath: string, signal: AbortSignal): Promise<void>;
88
- /**
89
- * Ask for diagnostics on one document.
90
- *
91
- * Diagnostics are **pushed**: the server sends `textDocument/publishDiagnostics` after `didOpen` or
92
- * `didChange`, with no request to correlate against. So this opens the document, then waits for a
93
- * notification for that URI (or the timeout). A server that never publishes yields an empty list rather
94
- * than an error — "no diagnostics" and "did not answer" look the same to a caller that only wants to
95
- * know whether the file is clean.
96
- */
97
- diagnostics(uri: string, text: string, signal: AbortSignal, timeoutMs?: number): Promise<{
98
- readonly diagnostics: readonly LspDiagnostic[];
99
- readonly answered: boolean;
100
- }>;
101
- /**
102
- * Open a document, or send the new text if it is already open.
103
- *
104
- * Position-based queries (`hover`, `definition`) need this first: a server answers about documents it
105
- * knows, and an unopened file gets an empty result rather than an error — which reads as "no symbol here".
106
- */
107
- openDocument(uri: string, text: string): void;
108
- /** Diagnostics already received for a URI, without asking again. */
109
- cachedDiagnostics(uri: string): readonly LspDiagnostic[] | undefined;
110
- /** One `textDocument/hover` query. */
111
- hover(uri: string, line: number, character: number, signal: AbortSignal): Promise<unknown>;
112
- /** One `textDocument/definition` query. */
113
- definition(uri: string, line: number, character: number, signal: AbortSignal): Promise<unknown>;
114
- /** Send one JSON-RPC request and wait for its response. */
115
- request(method: string, params: unknown, signal: AbortSignal, timeoutMs?: number): Promise<unknown>;
116
- /** Send one JSON-RPC notification (no response expected). */
117
- notify(method: string, params: unknown): void;
118
- /** Shut the server down politely, then stop it. */
119
- close(signal: AbortSignal): Promise<void>;
120
- }
121
- /**
122
- * Absolute path → `file://` URI.
123
- *
124
- * Percent-encoding matters: a path with a space or a Chinese character becomes a URI the server will not
125
- * match against its own, and every subsequent `didOpen` silently does nothing.
126
- */
127
- export declare function pathToUri(absolute: string): string;
128
- /** `file://` URI → absolute path. */
129
- export declare function uriToPath(uri: string): string;
130
- //# sourceMappingURL=lsp-session.d.ts.map
@@ -1,64 +0,0 @@
1
- /**
2
- * The management tool surface: `remote_transfer` (upload/download) and `remote_delete` (recycle/permanent).
3
- *
4
- * `remote_delete` is the reason this module exists separately from `remote-tools.ts`: a **permanent** delete
5
- * bypasses `ctx.fs` and cannot be undone, so it goes through the platform's pre-execute waterfall and is
6
- * answered with `ask` (which the registry turns into a denial when the composition has no approval surface —
7
- * fail closed). Recycle mode is an ordinary call: it is recoverable and `undo` exists.
8
- *
9
- * @module dsh-remote-workspace/integration/management-tools
10
- */
11
- import type { Context } from '@deepseek-ai/cordis';
12
- import { type ToolDefinition } from '@deepseek-ai/dsh-tools';
13
- import type { DiscardResult } from '../app/recycle-bin-service.ts';
14
- import type { TransferResult } from './transfer-service.ts';
15
- /** Where one call lands. */
16
- export interface ManagementTarget {
17
- readonly connectionId: string;
18
- /** Backend-absolute root path. */
19
- readonly root: string;
20
- }
21
- /** What the tools need, injected so the definitions stay testable without transports. */
22
- export interface ManagementToolBackend {
23
- /** Resolve the calling agent's working directory to a remote root. */
24
- resolve(cwd: string): ManagementTarget | undefined;
25
- /** Run one upload or download. */
26
- transfer(request: {
27
- readonly target: ManagementTarget;
28
- readonly direction: 'upload' | 'download';
29
- readonly localPath: string;
30
- readonly remotePath: string;
31
- readonly signal: AbortSignal;
32
- }): Promise<TransferResult>;
33
- /** Discard one path, into the bin or permanently. */
34
- discard(request: {
35
- readonly target: ManagementTarget;
36
- readonly path: string;
37
- readonly mode: 'recycle' | 'permanent';
38
- readonly signal: AbortSignal;
39
- }): Promise<DiscardResult>;
40
- }
41
- /** Human summary of a finished transfer. */
42
- export declare function formatTransfer(result: TransferResult): string;
43
- /** Human summary of a discard. */
44
- export declare function formatDiscard(result: DiscardResult): string;
45
- /**
46
- * Build the two definitions.
47
- *
48
- * @param backend - injected implementations.
49
- * @returns definitions ready for `ctx.tools.register`.
50
- */
51
- export declare function managementToolDefinitions(backend: ManagementToolBackend): ToolDefinition[];
52
- /**
53
- * Gate irreversible deletions behind the platform's approval surface.
54
- *
55
- * A **denial by default** is deliberate: when the composition has no approval support, the registry turns
56
- * `ask` into a denial, which is the right outcome for an operation that bypasses `ctx.fs` and cannot be undone.
57
- *
58
- * @param ctx - host context with the `tools` service.
59
- * @returns a disposer removing the gate.
60
- */
61
- export declare function permanentDeleteGate(ctx: Context): () => void;
62
- /** Register both tools and the gate. */
63
- export declare function registerManagementTools(ctx: Context, backend: ManagementToolBackend): () => void;
64
- //# sourceMappingURL=management-tools.d.ts.map