@skrr-ai/cli 0.1.26 → 0.1.28

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.
Files changed (45) hide show
  1. package/dist/base-command.js +25 -0
  2. package/dist/commands/machines/dedicated/attach.js +4 -3
  3. package/dist/commands/machines/dedicated/current.d.ts +19 -0
  4. package/dist/commands/machines/dedicated/current.js +49 -0
  5. package/dist/commands/machines/dedicated/destroy.js +7 -6
  6. package/dist/commands/machines/dedicated/exec.d.ts +4 -0
  7. package/dist/commands/machines/dedicated/exec.js +19 -2
  8. package/dist/commands/machines/dedicated/grow.js +3 -2
  9. package/dist/commands/machines/dedicated/health-check.js +4 -3
  10. package/dist/commands/machines/dedicated/incident-close.js +3 -2
  11. package/dist/commands/machines/dedicated/index.js +2 -0
  12. package/dist/commands/machines/dedicated/restart.js +3 -2
  13. package/dist/commands/machines/dedicated/restore.d.ts +26 -0
  14. package/dist/commands/machines/dedicated/restore.js +64 -0
  15. package/dist/commands/machines/dedicated/show.js +3 -2
  16. package/dist/commands/machines/dedicated/snapshot.js +3 -2
  17. package/dist/commands/machines/dedicated/spending-limit.js +4 -3
  18. package/dist/commands/machines/dedicated/start.js +3 -2
  19. package/dist/commands/machines/dedicated/stop.js +3 -2
  20. package/dist/lib/dedicated-exec.d.ts +80 -0
  21. package/dist/lib/dedicated-exec.js +271 -0
  22. package/dist/lib/dedicated-lease-command.d.ts +9 -0
  23. package/dist/lib/dedicated-lease-command.js +24 -1
  24. package/dist/lib/dedicated-machines.d.ts +90 -1
  25. package/dist/lib/dedicated-machines.js +125 -6
  26. package/dist/lib/edge-error-page.d.ts +49 -0
  27. package/dist/lib/edge-error-page.js +120 -0
  28. package/dist/lib/harnesses.d.ts +9 -1
  29. package/dist/lib/harnesses.js +20 -2
  30. package/dist/lib/hosted-machines.js +7 -0
  31. package/dist/lib/sky-code.js +11 -1
  32. package/dist/node_modules/@skrr-ai/data-provider/index.js +12 -0
  33. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/index.d.ts +1 -1
  34. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/index.js +3 -1
  35. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/loopback-server.js +64 -1
  36. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.d.ts +30 -0
  37. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.js +43 -1
  38. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/index.d.ts +1 -1
  39. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/index.js +1 -1
  40. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/loopback-server.js +64 -1
  41. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.d.ts +30 -0
  42. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.js +41 -0
  43. package/dist/node_modules/@skrr-ai/inference-broker/package.json +1 -1
  44. package/oclif.manifest.json +2928 -2734
  45. package/package.json +1 -1
@@ -38,6 +38,7 @@ const refresh_1 = require("./lib/refresh");
38
38
  const auth_storage_1 = require("./lib/auth-storage");
39
39
  const update_check_1 = require("./lib/update-check");
40
40
  const web_url_1 = require("./lib/web-url");
41
+ const edge_error_page_1 = require("./lib/edge-error-page");
41
42
  const delegated_cli_1 = require("./lib/delegated-cli");
42
43
  const tasks_1 = require("./lib/tasks");
43
44
  function assigneePayloadNeedsResolution(payload) {
@@ -887,6 +888,30 @@ class BaseCommand extends core_1.Command {
887
888
  retryable: true,
888
889
  });
889
890
  }
