@skrr-ai/cli 0.1.23 → 0.1.25

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 (85) hide show
  1. package/bin/run.js +54 -1
  2. package/dist/base-command.d.ts +4 -4
  3. package/dist/base-command.js +81 -6
  4. package/dist/commands/harnesses/leases/list.js +1 -1
  5. package/dist/commands/harnesses/products.js +1 -0
  6. package/dist/commands/machines/dedicated/create.d.ts +18 -0
  7. package/dist/commands/machines/dedicated/create.js +90 -0
  8. package/dist/commands/machines/dedicated/destroy.d.ts +14 -0
  9. package/dist/commands/machines/dedicated/destroy.js +56 -0
  10. package/dist/commands/machines/dedicated/grow.d.ts +13 -0
  11. package/dist/commands/machines/dedicated/grow.js +46 -0
  12. package/dist/commands/machines/dedicated/health-check.d.ts +12 -0
  13. package/dist/commands/machines/dedicated/health-check.js +42 -0
  14. package/dist/commands/machines/dedicated/incident-close.d.ts +12 -0
  15. package/dist/commands/machines/dedicated/incident-close.js +42 -0
  16. package/dist/commands/machines/dedicated/index.d.ts +6 -0
  17. package/dist/commands/machines/dedicated/index.js +39 -0
  18. package/dist/commands/machines/dedicated/list.d.ts +11 -0
  19. package/dist/commands/machines/dedicated/list.js +58 -0
  20. package/dist/commands/machines/dedicated/restart.d.ts +12 -0
  21. package/dist/commands/machines/dedicated/restart.js +42 -0
  22. package/dist/commands/machines/dedicated/show.d.ts +12 -0
  23. package/dist/commands/machines/dedicated/show.js +58 -0
  24. package/dist/commands/machines/dedicated/snapshot.d.ts +12 -0
  25. package/dist/commands/machines/dedicated/snapshot.js +42 -0
  26. package/dist/commands/machines/dedicated/start.d.ts +12 -0
  27. package/dist/commands/machines/dedicated/start.js +42 -0
  28. package/dist/commands/machines/dedicated/stop.d.ts +12 -0
  29. package/dist/commands/machines/dedicated/stop.js +42 -0
  30. package/dist/commands/machines/hosted/index.js +4 -1
  31. package/dist/commands/spaces/auto-executor/preview.d.ts +8 -0
  32. package/dist/commands/spaces/auto-executor/preview.js +41 -0
  33. package/dist/commands/spaces/task-rollups.d.ts +14 -0
  34. package/dist/commands/spaces/task-rollups.js +66 -0
  35. package/dist/commands/spaces/update.js +16 -12
  36. package/dist/commands/spaces/work-sync/reconcile.d.ts +38 -0
  37. package/dist/commands/spaces/work-sync/reconcile.js +90 -0
  38. package/dist/commands/spaces/work-sync/telemetry.d.ts +29 -0
  39. package/dist/commands/spaces/work-sync/telemetry.js +118 -0
  40. package/dist/commands/tasks/activity.js +5 -1
  41. package/dist/commands/tasks/assign.js +1 -1
  42. package/dist/commands/tasks/complete.d.ts +5 -1
  43. package/dist/commands/tasks/complete.js +17 -3
  44. package/dist/commands/tasks/create.d.ts +1 -0
  45. package/dist/commands/tasks/create.js +17 -4
  46. package/dist/commands/tasks/deliverable/add.js +22 -4
  47. package/dist/commands/tasks/deliverable/list.js +23 -2
  48. package/dist/commands/tasks/events/append.js +31 -3
  49. package/dist/commands/tasks/expectations/assess.d.ts +1 -1
  50. package/dist/commands/tasks/expectations/assess.js +33 -7
  51. package/dist/commands/tasks/expectations.js +110 -10
  52. package/dist/commands/tasks/output.d.ts +0 -1
  53. package/dist/commands/tasks/output.js +21 -1
  54. package/dist/commands/tasks/report.js +3 -1
  55. package/dist/commands/tasks/result/show.js +20 -2
  56. package/dist/commands/tasks/resume/save.js +11 -1
  57. package/dist/commands/tasks/self-schedule.js +7 -4
  58. package/dist/commands/tasks/show.js +19 -0
  59. package/dist/commands/tasks/timeline.js +9 -1
  60. package/dist/commands/tasks/updates/add.js +23 -2
  61. package/dist/lib/api-fetch.js +9 -1
  62. package/dist/lib/assignee-resolver.d.ts +7 -6
  63. package/dist/lib/daemonBroker.d.ts +20 -0
  64. package/dist/lib/daemonBroker.js +58 -17
  65. package/dist/lib/dedicated-machines.d.ts +66 -0
  66. package/dist/lib/dedicated-machines.js +161 -0
  67. package/dist/lib/harnesses.d.ts +5 -0
  68. package/dist/lib/harnesses.js +5 -2
  69. package/dist/lib/idempotency-scope.d.ts +10 -0
  70. package/dist/lib/idempotency-scope.js +16 -0
  71. package/dist/lib/node-adapter.d.ts +1 -1
  72. package/dist/lib/node-adapter.js +12 -10
  73. package/dist/lib/task-legacy.d.ts +24 -0
  74. package/dist/lib/task-legacy.js +48 -0
  75. package/dist/lib/tasks.d.ts +32 -0
  76. package/dist/lib/tasks.js +47 -1
  77. package/dist/lib/triggers.js +7 -0
  78. package/dist/lib/work-sync.d.ts +105 -0
  79. package/dist/lib/work-sync.js +29 -0
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +71 -21
  81. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.js +71 -21
  82. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  83. package/dist/node_modules/@skrr-ai/data-provider/index.js +2141 -2061
  84. package/oclif.manifest.json +15661 -14585
  85. package/package.json +1 -1
