@skrr-ai/cli 0.1.23 → 0.1.24
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/bin/run.js +54 -1
- package/dist/base-command.js +74 -1
- package/dist/commands/harnesses/leases/list.js +1 -1
- package/dist/commands/harnesses/products.js +1 -0
- package/dist/commands/machines/dedicated/create.d.ts +18 -0
- package/dist/commands/machines/dedicated/create.js +90 -0
- package/dist/commands/machines/dedicated/destroy.d.ts +14 -0
- package/dist/commands/machines/dedicated/destroy.js +56 -0
- package/dist/commands/machines/dedicated/grow.d.ts +13 -0
- package/dist/commands/machines/dedicated/grow.js +46 -0
- package/dist/commands/machines/dedicated/health-check.d.ts +12 -0
- package/dist/commands/machines/dedicated/health-check.js +42 -0
- package/dist/commands/machines/dedicated/incident-close.d.ts +12 -0
- package/dist/commands/machines/dedicated/incident-close.js +42 -0
- package/dist/commands/machines/dedicated/index.d.ts +6 -0
- package/dist/commands/machines/dedicated/index.js +39 -0
- package/dist/commands/machines/dedicated/list.d.ts +11 -0
- package/dist/commands/machines/dedicated/list.js +58 -0
- package/dist/commands/machines/dedicated/restart.d.ts +12 -0
- package/dist/commands/machines/dedicated/restart.js +42 -0
- package/dist/commands/machines/dedicated/show.d.ts +12 -0
- package/dist/commands/machines/dedicated/show.js +58 -0
- package/dist/commands/machines/dedicated/snapshot.d.ts +12 -0
- package/dist/commands/machines/dedicated/snapshot.js +42 -0
- package/dist/commands/machines/dedicated/start.d.ts +12 -0
- package/dist/commands/machines/dedicated/start.js +42 -0
- package/dist/commands/machines/dedicated/stop.d.ts +12 -0
- package/dist/commands/machines/dedicated/stop.js +42 -0
- package/dist/commands/machines/hosted/index.js +4 -1
- package/dist/commands/spaces/update.js +16 -12
- package/dist/commands/spaces/work-sync/reconcile.d.ts +38 -0
- package/dist/commands/spaces/work-sync/reconcile.js +90 -0
- package/dist/commands/spaces/work-sync/telemetry.d.ts +29 -0
- package/dist/commands/spaces/work-sync/telemetry.js +96 -0
- package/dist/commands/tasks/activity.js +5 -1
- package/dist/commands/tasks/complete.d.ts +5 -1
- package/dist/commands/tasks/complete.js +17 -3
- package/dist/commands/tasks/create.d.ts +1 -0
- package/dist/commands/tasks/create.js +7 -0
- package/dist/commands/tasks/deliverable/add.js +22 -4
- package/dist/commands/tasks/deliverable/list.js +23 -2
- package/dist/commands/tasks/events/append.js +31 -3
- package/dist/commands/tasks/expectations/assess.d.ts +1 -1
- package/dist/commands/tasks/expectations/assess.js +33 -7
- package/dist/commands/tasks/expectations.js +110 -10
- package/dist/commands/tasks/output.d.ts +0 -1
- package/dist/commands/tasks/output.js +21 -1
- package/dist/commands/tasks/report.js +3 -1
- package/dist/commands/tasks/result/show.js +20 -2
- package/dist/commands/tasks/resume/save.js +11 -1
- package/dist/commands/tasks/self-schedule.js +7 -4
- package/dist/commands/tasks/show.js +19 -0
- package/dist/commands/tasks/timeline.js +9 -1
- package/dist/commands/tasks/updates/add.js +23 -2
- package/dist/lib/dedicated-machines.d.ts +66 -0
- package/dist/lib/dedicated-machines.js +161 -0
- package/dist/lib/harnesses.d.ts +5 -0
- package/dist/lib/harnesses.js +5 -2
- package/dist/lib/task-legacy.d.ts +24 -0
- package/dist/lib/task-legacy.js +48 -0
- package/dist/lib/tasks.d.ts +32 -0
- package/dist/lib/tasks.js +47 -1
- package/dist/lib/work-sync.d.ts +70 -0
- package/dist/lib/work-sync.js +29 -0
- package/dist/node_modules/@skrr-ai/data-provider/index.js +2079 -2055
- package/oclif.manifest.json +12229 -11213
- 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})
|
|
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',
|
package/dist/base-command.js
CHANGED
|
@@ -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
|
-
|
|
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({
|
|
@@ -1521,6 +1532,42 @@ function isRetryableFailure(status, body) {
|
|
|
1521
1532
|
return false;
|
|
1522
1533
|
return status === 408 || status === 425 || status === 429 || !!(status && status >= 500);
|
|
1523
1534
|
}
|
|
1535
|
+
/**
|
|
1536
|
+
* Render server-supplied field validation into the human error.
|
|
1537
|
+
*
|
|
1538
|
+
* The canonical Task routes answer a schema rejection with
|
|
1539
|
+
* `{error: 'Invalid request data', details: <zod issues>}` — which names the
|
|
1540
|
+
* exact field — but the human path used to print only the generic sentence, so
|
|
1541
|
+
* `tasks updates add --type finding` failed with `Invalid request data` and the
|
|
1542
|
+
* operator had to re-run the identical command with `--json` to learn that
|
|
1543
|
+
* `data.evidenceRefs` was missing. The answer was already on the wire; only the
|
|
1544
|
+
* renderer threw it away.
|
|
1545
|
+
*
|
|
1546
|
+
* Shape-sniffed rather than typed against zod: `details` also carries unrelated
|
|
1547
|
+
* payloads (outbox ids, oclif suggestions), and those must pass through
|
|
1548
|
+
* untouched rather than render as pseudo-fields.
|
|
1549
|
+
*/
|
|
1550
|
+
function formatValidationIssues(details) {
|
|
1551
|
+
const issues = Array.isArray(details)
|
|
1552
|
+
? details
|
|
1553
|
+
: Array.isArray(details?.details)
|
|
1554
|
+
? details.details
|
|
1555
|
+
: Array.isArray(details?.issues)
|
|
1556
|
+
? details.issues
|
|
1557
|
+
: [];
|
|
1558
|
+
const lines = [];
|
|
1559
|
+
for (const issue of issues) {
|
|
1560
|
+
const row = issue;
|
|
1561
|
+
const message = typeof row?.message === 'string' ? row.message : '';
|
|
1562
|
+
if (!message)
|
|
1563
|
+
continue;
|
|
1564
|
+
const path = Array.isArray(row.path) ? row.path.join('.') : '';
|
|
1565
|
+
lines.push(path ? ` ${path}: ${message}` : ` ${message}`);
|
|
1566
|
+
if (lines.length === 10)
|
|
1567
|
+
break;
|
|
1568
|
+
}
|
|
1569
|
+
return lines.length > 0 ? `\n${lines.join('\n')}` : '';
|
|
1570
|
+
}
|
|
1524
1571
|
function detailsFromPrettyError(options) {
|
|
1525
1572
|
const details = {};
|
|
1526
1573
|
for (const key of ['suggestions', 'ref', 'showHelp']) {
|
|
@@ -1537,6 +1584,32 @@ function detailsFromCaughtError(err) {
|
|
|
1537
1584
|
details.exit = err.oclif.exit;
|
|
1538
1585
|
return Object.keys(details).length > 0 ? details : undefined;
|
|
1539
1586
|
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Where a removed flag's capability went. Keyed by flag name so it fires on
|
|
1589
|
+
* oclif's own `Nonexistent flags:` message without parsing its grammar.
|
|
1590
|
+
*/
|
|
1591
|
+
const RETIRED_FLAG_REPLACEMENTS = {
|
|
1592
|
+
'--verdict': '--verdict is gone: a review decision and a domain conclusion are different facts. ' +
|
|
1593
|
+
'Use `tasks review --decision accepted|changes_requested` for acceptance, and ' +
|
|
1594
|
+
'--conclusion-type/--conclusion-json for a conclusion such as NO-SHIP.',
|
|
1595
|
+
'--outcome': '--outcome is now --summary.',
|
|
1596
|
+
'--finding': '--finding is gone: record findings as `tasks updates add --type finding`.',
|
|
1597
|
+
'--evidence': '--evidence is now --evidence-ref on the Result, or an evidenceRefs entry.',
|
|
1598
|
+
'--next': '--next is now --remaining.',
|
|
1599
|
+
'--deliverables': '--deliverables is now --deliverable <task-resource-link-id>, recorded first with ' +
|
|
1600
|
+
'`tasks deliverable add`.',
|
|
1601
|
+
'--artifact': '--artifact is now --deliverable <task-resource-link-id>, recorded first with ' +
|
|
1602
|
+
'`tasks deliverable add`.',
|
|
1603
|
+
'--supersede': '--supersede is implicit: submitting again creates a new Result version.',
|
|
1604
|
+
};
|
|
1605
|
+
function retiredFlagHint(message) {
|
|
1606
|
+
if (!/nonexistent flag/i.test(message))
|
|
1607
|
+
return null;
|
|
1608
|
+
const hits = Object.keys(RETIRED_FLAG_REPLACEMENTS).filter((flag) => new RegExp(`${flag}(?![\\w-])`).test(message));
|
|
1609
|
+
if (hits.length === 0)
|
|
1610
|
+
return null;
|
|
1611
|
+
return hits.map((flag) => ` ${RETIRED_FLAG_REPLACEMENTS[flag]}`).join('\n');
|
|
1612
|
+
}
|
|
1540
1613
|
function parseCliErrorCode(err) {
|
|
1541
1614
|
if (err.name && err.name !== 'Error') {
|
|
1542
1615
|
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,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
|
+
}
|