@skrr-ai/cli 0.1.25 → 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 (70) hide show
  1. package/dist/base-command.js +4 -5
  2. package/dist/commands/code/install.js +13 -0
  3. package/dist/commands/harnesses/leases/billing.d.ts +9 -6
  4. package/dist/commands/harnesses/leases/billing.js +19 -24
  5. package/dist/commands/machines/dedicated/attach.d.ts +28 -0
  6. package/dist/commands/machines/dedicated/attach.js +75 -0
  7. package/dist/commands/machines/dedicated/catalog.d.ts +17 -0
  8. package/dist/commands/machines/dedicated/catalog.js +75 -0
  9. package/dist/commands/machines/dedicated/cp.d.ts +22 -0
  10. package/dist/commands/machines/dedicated/cp.js +76 -0
  11. package/dist/commands/machines/dedicated/create.d.ts +6 -2
  12. package/dist/commands/machines/dedicated/create.js +29 -20
  13. package/dist/commands/machines/dedicated/destroy.d.ts +6 -2
  14. package/dist/commands/machines/dedicated/destroy.js +41 -24
  15. package/dist/commands/machines/dedicated/exec.d.ts +28 -0
  16. package/dist/commands/machines/dedicated/exec.js +105 -0
  17. package/dist/commands/machines/dedicated/grow.d.ts +6 -2
  18. package/dist/commands/machines/dedicated/grow.js +14 -19
  19. package/dist/commands/machines/dedicated/health-check.d.ts +2 -2
  20. package/dist/commands/machines/dedicated/health-check.js +16 -14
  21. package/dist/commands/machines/dedicated/incident-close.d.ts +3 -2
  22. package/dist/commands/machines/dedicated/incident-close.js +11 -14
  23. package/dist/commands/machines/dedicated/index.js +37 -16
  24. package/dist/commands/machines/dedicated/list.d.ts +2 -2
  25. package/dist/commands/machines/dedicated/list.js +28 -17
  26. package/dist/commands/machines/dedicated/restart.d.ts +5 -2
  27. package/dist/commands/machines/dedicated/restart.js +8 -19
  28. package/dist/commands/machines/dedicated/show.d.ts +2 -2
  29. package/dist/commands/machines/dedicated/show.js +28 -30
  30. package/dist/commands/machines/dedicated/sign-in.d.ts +19 -0
  31. package/dist/commands/machines/dedicated/sign-in.js +49 -0
  32. package/dist/commands/machines/dedicated/snapshot.d.ts +5 -2
  33. package/dist/commands/machines/dedicated/snapshot.js +11 -19
  34. package/dist/commands/machines/dedicated/spending-limit.d.ts +22 -0
  35. package/dist/commands/machines/dedicated/spending-limit.js +50 -0
  36. package/dist/commands/machines/dedicated/start.d.ts +5 -2
  37. package/dist/commands/machines/dedicated/start.js +8 -19
  38. package/dist/commands/machines/dedicated/stop.d.ts +5 -2
  39. package/dist/commands/machines/dedicated/stop.js +8 -19
  40. package/dist/commands/machines/dedicated/terminal.d.ts +22 -0
  41. package/dist/commands/machines/dedicated/terminal.js +42 -0
  42. package/dist/commands/tasks/list.js +27 -0
  43. package/dist/lib/daemonBroker.d.ts +8 -0
  44. package/dist/lib/daemonBroker.js +2 -2
  45. package/dist/lib/dedicated-copy.d.ts +22 -0
  46. package/dist/lib/dedicated-copy.js +115 -0
  47. package/dist/lib/dedicated-lease-command.d.ts +50 -0
  48. package/dist/lib/dedicated-lease-command.js +158 -0
  49. package/dist/lib/dedicated-machines.d.ts +248 -12
  50. package/dist/lib/dedicated-machines.js +385 -25
  51. package/dist/lib/dedicated-terminal.d.ts +89 -0
  52. package/dist/lib/dedicated-terminal.js +275 -0
  53. package/dist/lib/dedicated-wait.d.ts +72 -0
  54. package/dist/lib/dedicated-wait.js +195 -0
  55. package/dist/lib/harnesses.d.ts +6 -0
  56. package/dist/lib/node-adapter.js +1 -1
  57. package/dist/lib/sky-code.d.ts +30 -1
  58. package/dist/lib/sky-code.js +44 -2
  59. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  60. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +2 -1
  61. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +10 -0
  62. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +17 -1
  63. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  64. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  65. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +10 -0
  66. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +16 -0
  67. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  68. package/dist/node_modules/@skrr-ai/data-provider/index.js +2613 -2608
  69. package/oclif.manifest.json +23016 -22295
  70. 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;