891
+ else if ((e.status === 403 || e.status === 504) &&
892
+ !body &&
893
+ (0, edge_error_page_1.describeEdgeErrorPage)({ status: e.status, body: e.body, method: e.method })) {
894
+ // An HTML page in place of the API's JSON: the edge answered, not the
895
+ // API (OSK-8700, OSK-8705). A WAF 403 is a content match that the same
896
+ // request will hit again, not "transient" and not a permission; an edge
897
+ // 504 is a request the API may still be carrying out, not proof of an
898
+ // outage. 502/503 pages keep the outage branch below, which is what
899
+ // they usually are and which records the incident.
900
+ const edge = (0, edge_error_page_1.describeEdgeErrorPage)({
901
+ status: e.status,
902
+ body: e.body,
903
+ method: e.method,
904
+ host: this.cliConfig?.baseURL,
905
+ });
906
+ this.failWithCliError({
907
+ message: say(edge.message),
908
+ code: edge.code,
909
+ status: e.status,
910
+ exit: e.status === 403 ? 3 : 5,
911
+ retryable: edge.retryable,
912
+ ...(edge.requestId ? { details: { edgeRequestId: edge.requestId } } : {}),
913
+ });
914
+ }
890
915
  else if (e.status === 403) {
891
916
  // A 403 WITH a body is the API deciding; it says why, and we relay it.
892
917
  //
@@ -30,7 +30,7 @@ class DedicatedMachinesAttach extends dedicated_lease_command_1.DedicatedLeaseCo
30
30
  ];
31
31
  static args = {
32
32
  lease: core_1.Args.string({
33
- description: 'Dedicated Runtime lease id',
33
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
34
34
  required: true,
35
35
  ignoreStdin: true,
36
36
  }),
@@ -50,7 +50,8 @@ class DedicatedMachinesAttach extends dedicated_lease_command_1.DedicatedLeaseCo
50
50
  async run() {
51
51
  this.requireAuth();
52
52
  const { args, flags } = await this.parse(DedicatedMachinesAttach);
53
- const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(args.lease, this.scopeFrom(flags)));
53
+ const leaseId = await this.resolveLeaseArg(args.lease);
54
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(leaseId, this.scopeFrom(flags)));
54
55
  const lease = response?.lease;
55
56
  if (!lease)
56
57
  this.error('Dedicated Runtime lease not found.', { exit: 1 });
@@ -61,7 +62,7 @@ class DedicatedMachinesAttach extends dedicated_lease_command_1.DedicatedLeaseCo
61
62
  }
62
63
  const { harness } = selection;
63
64
  if (!flags.json) {
64
- process.stderr.write(`Attaching ${harness.provider} on ${args.lease} (harness ${harness._id}, ${harness.status || 'status unknown'}).\n` +
65
+ process.stderr.write(`Attaching ${harness.provider} on ${leaseId} (harness ${harness._id}, ${harness.status || 'status unknown'}).\n` +
65
66
  'Everything the agent runs there acts as you: it shares the machine’s sign-ins and your skrr login.\n');
66
67
  }
67
68
  await attach_harness_1.default.run([
@@ -0,0 +1,19 @@
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ /**
3
+ * `skrr machines dedicated current` — which Dedicated Runtime am I running on?
4
+ *
5
+ * An agent working on the machine is the caller most likely to need its own
6
+ * lease — to snapshot before something risky, read the spend against the cap,
7
+ * or stop the machine when the work is done — and nothing in its environment
8
+ * names it. Every lease command also accepts `self`; this prints the answer so a
9
+ * script can hold it.
10
+ */
11
+ export default class DedicatedMachinesCurrent extends DedicatedLeaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ id: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ };
18
+ run(): Promise<void>;
19
+ }
@@ -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;
@@ -12,7 +12,7 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
12
12
  ];
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
- description: 'Dedicated Runtime lease id',
15
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
16
16
  required: true,
17
17
  ignoreStdin: true,
18
18
  }),
@@ -24,7 +24,7 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
24
24
  exclusive: ['purge-storage'],
25
25
  }),
26
26
  'purge-storage': core_1.Flags.boolean({
27
- description: 'Permanently delete the workspace volume. Asks first unless --yes.',
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.',
28
28
  exclusive: ['retain-storage'],
29
29
  }),