package/bin/run.js CHANGED
@@ -4,6 +4,41 @@ const path = require('node:path');
4
4
  const { spawnSync } = require('node:child_process');
5
5
  const { findAlternateCli, missingLocalCommandBuild } = require('./dev-fallback');
6
6
 
7
+ /**
8
+ * The version a CLI entry point would run, for the fallback notice. Best effort:
9
+ * a version we cannot read must never be the reason a command fails.
10
+ */
11
+ function describeCliVersion(startPath) {
12
+ const fsModule = require('node:fs');
13
+ // Resolve through the symlink first. An installed CLI is almost always a link
14
+ // in a bin directory, and walking up from THAT finds nothing — which is how
15
+ // the version, the one fact this message exists to report, came back unknown.
16
+ let resolved = startPath;
17
+ try {
18
+ resolved = fsModule.realpathSync(startPath);
19
+ } catch {
20
+ // fall through to the path as given
21
+ }
22
+ let dir =
23
+ fsModule.existsSync(resolved) && fsModule.statSync(resolved).isDirectory()
24
+ ? resolved
25
+ : path.dirname(resolved);
26
+ for (let depth = 0; depth < 6; depth += 1) {
27
+ try {
28
+ const pkg = JSON.parse(
29
+ require('node:fs').readFileSync(path.join(dir, 'package.json'), 'utf8'),
30
+ );
31
+ if (pkg?.version) return `v${pkg.version}`;
32
+ } catch {
33
+ // keep walking
34
+ }
35
+ const parent = path.dirname(dir);
36
+ if (parent === dir) break;
37
+ dir = parent;
38
+ }
39
+ return 'version unknown';
40
+ }
41
+
7
42
  const cliRoot = path.resolve(__dirname, '..');
