@skrr-ai/cli 0.1.24 → 0.1.26

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 (87) hide show
  1. package/dist/base-command.d.ts +4 -4
  2. package/dist/base-command.js +11 -10
  3. package/dist/commands/code/install.js +13 -0
  4. package/dist/commands/harnesses/leases/billing.d.ts +9 -6
  5. package/dist/commands/harnesses/leases/billing.js +19 -24
  6. package/dist/commands/machines/dedicated/attach.d.ts +28 -0
  7. package/dist/commands/machines/dedicated/attach.js +75 -0
  8. package/dist/commands/machines/dedicated/catalog.d.ts +17 -0
  9. package/dist/commands/machines/dedicated/catalog.js +75 -0
  10. package/dist/commands/machines/dedicated/cp.d.ts +22 -0
  11. package/dist/commands/machines/dedicated/cp.js +76 -0
  12. package/dist/commands/machines/dedicated/create.d.ts +6 -2
  13. package/dist/commands/machines/dedicated/create.js +29 -20
  14. package/dist/commands/machines/dedicated/destroy.d.ts +6 -2
  15. package/dist/commands/machines/dedicated/destroy.js +41 -24
  16. package/dist/commands/machines/dedicated/exec.d.ts +28 -0
  17. package/dist/commands/machines/dedicated/exec.js +105 -0
  18. package/dist/commands/machines/dedicated/grow.d.ts +6 -2
  19. package/dist/commands/machines/dedicated/grow.js +14 -19
  20. package/dist/commands/machines/dedicated/health-check.d.ts +2 -2
  21. package/dist/commands/machines/dedicated/health-check.js +16 -14
  22. package/dist/commands/machines/dedicated/incident-close.d.ts +3 -2
  23. package/dist/commands/machines/dedicated/incident-close.js +11 -14
  24. package/dist/commands/machines/dedicated/index.js +37 -16
  25. package/dist/commands/machines/dedicated/list.d.ts +2 -2
  26. package/dist/commands/machines/dedicated/list.js +28 -17
  27. package/dist/commands/machines/dedicated/restart.d.ts +5 -2
  28. package/dist/commands/machines/dedicated/restart.js +8 -19
  29. package/dist/commands/machines/dedicated/show.d.ts +2 -2
  30. package/dist/commands/machines/dedicated/show.js +28 -30
  31. package/dist/commands/machines/dedicated/sign-in.d.ts +19 -0
  32. package/dist/commands/machines/dedicated/sign-in.js +49 -0
  33. package/dist/commands/machines/dedicated/snapshot.d.ts +5 -2
  34. package/dist/commands/machines/dedicated/snapshot.js +11 -19
  35. package/dist/commands/machines/dedicated/spending-limit.d.ts +22 -0
  36. package/dist/commands/machines/dedicated/spending-limit.js +50 -0
  37. package/dist/commands/machines/dedicated/start.d.ts +5 -2
  38. package/dist/commands/machines/dedicated/start.js +8 -19
  39. package/dist/commands/machines/dedicated/stop.d.ts +5 -2
  40. package/dist/commands/machines/dedicated/stop.js +8 -19
  41. package/dist/commands/machines/dedicated/terminal.d.ts +22 -0
  42. package/dist/commands/machines/dedicated/terminal.js +42 -0
  43. package/dist/commands/spaces/auto-executor/preview.d.ts +8 -0
  44. package/dist/commands/spaces/auto-executor/preview.js +41 -0
  45. package/dist/commands/spaces/task-rollups.d.ts +14 -0
  46. package/dist/commands/spaces/task-rollups.js +66 -0
  47. package/dist/commands/spaces/work-sync/telemetry.js +22 -0
  48. package/dist/commands/tasks/assign.js +1 -1
  49. package/dist/commands/tasks/create.js +10 -4
  50. package/dist/commands/tasks/list.js +27 -0
  51. package/dist/lib/api-fetch.js +9 -1
  52. package/dist/lib/assignee-resolver.d.ts +7 -6
  53. package/dist/lib/daemonBroker.d.ts +28 -0
  54. package/dist/lib/daemonBroker.js +60 -19
  55. package/dist/lib/dedicated-copy.d.ts +22 -0
  56. package/dist/lib/dedicated-copy.js +115 -0
  57. package/dist/lib/dedicated-lease-command.d.ts +50 -0
  58. package/dist/lib/dedicated-lease-command.js +158 -0
  59. package/dist/lib/dedicated-machines.d.ts +248 -12
  60. package/dist/lib/dedicated-machines.js +385 -25
  61. package/dist/lib/dedicated-terminal.d.ts +89 -0
  62. package/dist/lib/dedicated-terminal.js +275 -0
  63. package/dist/lib/dedicated-wait.d.ts +72 -0
  64. package/dist/lib/dedicated-wait.js +195 -0
  65. package/dist/lib/harnesses.d.ts +6 -0
  66. package/dist/lib/idempotency-scope.d.ts +10 -0
  67. package/dist/lib/idempotency-scope.js +16 -0
  68. package/dist/lib/node-adapter.d.ts +1 -1
  69. package/dist/lib/node-adapter.js +13 -11
  70. package/dist/lib/sky-code.d.ts +30 -1
  71. package/dist/lib/sky-code.js +44 -2
  72. package/dist/lib/triggers.js +7 -0
  73. package/dist/lib/work-sync.d.ts +35 -0
  74. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  75. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +2 -1
  76. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +71 -21
  77. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +10 -0
  78. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +17 -1
  79. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  80. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  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/dist/esm/spawnEnv.d.ts +10 -0
  83. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +16 -0
  84. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  85. package/dist/node_modules/@skrr-ai/data-provider/index.js +2657 -2596
  86. package/oclif.manifest.json +5075 -4294
  87. package/package.json +1 -1
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../../base-command");
4
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
5
5
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
- class DedicatedMachinesRestart extends base_command_1.BaseCommand {
7
- static description = 'Restart a Dedicated Runtime lease';
6
+ class DedicatedMachinesRestart extends dedicated_lease_command_1.DedicatedLeaseCommand {
7
+ static description = 'Restart a Dedicated Runtime to recover availability. Files survive; memory, shells and background jobs do not.';
8
8
  static examples = [
9
9
  '<%= config.bin %> machines dedicated restart <lease-id>',
10
- '<%= config.bin %> machines dedicated restart <lease-id> --json',
10
+ '<%= config.bin %> machines dedicated restart <lease-id> --wait',
11
+ '<%= config.bin %> machines dedicated restart <lease-id> --wait --timeout 10m --json',
11
12
  ];
12
13
  static args = {
13
14
  lease: core_1.Args.string({
@@ -18,25 +19,13 @@ class DedicatedMachinesRestart extends base_command_1.BaseCommand {
18
19
  };
19
20
  static flags = {
20
21
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
22
+ ...dedicated_lease_command_1.dedicatedWaitFlags,
21
23
  };
22
24
  async run() {
23
25
  this.requireAuth();
24
26
  const { args, flags } = await this.parse(DedicatedMachinesRestart);
25
- let response;
26
- try {
27
- response = await (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'restart');
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)}.`);
27
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'restart', this.scopeFrom(flags)));
28
+ await this.reportLeaseAction(response, flags, { kind: 'running' }, 'Restarting');
40
29
  }
41
30
  }
42
31
  exports.default = DedicatedMachinesRestart;
@@ -1,5 +1,5 @@
1
- import { BaseCommand } from '../../../base-command';
2
- export default class DedicatedMachinesShow extends BaseCommand {
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ export default class DedicatedMachinesShow extends DedicatedLeaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../../base-command");
4
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
5
5
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
- class DedicatedMachinesShow extends base_command_1.BaseCommand {
7
- static description = 'Show one Dedicated Runtime lease';
6
+ const harnesses_1 = require("../../../lib/harnesses");
7
+ class DedicatedMachinesShow extends dedicated_lease_command_1.DedicatedLeaseCommand {
8
+ static description = 'Show one Dedicated Runtime lease: state, size, workspace, spend against the cap, health, deletion clock and the engines its daemon registered';
8
9
  static examples = [
9
10
  '<%= config.bin %> machines dedicated show <lease-id>',
10
11
  '<%= config.bin %> machines dedicated show <lease-id> --json',
@@ -16,43 +17,40 @@ class DedicatedMachinesShow extends base_command_1.BaseCommand {
16
17
  required: true,
17
18
  }),
18
19
  };
19
- static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
20
+ static flags = {
21
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
22
+ };
20
23
  async run() {
21
24
  this.requireAuth();
22
25
  const { args, flags } = await this.parse(DedicatedMachinesShow);
23
- let response;
24
- try {
25
- response = await (0, dedicated_machines_1.getDedicatedRuntime)(args.lease);
26
- }
27
- catch (err) {
28
- const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
29
- if (message)
30
- this.error(message, { exit: 1 });
31
- this.handleApiError(err);
32
- }
26
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.getDedicatedRuntime)(args.lease, this.scopeFrom(flags)));
33
27
  const lease = response?.lease;
34
28
  if (!lease) {
35
29
  this.error('Dedicated Runtime lease not found.', { exit: 1 });
36
30
  }
37
- if (flags.json) {
38
- this.log(JSON.stringify(response, null, 2));
39
- return;
40
- }
41
- this.log((0, dedicated_machines_1.dedicatedLeaseDisplayName)(lease));
42
- this.log(` id ${(0, dedicated_machines_1.dedicatedLeaseId)(lease)}`);
43
- this.log(` status ${(0, dedicated_machines_1.dedicatedLeaseState)(lease)}`);
44
- if (lease.storage?.retentionClass) {
45
- this.log(` retention ${lease.storage.retentionClass}`);
46
- }
47
- if (lease.storage?.backupProfile) {
48
- this.log(` backup ${lease.storage.backupProfile}`);
31
+ // The harness rows are what an agent attaches to and what a terminal opens
32
+ // on, and the lease payload deliberately names no daemon. Best-effort: a
33
+ // failed harness read must not hide the lease the caller asked for.
34
+ let harnesses = [];
35
+ try {
36
+ const listed = (await (0, harnesses_1.listHarnesses)());
37
+ harnesses = Array.isArray(listed) ? listed : (listed?.harnesses ?? []);
49
38
  }
50
- if (lease.storage?.lastBackupAt) {
51
- this.log(` last backup ${lease.storage.lastBackupAt}`);
39
+ catch {
40
+ harnesses = [];
52
41
  }
53
- if (lease.billing?.monthlySpendLimitCents != null) {
54
- this.log(` monthly cap ${lease.billing.monthlySpendLimitCents} cents`);
42
+ if (flags.json) {
43
+ const engines = (0, dedicated_machines_1.dedicatedLeaseHarnesses)(lease, harnesses).map((harness) => ({
44
+ harnessId: harness._id,
45
+ provider: harness.provider,
46
+ status: harness.status,
47
+ lastSeenAt: harness.lastSeenAt,
48
+ }));
49
+ this.log(JSON.stringify({ ...response, harnesses: engines }, null, 2));
50
+ return;
55
51
  }
52
+ for (const line of (0, dedicated_machines_1.describeDedicatedLease)(lease, harnesses))
53
+ this.log(line);
56
54
  }
57
55
  }
58
56
  exports.default = DedicatedMachinesShow;
@@ -0,0 +1,19 @@
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ /**
3
+ * `skrr machines dedicated sign-in` — the lease card's Sign in menu.
4
+ *
5
+ * Opens the machine's terminal and types the tool's sign-in command once the
6
+ * shell is ready. The commands are the SAME fixed strings the web offers,
7
+ * declared once in `@skrr-ai/data-provider`; each is a device-code or
8
+ * paste-a-code flow, because the machine has no browser.
9
+ */
10
+ export default class DedicatedMachinesSignIn 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
+ tool: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
16
+ };
17
+ static flags: {};
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 data_provider_1 = require("@skrr-ai/data-provider");
5
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
6
+ const TOOLS = data_provider_1.DEDICATED_RUNTIME_SIGN_IN_PRESETS.map((preset) => preset.tool);
7
+ /**
8
+ * `skrr machines dedicated sign-in` — the lease card's Sign in menu.
9
+ *
10
+ * Opens the machine's terminal and types the tool's sign-in command once the
11
+ * shell is ready. The commands are the SAME fixed strings the web offers,
12
+ * declared once in `@skrr-ai/data-provider`; each is a device-code or
13
+ * paste-a-code flow, because the machine has no browser.
14
+ */
15
+ class DedicatedMachinesSignIn extends dedicated_lease_command_1.DedicatedLeaseCommand {
16
+ static description = 'Sign in to GitHub CLI, Claude Code or Codex on a Dedicated Runtime, in an interactive terminal. The sign-in is shared by everything that runs on the machine, agents included.';
17
+ static examples = [
18
+ '<%= config.bin %> machines dedicated sign-in <lease-id> github',
19
+ '<%= config.bin %> machines dedicated sign-in <lease-id> claude',
20
+ '<%= config.bin %> machines dedicated sign-in <lease-id> codex',
21
+ ];
22
+ static args = {
23
+ lease: core_1.Args.string({
24
+ description: 'Dedicated Runtime lease id',
25
+ required: true,
26
+ ignoreStdin: true,
27
+ }),
28
+ tool: core_1.Args.string({
29
+ description: `What to sign in to: ${TOOLS.join(', ')}`,
30
+ required: true,
31
+ options: TOOLS,
32
+ ignoreStdin: true,
33
+ }),
34
+ };
35
+ static flags = {};
36
+ async run() {
37
+ this.requireAuth();
38
+ const { args, flags } = await this.parse(DedicatedMachinesSignIn);
39
+ const preset = data_provider_1.DEDICATED_RUNTIME_SIGN_IN_PRESETS.find((candidate) => candidate.tool === args.tool);
40
+ if (!preset) {
41
+ this.error(`Unknown tool "${args.tool}". Choose one of: ${TOOLS.join(', ')}.`, { exit: 2 });
42
+ }
43
+ // Said before, not after: once the code is entered the credential already
44
+ // sits on the workspace volume, in every later snapshot.
45
+ process.stderr.write(`${preset.label} sign-in is stored on the workspace volume and shared by everything running as skrr-workload on this machine, including agents. Prefer a narrowly-scoped account or token.\n`);
46
+ await this.openDedicatedTerminal(args.lease, flags, preset.command);
47
+ }
48
+ }
49
+ exports.default = DedicatedMachinesSignIn;
@@ -1,11 +1,14 @@
1
- import { BaseCommand } from '../../../base-command';
2
- export default class DedicatedMachinesSnapshot extends BaseCommand {
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ export default class DedicatedMachinesSnapshot extends DedicatedLeaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
6
  lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
+ wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
12
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
13
  };
11
14
  run(): Promise<void>;
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../../base-command");
4
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
5
5
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
- class DedicatedMachinesSnapshot extends base_command_1.BaseCommand {
7
- static description = 'Snapshot a Dedicated Runtime lease workspace';
6
+ class DedicatedMachinesSnapshot extends dedicated_lease_command_1.DedicatedLeaseCommand {
7
+ static description = 'Take a recovery point of a Dedicated Runtime workspace before something risky. With --wait, succeeds only once a new recovery point is recorded.';
8
8
  static examples = [
9
9
  '<%= config.bin %> machines dedicated snapshot <lease-id>',
10
- '<%= config.bin %> machines dedicated snapshot <lease-id> --json',
10
+ '<%= config.bin %> machines dedicated snapshot <lease-id> --wait',
11
+ '<%= config.bin %> machines dedicated snapshot <lease-id> --wait --json',
11
12
  ];
12
13
  static args = {
13
14
  lease: core_1.Args.string({
@@ -18,25 +19,16 @@ class DedicatedMachinesSnapshot extends base_command_1.BaseCommand {
18
19
  };
19
20
  static flags = {
20
21
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
22
+ ...dedicated_lease_command_1.dedicatedWaitFlags,
21
23
  };
22
24
  async run() {
23
25
  this.requireAuth();
24
26
  const { args, flags } = await this.parse(DedicatedMachinesSnapshot);
25
- let response;
26
- try {
27
- response = await (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'snapshot');
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)}.`);
27
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'snapshot', this.scopeFrom(flags)));
28
+ // A snapshot returns the lease to the state it left, so the state cannot say
29
+ // whether it worked. The recovery point's timestamp can: the 202 carries the
30
+ // previous one, and success is a newer one.
31
+ await this.reportLeaseAction(response, flags, { kind: 'snapshot', previousBackupAt: response?.lease?.storage?.lastBackupAt ?? null }, 'Snapshotting');
40
32
  }
41
33
  }