30
30
  yes: core_1.Flags.boolean({
@@ -37,6 +37,7 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
37
37
  async run() {
38
38
  this.requireAuth();
39
39
  const { args, flags } = await this.parse(DedicatedMachinesDestroy);
40
+ const leaseId = await this.resolveLeaseArg(args.lease);
40
41
  // Only a destroy that DELETES the workspace asks, and that is not only
41
42
  // `--purge-storage`: the server also purges when the lease is already
42
43
  // archived, or when its retention class is `none` (or unset)
@@ -45,7 +46,7 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
45
46
  // to PROMPT; the server still decides what happens.
46
47
  let willPurge = Boolean(flags['purge-storage']);
47
48
  if (!willPurge && !flags.yes) {
48
- const current = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(args.lease, this.scopeFrom(flags)));
49
+ const current = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(leaseId, this.scopeFrom(flags)));
49
50
  const lease = current?.lease;
50
51
  willPurge =
51
52
  lease?.state === 'archived' ||
@@ -53,9 +54,9 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
53
54
  }
54
55
  if (willPurge && !flags.yes) {
55
56
  if (!process.stdin.isTTY) {
56
- this.error('This destroy deletes the workspace volume permanently. Pass --yes to confirm when not at a terminal.', { exit: 2 });
57
+ this.error('This destroy deletes the workspace volume. Pass --yes to confirm when not at a terminal.', { exit: 2 });
57
58
  }
58
- const confirmed = await this.confirm(`Permanently delete the workspace of ${args.lease}? Files, sign-ins and repositories on it cannot be recovered. [y/N] `);
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] `);
59
60
  if (!confirmed) {
60
61
  this.log('Aborted.');
61
62
  this.exit(1);
@@ -66,7 +67,7 @@ class DedicatedMachinesDestroy extends dedicated_lease_command_1.DedicatedLeaseC
66
67
  retentionIntent = 'purge';
67
68
  else if (flags['retain-storage'])
68
69
  retentionIntent = 'retain';
69
- const response = await this.callDedicated(() => (0, dedicated_machines_1.destroyDedicatedRuntime)(args.lease, { ...this.scopeFrom(flags), retentionIntent }));
70
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.destroyDedicatedRuntime)(leaseId, { ...this.scopeFrom(flags), retentionIntent }));
70
71
  await this.reportLeaseAction(response, flags, { kind: 'destroyed' }, 'Destroying');
71
72
  }
72
73
  }
@@ -8,6 +8,9 @@ import { BaseCommand } from '../../../base-command';
8
8
  * Machine's `connect` is that loop and has to say so in its own docs. The honest
9
9
  * interactive surface is the terminal in the web app, which runs a real
10
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.
11
14
  */
12
15
  export default class DedicatedMachinesExec extends BaseCommand {
13
16
  static description: string;
@@ -21,6 +24,7 @@ export default class DedicatedMachinesExec extends BaseCommand {
21
24
  command: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
25
  cwd: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
23
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>;
24
28
  workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
25
29
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
26
30
  };
@@ -5,6 +5,7 @@ const base_command_1 = require("../../../base-command");
5
5
  const shell_quote_1 = require("../../../lib/shell-quote");
6
6
  const hosted_machines_1 = require("../../../lib/hosted-machines");
7
7
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
8
+ const dedicated_exec_1 = require("../../../lib/dedicated-exec");
8
9
  const exec_1 = require("../hosted/exec");
9
10
  /**
10
11
  * `skrr machines dedicated exec` — the Run Command half of EC2 parity.
@@ -15,6 +16,9 @@ const exec_1 = require("../hosted/exec");
15
16
  * Machine's `connect` is that loop and has to say so in its own docs. The honest
16
17
  * interactive surface is the terminal in the web app, which runs a real
17
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.
18
22
  */
19
23
  class DedicatedMachinesExec extends base_command_1.BaseCommand {
20
24
  static description = 'Run one command on a Dedicated Runtime machine and return its output and exit code';
@@ -23,6 +27,7 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
23
27
  '<%= config.bin %> machines dedicated exec <lease-id> -- git -C repos/app status',
24
28
  '<%= config.bin %> machines dedicated exec <lease-id> --cwd repos/app --timeout 5m -- npm test',
25
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',
26
31
  ];
27
32
  static usage = 'machines dedicated exec <lease-id> [flags] -- <command...>';
28
33
  static args = {
@@ -42,6 +47,9 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
42
47
  timeout: core_1.Flags.string({
43
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.`,
44
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
+ }),
45
53
  workspace: core_1.Flags.string({ description: 'Workspace scope' }),
46
54
  json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
47
55
  };
@@ -60,6 +68,10 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
60
68
  if (!command.trim()) {
61
69
  this.error('Command is required. Use --command or pass it after --.', { exit: 2 });
62
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
+ }
63
75
  let timeoutMs;
