@minato-aqukin/autodl-cli 0.1.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.
@@ -0,0 +1,433 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __nodeCreateRequire } from "node:module";
3
+ const require = __nodeCreateRequire(import.meta.url);
4
+ import {
5
+ UsageError,
6
+ debug,
7
+ normalizeBalance,
8
+ note,
9
+ warn,
10
+ yuanToMilli
11
+ } from "./chunk-6QR4ZYQR.js";
12
+
13
+ // src/core/catalog.ts
14
+ var GPU_SPECS = [
15
+ {
16
+ id: "h800",
17
+ displayName: "H800-80G",
18
+ tier: "general",
19
+ vramGb: 80,
20
+ aliases: ["h800", "h800-80g"],
21
+ stockName: "H800"
22
+ },
23
+ {
24
+ id: "v-48g",
25
+ displayName: "4090-48G",
26
+ tier: "general",
27
+ vramGb: 48,
28
+ aliases: ["4090", "4090-48g", "v-48g"],
29
+ stockName: "vGPU-48GB"
30
+ },
31
+ {
32
+ id: "4090D",
33
+ displayName: "4090D",
34
+ tier: "general",
35
+ vramGb: 24,
36
+ aliases: ["4090d"],
37
+ stockName: "RTX 4090D"
38
+ },
39
+ {
40
+ id: "v-48g-350w",
41
+ displayName: "3090-48G",
42
+ tier: "general",
43
+ vramGb: 48,
44
+ aliases: ["3090", "3090-48g", "v-48g-350w"],
45
+ stockName: "vGPU-48GB-350W"
46
+ },
47
+ {
48
+ id: "pro6000-p",
49
+ displayName: "PRO6000-96G",
50
+ tier: "performance",
51
+ vramGb: 96,
52
+ aliases: ["pro6000", "rtx-pro-6000", "pro6000-96g"],
53
+ stockName: "RTX PRO 6000"
54
+ },
55
+ {
56
+ id: "v-32g-p",
57
+ displayName: "4080(S)-32G",
58
+ tier: "performance",
59
+ vramGb: 32,
60
+ aliases: ["4080", "4080s", "4080-32g"],
61
+ stockName: "vGPU-32GB"
62
+ },
63
+ {
64
+ id: "5090-p",
65
+ displayName: "5090-32G",
66
+ tier: "performance",
67
+ vramGb: 32,
68
+ aliases: ["5090", "5090-32g"],
69
+ stockName: "RTX 5090"
70
+ }
71
+ ];
72
+ var REGIONS = [
73
+ {
74
+ id: "westDC2",
75
+ displayName: "\u897F\u5317\u4F01\u4E1A\u533A",
76
+ aliases: ["west2", "\u897F\u5317\u4F01\u4E1A\u533A", "\u897F\u5317\u4F01\u4E1A"],
77
+ proCreate: false
78
+ },
79
+ {
80
+ id: "westDC3",
81
+ displayName: "\u897F\u5317B\u533A",
82
+ aliases: ["west3", "\u897F\u5317b\u533A", "\u897F\u5317b"],
83
+ proCreate: true
84
+ },
85
+ {
86
+ id: "beijingDC1",
87
+ displayName: "\u5317\u4EACA\u533A",
88
+ aliases: ["bj1", "\u5317\u4EACa\u533A", "\u5317\u4EACa"],
89
+ proCreate: false
90
+ },
91
+ {
92
+ id: "beijingDC2",
93
+ displayName: "\u5317\u4EACB\u533A",
94
+ aliases: ["bj2", "\u5317\u4EACb\u533A", "\u5317\u4EACb"],
95
+ proCreate: true
96
+ },
97
+ {
98
+ id: "beijingDC3",
99
+ displayName: "V100\u4E13\u533A",
100
+ aliases: ["bj3", "v100", "v100\u4E13\u533A"],
101
+ proCreate: false
102
+ },
103
+ {
104
+ id: "beijingDC4",
105
+ displayName: "L20\u4E13\u533A",
106
+ aliases: ["bj4", "l20", "l20\u4E13\u533A"],
107
+ proCreate: false
108
+ },
109
+ {
110
+ id: "neimengDC1",
111
+ displayName: "\u5185\u8499A\u533A",
112
+ aliases: ["nm1", "\u5185\u8499a\u533A", "\u5185\u8499a"],
113
+ proCreate: false
114
+ },
115
+ {
116
+ id: "neimengDC3",
117
+ displayName: "\u5185\u8499B\u533A",
118
+ aliases: ["nm3", "\u5185\u8499b\u533A", "\u5185\u8499b"],
119
+ proCreate: false
120
+ },
121
+ { id: "foshanDC1", displayName: "\u4F5B\u5C71\u533A", aliases: ["fs1", "\u4F5B\u5C71"], proCreate: false },
122
+ {
123
+ id: "chongqingDC1",
124
+ displayName: "\u91CD\u5E86A\u533A",
125
+ aliases: ["cq1", "\u91CD\u5E86a\u533A", "\u91CD\u5E86"],
126
+ proCreate: false
127
+ },
128
+ {
129
+ id: "yangzhouDC1",
130
+ displayName: "3090\u4E13\u533A",
131
+ aliases: ["yz1", "3090\u4E13\u533A", "\u626C\u5DDE"],
132
+ proCreate: false
133
+ }
134
+ ];
135
+ var BASE_IMAGES = [
136
+ {
137
+ uuid: "base-image-l2t43iu6uk",
138
+ framework: "PyTorch",
139
+ tag: "cuda11.8-cudnn8-devel-ubuntu20.04-py38-torch2.0.0",
140
+ cuda: "11.8",
141
+ python: "3.8"
142
+ },
143
+ {
144
+ uuid: "base-image-l374uiucui",
145
+ framework: "PyTorch",
146
+ tag: "cuda11.3-cudnn8-devel-ubuntu20.04-py38-torch1.11.0",
147
+ cuda: "11.3",
148
+ python: "3.8"
149
+ },
150
+ {
151
+ uuid: "base-image-u9r24vthlk",
152
+ framework: "PyTorch",
153
+ tag: "cuda11.3-cudnn8-devel-ubuntu20.04-py38-torch1.10.0",
154
+ cuda: "11.3",
155
+ python: "3.8"
156
+ },
157
+ {
158
+ uuid: "base-image-12be412037",
159
+ framework: "PyTorch",
160
+ tag: "cuda11.1-cudnn8-devel-ubuntu18.04-py38-torch1.9.0",
161
+ cuda: "11.1",
162
+ python: "3.8"
163
+ },
164
+ {
165
+ uuid: "base-image-uxeklgirir",
166
+ framework: "TensorFlow",
167
+ tag: "cuda11.2-cudnn8-devel-ubuntu20.04-py38-tf2.9.0",
168
+ cuda: "11.2",
169
+ python: "3.8"
170
+ },
171
+ {
172
+ uuid: "base-image-0gxqmciyth",
173
+ framework: "TensorFlow",
174
+ tag: "cuda11.2-cudnn8-devel-ubuntu18.04-py38-tf2.5.0",
175
+ cuda: "11.2",
176
+ python: "3.8"
177
+ },
178
+ {
179
+ uuid: "base-image-4bpg0tt88l",
180
+ framework: "TensorFlow",
181
+ tag: "cuda11.4-py38-tf1.15.5",
182
+ cuda: "11.4",
183
+ python: "3.8"
184
+ },
185
+ {
186
+ uuid: "base-image-mbr2n4urrc",
187
+ framework: "Miniconda",
188
+ tag: "cuda11.6-cudnn8-devel-ubuntu20.04-py38",
189
+ cuda: "11.6",
190
+ python: "3.8"
191
+ },
192
+ {
193
+ uuid: "base-image-7bn8iqhkb5",
194
+ framework: "Miniconda",
195
+ tag: "cudagl11.3-cudnn8-devel-ubuntu20.04-py38",
196
+ cuda: "11.3",
197
+ python: "3.8"
198
+ },
199
+ {
200
+ uuid: "base-image-h041hn36yt",
201
+ framework: "Miniconda",
202
+ tag: "cuda11.1-cudnn8-devel-ubuntu18.04-py38",
203
+ cuda: "11.1",
204
+ python: "3.8"
205
+ },
206
+ {
207
+ uuid: "base-image-qkkhitpik5",
208
+ framework: "Miniconda",
209
+ tag: "cuda10.2-cudnn7-devel-ubuntu18.04-py38",
210
+ cuda: "10.2",
211
+ python: "3.8"
212
+ },
213
+ {
214
+ uuid: "base-image-k0vep6kyq8",
215
+ framework: "Miniconda",
216
+ tag: "cuda9.0-cudnn7-devel-ubuntu16.04-py36",
217
+ cuda: "9.0",
218
+ python: "3.6"
219
+ },
220
+ {
221
+ uuid: "base-image-l2843iu23k",
222
+ framework: "TensorRT",
223
+ tag: "cuda11.8-cudnn8-devel-ubuntu20.04-py38-trt8.5.1",
224
+ cuda: "11.8",
225
+ python: "3.8"
226
+ }
227
+ ];
228
+ var DEFAULT_BASE_IMAGE = "base-image-l2t43iu6uk";
229
+ function norm(value) {
230
+ return value.trim().toLowerCase();
231
+ }
232
+ function resolveGpuSpec(input) {
233
+ const needle = norm(input);
234
+ return GPU_SPECS.find(
235
+ (spec) => norm(spec.id) === needle || norm(spec.displayName) === needle || spec.aliases.some((alias) => norm(alias) === needle)
236
+ );
237
+ }
238
+ function resolveRegion(input) {
239
+ const needle = norm(input);
240
+ return REGIONS.find(
241
+ (region) => norm(region.id) === needle || norm(region.displayName) === needle || region.aliases.some((alias) => norm(alias) === needle)
242
+ );
243
+ }
244
+ function assertStockRegion(input) {
245
+ const region = resolveRegion(input);
246
+ if (!region) {
247
+ throw new UsageError(`\u672A\u77E5\u7684\u5730\u533A "${input}"`, {
248
+ hint: "\u8FD0\u884C `autodl regions` \u67E5\u770B\u6709\u6548\u5730\u533A\u4EE3\u7801\u3002\u6CE8\u610F\u5B9E\u4F8B\u8FD4\u56DE\u7684 region_sign\uFF08\u5982 bj-B2\uFF09\u4E0E\u8FD9\u91CC\u7684\u5730\u533A\u4EE3\u7801\uFF08\u5982 beijingDC2\uFF09\u4E0D\u662F\u540C\u4E00\u5957\u547D\u540D\uFF0C\u4E0D\u80FD\u6DF7\u7528\u3002"
249
+ });
250
+ }
251
+ return region;
252
+ }
253
+ var PRO_CREATE_REGIONS = REGIONS.filter((region) => region.proCreate);
254
+ function assertProCreateRegion(input) {
255
+ const region = assertStockRegion(input);
256
+ if (!region.proCreate) {
257
+ throw new UsageError(`\u5730\u533A "${region.displayName}"\uFF08${region.id}\uFF09\u4E0D\u652F\u6301\u521B\u5EFA Pro \u5B9E\u4F8B`, {
258
+ hint: `\u5B98\u65B9\u5F00\u653E API \u53EA\u80FD\u5728 ${PRO_CREATE_REGIONS.map((r) => `${r.displayName}(${r.id})`).join(" \u6216 ")} \u521B\u5EFA\u5B9E\u4F8B\uFF1B\u5176\u4F59\u5730\u533A\u4EC5\u7528\u4E8E\u5F39\u6027\u90E8\u7F72\u3002\u4E0D\u6307\u5B9A --region \u65F6\u7531 AutoDL \u81EA\u884C\u8C03\u5EA6\uFF0C\u6210\u529F\u7387\u66F4\u9AD8\u3002`
259
+ });
260
+ }
261
+ return region;
262
+ }
263
+ function findBaseImage(input) {
264
+ const needle = norm(input);
265
+ return BASE_IMAGES.find((image) => norm(image.uuid) === needle || norm(image.tag) === needle);
266
+ }
267
+ function parseCudaVersion(input) {
268
+ if (typeof input === "number") return input >= 100 ? input : Math.round(input * 10);
269
+ const trimmed = input.trim();
270
+ if (/^\d{3}$/.test(trimmed)) return Number(trimmed);
271
+ const asFloat = Number.parseFloat(trimmed);
272
+ if (Number.isNaN(asFloat)) return 0;
273
+ const [major = "0", minor = "0"] = trimmed.split(".");
274
+ return Number(major) * 10 + Number(minor.slice(0, 1) || "0");
275
+ }
276
+ function formatCudaVersion(value) {
277
+ if (!value) return "-";
278
+ return `${Math.floor(value / 10)}.${value % 10}`;
279
+ }
280
+
281
+ // src/core/endpoints/account.ts
282
+ async function getBalance(client) {
283
+ const data = await client.post("/api/v1/dev/wallet/balance", {});
284
+ return normalizeBalance(data);
285
+ }
286
+ async function setNfsMount(client, dataCenter, mount) {
287
+ await client.post("/api/v1/dev/exclusive_nfs/mount", {
288
+ data_center: dataCenter,
289
+ mountable: mount ? 1 : -1
290
+ });
291
+ }
292
+
293
+ // src/core/endpoints/machine.ts
294
+ async function getRegionGpuStock(client, query) {
295
+ const region = assertStockRegion(query.regionSign);
296
+ const payload = { region_sign: region.id };
297
+ if (query.gpuNames?.length) payload.gpu_name_set = query.gpuNames;
298
+ if (query.cudaFrom !== void 0) payload.cuda_v_from = query.cudaFrom;
299
+ if (query.cudaTo !== void 0) payload.cuda_v_to = query.cudaTo;
300
+ if (query.cpuNumFrom !== void 0) payload.cpu_num_from = query.cpuNumFrom;
301
+ if (query.cpuNumTo !== void 0) payload.cpu_num_to = query.cpuNumTo;
302
+ if (query.memorySizeFrom !== void 0) payload.memory_size_from = query.memorySizeFrom;
303
+ if (query.memorySizeTo !== void 0) payload.memory_size_to = query.memorySizeTo;
304
+ if (query.priceFromYuan !== void 0) payload.price_from = yuanToMilli(query.priceFromYuan);
305
+ if (query.priceToYuan !== void 0) payload.price_to = yuanToMilli(query.priceToYuan);
306
+ const data = await client.post("/api/v1/dev/machine/region/gpu_stock", payload);
307
+ const entries = [];
308
+ for (const item of Array.isArray(data) ? data : []) {
309
+ for (const [gpuName, value] of Object.entries(item ?? {})) {
310
+ entries.push({
311
+ gpuName,
312
+ idle: value?.idle_gpu_num ?? 0,
313
+ total: value?.total_gpu_num ?? 0,
314
+ chipCorp: value?.chip_corp ?? null,
315
+ cpuArch: value?.cpu_arch ?? null
316
+ });
317
+ }
318
+ }
319
+ return entries;
320
+ }
321
+
322
+ // src/core/stock.ts
323
+ async function getStockByRegion(client, options = {}) {
324
+ const targets = (options.regions?.length ? options.regions : REGIONS.map((r) => r.id)).map(
325
+ (input) => assertStockRegion(input)
326
+ );
327
+ const settled = await Promise.allSettled(
328
+ targets.map(async (region) => ({
329
+ region,
330
+ entries: await getRegionGpuStock(client, {
331
+ regionSign: region.id,
332
+ ...options.gpuNames?.length ? { gpuNames: options.gpuNames } : {}
333
+ })
334
+ }))
335
+ );
336
+ const snapshots = [];
337
+ const failures = [];
338
+ settled.forEach((result, index) => {
339
+ const region = targets[index];
340
+ if (!region) return;
341
+ if (result.status === "fulfilled") {
342
+ snapshots.push({
343
+ regionId: region.id,
344
+ regionName: region.displayName,
345
+ entries: result.value.entries
346
+ });
347
+ } else {
348
+ const reason = result.reason?.message ?? String(result.reason);
349
+ failures.push({ regionId: region.id, reason });
350
+ debug(`\u67E5\u8BE2 ${region.id} \u5E93\u5B58\u5931\u8D25\uFF1A${reason}`);
351
+ }
352
+ });
353
+ return { snapshots, failures };
354
+ }
355
+ async function findRegionsWithStock(client, spec, options = {}) {
356
+ const { snapshots, failures } = await getStockByRegion(client, {
357
+ ...options.regions?.length ? { regions: options.regions } : {},
358
+ gpuNames: [spec.stockName]
359
+ });
360
+ const ranked = [];
361
+ for (const snapshot of snapshots) {
362
+ const entry = snapshot.entries.find((e) => e.gpuName === spec.stockName);
363
+ if (!entry) continue;
364
+ ranked.push({
365
+ regionId: snapshot.regionId,
366
+ regionName: snapshot.regionName,
367
+ idle: entry.idle,
368
+ total: entry.total
369
+ });
370
+ }
371
+ ranked.sort((a, b) => b.idle - a.idle || b.total - a.total);
372
+ return { ranked, failures };
373
+ }
374
+ function specForStockName(gpuName) {
375
+ return GPU_SPECS.find((spec) => spec.stockName === gpuName);
376
+ }
377
+ async function chooseRegions(client, spec, requested) {
378
+ if (!requested?.length) {
379
+ return { regions: [], ranked: [], allBusy: false };
380
+ }
381
+ const validated = requested.map((input) => assertProCreateRegion(input).id);
382
+ const { ranked, failures } = await findRegionsWithStock(client, spec, { regions: validated });
383
+ for (const failure of failures) debug(`\u5E93\u5B58\u67E5\u8BE2\u5931\u8D25 ${failure.regionId}\uFF1A${failure.reason}`);
384
+ const withStock = ranked.filter((region) => region.idle > 0);
385
+ if (withStock.length === 0 && ranked.length > 0) {
386
+ warn(
387
+ `${spec.displayName} \u5728\u6307\u5B9A\u5730\u533A\u7684\u5F39\u6027\u90E8\u7F72\u5E93\u5B58\u4E3A 0\uFF0C\u4ECD\u4F1A\u5C1D\u8BD5\u521B\u5EFA\uFF08\u8BE5\u5E93\u5B58\u4E0D\u53CD\u6620 Pro \u5B9E\u4F8B\u53EF\u7528\u91CF\uFF0C\u4EC5\u4F9B\u53C2\u8003\uFF09`
388
+ );
389
+ return { regions: validated, ranked, allBusy: true };
390
+ }
391
+ if (withStock.length > 0) {
392
+ const best = withStock[0];
393
+ note(
394
+ `\u6307\u5B9A\u5730\u533A\u4E2D ${best.regionName} \u5E93\u5B58\u6700\u591A\uFF08${spec.displayName} \u7A7A\u95F2 ${best.idle}/${best.total}\uFF09`
395
+ );
396
+ const ordered = [
397
+ ...withStock.map((region) => region.regionId),
398
+ ...validated.filter((id) => !withStock.some((region) => region.regionId === id))
399
+ ];
400
+ return { regions: ordered, ranked, allBusy: false };
401
+ }
402
+ return { regions: validated, ranked, allBusy: false };
403
+ }
404
+
405
+ // src/version.ts
406
+ import { createRequire } from "module";
407
+ var require2 = createRequire(import.meta.url);
408
+ var pkg = require2("../package.json");
409
+ var VERSION = pkg.version;
410
+
411
+ export {
412
+ GPU_SPECS,
413
+ REGIONS,
414
+ BASE_IMAGES,
415
+ DEFAULT_BASE_IMAGE,
416
+ resolveGpuSpec,
417
+ resolveRegion,
418
+ assertStockRegion,
419
+ PRO_CREATE_REGIONS,
420
+ assertProCreateRegion,
421
+ findBaseImage,
422
+ parseCudaVersion,
423
+ formatCudaVersion,
424
+ getBalance,
425
+ setNfsMount,
426
+ getRegionGpuStock,
427
+ getStockByRegion,
428
+ findRegionsWithStock,
429
+ specForStockName,
430
+ chooseRegions,
431
+ VERSION
432
+ };
433
+ //# sourceMappingURL=chunk-CWCG3MOC.js.map
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __nodeCreateRequire } from "node:module";
3
+ const require = __nodeCreateRequire(import.meta.url);
4
+ import {
5
+ AutoDLClient,
6
+ configureOutput,
7
+ debug,
8
+ resolveBaseUrl,
9
+ resolveLang,
10
+ resolveToken,
11
+ setLang,
12
+ sweepExpired
13
+ } from "./chunk-6QR4ZYQR.js";
14
+
15
+ // src/context.ts
16
+ function createContext(options = {}) {
17
+ const lang = resolveLang(options.lang);
18
+ setLang(lang);
19
+ configureOutput({
20
+ json: options.json ?? false,
21
+ color: options.color ?? true,
22
+ verbose: options.verbose ?? false
23
+ });
24
+ const { token, source } = resolveToken(options.token);
25
+ debug(`Token \u6765\u6E90\uFF1A${source}`);
26
+ const client = new AutoDLClient({
27
+ token,
28
+ ...resolveBaseUrl(options.baseUrl) ? { baseUrl: resolveBaseUrl(options.baseUrl) } : {},
29
+ onDebug: debug
30
+ });
31
+ return { client, lang };
32
+ }
33
+ async function runOpportunisticSweep(context, options) {
34
+ if (options.sweep === false || process.env.AUTODL_NO_SWEEP === "1") return;
35
+ try {
36
+ await sweepExpired(context.client);
37
+ } catch (err) {
38
+ debug(`TTL \u6E05\u7406\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF09\uFF1A${err.message}`);
39
+ }
40
+ }
41
+
42
+ export {
43
+ createContext,
44
+ runOpportunisticSweep
45
+ };
46
+ //# sourceMappingURL=chunk-NBWWTYSL.js.map