@skrr-ai/cli 0.1.25 → 0.1.27
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/dist/base-command.js +29 -5
- package/dist/commands/code/install.js +13 -0
- package/dist/commands/harnesses/leases/billing.d.ts +9 -6
- package/dist/commands/harnesses/leases/billing.js +19 -24
- package/dist/commands/machines/dedicated/attach.d.ts +28 -0
- package/dist/commands/machines/dedicated/attach.js +76 -0
- package/dist/commands/machines/dedicated/catalog.d.ts +17 -0
- package/dist/commands/machines/dedicated/catalog.js +75 -0
- package/dist/commands/machines/dedicated/cp.d.ts +22 -0
- package/dist/commands/machines/dedicated/cp.js +76 -0
- package/dist/commands/machines/dedicated/create.d.ts +6 -2
- package/dist/commands/machines/dedicated/create.js +29 -20
- package/dist/commands/machines/dedicated/current.d.ts +19 -0
- package/dist/commands/machines/dedicated/current.js +49 -0
- package/dist/commands/machines/dedicated/destroy.d.ts +6 -2
- package/dist/commands/machines/dedicated/destroy.js +43 -25
- package/dist/commands/machines/dedicated/exec.d.ts +32 -0
- package/dist/commands/machines/dedicated/exec.js +122 -0
- package/dist/commands/machines/dedicated/grow.d.ts +6 -2
- package/dist/commands/machines/dedicated/grow.js +16 -20
- package/dist/commands/machines/dedicated/health-check.d.ts +2 -2
- package/dist/commands/machines/dedicated/health-check.js +18 -15
- package/dist/commands/machines/dedicated/incident-close.d.ts +3 -2
- package/dist/commands/machines/dedicated/incident-close.js +13 -15
- package/dist/commands/machines/dedicated/index.js +39 -16
- package/dist/commands/machines/dedicated/list.d.ts +2 -2
- package/dist/commands/machines/dedicated/list.js +28 -17
- package/dist/commands/machines/dedicated/restart.d.ts +5 -2
- package/dist/commands/machines/dedicated/restart.js +10 -20
- package/dist/commands/machines/dedicated/restore.d.ts +26 -0
- package/dist/commands/machines/dedicated/restore.js +64 -0
- package/dist/commands/machines/dedicated/show.d.ts +2 -2
- package/dist/commands/machines/dedicated/show.js +30 -31
- package/dist/commands/machines/dedicated/sign-in.d.ts +19 -0
- package/dist/commands/machines/dedicated/sign-in.js +49 -0
- package/dist/commands/machines/dedicated/snapshot.d.ts +5 -2
- package/dist/commands/machines/dedicated/snapshot.js +13 -20
- package/dist/commands/machines/dedicated/spending-limit.d.ts +22 -0
- package/dist/commands/machines/dedicated/spending-limit.js +51 -0
- package/dist/commands/machines/dedicated/start.d.ts +5 -2
- package/dist/commands/machines/dedicated/start.js +10 -20
- package/dist/commands/machines/dedicated/stop.d.ts +5 -2
- package/dist/commands/machines/dedicated/stop.js +10 -20
- package/dist/commands/machines/dedicated/terminal.d.ts +22 -0
- package/dist/commands/machines/dedicated/terminal.js +42 -0
- package/dist/commands/tasks/list.js +27 -0
- package/dist/lib/daemonBroker.d.ts +8 -0
- package/dist/lib/daemonBroker.js +2 -2
- package/dist/lib/dedicated-copy.d.ts +22 -0
- package/dist/lib/dedicated-copy.js +115 -0
- package/dist/lib/dedicated-exec.d.ts +80 -0
- package/dist/lib/dedicated-exec.js +271 -0
- package/dist/lib/dedicated-lease-command.d.ts +59 -0
- package/dist/lib/dedicated-lease-command.js +181 -0
- package/dist/lib/dedicated-machines.d.ts +337 -12
- package/dist/lib/dedicated-machines.js +502 -25
- package/dist/lib/dedicated-terminal.d.ts +89 -0
- package/dist/lib/dedicated-terminal.js +275 -0
- package/dist/lib/dedicated-wait.d.ts +72 -0
- package/dist/lib/dedicated-wait.js +195 -0
- package/dist/lib/edge-error-page.d.ts +49 -0
- package/dist/lib/edge-error-page.js +120 -0
- package/dist/lib/harnesses.d.ts +15 -1
- package/dist/lib/harnesses.js +20 -2
- package/dist/lib/hosted-machines.js +7 -0
- package/dist/lib/node-adapter.js +1 -1
- package/dist/lib/sky-code.d.ts +30 -1
- package/dist/lib/sky-code.js +44 -2
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +2 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +10 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +17 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +10 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +16 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +2625 -2608
- package/oclif.manifest.json +27851 -26936
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
|
+
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
6
|
+
const harnesses_1 = require("../../../lib/harnesses");
|
|
7
|
+
/**
|
|
8
|
+
* `skrr machines dedicated current` — which Dedicated Runtime am I running on?
|
|
9
|
+
*
|
|
10
|
+
* An agent working on the machine is the caller most likely to need its own
|
|
11
|
+
* lease — to snapshot before something risky, read the spend against the cap,
|
|
12
|
+
* or stop the machine when the work is done — and nothing in its environment
|
|
13
|
+
* names it. Every lease command also accepts `self`; this prints the answer so a
|
|
14
|
+
* script can hold it.
|
|
15
|
+
*/
|
|
16
|
+
class DedicatedMachinesCurrent extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
17
|
+
static description = 'Show the Dedicated Runtime this command is running on (every lease command also accepts `self`)';
|
|
18
|
+
static examples = [
|
|
19
|
+
'<%= config.bin %> machines dedicated current',
|
|
20
|
+
'<%= config.bin %> machines dedicated current --id',
|
|
21
|
+
'<%= config.bin %> machines dedicated snapshot self --wait',
|
|
22
|
+
];
|
|
23
|
+
static flags = {
|
|
24
|
+
id: core_1.Flags.boolean({ description: 'Print only the lease id', exclusive: ['json'] }),
|
|
25
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
26
|
+
};
|
|
27
|
+
async run() {
|
|
28
|
+
this.requireAuth();
|
|
29
|
+
const { flags } = await this.parse(DedicatedMachinesCurrent);
|
|
30
|
+
const leaseId = await this.resolveLeaseArg(dedicated_lease_command_1.DEDICATED_SELF_LEASE);
|
|
31
|
+
if (flags.id) {
|
|
32
|
+
this.log(leaseId);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(leaseId));
|
|
36
|
+
if (flags.json) {
|
|
37
|
+
this.log(JSON.stringify(response, null, 2));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const lease = response?.lease;
|
|
41
|
+
if (!lease) {
|
|
42
|
+
this.error(`Dedicated Runtime ${leaseId} is not visible to this login.`, { exit: 1 });
|
|
43
|
+
}
|
|
44
|
+
const listed = await this.callDedicated(() => (0, harnesses_1.listHarnesses)());
|
|
45
|
+
for (const line of (0, dedicated_machines_1.describeDedicatedLease)(lease, listed?.harnesses ?? []))
|
|
46
|
+
this.log(line);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.default = DedicatedMachinesCurrent;
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DedicatedMachinesDestroy extends
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
export default class DedicatedMachinesDestroy extends DedicatedLeaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
6
6
|
lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
|
+
wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
12
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
13
|
'retain-storage': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
14
|
'purge-storage': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
16
|
};
|
|
13
17
|
run(): Promise<void>;
|
|
14
18
|
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
5
|
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
6
|
-
class DedicatedMachinesDestroy extends
|
|
7
|
-
static description = 'Destroy a Dedicated Runtime lease. Retention class standard/extended archives the lease and keeps the workspace volume; destroy an archived lease
|
|
6
|
+
class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
7
|
+
static description = 'Destroy a Dedicated Runtime lease. Retention class standard/extended archives the lease and keeps the workspace volume; destroy an archived lease, or pass --purge-storage, to delete it.';
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> machines dedicated destroy <lease-id>',
|
|
10
|
-
'<%= config.bin %> machines dedicated destroy <lease-id> --
|
|
10
|
+
'<%= config.bin %> machines dedicated destroy <lease-id> --retain-storage --wait',
|
|
11
|
+
'<%= config.bin %> machines dedicated destroy <lease-id> --purge-storage --yes --json',
|
|
11
12
|
];
|
|
12
13
|
static args = {
|
|
13
14
|
lease: core_1.Args.string({
|
|
14
|
-
description:
|
|
15
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
15
16
|
required: true,
|
|
16
17
|
ignoreStdin: true,
|
|
17
18
|
}),
|
|
@@ -23,34 +24,51 @@ class DedicatedMachinesDestroy extends base_command_1.BaseCommand {
|
|
|
23
24
|
exclusive: ['purge-storage'],
|
|
24
25
|
}),
|
|
25
26
|
'purge-storage': core_1.Flags.boolean({
|
|
26
|
-
description: '
|
|
27
|
+
description: 'Delete the workspace volume. It can be restored into a new machine for 7 days (`restore`), then every copy is deleted. Asks first unless --yes.',
|
|
27
28
|
exclusive: ['retain-storage'],
|
|
28
29
|
}),
|
|
30
|
+
yes: core_1.Flags.boolean({
|
|
31
|
+
char: 'y',
|
|
32
|
+
description: 'Skip the confirmation a destroy that deletes the workspace asks for',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
...dedicated_lease_command_1.dedicatedWaitFlags,
|
|
29
36
|
};
|
|
30
37
|
async run() {
|
|
31
38
|
this.requireAuth();
|
|
32
39
|
const { args, flags } = await this.parse(DedicatedMachinesDestroy);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.handleApiError(err);
|
|
40
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
41
|
+
// Only a destroy that DELETES the workspace asks, and that is not only
|
|
42
|
+
// `--purge-storage`: the server also purges when the lease is already
|
|
43
|
+
// archived, or when its retention class is `none` (or unset)
|
|
44
|
+
// — `resolveDestroyRetention`. A retained destroy can still be purged later,
|
|
45
|
+
// so it does not ask. This mirrors the server's rule only to decide whether
|
|
46
|
+
// to PROMPT; the server still decides what happens.
|
|
47
|
+
let willPurge = Boolean(flags['purge-storage']);
|
|
48
|
+
if (!willPurge && !flags.yes) {
|
|
49
|
+
const current = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(leaseId, this.scopeFrom(flags)));
|
|
50
|
+
const lease = current?.lease;
|
|
51
|
+
willPurge =
|
|
52
|
+
lease?.state === 'archived' ||
|
|
53
|
+
(!flags['retain-storage'] && (lease?.storage?.retentionClass || 'none') === 'none');
|
|
48
54
|
}
|
|
49
|
-
if (flags.
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
if (willPurge && !flags.yes) {
|
|
56
|
+
if (!process.stdin.isTTY) {
|
|
57
|
+
this.error('This destroy deletes the workspace volume. Pass --yes to confirm when not at a terminal.', { exit: 2 });
|
|
58
|
+
}
|
|
59
|
+
const confirmed = await this.confirm(`Delete the workspace of ${leaseId}? You can restore it into a new machine for 7 days; after that its files, sign-ins and repositories are gone for good. [y/N] `);
|
|
60
|
+
if (!confirmed) {
|
|
61
|
+
this.log('Aborted.');
|
|
62
|
+
this.exit(1);
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
|
-
|
|
65
|
+
let retentionIntent;
|
|
66
|
+
if (flags['purge-storage'])
|
|
67
|
+
retentionIntent = 'purge';
|
|
68
|
+
else if (flags['retain-storage'])
|
|
69
|
+
retentionIntent = 'retain';
|
|
70
|
+
const response = await this.callDedicated(() => (0, dedicated_machines_1.destroyDedicatedRuntime)(leaseId, { ...this.scopeFrom(flags), retentionIntent }));
|
|
71
|
+
await this.reportLeaseAction(response, flags, { kind: 'destroyed' }, 'Destroying');
|
|
54
72
|
}
|
|
55
73
|
}
|
|
56
74
|
exports.default = DedicatedMachinesDestroy;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines dedicated exec` — the Run Command half of EC2 parity.
|
|
4
|
+
*
|
|
5
|
+
* There is deliberately no `shell` beside it. A loop that sends one line at a
|
|
6
|
+
* time through exec is not a terminal: no TTY, no job control, no prompts a
|
|
7
|
+
* program can ask, no state between lines (`cd` does not stick). Hosted
|
|
8
|
+
* Machine's `connect` is that loop and has to say so in its own docs. The honest
|
|
9
|
+
* interactive surface is the terminal in the web app, which runs a real
|
|
10
|
+
* pseudo-terminal on the machine through the same daemon.
|
|
11
|
+
*
|
|
12
|
+
* The command is started and then observed (`lib/dedicated-exec.ts`), so it can
|
|
13
|
+
* run for its whole timeout whatever sits between the CLI and the API.
|
|
14
|
+
*/
|
|
15
|
+
export default class DedicatedMachinesExec extends BaseCommand {
|
|
16
|
+
static description: string;
|
|
17
|
+
static strict: boolean;
|
|
18
|
+
static examples: string[];
|
|
19
|
+
static usage: string;
|
|
20
|
+
static args: {
|
|
21
|
+
id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
22
|
+
};
|
|
23
|
+
static flags: {
|
|
24
|
+
command: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
cwd: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
26
|
+
timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
|
+
'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
28
|
+
workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
29
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
30
|
+
};
|
|
31
|
+
run(): Promise<void>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../../base-command");
|
|
5
|
+
const shell_quote_1 = require("../../../lib/shell-quote");
|
|
6
|
+
const hosted_machines_1 = require("../../../lib/hosted-machines");
|
|
7
|
+
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
8
|
+
const dedicated_exec_1 = require("../../../lib/dedicated-exec");
|
|
9
|
+
const exec_1 = require("../hosted/exec");
|
|
10
|
+
/**
|
|
11
|
+
* `skrr machines dedicated exec` — the Run Command half of EC2 parity.
|
|
12
|
+
*
|
|
13
|
+
* There is deliberately no `shell` beside it. A loop that sends one line at a
|
|
14
|
+
* time through exec is not a terminal: no TTY, no job control, no prompts a
|
|
15
|
+
* program can ask, no state between lines (`cd` does not stick). Hosted
|
|
16
|
+
* Machine's `connect` is that loop and has to say so in its own docs. The honest
|
|
17
|
+
* interactive surface is the terminal in the web app, which runs a real
|
|
18
|
+
* pseudo-terminal on the machine through the same daemon.
|
|
19
|
+
*
|
|
20
|
+
* The command is started and then observed (`lib/dedicated-exec.ts`), so it can
|
|
21
|
+
* run for its whole timeout whatever sits between the CLI and the API.
|
|
22
|
+
*/
|
|
23
|
+
class DedicatedMachinesExec extends base_command_1.BaseCommand {
|
|
24
|
+
static description = 'Run one command on a Dedicated Runtime machine and return its output and exit code';
|
|
25
|
+
static strict = false;
|
|
26
|
+
static examples = [
|
|
27
|
+
'<%= config.bin %> machines dedicated exec <lease-id> -- git -C repos/app status',
|
|
28
|
+
'<%= config.bin %> machines dedicated exec <lease-id> --cwd repos/app --timeout 5m -- npm test',
|
|
29
|
+
'<%= config.bin %> machines dedicated exec <lease-id> --command "ls -la user-data" --json',
|
|
30
|
+
'<%= config.bin %> machines dedicated exec <lease-id> --request-id deploy-42 -- ./deploy.sh',
|
|
31
|
+
];
|
|
32
|
+
static usage = 'machines dedicated exec <lease-id> [flags] -- <command...>';
|
|
33
|
+
static args = {
|
|
34
|
+
id: core_1.Args.string({
|
|
35
|
+
description: 'Dedicated Runtime lease id',
|
|
36
|
+
required: true,
|
|
37
|
+
ignoreStdin: true,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
static flags = {
|
|
41
|
+
command: core_1.Flags.string({
|
|
42
|
+
description: 'Command to run as one shell string, instead of trailing argv',
|
|
43
|
+
}),
|
|
44
|
+
cwd: core_1.Flags.string({
|
|
45
|
+
description: 'Working directory, relative to /workspace (for example repos/app)',
|
|
46
|
+
}),
|
|
47
|
+
timeout: core_1.Flags.string({
|
|
48
|
+
description: `How long to let it run, such as 30s or 5m (default 2m, max ${dedicated_machines_1.DEDICATED_EXEC_MAX_TIMEOUT_MS / 60000}m). The process group is killed at the deadline.`,
|
|
49
|
+
}),
|
|
50
|
+
'request-id': core_1.Flags.string({
|
|
51
|
+
description: 'Idempotency key for this command. Repeating the invocation with the same id returns the run it already started (and its output, for 5 minutes after it ends) instead of running it again. Letters, digits and . _ : / - only.',
|
|
52
|
+
}),
|
|
53
|
+
workspace: core_1.Flags.string({ description: 'Workspace scope' }),
|
|
54
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
55
|
+
};
|
|
56
|
+
async run() {
|
|
57
|
+
this.requireAuth();
|
|
58
|
+
// Same argv contract as `machines hosted exec`: everything after the FIRST
|
|
59
|
+
// `--` is the remote argv, taken from the raw line so a second `--` survives.
|
|
60
|
+
const { head, tail } = (0, exec_1.splitExecArgv)(this.argv);
|
|
61
|
+
const { argv, flags } = await this.parse(DedicatedMachinesExec, head);
|
|
62
|
+
const raw = argv;
|
|
63
|
+
const id = raw[0];
|
|
64
|
+
const command = flags.command || (0, shell_quote_1.shellQuoteArgv)(tail ?? raw.slice(1));
|
|
65
|
+
if (!id) {
|
|
66
|
+
this.error('Lease id is required.', { exit: 2 });
|
|
67
|
+
}
|
|
68
|
+
if (!command.trim()) {
|
|
69
|
+
this.error('Command is required. Use --command or pass it after --.', { exit: 2 });
|
|
70
|
+
}
|
|
71
|
+
const requestId = flags['request-id'];
|
|
72
|
+
if (requestId !== undefined && !dedicated_exec_1.EXEC_REQUEST_ID_PATTERN.test(requestId)) {
|
|
73
|
+
this.error('--request-id must be 1-200 characters of letters, digits and . _ : / - (it is sent as an idempotency key).', { exit: 2 });
|
|
74
|
+
}
|
|
75
|
+
let timeoutMs;
|
|
76
|
+
try {
|
|
77
|
+
timeoutMs = (0, hosted_machines_1.parseDurationMs)(flags.timeout, '--timeout');
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
this.error(err.message, { exit: 2 });
|
|
81
|
+
}
|
|
82
|
+
if (timeoutMs !== undefined && timeoutMs > dedicated_machines_1.DEDICATED_EXEC_MAX_TIMEOUT_MS) {
|
|
83
|
+
this.error(`--timeout is at most ${dedicated_machines_1.DEDICATED_EXEC_MAX_TIMEOUT_MS / 60000}m. For longer work, start it in the background (nohup … &) or give it to an agent.`, { exit: 2 });
|
|
84
|
+
}
|
|
85
|
+
let result;
|
|
86
|
+
try {
|
|
87
|
+
result = await (0, dedicated_exec_1.runDedicatedExec)(id, { command, ...(flags.cwd ? { cwd: flags.cwd } : {}), ...(timeoutMs ? { timeoutMs } : {}) }, { workspaceId: flags.workspace, ...(requestId ? { requestId } : {}) });
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
if (err instanceof dedicated_exec_1.DedicatedExecContactLostError ||
|
|
91
|
+
err instanceof dedicated_exec_1.DedicatedExecStartUnconfirmedError ||
|
|
92
|
+
err instanceof dedicated_exec_1.DedicatedExecIdempotencyUnsupportedError) {
|
|
93
|
+
this.error(err.message, { exit: 1, code: err.code });
|
|
94
|
+
}
|
|
95
|
+
const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
|
|
96
|
+
if (message)
|
|
97
|
+
this.error(message, { exit: 1, code: (0, dedicated_machines_1.dedicatedRuntimeApiErrorCode)(err) });
|
|
98
|
+
this.handleApiError(err);
|
|
99
|
+
}
|
|
100
|
+
if (flags.json) {
|
|
101
|
+
this.log(JSON.stringify(result, null, 2));
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
if (result.stdout)
|
|
105
|
+
process.stdout.write(result.stdout);
|
|
106
|
+
// About the invocation, not the command's output — stderr, so a caller
|
|
107
|
+
// piping stdout reads only what the machine printed.
|
|
108
|
+
if (result.truncated) {
|
|
109
|
+
process.stderr.write(`\n${(0, dedicated_exec_1.describeTruncation)(result)}\n`);
|
|
110
|
+
}
|
|
111
|
+
if (result.timedOut) {
|
|
112
|
+
process.stderr.write(`\n[timed out after ${Math.round(result.durationMs / 1000)}s; the process group was killed]\n`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Mirror the remote exit status so `exec … && next` composes like a local
|
|
116
|
+
// command. A timeout has no status of its own; 124 is what `timeout(1)` uses.
|
|
117
|
+
const exitCode = result.timedOut ? 124 : (result.exitCode ?? 1);
|
|
118
|
+
if (exitCode !== 0)
|
|
119
|
+
this.exit(exitCode);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.default = DedicatedMachinesExec;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DedicatedMachinesGrow extends
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
export default class DedicatedMachinesGrow extends DedicatedLeaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
6
6
|
lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
|
+
wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
12
|
'storage-gb': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
14
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
11
15
|
};
|
|
12
16
|
run(): Promise<void>;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
5
|
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
6
|
-
class DedicatedMachinesGrow extends
|
|
7
|
-
static description = 'Increase Dedicated Runtime workspace storage. Shrink is unsupported.';
|
|
6
|
+
class DedicatedMachinesGrow extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
7
|
+
static description = 'Increase Dedicated Runtime workspace storage. Shrink is unsupported, and growth is permanent for the life of the volume.';
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200',
|
|
10
|
-
'<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200 --json',
|
|
10
|
+
'<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200 --wait --json',
|
|
11
11
|
];
|
|
12
12
|
static args = {
|
|
13
13
|
lease: core_1.Args.string({
|
|
14
|
-
description:
|
|
14
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
15
15
|
required: true,
|
|
16
16
|
ignoreStdin: true,
|
|
17
17
|
}),
|
|
@@ -21,26 +21,22 @@ class DedicatedMachinesGrow extends base_command_1.BaseCommand {
|
|
|
21
21
|
description: 'New workspace size in GiB. Must be larger than the current size.',
|
|
22
22
|
required: true,
|
|
23
23
|
}),
|
|
24
|
+
'request-id': core_1.Flags.string({
|
|
25
|
+
description: 'Idempotency key. Reuse it to safely retry the same grow request.',
|
|
26
|
+
}),
|
|
24
27
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
28
|
+
...dedicated_lease_command_1.dedicatedWaitFlags,
|
|
25
29
|
};
|
|
26
30
|
async run() {
|
|
27
31
|
this.requireAuth();
|
|
28
32
|
const { args, flags } = await this.parse(DedicatedMachinesGrow);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.error(message, { exit: 1 });
|
|
37
|
-
this.handleApiError(err);
|
|
38
|
-
}
|
|
39
|
-
if (flags.json) {
|
|
40
|
-
this.log(JSON.stringify(response, null, 2));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}.`);
|
|
33
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
34
|
+
const response = await this.callDedicated(() => (0, dedicated_machines_1.growDedicatedRuntime)(leaseId, flags['storage-gb'], {
|
|
35
|
+
...this.scopeFrom(flags),
|
|
36
|
+
...(flags['request-id'] ? { requestId: flags['request-id'] } : {}),
|
|
37
|
+
}));
|
|
38
|
+
// A grow never changes the lease state, so --wait watches the size itself.
|
|
39
|
+
await this.reportLeaseAction(response, flags, { kind: 'grown', storageGb: flags['storage-gb'] }, 'Growing');
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
exports.default = DedicatedMachinesGrow;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DedicatedMachinesHealthCheck extends
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
export default class DedicatedMachinesHealthCheck extends DedicatedLeaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
5
|
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
6
|
-
class DedicatedMachinesHealthCheck extends
|
|
7
|
-
static description = '
|
|
6
|
+
class DedicatedMachinesHealthCheck extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
7
|
+
static description = 'Ask the control plane to re-observe a Dedicated Runtime (compute, volume, daemon heartbeat) and print what it found';
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> machines dedicated health-check <lease-id>',
|
|
10
10
|
'<%= config.bin %> machines dedicated health-check <lease-id> --json',
|
|
11
11
|
];
|
|
12
12
|
static args = {
|
|
13
13
|
lease: core_1.Args.string({
|
|
14
|
-
description:
|
|
14
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
15
15
|
required: true,
|
|
16
16
|
ignoreStdin: true,
|
|
17
17
|
}),
|
|
@@ -22,21 +22,24 @@ class DedicatedMachinesHealthCheck extends base_command_1.BaseCommand {
|
|
|
22
22
|
async run() {
|
|
23
23
|
this.requireAuth();
|
|
24
24
|
const { args, flags } = await this.parse(DedicatedMachinesHealthCheck);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
response = await (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'health-check');
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
|
|
31
|
-
if (message)
|
|
32
|
-
this.error(message, { exit: 1 });
|
|
33
|
-
this.handleApiError(err);
|
|
34
|
-
}
|
|
25
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
26
|
+
const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(leaseId, 'health-check', this.scopeFrom(flags)));
|
|
35
27
|
if (flags.json) {
|
|
36
28
|
this.log(JSON.stringify(response, null, 2));
|
|
37
29
|
return;
|
|
38
30
|
}
|
|
39
|
-
|
|
31
|
+
const lease = response?.lease;
|
|
32
|
+
if (!lease) {
|
|
33
|
+
this.log(`Dedicated Runtime ${leaseId} ${(0, dedicated_machines_1.dedicatedLeaseState)(lease)}.`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// A health check exists to answer "can it take work, and if not why" — the
|
|
37
|
+
// one-line state it used to print could not say either.
|
|
38
|
+
for (const line of (0, dedicated_machines_1.describeDedicatedLease)(lease))
|
|
39
|
+
this.log(line);
|
|
40
|
+
if (lease.health?.reasons?.includes('dedicated_runtime_provider_blind')) {
|
|
41
|
+
this.log('\nThe provider could not be read just now. That is not the same as the machine being gone; check again shortly.');
|
|
42
|
+
}
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
exports.default = DedicatedMachinesHealthCheck;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DedicatedMachinesIncidentClose extends
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
export default class DedicatedMachinesIncidentClose extends DedicatedLeaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static args: {
|
|
@@ -7,6 +7,7 @@ export default class DedicatedMachinesIncidentClose extends BaseCommand {
|
|
|
7
7
|
};
|
|
8
8
|
static flags: {
|
|
9
9
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<void>;
|
|
12
13
|
}
|
|
@@ -1,42 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
-
const
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
5
|
const dedicated_machines_1 = require("../../../lib/dedicated-machines");
|
|
6
|
-
class DedicatedMachinesIncidentClose extends
|
|
7
|
-
static description = 'Close a Dedicated Runtime AZ-recovery incident hold. Does not
|
|
6
|
+
class DedicatedMachinesIncidentClose extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
7
|
+
static description = 'Close a Dedicated Runtime AZ-recovery incident hold, releasing the held failed source volume. Does not touch the live workspace.';
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> machines dedicated incident-close <lease-id>',
|
|
10
10
|
'<%= config.bin %> machines dedicated incident-close <lease-id> --json',
|
|
11
11
|
];
|
|
12
12
|
static args = {
|
|
13
13
|
lease: core_1.Args.string({
|
|
14
|
-
description:
|
|
14
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
15
15
|
required: true,
|
|
16
16
|
ignoreStdin: true,
|
|
17
17
|
}),
|
|
18
18
|
};
|
|
19
19
|
static flags = {
|
|
20
20
|
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
21
|
+
'request-id': core_1.Flags.string({
|
|
22
|
+
description: 'Idempotency key. Reuse it to safely retry the same close.',
|
|
23
|
+
}),
|
|
21
24
|
};
|
|
22
25
|
async run() {
|
|
23
26
|
this.requireAuth();
|
|
24
27
|
const { args, flags } = await this.parse(DedicatedMachinesIncidentClose);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
|
|
31
|
-
if (message)
|
|
32
|
-
this.error(message, { exit: 1 });
|
|
33
|
-
this.handleApiError(err);
|
|
34
|
-
}
|
|
28
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
29
|
+
const response = await this.callDedicated(() => (0, dedicated_machines_1.closeDedicatedRuntimeIncidentHold)(leaseId, {
|
|
30
|
+
...this.scopeFrom(flags),
|
|
31
|
+
...(flags['request-id'] ? { requestId: flags['request-id'] } : {}),
|
|
32
|
+
}));
|
|
35
33
|
if (flags.json) {
|
|
36
34
|
this.log(JSON.stringify(response, null, 2));
|
|
37
35
|
return;
|
|
38
36
|
}
|
|
39
|
-
this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}.`);
|
|
37
|
+
this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}; incident hold ${response?.lease?.recovery?.incidentHold?.status ?? 'closed'}.`);
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
exports.default = DedicatedMachinesIncidentClose;
|
|
@@ -9,31 +9,54 @@ class DedicatedMachines extends core_1.Command {
|
|
|
9
9
|
// — was invisible until a restart lost their work.
|
|
10
10
|
static description = 'A private VM with a durable workspace — files survive restart, running processes do not';
|
|
11
11
|
static examples = [
|
|
12
|
+
'<%= config.bin %> machines dedicated catalog',
|
|
13
|
+
'<%= config.bin %> machines dedicated create --name dev-box --size-preset standard --spending-limit-cents 20000 --wait',
|
|
12
14
|
'<%= config.bin %> machines dedicated list',
|
|
13
15
|
'<%= config.bin %> machines dedicated show <lease-id>',
|
|
14
|
-
'<%= config.bin %> machines dedicated
|
|
15
|
-
'<%= config.bin %> machines dedicated
|
|
16
|
-
'<%= config.bin %> machines dedicated
|
|
16
|
+
'<%= config.bin %> machines dedicated snapshot self --wait',
|
|
17
|
+
'<%= config.bin %> machines dedicated attach <lease-id> --agent <agent-id>',
|
|
18
|
+
'<%= config.bin %> machines dedicated terminal <lease-id>',
|
|
19
|
+
'<%= config.bin %> machines dedicated sign-in <lease-id> github',
|
|
20
|
+
'<%= config.bin %> machines dedicated exec <lease-id> -- git -C repos/app status',
|
|
21
|
+
'<%= config.bin %> machines dedicated cp ./notes.md <lease-id>:user-data/notes.md',
|
|
22
|
+
'<%= config.bin %> machines dedicated stop <lease-id> --wait',
|
|
23
|
+
'<%= config.bin %> machines dedicated start <lease-id> --wait',
|
|
17
24
|
'<%= config.bin %> machines dedicated restart <lease-id>',
|
|
18
|
-
'<%= config.bin %> machines dedicated snapshot <lease-id>',
|
|
25
|
+
'<%= config.bin %> machines dedicated snapshot <lease-id> --wait',
|
|
19
26
|
'<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200',
|
|
20
|
-
'<%= config.bin %> machines dedicated
|
|
27
|
+
'<%= config.bin %> machines dedicated spending-limit <lease-id> --cents 30000',
|
|
21
28
|
'<%= config.bin %> machines dedicated health-check <lease-id>',
|
|
29
|
+
'<%= config.bin %> machines dedicated incident-close <lease-id>',
|
|
22
30
|
'<%= config.bin %> machines dedicated destroy <lease-id>',
|
|
23
31
|
];
|
|
24
32
|
async run() {
|
|
33
|
+
const rows = [
|
|
34
|
+
['catalog', 'sizes, storage bounds and prices create accepts'],
|
|
35
|
+
['create', 'request a Dedicated Runtime'],
|
|
36
|
+
['list', 'list Dedicated Runtime leases'],
|
|
37
|
+
['show', 'state, size, spend, health and engines of one lease'],
|
|
38
|
+
['current', 'the lease of the machine this runs on (or pass `self`)'],
|
|
39
|
+
['attach', 'pin an agent so its work runs on the machine'],
|
|
40
|
+
['terminal', 'open an interactive shell on the machine'],
|
|
41
|
+
['sign-in', 'sign in to GitHub CLI, Claude Code or Codex there'],
|
|
42
|
+
['exec', 'run one command; output and exit code'],
|
|
43
|
+
['cp', 'copy a file to or from the machine'],
|
|
44
|
+
['start', 'start a stopped runtime'],
|
|
45
|
+
['stop', 'stop compute and keep the disk'],
|
|
46
|
+
['restart', 'restart the instance; files stay'],
|
|
47
|
+
['snapshot', 'create a recovery point'],
|
|
48
|
+
['grow', 'increase workspace storage; shrink is unsupported'],
|
|
49
|
+
['spending-limit', 'change the monthly spending cap'],
|
|
50
|
+
['health-check', 'probe daemon and disk liveness'],
|
|
51
|
+
['incident-close', 'close AZ-recovery evidence hold'],
|
|
52
|
+
['destroy', 'stop compute; keep or purge the workspace disk'],
|
|
53
|
+
];
|
|
25
54
|
this.log('skrr Dedicated Runtime commands:');
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.log('
|
|
30
|
-
this.log('
|
|
31
|
-
this.log(' skrr machines dedicated restart restart the instance; files stay');
|
|
32
|
-
this.log(' skrr machines dedicated snapshot create a recovery point');
|
|
33
|
-
this.log(' skrr machines dedicated grow increase workspace storage; shrink is unsupported');
|
|
34
|
-
this.log(' skrr machines dedicated incident-close close AZ-recovery evidence hold');
|
|
35
|
-
this.log(' skrr machines dedicated health-check probe daemon and disk liveness');
|
|
36
|
-
this.log(' skrr machines dedicated destroy stop compute; keep or purge the workspace disk');
|
|
55
|
+
for (const [name, summary] of rows) {
|
|
56
|
+
this.log(` skrr machines dedicated ${name.padEnd(15)} ${summary}`);
|
|
57
|
+
}
|
|
58
|
+
this.log('');
|
|
59
|
+
this.log('Lifecycle commands take --wait; every command takes --workspace for a workspace machine.');
|
|
37
60
|
}
|
|
38
61
|
}
|
|
39
62
|
exports.default = DedicatedMachines;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default class DedicatedMachinesList extends
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
export default class DedicatedMachinesList extends DedicatedLeaseCommand {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|