64
76
  try {
65
77
  timeoutMs = (0, hosted_machines_1.parseDurationMs)(flags.timeout, '--timeout');
@@ -72,9 +84,14 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
72
84
  }
73
85
  let result;
74
86
  try {
75
- result = await (0, dedicated_machines_1.execDedicatedRuntime)(id, { command, ...(flags.cwd ? { cwd: flags.cwd } : {}), ...(timeoutMs ? { timeoutMs } : {}) }, { workspaceId: flags.workspace });
87
+ result = await (0, dedicated_exec_1.runDedicatedExec)(id, { command, ...(flags.cwd ? { cwd: flags.cwd } : {}), ...(timeoutMs ? { timeoutMs } : {}) }, { workspaceId: flags.workspace, ...(requestId ? { requestId } : {}) });
76
88
  }
77
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
+ }
78
95
  const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
79
96
  if (message)
80
97
  this.error(message, { exit: 1, code: (0, dedicated_machines_1.dedicatedRuntimeApiErrorCode)(err) });
@@ -89,7 +106,7 @@ class DedicatedMachinesExec extends base_command_1.BaseCommand {
89
106
  // About the invocation, not the command's output — stderr, so a caller
90
107
  // piping stdout reads only what the machine printed.
91
108
  if (result.truncated) {
92
- process.stderr.write('\n[output truncated at 1 MB]\n');
109
+ process.stderr.write(`\n${(0, dedicated_exec_1.describeTruncation)(result)}\n`);
93
110
  }
94
111
  if (result.timedOut) {
95
112
  process.stderr.write(`\n[timed out after ${Math.round(result.durationMs / 1000)}s; the process group was killed]\n`);
@@ -11,7 +11,7 @@ class DedicatedMachinesGrow extends dedicated_lease_command_1.DedicatedLeaseComm
11
11
  ];
12
12
  static args = {
13
13
  lease: core_1.Args.string({
14
- description: 'Dedicated Runtime lease id',
14
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
15
15
  required: true,
16
16
  ignoreStdin: true,
17
17
  }),
@@ -30,7 +30,8 @@ class DedicatedMachinesGrow extends dedicated_lease_command_1.DedicatedLeaseComm
30
30
  async run() {
31
31
  this.requireAuth();
32
32
  const { args, flags } = await this.parse(DedicatedMachinesGrow);
33
- const response = await this.callDedicated(() => (0, dedicated_machines_1.growDedicatedRuntime)(args.lease, flags['storage-gb'], {
33
+ const leaseId = await this.resolveLeaseArg(args.lease);
34
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.growDedicatedRuntime)(leaseId, flags['storage-gb'], {
34
35
  ...this.scopeFrom(flags),
35
36
  ...(flags['request-id'] ? { requestId: flags['request-id'] } : {}),
36
37
  }));
@@ -11,7 +11,7 @@ class DedicatedMachinesHealthCheck extends dedicated_lease_command_1.DedicatedLe
11
11
  ];
12
12
  static args = {
13
13
  lease: core_1.Args.string({
14
- description: 'Dedicated Runtime lease id',
14
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
15
15
  required: true,
16
16
  ignoreStdin: true,
17
17
  }),
@@ -22,14 +22,15 @@ class DedicatedMachinesHealthCheck extends dedicated_lease_command_1.DedicatedLe
22
22
  async run() {
23
23
  this.requireAuth();
24
24
  const { args, flags } = await this.parse(DedicatedMachinesHealthCheck);
25
- const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'health-check', this.scopeFrom(flags)));
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)));
26
27
  if (flags.json) {
27
28
  this.log(JSON.stringify(response, null, 2));
28
29
  return;
29
30
  }
30
31
  const lease = response?.lease;
31
32
  if (!lease) {
32
- this.log(`Dedicated Runtime ${args.lease} ${(0, dedicated_machines_1.dedicatedLeaseState)(lease)}.`);
33
+ this.log(`Dedicated Runtime ${leaseId} ${(0, dedicated_machines_1.dedicatedLeaseState)(lease)}.`);
33
34
  return;
34
35
  }
35
36
  // A health check exists to answer "can it take work, and if not why" — the
