@exedev/sdk 0.0.6 → 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/LICENSE +21 -0
- package/README.md +128 -46
- package/dist/client.d.ts +59 -54
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +343 -99
- package/dist/client.js.map +1 -1
- package/dist/commands.gen.d.ts +1468 -0
- package/dist/commands.gen.d.ts.map +1 -0
- package/dist/commands.gen.js +1640 -0
- package/dist/commands.gen.js.map +1 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +110 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +8 -5
|
@@ -0,0 +1,1640 @@
|
|
|
1
|
+
// Code generated by "go run ./cmd/gensdkjs" in the exe.dev repository. DO NOT EDIT.
|
|
2
|
+
import { Transport, ExeAPIError, ExeProtocolError, abortable, delay } from "./client.js";
|
|
3
|
+
export class ExedevClient {
|
|
4
|
+
#transport;
|
|
5
|
+
constructor(options) { this.#transport = new Transport(options); }
|
|
6
|
+
/** Reference an existing VM without a request. Use refresh() to fetch its metadata. */
|
|
7
|
+
vm(name) {
|
|
8
|
+
if (typeof name !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9-]*$/.test(name)) {
|
|
9
|
+
throw new TypeError("exedev: expected a VM name, not a command or SSH destination");
|
|
10
|
+
}
|
|
11
|
+
return new VM(this.#transport, { name, tags: [] });
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Browse documentation
|
|
15
|
+
*
|
|
16
|
+
* Usage: `doc [slug-or-query...]`
|
|
17
|
+
*
|
|
18
|
+
* Tag-scoped API keys may run this command.
|
|
19
|
+
*/
|
|
20
|
+
async doc(slugOrQueries, options) {
|
|
21
|
+
const result = await this.#transport.call("doc", [slugOrQueries], options, {}, false);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* List your VMs
|
|
26
|
+
*
|
|
27
|
+
* Usage: `ls [-l] [--group=tag|region|type] [name|pattern]`
|
|
28
|
+
*
|
|
29
|
+
* Tag-scoped API keys may run this command.
|
|
30
|
+
*/
|
|
31
|
+
async ls(nameOrPattern, options) {
|
|
32
|
+
const result = await this.#transport.call("ls", [nameOrPattern], options, {
|
|
33
|
+
group: "string",
|
|
34
|
+
l: "bool",
|
|
35
|
+
}, true);
|
|
36
|
+
return listVMs(this.#transport, result);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a new VM
|
|
40
|
+
*
|
|
41
|
+
* CLI examples:
|
|
42
|
+
* ```
|
|
43
|
+
* new # just give me a computer
|
|
44
|
+
* new --name=b --image=ubuntu:22.04 # custom image and name
|
|
45
|
+
* new --cpu=4 --memory=16GB # 4 CPUs, 16GB RAM
|
|
46
|
+
* new --disk=50GB # 50GB disk
|
|
47
|
+
* new --tag=prod,staging # create with tags
|
|
48
|
+
* new --env FOO=bar --env BAZ=qux # with environment variables
|
|
49
|
+
* new --integration=myproxy # attach an integration
|
|
50
|
+
* echo 'build me a web app' | ssh exe.dev new --prompt=/dev/stdin
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* Tag-scoped API keys may run this command.
|
|
54
|
+
*/
|
|
55
|
+
async new(options) {
|
|
56
|
+
const ready = readiness(options ?? {});
|
|
57
|
+
const { waitUntil, timeoutMs, ...flags } = options ?? {};
|
|
58
|
+
const result = await this.#transport.call("new", [], flags, {
|
|
59
|
+
comment: "string",
|
|
60
|
+
cpu: "number",
|
|
61
|
+
disk: "string",
|
|
62
|
+
env: "repeated",
|
|
63
|
+
image: "string",
|
|
64
|
+
integration: "repeated",
|
|
65
|
+
memory: "string",
|
|
66
|
+
name: "string",
|
|
67
|
+
"no-email": "bool",
|
|
68
|
+
"no-pool": "bool",
|
|
69
|
+
pool: "string",
|
|
70
|
+
prompt: "string",
|
|
71
|
+
"registry-auth": "string",
|
|
72
|
+
sandbox: "bool",
|
|
73
|
+
"setup-script": "string",
|
|
74
|
+
standalone: "bool",
|
|
75
|
+
tag: "repeated",
|
|
76
|
+
}, true);
|
|
77
|
+
const vm = new VM(this.#transport, vmInfo(result, "new"));
|
|
78
|
+
if (ready)
|
|
79
|
+
await vm.waitUntilReady(ready);
|
|
80
|
+
return vm;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* List custom domains for a VM (or -a for all your VMs)
|
|
84
|
+
*
|
|
85
|
+
* Usage: `domain ls <vm> | domain ls -a`
|
|
86
|
+
*/
|
|
87
|
+
async domainLs(args, options) {
|
|
88
|
+
const result = await this.#transport.call("domain ls", [args], options, {
|
|
89
|
+
a: "bool",
|
|
90
|
+
}, false);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Show user information (email, keys, etc)
|
|
95
|
+
*
|
|
96
|
+
* Usage: `whoami`
|
|
97
|
+
*
|
|
98
|
+
* Tag-scoped API keys may run this command.
|
|
99
|
+
*/
|
|
100
|
+
async whoami(options) {
|
|
101
|
+
const result = await this.#transport.call("whoami", [], options, {}, true);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* List all SSH keys associated with your account
|
|
106
|
+
*
|
|
107
|
+
* Usage: `ssh-key list`
|
|
108
|
+
*
|
|
109
|
+
* Tag-scoped API keys may run this command.
|
|
110
|
+
*/
|
|
111
|
+
async sshKeyList(options) {
|
|
112
|
+
const result = await this.#transport.call("ssh-key list", [], options, {}, false);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Add a new SSH key to your account
|
|
117
|
+
*
|
|
118
|
+
* Usage: `ssh-key add [--tag=TAG] <public-key>`
|
|
119
|
+
*
|
|
120
|
+
* CLI examples:
|
|
121
|
+
* ```
|
|
122
|
+
* ssh-key add 'ssh-ed25519 AAAA... my-laptop'
|
|
123
|
+
*
|
|
124
|
+
* To generate a new key locally:
|
|
125
|
+
* ssh-keygen -t ed25519 -C "mnemonic-for-this-key" -f ~/.ssh/id_exe
|
|
126
|
+
*
|
|
127
|
+
* The -C flag sets a name for the key.
|
|
128
|
+
*
|
|
129
|
+
* Then add the public key from your local shell:
|
|
130
|
+
* cat ~/.ssh/id_exe.pub | ssh exe.dev ssh-key add
|
|
131
|
+
*
|
|
132
|
+
* Or from the exe.dev shell:
|
|
133
|
+
* ssh-key add 'ssh-ed25519 AAAA... my-laptop'
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* Tag-scoped API keys may run this command.
|
|
137
|
+
*/
|
|
138
|
+
async sshKeyAdd(publicKey, options) {
|
|
139
|
+
const result = await this.#transport.call("ssh-key add", [publicKey], options, {
|
|
140
|
+
tag: "string",
|
|
141
|
+
}, false);
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Remove an SSH key from your account
|
|
146
|
+
*
|
|
147
|
+
* Usage: `ssh-key remove <name|fingerprint|public-key>`
|
|
148
|
+
*
|
|
149
|
+
* Tag-scoped API keys may run this command.
|
|
150
|
+
*/
|
|
151
|
+
async sshKeyRemove(nameOrFingerprintOrPublicKey, options) {
|
|
152
|
+
const result = await this.#transport.call("ssh-key remove", [nameOrFingerprintOrPublicKey], options, {}, false);
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Rename an SSH key
|
|
157
|
+
*
|
|
158
|
+
* Usage: `ssh-key rename <old-name> <new-name>`
|
|
159
|
+
*
|
|
160
|
+
* Tag-scoped API keys may run this command.
|
|
161
|
+
*/
|
|
162
|
+
async sshKeyRename(oldName, newName, options) {
|
|
163
|
+
const result = await this.#transport.call("ssh-key rename", [oldName, newName], options, {}, false);
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Generate an API key for the exe.dev HTTPS API or for a specific VM
|
|
168
|
+
*
|
|
169
|
+
* Usage: `ssh-key generate-api-key [--label=NAME] [--vm=VMNAME] [--cmds=CMD1,CMD2] [--exp=30d]`
|
|
170
|
+
*
|
|
171
|
+
* CLI examples:
|
|
172
|
+
* ```
|
|
173
|
+
* # Generate a key for the exe.dev API (lobby commands like ls, new, whoami):
|
|
174
|
+
* ssh-key generate-api-key --label=ci --cmds=ls,new --exp=90d
|
|
175
|
+
*
|
|
176
|
+
* # Generate a key scoped to a VM (authenticates to its HTTPS proxy):
|
|
177
|
+
* ssh-key generate-api-key --vm=my-vm --label=deploy
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* Tag-scoped API keys may run this command.
|
|
181
|
+
*/
|
|
182
|
+
async sshKeyGenerateApiKey(options) {
|
|
183
|
+
const result = await this.#transport.call("ssh-key generate-api-key", [], options, {
|
|
184
|
+
cmds: "string",
|
|
185
|
+
exp: "string",
|
|
186
|
+
label: "string",
|
|
187
|
+
vm: "string",
|
|
188
|
+
}, false);
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Set your preferred region for new VMs.
|
|
193
|
+
*
|
|
194
|
+
* Usage: `set-region <region-code>`
|
|
195
|
+
*/
|
|
196
|
+
async setRegion(regionCode, options) {
|
|
197
|
+
const result = await this.#transport.call("set-region", [regionCode], options, {}, false);
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* List your integrations
|
|
202
|
+
*
|
|
203
|
+
* Usage: `integrations list [--json [--usage]]`
|
|
204
|
+
*
|
|
205
|
+
* Tag-scoped API keys may run this command.
|
|
206
|
+
*/
|
|
207
|
+
async integrationsList(options) {
|
|
208
|
+
const result = await this.#transport.call("integrations list", [], options, {
|
|
209
|
+
usage: "bool",
|
|
210
|
+
}, false);
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Set up GitHub integration
|
|
215
|
+
*
|
|
216
|
+
* Usage: `integrations setup github [--list|--verify|-d]`
|
|
217
|
+
*/
|
|
218
|
+
async integrationsSetupGithub(options) {
|
|
219
|
+
const result = await this.#transport.call("integrations setup github", [], options, {
|
|
220
|
+
d: "bool",
|
|
221
|
+
delete: "bool",
|
|
222
|
+
list: "bool",
|
|
223
|
+
verify: "bool",
|
|
224
|
+
}, false);
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Set up ChatGPT account access for LLM integrations
|
|
229
|
+
*
|
|
230
|
+
* Usage: `integrations setup chatgpt [--name=<account-name>|--list|--verify|-d]`
|
|
231
|
+
*/
|
|
232
|
+
async integrationsSetupChatgpt(options) {
|
|
233
|
+
const result = await this.#transport.call("integrations setup chatgpt", [], options, {
|
|
234
|
+
d: "bool",
|
|
235
|
+
delete: "bool",
|
|
236
|
+
list: "bool",
|
|
237
|
+
name: "string",
|
|
238
|
+
verify: "bool",
|
|
239
|
+
}, false);
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Add a new integration
|
|
244
|
+
*
|
|
245
|
+
* Credential value flags (keys, tokens, passwords, bearer tokens, and webhook URLs) accept - to read from stdin.
|
|
246
|
+
*
|
|
247
|
+
* Usage: `integrations add <type> [--default | --name=<name> [--team] [args...]]`
|
|
248
|
+
*/
|
|
249
|
+
async integrationsAdd(type, options) {
|
|
250
|
+
const result = await this.#transport.call("integrations add", [type], options, {
|
|
251
|
+
"act-as-user": "bool",
|
|
252
|
+
attach: "repeated",
|
|
253
|
+
bearer: "string",
|
|
254
|
+
comment: "string",
|
|
255
|
+
default: "bool",
|
|
256
|
+
fields: "string",
|
|
257
|
+
for: "string",
|
|
258
|
+
header: "repeated",
|
|
259
|
+
"host-key": "repeated",
|
|
260
|
+
name: "string",
|
|
261
|
+
"no-auth": "bool",
|
|
262
|
+
peer: "bool",
|
|
263
|
+
readonly: "bool",
|
|
264
|
+
repository: "string",
|
|
265
|
+
"strip-prefix": "string",
|
|
266
|
+
target: "string",
|
|
267
|
+
team: "bool",
|
|
268
|
+
}, false);
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Remove an integration
|
|
273
|
+
*
|
|
274
|
+
* Usage: `integrations remove <name> [--team]`
|
|
275
|
+
*/
|
|
276
|
+
async integrationsRemove(name, options) {
|
|
277
|
+
const result = await this.#transport.call("integrations remove", [name], options, {
|
|
278
|
+
team: "bool",
|
|
279
|
+
}, false);
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Test an integration's credential (connection check)
|
|
284
|
+
*
|
|
285
|
+
* Usage: `integrations test <name> [--team]`
|
|
286
|
+
*/
|
|
287
|
+
async integrationsTest(name, options) {
|
|
288
|
+
const result = await this.#transport.call("integrations test", [name], options, {
|
|
289
|
+
team: "bool",
|
|
290
|
+
}, false);
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Edit an integration
|
|
295
|
+
*
|
|
296
|
+
* Credential value flags (keys, tokens, passwords, bearer tokens, and webhook URLs) accept - to read from stdin.
|
|
297
|
+
*
|
|
298
|
+
* Usage: `integrations edit <name> [--team] [args...]`
|
|
299
|
+
*/
|
|
300
|
+
async integrationsEdit(name, args, options) {
|
|
301
|
+
const result = await this.#transport.call("integrations edit", [name, args], options, {
|
|
302
|
+
"act-as-user": "bool",
|
|
303
|
+
bearer: "string",
|
|
304
|
+
"clear-header": "bool",
|
|
305
|
+
comment: "string",
|
|
306
|
+
fields: "string",
|
|
307
|
+
header: "repeated",
|
|
308
|
+
"host-key": "repeated",
|
|
309
|
+
"no-auth": "bool",
|
|
310
|
+
readonly: "bool",
|
|
311
|
+
repository: "string",
|
|
312
|
+
"strip-prefix": "string",
|
|
313
|
+
target: "string",
|
|
314
|
+
team: "bool",
|
|
315
|
+
"webhook-url": "string",
|
|
316
|
+
}, false);
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Attach an integration to a VM, tag, or all VMs
|
|
321
|
+
*
|
|
322
|
+
* A <spec> controls where the integration is mounted:
|
|
323
|
+
* vm:<vm-name> attach to a specific VM (personal only)
|
|
324
|
+
* tag:<tag-name> attach to every VM with the given tag
|
|
325
|
+
* auto:all attach to all current and future VMs (personal only)
|
|
326
|
+
*
|
|
327
|
+
* You can attach the same integration multiple times with different specs.
|
|
328
|
+
* Team integrations only support tag:<tag-name>.
|
|
329
|
+
*
|
|
330
|
+
* A grant can be time-boxed with --for <duration> or --until <RFC3339>;
|
|
331
|
+
* when it lapses, access stops immediately, with nothing to revoke.
|
|
332
|
+
* Re-attaching the same spec with a new --for/--until extends or shortens it.
|
|
333
|
+
*
|
|
334
|
+
* Usage: `integrations attach <name> <spec> [--team] [--for <duration> | --until <time>]`
|
|
335
|
+
*
|
|
336
|
+
* CLI examples:
|
|
337
|
+
* ```
|
|
338
|
+
* int attach my-mcp vm:dev1
|
|
339
|
+
* int attach my-mcp tag:production
|
|
340
|
+
* int attach my-mcp auto:all
|
|
341
|
+
* int attach shared-mcp tag:production
|
|
342
|
+
* int attach gmail vm:dev1 --for 2h
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
async integrationsAttach(name, spec, options) {
|
|
346
|
+
const result = await this.#transport.call("integrations attach", [name, spec], options, {
|
|
347
|
+
for: "string",
|
|
348
|
+
team: "bool",
|
|
349
|
+
until: "string",
|
|
350
|
+
}, false);
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Detach an integration from a VM, tag, or all VMs
|
|
355
|
+
*
|
|
356
|
+
* Usage: `integrations detach <name> <spec> [--team]`
|
|
357
|
+
*/
|
|
358
|
+
async integrationsDetach(name, spec, options) {
|
|
359
|
+
const result = await this.#transport.call("integrations detach", [name, spec], options, {
|
|
360
|
+
team: "bool",
|
|
361
|
+
}, false);
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Rename an integration
|
|
366
|
+
*
|
|
367
|
+
* Usage: `integrations rename <name> <new-name> [--team]`
|
|
368
|
+
*/
|
|
369
|
+
async integrationsRename(name, newName, options) {
|
|
370
|
+
const result = await this.#transport.call("integrations rename", [name, newName], options, {
|
|
371
|
+
team: "bool",
|
|
372
|
+
}, false);
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Browse the catalog of ready-made service integrations
|
|
377
|
+
*
|
|
378
|
+
* Usage: `integrations catalog [service-or-search-term]`
|
|
379
|
+
*
|
|
380
|
+
* CLI examples:
|
|
381
|
+
* ```
|
|
382
|
+
* int catalog
|
|
383
|
+
* int catalog stripe
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
async integrationsCatalog(serviceOrSearchTerm, options) {
|
|
387
|
+
const result = await this.#transport.call("integrations catalog", [serviceOrSearchTerm], options, {}, false);
|
|
388
|
+
return result;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* View and manage your team
|
|
392
|
+
*/
|
|
393
|
+
async team(options) {
|
|
394
|
+
const result = await this.#transport.call("team", [], options, {}, false);
|
|
395
|
+
return result;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Disband your team
|
|
399
|
+
*
|
|
400
|
+
* Usage: `team disable`
|
|
401
|
+
*/
|
|
402
|
+
async teamDisable(options) {
|
|
403
|
+
const result = await this.#transport.call("team disable", [], options, {
|
|
404
|
+
yes: "bool",
|
|
405
|
+
}, false);
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* List team members
|
|
410
|
+
*
|
|
411
|
+
* Usage: `team members`
|
|
412
|
+
*/
|
|
413
|
+
async teamMembers(options) {
|
|
414
|
+
const result = await this.#transport.call("team members", [], options, {}, false);
|
|
415
|
+
return result;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Show team pool, disk, and bandwidth usage for the billing period
|
|
419
|
+
*
|
|
420
|
+
* Usage: `team usage`
|
|
421
|
+
*/
|
|
422
|
+
async teamUsage(options) {
|
|
423
|
+
const result = await this.#transport.call("team usage", [], options, {}, false);
|
|
424
|
+
return result;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Add a user to the team
|
|
428
|
+
*
|
|
429
|
+
* Usage: `team add <email> [<user|admin|billing_owner>]`
|
|
430
|
+
*/
|
|
431
|
+
async teamAdd(email, userOrAdminOrBillingOwner, options) {
|
|
432
|
+
const result = await this.#transport.call("team add", [email, userOrAdminOrBillingOwner], options, {}, false);
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Remove a user from the team
|
|
437
|
+
*
|
|
438
|
+
* Usage: `team remove <email> [--transfer-vms-to <email>]`
|
|
439
|
+
*/
|
|
440
|
+
async teamRemove(email, options) {
|
|
441
|
+
const result = await this.#transport.call("team remove", [email], options, {
|
|
442
|
+
"transfer-vms-to": "string",
|
|
443
|
+
}, false);
|
|
444
|
+
return result;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Change a team member's role
|
|
448
|
+
*
|
|
449
|
+
* Usage: `team role <email> <user|admin|billing_owner>`
|
|
450
|
+
*/
|
|
451
|
+
async teamRole(email, userOrAdminOrBillingOwner, options) {
|
|
452
|
+
const result = await this.#transport.call("team role", [email, userOrAdminOrBillingOwner], options, {}, false);
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Rename your team
|
|
457
|
+
*
|
|
458
|
+
* Usage: `team rename <name>`
|
|
459
|
+
*/
|
|
460
|
+
async teamRename(name, options) {
|
|
461
|
+
const result = await this.#transport.call("team rename", [name], options, {}, false);
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Show your team's plan
|
|
466
|
+
*
|
|
467
|
+
* Usage: `team billing plan [--all]`
|
|
468
|
+
*
|
|
469
|
+
* CLI examples:
|
|
470
|
+
* ```
|
|
471
|
+
* team billing plan
|
|
472
|
+
* team billing plan --all # plans your team can switch to
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
475
|
+
async teamBillingPlan(options) {
|
|
476
|
+
const result = await this.#transport.call("team billing plan", [], options, {
|
|
477
|
+
all: "bool",
|
|
478
|
+
}, false);
|
|
479
|
+
return result;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Update team billing information
|
|
483
|
+
*
|
|
484
|
+
* Usage: `team billing update [--email=<email>] [--name=<name>] [--business-name=<name>] [--phone=<phone>] [--address-line1=<line>] [--address-line2=<line>] [--address-city=<city>] [--address-state=<state>] [--address-postal-code=<code>] [--address-country=<country>] [--tax-id-type=<type>] [--tax-id-value=<value>]`
|
|
485
|
+
*/
|
|
486
|
+
async teamBillingUpdate(options) {
|
|
487
|
+
const result = await this.#transport.call("team billing update", [], options, {
|
|
488
|
+
"address-city": "string",
|
|
489
|
+
"address-country": "string",
|
|
490
|
+
"address-line1": "string",
|
|
491
|
+
"address-line2": "string",
|
|
492
|
+
"address-postal-code": "string",
|
|
493
|
+
"address-state": "string",
|
|
494
|
+
"business-name": "string",
|
|
495
|
+
email: "string",
|
|
496
|
+
name: "string",
|
|
497
|
+
phone: "string",
|
|
498
|
+
"tax-id-type": "string",
|
|
499
|
+
"tax-id-value": "string",
|
|
500
|
+
}, false);
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Transfer a VM to another team member
|
|
505
|
+
*
|
|
506
|
+
* Usage: `team transfer <vm_name> <target_email>`
|
|
507
|
+
*/
|
|
508
|
+
async teamTransfer(vmName, targetEmail, options) {
|
|
509
|
+
const result = await this.#transport.call("team transfer", [vmName, targetEmail], options, {}, false);
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* View and manage team auth settings
|
|
514
|
+
*
|
|
515
|
+
* Usage: `team auth`
|
|
516
|
+
*/
|
|
517
|
+
async teamAuth(options) {
|
|
518
|
+
const result = await this.#transport.call("team auth", [], options, {}, false);
|
|
519
|
+
return result;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Require OIDC for web login (web|off)
|
|
523
|
+
*
|
|
524
|
+
* Usage: `team auth require-oidc <web|off>`
|
|
525
|
+
*/
|
|
526
|
+
async teamAuthRequireOidc(webOrOff, options) {
|
|
527
|
+
const result = await this.#transport.call("team auth require-oidc", [webOrOff], options, {}, false);
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Set the team auth provider (default, google, oidc)
|
|
532
|
+
*
|
|
533
|
+
* Usage: `team auth set <default|google|oidc> [--issuer-url=<url> --client-id=<id> --client-secret=<secret>]`
|
|
534
|
+
*/
|
|
535
|
+
async teamAuthSet(defaultOrGoogleOrOidc, options) {
|
|
536
|
+
const result = await this.#transport.call("team auth set", [defaultOrGoogleOrOidc], options, {
|
|
537
|
+
"client-id": "string",
|
|
538
|
+
"client-secret": "string",
|
|
539
|
+
"display-name": "string",
|
|
540
|
+
"issuer-url": "string",
|
|
541
|
+
}, false);
|
|
542
|
+
return result;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* View and manage team settings
|
|
546
|
+
*
|
|
547
|
+
* Usage: `team settings`
|
|
548
|
+
*/
|
|
549
|
+
async teamSettings(options) {
|
|
550
|
+
const result = await this.#transport.call("team settings", [], options, {}, false);
|
|
551
|
+
return result;
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* View and manage automatic VM placement
|
|
555
|
+
*
|
|
556
|
+
* Usage: `team settings vm-placement`
|
|
557
|
+
*/
|
|
558
|
+
async teamSettingsVmPlacement(options) {
|
|
559
|
+
const result = await this.#transport.call("team settings vm-placement", [], options, {}, false);
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Use ordinary VM placement
|
|
564
|
+
*
|
|
565
|
+
* Usage: `team settings vm-placement default`
|
|
566
|
+
*/
|
|
567
|
+
async teamSettingsVmPlacementDefault(options) {
|
|
568
|
+
const result = await this.#transport.call("team settings vm-placement default", [], options, {}, false);
|
|
569
|
+
return result;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Send bare new commands to a shared team pool
|
|
573
|
+
*
|
|
574
|
+
* Usage: `team settings vm-placement pool <name>`
|
|
575
|
+
*/
|
|
576
|
+
async teamSettingsVmPlacementPool(name, options) {
|
|
577
|
+
const result = await this.#transport.call("team settings vm-placement pool", [name], options, {}, false);
|
|
578
|
+
return result;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Create or reuse one team pool per member for bare new commands
|
|
582
|
+
*
|
|
583
|
+
* Usage: `team settings vm-placement member-pool --cpus=N [--max-vms=N]`
|
|
584
|
+
*/
|
|
585
|
+
async teamSettingsVmPlacementMemberPool(options) {
|
|
586
|
+
const result = await this.#transport.call("team settings vm-placement member-pool", [], options, {
|
|
587
|
+
cpus: "number",
|
|
588
|
+
"max-vms": "number",
|
|
589
|
+
}, false);
|
|
590
|
+
return result;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Keep bare new commands outside pools while migrating (legacy)
|
|
594
|
+
*
|
|
595
|
+
* Usage: `team settings vm-placement poolless`
|
|
596
|
+
*/
|
|
597
|
+
async teamSettingsVmPlacementPoolless(options) {
|
|
598
|
+
const result = await this.#transport.call("team settings vm-placement poolless", [], options, {}, false);
|
|
599
|
+
return result;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Set who can create standalone VMs
|
|
603
|
+
*
|
|
604
|
+
* Usage: `team settings standalone <off|admins-only|all-users>`
|
|
605
|
+
*/
|
|
606
|
+
async teamSettingsStandalone(offOrAdminsOnlyOrAllUsers, options) {
|
|
607
|
+
const result = await this.#transport.call("team settings standalone", [offOrAdminsOnlyOrAllUsers], options, {}, false);
|
|
608
|
+
return result;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Allow or block the exe.dev LLM gateway (your own API keys are unaffected)
|
|
612
|
+
*
|
|
613
|
+
* Usage: `team settings llm-gateway <on|off>`
|
|
614
|
+
*/
|
|
615
|
+
async teamSettingsLlmGateway(onOrOff, options) {
|
|
616
|
+
const result = await this.#transport.call("team settings llm-gateway", [onOrOff], options, {}, false);
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Allow team VMs to share CPU cores with each other
|
|
621
|
+
*
|
|
622
|
+
* Usage: `team settings core-sharing <on|off>`
|
|
623
|
+
*/
|
|
624
|
+
async teamSettingsCoreSharing(onOrOff, options) {
|
|
625
|
+
const result = await this.#transport.call("team settings core-sharing", [onOrOff], options, {}, false);
|
|
626
|
+
return result;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Set who can share team VMs
|
|
630
|
+
*
|
|
631
|
+
* Usage: `team settings vm-sharing <admins-only|all-members>`
|
|
632
|
+
*/
|
|
633
|
+
async teamSettingsVmSharing(adminsOnlyOrAllMembers, options) {
|
|
634
|
+
const result = await this.#transport.call("team settings vm-sharing", [adminsOnlyOrAllMembers], options, {}, false);
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Set how long members stay signed in on the web and mobile apps
|
|
639
|
+
*
|
|
640
|
+
* Usage: `team settings session-length <length>`
|
|
641
|
+
*
|
|
642
|
+
* CLI examples:
|
|
643
|
+
* ```
|
|
644
|
+
* team settings session-length 1d
|
|
645
|
+
* team settings session-length default
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
648
|
+
async teamSettingsSessionLength(length, options) {
|
|
649
|
+
const result = await this.#transport.call("team settings session-length", [length], options, {}, false);
|
|
650
|
+
return result;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Allow users from your email domain to join this team on signup
|
|
654
|
+
*
|
|
655
|
+
* Usage: `team settings auto-join <on|off>`
|
|
656
|
+
*/
|
|
657
|
+
async teamSettingsAutoJoin(onOrOff, options) {
|
|
658
|
+
const result = await this.#transport.call("team settings auto-join", [onOrOff], options, {}, false);
|
|
659
|
+
return result;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* List all VMs across your team
|
|
663
|
+
*
|
|
664
|
+
* Usage: `team vm ls [-l] [--group=tag|region|type|user|access] [name|pattern]`
|
|
665
|
+
*
|
|
666
|
+
* Tag-scoped API keys may run this command.
|
|
667
|
+
*/
|
|
668
|
+
async teamVmLs(nameOrPattern, options) {
|
|
669
|
+
const result = await this.#transport.call("team vm ls", [nameOrPattern], options, {
|
|
670
|
+
group: "string",
|
|
671
|
+
l: "bool",
|
|
672
|
+
}, false);
|
|
673
|
+
return result;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Create a pool: reserved capacity for your team's VMs
|
|
677
|
+
*
|
|
678
|
+
* Usage: `pool new <name> --cpus=N [--region=<region>] [--max-vms=M]`
|
|
679
|
+
*/
|
|
680
|
+
async poolNew(name, options) {
|
|
681
|
+
const result = await this.#transport.call("pool new", [name], options, {
|
|
682
|
+
cpus: "number",
|
|
683
|
+
"max-vms": "number",
|
|
684
|
+
region: "string",
|
|
685
|
+
}, false);
|
|
686
|
+
return result;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Show your team's dedicated hosts, where its new pools are placed
|
|
690
|
+
*
|
|
691
|
+
* Usage: `pool hosts`
|
|
692
|
+
*/
|
|
693
|
+
async poolHosts(options) {
|
|
694
|
+
const result = await this.#transport.call("pool hosts", [], options, {}, false);
|
|
695
|
+
return result;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* List your team's pools, or show live or historical usage with --usage
|
|
699
|
+
*
|
|
700
|
+
* Usage: `pool list [pool-name] [--usage [--range=live|24h|7d|30d]]`
|
|
701
|
+
*/
|
|
702
|
+
async poolList(poolName, options) {
|
|
703
|
+
const result = await this.#transport.call("pool list", [poolName], options, {
|
|
704
|
+
range: "string",
|
|
705
|
+
usage: "bool",
|
|
706
|
+
}, false);
|
|
707
|
+
return result;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Adopt a VM into a pool; this can take several minutes
|
|
711
|
+
*
|
|
712
|
+
* Usage: `pool adopt --vm=<vm-name> --pool=<pool-name>`
|
|
713
|
+
*
|
|
714
|
+
* CLI examples:
|
|
715
|
+
* ```
|
|
716
|
+
* pool adopt --vm=builder --pool=compile
|
|
717
|
+
* ```
|
|
718
|
+
*/
|
|
719
|
+
async poolAdopt(options) {
|
|
720
|
+
const result = await this.#transport.call("pool adopt", [], options, {
|
|
721
|
+
pool: "string",
|
|
722
|
+
vm: "string",
|
|
723
|
+
}, false);
|
|
724
|
+
return result;
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Detach a VM from its pool into its own standalone capacity (--poolless leaves it outside any pool)
|
|
728
|
+
*
|
|
729
|
+
* Usage: `pool detach --vm=<vm-name> [--poolless]`
|
|
730
|
+
*
|
|
731
|
+
* CLI examples:
|
|
732
|
+
* ```
|
|
733
|
+
* pool detach --vm=builder
|
|
734
|
+
* pool detach --vm=builder --poolless
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
async poolDetach(options) {
|
|
738
|
+
const result = await this.#transport.call("pool detach", [], options, {
|
|
739
|
+
poolless: "bool",
|
|
740
|
+
vm: "string",
|
|
741
|
+
}, false);
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Change a pool's CPU capacity or VM cap
|
|
746
|
+
*
|
|
747
|
+
* Usage: `pool resize <name> --cpus=N | pool resize <name> --max-vms=N [--force]`
|
|
748
|
+
*/
|
|
749
|
+
async poolResize(args, options) {
|
|
750
|
+
const result = await this.#transport.call("pool resize", [args], options, {
|
|
751
|
+
cpus: "number",
|
|
752
|
+
force: "bool",
|
|
753
|
+
"max-vms": "string",
|
|
754
|
+
}, false);
|
|
755
|
+
return result;
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Rename a pool without changing its capacity or VMs
|
|
759
|
+
*
|
|
760
|
+
* Usage: `pool rename <old-name> <new-name>`
|
|
761
|
+
*/
|
|
762
|
+
async poolRename(oldName, newName, options) {
|
|
763
|
+
const result = await this.#transport.call("pool rename", [oldName, newName], options, {}, false);
|
|
764
|
+
return result;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Delete a pool (refused while it has VMs; --force detaches them)
|
|
768
|
+
*
|
|
769
|
+
* Usage: `pool delete <name> [--force]`
|
|
770
|
+
*/
|
|
771
|
+
async poolDelete(name, options) {
|
|
772
|
+
const result = await this.#transport.call("pool delete", [name], options, {}, false);
|
|
773
|
+
return result;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Show your current plan and resource limits
|
|
777
|
+
*
|
|
778
|
+
* Usage: `billing plan [--all]`
|
|
779
|
+
*
|
|
780
|
+
* CLI examples:
|
|
781
|
+
* ```
|
|
782
|
+
* billing plan
|
|
783
|
+
* billing plan --all # plans you can switch to
|
|
784
|
+
* ```
|
|
785
|
+
*/
|
|
786
|
+
async billingPlan(options) {
|
|
787
|
+
const result = await this.#transport.call("billing plan", [], options, {
|
|
788
|
+
all: "bool",
|
|
789
|
+
}, false);
|
|
790
|
+
return result;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Show VM resource usage against your plan quotas
|
|
794
|
+
*
|
|
795
|
+
* Usage: `billing usage [--range=cycle|24h|7d|30d] [--group=vm]`
|
|
796
|
+
*
|
|
797
|
+
* CLI examples:
|
|
798
|
+
* ```
|
|
799
|
+
* billing usage --range=7d
|
|
800
|
+
* billing credits usage # Shelley/LLM credit spend instead
|
|
801
|
+
* ```
|
|
802
|
+
*/
|
|
803
|
+
async billingUsage(options) {
|
|
804
|
+
const result = await this.#transport.call("billing usage", [], options, {
|
|
805
|
+
group: "string",
|
|
806
|
+
range: "string",
|
|
807
|
+
}, false);
|
|
808
|
+
return result;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Show Shelley credit balances
|
|
812
|
+
*
|
|
813
|
+
* Usage: `billing credits [usage|transactions|buy]`
|
|
814
|
+
*/
|
|
815
|
+
async billingCredits(options) {
|
|
816
|
+
const result = await this.#transport.call("billing credits", [], options, {}, false);
|
|
817
|
+
return result;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Show Shelley (LLM) credit spend by model, day, or VM
|
|
821
|
+
*
|
|
822
|
+
* Usage: `billing credits usage [--month=YYYY-MM] [--group=model|day|box] [--detail]`
|
|
823
|
+
*
|
|
824
|
+
* CLI examples:
|
|
825
|
+
* ```
|
|
826
|
+
* billing credits usage --group=day
|
|
827
|
+
* billing credits usage --group=box --detail
|
|
828
|
+
* billing credits usage --month=2026-05 --group=box
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
async billingCreditsUsage(options) {
|
|
832
|
+
const result = await this.#transport.call("billing credits usage", [], options, {
|
|
833
|
+
detail: "bool",
|
|
834
|
+
group: "string",
|
|
835
|
+
month: "string",
|
|
836
|
+
}, false);
|
|
837
|
+
return result;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Show your credit purchases and gifts
|
|
841
|
+
*
|
|
842
|
+
* Usage: `billing credits transactions [--limit=N]`
|
|
843
|
+
*/
|
|
844
|
+
async billingCreditsTransactions(options) {
|
|
845
|
+
const result = await this.#transport.call("billing credits transactions", [], options, {
|
|
846
|
+
limit: "string",
|
|
847
|
+
}, false);
|
|
848
|
+
return result;
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Buy Shelley credits with your personal payment method
|
|
852
|
+
*
|
|
853
|
+
* Usage: `billing credits buy <dollars> [--yes]`
|
|
854
|
+
*
|
|
855
|
+
* CLI examples:
|
|
856
|
+
* ```
|
|
857
|
+
* billing credits buy 25
|
|
858
|
+
* billing credits buy 100 --yes
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
async billingCreditsBuy(dollars, options) {
|
|
862
|
+
const result = await this.#transport.call("billing credits buy", [dollars], options, {
|
|
863
|
+
"idempotency-key": "string",
|
|
864
|
+
yes: "bool",
|
|
865
|
+
}, false);
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Show invite rewards you've earned
|
|
870
|
+
*
|
|
871
|
+
* Usage: `billing rewards`
|
|
872
|
+
*/
|
|
873
|
+
async billingRewards(options) {
|
|
874
|
+
const result = await this.#transport.call("billing rewards", [], options, {}, false);
|
|
875
|
+
return result;
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Change your subscription capacity
|
|
879
|
+
*
|
|
880
|
+
* Usage: `billing capacity [--cpu=N] [--yes]`
|
|
881
|
+
*
|
|
882
|
+
* CLI examples:
|
|
883
|
+
* ```
|
|
884
|
+
* billing capacity
|
|
885
|
+
* billing capacity --cpu=4 --yes
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
888
|
+
async billingCapacity(options) {
|
|
889
|
+
const result = await this.#transport.call("billing capacity", [], options, {
|
|
890
|
+
cpu: "number",
|
|
891
|
+
yes: "bool",
|
|
892
|
+
}, false);
|
|
893
|
+
return result;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Show your payment methods
|
|
897
|
+
*
|
|
898
|
+
* Usage: `billing payment [list]`
|
|
899
|
+
*/
|
|
900
|
+
async billingPayment(options) {
|
|
901
|
+
const result = await this.#transport.call("billing payment", [], options, {}, false);
|
|
902
|
+
return result;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* List all payment methods on file
|
|
906
|
+
*
|
|
907
|
+
* Usage: `billing payment list`
|
|
908
|
+
*/
|
|
909
|
+
async billingPaymentList(options) {
|
|
910
|
+
const result = await this.#transport.call("billing payment list", [], options, {}, false);
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* Remove a saved payment method
|
|
915
|
+
*
|
|
916
|
+
* Usage: `billing payment remove <ref>`
|
|
917
|
+
*
|
|
918
|
+
* CLI examples:
|
|
919
|
+
* ```
|
|
920
|
+
* billing payment remove 4f1c2a9b8d3e
|
|
921
|
+
* ```
|
|
922
|
+
*/
|
|
923
|
+
async billingPaymentRemove(ref, options) {
|
|
924
|
+
const result = await this.#transport.call("billing payment remove", [ref], options, {}, false);
|
|
925
|
+
return result;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Make a saved payment method the default
|
|
929
|
+
*
|
|
930
|
+
* Usage: `billing payment default <ref>`
|
|
931
|
+
*
|
|
932
|
+
* CLI examples:
|
|
933
|
+
* ```
|
|
934
|
+
* billing payment default 4f1c2a9b8d3e
|
|
935
|
+
* ```
|
|
936
|
+
*/
|
|
937
|
+
async billingPaymentDefault(ref, options) {
|
|
938
|
+
const result = await this.#transport.call("billing payment default", [ref], options, {}, false);
|
|
939
|
+
return result;
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Open the billing management page
|
|
943
|
+
*
|
|
944
|
+
* Usage: `billing manage`
|
|
945
|
+
*/
|
|
946
|
+
async billingManage(options) {
|
|
947
|
+
const result = await this.#transport.call("billing manage", [], options, {}, false);
|
|
948
|
+
return result;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Open the personal plan activation page
|
|
952
|
+
*
|
|
953
|
+
* Usage: `billing activate`
|
|
954
|
+
*/
|
|
955
|
+
async billingActivate(options) {
|
|
956
|
+
const result = await this.#transport.call("billing activate", [], options, {}, false);
|
|
957
|
+
return result;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Update your billing contact information
|
|
961
|
+
*
|
|
962
|
+
* Usage: `billing update [--email=<email>] [--name=<name>] [--business-name=<name>] [--phone=<phone>] [--address-line1=<line>] [--address-line2=<line>] [--address-city=<city>] [--address-state=<state>] [--address-postal-code=<code>] [--address-country=<country>] [--tax-id-type=<type>] [--tax-id-value=<value>]`
|
|
963
|
+
*/
|
|
964
|
+
async billingUpdate(options) {
|
|
965
|
+
const result = await this.#transport.call("billing update", [], options, {
|
|
966
|
+
"address-city": "string",
|
|
967
|
+
"address-country": "string",
|
|
968
|
+
"address-line1": "string",
|
|
969
|
+
"address-line2": "string",
|
|
970
|
+
"address-postal-code": "string",
|
|
971
|
+
"address-state": "string",
|
|
972
|
+
"business-name": "string",
|
|
973
|
+
email: "string",
|
|
974
|
+
name: "string",
|
|
975
|
+
phone: "string",
|
|
976
|
+
"tax-id-type": "string",
|
|
977
|
+
"tax-id-value": "string",
|
|
978
|
+
}, false);
|
|
979
|
+
return result;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Show recent invoices
|
|
983
|
+
*
|
|
984
|
+
* Usage: `billing invoices`
|
|
985
|
+
*/
|
|
986
|
+
async billingInvoices(options) {
|
|
987
|
+
const result = await this.#transport.call("billing invoices", [], options, {}, false);
|
|
988
|
+
return result;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* List invoices for your personal or team account
|
|
992
|
+
*
|
|
993
|
+
* Usage: `billing invoices list [--account=personal|team]`
|
|
994
|
+
*
|
|
995
|
+
* CLI examples:
|
|
996
|
+
* ```
|
|
997
|
+
* billing invoices list --account=team
|
|
998
|
+
* ```
|
|
999
|
+
*/
|
|
1000
|
+
async billingInvoicesList(options) {
|
|
1001
|
+
const result = await this.#transport.call("billing invoices list", [], options, {
|
|
1002
|
+
account: "string",
|
|
1003
|
+
}, false);
|
|
1004
|
+
return result;
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Show one invoice with its usage breakdown
|
|
1008
|
+
*
|
|
1009
|
+
* Usage: `billing invoices show <id> [--vms]`
|
|
1010
|
+
*
|
|
1011
|
+
* CLI examples:
|
|
1012
|
+
* ```
|
|
1013
|
+
* billing invoices show in_1Abc --vms
|
|
1014
|
+
* ```
|
|
1015
|
+
*/
|
|
1016
|
+
async billingInvoicesShow(id, options) {
|
|
1017
|
+
const result = await this.#transport.call("billing invoices show", [id], options, {
|
|
1018
|
+
vms: "bool",
|
|
1019
|
+
}, false);
|
|
1020
|
+
return result;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Show credit purchase receipts and purchases (this billing account only)
|
|
1024
|
+
*
|
|
1025
|
+
* Usage: `billing receipts [--from=<YYYY-MM-DD>] [--to=<YYYY-MM-DD>]`
|
|
1026
|
+
*
|
|
1027
|
+
* CLI examples:
|
|
1028
|
+
* ```
|
|
1029
|
+
* billing receipts --from=2026-01-01 --to=2026-06-30
|
|
1030
|
+
* ```
|
|
1031
|
+
*/
|
|
1032
|
+
async billingReceipts(options) {
|
|
1033
|
+
const result = await this.#transport.call("billing receipts", [], options, {
|
|
1034
|
+
from: "string",
|
|
1035
|
+
to: "string",
|
|
1036
|
+
}, false);
|
|
1037
|
+
return result;
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Open a consolidated credit purchase statement
|
|
1041
|
+
*
|
|
1042
|
+
* Usage: `billing statement [--from=<YYYY-MM-DD>] [--to=<YYYY-MM-DD>]`
|
|
1043
|
+
*
|
|
1044
|
+
* CLI examples:
|
|
1045
|
+
* ```
|
|
1046
|
+
* billing statement --from=2026-01-01 --to=2026-06-30
|
|
1047
|
+
* ```
|
|
1048
|
+
*/
|
|
1049
|
+
async billingStatement(options) {
|
|
1050
|
+
const result = await this.#transport.call("billing statement", [], options, {
|
|
1051
|
+
from: "string",
|
|
1052
|
+
to: "string",
|
|
1053
|
+
}, false);
|
|
1054
|
+
return result;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Connect a marketplace subscription to your team
|
|
1058
|
+
*
|
|
1059
|
+
* Usage: `billing provider link <aws|azure> --token=<link-token> [--size=<team-size>] [--team-name=<name>]`
|
|
1060
|
+
*/
|
|
1061
|
+
async billingProviderLink(awsOrAzure, options) {
|
|
1062
|
+
const result = await this.#transport.call("billing provider link", [awsOrAzure], options, {
|
|
1063
|
+
size: "string",
|
|
1064
|
+
"team-name": "string",
|
|
1065
|
+
token: "string",
|
|
1066
|
+
}, false);
|
|
1067
|
+
return result;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Manage your invite link and rewards
|
|
1071
|
+
*/
|
|
1072
|
+
async invite(options) {
|
|
1073
|
+
const result = await this.#transport.call("invite", [], options, {}, false);
|
|
1074
|
+
return result;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Show your active invite link and reward
|
|
1078
|
+
*
|
|
1079
|
+
* Usage: `invite show`
|
|
1080
|
+
*/
|
|
1081
|
+
async inviteShow(options) {
|
|
1082
|
+
const result = await this.#transport.call("invite show", [], options, {}, false);
|
|
1083
|
+
return result;
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Print only your active invite link
|
|
1087
|
+
*
|
|
1088
|
+
* Usage: `invite link`
|
|
1089
|
+
*/
|
|
1090
|
+
async inviteLink(options) {
|
|
1091
|
+
const result = await this.#transport.call("invite link", [], options, {}, false);
|
|
1092
|
+
return result;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* List invite rewards you can use
|
|
1096
|
+
*
|
|
1097
|
+
* Usage: `invite rewards`
|
|
1098
|
+
*/
|
|
1099
|
+
async inviteRewards(options) {
|
|
1100
|
+
const result = await this.#transport.call("invite rewards", [], options, {}, false);
|
|
1101
|
+
return result;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Choose the reward for your invite link
|
|
1105
|
+
*
|
|
1106
|
+
* Usage: `invite set-reward standard|bonus-credits|extra-memory|extra-disk`
|
|
1107
|
+
*/
|
|
1108
|
+
async inviteSetReward(standardOrBonusCreditsOrExtraMemoryOrExtraDisk, options) {
|
|
1109
|
+
const result = await this.#transport.call("invite set-reward", [standardOrBonusCreditsOrExtraMemoryOrExtraDisk], options, {}, false);
|
|
1110
|
+
return result;
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Show signups, upgrades, and reward status
|
|
1114
|
+
*
|
|
1115
|
+
* Usage: `invite activity`
|
|
1116
|
+
*/
|
|
1117
|
+
async inviteActivity(options) {
|
|
1118
|
+
const result = await this.#transport.call("invite activity", [], options, {}, false);
|
|
1119
|
+
return result;
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Request more trial invites
|
|
1123
|
+
*
|
|
1124
|
+
* Usage: `invite request`
|
|
1125
|
+
*/
|
|
1126
|
+
async inviteRequest(options) {
|
|
1127
|
+
const result = await this.#transport.call("invite request", [], options, {}, false);
|
|
1128
|
+
return result;
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Open the invites page
|
|
1132
|
+
*
|
|
1133
|
+
* Usage: `invite manage`
|
|
1134
|
+
*/
|
|
1135
|
+
async inviteManage(options) {
|
|
1136
|
+
const result = await this.#transport.call("invite manage", [], options, {}, false);
|
|
1137
|
+
return result;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Generate a magic link to log in to the website
|
|
1141
|
+
*
|
|
1142
|
+
* Usage: `browser`
|
|
1143
|
+
*/
|
|
1144
|
+
async browser(options) {
|
|
1145
|
+
const result = await this.#transport.call("browser", [], options, {
|
|
1146
|
+
qr: "bool",
|
|
1147
|
+
}, false);
|
|
1148
|
+
return result;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
/** A VM reference. info is a snapshot; refresh() fetches current metadata. */
|
|
1152
|
+
export class VM {
|
|
1153
|
+
#transport;
|
|
1154
|
+
#info;
|
|
1155
|
+
/** @internal Obtain VMs through exe.new(), exe.ls(), exe.vm(), or vm.cp(). */
|
|
1156
|
+
constructor(transport, info) {
|
|
1157
|
+
this.#transport = transport;
|
|
1158
|
+
this.#info = Object.freeze({ ...info, tags: Object.freeze([...info.tags]) });
|
|
1159
|
+
}
|
|
1160
|
+
get info() { return this.#info; }
|
|
1161
|
+
get name() { return this.#info.name; }
|
|
1162
|
+
get httpsUrl() { return this.#info.httpsUrl; }
|
|
1163
|
+
get sshDest() { return this.#info.sshDest; }
|
|
1164
|
+
get tags() { return this.#info.tags; }
|
|
1165
|
+
/** Run a shell command once. Nonzero exit codes are results, not exceptions. */
|
|
1166
|
+
ssh(command, options) {
|
|
1167
|
+
return this.#transport.ssh(this.name, command, options);
|
|
1168
|
+
}
|
|
1169
|
+
/** Refresh metadata without changing this reference's identity. Requires ls permission. */
|
|
1170
|
+
async refresh(options) {
|
|
1171
|
+
const result = await this.#transport.call("ls", [this.name], options, {}, true);
|
|
1172
|
+
const vm = listVMs(this.#transport, result).find((vm) => vm.name === this.name);
|
|
1173
|
+
if (!vm)
|
|
1174
|
+
throw new ExeAPIError("ls", 404, "VM not found");
|
|
1175
|
+
this.#info = vm.info;
|
|
1176
|
+
return this;
|
|
1177
|
+
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Probe SSH with `true` until it exits successfully. Never reruns a user command.
|
|
1180
|
+
* The default deadline is 60 seconds, including requests and backoff. This does
|
|
1181
|
+
* not wait for application servers or setup scripts. Requires ssh permission.
|
|
1182
|
+
*/
|
|
1183
|
+
async waitUntilReady(options = {}) {
|
|
1184
|
+
const timeoutMs = readyTimeout(options.timeoutMs);
|
|
1185
|
+
options.signal?.throwIfAborted();
|
|
1186
|
+
const controller = new AbortController();
|
|
1187
|
+
const abort = () => controller.abort(options.signal.reason);
|
|
1188
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
1189
|
+
const timer = setTimeout(() => controller.abort(new DOMException("SSH readiness timed out", "TimeoutError")), timeoutMs);
|
|
1190
|
+
let backoff = 100;
|
|
1191
|
+
try {
|
|
1192
|
+
while (true) {
|
|
1193
|
+
try {
|
|
1194
|
+
const result = await abortable(this.ssh("true", { signal: controller.signal, capture: false }), controller.signal);
|
|
1195
|
+
controller.signal.throwIfAborted();
|
|
1196
|
+
if (result.exitCode !== 0)
|
|
1197
|
+
throw new ExeProtocolError("ssh readiness probe");
|
|
1198
|
+
return this;
|
|
1199
|
+
}
|
|
1200
|
+
catch (err) {
|
|
1201
|
+
controller.signal.throwIfAborted();
|
|
1202
|
+
// /exec reports these failures before a remote command starts. Other
|
|
1203
|
+
// rejections (not found, permissions, no SSH configured) fail fast.
|
|
1204
|
+
if (!(err instanceof ExeAPIError) || err.status !== 422 ||
|
|
1205
|
+
!/failed to (?:connect|dial|create session|run command on VM)/i.test(err.details().body))
|
|
1206
|
+
throw err;
|
|
1207
|
+
}
|
|
1208
|
+
await delay(backoff, controller.signal);
|
|
1209
|
+
backoff = Math.min(backoff * 2, 1000);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
catch (err) {
|
|
1213
|
+
options.signal?.throwIfAborted();
|
|
1214
|
+
throw new VMReadyError(this, err);
|
|
1215
|
+
}
|
|
1216
|
+
finally {
|
|
1217
|
+
clearTimeout(timer);
|
|
1218
|
+
options.signal?.removeEventListener("abort", abort);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Delete a VM
|
|
1223
|
+
*
|
|
1224
|
+
* Usage: `rm <vmname>...`
|
|
1225
|
+
*
|
|
1226
|
+
* Tag-scoped API keys may run this command.
|
|
1227
|
+
*/
|
|
1228
|
+
async rm(options) {
|
|
1229
|
+
const result = await this.#transport.call("rm", [this.name], options, {}, true);
|
|
1230
|
+
return result;
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Restart a VM
|
|
1234
|
+
*
|
|
1235
|
+
* Usage: `restart <vmname>`
|
|
1236
|
+
*
|
|
1237
|
+
* Tag-scoped API keys may run this command.
|
|
1238
|
+
*/
|
|
1239
|
+
async restart(options) {
|
|
1240
|
+
const ready = readiness(options ?? {});
|
|
1241
|
+
const { waitUntil, timeoutMs, ...flags } = options ?? {};
|
|
1242
|
+
const result = await this.#transport.call("restart", [this.name], flags, {}, true);
|
|
1243
|
+
if (ready)
|
|
1244
|
+
await this.waitUntilReady(ready);
|
|
1245
|
+
return this;
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Pause a VM (snapshot RAM to disk, free its CPU and memory)
|
|
1249
|
+
*
|
|
1250
|
+
* Usage: `pause <vmname>`
|
|
1251
|
+
*
|
|
1252
|
+
* CLI examples:
|
|
1253
|
+
* ```
|
|
1254
|
+
* pause my-vm # snapshot RAM to disk; resume later with 'resume my-vm'
|
|
1255
|
+
* ```
|
|
1256
|
+
*
|
|
1257
|
+
* Tag-scoped API keys may run this command.
|
|
1258
|
+
*/
|
|
1259
|
+
async pause(options) {
|
|
1260
|
+
const result = await this.#transport.call("pause", [this.name], options, {}, false);
|
|
1261
|
+
return result;
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Resume a paused VM (restore RAM from disk)
|
|
1265
|
+
*
|
|
1266
|
+
* Usage: `resume <vmname>`
|
|
1267
|
+
*
|
|
1268
|
+
* Tag-scoped API keys may run this command.
|
|
1269
|
+
*/
|
|
1270
|
+
async resume(options) {
|
|
1271
|
+
const ready = readiness(options ?? {});
|
|
1272
|
+
const { waitUntil, timeoutMs, ...flags } = options ?? {};
|
|
1273
|
+
const result = await this.#transport.call("resume", [this.name], flags, {}, false);
|
|
1274
|
+
if (ready)
|
|
1275
|
+
await this.waitUntilReady(ready);
|
|
1276
|
+
return this;
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* rename a vm
|
|
1280
|
+
*
|
|
1281
|
+
* Usage: `rename <oldname> <newname>`
|
|
1282
|
+
*
|
|
1283
|
+
* Tag-scoped API keys may run this command.
|
|
1284
|
+
*/
|
|
1285
|
+
async rename(newname, options) {
|
|
1286
|
+
if (newname === this.name)
|
|
1287
|
+
return this;
|
|
1288
|
+
const result = await this.#transport.call("rename", [this.name, newname], options, {}, true);
|
|
1289
|
+
if (result?.new_name !== newname || result?.old_name !== this.name)
|
|
1290
|
+
throw new ExeProtocolError("rename");
|
|
1291
|
+
// Destinations and other metadata may have changed. Do not invent URLs.
|
|
1292
|
+
this.#info = Object.freeze({ name: newname, tags: this.tags });
|
|
1293
|
+
return this;
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Add or remove tags on a VM
|
|
1297
|
+
*
|
|
1298
|
+
* Usage: `tag [-d] <vm> <tag-name> [tag-name...]`
|
|
1299
|
+
*
|
|
1300
|
+
* CLI examples:
|
|
1301
|
+
* ```
|
|
1302
|
+
* tag my-vm prod web # add tags
|
|
1303
|
+
* tag -d my-vm prod web # remove tags
|
|
1304
|
+
* ```
|
|
1305
|
+
*
|
|
1306
|
+
* Tag-scoped API keys may run this command.
|
|
1307
|
+
*/
|
|
1308
|
+
async tag(tagNames, options) {
|
|
1309
|
+
const result = await this.#transport.call("tag", [this.name, tagNames], options, {
|
|
1310
|
+
d: "bool",
|
|
1311
|
+
}, false);
|
|
1312
|
+
return result;
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Copy an existing VM
|
|
1316
|
+
*
|
|
1317
|
+
* Usage: `cp <source-vm> [new-name] [--pool=<name>] [--memory=<size>] [--cpu=<count>] [--disk=<size>]`
|
|
1318
|
+
*
|
|
1319
|
+
* CLI examples:
|
|
1320
|
+
* ```
|
|
1321
|
+
* cp my-vm # copy with auto-generated name
|
|
1322
|
+
* cp my-vm my-vm-copy # copy with specific name
|
|
1323
|
+
* cp my-vm --cpu=4 --memory=16GB # copy with different resources
|
|
1324
|
+
* cp my-vm my-pool-copy --pool=build # copy into a team pool
|
|
1325
|
+
* cp my-vm --copy-tags=false # copy without tags
|
|
1326
|
+
* ```
|
|
1327
|
+
*
|
|
1328
|
+
* Tag-scoped API keys may run this command.
|
|
1329
|
+
*/
|
|
1330
|
+
async cp(options) {
|
|
1331
|
+
const ready = readiness(options ?? {});
|
|
1332
|
+
const { waitUntil, timeoutMs, name, ...flags } = options ?? {};
|
|
1333
|
+
const result = await this.#transport.call("cp", [this.name, name], flags, {
|
|
1334
|
+
"copy-tags": "bool",
|
|
1335
|
+
cpu: "number",
|
|
1336
|
+
disk: "string",
|
|
1337
|
+
memory: "string",
|
|
1338
|
+
pool: "string",
|
|
1339
|
+
sandbox: "bool",
|
|
1340
|
+
standalone: "bool",
|
|
1341
|
+
}, true);
|
|
1342
|
+
const vm = new VM(this.#transport, vmInfo(result, "cp"));
|
|
1343
|
+
if (ready)
|
|
1344
|
+
await vm.waitUntilReady(ready);
|
|
1345
|
+
return vm;
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Resize a VM's resources (memory, CPU, disk)
|
|
1349
|
+
*
|
|
1350
|
+
* Usage: `resize <vmname> [--memory=<size>] [--cpu=<count>] [--disk=<size>]`
|
|
1351
|
+
*
|
|
1352
|
+
* Tag-scoped API keys may run this command.
|
|
1353
|
+
*/
|
|
1354
|
+
async resize(options) {
|
|
1355
|
+
const result = await this.#transport.call("resize", [this.name], options, {
|
|
1356
|
+
cpu: "number",
|
|
1357
|
+
disk: "string",
|
|
1358
|
+
memory: "string",
|
|
1359
|
+
}, false);
|
|
1360
|
+
return result;
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Set or clear a short comment on a VM
|
|
1364
|
+
*
|
|
1365
|
+
* Usage: `comment <hostname> <text>`
|
|
1366
|
+
*
|
|
1367
|
+
* CLI examples:
|
|
1368
|
+
* ```
|
|
1369
|
+
* comment my-vm staging copy
|
|
1370
|
+
* comment my-vm "" # clear the comment
|
|
1371
|
+
* ```
|
|
1372
|
+
*
|
|
1373
|
+
* Tag-scoped API keys may run this command.
|
|
1374
|
+
*/
|
|
1375
|
+
async comment(text, options) {
|
|
1376
|
+
const result = await this.#transport.call("comment", [this.name, text], options, {}, false);
|
|
1377
|
+
return result;
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Link a custom domain to a VM
|
|
1381
|
+
*
|
|
1382
|
+
* Usage: `domain add [--wildcard] <vm> <domain>`
|
|
1383
|
+
*/
|
|
1384
|
+
async domainAdd(domain, options) {
|
|
1385
|
+
const result = await this.#transport.call("domain add", [this.name, domain], options, {
|
|
1386
|
+
wildcard: "bool",
|
|
1387
|
+
}, false);
|
|
1388
|
+
return result;
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Remove a custom domain from a VM
|
|
1392
|
+
*
|
|
1393
|
+
* Usage: `domain rm <vm> <domain>`
|
|
1394
|
+
*/
|
|
1395
|
+
async domainRm(domain, options) {
|
|
1396
|
+
const result = await this.#transport.call("domain rm", [this.name, domain], options, {}, false);
|
|
1397
|
+
return result;
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Show current shares for a VM
|
|
1401
|
+
*
|
|
1402
|
+
* Usage: `share show <vm>`
|
|
1403
|
+
*
|
|
1404
|
+
* Tag-scoped API keys may run this command.
|
|
1405
|
+
*/
|
|
1406
|
+
async shareShow(options) {
|
|
1407
|
+
const result = await this.#transport.call("share show", [this.name], options, {
|
|
1408
|
+
qr: "bool",
|
|
1409
|
+
}, false);
|
|
1410
|
+
return result;
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* Set the HTTP proxy port for a VM
|
|
1414
|
+
*
|
|
1415
|
+
* Usage: `share port <vm> [port]`
|
|
1416
|
+
*
|
|
1417
|
+
* CLI examples:
|
|
1418
|
+
* ```
|
|
1419
|
+
* share port mybox 8080
|
|
1420
|
+
* ```
|
|
1421
|
+
*
|
|
1422
|
+
* Tag-scoped API keys may run this command.
|
|
1423
|
+
*/
|
|
1424
|
+
async sharePort(port, options) {
|
|
1425
|
+
const result = await this.#transport.call("share port", [this.name, port], options, {}, false);
|
|
1426
|
+
return result;
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Make the HTTP proxy publicly accessible
|
|
1430
|
+
*
|
|
1431
|
+
* Usage: `share set-public <vm>`
|
|
1432
|
+
*
|
|
1433
|
+
* Tag-scoped API keys may run this command.
|
|
1434
|
+
*/
|
|
1435
|
+
async shareSetPublic(options) {
|
|
1436
|
+
const result = await this.#transport.call("share set-public", [this.name], options, {}, false);
|
|
1437
|
+
return result;
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Restrict the HTTP proxy to authenticated users
|
|
1441
|
+
*
|
|
1442
|
+
* Usage: `share set-private <vm>`
|
|
1443
|
+
*
|
|
1444
|
+
* Tag-scoped API keys may run this command.
|
|
1445
|
+
*/
|
|
1446
|
+
async shareSetPrivate(options) {
|
|
1447
|
+
const result = await this.#transport.call("share set-private", [this.name], options, {}, false);
|
|
1448
|
+
return result;
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Share VM with a user via email, or grant shell access with --root
|
|
1452
|
+
*
|
|
1453
|
+
* Usage: `share add <vm> <email|team> [--root] [--message='...']`
|
|
1454
|
+
*
|
|
1455
|
+
* CLI examples:
|
|
1456
|
+
* ```
|
|
1457
|
+
* share add mybox user@example.com
|
|
1458
|
+
* share add mybox user@example.com --message='Check this out'
|
|
1459
|
+
* share add mybox team
|
|
1460
|
+
* share add mybox teammate@example.com --root
|
|
1461
|
+
* share add mybox team --root
|
|
1462
|
+
* ```
|
|
1463
|
+
*
|
|
1464
|
+
* Tag-scoped API keys may run this command.
|
|
1465
|
+
*/
|
|
1466
|
+
async shareAdd(emailOrTeam, options) {
|
|
1467
|
+
const result = await this.#transport.call("share add", [this.name, emailOrTeam], options, {
|
|
1468
|
+
message: "string",
|
|
1469
|
+
qr: "bool",
|
|
1470
|
+
root: "bool",
|
|
1471
|
+
}, false);
|
|
1472
|
+
return result;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Revoke a user's access to a VM, or downgrade shell access to web with --root
|
|
1476
|
+
*
|
|
1477
|
+
* Usage: `share remove <vm> <email|team> [--root]`
|
|
1478
|
+
*
|
|
1479
|
+
* CLI examples:
|
|
1480
|
+
* ```
|
|
1481
|
+
* share remove mybox user@example.com
|
|
1482
|
+
* share remove mybox team
|
|
1483
|
+
* share remove mybox teammate@example.com --root
|
|
1484
|
+
* share remove mybox team --root
|
|
1485
|
+
* ```
|
|
1486
|
+
*
|
|
1487
|
+
* Tag-scoped API keys may run this command.
|
|
1488
|
+
*/
|
|
1489
|
+
async shareRemove(emailOrTeam, options) {
|
|
1490
|
+
const result = await this.#transport.call("share remove", [this.name, emailOrTeam], options, {
|
|
1491
|
+
root: "bool",
|
|
1492
|
+
}, false);
|
|
1493
|
+
return result;
|
|
1494
|
+
}
|
|
1495
|
+
/**
|
|
1496
|
+
* Create a shareable link for a VM
|
|
1497
|
+
*
|
|
1498
|
+
* Usage: `share add-link <vm>`
|
|
1499
|
+
*
|
|
1500
|
+
* Tag-scoped API keys may run this command.
|
|
1501
|
+
*/
|
|
1502
|
+
async shareAddLink(options) {
|
|
1503
|
+
const result = await this.#transport.call("share add-link", [this.name], options, {
|
|
1504
|
+
qr: "bool",
|
|
1505
|
+
}, false);
|
|
1506
|
+
return result;
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Revoke a shareable link
|
|
1510
|
+
*
|
|
1511
|
+
* Usage: `share remove-link <vm> <token>`
|
|
1512
|
+
*
|
|
1513
|
+
* Tag-scoped API keys may run this command.
|
|
1514
|
+
*/
|
|
1515
|
+
async shareRemoveLink(token, options) {
|
|
1516
|
+
const result = await this.#transport.call("share remove-link", [this.name, token], options, {}, false);
|
|
1517
|
+
return result;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Enable or disable inbound email for a VM
|
|
1521
|
+
*
|
|
1522
|
+
* Usage: `share receive-email <vm> [on|off] [--reply-policy=all|known|owner|none]`
|
|
1523
|
+
*
|
|
1524
|
+
* CLI examples:
|
|
1525
|
+
* ```
|
|
1526
|
+
* share receive-email mybox on
|
|
1527
|
+
* share receive-email mybox off
|
|
1528
|
+
* share receive-email mybox --reply-policy=known
|
|
1529
|
+
* share receive-email mybox
|
|
1530
|
+
* ```
|
|
1531
|
+
*
|
|
1532
|
+
* Tag-scoped API keys may run this command.
|
|
1533
|
+
*/
|
|
1534
|
+
async shareReceiveEmail(onOrOff, options) {
|
|
1535
|
+
const result = await this.#transport.call("share receive-email", [this.name, onOrOff], options, {
|
|
1536
|
+
"reply-policy": "string",
|
|
1537
|
+
}, false);
|
|
1538
|
+
return result;
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* Install or upgrade Shelley to the current version
|
|
1542
|
+
*
|
|
1543
|
+
* Usage: `shelley install <vm>`
|
|
1544
|
+
*
|
|
1545
|
+
* Tag-scoped API keys may run this command.
|
|
1546
|
+
*/
|
|
1547
|
+
async shelleyInstall(options) {
|
|
1548
|
+
const result = await this.#transport.call("shelley install", [this.name], options, {}, false);
|
|
1549
|
+
return result;
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Allow exe.dev support to log in to a VM
|
|
1553
|
+
*
|
|
1554
|
+
* Usage: `grant-support-root <vmname> on|off`
|
|
1555
|
+
*
|
|
1556
|
+
* Tag-scoped API keys may run this command.
|
|
1557
|
+
*/
|
|
1558
|
+
async grantSupportRoot(onOrOff, options) {
|
|
1559
|
+
const result = await this.#transport.call("grant-support-root", [this.name, onOrOff], options, {}, false);
|
|
1560
|
+
return result;
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Show vCPU, disk, IO, and network (RX/TX) metrics for a VM
|
|
1564
|
+
*
|
|
1565
|
+
* Usage: `stat <vm-name> [--range=24h|7d|30d]`
|
|
1566
|
+
*
|
|
1567
|
+
* CLI examples:
|
|
1568
|
+
* ```
|
|
1569
|
+
* stat my-vm # last 24 hours (default)
|
|
1570
|
+
* stat my-vm --range=7d # last 7 days
|
|
1571
|
+
* stat my-vm --range=30d # last 30 days
|
|
1572
|
+
* ```
|
|
1573
|
+
*
|
|
1574
|
+
* Tag-scoped API keys may run this command.
|
|
1575
|
+
*/
|
|
1576
|
+
async stat(options) {
|
|
1577
|
+
const result = await this.#transport.call("stat", [this.name], options, {
|
|
1578
|
+
range: "string",
|
|
1579
|
+
}, true);
|
|
1580
|
+
return result;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
/** Readiness failed after a VM was obtained/created. The VM is not deleted. */
|
|
1584
|
+
export class VMReadyError extends Error {
|
|
1585
|
+
vm;
|
|
1586
|
+
constructor(vm, cause) {
|
|
1587
|
+
super(`exedev: VM ${vm.name} is not SSH-ready`, { cause });
|
|
1588
|
+
this.vm = vm;
|
|
1589
|
+
this.name = "VMReadyError";
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
function readyTimeout(value = 60_000) {
|
|
1593
|
+
if (!Number.isSafeInteger(value) || value <= 0 || value > 2_147_483_647) {
|
|
1594
|
+
throw new TypeError("exedev: timeoutMs must be a positive integer no greater than 2147483647");
|
|
1595
|
+
}
|
|
1596
|
+
return value;
|
|
1597
|
+
}
|
|
1598
|
+
function readiness(options) {
|
|
1599
|
+
const { waitUntil = "ssh", timeoutMs, signal } = options;
|
|
1600
|
+
readyTimeout(timeoutMs); // Validate before creating/copying/restarting a VM.
|
|
1601
|
+
if (waitUntil !== "ssh" && waitUntil !== "created")
|
|
1602
|
+
throw new TypeError("exedev: waitUntil must be ssh or created");
|
|
1603
|
+
return waitUntil === "ssh" ? { timeoutMs, signal } : undefined;
|
|
1604
|
+
}
|
|
1605
|
+
function vmInfo(value, operation) {
|
|
1606
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
1607
|
+
throw new ExeProtocolError(operation);
|
|
1608
|
+
const obj = value;
|
|
1609
|
+
const string = (key, required = false) => {
|
|
1610
|
+
const value = obj[key];
|
|
1611
|
+
if (value === undefined && !required)
|
|
1612
|
+
return undefined;
|
|
1613
|
+
if (typeof value !== "string" || required && !value)
|
|
1614
|
+
throw new ExeProtocolError(operation);
|
|
1615
|
+
return value;
|
|
1616
|
+
};
|
|
1617
|
+
const name = string(operation === "cp" ? "name" : "vm_name", true);
|
|
1618
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9-]*$/.test(name))
|
|
1619
|
+
throw new ExeProtocolError(operation);
|
|
1620
|
+
const tags = obj.tags ?? [];
|
|
1621
|
+
if (!Array.isArray(tags) || !tags.every((tag) => typeof tag === "string"))
|
|
1622
|
+
throw new ExeProtocolError(operation);
|
|
1623
|
+
return {
|
|
1624
|
+
name, tags,
|
|
1625
|
+
sshDest: string(operation === "cp" ? "ssh" : "ssh_dest", true),
|
|
1626
|
+
httpsUrl: string("https_url", operation !== "cp"),
|
|
1627
|
+
status: string(operation === "cp" ? "state" : "status"),
|
|
1628
|
+
region: string("region"),
|
|
1629
|
+
comment: string("comment"),
|
|
1630
|
+
createdAt: string("created_at"),
|
|
1631
|
+
setupError: string("error"),
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
function listVMs(transport, value) {
|
|
1635
|
+
if (!value || typeof value !== "object" || !("vms" in value) || !Array.isArray(value.vms)) {
|
|
1636
|
+
throw new ExeProtocolError("ls");
|
|
1637
|
+
}
|
|
1638
|
+
return value.vms.map((row) => new VM(transport, vmInfo(row, "ls")));
|
|
1639
|
+
}
|
|
1640
|
+
//# sourceMappingURL=commands.gen.js.map
|