@@ -86,6 +86,33 @@ function emptyTasksMessage(flags, bin = 'skrr') {
86
86
  lines.push(' no longer has that status. Try `--execution-state active` (running now) or');
87
87
  lines.push(` \`--execution-state recovered\` (reaped, startable), or \`${bin} tasks active\`.`);
88
88
  }
89
+ else if (typeof flags.status === 'string' &&
90
+ flags.status.length > 0 &&
91
+ !flags['execution-state']) {
92
+ // A filter that matches nothing and a board that IS empty print the same
93
+ // thing, and the caller cannot tell which they are looking at. Observed:
94
+ // `--status todo` on a board whose open column is `backlog` said `No tasks.`
95
+ // while twelve were open, and it was believed.
96
+ //
97
+ // Not fixed by validating the value, for two reasons. A status is a
98
+ // Space-owned workflow-state id — TASK_STATUSES is a legacy default set, not
99
+ // a closed vocabulary — so a space may legitimately define one we have never
100
+ // heard of. And `todo` IS a built-in, so refusing unknown values would not
101
+ // have caught the case that prompted this. What distinguishes the two
102
+ // readings is naming the filter and how to drop it.
103
+ //
104
+ // Silent when `--execution-state` is also set, to leave the exact bare
105
+ // string the branch above deliberately produces for that combination. The
106
+ // same ambiguity exists there, but overturning a pinned decision is not
107
+ // this change's business.
108
+ lines.push('');
109
+ lines.push(`Note: nothing matched \`--status ${flags.status}\`. A status is a workflow-state id the`);
110
+ lines.push(' space owns, so a board need not use this one at all.');
111
+ lines.push(' → See what this scope actually holds: the same command without `--status`.');
112
+ if (!data_provider_1.TASK_STATUSES.includes(flags.status)) {
113
+ lines.push(` (built-in ids: ${data_provider_1.TASK_STATUSES.join(', ')})`);
114
+ }
115
+ }
89
116
  return lines.join('\n');
90
117
  }
91
118
  /**
@@ -36,6 +36,7 @@
36
36
  * liveness with `process.kill(pid, 0)` to filter stale files left behind
37
37
  * by a force-killed daemon.
38
38
  */
39
+ import { type AuthBackend } from './auth-storage';
39
40
  import { type CliConfig } from './config';
40
41
  /**
41
42
  * Wire-shape of the bootstrap file. Mirrors
@@ -86,6 +87,13 @@ export interface DaemonBrokerResult {
86
87
  * the mint/confirm split, where the mint still revoked eagerly.
87
88
  */
88
89
  familyId?: string;
90
+ /**
91
+ * Where `attemptDaemonBrokerLoginAndPersist` actually stored the credential.
92
+ * Callers label the token's source from this, not from the platform: Keychain
93
+ * only exists on macOS, and even there a failed Keychain write falls back to
94
+ * the file.
95
+ */
96
+ storedIn?: Exclude<AuthBackend, 'none'>;
89
97
  }
90
98
  /**
91
99
  * Explicit reasons the broker path could fail. These exist to keep the
@@ -527,7 +527,7 @@ async function attemptDaemonBrokerLoginAndPersist(opts) {
527
527
  if (!serverOrigin) {
528
528
  throw new Error('Daemon-broker credential persistence requires a valid CLI baseURL.');
529
529
  }
530
- (0, auth_storage_1.writeToBackend)({
530
+ const storedIn = (0, auth_storage_1.writeToBackend)({
531
531
  token: outcome.accessToken,
532
532
  refreshToken: outcome.refreshToken,
533
533
  ...(expiryToEpochMs(outcome.accessExpiresAt) !== undefined
@@ -548,7 +548,7 @@ async function attemptDaemonBrokerLoginAndPersist(opts) {
548
548
  familyId: outcome.familyId,
549
549
  });
550
550
  }
551
- return outcome;
551
+ return storedIn === 'none' ? outcome : { ...outcome, storedIn };
552
552
  }
553
553
  // ---------------------------------------------------------------------
554
554
  // Auto-broker on first command (BaseCommand.init hook)