@ornncompute/cli 1.0.75 → 1.0.107

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 (54) hide show
  1. package/README.md +38 -5
  2. package/package.json +4 -2
  3. package/src/admin-capacity-reservations.mjs +4 -1
  4. package/src/admin-command-handlers.mjs +4 -0
  5. package/src/admin-node-diagnostics.mjs +1 -5
  6. package/src/admin-node-lifecycle.mjs +23 -125
  7. package/src/admin-node-sanitize.mjs +243 -0
  8. package/src/admin-ssh.mjs +113 -0
  9. package/src/api-client.mjs +4 -1
  10. package/src/catalog-shell.mjs +6 -6
  11. package/src/evidence-commands.mjs +4 -6
  12. package/src/external-bucket-commands.mjs +71 -23
  13. package/src/interaction-runtime.mjs +3 -0
  14. package/src/kubernetes-commands.mjs +16 -83
  15. package/src/machine-reference.mjs +33 -56
  16. package/src/slurm-commands.mjs +13 -2
  17. package/src/vm-commands.mjs +39 -59
  18. package/vendor/api-client/commerce.js +745 -0
  19. package/vendor/capabilities/cli.js +7756 -7
  20. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +0 -101
  21. package/vendor/capabilities/capabilities/admin-enrollment.js +0 -322
  22. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +0 -88
  23. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +0 -137
  24. package/vendor/capabilities/capabilities/admin.js +0 -91
  25. package/vendor/capabilities/capabilities/cli.js +0 -156
  26. package/vendor/capabilities/capabilities/clusters.js +0 -248
  27. package/vendor/capabilities/capabilities/commerce-market.js +0 -405
  28. package/vendor/capabilities/capabilities/compute.js +0 -523
  29. package/vendor/capabilities/capabilities/credits.js +0 -83
  30. package/vendor/capabilities/capabilities/evidence.js +0 -145
  31. package/vendor/capabilities/capabilities/external-buckets.js +0 -191
  32. package/vendor/capabilities/capabilities/fleet.js +0 -386
  33. package/vendor/capabilities/capabilities/identity.js +0 -129
  34. package/vendor/capabilities/capabilities/listings.js +0 -398
  35. package/vendor/capabilities/capabilities/locality.js +0 -42
  36. package/vendor/capabilities/capabilities/market-shared.js +0 -46
  37. package/vendor/capabilities/capabilities/markets.js +0 -482
  38. package/vendor/capabilities/capabilities/mounts.js +0 -176
  39. package/vendor/capabilities/capabilities/native-listing.js +0 -99
  40. package/vendor/capabilities/capabilities/networks.js +0 -1264
  41. package/vendor/capabilities/capabilities/observability.js +0 -253
  42. package/vendor/capabilities/capabilities/organization-invites.js +0 -53
  43. package/vendor/capabilities/capabilities/reservation-list.js +0 -68
  44. package/vendor/capabilities/capabilities/staff-shared.js +0 -64
  45. package/vendor/capabilities/capabilities/tokens.js +0 -161
  46. package/vendor/capabilities/capabilities/users.js +0 -157
  47. package/vendor/capabilities/capabilities/volumes.js +0 -178
  48. package/vendor/capabilities/capability.js +0 -99
  49. package/vendor/capabilities/cli-catalog.js +0 -73
  50. package/vendor/capabilities/cli-migrations.js +0 -264
  51. package/vendor/capabilities/names.js +0 -6
  52. package/vendor/capabilities/software-catalog.js +0 -82
  53. package/vendor/capabilities/spec-catalog.js +0 -151
  54. package/vendor/capabilities/supplier-directory.js +0 -20