@@ -11,7 +11,7 @@ class DedicatedMachinesIncidentClose extends dedicated_lease_command_1.Dedicated
11
11
  ];
12
12
  static args = {
13
13
  lease: core_1.Args.string({
14
- description: 'Dedicated Runtime lease id',
14
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
15
15
  required: true,
16
16
  ignoreStdin: true,
17
17
  }),
@@ -25,7 +25,8 @@ class DedicatedMachinesIncidentClose extends dedicated_lease_command_1.Dedicated
25
25
  async run() {
26
26
  this.requireAuth();
27
27
  const { args, flags } = await this.parse(DedicatedMachinesIncidentClose);
28
- const response = await this.callDedicated(() => (0, dedicated_machines_1.closeDedicatedRuntimeIncidentHold)(args.lease, {
28
+ const leaseId = await this.resolveLeaseArg(args.lease);
29
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.closeDedicatedRuntimeIncidentHold)(leaseId, {
29
30
  ...this.scopeFrom(flags),
30
31
  ...(flags['request-id'] ? { requestId: flags['request-id'] } : {}),
31
32
  }));
@@ -13,6 +13,7 @@ class DedicatedMachines extends core_1.Command {
13
13
  '<%= config.bin %> machines dedicated create --name dev-box --size-preset standard --spending-limit-cents 20000 --wait',
14
14
  '<%= config.bin %> machines dedicated list',
15
15
  '<%= config.bin %> machines dedicated show <lease-id>',
16
+ '<%= config.bin %> machines dedicated snapshot self --wait',
16
17
  '<%= config.bin %> machines dedicated attach <lease-id> --agent <agent-id>',
17
18
  '<%= config.bin %> machines dedicated terminal <lease-id>',
18
19
  '<%= config.bin %> machines dedicated sign-in <lease-id> github',
@@ -34,6 +35,7 @@ class DedicatedMachines extends core_1.Command {
34
35
  ['create', 'request a Dedicated Runtime'],
35
36
  ['list', 'list Dedicated Runtime leases'],
36
37
  ['show', 'state, size, spend, health and engines of one lease'],
38
+ ['current', 'the lease of the machine this runs on (or pass `self`)'],
37
39
  ['attach', 'pin an agent so its work runs on the machine'],
38
40
  ['terminal', 'open an interactive shell on the machine'],
39
41
  ['sign-in', 'sign in to GitHub CLI, Claude Code or Codex there'],
@@ -12,7 +12,7 @@ class DedicatedMachinesRestart extends dedicated_lease_command_1.DedicatedLeaseC
12
12
  ];
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
- description: 'Dedicated Runtime lease id',
15
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
16
16
  required: true,
17
17
  ignoreStdin: true,
18
18
  }),
@@ -24,7 +24,8 @@ class DedicatedMachinesRestart extends dedicated_lease_command_1.DedicatedLeaseC
24
24
  async run() {
25
25
  this.requireAuth();
26
26
  const { args, flags } = await this.parse(DedicatedMachinesRestart);
27
- const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'restart', this.scopeFrom(flags)));
27
+ const leaseId = await this.resolveLeaseArg(args.lease);
28
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(leaseId, 'restart', this.scopeFrom(flags)));
28
29
  await this.reportLeaseAction(response, flags, { kind: 'running' }, 'Restarting');
29
30
  }
30
31
  }