42
34
  exports.default = DedicatedMachinesSnapshot;
@@ -0,0 +1,22 @@
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ /**
3
+ * `skrr machines dedicated spending-limit` — change the monthly cap after create.
4
+ *
5
+ * The cap is the ONE guardrail on a machine with no wall-clock TTL: when a
6
+ * month's spend reaches it, the platform stops compute and keeps the workspace.
7
+ * It could be set at create and changed from the web lease card, but not from
8
+ * here — so an operator who hit it at 2am had to find a browser to raise it,
9
+ * and an agent watching its own machine could not lower it.
10
+ */
11
+ export default class DedicatedMachinesSpendingLimit extends DedicatedLeaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static args: {
15
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
16
+ };
17
+ static flags: {
18
+ cents: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
@@ -0,0 +1,50 @@
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
+ /**
7
+ * `skrr machines dedicated spending-limit` — change the monthly cap after create.
8
+ *
9
+ * The cap is the ONE guardrail on a machine with no wall-clock TTL: when a
10
+ * month's spend reaches it, the platform stops compute and keeps the workspace.
11
+ * It could be set at create and changed from the web lease card, but not from
12
+ * here — so an operator who hit it at 2am had to find a browser to raise it,
13
+ * and an agent watching its own machine could not lower it.
14
+ */
15
+ class DedicatedMachinesSpendingLimit extends dedicated_lease_command_1.DedicatedLeaseCommand {
16
+ static description = 'Change the monthly spending cap of a Dedicated Runtime. At the cap, compute stops and the workspace is kept.';
17
+ static examples = [
18
+ '<%= config.bin %> machines dedicated spending-limit <lease-id> --cents 30000',
19
+ '<%= config.bin %> machines dedicated spending-limit <lease-id> --cents 5000 --json',
20
+ ];
21
+ static args = {
22
+ lease: core_1.Args.string({
23
+ description: 'Dedicated Runtime lease id',
24
+ required: true,
25
+ ignoreStdin: true,
26
+ }),
27
+ };
28
+ static flags = {
29
+ cents: core_1.Flags.integer({
30
+ description: 'New monthly cap in cents (30000 = $300). Refused below what this month has already spent or is projected to.',
31
+ required: true,
32
+ min: 1,
33
+ }),
34
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
35
+ };
36
+ async run() {
37
+ this.requireAuth();
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)));
40
+ if (flags.json) {
41
+ this.log(JSON.stringify(response, null, 2));
42
+ return;
43
+ }
44
+ const lease = response?.lease;
45
+ this.log(`Dedicated Runtime ${(0, dedicated_machines_1.dedicatedLeaseId)(lease) || args.lease} spending cap updated.`);
46
+ if (lease)
47
+ this.log(` ${(0, dedicated_machines_1.dedicatedSpendSummary)(lease)}`);
48
+ }
49
+ }
50
+ exports.default = DedicatedMachinesSpendingLimit;
@@ -1,11 +1,14 @@
1
- import { BaseCommand } from '../../../base-command';
2
- export default class DedicatedMachinesStart extends BaseCommand {
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ export default class DedicatedMachinesStart extends DedicatedLeaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
6
  lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
+ wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
12
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
13
  };