@@ -1,91 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
3
- import { listFacilitiesCapability, listNodesCapability, listSuppliersCapability } from "./fleet.js";
4
- import { logsLatestCapability, telemetryLatestCapability } from "./observability.js";
5
- import { tokensListCapability } from "./tokens.js";
6
- import { organizationListCapability, usersListCapability } from "./users.js";
7
- export const ADMIN_CLI_ROOTS = [
8
- { name: "users" },
9
- { name: "organizations" },
10
- { name: "suppliers" },
11
- { name: "facilities" },
12
- { name: "nodes" },
13
- { name: "enrollment-tokens" },
14
- { name: "capacity-offers" },
15
- { name: "reservations" },
16
- ];
17
- function adminHelp(command, outcome, human, automation, acceptedReferences = []) {
18
- return {
19
- audience: "admin",
20
- category: "resource",
21
- command,
22
- outcome,
23
- human,
24
- automation,
25
- acceptedReferences,
26
- };
27
- }
28
- function withAdminBinding(capability, help) {
29
- if (!help.command)
30
- throw new Error(`${capability.id} requires a canonical CLI command`);
31
- return {
32
- ...capability,
33
- cli: {
34
- command: [...help.command],
35
- vnext: help,
36
- },
37
- };
38
- }
39
- export const adminUsersListCapability = withAdminBinding(usersListCapability, adminHelp(["admin", "users", "list"], "List users in the Authorization directory; pass next_offset as --offset to continue.", "ornn admin users list [--query QUERY] [--organization UUID] [--limit 25] [--offset OFFSET]", "ornn admin users list --query QUERY --limit 25 [--offset OFFSET] --format json"));
40
- export const adminOrganizationsListCapability = withAdminBinding(organizationListCapability, adminHelp(["admin", "organizations", "list"], "List organizations in the Authorization directory; pass next_offset as --offset to continue.", "ornn admin organizations list [--query QUERY] [--role consumer|supplier] [--approved true|false] [--ids UUID,...] [--limit 25] [--offset OFFSET]", "ornn admin organizations list --query QUERY --limit 25 [--offset OFFSET] --format json"));
41
- export const adminSuppliersListCapability = withAdminBinding(listSuppliersCapability, adminHelp(["admin", "suppliers", "list"], "List supplier organizations visible to staff; pass next_offset as --offset to continue.", "ornn admin suppliers list [--limit 50] [--offset OFFSET]", "ornn admin suppliers list --limit 50 --offset OFFSET --format json"));
42
- export const adminFacilitiesListCapability = withAdminBinding(listFacilitiesCapability, adminHelp(["admin", "facilities", "list"], "List facilities visible to staff.", "ornn admin facilities list [--supplier UUID] [--limit 50] [--cursor CURSOR]", "ornn admin facilities list --limit 50 --format json"));
43
- export const adminNodesListCapability = withAdminBinding(listNodesCapability, adminHelp(["admin", "nodes", "list"], "List enrolled, ghost, and off-grid nodes.", "ornn admin nodes list [--supplier UUID] [--facility FACILITY] [--status STATUS] [--reservation UUID] [--limit 50] [--cursor CURSOR]", "ornn admin nodes list --limit 50 [--cursor CURSOR] --format json"));
44
- const nodeInput = z.object({ node_id: z.string().min(1) });
45
- export const adminNodeHealthCapability = defineCapability({
46
- id: "nodes.health",
47
- domain: "fleet",
48
- roles: ["admin"],
49
- description: "Read lifecycle and readiness facts for one enrolled node.",
50
- mutation: "read",
51
- http: { method: "GET", path: "/nodes/{id}" },
52
- cli: {
53
- command: ["admin", "nodes", "health"],
54
- vnext: adminHelp(["admin", "nodes", "health"], "Inspect lifecycle and readiness facts for one node.", "ornn admin nodes health <node-id>", "ornn admin nodes health <node-id> --format json", ["canonical node ID"]),
55
- },
56
- mcp: false,
57
- slack: false,
58
- input: nodeInput,
59
- execute: async (ctx, input) => {
60
- const parsed = nodeInput.parse(input);
61
- return ctx.fetch(`/nodes/${encodeURIComponent(parsed.node_id)}`, { method: "GET" });
62
- },
63
- });
64
- export const adminNodeMetricsCapability = withAdminBinding(telemetryLatestCapability, adminHelp(["admin", "nodes", "metrics"], "Read a bounded telemetry window for one node.", "ornn admin nodes metrics <node-id> [--span 15m] [--start TIME --end TIME] [--max-points 240]", "ornn admin nodes metrics <node-id> --span 15m [--start TIME --end TIME] --max-points 240 --format json", ["canonical node ID"]));
65
- export const adminNodeLogsCapability = withAdminBinding(logsLatestCapability, adminHelp(["admin", "nodes", "logs"], "Read one bounded node log page.", "ornn admin nodes logs <node-id> [--stream kernel|serial] [--count 200] [--before TIME] [--cursor CURSOR]", "ornn admin nodes logs <node-id> --stream kernel --count 200 [--before TIME] [--cursor CURSOR] --format json", ["canonical node ID"]));
66
- export const adminEnrollmentTokensListCapability = withAdminBinding(tokensListCapability, adminHelp(["admin", "enrollment-tokens", "list"], "List enrollment-token metadata without token bytes.", "ornn admin enrollment-tokens list [--limit 50] [--cursor CURSOR]", "ornn admin enrollment-tokens list --limit 50 --format json"));
67
- export const adminCapabilities = [
68
- adminUsersListCapability,
69
- adminOrganizationsListCapability,
70
- adminSuppliersListCapability,
71
- adminFacilitiesListCapability,
72
- adminNodesListCapability,
73
- adminNodeHealthCapability,
74
- adminNodeMetricsCapability,
75
- adminNodeLogsCapability,
76
- adminEnrollmentTokensListCapability,
77
- ];
78
- const replacements = {
79
- "facilities.list": adminFacilitiesListCapability,
80
- "logs.latest": adminNodeLogsCapability,
81
- "nodes.list": adminNodesListCapability,
82
- "supplier.list": adminSuppliersListCapability,
83
- "telemetry.latest": adminNodeMetricsCapability,
84
- "tokens.list": adminEnrollmentTokensListCapability,
85
- "users.list": adminUsersListCapability,
86
- "organization.list": adminOrganizationsListCapability,
87
- };
88
- /** Applies canonical admin CLI bindings without changing MCP or Slack identities. */
89
- export function bindAdminCapabilities(capabilities) {
90
- return capabilities.map((capability) => replacements[capability.id] ?? capability);
91
- }
@@ -1,156 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
3
- export const CLI_MACHINE_SCHEMA = "ornn.cli/v1";
4
- const emptyInput = z.object({});
5
- function requireCliRuntime(context) {
6
- if (!context.cli) {
7
- throw new Error("This capability must execute through the Ornn CLI runtime.");
8
- }
9
- return context.cli;
10
- }
11
- const updateInput = z.object({
12
- $positionals: z.array(z.string()).max(0).default([]),
13
- major: z.boolean().optional(),
14
- });
15
- const completionInput = z
16
- .object({
17
- $positionals: z.tuple([z.enum(["bash", "fish", "zsh"])]),
18
- })
19
- .transform(({ $positionals }) => ({ shell: $positionals[0] }));
20
- export const versionCapability = defineCapability({
21
- id: "cli.version",
22
- domain: "cli",
23
- roles: ["user"],
24
- description: "Show the CLI version and machine-output contract.",
25
- mutation: "local",
26
- input: emptyInput,
27
- cli: {
28
- command: ["version"],
29
- vnext: {
30
- audience: "customer",
31
- category: "platform",
32
- outcome: "Identify the installed CLI and its machine-output contract.",
33
- human: "ornn version",
34
- automation: "ornn version --format json",
35
- related: ["status", "resources"],
36
- order: 20,
37
- },
38
- },
39
- mcp: false,
40
- slack: false,
41
- execute: async (context) => {
42
- const runtime = requireCliRuntime(context);
43
- return {
44
- version: runtime.version,
45
- machine_schema: runtime.machineSchema,
46
- update_channel: runtime.updateChannel,
47
- };
48
- },
49
- });
50
- export const updateCapability = defineCapability({
51
- id: "cli.update",
52
- domain: "cli",
53
- roles: ["user"],
54
- description: "Update the installed CLI through its detected package manager.",
55
- mutation: "local",
56
- input: updateInput,
57
- cli: {
58
- command: ["update"],
59
- vnext: {
60
- arguments: "semantic",
61
- audience: "customer",
62
- category: "platform",
63
- outcome: "Update the installed CLI with explicit acknowledgement for a major crossing.",
64
- human: "ornn update [--major]",
65
- automation: "ornn update --format human [--major]",
66
- related: ["version"],
67
- order: 25,
68
- },
69
- },
70
- mcp: false,
71
- slack: false,
72
- execute: async (context, input) => {
73
- const runtime = requireCliRuntime(context);
74
- if (!runtime.update) {
75
- throw new Error("This capability must execute through the Ornn CLI update runtime.");
76
- }
77
- return runtime.update(input);
78
- },
79
- });
80
- export const completionCapability = defineCapability({
81
- id: "cli.completion",
82
- domain: "cli",
83
- roles: ["user"],
84
- description: "Generate shell completion from canonical catalog commands.",
85
- mutation: "local",
86
- input: completionInput,
87
- cli: {
88
- command: ["completion"],
89
- vnext: {
90
- arguments: "semantic",
91
- audience: "customer",
92
- category: "platform",
93
- outcome: "Generate bash, fish, or zsh completion from the canonical command catalog.",
94
- human: "ornn completion <bash|fish|zsh> --format human",
95
- automation: "ornn completion <bash|fish|zsh> --format json",
96
- related: ["resources"],
97
- order: 27,
98
- },
99
- },
100
- mcp: false,
101
- slack: false,
102
- execute: async (context, input) => {
103
- const runtime = requireCliRuntime(context);
104
- if (!runtime.completion) {
105
- throw new Error("This capability must execute through the Ornn CLI completion runtime.");
106
- }
107
- return runtime.completion(input);
108
- },
109
- });
110
- export const resourcesCapability = defineCapability({
111
- id: "cli.resources",
112
- domain: "cli",
113
- roles: ["user"],
114
- description: "List registered advanced customer resource commands.",
115
- mutation: "local",
116
- input: emptyInput,
117
- cli: {
118
- command: ["resources"],
119
- vnext: {
120
- audience: "customer",
121
- category: "platform",
122
- outcome: "Discover advanced customer resource commands without dispatching a generic request.",
123
- human: "ornn resources",
124
- automation: "ornn resources --format json",
125
- related: ["status", "version"],
126
- order: 30,
127
- },
128
- },
129
- mcp: false,
130
- slack: false,
131
- execute: async (context) => {
132
- const runtime = requireCliRuntime(context);
133
- const resources = [];
134
- for (const capability of runtime.catalog) {
135
- const binding = capability.cli;
136
- const help = binding?.vnext;
137
- if (!binding || help?.audience !== "customer" || help.category !== "resource") {
138
- continue;
139
- }
140
- resources.push({
141
- command: binding.command.join(" "),
142
- outcome: help.outcome,
143
- human: help.human,
144
- automation: help.automation,
145
- });
146
- }
147
- resources.sort((left, right) => left.command.localeCompare(right.command));
148
- return { resources };
149
- },
150
- });
151
- export const cliShellCapabilities = [
152
- versionCapability,
153
- updateCapability,
154
- completionCapability,
155
- resourcesCapability,
156
- ];
@@ -1,248 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability, preview, } from "../capability.js";
3
- const reservationInput = z.object({
4
- reservation_id: z.string().min(1),
5
- reservationId: z.string().optional(),
6
- });
7
- const launchInput = reservationInput.extend({
8
- network_mode: z.enum(["public", "private"]).optional(),
9
- node_count: z.number().int().positive().optional(),
10
- node_ids: z.array(z.string()).optional(),
11
- });
12
- const clusterCliInput = z
13
- .object({
14
- $positionals: z.array(z.string()).optional(),
15
- cursor: z.string().optional(),
16
- guided: z.boolean().optional(),
17
- idempotencyKey: z.string().optional(),
18
- limit: z.union([z.string(), z.number()]).optional(),
19
- machine: z.string().optional(),
20
- machines: z.string().optional(),
21
- network: z.enum(["public", "private"]).optional(),
22
- noWait: z.boolean().optional(),
23
- nodes: z.union([z.string(), z.number()]).optional(),
24
- output: z.string().optional(),
25
- overwrite: z.boolean().optional(),
26
- timeout: z.string().optional(),
27
- wait: z.boolean().optional(),
28
- yes: z.boolean().optional(),
29
- })
30
- .strict();
31
- function reservationId(input) {
32
- return (input.reservation_id || input.reservationId || "").trim();
33
- }
34
- function clusterPath(kind, id, suffix) {
35
- return `/${kind}/reservations/${encodeURIComponent(id)}/${suffix}`;
36
- }
37
- function clusterExecutor(context) {
38
- const runtime = context.cli?.interaction;
39
- if (!runtime?.cluster) {
40
- throw new Error("This capability must execute through the Ornn CLI cluster runtime.");
41
- }
42
- return runtime.cluster.bind(runtime);
43
- }
44
- function clusterCliCapability({ acceptedReferences = [], automation, command, description, human, id, mutation, outcome, related = [], review, }) {
45
- return defineCapability({
46
- id,
47
- domain: "clusters",
48
- roles: ["user"],
49
- description,
50
- mutation,
51
- input: clusterCliInput,
52
- cli: {
53
- command,
54
- vnext: {
55
- arguments: "semantic",
56
- audience: "customer",
57
- category: "resource",
58
- outcome,
59
- human,
60
- automation,
61
- acceptedReferences,
62
- ...(review ? { review } : {}),
63
- resumableStates: ["working", "ready", "partial", "failed", "ended"],
64
- related,
65
- },
66
- },
67
- mcp: false,
68
- slack: false,
69
- execute: async (context, input) => clusterExecutor(context)(id, input),
70
- });
71
- }
72
- function clusterPair(kind, domain) {
73
- const label = kind === "slurm" ? "Slurm" : "Kubernetes";
74
- return [
75
- defineCapability({
76
- id: `${kind}.eligible`,
77
- domain,
78
- roles: ["user"],
79
- description: `${label} launch is blocked only when the reservation's nodes already belong to a different controller. Returns eligible=false with reason other_cluster in that case.`,
80
- mutation: "read",
81
- http: { method: "GET", path: `/${kind}/reservations/{id}/cluster/eligible` },
82
- slack: false,
83
- input: reservationInput,
84
- execute: async (ctx, input) => {
85
- const parsed = reservationInput.parse(input);
86
- return ctx.fetch(clusterPath(kind, reservationId(parsed), "cluster/eligible"), {
87
- method: "GET",
88
- });
89
- },
90
- }),
91
- defineCapability({
92
- id: `${kind}.launch`,
93
- domain,
94
- roles: ["user"],
95
- description: `Launch a ${label} controller on a reservation. Blocked when ${kind}.eligible reports other_cluster.`,
96
- mutation: "preview-confirm",
97
- http: { method: "POST", path: `/${kind}/reservations/{id}/cluster/launch` },
98
- slack: false,
99
- input: launchInput,
100
- execute: async (ctx, input) => {
101
- const parsed = launchInput.parse(input);
102
- const id = reservationId(parsed);
103
- const eligibility = (await ctx.fetch(clusterPath(kind, id, "cluster/eligible"), {
104
- method: "GET",
105
- }));
106
- if (eligibility?.eligible === false && eligibility.reason === "other_cluster") {
107
- return { ok: false, error: "other_cluster", reason: "other_cluster" };
108
- }
109
- if (!ctx.confirmed) {
110
- return preview(`${kind}.launch`, { reservation_id: id });
111
- }
112
- return ctx.fetch(clusterPath(kind, id, "cluster/launch"), {
113
- method: "POST",
114
- body: {
115
- network_mode: parsed.network_mode ?? "public",
116
- ...(parsed.node_count != null ? { node_count: parsed.node_count } : {}),
117
- ...(parsed.node_ids?.length ? { node_ids: parsed.node_ids } : {}),
118
- },
119
- });
120
- },
121
- }),
122
- defineCapability({
123
- id: `${kind}.teardown`,
124
- domain,
125
- roles: ["user"],
126
- description: `Tear down the ${label} controller for a reservation.`,
127
- mutation: "preview-confirm",
128
- http: { method: "POST", path: `/${kind}/reservations/{id}/cluster/teardown` },
129
- slack: false,
130
- input: reservationInput,
131
- execute: async (ctx, input) => {
132
- const parsed = reservationInput.parse(input);
133
- const id = reservationId(parsed);
134
- if (!ctx.confirmed) {
135
- return preview(`${kind}.teardown`, { reservation_id: id });
136
- }
137
- return ctx.fetch(clusterPath(kind, id, "cluster/teardown"), { method: "POST" });
138
- },
139
- }),
140
- defineCapability({
141
- id: `${kind}.show`,
142
- domain,
143
- roles: ["user"],
144
- description: `Show the ${label} controller for a reservation.`,
145
- mutation: "read",
146
- http: { method: "GET", path: `/${kind}/reservations/{id}/cluster` },
147
- slack: false,
148
- input: reservationInput,
149
- execute: async (ctx, input) => {
150
- const parsed = reservationInput.parse(input);
151
- return ctx.fetch(clusterPath(kind, reservationId(parsed), "cluster"), { method: "GET" });
152
- },
153
- }),
154
- ];
155
- }
156
- export const clusterCliCapabilities = [
157
- clusterCliCapability({
158
- id: "clusters.list",
159
- command: ["clusters", "list"],
160
- description: "List customer-safe Kubernetes and Slurm cluster facts in one bounded page.",
161
- mutation: "read",
162
- outcome: "List clusters without generated names, credentials, or controller details.",
163
- human: "ornn clusters list [--limit <1-500>] [--cursor <cursor>]",
164
- automation: "ornn clusters list --limit 50 --format json",
165
- related: ["clusters show", "clusters wait"],
166
- }),
167
- clusterCliCapability({
168
- id: "clusters.show",
169
- command: ["clusters", "show"],
170
- description: "Inspect one exact cluster through safe customer facts.",
171
- mutation: "read",
172
- outcome: "Show lifecycle and membership without exposing credentials or controller internals.",
173
- human: "ornn clusters show [<cluster-id>] [--guided]",
174
- automation: "ornn clusters show <cluster-id> --format json",
175
- acceptedReferences: ["canonical cluster ID", "invocation-local guided choice"],
176
- related: ["clusters wait", "connect"],
177
- }),
178
- clusterCliCapability({
179
- id: "clusters.wait",
180
- command: ["clusters", "wait"],
181
- description: "Wait locally for one cluster to become usable without cancelling remote work.",
182
- mutation: "read",
183
- outcome: "Wait for usable native access with bounded timeout and interruption results.",
184
- human: "ornn clusters wait [<cluster-id>] [--guided] [--timeout <duration>]",
185
- automation: "ornn clusters wait <cluster-id> --timeout <duration> --format json",
186
- acceptedReferences: ["canonical cluster ID", "invocation-local guided choice"],
187
- related: ["clusters show", "connect"],
188
- }),
189
- clusterCliCapability({
190
- id: "clusters.eligible_machines",
191
- command: ["clusters", "eligible-machines"],
192
- description: "Read the authoritative same-reservation eligible-machine projection.",
193
- mutation: "read",
194
- outcome: "List only canonical machine IDs and hostnames currently eligible for this cluster.",
195
- human: "ornn clusters eligible-machines [<cluster-id>] [--guided] [--limit <1-500>] [--cursor <cursor>]",
196
- automation: "ornn clusters eligible-machines <cluster-id> --limit 50 --format json",
197
- acceptedReferences: ["canonical cluster ID", "invocation-local guided choice"],
198
- related: ["clusters add-node", "clusters remove-node"],
199
- }),
200
- clusterCliCapability({
201
- id: "clusters.add_node",
202
- command: ["clusters", "add-node"],
203
- description: "Reconcile one exact cluster membership-increase goal.",
204
- mutation: "preview-confirm",
205
- outcome: "Add one currently eligible machine, or rediscover that exact membership goal.",
206
- human: "ornn clusters add-node [<cluster-id>] [<machine-id-or-hostname>] [--guided] [--no-wait]",
207
- automation: "ornn clusters add-node <cluster-id> <machine-id> --idempotency-key <key> --format json",
208
- acceptedReferences: [
209
- "canonical cluster ID",
210
- "canonical machine ID",
211
- "exact unique eligible hostname",
212
- "invocation-local guided choice",
213
- ],
214
- review: "Review the exact cluster, selected machine, and resulting membership count.",
215
- related: ["clusters eligible-machines", "clusters remove-node"],
216
- }),
217
- clusterCliCapability({
218
- id: "clusters.remove_node",
219
- command: ["clusters", "remove-node"],
220
- description: "Reconcile one exact cluster membership-reduction goal.",
221
- mutation: "preview-confirm",
222
- outcome: "Remove one exact member, or rediscover that exact membership goal.",
223
- human: "ornn clusters remove-node [<cluster-id>] [<machine-id-or-hostname>] [--guided] [--no-wait]",
224
- automation: "ornn clusters remove-node <cluster-id> <machine-id> --idempotency-key <key> --format json",
225
- acceptedReferences: [
226
- "canonical cluster ID",
227
- "canonical machine ID",
228
- "exact unique member hostname",
229
- "invocation-local guided choice",
230
- ],
231
- review: "Review the exact cluster, removed machine, access reduction, and resulting membership count.",
232
- related: ["clusters eligible-machines", "clusters add-node"],
233
- }),
234
- clusterCliCapability({
235
- id: "clusters.teardown",
236
- command: ["clusters", "teardown"],
237
- description: "Tear down one cluster without surrendering its capacity reservation.",
238
- mutation: "preview-confirm",
239
- outcome: "End cluster lifecycle while reporting partial member failures and continuing reservation charges.",
240
- human: "ornn clusters teardown [<cluster-id>] [--guided] [--no-wait]",
241
- automation: "ornn clusters teardown <cluster-id> --idempotency-key <key> --format json",
242
- acceptedReferences: ["canonical cluster ID", "invocation-local guided choice"],
243
- review: "The cluster and native access end; the capacity reservation and its charges remain.",
244
- related: ["clusters show", "reservations show"],
245
- }),
246
- ];
247
- export const slurmCapabilities = clusterPair("slurm", "slurm");
248
- export const kubernetesCapabilities = clusterPair("kubernetes", "kubernetes");