@@ -0,0 +1,26 @@
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ /**
3
+ * `skrr machines dedicated restore` — bring back a deleted Dedicated Runtime.
4
+ *
5
+ * Deleting a workspace keeps one final recovery point for a window (seven days
6
+ * by default), because whoever deleted it may have been an agent acting with
7
+ * the owner's authority. This builds a NEW machine from that point, with the
8
+ * deleted one's files; the deleted lease stays deleted.
9
+ */
10
+ export default class DedicatedMachinesRestore extends DedicatedLeaseCommand {
11
+ static description: string;
12
+ static examples: string[];
13
+ static args: {
14
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
15
+ };
16
+ static flags: {
17
+ wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
21
+ 'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
22
+ 'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
23
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
24
+ };
25
+ run(): Promise<void>;
26
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const node_crypto_1 = require("node:crypto");
5
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
6
+ const dedicated_machines_1 = require("../../../lib/dedicated-machines");
7
+ /**
8
+ * `skrr machines dedicated restore` — bring back a deleted Dedicated Runtime.
9
+ *
10
+ * Deleting a workspace keeps one final recovery point for a window (seven days
11
+ * by default), because whoever deleted it may have been an agent acting with
12
+ * the owner's authority. This builds a NEW machine from that point, with the
13
+ * deleted one's files; the deleted lease stays deleted.
14
+ */
15
+ class DedicatedMachinesRestore extends dedicated_lease_command_1.DedicatedLeaseCommand {
16
+ static description = 'Restore a deleted Dedicated Runtime into a new machine, from the recovery point its deletion kept. Only inside the recovery window, and once.';
17
+ static examples = [
18
+ '<%= config.bin %> machines dedicated restore <deleted-lease-id>',
19
+ '<%= config.bin %> machines dedicated restore <deleted-lease-id> --name research-box --wait',
20
+ ];
21
+ static args = {
22
+ lease: core_1.Args.string({
23
+ description: 'The deleted Dedicated Runtime lease id (see `machines dedicated show`)',
24
+ required: true,
25
+ ignoreStdin: true,
26
+ }),
27
+ };
28
+ static flags = {
29
+ name: core_1.Flags.string({
30
+ description: 'Display name for the new machine (defaults to the deleted one, "(restored)")',
31
+ }),
32
+ 'spending-limit-cents': core_1.Flags.integer({
33
+ description: "Monthly spending cap for the new machine (defaults to the deleted machine's)",
34
+ min: 1,
35
+ }),
36
+ 'request-id': core_1.Flags.string({
37
+ description: 'Idempotency key. Reuse it to safely retry the same restore.',
38
+ }),
39
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
40
+ ...dedicated_lease_command_1.dedicatedWaitFlags,
41
+ };
42
+ async run() {
43
+ this.requireAuth();
44
+ const { args, flags } = await this.parse(DedicatedMachinesRestore);
45
+ const requestId = flags['request-id'] || `dedicated-restore:${Date.now()}:${(0, node_crypto_1.randomBytes)(6).toString('hex')}`;
46
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.restoreDeletedDedicatedRuntime)(args.lease, {
47
+ ...this.scopeFrom(flags),
48
+ requestId,
49
+ ...(flags.name ? { displayName: flags.name } : {}),
50
+ ...(flags['spending-limit-cents'] !== undefined
51
+ ? { monthlySpendingLimitCents: flags['spending-limit-cents'] }
52
+ : {}),
53
+ }));
54
+ if (!flags.json) {
55
+ const lease = response?.lease;
56
+ this.log(`Restoring ${args.lease} into ${(0, dedicated_machines_1.dedicatedLeaseDisplayName)(lease)} (${(0, dedicated_machines_1.dedicatedLeaseId)(lease) || 'unknown'}).`);
57
+ if (flags.wait && !flags['request-id']) {
58
+ process.stderr.write(`Request id ${requestId} (reuse it with --request-id to retry safely)\n`);
59
+ }
60
+ }
61
+ await this.reportLeaseAction(response, flags, { kind: 'running' }, 'Restoring');
62
+ }
63
+ }
64
+ exports.default = DedicatedMachinesRestore;
@@ -13,7 +13,7 @@ class DedicatedMachinesShow extends dedicated_lease_command_1.DedicatedLeaseComm
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
15
  ignoreStdin: true,
16
- description: 'Dedicated Runtime lease id',
16
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
17
17
  required: true,
18
18
  }),
19
19
  };
@@ -23,7 +23,8 @@ class DedicatedMachinesShow extends dedicated_lease_command_1.DedicatedLeaseComm
23
23
  async run() {
24
24
  this.requireAuth();
25
25
  const { args, flags } = await this.parse(DedicatedMachinesShow);
26
- const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(args.lease, this.scopeFrom(flags)));
26
+ const leaseId = await this.resolveLeaseArg(args.lease);
27
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(leaseId, this.scopeFrom(flags)));
27
28
  const lease = response?.lease;
28
29
  if (!lease) {
29
30
  this.error('Dedicated Runtime lease not found.', { exit: 1 });
@@ -12,7 +12,7 @@ class DedicatedMachinesSnapshot extends dedicated_lease_command_1.DedicatedLease
12
12
  ];
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
- description: 'Dedicated Runtime lease id',
15
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
16
16
  required: true,
