host-execution-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +330 -0
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/SECURITY.md +72 -0
- package/dist/access/docker-runtime.d.ts +38 -0
- package/dist/access/docker-runtime.js +61 -0
- package/dist/access/docker-runtime.js.map +1 -0
- package/dist/access/index.d.ts +110 -0
- package/dist/access/index.js +174 -0
- package/dist/access/index.js.map +1 -0
- package/dist/access/paradi-auth.d.ts +33 -0
- package/dist/access/paradi-auth.js +89 -0
- package/dist/access/paradi-auth.js.map +1 -0
- package/dist/access/paradi-transport.d.ts +10 -0
- package/dist/access/paradi-transport.js +39 -0
- package/dist/access/paradi-transport.js.map +1 -0
- package/dist/access/paradi-username.d.ts +5 -0
- package/dist/access/paradi-username.js +14 -0
- package/dist/access/paradi-username.js.map +1 -0
- package/dist/access/probe.d.ts +14 -0
- package/dist/access/probe.js +63 -0
- package/dist/access/probe.js.map +1 -0
- package/dist/access/session-pool.d.ts +25 -0
- package/dist/access/session-pool.js +46 -0
- package/dist/access/session-pool.js.map +1 -0
- package/dist/access/ssh-transport.d.ts +16 -0
- package/dist/access/ssh-transport.js +74 -0
- package/dist/access/ssh-transport.js.map +1 -0
- package/dist/access/types.d.ts +43 -0
- package/dist/access/types.js +21 -0
- package/dist/access/types.js.map +1 -0
- package/dist/config.d.ts +52 -0
- package/dist/config.js +179 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +4 -0
- package/dist/instructions.js +93 -0
- package/dist/instructions.js.map +1 -0
- package/dist/kubectl/runner.d.ts +32 -0
- package/dist/kubectl/runner.js +79 -0
- package/dist/kubectl/runner.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +24 -0
- package/dist/server.js.map +1 -0
- package/dist/ssh/access-client.d.ts +62 -0
- package/dist/ssh/access-client.js +470 -0
- package/dist/ssh/access-client.js.map +1 -0
- package/dist/ssh/access-errors.d.ts +53 -0
- package/dist/ssh/access-errors.js +180 -0
- package/dist/ssh/access-errors.js.map +1 -0
- package/dist/ssh/access-sftp.d.ts +14 -0
- package/dist/ssh/access-sftp.js +456 -0
- package/dist/ssh/access-sftp.js.map +1 -0
- package/dist/ssh/bastion-client.d.ts +60 -0
- package/dist/ssh/bastion-client.js +423 -0
- package/dist/ssh/bastion-client.js.map +1 -0
- package/dist/ssh/bastion-errors.d.ts +62 -0
- package/dist/ssh/bastion-errors.js +190 -0
- package/dist/ssh/bastion-errors.js.map +1 -0
- package/dist/ssh/hop1-sftp.d.ts +14 -0
- package/dist/ssh/hop1-sftp.js +437 -0
- package/dist/ssh/hop1-sftp.js.map +1 -0
- package/dist/tools/copy-job-schemas.d.ts +709 -0
- package/dist/tools/copy-job-schemas.js +48 -0
- package/dist/tools/copy-job-schemas.js.map +1 -0
- package/dist/tools/register.d.ts +14 -0
- package/dist/tools/register.js +619 -0
- package/dist/tools/register.js.map +1 -0
- package/dist/tools/remote-schemas.d.ts +879 -0
- package/dist/tools/remote-schemas.js +214 -0
- package/dist/tools/remote-schemas.js.map +1 -0
- package/dist/utils/copy-executor.d.ts +41 -0
- package/dist/utils/copy-executor.js +231 -0
- package/dist/utils/copy-executor.js.map +1 -0
- package/dist/utils/copy-job-manager.d.ts +34 -0
- package/dist/utils/copy-job-manager.js +400 -0
- package/dist/utils/copy-job-manager.js.map +1 -0
- package/dist/utils/copy-job-store.d.ts +18 -0
- package/dist/utils/copy-job-store.js +104 -0
- package/dist/utils/copy-job-store.js.map +1 -0
- package/dist/utils/copy-job-types.d.ts +133 -0
- package/dist/utils/copy-job-types.js +37 -0
- package/dist/utils/copy-job-types.js.map +1 -0
- package/dist/utils/copy-transfer.d.ts +59 -0
- package/dist/utils/copy-transfer.js +86 -0
- package/dist/utils/copy-transfer.js.map +1 -0
- package/dist/utils/remote-copy.d.ts +14 -0
- package/dist/utils/remote-copy.js +115 -0
- package/dist/utils/remote-copy.js.map +1 -0
- package/dist/utils/remote-executor.d.ts +15 -0
- package/dist/utils/remote-executor.js +34 -0
- package/dist/utils/remote-executor.js.map +1 -0
- package/dist/utils/remote-target.d.ts +22 -0
- package/dist/utils/remote-target.js +75 -0
- package/dist/utils/remote-target.js.map +1 -0
- package/dist/utils/result.d.ts +87 -0
- package/dist/utils/result.js +81 -0
- package/dist/utils/result.js.map +1 -0
- package/dist/utils/shell-quote.d.ts +22 -0
- package/dist/utils/shell-quote.js +55 -0
- package/dist/utils/shell-quote.js.map +1 -0
- package/dist/utils/timeout.d.ts +1 -0
- package/dist/utils/timeout.js +18 -0
- package/dist/utils/timeout.js.map +1 -0
- package/dist/utils/truncate.d.ts +5 -0
- package/dist/utils/truncate.js +12 -0
- package/dist/utils/truncate.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/docs/AGENT_GUIDE.md +161 -0
- package/docs/CONFIGURATION.md +130 -0
- package/docs/COPY_SPECIALIZED_TEST_CHECKLIST.md +9 -0
- package/docs/HOP1_E2E_CHECKLIST.md +128 -0
- package/docs/HOP1_E2E_RESULTS.json +647 -0
- package/docs/PARADI_ACCESS_PLAN.md +272 -0
- package/docs/REMOTE_COPY_JOB_API.md +92 -0
- package/docs/TODO.md +66 -0
- package/docs/USER_GUIDE.zh-CN.md +93 -0
- package/docs/clients/claude-desktop.json.example +12 -0
- package/docs/clients/cursor-npx.json.example +12 -0
- package/docs/clients/cursor.json.example +12 -0
- package/docs/clients/vscode.json.example +12 -0
- package/package.json +65 -0
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hop1 local ↔ accessClient transfers via ssh2-sftp-client (independent TCP).
|
|
3
|
+
* Directory = list + per-file put/get (not uploadDir/downloadDir).
|
|
4
|
+
*
|
|
5
|
+
* skipIfComplete gate strength = verify mode (no auto-upgrade to sha256).
|
|
6
|
+
* verify fail on skip → fallthrough rewrite (never throw-only).
|
|
7
|
+
*/
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import SftpClient from "ssh2-sftp-client";
|
|
11
|
+
import { resolveAccessSshIdentity, resolveSshAuthOptions } from "../config.js";
|
|
12
|
+
import { getPinnedParadiAuth, resolveParadiConnectParams, } from "../access/paradi-auth.js";
|
|
13
|
+
import { toAccessUnavailableError } from "./access-errors.js";
|
|
14
|
+
import { createProgressReporter, createTransferId, DEFAULT_CONNECTION_TIMEOUT_MS, DEFAULT_PROGRESS_INTERVAL_MS, resolveEffectiveVerify, sha256File, throwIfAborted, transferSkipFields, } from "../utils/copy-transfer.js";
|
|
15
|
+
function posixJoin(...parts) {
|
|
16
|
+
return parts
|
|
17
|
+
.join("/")
|
|
18
|
+
.replace(/\\/g, "/")
|
|
19
|
+
.replace(/\/+/g, "/")
|
|
20
|
+
.replace(/\/$/, "") || "/";
|
|
21
|
+
}
|
|
22
|
+
function isAbortError(error, signal) {
|
|
23
|
+
return signal?.aborted === true || (error instanceof Error && error.message === "Copy aborted");
|
|
24
|
+
}
|
|
25
|
+
async function walkLocalFiles(root) {
|
|
26
|
+
const out = [];
|
|
27
|
+
async function walk(abs, rel) {
|
|
28
|
+
const st = await fs.stat(abs);
|
|
29
|
+
if (st.isFile()) {
|
|
30
|
+
out.push({ localPath: abs, remotePath: rel, size: st.size });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!st.isDirectory()) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const names = await fs.readdir(abs);
|
|
37
|
+
for (const name of names) {
|
|
38
|
+
await walk(path.join(abs, name), rel ? `${rel}/${name}` : name);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
await walk(root, "");
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
async function walkRemoteFiles(sftp, root) {
|
|
45
|
+
const out = [];
|
|
46
|
+
async function walk(remoteAbs, rel) {
|
|
47
|
+
const list = await sftp.list(remoteAbs);
|
|
48
|
+
for (const item of list) {
|
|
49
|
+
const childRel = rel ? `${rel}/${item.name}` : item.name;
|
|
50
|
+
const childAbs = posixJoin(remoteAbs, item.name);
|
|
51
|
+
if (item.type === "d") {
|
|
52
|
+
await walk(childAbs, childRel);
|
|
53
|
+
}
|
|
54
|
+
else if (item.type === "-") {
|
|
55
|
+
out.push({ localPath: childRel, remotePath: childAbs, size: item.size });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
await walk(root, "");
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
async function connectSftp(config, connectionTimeoutMs) {
|
|
63
|
+
const auth = resolveSshAuthOptions(config);
|
|
64
|
+
const sftp = new SftpClient();
|
|
65
|
+
const connectOpts = {
|
|
66
|
+
readyTimeout: connectionTimeoutMs,
|
|
67
|
+
};
|
|
68
|
+
if (config.accessKind === "paradi-gateway") {
|
|
69
|
+
// Prefer process pin (set after first successful Access SSH). Fallback matches
|
|
70
|
+
// resolveAccessSshIdentity (compound override or slash).
|
|
71
|
+
const mode = getPinnedParadiAuth(config) ??
|
|
72
|
+
(config.accessParadiAuth === "compound" ? "compound" : "slash");
|
|
73
|
+
const params = resolveParadiConnectParams(config, mode);
|
|
74
|
+
connectOpts.host = params.host;
|
|
75
|
+
connectOpts.port = params.port;
|
|
76
|
+
connectOpts.username = params.username;
|
|
77
|
+
if (params.password) {
|
|
78
|
+
connectOpts.password = params.password;
|
|
79
|
+
}
|
|
80
|
+
else if (auth.password) {
|
|
81
|
+
connectOpts.password = auth.password;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const identity = resolveAccessSshIdentity(config);
|
|
86
|
+
connectOpts.host = identity.host;
|
|
87
|
+
connectOpts.port = identity.port;
|
|
88
|
+
connectOpts.username = identity.username;
|
|
89
|
+
if (auth.password) {
|
|
90
|
+
connectOpts.password = auth.password;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (auth.privateKey) {
|
|
94
|
+
connectOpts.privateKey = auth.privateKey;
|
|
95
|
+
}
|
|
96
|
+
if (auth.agent) {
|
|
97
|
+
connectOpts.agent = auth.agent;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await sftp.connect(connectOpts);
|
|
101
|
+
return sftp;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
const unavailable = toAccessUnavailableError(error, config.accessHost, config.accessPort, "connect");
|
|
105
|
+
throw unavailable ?? error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function safeEnd(sftp) {
|
|
109
|
+
if (!sftp) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
await sftp.end();
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// ignore
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function remoteFileSize(sftp, remotePath) {
|
|
120
|
+
try {
|
|
121
|
+
const st = await sftp.stat(remotePath);
|
|
122
|
+
return st.size;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function remoteIsDirectory(sftp, remotePath) {
|
|
129
|
+
try {
|
|
130
|
+
await sftp.list(remotePath);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function verifyFile(sftp, localPath, remotePath, expectedSize, verify, execSha256) {
|
|
138
|
+
if (verify === "none") {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const localStat = await fs.stat(localPath);
|
|
142
|
+
const remoteSize = await remoteFileSize(sftp, remotePath);
|
|
143
|
+
if (localStat.size !== expectedSize) {
|
|
144
|
+
throw new Error(`Local size mismatch: local=${localStat.size} expected=${expectedSize}`);
|
|
145
|
+
}
|
|
146
|
+
if (remoteSize !== expectedSize) {
|
|
147
|
+
throw new Error(`Remote size mismatch: remote=${remoteSize} expected=${expectedSize}`);
|
|
148
|
+
}
|
|
149
|
+
if (verify === "size+sha256") {
|
|
150
|
+
const [localHash, remoteHash] = await Promise.all([
|
|
151
|
+
sha256File(localPath),
|
|
152
|
+
execSha256(remotePath),
|
|
153
|
+
]);
|
|
154
|
+
if (localHash !== remoteHash) {
|
|
155
|
+
throw new Error(`sha256 mismatch: local=${localHash} remote=${remoteHash}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Transfer a local file or directory to/from accessClient over an independent SFTP connection.
|
|
161
|
+
*/
|
|
162
|
+
export async function transferLocalAccess(params, execSha256) {
|
|
163
|
+
const { direction, localPath, remotePath, config } = params;
|
|
164
|
+
const opts = params.options ?? {};
|
|
165
|
+
const transferId = opts.transferId ?? createTransferId();
|
|
166
|
+
const skipIfComplete = opts.skipIfComplete === true;
|
|
167
|
+
const verify = resolveEffectiveVerify(skipIfComplete, opts.verify);
|
|
168
|
+
const totalTimeoutMs = opts.totalTimeoutMs ?? config.defaultTimeoutMs;
|
|
169
|
+
const connectionTimeoutMs = opts.connectionTimeoutMs ?? DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
170
|
+
const progressIntervalMs = opts.progressIntervalMs ?? DEFAULT_PROGRESS_INTERVAL_MS;
|
|
171
|
+
const signal = opts.signal;
|
|
172
|
+
const sha = (p) => execSha256(p, totalTimeoutMs);
|
|
173
|
+
throwIfAborted(signal);
|
|
174
|
+
let sftp = null;
|
|
175
|
+
let abortHandler;
|
|
176
|
+
const run = async () => {
|
|
177
|
+
sftp = await connectSftp(config, connectionTimeoutMs);
|
|
178
|
+
throwIfAborted(signal);
|
|
179
|
+
abortHandler = () => {
|
|
180
|
+
void safeEnd(sftp);
|
|
181
|
+
};
|
|
182
|
+
if (signal) {
|
|
183
|
+
if (signal.aborted) {
|
|
184
|
+
throw new Error("Copy aborted");
|
|
185
|
+
}
|
|
186
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
187
|
+
}
|
|
188
|
+
const localStat = await fs.stat(localPath).catch(() => undefined);
|
|
189
|
+
if (direction === "upload") {
|
|
190
|
+
if (!localStat) {
|
|
191
|
+
throw new Error(`Local path not found: ${localPath}`);
|
|
192
|
+
}
|
|
193
|
+
if (localStat.isFile()) {
|
|
194
|
+
return uploadOneFile(sftp, localPath, remotePath, localStat.size);
|
|
195
|
+
}
|
|
196
|
+
if (localStat.isDirectory()) {
|
|
197
|
+
return uploadDirectory(sftp, localPath, remotePath);
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`Unsupported local path type: ${localPath}`);
|
|
200
|
+
}
|
|
201
|
+
const isDir = await remoteIsDirectory(sftp, remotePath).catch(() => false);
|
|
202
|
+
if (isDir) {
|
|
203
|
+
return downloadDirectory(sftp, remotePath, localPath);
|
|
204
|
+
}
|
|
205
|
+
const remoteSize = await remoteFileSize(sftp, remotePath);
|
|
206
|
+
if (remoteSize === undefined) {
|
|
207
|
+
throw new Error(`Remote path not found: ${remotePath}`);
|
|
208
|
+
}
|
|
209
|
+
return downloadOneFile(sftp, remotePath, localPath, remoteSize);
|
|
210
|
+
};
|
|
211
|
+
function resultBase(bytes, totalBytes, skippedBytes, usedFastPath) {
|
|
212
|
+
return {
|
|
213
|
+
bytes,
|
|
214
|
+
totalBytes,
|
|
215
|
+
...transferSkipFields(skippedBytes, verify),
|
|
216
|
+
transferId,
|
|
217
|
+
verified: verify !== "none",
|
|
218
|
+
usedFastPath,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
async function uploadOneFile(client, local, remote, size) {
|
|
222
|
+
const remoteDir = path.posix.dirname(remote.replace(/\\/g, "/"));
|
|
223
|
+
if (remoteDir && remoteDir !== ".") {
|
|
224
|
+
await client.mkdir(remoteDir, true);
|
|
225
|
+
}
|
|
226
|
+
if (skipIfComplete) {
|
|
227
|
+
try {
|
|
228
|
+
const existing = await remoteFileSize(client, remote);
|
|
229
|
+
if (existing === size) {
|
|
230
|
+
await verifyFile(client, local, remote, size, verify, sha);
|
|
231
|
+
opts.onProgress?.({
|
|
232
|
+
transferred: size,
|
|
233
|
+
total: size,
|
|
234
|
+
percent: 100,
|
|
235
|
+
skippedBytes: size,
|
|
236
|
+
});
|
|
237
|
+
return resultBase(size, size, size, false);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (isAbortError(error, signal)) {
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const reporter = createProgressReporter(progressIntervalMs, opts.onProgress, 0);
|
|
247
|
+
await client.fastPut(local, remote, {
|
|
248
|
+
step: (total_transferred, _chunk, total) => {
|
|
249
|
+
reporter.report(total_transferred, total);
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
reporter.flush(size, size);
|
|
253
|
+
await verifyFile(client, local, remote, size, verify, sha);
|
|
254
|
+
return resultBase(size, size, 0, true);
|
|
255
|
+
}
|
|
256
|
+
async function downloadOneFile(client, remote, local, size) {
|
|
257
|
+
await fs.mkdir(path.dirname(local), { recursive: true });
|
|
258
|
+
if (skipIfComplete) {
|
|
259
|
+
try {
|
|
260
|
+
const st = await fs.stat(local);
|
|
261
|
+
if (st.isFile() && st.size === size) {
|
|
262
|
+
await verifyFile(client, local, remote, size, verify, sha);
|
|
263
|
+
opts.onProgress?.({
|
|
264
|
+
transferred: size,
|
|
265
|
+
total: size,
|
|
266
|
+
percent: 100,
|
|
267
|
+
skippedBytes: size,
|
|
268
|
+
});
|
|
269
|
+
return resultBase(size, size, size, false);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
if (isAbortError(error, signal)) {
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (size === 0) {
|
|
279
|
+
await fs.writeFile(local, "");
|
|
280
|
+
return resultBase(0, 0, 0, false);
|
|
281
|
+
}
|
|
282
|
+
const reporter = createProgressReporter(progressIntervalMs, opts.onProgress, 0);
|
|
283
|
+
await client.fastGet(remote, local, {
|
|
284
|
+
step: (total_transferred, _chunk, total) => {
|
|
285
|
+
reporter.report(total_transferred, total);
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
reporter.flush(size, size);
|
|
289
|
+
await verifyFile(client, local, remote, size, verify, sha);
|
|
290
|
+
return resultBase(size, size, 0, true);
|
|
291
|
+
}
|
|
292
|
+
async function uploadDirectory(client, localRoot, remoteRoot) {
|
|
293
|
+
const files = await walkLocalFiles(localRoot);
|
|
294
|
+
const totalBytes = files.reduce((s, f) => s + f.size, 0);
|
|
295
|
+
await client.mkdir(remoteRoot.replace(/\\/g, "/"), true);
|
|
296
|
+
let transferred = 0;
|
|
297
|
+
let skippedBytes = 0;
|
|
298
|
+
const reporter = createProgressReporter(progressIntervalMs, opts.onProgress, 0);
|
|
299
|
+
for (const file of files) {
|
|
300
|
+
throwIfAborted(signal);
|
|
301
|
+
const remoteFile = posixJoin(remoteRoot, file.remotePath);
|
|
302
|
+
const remoteDir = path.posix.dirname(remoteFile);
|
|
303
|
+
await client.mkdir(remoteDir, true);
|
|
304
|
+
let skipped = false;
|
|
305
|
+
if (skipIfComplete) {
|
|
306
|
+
try {
|
|
307
|
+
const existing = await remoteFileSize(client, remoteFile);
|
|
308
|
+
if (existing === file.size) {
|
|
309
|
+
await verifyFile(client, file.localPath, remoteFile, file.size, verify, sha);
|
|
310
|
+
skipped = true;
|
|
311
|
+
skippedBytes += file.size;
|
|
312
|
+
transferred += file.size;
|
|
313
|
+
reporter.report(transferred, totalBytes);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
if (isAbortError(error, signal)) {
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (!skipped) {
|
|
323
|
+
await client.fastPut(file.localPath, remoteFile, {
|
|
324
|
+
step: (n, _c, fileTotal) => {
|
|
325
|
+
reporter.report(transferred + n, totalBytes);
|
|
326
|
+
void fileTotal;
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
transferred += file.size;
|
|
330
|
+
reporter.report(transferred, totalBytes);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
reporter.flush(transferred, totalBytes);
|
|
334
|
+
const remoteFiles = await walkRemoteFiles(client, remoteRoot.replace(/\\/g, "/"));
|
|
335
|
+
await verifyDirectoryTree(client, files, remoteFiles, "upload", verify, sha);
|
|
336
|
+
return resultBase(transferred, totalBytes, skippedBytes, skippedBytes < totalBytes);
|
|
337
|
+
}
|
|
338
|
+
async function downloadDirectory(client, remoteRoot, localRoot) {
|
|
339
|
+
const remoteFiles = await walkRemoteFiles(client, remoteRoot.replace(/\\/g, "/"));
|
|
340
|
+
const totalBytes = remoteFiles.reduce((s, f) => s + f.size, 0);
|
|
341
|
+
await fs.mkdir(localRoot, { recursive: true });
|
|
342
|
+
let transferred = 0;
|
|
343
|
+
let skippedBytes = 0;
|
|
344
|
+
const reporter = createProgressReporter(progressIntervalMs, opts.onProgress, 0);
|
|
345
|
+
const localFiles = [];
|
|
346
|
+
for (const file of remoteFiles) {
|
|
347
|
+
throwIfAborted(signal);
|
|
348
|
+
const rel = file.localPath.replace(/\\/g, "/");
|
|
349
|
+
const localFile = path.join(localRoot, rel.replace(/\//g, path.sep));
|
|
350
|
+
await fs.mkdir(path.dirname(localFile), { recursive: true });
|
|
351
|
+
let skipped = false;
|
|
352
|
+
if (skipIfComplete) {
|
|
353
|
+
try {
|
|
354
|
+
const st = await fs.stat(localFile);
|
|
355
|
+
if (st.isFile() && st.size === file.size) {
|
|
356
|
+
await verifyFile(client, localFile, file.remotePath, file.size, verify, sha);
|
|
357
|
+
skipped = true;
|
|
358
|
+
skippedBytes += file.size;
|
|
359
|
+
transferred += file.size;
|
|
360
|
+
localFiles.push({
|
|
361
|
+
localPath: localFile,
|
|
362
|
+
remotePath: rel,
|
|
363
|
+
size: file.size,
|
|
364
|
+
});
|
|
365
|
+
reporter.report(transferred, totalBytes);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
if (isAbortError(error, signal)) {
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (!skipped) {
|
|
375
|
+
await client.fastGet(file.remotePath, localFile, {
|
|
376
|
+
step: (n) => {
|
|
377
|
+
reporter.report(transferred + n, totalBytes);
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
transferred += file.size;
|
|
381
|
+
localFiles.push({
|
|
382
|
+
localPath: localFile,
|
|
383
|
+
remotePath: rel,
|
|
384
|
+
size: file.size,
|
|
385
|
+
});
|
|
386
|
+
reporter.report(transferred, totalBytes);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
reporter.flush(transferred, totalBytes);
|
|
390
|
+
await verifyDirectoryTree(client, localFiles, remoteFiles, "download", verify, sha);
|
|
391
|
+
return resultBase(transferred, totalBytes, skippedBytes, skippedBytes < totalBytes);
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
const result = await Promise.race([
|
|
395
|
+
run(),
|
|
396
|
+
new Promise((_, reject) => {
|
|
397
|
+
const t = setTimeout(() => {
|
|
398
|
+
reject(new Error(`Hop1 total timeout after ${totalTimeoutMs}ms`));
|
|
399
|
+
}, totalTimeoutMs);
|
|
400
|
+
t.unref?.();
|
|
401
|
+
}),
|
|
402
|
+
]);
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
407
|
+
if (/total timeout/i.test(msg)) {
|
|
408
|
+
const timeoutErr = new Error(msg);
|
|
409
|
+
timeoutErr.code = "TIMEOUT";
|
|
410
|
+
throw timeoutErr;
|
|
411
|
+
}
|
|
412
|
+
throw error;
|
|
413
|
+
}
|
|
414
|
+
finally {
|
|
415
|
+
if (signal && abortHandler) {
|
|
416
|
+
signal.removeEventListener("abort", abortHandler);
|
|
417
|
+
}
|
|
418
|
+
await safeEnd(sftp);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Path-aligned directory verify.
|
|
423
|
+
* upload localFiles: remotePath=rel, localPath=abs
|
|
424
|
+
* download localFiles: remotePath=rel, localPath=abs
|
|
425
|
+
* remoteFiles: localPath=rel, remotePath=abs
|
|
426
|
+
*/
|
|
427
|
+
async function verifyDirectoryTree(sftp, localFiles, remoteFiles, _mode, verify, execSha256) {
|
|
428
|
+
if (verify === "none") {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
const remoteByRel = new Map(remoteFiles.map((f) => [f.localPath.replace(/\\/g, "/"), f]));
|
|
432
|
+
const localBytes = localFiles.reduce((s, f) => s + f.size, 0);
|
|
433
|
+
const remoteBytes = remoteFiles.reduce((s, f) => s + f.size, 0);
|
|
434
|
+
if (localFiles.length !== remoteFiles.length || localBytes !== remoteBytes) {
|
|
435
|
+
throw new Error(`Directory verify failed: local files=${localFiles.length} bytes=${localBytes} ` +
|
|
436
|
+
`remote files=${remoteFiles.length} bytes=${remoteBytes}`);
|
|
437
|
+
}
|
|
438
|
+
for (const lf of localFiles) {
|
|
439
|
+
const rel = lf.remotePath.replace(/\\/g, "/");
|
|
440
|
+
const rf = remoteByRel.get(rel);
|
|
441
|
+
if (!rf || rf.size !== lf.size) {
|
|
442
|
+
throw new Error(`Directory verify path/size mismatch for ${rel}`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (verify === "size+sha256") {
|
|
446
|
+
for (const lf of localFiles) {
|
|
447
|
+
const rel = lf.remotePath.replace(/\\/g, "/");
|
|
448
|
+
const rf = remoteByRel.get(rel);
|
|
449
|
+
if (!rf) {
|
|
450
|
+
throw new Error(`Directory verify missing remote for ${rel}`);
|
|
451
|
+
}
|
|
452
|
+
await verifyFile(sftp, lf.localPath, rf.remotePath, lf.size, "size+sha256", execSha256);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
//# sourceMappingURL=access-sftp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-sftp.js","sourceRoot":"","sources":["../../src/ssh/access-sftp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AppConfig } from "../config.js";
|
|
2
|
+
import { type SftpCopyOptions, type SftpTransferResult } from "../utils/copy-transfer.js";
|
|
3
|
+
import { type AccessCheckResult } from "./bastion-errors.js";
|
|
4
|
+
export interface ExecOutput {
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
exitCode: number;
|
|
8
|
+
durationMs: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class BastionClient {
|
|
11
|
+
private client;
|
|
12
|
+
private connecting;
|
|
13
|
+
/** Serializes ensureBastionReady / check cache updates. */
|
|
14
|
+
private gate;
|
|
15
|
+
private readonly config;
|
|
16
|
+
private readyUntil;
|
|
17
|
+
private unavailableUntil;
|
|
18
|
+
private lastUnavailable;
|
|
19
|
+
constructor(config: AppConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Ensure bastion is reachable (TTL-cached). Uses an ephemeral SSH probe ?
|
|
22
|
+
* never disconnects an in-flight shared exec session on success.
|
|
23
|
+
*/
|
|
24
|
+
ensureBastionReady(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Short-timeout Local to ACCESS probe (ephemeral client; <=10s worst case).
|
|
27
|
+
* Respects negative TTL (returns cached failure). Does not sever shared exec SSH.
|
|
28
|
+
*/
|
|
29
|
+
check(): Promise<AccessCheckResult>;
|
|
30
|
+
exec(command: string, timeoutMs?: number, cwd?: string, signal?: AbortSignal): Promise<ExecOutput>;
|
|
31
|
+
disconnect(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Upload local path (file or directory) ? bastion via independent Hop1 SFTP.
|
|
34
|
+
* Transfer-phase errors are not reclassified into ACCESS_UNAVAILABLE.
|
|
35
|
+
*/
|
|
36
|
+
uploadPath(localPath: string, remotePath: string, options?: SftpCopyOptions): Promise<SftpTransferResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Download bastion path (file or directory) ? local via independent Hop1 SFTP.
|
|
39
|
+
*/
|
|
40
|
+
downloadPath(remotePath: string, localPath: string, options?: SftpCopyOptions): Promise<SftpTransferResult>;
|
|
41
|
+
private withGate;
|
|
42
|
+
private markReady;
|
|
43
|
+
/**
|
|
44
|
+
* Record a connect-phase failure. Negative TTL only for classified causes
|
|
45
|
+
* (not UNKNOWN), so transient unknowns are not blackholed for 15s.
|
|
46
|
+
*/
|
|
47
|
+
private markConnectUnavailable;
|
|
48
|
+
/** Ephemeral SSH + shell probe; never assigns or disconnects `this.client`. */
|
|
49
|
+
private probeEphemeral;
|
|
50
|
+
private remoteSha256;
|
|
51
|
+
private ensureConnected;
|
|
52
|
+
private ensureConnectedUnlocked;
|
|
53
|
+
private requireClient;
|
|
54
|
+
/**
|
|
55
|
+
* Open a dedicated ssh2 Client with readyTimeout + hard deadline
|
|
56
|
+
* (covers TCP blackhole where ssh2 readyTimeout alone is insufficient).
|
|
57
|
+
*/
|
|
58
|
+
private openSshClient;
|
|
59
|
+
private execOnClient;
|
|
60
|
+
}
|