11
14
  run(): Promise<void>;
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../../base-command");
4
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
5
5
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
- class DedicatedMachinesStart extends base_command_1.BaseCommand {
7
- static description = 'Start a Dedicated Runtime lease';
6
+ class DedicatedMachinesStart extends dedicated_lease_command_1.DedicatedLeaseCommand {
7
+ static description = 'Start a stopped Dedicated Runtime. Files under /workspace are as you left them; nothing that was running is.';
8
8
  static examples = [
9
9
  '<%= config.bin %> machines dedicated start <lease-id>',
10
- '<%= config.bin %> machines dedicated start <lease-id> --json',
10
+ '<%= config.bin %> machines dedicated start <lease-id> --wait',
11
+ '<%= config.bin %> machines dedicated start <lease-id> --wait --timeout 10m --json',
11
12
  ];
12
13
  static args = {
13
14
  lease: core_1.Args.string({
@@ -18,25 +19,13 @@ class DedicatedMachinesStart extends base_command_1.BaseCommand {
18
19
  };
19
20
  static flags = {
20
21
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
22
+ ...dedicated_lease_command_1.dedicatedWaitFlags,
21
23
  };
22
24
  async run() {
23
25
  this.requireAuth();
24
26
  const { args, flags } = await this.parse(DedicatedMachinesStart);
25
- let response;
26
- try {
27
- response = await (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'start');
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)}.`);
27
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'start', this.scopeFrom(flags)));
28
+ await this.reportLeaseAction(response, flags, { kind: 'running' }, 'Starting');
40
29
  }
41
30
  }
42
31
  exports.default = DedicatedMachinesStart;
@@ -1,11 +1,14 @@
1
- import { BaseCommand } from '../../../base-command';
2
- export default class DedicatedMachinesStop extends BaseCommand {
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ export default class DedicatedMachinesStop extends DedicatedLeaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static args: {
6
6
  lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
7
  };
8
8
  static flags: {
9
+ wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ timeout: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ interval: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
12
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
13
  };
11
14
  run(): Promise<void>;
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
- const base_command_1 = require("../../../base-command");
4
+ const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
5
5
  const dedicated_machines_1 = require("../../../lib/dedicated-machines");
6
- class DedicatedMachinesStop extends base_command_1.BaseCommand {
7
- static description = 'Stop a Dedicated Runtime lease';
6
+ class DedicatedMachinesStop extends dedicated_lease_command_1.DedicatedLeaseCommand {
7
+ static description = 'Stop a Dedicated Runtime: compute billing ends, the workspace volume and its storage billing stay. Running processes end.';
8
8
  static examples = [
9
9
  '<%= config.bin %> machines dedicated stop <lease-id>',
10
- '<%= config.bin %> machines dedicated stop <lease-id> --json',
10
+ '<%= config.bin %> machines dedicated stop <lease-id> --wait',
11
+ '<%= config.bin %> machines dedicated stop <lease-id> --wait --timeout 10m --json',
11
12
  ];
12
13
  static args = {
13
14
  lease: core_1.Args.string({
@@ -18,25 +19,13 @@ class DedicatedMachinesStop extends base_command_1.BaseCommand {
18
19
  };
19
20
  static flags = {
20
21
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
22
+ ...dedicated_lease_command_1.dedicatedWaitFlags,
21
23
  };
22
24
  async run() {
23
25
  this.requireAuth();
24
26
  const { args, flags } = await this.parse(DedicatedMachinesStop);
25
- let response;
26
- try {
27
- response = await (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'stop');
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)}.`);
27
+ const response = await this.callDedicated(() => (0, dedicated_machines_1.performDedicatedLeaseAction)(args.lease, 'stop', this.scopeFrom(flags)));
28
+ await this.reportLeaseAction(response, flags, { kind: 'stopped' }, 'Stopping');
40
29
  }
41
30
  }
42
31
  exports.default = DedicatedMachinesStop;
@@ -0,0 +1,22 @@
1
+ import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
2
+ /**
3
+ * `skrr machines dedicated terminal` — the web lease card's "Open terminal",
4
+ * from a terminal.
5
+ *
6
+ * `exec` has no TTY and cannot drive anything that prompts, which left
7
+ * `gh auth login`, a REPL, a dev server's interactive setup and `claude` itself
8
+ * reachable only from a browser. This opens the same real PTY the web does,
9
+ * through the same relay and the same admission.
10
+ */
11
+ export default class DedicatedMachinesTerminal extends DedicatedLeaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static args: {
15
+ lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
16
+ };
17
+ static flags: {
18
+ cwd: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ command: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ };
21
+ run(): Promise<void>;
22
+ }
@@ -0,0 +1,42 @@
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
+ /**
6
+ * `skrr machines dedicated terminal` — the web lease card's "Open terminal",
7
+ * from a terminal.
8
+ *
9
+ * `exec` has no TTY and cannot drive anything that prompts, which left
10
+ * `gh auth login`, a REPL, a dev server's interactive setup and `claude` itself
11
+ * reachable only from a browser. This opens the same real PTY the web does,
12
+ * through the same relay and the same admission.
13
+ */
14
+ class DedicatedMachinesTerminal extends dedicated_lease_command_1.DedicatedLeaseCommand {
15
+ static description = 'Open an interactive shell on a Dedicated Runtime (a real PTY, as skrr-workload). Ctrl-] closes it.';
16
+ static examples = [
17
+ '<%= config.bin %> machines dedicated terminal <lease-id>',
18
+ '<%= config.bin %> machines dedicated terminal <lease-id> --cwd /workspace/repos/app',
19
+ '<%= config.bin %> machines dedicated terminal <lease-id> --command "npm run dev"',
20
+ ];
21
+ static args = {
22
+ lease: core_1.Args.string({
23
+ description: 'Dedicated Runtime lease id',
24
+ required: true,
25
+ ignoreStdin: true,
26
+ }),
27
+ };
28
+ static flags = {
29
+ cwd: core_1.Flags.string({
30
+ description: 'Directory to start in (defaults to HOME, /workspace/user-data)',
31
+ }),
32
+ command: core_1.Flags.string({
33
+ description: 'A command to type into the shell once it is ready, as if you typed it. The shell stays open after it.',
34
+ }),
35
+ };
36
+ async run() {
37
+ this.requireAuth();
38
+ const { args, flags } = await this.parse(DedicatedMachinesTerminal);
39
+ await this.openDedicatedTerminal(args.lease, flags, flags.command);
40
+ }
41
+ }
42
+ exports.default = DedicatedMachinesTerminal;
@@ -1,3 +1,4 @@
1
+ import { type SpaceAutoExecutorRefillState } from '@skrr-ai/data-provider';
1
2
  import { BaseCommand } from '../../../base-command';
2
3
  export default class SpacesAutoExecutorPreview extends BaseCommand {
3
4
  static description: string;
@@ -10,3 +11,10 @@ export default class SpacesAutoExecutorPreview extends BaseCommand {
10
11
  };
11
12
  run(): Promise<void>;
12
13
  }
14
+ /**
15
+ * The refill latch in words: whether start work is owed, why it last woke, and
16
+ * what each recent task-pool change did. This is how "the board is not picking
17
+ * up work" becomes a question with an answer. `undefined` is a server that does
18
+ * not report it; `null` is one that could not read it, and says so.
19
+ */
20
+ export declare function refillLines(refill: SpaceAutoExecutorRefillState | null | undefined): string[];
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.refillLines = refillLines;
3
4
  const core_1 = require("@oclif/core");
4
5
  const data_provider_1 = require("@skrr-ai/data-provider");
5
6
  const base_command_1 = require("../../../base-command");
@@ -49,6 +50,8 @@ class SpacesAutoExecutorPreview extends base_command_1.BaseCommand {
49
50
  if (capacity.budget && !capacity.budget.unlimited) {
50
51
  this.log(`Budget: ${capacity.budget.consumedStarts}/${capacity.budget.maxStarts} starts used this round`);
51
52
  }
53
+ for (const line of refillLines(result.refill))
54
+ this.log(line);
52
55
  const { actions, summary } = plan;
53
56
  this.log('');
54
57
  this.log(`Board: ${summary.readyCount} ready · ${summary.unassignedCount} unassigned · ` +
@@ -70,6 +73,44 @@ class SpacesAutoExecutorPreview extends base_command_1.BaseCommand {
70
73
  }
71
74
  }
72
75
  exports.default = SpacesAutoExecutorPreview;
76
+ /**
77
+ * The refill latch in words: whether start work is owed, why it last woke, and
78
+ * what each recent task-pool change did. This is how "the board is not picking
79
+ * up work" becomes a question with an answer. `undefined` is a server that does
80
+ * not report it; `null` is one that could not read it, and says so.
81
+ */
82
+ function refillLines(refill) {
83
+ if (refill === undefined)
84
+ return [];
85
+ if (refill === null)
86
+ return ['Refill: state unavailable (the server could not read it)'];
87
+ const owed = refill.requestedGeneration - refill.processedGeneration;
88
+ const lines = [
89
+ `Refill: ${refill.pending
90
+ ? `${owed} wake${owed === 1 ? '' : 's'} owed (generation ${refill.processedGeneration} → ${refill.requestedGeneration})`
91
+ : `caught up (generation ${refill.processedGeneration})`}${refill.lastReason ? ` · last: ${refill.lastReason}` : ''}`,
92
+ ];
93
+ if (refill.notBefore)
94
+ lines.push(` deferred until ${refill.notBefore}`);
95
+ if (refill.waitingOnAgentIds.length) {
96
+ lines.push(` waiting on agent capacity: ${refill.waitingOnAgentIds.join(', ')}`);
97
+ }
98
+ const wakes = refill.taskPool.recentWakes;
99
+ if (wakes.length) {
100
+ lines.push('');
101
+ lines.push(`Recent task-pool changes (${wakes.length}):`);
102
+ for (const wake of wakes) {
103
+ const effect = wake.refillRelevant === true
104
+ ? 'can start work'
105
+ : wake.refillRelevant === false
106
+ ? 'nothing to start'
107
+ : 'unclassified';
108
+ const outcome = wake.status === 'processed' ? (wake.decision ?? 'processed') : wake.status;
109
+ lines.push(` - #${wake.generation} ${wake.mutation} · ${effect} · ${outcome}`);
110
+ }
111
+ }
112
+ return lines;
113
+ }
73
114
  function taskLine(task) {
74
115
  return `${task.identifier ? `${task.identifier} ` : ''}${task.title}`;
75
116
  }