17
17
  ignoreStdin: true,
18
18
  }),
@@ -24,7 +24,8 @@ class DedicatedMachinesSnapshot extends dedicated_lease_command_1.DedicatedLease
24
24
  async run() {
25
25
  this.requireAuth();
26
26
  const { args, flags } = await this.parse(DedicatedMachinesSnapshot);
27
- const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'snapshot', this.scopeFrom(flags)));
27
+ const leaseId = await this.resolveLeaseArg(args.lease);
28
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(leaseId, 'snapshot', this.scopeFrom(flags)));
28
29
  // A snapshot returns the lease to the state it left, so the state cannot say
29
30
  // whether it worked. The recovery point's timestamp can: the 202 carries the
30
31
  // previous one, and success is a newer one.
@@ -20,7 +20,7 @@ class DedicatedMachinesSpendingLimit extends dedicated_lease_command_1.Dedicated
20
20
  ];
21
21
  static args = {
22
22
  lease: core_1.Args.string({
23
- description: 'Dedicated Runtime lease id',
23
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
24
24
  required: true,
25
25
  ignoreStdin: true,
26
26
  }),
@@ -36,13 +36,14 @@ class DedicatedMachinesSpendingLimit extends dedicated_lease_command_1.Dedicated
36
36
  async run() {
37
37
  this.requireAuth();
38
38
  const { args, flags } = await this.parse(DedicatedMachinesSpendingLimit);
39
- const response = await this.callDedicated(() => (0, dedicated_machines_1.setDedicatedRuntimeSpendingLimit)(args.lease, flags.cents, this.scopeFrom(flags)));
39
+ const leaseId = await this.resolveLeaseArg(args.lease);
40
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.setDedicatedRuntimeSpendingLimit)(leaseId, flags.cents, this.scopeFrom(flags)));
40
41
  if (flags.json) {
41
42
  this.log(JSON.stringify(response, null, 2));
42
43
  return;
43
44
  }
44
45
  const lease = response?.lease;
45
- this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(lease) || args.lease} spending cap updated.`);
46
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(lease) || leaseId} spending cap updated.`);
46
47
  if (lease)
47
48
  this.log(` ${(0, dedicated_machines_1.dedicatedSpendSummary)(lease)}`);
48
49
  }
@@ -12,7 +12,7 @@ class DedicatedMachinesStart extends dedicated_lease_command_1.DedicatedLeaseCom
12
12
  ];
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
- description: 'Dedicated Runtime lease id',
15
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
16
16
  required: true,
17
17
  ignoreStdin: true,
18
18
  }),
@@ -24,7 +24,8 @@ class DedicatedMachinesStart extends dedicated_lease_command_1.DedicatedLeaseCom
24
24
  async run() {
25
25
  this.requireAuth();
26
26
  const { args, flags } = await this.parse(DedicatedMachinesStart);
27
- const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'start', this.scopeFrom(flags)));
27
+ const leaseId = await this.resolveLeaseArg(args.lease);
28
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(leaseId, 'start', this.scopeFrom(flags)));
28
29
  await this.reportLeaseAction(response, flags, { kind: 'running' }, 'Starting');
29
30
  }
30
31
  }
@@ -12,7 +12,7 @@ class DedicatedMachinesStop extends dedicated_lease_command_1.DedicatedLeaseComm
12
12
  ];
13
13
  static args = {
14
14
  lease: core_1.Args.string({
15
- description: 'Dedicated Runtime lease id',
15
+ description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
16
16
  required: true,
17
17
  ignoreStdin: true,
18
18
  }),
@@ -24,7 +24,8 @@ class DedicatedMachinesStop extends dedicated_lease_command_1.DedicatedLeaseComm
24
24
  async run() {
25
25
  this.requireAuth();
26
26
  const { args, flags } = await this.parse(DedicatedMachinesStop);
27
- const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'stop', this.scopeFrom(flags)));
27
+ const leaseId = await this.resolveLeaseArg(args.lease);
28
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(leaseId, 'stop', this.scopeFrom(flags)));
28
29
  await this.reportLeaseAction(response, flags, { kind: 'stopped' }, 'Stopping');
29
30
  }
30
31
  }