8
43
  const missingBuildPath = missingLocalCommandBuild({
9
44
  cliRoot,
@@ -22,8 +57,26 @@ if (missingBuildPath) {
22
57
  requiredCommand: path.relative(path.join(cliRoot, 'dist', 'commands'), missingBuildPath),
23
58
  });
24
59
  if (fallback) {
60
+ // A developer verifying a change is the one caller for whom this fallback is
61
+ // not a safety net: it silently substitutes a DIFFERENT BUILD of the thing
62
+ // under test. The loop that trips it is exactly fix -> commit -> verify,
63
+ // because the pre-commit hook reformats staged sources and that invalidates
64
+ // the whole-tree digest for every command, not just the one edited.
65
+ //
66
+ // So name the substitution rather than just the fact, and let anyone who is
67
+ // verifying turn the fallback off outright.
68
+ if (process.env.SKRR_NO_DEV_FALLBACK === '1') {
69
+ console.error(
70
+ `[skrr] Refusing to fall back: SKRR_NO_DEV_FALLBACK=1 and the local build is stale at ` +
71
+ `${missingBuildPath}. Run "npm --prefix cli run build".`,
72
+ );
73
+ process.exit(1);
74
+ }
25
75
  console.error(
26
- `[skrr] Local development build is incomplete (${missingBuildPath}); using fallback CLI ${fallback}.`,
76
+ `[skrr] Local development build is incomplete (${missingBuildPath}).\n` +
77
+ `[skrr] Running ${fallback} (${describeCliVersion(fallback)}) INSTEAD OF ` +
78
+ `this checkout (${describeCliVersion(cliRoot)}). Run "npm --prefix cli run build" to use ` +
79
+ `your own changes, or set SKRR_NO_DEV_FALLBACK=1 to make this an error.`,
27
80
  );
28
81
  const delegated = spawnSync(fallback, process.argv.slice(2), {
29
82
  stdio: 'inherit',
@@ -199,10 +199,10 @@ export declare abstract class BaseCommand extends Command {
199
199
  *
200
200
  * Shared by every command that accepts an assignee reference. A failure is
201
201
  * fatal rather than a silent fall-back to a global directory search: the
202
- * server only accepts assignees who are members of the space
203
- * (`ASSIGNEE_NOT_IN_SPACE`), so widening the lookup could only ever produce
204
- * a request guaranteed to be rejected or, worse, resolve a typo to a
205
- * stranger the caller never intended to name.
202
+ * server accepts space members, plus only the caller's own unshared agents
203
+ * (`AgentTaskConsent`; anything else is `ASSIGNEE_NOT_IN_SPACE`), so widening
204
+ * the lookup could only ever produce a request the server refuses or,
205
+ * worse, resolve a typo to a stranger the caller never intended to name.
206
206
  */
207
207
  protected loadSpaceMembers(spaceId: string): Promise<SpaceMember[]>;
208
208
  /**
@@ -645,10 +645,10 @@ class BaseCommand extends core_1.Command {
645
645
  *
646
646
  * Shared by every command that accepts an assignee reference. A failure is
647
647
  * fatal rather than a silent fall-back to a global directory search: the
648
- * server only accepts assignees who are members of the space
649
- * (`ASSIGNEE_NOT_IN_SPACE`), so widening the lookup could only ever produce
650
- * a request guaranteed to be rejected or, worse, resolve a typo to a
651
- * stranger the caller never intended to name.
648
+ * server accepts space members, plus only the caller's own unshared agents
649
+ * (`AgentTaskConsent`; anything else is `ASSIGNEE_NOT_IN_SPACE`), so widening
650
+ * the lookup could only ever produce a request the server refuses or,
651
+ * worse, resolve a typo to a stranger the caller never intended to name.
652
652
  */
653
653
  async loadSpaceMembers(spaceId) {
654
654
  let response;
@@ -752,6 +752,14 @@ class BaseCommand extends core_1.Command {
752
752
  if (isOclifExitError(err)) {
753
753
  return super.catch(err);
754
754
  }
755
+ // Canonical Task Model v1 removed several `tasks complete` flags outright,
756
+ // so a caller following older instructions — including the managed block the
757
+ // platform itself installed — got a bare `Nonexistent flags:` with no hint
758
+ // that the capability moved rather than vanished. Name where each went.
759
+ const retiredHint = retiredFlagHint(err.message || '');
760
+ if (retiredHint) {
761
+ err.message = `${err.message}\n\n${retiredHint}`;
762
+ }
755
763
  if (this.wantsJsonOutput()) {
756
764
  const exit = err.exitCode ?? err.oclif?.exit ?? 1;
757
765
  process.exitCode = exit;
@@ -1163,7 +1171,10 @@ class BaseCommand extends core_1.Command {
1163
1171
  // terminal refusal or a 500. oclif's pretty-printer renders a `code` on a
1164
1172
  // CLIError as its own `Code: <code>` line, so passing it through gives
1165
1173
  // every skrr command a greppable failure line at no other cost.
1166
- this.error(message, { exit, code });
1174
+ //
1175
+ // Field-level validation is appended for the same reason: the server names
1176
+ // the offending field and only `--json` callers could read it.
1177
+ this.error(`${message}${formatValidationIssues(details)}`, { exit, code });
1167
1178
  }
1168
1179
  writeJsonCliError({ message, code, status, exit, retryable, details, }) {
1169
1180
  this.log(JSON.stringify({
@@ -1365,8 +1376,10 @@ function describeAssigneeNotInSpace(serverMessage, bin = 'skrr') {
1365
1376
  const base = serverMessage?.trim() || 'That assignee is not a member of this space.';
1366
1377
  if (base.includes(`${bin} spaces members add`))
1367
1378
  return base;
1379
+ // Two ways forward, because the server accepts two consents: membership, or
1380
+ // an owner assigning their own unshared agent to one task (AgentTaskConsent).
1368
1381
  return (`${base}\n → add it to the space with \`${bin} spaces members add\`, ` +
1369
- 'or assign someone already in it.');
1382
+ 'assign someone already in it, or — for your own unshared agent — assign it yourself.');
1370
1383
  }
1371
1384
  /**
1372
1385
  * Server-declared TERMINAL refusals: a state conflict the caller must resolve
@@ -1521,6 +1534,42 @@ function isRetryableFailure(status, body) {
1521
1534
  return false;
1522
1535
  return status === 408 || status === 425 || status === 429 || !!(status && status >= 500);
1523
1536
  }
1537
+ /**
1538
+ * Render server-supplied field validation into the human error.
1539
+ *
1540
+ * The canonical Task routes answer a schema rejection with
1541
+ * `{error: 'Invalid request data', details: <zod issues>}` — which names the
1542
+ * exact field — but the human path used to print only the generic sentence, so
1543
+ * `tasks updates add --type finding` failed with `Invalid request data` and the
1544
+ * operator had to re-run the identical command with `--json` to learn that
1545
+ * `data.evidenceRefs` was missing. The answer was already on the wire; only the
1546
+ * renderer threw it away.
1547
+ *
1548
+ * Shape-sniffed rather than typed against zod: `details` also carries unrelated
1549
+ * payloads (outbox ids, oclif suggestions), and those must pass through
1550
+ * untouched rather than render as pseudo-fields.
1551
+ */
1552
+ function formatValidationIssues(details) {
1553
+ const issues = Array.isArray(details)
1554
+ ? details
1555
+ : Array.isArray(details?.details)
1556
+ ? details.details
1557
+ : Array.isArray(details?.issues)
1558
+ ? details.issues
1559
+ : [];
1560
+ const lines = [];
1561
+ for (const issue of issues) {
1562
+ const row = issue;
1563
+ const message = typeof row?.message === 'string' ? row.message : '';
1564
+ if (!message)
1565
+ continue;
1566
+ const path = Array.isArray(row.path) ? row.path.join('.') : '';
1567
+ lines.push(path ? ` ${path}: ${message}` : ` ${message}`);
1568
+ if (lines.length === 10)
1569
+ break;
1570
+ }
1571
+ return lines.length > 0 ? `\n${lines.join('\n')}` : '';
1572
+ }
1524
1573
  function detailsFromPrettyError(options) {
1525
1574
  const details = {};
1526
1575
  for (const key of ['suggestions', 'ref', 'showHelp']) {
@@ -1537,6 +1586,32 @@ function detailsFromCaughtError(err) {
1537
1586
  details.exit = err.oclif.exit;
1538
1587
  return Object.keys(details).length > 0 ? details : undefined;
1539
1588
  }
1589
+ /**
1590
+ * Where a removed flag's capability went. Keyed by flag name so it fires on
1591
+ * oclif's own `Nonexistent flags:` message without parsing its grammar.
1592
+ */
1593
+ const RETIRED_FLAG_REPLACEMENTS = {
1594
+ '--verdict': '--verdict is gone: a review decision and a domain conclusion are different facts. ' +
1595
+ 'Use `tasks review --decision accepted|changes_requested` for acceptance, and ' +
1596
+ '--conclusion-type/--conclusion-json for a conclusion such as NO-SHIP.',
1597
+ '--outcome': '--outcome is now --summary.',
1598
+ '--finding': '--finding is gone: record findings as `tasks updates add --type finding`.',
1599
+ '--evidence': '--evidence is now --evidence-ref on the Result, or an evidenceRefs entry.',
1600
+ '--next': '--next is now --remaining.',
1601
+ '--deliverables': '--deliverables is now --deliverable <task-resource-link-id>, recorded first with ' +
1602
+ '`tasks deliverable add`.',
1603
+ '--artifact': '--artifact is now --deliverable <task-resource-link-id>, recorded first with ' +
1604
+ '`tasks deliverable add`.',
1605
+ '--supersede': '--supersede is implicit: submitting again creates a new Result version.',
1606
+ };
1607
+ function retiredFlagHint(message) {
1608
+ if (!/nonexistent flag/i.test(message))
1609
+ return null;
1610
+ const hits = Object.keys(RETIRED_FLAG_REPLACEMENTS).filter((flag) => new RegExp(`${flag}(?![\\w-])`).test(message));
1611
+ if (hits.length === 0)
1612
+ return null;
1613
+ return hits.map((flag) => ` ${RETIRED_FLAG_REPLACEMENTS[flag]}`).join('\n');
1614
+ }
1540
1615
  function parseCliErrorCode(err) {
1541
1616
  if (err.name && err.name !== 'Error') {
1542
1617
  return err.name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
@@ -33,7 +33,7 @@ class HarnessesLeasesList extends base_command_1.BaseCommand {
33
33
  }),
34
34
  product: core_1.Flags.string({
35
35
  description: 'Only this machine product',
36
- options: ['hosted-machine', 'hosted-job-machine'],
36
+ options: ['hosted-machine', 'hosted-job-machine', 'dedicated-machine'],
37
37
  }),
38
38
  };
39
39
  async run() {
@@ -31,6 +31,7 @@ const START_COMMAND = {
31
31
  // a reader who wants compute at the repository flow is a smaller version of
32
32
  // pointing them at a verb nobody implements.
33
33
  'hosted-job-machine': 'code jobs run',
34
+ 'dedicated-machine': 'machines dedicated create',
34
35
  };
35
36
  /**
36
37
  * `availability` is a string on some rows and an object on others. The table
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesCreate extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
7
+ 'size-preset': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ 'region-class': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ 'storage-gb': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ 'retention-class': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'backup-profile': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'spending-limit-cents': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ workspace: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ 'request-id': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,90 @@
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 base_command_1 = require("../../../base-command");
6
+ const dedicated_machines_1 = require("../../../lib/dedicated-machines");
7
+ class DedicatedMachinesCreate extends base_command_1.BaseCommand {
8
+ static description = 'Request a Dedicated Runtime lease';
9
+ static examples = [
10
+ '<%= config.bin %> machines dedicated create --name dev-box --size-preset standard --spending-limit-cents 20000',
11
+ '<%= config.bin %> machines dedicated create --name dev-box --size-preset standard --spending-limit-cents 20000 --json',
12
+ ];
13
+ static flags = {
14
+ name: core_1.Flags.string({ description: 'Display name for the dedicated machine', required: true }),
15
+ 'size-preset': core_1.Flags.string({
16
+ description: 'Instance size preset (from harnesses products)',
17
+ required: true,
18
+ }),
19
+ // None of these four carry a client-side default, deliberately.
20
+ //
21
+ // The server already defaults every one of them, and a CLI that restates a
22
+ // default it does not own cannot be right for long. `--storage-gb` proved
23
+ // it: it defaulted to 100 while the product's default is 50, so a user who
24
+ // never chose a size was billed for twice the documented disk, the server's
25
+ // own `workspaceDefaultGb` was unreachable through the CLI, and the
26
+ // decision record that set the number was wrong for CLI users. The other
27
+ // three happened to agree, which is worse rather than better — it is the
28
+ // same bug with the symptom switched off until someone moves a default.
29
+ 'region-class': core_1.Flags.string({
30
+ description: 'Region class. Defaults to the product catalog value (usually primary).',
31
+ }),
32
+ 'storage-gb': core_1.Flags.integer({
33
+ description: 'Workspace storage size in GB. Defaults to the product catalog size.',
34
+ }),
35
+ 'retention-class': core_1.Flags.string({
36
+ description: 'Retention class for stopped instances. Defaults to the product catalog value.',
37
+ }),
38
+ 'backup-profile': core_1.Flags.string({
39
+ description: 'crash-consistent (AWS Backup) or application-consistent (guest fsfreeze while the daemon is reachable; scheduled DLM when that plan is enabled). Defaults to the product catalog value.',
40
+ }),
41
+ 'spending-limit-cents': core_1.Flags.integer({
42
+ description: 'Monthly spending limit in cents. Required before start.',
43
+ required: true,
44
+ }),
45
+ workspace: core_1.Flags.string({ description: 'Workspace scope' }),
46
+ 'request-id': core_1.Flags.string({
47
+ description: 'Idempotency key. Reuse it to safely retry the same create request.',
48
+ }),
49
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
50
+ };
51
+ async run() {
52
+ this.requireAuth();
53
+ const { flags } = await this.parse(DedicatedMachinesCreate);
54
+ const body = (0, dedicated_machines_1.dedicatedRuntimeCreateInput)({
55
+ requestId: flags['request-id'] || newRequestId(),
56
+ displayName: flags.name,
57
+ sizePreset: flags['size-preset'],
58
+ monthlySpendingLimitCents: flags['spending-limit-cents'],
59
+ regionClass: flags['region-class'],
60
+ storageGb: flags['storage-gb'],
61
+ retentionClass: flags['retention-class'],
62
+ backupProfile: flags['backup-profile'],
63
+ workspaceId: flags.workspace,
64
+ });
65
+ let response;
66
+ try {
67
+ response = await (0, dedicated_machines_1.createDedicatedRuntime)(body);
68
+ }
69
+ catch (err) {
70
+ const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
71
+ if (message)
72
+ this.error(message, { exit: 1 });
73
+ this.handleApiError(err);
74
+ }
75
+ const lease = response?.lease;
76
+ if (flags.json) {
77
+ this.log(JSON.stringify(response, null, 2));
78
+ return;
79
+ }
80
+ const id = (0, dedicated_machines_1.dedicatedLeaseId)(lease);
81
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseDisplayName)(lease)} (${id || 'unknown'}) ${(0, dedicated_machines_1.dedicatedLeaseState)(lease)}.`);
82
+ if (id) {
83
+ this.log(`Poll: ${this.config.bin} machines dedicated show ${id}`);
84
+ }
85
+ }
86
+ }
87
+ exports.default = DedicatedMachinesCreate;
88
+ function newRequestId() {
89
+ return `dedicated-machine:${Date.now()}:${(0, node_crypto_1.randomBytes)(6).toString('hex')}`;
90
+ }
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesDestroy extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ 'retain-storage': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ 'purge-storage': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,56 @@
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 dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
+ class DedicatedMachinesDestroy extends base_command_1.BaseCommand {
7
+ static description = 'Destroy a Dedicated Runtime lease. Retention class standard/extended archives the lease and keeps the workspace volume; destroy an archived lease to purge storage.';
8
+ static examples = [
9
+ '<%= config.bin %> machines dedicated destroy <lease-id>',
10
+ '<%= config.bin %> machines dedicated destroy <lease-id> --json',
11
+ ];
12
+ static args = {
13
+ lease: core_1.Args.string({
14
+ description: 'Dedicated Runtime lease id',
15
+ required: true,
16
+ ignoreStdin: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
21
+ 'retain-storage': core_1.Flags.boolean({
22
+ description: 'Archive the lease and keep the workspace volume',
23
+ exclusive: ['purge-storage'],
24
+ }),
25
+ 'purge-storage': core_1.Flags.boolean({
26
+ description: 'Permanently delete the workspace volume',
27
+ exclusive: ['retain-storage'],
28
+ }),
29
+ };
30
+ async run() {
31
+ this.requireAuth();
32
+ const { args, flags } = await this.parse(DedicatedMachinesDestroy);
33
+ let response;
34
+ try {
35
+ response = await (0, dedicated_machines_1.destroyDedicatedRuntime)(args.lease, {
36
+ retentionIntent: flags['purge-storage']
37
+ ? 'purge'
38
+ : flags['retain-storage']
39
+ ? 'retain'
40
+ : undefined,
41
+ });
42
+ }
43
+ catch (err) {
44
+ const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
45
+ if (message)
46
+ this.error(message, { exit: 1 });
47
+ this.handleApiError(err);
48
+ }
49
+ if (flags.json) {
50
+ this.log(JSON.stringify(response, null, 2));
51
+ return;
52
+ }
53
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}.`);
54
+ }
55
+ }
56
+ exports.default = DedicatedMachinesDestroy;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesGrow extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'storage-gb': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,46 @@
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 dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
+ class DedicatedMachinesGrow extends base_command_1.BaseCommand {
7
+ static description = 'Increase Dedicated Runtime workspace storage. Shrink is unsupported.';
8
+ static examples = [
9
+ '<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200',
10
+ '<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200 --json',
11
+ ];
12
+ static args = {
13
+ lease: core_1.Args.string({
14
+ description: 'Dedicated Runtime lease id',
15
+ required: true,
16
+ ignoreStdin: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ 'storage-gb': core_1.Flags.integer({
21
+ description: 'New workspace size in GiB. Must be larger than the current size.',
22
+ required: true,
23
+ }),
24
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
25
+ };
26
+ async run() {
27
+ this.requireAuth();
28
+ const { args, flags } = await this.parse(DedicatedMachinesGrow);
29
+ let response;
30
+ try {
31
+ response = await (0, dedicated_machines_1.growDedicatedRuntime)(args.lease, flags['storage-gb']);
32
+ }
33
+ catch (err) {
34
+ const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
35
+ if (message)
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)}.`);
44
+ }
45
+ }
46
+ exports.default = DedicatedMachinesGrow;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesHealthCheck extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,42 @@
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 dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
+ class DedicatedMachinesHealthCheck extends base_command_1.BaseCommand {
7
+ static description = 'Health-check a Dedicated Runtime lease';
8
+ static examples = [
9
+ '<%= config.bin %> machines dedicated health-check <lease-id>',
10
+ '<%= config.bin %> machines dedicated health-check <lease-id> --json',
11
+ ];
12
+ static args = {
13
+ lease: core_1.Args.string({
14
+ description: 'Dedicated Runtime lease id',
15
+ required: true,
16
+ ignoreStdin: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
21
+ };
22
+ async run() {
23
+ this.requireAuth();
24
+ const { args, flags } = await this.parse(DedicatedMachinesHealthCheck);
25
+ let response;
26
+ try {
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
+ }
35
+ if (flags.json) {
36
+ this.log(JSON.stringify(response, null, 2));
37
+ return;
38
+ }
39
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}.`);
40
+ }
41
+ }
42
+ exports.default = DedicatedMachinesHealthCheck;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesIncidentClose extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,42 @@
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 dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
+ class DedicatedMachinesIncidentClose extends base_command_1.BaseCommand {
7
+ static description = 'Close a Dedicated Runtime AZ-recovery incident hold. Does not delete the workspace.';
8
+ static examples = [
9
+ '<%= config.bin %> machines dedicated incident-close <lease-id>',
10
+ '<%= config.bin %> machines dedicated incident-close <lease-id> --json',
11
+ ];
12
+ static args = {
13
+ lease: core_1.Args.string({
14
+ description: 'Dedicated Runtime lease id',
15
+ required: true,
16
+ ignoreStdin: true,
17
+ }),
18
+ };
19
+ static flags = {
20
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
21
+ };
22
+ async run() {
23
+ this.requireAuth();
24
+ const { args, flags } = await this.parse(DedicatedMachinesIncidentClose);
25
+ let response;
26
+ try {
27
+ response = await (0, dedicated_machines_1.closeDedicatedRuntimeIncidentHold)(args.lease);
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
+ }
35
+ if (flags.json) {
36
+ this.log(JSON.stringify(response, null, 2));
37
+ return;
38
+ }
39
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(response?.lease)} ${(0, dedicated_machines_1.dedicatedLeaseState)(response?.lease)}.`);
40
+ }
41
+ }
42
+ exports.default = DedicatedMachinesIncidentClose;
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DedicatedMachines extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ class DedicatedMachines extends core_1.Command {
5
+ // This line is read at the moment someone CHOOSES between the two products,
6
+ // so it states the trade rather than restating the product name. "Manage
7
+ // Dedicated Runtime leases" told a user nothing they could decide on, and the
8
+ // difference that matters — files survive a restart, running processes do not
9
+ // — was invisible until a restart lost their work.
10
+ static description = 'A private VM with a durable workspace — files survive restart, running processes do not';
11
+ static examples = [
12
+ '<%= config.bin %> machines dedicated list',
13
+ '<%= config.bin %> machines dedicated show <lease-id>',
14
+ '<%= config.bin %> machines dedicated create --name dev-box --size-preset standard --spending-limit-cents 20000',
15
+ '<%= config.bin %> machines dedicated stop <lease-id>',
16
+ '<%= config.bin %> machines dedicated start <lease-id>',
17
+ '<%= config.bin %> machines dedicated restart <lease-id>',
18
+ '<%= config.bin %> machines dedicated snapshot <lease-id>',
19
+ '<%= config.bin %> machines dedicated grow <lease-id> --storage-gb 200',
20
+ '<%= config.bin %> machines dedicated incident-close <lease-id>',
21
+ '<%= config.bin %> machines dedicated health-check <lease-id>',
22
+ '<%= config.bin %> machines dedicated destroy <lease-id>',
23
+ ];
24
+ async run() {
25
+ this.log('skrr Dedicated Runtime commands:');
26
+ this.log(' skrr machines dedicated list list Dedicated Runtime leases');
27
+ this.log(' skrr machines dedicated show show one Dedicated Runtime lease');
28
+ this.log(' skrr machines dedicated create request a Dedicated Runtime');
29
+ this.log(' skrr machines dedicated start start a stopped runtime');
30
+ this.log(' skrr machines dedicated stop stop compute and keep the disk');
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');
37
+ }
38
+ }
39
+ exports.default = DedicatedMachines;
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class DedicatedMachinesList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ state: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ };
10
+ run(): Promise<void>;
11
+ }