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,46 +0,0 @@
1
- /**
2
- * The session-administration tool surface: one `remote_sessions` tool whose `action` picks list / delete /
3
- * delete_workspace / restore. Four separate tools for a rarely-used feature was the worst size-to-value ratio
4
- * on the whole surface.
5
- *
6
- * These operate on the **platform's session store**, not on a remote root, so they take no connection or root:
7
- * a session is identified by its id, and its location is derived from its own header (`cwd` → `projectKey`).
8
- * That is also why they do not go through `ctx.fs` — the store is not a workspace file.
9
- *
10
- * **Irreversible calls are gated.** `mode: "permanent"` goes through the platform's pre-execute waterfall and is
11
- * answered with `ask`; when the composition has no approval surface the registry turns that into a denial (fail
12
- * closed). Recycle-mode deletion is an ordinary call: it is recoverable.
13
- *
14
- * @module dsh-over-ssh/integration/session-tools
15
- */
16
- import type { Context } from '@deepseek-ai/cordis';
17
- import { type ToolDefinition } from '@deepseek-ai/dsh-tools';
18
- import type { DeleteSessionResult, SessionAdminService } from '../../app/session-admin/session-admin-service.ts';
19
- import type { SessionTrashEntry } from '../../domain/session/session-admin.ts';
20
- import type { SessionRecord } from '../../domain/session/session-admin.ts';
21
- /** Format one inventory record as a human-readable line. */
22
- export declare function formatSession(record: SessionRecord): string;
23
- /** Human summary of a session deletion. */
24
- export declare function formatSessionDelete(result: DeleteSessionResult): string;
25
- /** Human summary of the bin. */
26
- export declare function formatSessionBin(entries: readonly SessionTrashEntry[]): string;
27
- /**
28
- * Build the session-administration definitions.
29
- *
30
- * @param service - the session administration service.
31
- * @returns definitions ready for `ctx.tools.register`.
32
- */
33
- export declare function sessionToolDefinitions(service: SessionAdminService): ToolDefinition[];
34
- /**
35
- * Gate irreversible session operations behind the platform's approval surface.
36
- *
37
- * Denial by default is deliberate: these calls destroy conversation history that cannot be regenerated, and a
38
- * composition without an approval surface must refuse rather than proceed.
39
- *
40
- * @param ctx - host context with the `tools` service.
41
- * @returns a disposer removing the gate.
42
- */
43
- export declare function sessionDestructionGate(ctx: Context): () => void;
44
- /** Register the session tool and the gate. */
45
- export declare function registerSessionTools(ctx: Context, service: SessionAdminService): () => void;
46
- //# sourceMappingURL=session-tools.d.ts.map
@@ -1,79 +0,0 @@
1
- /**
2
- * Strict root-level argument validation for this plugin's tool surface.
3
- *
4
- * **Why this exists.** `defineTool` compiles the parameter map into an object-rooted JSON Schema that
5
- * carries `properties` and `required` but **no `additionalProperties`**, and the core validator only
6
- * reports an undeclared property when that keyword is explicitly `false`
7
- * (`@deepseek-ai/dsh-tools` `json-schema.ts`, the `object` case). A model that writes `stdin`, `shell`,
8
- * `waitMs`, `mode` or `executable` therefore gets a **successful** call in which the field was silently
9
- * dropped — the most dangerous failure mode there is, because the caller believes the setting took effect.
10
- *
11
- * The plugin cannot close the core's implicit root, so it enforces closure itself on the documented
12
- * pre-dispatch extension point (`tools/pre-execute`), the same hook `permanentDeleteGate` already uses.
13
- *
14
- * **One message, everything wrong at once.** The core reports missing/typed arguments from inside
15
- * `execute`, but a pre-execute gate runs *before* that, so this gate can name every unknown field and every
16
- * missing required field in a single refusal instead of sending the caller back one field at a time.
17
- *
18
- * @module dsh-over-ssh/integration/strict-arguments
19
- */
20
- import type { Context } from '@deepseek-ai/cordis';
21
- /**
22
- * The name prefix every tool of this plugin uses.
23
- *
24
- * The gate is scoped by prefix rather than by a copied name list: a list would drift the moment a tool is
25
- * added, and this plugin's namespace is `remote_*`. `tests/strict-arguments.test.ts` pins that every tool
26
- * name this plugin registers starts with the prefix, so the assumption cannot rot silently.
27
- */
28
- export declare const STRICT_TOOL_PREFIX = "remote_";
29
- /** Whether a tool name belongs to this plugin's surface. */
30
- export declare function isStrictTool(name: string): boolean;
31
- /** What one argument check found. */
32
- export interface ArgumentViolations {
33
- /** Fields the caller sent that the tool does not declare. */
34
- readonly unknown: readonly string[];
35
- /** Fields the tool requires that the caller did not send. */
36
- readonly missing: readonly string[];
37
- /** Every field the tool does declare, in declaration order. */
38
- readonly declared: readonly string[];
39
- }
40
- /** The parts of one registered parameter schema this gate reads. */
41
- export interface StrictParameterSchema {
42
- readonly properties?: Readonly<Record<string, unknown>> | undefined;
43
- readonly required?: readonly string[] | undefined;
44
- }
45
- /**
46
- * Compare a call's arguments against the tool's own declared parameters.
47
- *
48
- * Only the **root** is checked: a nested open map (such as `remote_exec`'s `env`) keeps whatever openness it
49
- * declared, because closing it would reject the very keys that field exists to carry.
50
- *
51
- * A non-object argument (or a missing schema) yields no violations here: the core's own validation owns
52
- * those cases, and reporting them twice would produce two different messages for one mistake.
53
- *
54
- * @param schema - the registered parameter schema (`properties` / `required`).
55
- * @param args - the model-supplied arguments, however malformed.
56
- * @returns the unknown fields, the missing required fields, and the declared field list.
57
- */
58
- export declare function argumentViolations(schema: StrictParameterSchema | undefined, args: unknown): ArgumentViolations;
59
- /** Whether anything was found worth refusing. */
60
- export declare function hasViolations(violations: ArgumentViolations): boolean;
61
- /**
62
- * The model-facing refusal.
63
- *
64
- * It names what was rejected **and** what is accepted: the caller's next attempt should be a correction, not
65
- * a guess. "Unknown field" alone would leave the model trying spellings one at a time.
66
- *
67
- * @param toolName - the tool that was called.
68
- * @param violations - what the check found.
69
- * @returns one actionable sentence.
70
- */
71
- export declare function formatArgumentViolations(toolName: string, violations: ArgumentViolations): string;
72
- /**
73
- * Register the gate.
74
- *
75
- * @param ctx - host context with the `tools` service.
76
- * @returns a disposer removing the listener (idempotent).
77
- */
78
- export declare function strictArgumentsGate(ctx: Context): () => void;
79
- //# sourceMappingURL=strict-arguments.d.ts.map
@@ -1,94 +0,0 @@
1
- /**
2
- * The files a terminal wrapper reads: the root manifest and per-session state.
3
- *
4
- * The wrapper is a **separate process** launched by the platform's terminal controller, so it cannot ask the
5
- * host anything over IPC — it reads two small JSON files instead:
6
- *
7
- * - `roots.json` — every remote root with its local anchor and its already-credential-resolved ssh argv;
8
- * - `state/<sessionId>.json` — the remote target of one session, written when the host resolves it.
9
- *
10
- * Writes are atomic (temp file + rename) because the wrapper may read them at any moment, and a half-written
11
- * JSON must never decide where the user's terminal goes.
12
- *
13
- * @module dsh-over-ssh/integration/terminal-manifest
14
- */
15
- import { type ManifestRoot, type RootManifest, type SessionState, type SshInvocation } from '../../domain/session/terminal-target.ts';
16
- /**
17
- * Build the ssh invocation the terminal wrapper spawns for one connection.
18
- *
19
- * Deliberately shared with the entry **and** with the real-host verification: a hand-written copy is exactly
20
- * how a wrapper ends up connecting as the local user instead of the configured one (the verification script
21
- * hit that: `ssh host` used `yerier@…` and was refused, because the manifest lacked `-l root`).
22
- *
23
- * Difference from the alias transport: terminals are interactive, so a password connection must be allowed to
24
- * prompt (`BatchMode=no`) — an agent-authenticated one must not.
25
- *
26
- * @param profile - connection facts (host, alias, port, user, auth).
27
- * @param limits - resolved plugin limits (`knownHostsFile`, `connectTimeoutMs`).
28
- * @returns destination plus credential arguments.
29
- */
30
- export declare function sshInvocationFor(profile: {
31
- readonly host: string;
32
- readonly alias?: string;
33
- readonly port?: number;
34
- readonly user?: string;
35
- readonly authKind: 'agent' | 'key' | 'password';
36
- readonly identityFile?: string;
37
- readonly connectTimeoutMs?: number;
38
- }, limits?: {
39
- readonly knownHostsFile?: string;
40
- readonly connectTimeoutMs?: number;
41
- }): SshInvocation;
42
- /** File-system surface, injected so tests never touch the developer's home directory. */
43
- export interface ManifestIo {
44
- readFile(path: string): Promise<string>;
45
- writeFile(path: string, data: string): Promise<void>;
46
- mkdir(path: string): Promise<void>;
47
- rename(from: string, to: string): Promise<void>;
48
- remove(path: string): Promise<void>;
49
- list(dir: string): Promise<readonly string[]>;
50
- }
51
- /** Real file-system binding. */
52
- export declare const nodeManifestIo: ManifestIo;
53
- /**
54
- * Turn a session id into a safe file name.
55
- *
56
- * Session ids are host-chosen strings and may contain separators or colons; the name is sanitized and given a
57
- * short hash suffix so two distinct ids can never collide onto one file.
58
- *
59
- * @param sessionId - raw session id.
60
- * @returns a file name (no directory part) unique to that id.
61
- */
62
- export declare function sessionFileName(sessionId: string): string;
63
- /** Reads and writes the wrapper's manifest files. */
64
- export declare class TerminalManifestStore {
65
- #private;
66
- /**
67
- * @param options - `dir` is the plugin state directory (usually `~/.dsh/over-ssh`).
68
- */
69
- constructor(options: {
70
- readonly dir: string;
71
- readonly io?: ManifestIo;
72
- });
73
- /** Absolute path of the root manifest. */
74
- get manifestPath(): string;
75
- /** Absolute path of one session's state file. */
76
- statePath(sessionId: string): string;
77
- /**
78
- * Replace the whole root manifest.
79
- *
80
- * @param roots - remote roots the terminal wrapper may target.
81
- */
82
- writeRoots(roots: readonly ManifestRoot[]): Promise<void>;
83
- /** Read the root manifest; `undefined` when missing, malformed, or from another format version. */
84
- readRoots(): Promise<RootManifest | undefined>;
85
- /** Record one session's remote target. */
86
- writeSession(state: SessionState): Promise<void>;
87
- /** Read one session's target; `undefined` when missing or malformed. */
88
- readSession(sessionId: string): Promise<SessionState | undefined>;
89
- /** Remove one session's state (session closed); missing files are not an error. */
90
- forgetSession(sessionId: string): Promise<void>;
91
- /** Every readable session state (used by the wrapper when it has no session id). */
92
- listSessions(): Promise<readonly SessionState[]>;
93
- }
94
- //# sourceMappingURL=terminal-manifest.d.ts.map
@@ -1,66 +0,0 @@
1
- /**
2
- * Copy one remote file to another path **on the remote side**.
3
- *
4
- * Why this exists separately from the transfer service: that service models "local file ↔ remote file", and
5
- * its failure context is typed `upload | download`. A remote-to-remote copy has neither a local path nor a
6
- * direction, so folding it in would mean widening every one of those types for one caller.
7
- *
8
- * Two paths, in order of preference:
9
- *
10
- * 1. **Server-side** (`transport.copyFile`): the remote host copies the file itself. No bytes cross this
11
- * process and none touch the local disk — the whole point of the operation.
12
- * 2. **Relay**: read a chunk from the source and write it to the destination through this process. Used when
13
- * the transport has no server-side copy (Tier 1, or an agent that predates `fs.copy`). The bytes do pass
14
- * through here, and the outcome says so instead of implying otherwise.
15
- *
16
- * @module dsh-over-ssh/integration/transfer/remote-copy
17
- */
18
- import type { RemoteStatResult, Transport } from '../../infra/transport/transport.ts';
19
- /** What one copy needs, injected so the module stays testable without a transport. */
20
- export interface RemoteCopyDeps {
21
- readonly transportFor: (connectionId: string) => Promise<Transport>;
22
- readonly statRemote: (absolute: string) => Promise<RemoteStatResult>;
23
- /** Chunk ceiling for the relay path; ignored when the copy happens on the server. */
24
- readonly chunkBytes: number;
25
- readonly now: () => number;
26
- }
27
- /** One copy request; both paths are already root-absolute. */
28
- export interface RemoteCopyRequest {
29
- readonly connectionId: string;
30
- readonly from: string;
31
- readonly to: string;
32
- /** Replace an existing destination. When false the copy refuses to clobber. */
33
- readonly overwrite: boolean;
34
- /**
35
- * Copy a whole directory tree.
36
- *
37
- * Only the server-side path can do this. There is deliberately **no relay fallback**: relaying a tree file
38
- * by file is the exact cost this mode exists to remove, and a silent fallback would turn one round trip into
39
- * thousands while still reporting success.
40
- */
41
- readonly recursive?: boolean;
42
- readonly signal?: AbortSignal;
43
- readonly onProgress?: (transferredBytes: number, totalBytes: number) => void;
44
- }
45
- /** What the copy did. */
46
- export interface RemoteCopyOutcome {
47
- readonly bytes: number;
48
- /** `server` means the remote host copied it; `relay` means the bytes came through this process. */
49
- readonly via: 'server' | 'relay';
50
- readonly durationMs: number;
51
- /** Recursive copies only: how many of each kind were produced. */
52
- readonly files?: number;
53
- readonly dirs?: number;
54
- readonly symlinks?: number;
55
- }
56
- /**
57
- * Copy `from` to `to` on the remote host, preferring the server-side path.
58
- *
59
- * @param deps - transport lookup, remote stat, chunk size and clock.
60
- * @param request - the two absolute paths, the overwrite policy and an optional cancel signal.
61
- * @returns bytes copied and which path was taken.
62
- * @throws SshDevError `REMOTE_NOT_FOUND` when the source is missing, `REMOTE_UNSUPPORTED` when neither path
63
- * is available, `TRANSFER_CONFLICT` when the destination exists and `overwrite` is false.
64
- */
65
- export declare function copyRemoteFile(deps: RemoteCopyDeps, request: RemoteCopyRequest): Promise<RemoteCopyOutcome>;
66
- //# sourceMappingURL=remote-copy.d.ts.map
@@ -1,48 +0,0 @@
1
- /**
2
- * Adapters that turn the plugin's routing + transports into the injected dependencies the transfer and
3
- * recycle-bin services expect.
4
- *
5
- * Two rules shape everything here:
6
- *
7
- * - **Remote work uses the real primitives.** Chunked reads go through `Transport.readFileRange` (verified on
8
- * a real host: exact window, no whole-file read) and positioned writes through `writeFileRange` (POSIX
9
- * `pwrite` semantics, shared by all three transports). Where a transport lacks the method the fallback is
10
- * written down instead of hidden.
11
- * - **Local work never borrows the remote path.** `node:fs` is opened with `position` arguments so a local
12
- * chunk does not read the whole file either; the recycle bin's local mutators are a separate object, so a
13
- * local target can never end up being "moved" by an ssh command.
14
- *
15
- * @module dsh-over-ssh/integration/transfer-adapters
16
- */
17
- import type { RootRef } from '../../domain/roots/root.ts';
18
- import type { RoutedFileSystem } from '../../app/routed-fs.ts';
19
- import type { Transport } from '../../infra/transport/transport.ts';
20
- import type { RecycleBinServiceDeps } from '../../app/recycle-bin/recycle-bin-service.ts';
21
- import type { TransferDependencies } from './transfer-service.ts';
22
- /** What both adapters need from the plugin. */
23
- export interface WorldAdapterDeps {
24
- /** Path routing: turns a path in any root's spelling into `{root, backend, absolute}`. */
25
- readonly routed: RoutedFileSystem;
26
- /** The transport of one connection (the caller already owns the profile lookup). */
27
- readonly transportFor: (connectionId: string) => Promise<Transport>;
28
- /** Bin directory **inside one root** (same device, so the move stays a rename). */
29
- readonly binRootFor: (root: RootRef) => string;
30
- /** Chunk ceiling passed to the transfer service. */
31
- readonly chunkBytes: number;
32
- /** Chunks in flight at once, passed to the transfer service. */
33
- readonly concurrency: number;
34
- /** Upper bound for one text read (the index file). */
35
- readonly maxReadBytes: number;
36
- /** Clock, injected for tests. */
37
- readonly now?: () => number;
38
- }
39
- /** The transfer service's dependencies. */
40
- export declare function createTransferDeps(deps: WorldAdapterDeps): TransferDependencies;
41
- /** The recycle bin's dependencies: remote primitives plus an explicit local world. */
42
- export declare function createRecycleBinDeps(deps: WorldAdapterDeps & {
43
- readonly knownRoots: () => readonly RootRef[];
44
- readonly undoDepth: number;
45
- /** Cross-process lock around the bin index read-modify-write. */
46
- readonly withIndexLock?: import('../../app/recycle-bin/recycle-bin-contract.ts').WithIndexLock;
47
- }): RecycleBinServiceDeps;
48
- //# sourceMappingURL=transfer-adapters.d.ts.map
@@ -1,106 +0,0 @@
1
- /**
2
- * A bounded registry of in-flight and recently finished transfers (FR-2.6.4).
3
- *
4
- * Why a registry and not a callback straight into the client: the UI asks "what is happening" whenever it
5
- * renders, which is a *pull*. Pushing would need a channel this plugin does not have (its client half talks
6
- * over one HTTP route), so the honest shape is a small table the UI polls.
7
- *
8
- * Three rules, each of which is a way a progress UI usually lies:
9
- *
10
- * 1. **A finished transfer is kept, not deleted.** A row that vanishes the instant it completes leaves the
11
- * user unable to tell "done" from "failed and cleared"; the failure list FR-2.6.4 asks for is exactly
12
- * the recent history.
13
- * 2. **The table is bounded** (`maxEntries`, oldest finished first). An unbounded map keyed by transfer id is
14
- * a leak that only shows up after a long session.
15
- * 3. **`percent` is computed from the bytes that landed, never extrapolated.** A progress bar that jumps to
16
- * the end because a chunk was *planned* is worse than no bar.
17
- *
18
- * The module imports no cordis and no `node:fs`: it is a table plus transitions, so it is testable offline.
19
- *
20
- * @module dsh-over-ssh/integration/transfer-tracker
21
- */
22
- import { type TransferProgress } from '../../domain/transfer/transfer.ts';
23
- /** Lifecycle of one tracked transfer. */
24
- export type TrackedTransferStatus = 'running' | 'done' | 'failed' | 'cancelled';
25
- /** One tracked transfer, as the UI sees it. */
26
- export interface TrackedTransfer {
27
- readonly id: string;
28
- readonly direction: 'upload' | 'download';
29
- readonly connectionId: string;
30
- /** Remote path (root-absolute). */
31
- readonly remotePath: string;
32
- /** Local path; for a download this is the destination, for an upload the source. */
33
- readonly localPath: string;
34
- readonly status: TrackedTransferStatus;
35
- readonly progress: TransferProgress;
36
- /** Message of the failure, when `status === 'failed'`. */
37
- readonly error?: string;
38
- /** Machine-readable code of the failure, when the host named one. */
39
- readonly errorCode?: string;
40
- readonly startedAt: number;
41
- /** When it stopped running; absent while it is still running. */
42
- readonly finishedAt?: number;
43
- }
44
- /** What a caller supplies to open a transfer. */
45
- export interface TransferStart {
46
- readonly direction: 'upload' | 'download';
47
- readonly connectionId: string;
48
- readonly remotePath: string;
49
- readonly localPath: string;
50
- readonly totalBytes: number;
51
- }
52
- /** The tracker's injected facts. */
53
- export interface TransferTrackerOptions {
54
- /** How many entries to retain, finished ones evicted oldest-first. At least 1. */
55
- readonly maxEntries: number;
56
- /** Injectable clock. */
57
- readonly now?: () => number;
58
- }
59
- /** The table. */
60
- export interface TransferTracker {
61
- /** Open a transfer and return its id. */
62
- start(input: TransferStart): string;
63
- /**
64
- * Record progress; unknown ids are ignored (a late callback after eviction must not throw).
65
- *
66
- * `totalBytes` is carried on every report because the tracker does **not** know the size up front: the plan is
67
- * computed inside the transfer service, so the first honest total arrives with the first progress callback.
68
- * Guessing a total at `start` would show 100% for a transfer that has barely begun.
69
- */
70
- progress(id: string, transferredBytes: number, totalBytes?: number): void;
71
- /** Mark it finished. */
72
- done(id: string, transferredBytes?: number): void;
73
- /** Mark it failed, with whatever code the host produced. */
74
- fail(id: string, error: string, errorCode?: string): void;
75
- /** Mark it cancelled (the user's own action, which is not a failure). */
76
- cancel(id: string): void;
77
- /**
78
- * Close a transfer from the error it threw, choosing between `cancelled` and `failed`.
79
- *
80
- * The policy lives here rather than at the call site because it is a **domain** rule, not plumbing: a
81
- * cancelled transfer is the user's own action, so listing it among failures would bury the real ones — and
82
- * the requirement's failure list is the thing that has to stay readable. It sat in the composition root
83
- * first, where no test could reach it (audit 0046).
84
- *
85
- * @param id - the transfer.
86
- * @param failure - the thrown value and the code the host produced, if any.
87
- */
88
- settle(id: string, failure: {
89
- readonly code?: string | undefined;
90
- readonly message: string;
91
- }): void;
92
- /** Everything retained, newest first. */
93
- list(): readonly TrackedTransfer[];
94
- /** One entry, if it is still retained. */
95
- get(id: string): TrackedTransfer | undefined;
96
- /** Drop every finished entry (the UI's "clear" button). */
97
- clearFinished(): number;
98
- }
99
- /**
100
- * Build a tracker.
101
- *
102
- * @param options - bounds and clock.
103
- * @returns the tracker.
104
- */
105
- export declare function createTransferTracker(options: TransferTrackerOptions): TransferTracker;
106
- //# sourceMappingURL=transfer-tracker.d.ts.map
@@ -1,44 +0,0 @@
1
- /**
2
- * Adapters that turn the plugin's routing + transports into the injected dependencies the transfer and
3
- * recycle-bin services expect.
4
- *
5
- * Two rules shape everything here:
6
- *
7
- * - **Remote work uses the real primitives.** Chunked reads go through `Transport.readFileRange` (verified on
8
- * a real host: exact window, no whole-file read) and positioned writes through `writeFileRange` (POSIX
9
- * `pwrite` semantics, shared by all three transports). Where a transport lacks the method the fallback is
10
- * written down instead of hidden.
11
- * - **Local work never borrows the remote path.** `node:fs` is opened with `position` arguments so a local
12
- * chunk does not read the whole file either; the recycle bin's local mutators are a separate object, so a
13
- * local target can never end up being "moved" by an ssh command.
14
- *
15
- * @module dsh-remote-workspace/integration/transfer-adapters
16
- */
17
- import type { RootRef } from '../domain/root.ts';
18
- import type { RoutedFileSystem } from '../app/routed-fs.ts';
19
- import type { Transport } from '../infra/transport/transport.ts';
20
- import type { RecycleBinServiceDeps } from '../app/recycle-bin-service.ts';
21
- import type { TransferDependencies } from './transfer-service.ts';
22
- /** What both adapters need from the plugin. */
23
- export interface WorldAdapterDeps {
24
- /** Path routing: turns a path in any root's spelling into `{root, backend, absolute}`. */
25
- readonly routed: RoutedFileSystem;
26
- /** The transport of one connection (the caller already owns the profile lookup). */
27
- readonly transportFor: (connectionId: string) => Promise<Transport>;
28
- /** Bin directory **inside one root** (same device, so the move stays a rename). */
29
- readonly binRootFor: (root: RootRef) => string;
30
- /** Chunk ceiling passed to the transfer service. */
31
- readonly chunkBytes: number;
32
- /** Upper bound for one text read (the index file). */
33
- readonly maxReadBytes: number;
34
- /** Clock, injected for tests. */
35
- readonly now?: () => number;
36
- }
37
- /** The transfer service's dependencies. */
38
- export declare function createTransferDeps(deps: WorldAdapterDeps): TransferDependencies;
39
- /** The recycle bin's dependencies: remote primitives plus an explicit local world. */
40
- export declare function createRecycleBinDeps(deps: WorldAdapterDeps & {
41
- readonly knownRoots: () => readonly RootRef[];
42
- readonly undoDepth: number;
43
- }): RecycleBinServiceDeps;
44
- //# sourceMappingURL=transfer-adapters.d.ts.map
@@ -1,164 +0,0 @@
1
- /**
2
- * The remote-file transfer seam: move one file in one direction, in bounded chunks, with progress.
3
- *
4
- * This module owns the *policy* half of a transfer — offsets, resume decisions, progress callbacks,
5
- * cancellation and failure classification — and none of the I/O. Every side effect arrives as an
6
- * injected dependency (`readLocal`, `writeRemote`, `readRemote`, `writeLocal`, `statLocal`,
7
- * `statRemote`, optional `sha256Local`, optional clock), so the whole flow can be exercised offline
8
- * against substitute I/O (AGENTS.md 红线 3), and the same code runs on a real host by wiring the real
9
- * implementations in [`src/index.ts`] (left to the plugin entry, which this change does not touch).
10
- *
11
- * Contract notes that callers and implementers both rely on:
12
- *
13
- * - **Memory is bounded by `chunkBytes`**: a chunk is read, written and dropped; the file is never
14
- * assembled in memory. A test asserts this by recording every `readLocal` request, not by claiming it.
15
- * - **`offset === undefined` means "replace the target's content with exactly these bytes"**;
16
- * `offset === n` means "place these bytes at byte n, extending the target". The first write of a
17
- * fresh transfer therefore carries no offset, and every later chunk carries its absolute offset.
18
- * - **Progress fires once per completed write** and never decreases: each snapshot is computed from
19
- * a running byte counter, and the clock is injected so rates are reproducible in tests.
20
- * - **Cancellation is reported, never swallowed**: an aborted transfer fails with `CANCELLED` and
21
- * details carrying the bytes that are known to have landed, how many chunks were written, and
22
- * whether the chunk in flight may have landed partially.
23
- * - **Failure is classified**: `details.kind` is the precise {@link TransferFailureKind}; the error
24
- * code stays inside the existing `SSH_DEV_ERROR_CODES` table (see `domain/transfer.ts`).
25
- *
26
- * @module dsh-remote-workspace/integration/transfer-service
27
- */
28
- import { type TransferDegradation, type TransferProgress } from '../domain/transfer.ts';
29
- import type { BackendStat } from '../app/backend.ts';
30
- import type { RemoteWriteOutcome } from '../infra/transport/transport.ts';
31
- /** Default cap on one read/write step; overridable per call and per service instance. */
32
- export declare const DEFAULT_TRANSFER_CHUNK_BYTES: number;
33
- /** One bounded source read. */
34
- export interface SourceReadOptions {
35
- /** Byte offset to start at. */
36
- readonly offset: number;
37
- /** Maximum bytes to return; a shorter answer means the source ended early. */
38
- readonly length: number;
39
- readonly signal?: AbortSignal;
40
- }
41
- /** One bounded remote read. */
42
- export interface RemoteReadOptions {
43
- /** Byte offset to start at; omitted means 0. */
44
- readonly offset?: number;
45
- /** Maximum bytes to return *from `offset`*. */
46
- readonly maxBytes: number;
47
- readonly signal?: AbortSignal;
48
- }
49
- /** One remote write. */
50
- export interface RemoteWriteOptions {
51
- /** `undefined` replaces the file's content; `n` places the bytes at byte `n`. */
52
- readonly offset?: number;
53
- /** Refuse the write unless the target's current content has this digest (optimistic guard). */
54
- readonly expectedSha256?: string;
55
- readonly signal?: AbortSignal;
56
- }
57
- /** One local write (the download side). */
58
- export interface LocalWriteOptions {
59
- /** `undefined` replaces the file's content; `n` places the bytes at byte `n`. */
60
- readonly offset?: number;
61
- }
62
- /** Everything a transfer needs from the outside world. */
63
- export interface TransferDependencies {
64
- /** Bounded local read. Must not return more than `length` bytes. */
65
- readonly readLocal: (path: string, options: SourceReadOptions) => Promise<Uint8Array>;
66
- /**
67
- * Remote write. `offset === undefined` replaces the target; `offset === n` writes at `n`.
68
- * Returning {@link RemoteWriteOutcome} is how a remote digest (if any) reaches the caller.
69
- */
70
- readonly writeRemote: (absolute: string, bytes: Uint8Array, options: RemoteWriteOptions) => Promise<RemoteWriteOutcome>;
71
- /**
72
- * Remote read, bounded by `maxBytes` and optionally starting at `offset`.
73
- *
74
- * The sketched Tier 1 transport takes only `maxBytes`; the optional `offset` is what makes a
75
- * chunked download possible, so an implementation that cannot honour it must say so rather than
76
- * silently returning the head of the file (a wrong answer is worse than a refused one).
77
- */
78
- readonly readRemote: (absolute: string, options: RemoteReadOptions) => Promise<Uint8Array>;
79
- /** Local write; same offset convention as {@link TransferDependencies.writeRemote}. */
80
- readonly writeLocal: (path: string, bytes: Uint8Array, options: LocalWriteOptions) => Promise<void>;
81
- /** Local metadata. Must report `exists: false` for a missing path instead of throwing. */
82
- readonly statLocal: (path: string) => Promise<BackendStat>;
83
- /** Remote metadata. Same `exists` rule as {@link TransferDependencies.statLocal}. */
84
- readonly statRemote: (absolute: string) => Promise<BackendStat>;
85
- /** Optional digest of a local file; when absent the result reports `sha256: null`. */
86
- readonly sha256Local?: (path: string) => Promise<string>;
87
- /**
88
- * Whether `writeRemote` may continue an existing partial remote file (`resume: true` requests).
89
- * Defaults to `false`: a requested resume then degrades to a full rewrite **and says so**.
90
- */
91
- readonly supportsResume?: boolean;
92
- /** Default per-chunk cap; a request may override it. */
93
- readonly chunkBytes?: number;
94
- /** Clock, injected so rate/remaining estimates are reproducible in tests. */
95
- readonly nowMs?: () => number;
96
- }
97
- /** Common request fields. */
98
- export interface TransferRequestBase {
99
- /** Connection the remote path belongs to; recorded in the result and in failures. */
100
- readonly connectionId: string;
101
- /** Absolute POSIX root the remote path must stay inside. */
102
- readonly root: string;
103
- /** Remote path relative to the root; `..` is folded and can never escape. */
104
- readonly remotePath: string;
105
- /** Per-chunk cap for this call; defaults to the service's `chunkBytes`. */
106
- readonly chunkBytes?: number;
107
- /** Keep bytes already present on the target when possible; defaults to `false`. */
108
- readonly resume?: boolean;
109
- readonly onProgress?: (progress: TransferProgress) => void;
110
- readonly signal?: AbortSignal;
111
- }
112
- /** Upload one local file to the remote root. */
113
- export interface UploadRequest extends TransferRequestBase {
114
- /** Local source file. */
115
- readonly localPath: string;
116
- /**
117
- * Digest the remote target must currently have, forwarded to the first `writeRemote` call as its
118
- * optimistic guard. A dependency that refuses the write surfaces as `TRANSFER_CONFLICT`.
119
- */
120
- readonly expectedSha256?: string;
121
- }
122
- /** Download one remote file into a local path. */
123
- export interface DownloadRequest extends TransferRequestBase {
124
- /** Local destination *file* path (its base name is validated for the host platform). */
125
- readonly localPath: string;
126
- }
127
- /** What one transfer did. */
128
- export interface TransferResult {
129
- readonly direction: 'upload' | 'download';
130
- readonly connectionId: string;
131
- readonly root: string;
132
- readonly localPath: string;
133
- /** Root-absolute remote path the transfer actually used (after `..` folding). */
134
- readonly remotePath: string;
135
- readonly totalBytes: number;
136
- /** Bytes this transfer wrote, excluding any prefix it resumed from. */
137
- readonly bytesTransferred: number;
138
- /** Writes performed by this transfer (0 for a resumed transfer with nothing left; 1 for an empty file). */
139
- readonly chunks: number;
140
- readonly resumed: boolean;
141
- /** Offset the transfer started at. */
142
- readonly startOffset: number;
143
- readonly durationMs: number;
144
- /**
145
- * Digest of the transferred content, or `null` when no digest was obtainable:
146
- * the remote's own digest for a single non-resumed write, else `sha256Local`'s answer.
147
- */
148
- readonly sha256: string | null;
149
- /** Why something was not done as asked (resume refused, digest unavailable); empty when clean. */
150
- readonly degradations: readonly TransferDegradation[];
151
- }
152
- /** The two operations this seam exposes. */
153
- export interface TransferService {
154
- upload(request: UploadRequest): Promise<TransferResult>;
155
- download(request: DownloadRequest): Promise<TransferResult>;
156
- }
157
- /**
158
- * Build the transfer service.
159
- *
160
- * @param dependencies - all local/remote I/O plus the optional clock, digest and resume capability.
161
- * @returns the upload/download operations; no state is kept between calls.
162
- */
163
- export declare function createTransferService(dependencies: TransferDependencies): TransferService;
164
- //# sourceMappingURL=transfer-service.d.ts.map