@minato-aqukin/autodl-cli 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -6
- package/README.zh-CN.md +64 -5
- package/dist/{app-4PY7NE53.js → app-V5GCG3MC.js} +2081 -412
- package/dist/chunk-2E2Y5GFH.js +1704 -0
- package/dist/{chunk-6QR4ZYQR.js → chunk-GHJVQKKC.js} +78 -32
- package/dist/{chunk-LHDSN4DL.js → chunk-JOOIUQLJ.js} +10 -4
- package/dist/{chunk-5RZ4Q7T4.js → chunk-MWYYK755.js} +4 -4
- package/dist/{chunk-NBWWTYSL.js → chunk-VEDMEYCW.js} +2 -2
- package/dist/{chunk-CWCG3MOC.js → chunk-WN2CXPD2.js} +7 -2
- package/dist/cli.js +319 -25
- package/dist/index.d.ts +11 -2
- package/dist/index.js +6 -4
- package/dist/{tui-LEZV34YH.js → tui-ZT5ZBVSQ.js} +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,13 @@ import {
|
|
|
13
13
|
saveImage,
|
|
14
14
|
startMcpServer,
|
|
15
15
|
watchIdle
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MWYYK755.js";
|
|
17
|
+
import {
|
|
18
|
+
FileWorkspace,
|
|
19
|
+
TransferQueue,
|
|
20
|
+
connectTerminal,
|
|
21
|
+
identityFromToken
|
|
22
|
+
} from "./chunk-2E2Y5GFH.js";
|
|
17
23
|
import {
|
|
18
24
|
BASE_IMAGES,
|
|
19
25
|
DEFAULT_BASE_IMAGE,
|
|
@@ -29,7 +35,7 @@ import {
|
|
|
29
35
|
parseCudaVersion,
|
|
30
36
|
resolveGpuSpec,
|
|
31
37
|
resolveRegion
|
|
32
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-WN2CXPD2.js";
|
|
33
39
|
import {
|
|
34
40
|
action,
|
|
35
41
|
bareAction,
|
|
@@ -37,10 +43,11 @@ import {
|
|
|
37
43
|
globalsOf,
|
|
38
44
|
lazyAction,
|
|
39
45
|
registerTuiCommand
|
|
40
|
-
} from "./chunk-
|
|
41
|
-
import "./chunk-
|
|
46
|
+
} from "./chunk-JOOIUQLJ.js";
|
|
47
|
+
import "./chunk-VEDMEYCW.js";
|
|
42
48
|
import {
|
|
43
49
|
AutoDLClient,
|
|
50
|
+
DEFAULT_BASE_URL,
|
|
44
51
|
ExitCode,
|
|
45
52
|
UsageError,
|
|
46
53
|
armTTLOverSSH,
|
|
@@ -76,7 +83,9 @@ import {
|
|
|
76
83
|
recordTTL,
|
|
77
84
|
redactToken,
|
|
78
85
|
releaseInstance,
|
|
86
|
+
resolveBaseUrl,
|
|
79
87
|
resolveLang,
|
|
88
|
+
resolveToken,
|
|
80
89
|
setLang,
|
|
81
90
|
success,
|
|
82
91
|
sweepExpired,
|
|
@@ -87,7 +96,7 @@ import {
|
|
|
87
96
|
waitForRunning,
|
|
88
97
|
waitForShutdown,
|
|
89
98
|
warn
|
|
90
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-GHJVQKKC.js";
|
|
91
100
|
|
|
92
101
|
// src/cli.ts
|
|
93
102
|
import { Command } from "commander";
|
|
@@ -356,6 +365,250 @@ function registerDeployCommand(program) {
|
|
|
356
365
|
);
|
|
357
366
|
}
|
|
358
367
|
|
|
368
|
+
// src/commands/files.ts
|
|
369
|
+
import { createHash } from "crypto";
|
|
370
|
+
function queueNamespace(token, baseUrl) {
|
|
371
|
+
const identity = identityFromToken(token);
|
|
372
|
+
const account = [identity.tenant, identity.uid ?? identity.uuid ?? token];
|
|
373
|
+
return createHash("sha256").update(JSON.stringify([(baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""), account])).digest("hex");
|
|
374
|
+
}
|
|
375
|
+
function queueFor(context, command) {
|
|
376
|
+
const globals = globalsOf(command);
|
|
377
|
+
const resolved = resolveToken(globals.token);
|
|
378
|
+
const baseUrl = resolveBaseUrl(globals.baseUrl);
|
|
379
|
+
const queue = new TransferQueue(context.client, queueNamespace(resolved.token, baseUrl));
|
|
380
|
+
let released = false;
|
|
381
|
+
return {
|
|
382
|
+
queue,
|
|
383
|
+
release: async () => {
|
|
384
|
+
if (!released) {
|
|
385
|
+
released = true;
|
|
386
|
+
await queue.dispose();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
async function withWorkspace(context, id, fn) {
|
|
392
|
+
const workspace = new FileWorkspace(context.client, id);
|
|
393
|
+
try {
|
|
394
|
+
return await fn(workspace);
|
|
395
|
+
} finally {
|
|
396
|
+
workspace.dispose();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function ensureStarted(context, id, start) {
|
|
400
|
+
if (start) await getCredentials(context.client, id, { autoStart: true });
|
|
401
|
+
}
|
|
402
|
+
var STATE_LABEL = {
|
|
403
|
+
queued: "\u6392\u961F",
|
|
404
|
+
running: "\u4F20\u8F93\u4E2D",
|
|
405
|
+
conflict: "\u5F85\u786E\u8BA4",
|
|
406
|
+
paused: "\u5DF2\u6682\u505C",
|
|
407
|
+
completed: "\u5B8C\u6210",
|
|
408
|
+
cancelled: "\u5DF2\u53D6\u6D88"
|
|
409
|
+
};
|
|
410
|
+
function registerFileCommands(program) {
|
|
411
|
+
const files = program.command("files").description("\u6D4F\u89C8\u4E0E\u7BA1\u7406\u5B9E\u4F8B\u6587\u4EF6\uFF08SFTP\uFF0C\u8FDE\u63A5\u590D\u7528\uFF09");
|
|
412
|
+
files.command("ls <id> [remote]").description("\u5217\u51FA\u8FDC\u7A0B\u76EE\u5F55\uFF08\u5F53\u524D\u5C42\uFF0C\u65E0\u9012\u5F52\uFF09").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).action(
|
|
413
|
+
action(
|
|
414
|
+
async (context, id, remote, options) => {
|
|
415
|
+
const dir = remote ?? "/root/autodl-tmp";
|
|
416
|
+
const entries = await withWorkspace(context, id, async (workspace) => {
|
|
417
|
+
await ensureStarted(context, id, options.start);
|
|
418
|
+
return workspace.list("remote", dir);
|
|
419
|
+
});
|
|
420
|
+
emit({ uuid: id, path: dir, entries }, () => {
|
|
421
|
+
for (const entry of entries) {
|
|
422
|
+
printKeyValues([[entry.name, `${entry.kind} ${entry.size} ${entry.path}`]]);
|
|
423
|
+
}
|
|
424
|
+
if (entries.length === 0) note("\u7A7A\u76EE\u5F55");
|
|
425
|
+
});
|
|
426
|
+
return 0;
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
files.command("mkdir <id> <remote>").description("\u5728\u5B9E\u4F8B\u4E0A\u521B\u5EFA\u76EE\u5F55").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).action(
|
|
431
|
+
action(async (context, id, remote, options) => {
|
|
432
|
+
await withWorkspace(context, id, async (workspace) => {
|
|
433
|
+
await ensureStarted(context, id, options.start);
|
|
434
|
+
return workspace.mkdir("remote", remote);
|
|
435
|
+
});
|
|
436
|
+
emit({ uuid: id, path: remote, created: true }, () => success(`\u5DF2\u521B\u5EFA ${remote}`));
|
|
437
|
+
return 0;
|
|
438
|
+
})
|
|
439
|
+
);
|
|
440
|
+
files.command("mv <id> <from> <to>").description("\u5728\u5B9E\u4F8B\u4E0A\u6539\u540D\u6216\u79FB\u52A8\uFF08\u4E0D\u8986\u76D6\u5DF2\u5B58\u5728\u76EE\u6807\uFF09").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).action(
|
|
441
|
+
action(async (context, id, from, to, options) => {
|
|
442
|
+
await withWorkspace(context, id, async (workspace) => {
|
|
443
|
+
await ensureStarted(context, id, options.start);
|
|
444
|
+
return workspace.rename("remote", from, to);
|
|
445
|
+
});
|
|
446
|
+
emit({ uuid: id, from, to, moved: true }, () => success(`\u5DF2\u79FB\u52A8 ${from} \u2192 ${to}`));
|
|
447
|
+
return 0;
|
|
448
|
+
})
|
|
449
|
+
);
|
|
450
|
+
files.command("rm <id> <remote>").description("\u5220\u9664\u5B9E\u4F8B\u6587\u4EF6\u6216\u76EE\u5F55\uFF08\u9012\u5F52\uFF0C\u4E0D\u53EF\u6062\u590D\uFF09").option("--yes", "\u786E\u8BA4\u5220\u9664", false).option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).action(
|
|
451
|
+
action(
|
|
452
|
+
async (context, id, remote, options) => {
|
|
453
|
+
const confirmed = await confirmDestructive(
|
|
454
|
+
`\u6C38\u4E45\u5220\u9664\u5B9E\u4F8B\u6587\u4EF6 ${id}:${remote}`,
|
|
455
|
+
options.yes
|
|
456
|
+
);
|
|
457
|
+
if (!confirmed) {
|
|
458
|
+
emit({ uuid: id, path: remote, removed: false, cancelled: true }, () => note("\u5DF2\u53D6\u6D88"));
|
|
459
|
+
return 0;
|
|
460
|
+
}
|
|
461
|
+
await withWorkspace(context, id, async (workspace) => {
|
|
462
|
+
await ensureStarted(context, id, options.start);
|
|
463
|
+
return workspace.remove("remote", remote);
|
|
464
|
+
});
|
|
465
|
+
emit({ uuid: id, path: remote, removed: true }, () => success(`\u5DF2\u5220\u9664 ${remote}`));
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
);
|
|
470
|
+
const queue = program.command("queue").description("\u4E32\u884C\u4F20\u8F93\u961F\u5217\uFF08\u4E0E\u770B\u677F\u5171\u7528\u540C\u4E00\u961F\u5217\uFF09");
|
|
471
|
+
queue.command("add <id> <source> <destination>").description("\u52A0\u5165\u4E0A\u4F20/\u4E0B\u8F7D\u4EFB\u52A1\uFF08\u6765\u6E90\u5728\u672C\u5730\u5219\u4E0A\u4F20\uFF0C\u5728\u8FDC\u7AEF\u9700 --download\uFF09").option("--download", "\u4ECE\u5B9E\u4F8B\u4E0B\u8F7D\u5230\u672C\u5730", false).option("--sync", "\u5355\u5411\u589E\u91CF\u540C\u6B65\uFF0C\u4E0D\u5220\u9664\u76EE\u6807\u72EC\u6709\u6587\u4EF6", false).option("--checksum", "SHA-256 \u5185\u5BB9\u6821\u9A8C", false).option("--wait", "\u7B49\u5F85\u4EFB\u52A1\u5B8C\u6210", false).action(
|
|
472
|
+
action(
|
|
473
|
+
async (context, id, source, destination, options, command) => {
|
|
474
|
+
const { queue: transferQueue, release } = queueFor(context, command);
|
|
475
|
+
try {
|
|
476
|
+
const jobId = transferQueue.enqueue({
|
|
477
|
+
uuid: id,
|
|
478
|
+
direction: options.download ? "download" : "upload",
|
|
479
|
+
sources: [source],
|
|
480
|
+
destination,
|
|
481
|
+
sync: options.sync,
|
|
482
|
+
checksum: options.checksum
|
|
483
|
+
});
|
|
484
|
+
if (options.wait) {
|
|
485
|
+
const done = await waitForJob(transferQueue, jobId);
|
|
486
|
+
emit(
|
|
487
|
+
{ jobId, ...done },
|
|
488
|
+
() => success(`\u4EFB\u52A1 ${jobId}\uFF1A${STATE_LABEL[done.state] ?? done.state}`)
|
|
489
|
+
);
|
|
490
|
+
return 0;
|
|
491
|
+
}
|
|
492
|
+
emit({ jobId, uuid: id }, () => success(`\u5DF2\u52A0\u5165\u961F\u5217\uFF1A${jobId}`));
|
|
493
|
+
return 0;
|
|
494
|
+
} finally {
|
|
495
|
+
await release();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
);
|
|
500
|
+
queue.command("ls").description("\u5217\u51FA\u5F53\u524D\u8D26\u53F7\u7684\u4F20\u8F93\u4EFB\u52A1").action(
|
|
501
|
+
action(async (context, _options, command) => {
|
|
502
|
+
const { queue: transferQueue, release } = queueFor(context, command);
|
|
503
|
+
try {
|
|
504
|
+
const jobs = transferQueue.snapshot().map((job) => ({
|
|
505
|
+
id: job.request.id,
|
|
506
|
+
uuid: job.request.uuid,
|
|
507
|
+
direction: job.request.direction,
|
|
508
|
+
sources: job.request.sources,
|
|
509
|
+
destination: job.request.destination,
|
|
510
|
+
sync: job.request.sync,
|
|
511
|
+
checksum: job.request.checksum,
|
|
512
|
+
state: job.state,
|
|
513
|
+
...job.error !== void 0 ? { error: job.error } : {},
|
|
514
|
+
...job.result ? { result: job.result } : {}
|
|
515
|
+
}));
|
|
516
|
+
emit({ jobs }, () => {
|
|
517
|
+
if (jobs.length === 0) {
|
|
518
|
+
note("\u961F\u5217\u4E3A\u7A7A");
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
for (const job of jobs) {
|
|
522
|
+
printKeyValues([
|
|
523
|
+
[
|
|
524
|
+
job.id,
|
|
525
|
+
`${job.direction} ${STATE_LABEL[job.state] ?? job.state} \u2192 ${job.destination}`
|
|
526
|
+
]
|
|
527
|
+
]);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
return 0;
|
|
531
|
+
} finally {
|
|
532
|
+
await release();
|
|
533
|
+
}
|
|
534
|
+
})
|
|
535
|
+
);
|
|
536
|
+
queue.command("resume <jobId>").description("\u6062\u590D\u5DF2\u6682\u505C/\u5DF2\u53D6\u6D88\u7684\u4EFB\u52A1\uFF08\u9700\u5B9E\u4F8B\u8FD0\u884C\u4E2D\uFF0C\u4E0D\u81EA\u52A8\u5F00\u673A\uFF09").action(
|
|
537
|
+
action(async (context, jobId, _options, command) => {
|
|
538
|
+
const { queue: transferQueue, release } = queueFor(context, command);
|
|
539
|
+
try {
|
|
540
|
+
transferQueue.resume(jobId);
|
|
541
|
+
emit({ jobId, resumed: true }, () => success(`\u5DF2\u6062\u590D ${jobId}`));
|
|
542
|
+
return 0;
|
|
543
|
+
} finally {
|
|
544
|
+
await release();
|
|
545
|
+
}
|
|
546
|
+
})
|
|
547
|
+
);
|
|
548
|
+
queue.command("cancel <jobId>").description("\u53D6\u6D88\u6392\u961F/\u4F20\u8F93\u4E2D\u7684\u4EFB\u52A1\uFF08\u4FDD\u7559\u7EED\u4F20\u6570\u636E\uFF09").action(
|
|
549
|
+
action(async (context, jobId, _options, command) => {
|
|
550
|
+
const { queue: transferQueue, release } = queueFor(context, command);
|
|
551
|
+
try {
|
|
552
|
+
transferQueue.cancel(jobId);
|
|
553
|
+
emit({ jobId, cancelled: true }, () => success(`\u5DF2\u53D6\u6D88 ${jobId}`));
|
|
554
|
+
return 0;
|
|
555
|
+
} finally {
|
|
556
|
+
await release();
|
|
557
|
+
}
|
|
558
|
+
})
|
|
559
|
+
);
|
|
560
|
+
queue.command("resolve <jobId> <choice>").description("\u5904\u7406\u4EFB\u52A1\u7684\u6587\u4EF6\u51B2\u7A81\uFF1Aoverwrite / skip / keep-both").option("--all", "\u5E94\u7528\u4E8E\u672C\u4EFB\u52A1\u5176\u4F59\u51B2\u7A81", false).action(
|
|
561
|
+
action(
|
|
562
|
+
async (context, jobId, choice, options, command) => {
|
|
563
|
+
if (choice !== "overwrite" && choice !== "skip" && choice !== "keep-both") {
|
|
564
|
+
throw new UsageError("choice \u5FC5\u987B\u662F overwrite / skip / keep-both");
|
|
565
|
+
}
|
|
566
|
+
const { queue: transferQueue, release } = queueFor(context, command);
|
|
567
|
+
try {
|
|
568
|
+
transferQueue.resolveConflict(jobId, { choice, applyToAll: options.all });
|
|
569
|
+
emit(
|
|
570
|
+
{ jobId, choice, applyToAll: options.all },
|
|
571
|
+
() => success(`\u5DF2\u5904\u7406\u51B2\u7A81\uFF1A${choice}`)
|
|
572
|
+
);
|
|
573
|
+
return 0;
|
|
574
|
+
} finally {
|
|
575
|
+
await release();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
)
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
async function waitForJob(queue, jobId) {
|
|
582
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
583
|
+
const done = (state, error) => resolve(error === void 0 ? { state } : { state, error });
|
|
584
|
+
const check = () => {
|
|
585
|
+
const job = queue.snapshot().find((entry) => entry.request.id === jobId);
|
|
586
|
+
if (!job) {
|
|
587
|
+
done("missing", "\u4EFB\u52A1\u4E0D\u5B58\u5728");
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
if (job.state === "completed" || job.state === "cancelled") {
|
|
591
|
+
done(job.state, job.error);
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
if (job.state === "paused") {
|
|
595
|
+
done(job.state, job.error ?? "\u4EFB\u52A1\u5DF2\u6682\u505C");
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
if (job.state === "conflict" && isJson()) {
|
|
599
|
+
done(job.state, job.error ?? "\u4EFB\u52A1\u7B49\u5F85\u51B2\u7A81\u786E\u8BA4\uFF08\u975E\u4EA4\u4E92\u6A21\u5F0F\u65E0\u6CD5\u56DE\u7B54\uFF09");
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
return false;
|
|
603
|
+
};
|
|
604
|
+
if (check()) return promise;
|
|
605
|
+
const unsubscribe = queue.subscribe(() => {
|
|
606
|
+
if (check()) unsubscribe();
|
|
607
|
+
});
|
|
608
|
+
if (check()) unsubscribe();
|
|
609
|
+
return promise;
|
|
610
|
+
}
|
|
611
|
+
|
|
359
612
|
// src/commands/guard.ts
|
|
360
613
|
import pc4 from "picocolors";
|
|
361
614
|
function registerGuardCommands(program) {
|
|
@@ -803,24 +1056,37 @@ function registerRunCommand(program) {
|
|
|
803
1056
|
// src/commands/ssh.ts
|
|
804
1057
|
import pc6 from "picocolors";
|
|
805
1058
|
function registerSSHCommands(program) {
|
|
806
|
-
program.command("ssh <id>").description("\u4EA4\u4E92\u5F0F SSH \u767B\u5F55\u5B9E\u4F8B").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).option("--print", "\u53EA\u6253\u5370\u8FDE\u63A5\u4FE1\u606F\uFF0C\u4E0D\u5EFA\u7ACB\u8FDE\u63A5", false).allowUnknownOption().action(
|
|
807
|
-
action(
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
[
|
|
813
|
-
|
|
814
|
-
|
|
1059
|
+
program.command("ssh <id>").description("\u4EA4\u4E92\u5F0F SSH \u767B\u5F55\u5B9E\u4F8B").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).option("--print", "\u53EA\u6253\u5370\u8FDE\u63A5\u4FE1\u606F\uFF0C\u4E0D\u5EFA\u7ACB\u8FDE\u63A5", false).option("--auto-auth", "\u4F7F\u7528\u5B9E\u4F8B\u5BC6\u7801\u81EA\u52A8\u8BA4\u8BC1\uFF08\u72EC\u5360\u5F53\u524D\u7EC8\u7AEF\uFF0C\u4E0D\u8BFB\u53D6 OpenSSH \u914D\u7F6E\uFF09", false).allowUnknownOption().action(
|
|
1060
|
+
action(
|
|
1061
|
+
async (context, id, options, command) => {
|
|
1062
|
+
if (options.print) {
|
|
1063
|
+
const creds = await getCredentials(context.client, id, { autoStart: options.start });
|
|
1064
|
+
emit(creds, () => {
|
|
1065
|
+
printKeyValues([
|
|
1066
|
+
["\u547D\u4EE4", `ssh -p ${creds.port} ${creds.user}@${creds.host}`],
|
|
1067
|
+
["\u5BC6\u7801", creds.password]
|
|
1068
|
+
]);
|
|
1069
|
+
});
|
|
1070
|
+
return 0;
|
|
1071
|
+
}
|
|
1072
|
+
const extraArgs = command.args.slice(1);
|
|
1073
|
+
if (options.autoAuth) {
|
|
1074
|
+
if (isJson() || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1075
|
+
throw new UsageError("--auto-auth \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\uFF0C\u4E0D\u652F\u6301 --json");
|
|
1076
|
+
}
|
|
1077
|
+
if (extraArgs.length) {
|
|
1078
|
+
throw new UsageError(
|
|
1079
|
+
"--auto-auth \u4E0D\u63A5\u53D7 OpenSSH \u53C2\u6570\uFF1B\u7AEF\u53E3\u8F6C\u53D1\u7B49\u573A\u666F\u8BF7\u4F7F\u7528\u666E\u901A autodl ssh"
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
return connectTerminal(context.client, id, { autoStart: options.start });
|
|
1083
|
+
}
|
|
1084
|
+
return connectInteractive(context.client, id, {
|
|
1085
|
+
autoStart: options.start,
|
|
1086
|
+
extraArgs
|
|
815
1087
|
});
|
|
816
|
-
return 0;
|
|
817
1088
|
}
|
|
818
|
-
|
|
819
|
-
return connectInteractive(context.client, id, {
|
|
820
|
-
autoStart: options.start,
|
|
821
|
-
extraArgs
|
|
822
|
-
});
|
|
823
|
-
})
|
|
1089
|
+
)
|
|
824
1090
|
);
|
|
825
1091
|
program.command("exec <id> <command...>").description("\u5728\u5B9E\u4F8B\u4E0A\u6267\u884C\u547D\u4EE4\uFF0C\u6D41\u5F0F\u56DE\u4F20\u8F93\u51FA\uFF0C\u900F\u4F20\u8FDC\u7A0B\u9000\u51FA\u7801").option("--start", "\u5B9E\u4F8B\u672A\u8FD0\u884C\u65F6\u81EA\u52A8\u5F00\u673A", false).option("--cwd <dir>", "\u8FDC\u7A0B\u5DE5\u4F5C\u76EE\u5F55").option("--timeout <duration>", "\u547D\u4EE4\u8D85\u65F6\u65F6\u95F4\uFF0C\u5982 30m").option("--env <key=value...>", "\u6CE8\u5165\u73AF\u5883\u53D8\u91CF").option("--pty", "\u5206\u914D\u4F2A\u7EC8\u7AEF\uFF08\u9700\u8981 isatty \u7684\u7A0B\u5E8F\u7528\u5F97\u4E0A\uFF09", false).action(
|
|
826
1092
|
action(
|
|
@@ -983,6 +1249,7 @@ function buildProgram() {
|
|
|
983
1249
|
registerAccountCommands(program);
|
|
984
1250
|
registerInstanceCommands(program);
|
|
985
1251
|
registerSSHCommands(program);
|
|
1252
|
+
registerFileCommands(program);
|
|
986
1253
|
registerRunCommand(program);
|
|
987
1254
|
registerDeployCommand(program);
|
|
988
1255
|
registerGuardCommands(program);
|
|
@@ -1021,7 +1288,7 @@ function shouldLaunchBareTui(argv) {
|
|
|
1021
1288
|
async function main(argv = process.argv) {
|
|
1022
1289
|
if (shouldLaunchBareTui(argv)) {
|
|
1023
1290
|
try {
|
|
1024
|
-
const { launchTui } = await import("./tui-
|
|
1291
|
+
const { launchTui } = await import("./tui-ZT5ZBVSQ.js");
|
|
1025
1292
|
await launchTui({});
|
|
1026
1293
|
return;
|
|
1027
1294
|
} catch (err) {
|
|
@@ -1032,12 +1299,39 @@ async function main(argv = process.argv) {
|
|
|
1032
1299
|
}
|
|
1033
1300
|
}
|
|
1034
1301
|
const program = buildProgram();
|
|
1302
|
+
const parseDiagnostics = [];
|
|
1303
|
+
const bufferDiagnostic = (message) => {
|
|
1304
|
+
parseDiagnostics.push(message);
|
|
1305
|
+
};
|
|
1306
|
+
const installParseHandling = (command) => {
|
|
1307
|
+
command.configureOutput({ outputError: bufferDiagnostic, writeErr: bufferDiagnostic });
|
|
1308
|
+
command.exitOverride();
|
|
1309
|
+
for (const subcommand of command.commands) installParseHandling(subcommand);
|
|
1310
|
+
};
|
|
1311
|
+
installParseHandling(program);
|
|
1035
1312
|
try {
|
|
1036
1313
|
await program.parseAsync(argv);
|
|
1037
1314
|
} catch (err) {
|
|
1038
|
-
const
|
|
1039
|
-
if (typeof
|
|
1040
|
-
|
|
1315
|
+
const commanderError = err;
|
|
1316
|
+
if (typeof commanderError?.code === "string" && commanderError.code.startsWith("commander.")) {
|
|
1317
|
+
if (commanderError.code === "commander.helpDisplayed" || commanderError.code === "commander.version") {
|
|
1318
|
+
process.exitCode = commanderError.exitCode ?? ExitCode.OK;
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
const jsonRequested = program.opts().json === true;
|
|
1322
|
+
if (jsonRequested) {
|
|
1323
|
+
configureOutput({ json: true });
|
|
1324
|
+
emitError(
|
|
1325
|
+
new UsageError(
|
|
1326
|
+
commanderError.code === "commander.help" ? "\u672A\u6307\u5B9A\u5B50\u547D\u4EE4" : (commanderError.message ?? "").replace(/^error:\s*/, ""),
|
|
1327
|
+
{ hint: "\u8FD0\u884C `autodl --help` \u67E5\u770B\u7528\u6CD5" }
|
|
1328
|
+
)
|
|
1329
|
+
);
|
|
1330
|
+
process.exitCode = ExitCode.USAGE;
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
if (parseDiagnostics.length > 0) process.stderr.write(parseDiagnostics.join(""));
|
|
1334
|
+
process.exitCode = commanderError.code === "commander.help" ? commanderError.exitCode ?? ExitCode.GENERIC : ExitCode.USAGE;
|
|
1041
1335
|
return;
|
|
1042
1336
|
}
|
|
1043
1337
|
const error = toAutoDLError(err);
|
package/dist/index.d.ts
CHANGED
|
@@ -745,7 +745,7 @@ interface ConnectOptions extends CredentialOptions {
|
|
|
745
745
|
connectAttempts?: number;
|
|
746
746
|
}
|
|
747
747
|
/**
|
|
748
|
-
* The single funnel for every SSH operation.
|
|
748
|
+
* The single funnel for every one-shot SSH operation.
|
|
749
749
|
*
|
|
750
750
|
* Each attempt re-reads the credentials, which covers both ways a connection can fail:
|
|
751
751
|
* the port may have been reassigned since the snapshot was taken, and sshd may simply
|
|
@@ -753,6 +753,15 @@ interface ConnectOptions extends CredentialOptions {
|
|
|
753
753
|
* second only by waiting — so attempts are spaced out rather than fired back to back.
|
|
754
754
|
*/
|
|
755
755
|
declare function withSSH<T>(client: AutoDLClient, uuid: string, fn: (conn: Client, creds: SSHCredentials) => Promise<T>, options?: ConnectOptions): Promise<T>;
|
|
756
|
+
/**
|
|
757
|
+
* Build one authenticated connection and hand ownership to the caller.
|
|
758
|
+
*
|
|
759
|
+
* Same retry policy as `withSSH` (fresh credentials per attempt, spaced retries
|
|
760
|
+
* for sshd-not-up-yet and port reassignment), except nothing is closed: the
|
|
761
|
+
* caller MUST eventually call `conn.end()`. Used for the file view's reusable
|
|
762
|
+
* browsing connection; one-shot operations should keep using `withSSH`.
|
|
763
|
+
*/
|
|
764
|
+
declare function connectSSH(client: AutoDLClient, uuid: string, options?: ConnectOptions): Promise<Client>;
|
|
756
765
|
|
|
757
766
|
/**
|
|
758
767
|
* Interactive login hands off to the system `ssh` binary rather than ssh2: the user
|
|
@@ -945,4 +954,4 @@ interface RunResult {
|
|
|
945
954
|
*/
|
|
946
955
|
declare function runWorkflow(client: AutoDLClient, options: RunOptions): Promise<RunResult>;
|
|
947
956
|
|
|
948
|
-
export { AuthError, AutoDLClient, AutoDLError, BASE_IMAGES, type Balance, type BaseImage, BudgetError, type ClientOptions, type Context, type CreateInstanceInput, DEFAULT_BASE_IMAGE, DEFAULT_BASE_URL, type DeployOptions, type DeployResult, type ErrorCode, type ExecOptions, type ExecResult, ExitCode, GPU_SPECS, type GlobalOptions, type GpuSpec, type GpuStockEntry, type IdleOptions, type IdleResult, type Instance, type InstanceSnapshot, type InstanceStatus, NoStockError, NotFoundError, type Pagination, type ParsedRepo, type PrivateImage, REGIONS, type Region, type RegionChoice, type RegionStock, type RunOptions, type RunResult, type SSHCredentials, SSHError, type ServiceEndpoint, type StockQuery, type StockSnapshot, type StoredConfig, TimeoutError, type TransferOptions, type TransferSummary, UsageError, VERSION, type WaitOptions, armTTLOverSSH, assertBudget, assertStockRegion, buildServer, buildTTLSnippet, chooseRegions, composeStartCommand, connectInteractive, createContext, createInstance, deployWorkflow, disarmTTLOverSSH, estimateCost, execCommand, execOnConnection, findBaseImage, findInstance, findRegionsWithStock, formatCudaVersion, formatDuration, formatRate, formatSSHCommand, formatYuan, getBalance, getCredentials, getInstanceSnapshot, getInstanceStatus, getRegionGpuStock, getStockByRegion, listAllInstances, listInstancesPage, listPrivateImages, milliToYuan, normalizeBalance, normalizeInstance, normalizeSnapshot, parseCudaVersion, parseDuration, parseRepo, parseUtilisation, powerOffInstance, powerOnInstance, pull, push, readConfig, recordTTL, redactCredentials, redactSnapshot, redactToken, releaseInstance, resolveGitToken, resolveGpuSpec, resolveMinBalance, resolveRegion, resolveToken, runWorkflow, saveImage, setNfsMount, specForStockName, startMcpServer, sweepExpired, toAutoDLError, updateConfig, waitForRunning, waitForShutdown, waitForStatus, watchIdle, withCredentials, withSSH, writeConfig, yuanToMilli };
|
|
957
|
+
export { AuthError, AutoDLClient, AutoDLError, BASE_IMAGES, type Balance, type BaseImage, BudgetError, type ClientOptions, type Context, type CreateInstanceInput, DEFAULT_BASE_IMAGE, DEFAULT_BASE_URL, type DeployOptions, type DeployResult, type ErrorCode, type ExecOptions, type ExecResult, ExitCode, GPU_SPECS, type GlobalOptions, type GpuSpec, type GpuStockEntry, type IdleOptions, type IdleResult, type Instance, type InstanceSnapshot, type InstanceStatus, NoStockError, NotFoundError, type Pagination, type ParsedRepo, type PrivateImage, REGIONS, type Region, type RegionChoice, type RegionStock, type RunOptions, type RunResult, type SSHCredentials, SSHError, type ServiceEndpoint, type StockQuery, type StockSnapshot, type StoredConfig, TimeoutError, type TransferOptions, type TransferSummary, UsageError, VERSION, type WaitOptions, armTTLOverSSH, assertBudget, assertStockRegion, buildServer, buildTTLSnippet, chooseRegions, composeStartCommand, connectInteractive, connectSSH, createContext, createInstance, deployWorkflow, disarmTTLOverSSH, estimateCost, execCommand, execOnConnection, findBaseImage, findInstance, findRegionsWithStock, formatCudaVersion, formatDuration, formatRate, formatSSHCommand, formatYuan, getBalance, getCredentials, getInstanceSnapshot, getInstanceStatus, getRegionGpuStock, getStockByRegion, listAllInstances, listInstancesPage, listPrivateImages, milliToYuan, normalizeBalance, normalizeInstance, normalizeSnapshot, parseCudaVersion, parseDuration, parseRepo, parseUtilisation, powerOffInstance, powerOnInstance, pull, push, readConfig, recordTTL, redactCredentials, redactSnapshot, redactToken, releaseInstance, resolveGitToken, resolveGpuSpec, resolveMinBalance, resolveRegion, resolveToken, runWorkflow, saveImage, setNfsMount, specForStockName, startMcpServer, sweepExpired, toAutoDLError, updateConfig, waitForRunning, waitForShutdown, waitForStatus, watchIdle, withCredentials, withSSH, writeConfig, yuanToMilli };
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
startMcpServer,
|
|
21
21
|
watchIdle,
|
|
22
22
|
withCredentials
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-MWYYK755.js";
|
|
24
24
|
import {
|
|
25
25
|
BASE_IMAGES,
|
|
26
26
|
DEFAULT_BASE_IMAGE,
|
|
@@ -40,10 +40,10 @@ import {
|
|
|
40
40
|
resolveRegion,
|
|
41
41
|
setNfsMount,
|
|
42
42
|
specForStockName
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-WN2CXPD2.js";
|
|
44
44
|
import {
|
|
45
45
|
createContext
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-VEDMEYCW.js";
|
|
47
47
|
import {
|
|
48
48
|
AuthError,
|
|
49
49
|
AutoDLClient,
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
armTTLOverSSH,
|
|
60
60
|
buildTTLSnippet,
|
|
61
61
|
composeStartCommand,
|
|
62
|
+
connectSSH,
|
|
62
63
|
createInstance,
|
|
63
64
|
disarmTTLOverSSH,
|
|
64
65
|
estimateCost,
|
|
@@ -95,7 +96,7 @@ import {
|
|
|
95
96
|
withSSH,
|
|
96
97
|
writeConfig,
|
|
97
98
|
yuanToMilli
|
|
98
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-GHJVQKKC.js";
|
|
99
100
|
export {
|
|
100
101
|
AuthError,
|
|
101
102
|
AutoDLClient,
|
|
@@ -121,6 +122,7 @@ export {
|
|
|
121
122
|
chooseRegions,
|
|
122
123
|
composeStartCommand,
|
|
123
124
|
connectInteractive,
|
|
125
|
+
connectSSH,
|
|
124
126
|
createContext,
|
|
125
127
|
createInstance,
|
|
126
128
|
deployWorkflow,
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
assertInteractive,
|
|
6
6
|
launchTui,
|
|
7
7
|
registerTuiCommand
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-JOOIUQLJ.js";
|
|
9
|
+
import "./chunk-VEDMEYCW.js";
|
|
10
|
+
import "./chunk-GHJVQKKC.js";
|
|
11
11
|
export {
|
|
12
12
|
assertInteractive,
|
|
13
13
|
launchTui,
|
|
14
14
|
registerTuiCommand
|
|
15
15
|
};
|
|
16
|
-
//# sourceMappingURL=tui-
|
|
16
|
+
//# sourceMappingURL=tui-ZT5ZBVSQ.js.map
|
package/package.json
CHANGED