@ornncompute/cli 1.0.72 → 1.0.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -24
- package/package.json +4 -2
- package/src/admin-capacity-reservations.mjs +6 -13
- package/src/admin-command-handlers.mjs +2 -1
- package/src/admin-credits.mjs +1 -2
- package/src/admin-enrollment.mjs +22 -30
- package/src/admin-mutations.mjs +6 -56
- package/src/admin-node-diagnostics.mjs +3 -41
- package/src/admin-node-lifecycle.mjs +40 -160
- package/src/admin-node-sanitize.mjs +243 -0
- package/src/admin-shell.mjs +39 -32
- package/src/catalog-shell.mjs +6 -6
- package/src/evidence-commands.mjs +4 -6
- package/src/external-bucket-commands.mjs +76 -96
- package/src/interaction-runtime.mjs +5 -37
- package/src/kubernetes-commands.mjs +25 -183
- package/src/launch-mode-handlers.mjs +0 -1
- package/src/machine-reference.mjs +33 -56
- package/src/mount-commands.mjs +25 -131
- package/src/slurm-commands.mjs +13 -2
- package/src/storage-commands.mjs +2 -87
- package/src/vm-commands.mjs +48 -101
- package/vendor/api-client/commerce.js +743 -0
- package/vendor/capabilities/cli.js +7688 -7
- package/vendor/capabilities/capabilities/admin-capacity-reservations.js +0 -101
- package/vendor/capabilities/capabilities/admin-enrollment.js +0 -321
- package/vendor/capabilities/capabilities/admin-node-diagnostics.js +0 -88
- package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +0 -235
- package/vendor/capabilities/capabilities/admin.js +0 -91
- package/vendor/capabilities/capabilities/cli.js +0 -156
- package/vendor/capabilities/capabilities/clusters.js +0 -248
- package/vendor/capabilities/capabilities/commerce-market.js +0 -405
- package/vendor/capabilities/capabilities/compute.js +0 -523
- package/vendor/capabilities/capabilities/credits.js +0 -78
- package/vendor/capabilities/capabilities/evidence.js +0 -145
- package/vendor/capabilities/capabilities/external-buckets.js +0 -191
- package/vendor/capabilities/capabilities/fleet.js +0 -306
- package/vendor/capabilities/capabilities/identity.js +0 -129
- package/vendor/capabilities/capabilities/listings.js +0 -398
- package/vendor/capabilities/capabilities/locality.js +0 -42
- package/vendor/capabilities/capabilities/market-shared.js +0 -46
- package/vendor/capabilities/capabilities/markets.js +0 -482
- package/vendor/capabilities/capabilities/mounts.js +0 -176
- package/vendor/capabilities/capabilities/native-listing.js +0 -99
- package/vendor/capabilities/capabilities/networks.js +0 -1264
- package/vendor/capabilities/capabilities/observability.js +0 -218
- package/vendor/capabilities/capabilities/organization-invites.js +0 -53
- package/vendor/capabilities/capabilities/reservation-list.js +0 -68
- package/vendor/capabilities/capabilities/staff-shared.js +0 -64
- package/vendor/capabilities/capabilities/tokens.js +0 -165
- package/vendor/capabilities/capabilities/users.js +0 -159
- package/vendor/capabilities/capabilities/volumes.js +0 -178
- package/vendor/capabilities/capability.js +0 -99
- package/vendor/capabilities/cli-catalog.js +0 -73
- package/vendor/capabilities/cli-migrations.js +0 -264
- package/vendor/capabilities/names.js +0 -6
- package/vendor/capabilities/software-catalog.js +0 -82
- package/vendor/capabilities/spec-catalog.js +0 -151
- package/vendor/capabilities/supplier-directory.js +0 -20
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { defineCapability, } from "../capability.js";
|
|
3
|
-
const positionals = z.array(z.string()).default([]);
|
|
4
|
-
export const evidenceInput = z
|
|
5
|
-
.object({
|
|
6
|
-
$positionals: positionals,
|
|
7
|
-
before: z.string().optional(),
|
|
8
|
-
count: z.string().optional(),
|
|
9
|
-
cursor: z.string().optional(),
|
|
10
|
-
end: z.string().optional(),
|
|
11
|
-
follow: z.boolean().optional(),
|
|
12
|
-
guided: z.boolean().optional(),
|
|
13
|
-
interval: z.string().optional(),
|
|
14
|
-
limit: z.string().optional(),
|
|
15
|
-
maxPoints: z.string().optional(),
|
|
16
|
-
start: z.string().optional(),
|
|
17
|
-
stream: z.enum(["kernel", "serial"]).optional(),
|
|
18
|
-
timeout: z.string().optional(),
|
|
19
|
-
})
|
|
20
|
-
.strict();
|
|
21
|
-
function runtime(context) {
|
|
22
|
-
const interaction = context.cli?.interaction;
|
|
23
|
-
if (!interaction?.evidence)
|
|
24
|
-
throw new Error("The CLI evidence runtime is unavailable.");
|
|
25
|
-
return interaction;
|
|
26
|
-
}
|
|
27
|
-
function execute(command) {
|
|
28
|
-
return (context, input) => runtime(context).evidence(command, input, context);
|
|
29
|
-
}
|
|
30
|
-
function cliOnly({ automation, category, command, description, human, id, order, outcome, references, related, }) {
|
|
31
|
-
const executor = command.length === 1 ? "check" : `${command[0]}.${command[1]}`;
|
|
32
|
-
return defineCapability({
|
|
33
|
-
id,
|
|
34
|
-
domain: "observability",
|
|
35
|
-
roles: ["user"],
|
|
36
|
-
description,
|
|
37
|
-
mutation: "read",
|
|
38
|
-
input: evidenceInput,
|
|
39
|
-
cli: {
|
|
40
|
-
command,
|
|
41
|
-
vnext: {
|
|
42
|
-
arguments: "semantic",
|
|
43
|
-
audience: "customer",
|
|
44
|
-
category,
|
|
45
|
-
order,
|
|
46
|
-
outcome,
|
|
47
|
-
human,
|
|
48
|
-
automation,
|
|
49
|
-
acceptedReferences: references,
|
|
50
|
-
resumableStates: ["no data", "unavailable", "streaming", "ended", "interrupted"],
|
|
51
|
-
related,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
mcp: false,
|
|
55
|
-
slack: false,
|
|
56
|
-
execute: execute(executor),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
export const checkCapability = cliOnly({
|
|
60
|
-
id: "evidence.check",
|
|
61
|
-
command: ["check"],
|
|
62
|
-
category: "journey",
|
|
63
|
-
order: 4,
|
|
64
|
-
description: "Compose lifecycle, reachability, authoritative health, metrics, and logs for one machine or cluster.",
|
|
65
|
-
outcome: "Check one exact machine or cluster without turning missing evidence into health.",
|
|
66
|
-
human: "ornn check [<canonical-resource-id-or-exact-hostname>] [--follow] [--start <time> --end <time>]",
|
|
67
|
-
automation: "ornn check <canonical-machine-or-cluster-id> --start <time> --end <time> --max-points 240 --limit 200 --format json",
|
|
68
|
-
references: [
|
|
69
|
-
"canonical machine ID",
|
|
70
|
-
"exact unique machine hostname",
|
|
71
|
-
"canonical cluster ID",
|
|
72
|
-
"invocation-local guided choice",
|
|
73
|
-
],
|
|
74
|
-
related: [
|
|
75
|
-
"connect",
|
|
76
|
-
"machines metrics",
|
|
77
|
-
"machines logs",
|
|
78
|
-
"clusters metrics",
|
|
79
|
-
"clusters logs",
|
|
80
|
-
"cost",
|
|
81
|
-
],
|
|
82
|
-
});
|
|
83
|
-
export const machineMetricsCapability = cliOnly({
|
|
84
|
-
id: "evidence.machine_metrics",
|
|
85
|
-
command: ["machines", "metrics"],
|
|
86
|
-
category: "resource",
|
|
87
|
-
order: 560,
|
|
88
|
-
description: "Read or follow bounded customer-safe metrics for one exact machine.",
|
|
89
|
-
outcome: "Return normalized machine metrics with explicit evidence state and window.",
|
|
90
|
-
human: "ornn machines metrics [<machine-id-or-exact-hostname>] [--guided] [--start <time> --end <time>] [--max-points <1-500>] [--follow]",
|
|
91
|
-
automation: "ornn machines metrics <canonical-machine-id> --start <time> --end <time> --max-points 240 --format json",
|
|
92
|
-
references: [
|
|
93
|
-
"canonical machine ID",
|
|
94
|
-
"exact unique machine hostname",
|
|
95
|
-
"invocation-local guided choice",
|
|
96
|
-
],
|
|
97
|
-
related: ["check", "machines logs"],
|
|
98
|
-
});
|
|
99
|
-
export const machineLogsCapability = cliOnly({
|
|
100
|
-
id: "evidence.machine_logs",
|
|
101
|
-
command: ["machines", "logs"],
|
|
102
|
-
category: "resource",
|
|
103
|
-
order: 561,
|
|
104
|
-
description: "Read or follow bounded customer-safe kernel or serial logs for one exact machine.",
|
|
105
|
-
outcome: "Return normalized machine logs with opaque pagination and unsafe lines omitted.",
|
|
106
|
-
human: "ornn machines logs [<machine-id-or-exact-hostname>] [--guided] [--stream kernel|serial] [--limit <1-500>] [--cursor <cursor>] [--follow]",
|
|
107
|
-
automation: "ornn machines logs <canonical-machine-id> --stream kernel --limit 200 --format json",
|
|
108
|
-
references: [
|
|
109
|
-
"canonical machine ID",
|
|
110
|
-
"exact unique machine hostname",
|
|
111
|
-
"invocation-local guided choice",
|
|
112
|
-
],
|
|
113
|
-
related: ["check", "machines metrics"],
|
|
114
|
-
});
|
|
115
|
-
export const clusterMetricsCapability = cliOnly({
|
|
116
|
-
id: "evidence.cluster_metrics",
|
|
117
|
-
command: ["clusters", "metrics"],
|
|
118
|
-
category: "resource",
|
|
119
|
-
order: 562,
|
|
120
|
-
description: "Read or follow bounded customer-safe metrics for every member of one exact cluster.",
|
|
121
|
-
outcome: "Return normalized per-machine cluster metrics without changing cluster health.",
|
|
122
|
-
human: "ornn clusters metrics [<cluster-id>] [--guided] [--start <time> --end <time>] [--max-points <1-500>] [--follow]",
|
|
123
|
-
automation: "ornn clusters metrics <canonical-cluster-id> --start <time> --end <time> --max-points 240 --format json",
|
|
124
|
-
references: ["canonical cluster ID", "invocation-local guided choice"],
|
|
125
|
-
related: ["check", "clusters logs"],
|
|
126
|
-
});
|
|
127
|
-
export const clusterLogsCapability = cliOnly({
|
|
128
|
-
id: "evidence.cluster_logs",
|
|
129
|
-
command: ["clusters", "logs"],
|
|
130
|
-
category: "resource",
|
|
131
|
-
order: 563,
|
|
132
|
-
description: "Read or follow bounded customer-safe logs for every member of one exact cluster.",
|
|
133
|
-
outcome: "Return normalized per-machine cluster logs without exposing staff or supplier details.",
|
|
134
|
-
human: "ornn clusters logs [<cluster-id>] [--guided] [--stream kernel|serial] [--limit <1-500>] [--follow]",
|
|
135
|
-
automation: "ornn clusters logs <canonical-cluster-id> --stream kernel --limit 200 --format json",
|
|
136
|
-
references: ["canonical cluster ID", "invocation-local guided choice"],
|
|
137
|
-
related: ["check", "clusters metrics"],
|
|
138
|
-
});
|
|
139
|
-
export const evidenceCapabilities = [
|
|
140
|
-
checkCapability,
|
|
141
|
-
machineMetricsCapability,
|
|
142
|
-
machineLogsCapability,
|
|
143
|
-
clusterMetricsCapability,
|
|
144
|
-
clusterLogsCapability,
|
|
145
|
-
];
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { defineCapability, } from "../capability.js";
|
|
3
|
-
const pageInput = z
|
|
4
|
-
.object({
|
|
5
|
-
$positionals: z.array(z.string()).optional(),
|
|
6
|
-
cursor: z.string().optional(),
|
|
7
|
-
limit: z.union([z.string(), z.number()]).optional(),
|
|
8
|
-
})
|
|
9
|
-
.strict();
|
|
10
|
-
const showInput = z
|
|
11
|
-
.object({
|
|
12
|
-
$positionals: z.array(z.string()).optional(),
|
|
13
|
-
})
|
|
14
|
-
.strict();
|
|
15
|
-
const verificationInput = z
|
|
16
|
-
.object({
|
|
17
|
-
$positionals: z.array(z.string()).optional(),
|
|
18
|
-
idempotencyKey: z.string().optional(),
|
|
19
|
-
})
|
|
20
|
-
.strict();
|
|
21
|
-
const disconnectInput = z
|
|
22
|
-
.object({
|
|
23
|
-
$positionals: z.array(z.string()).optional(),
|
|
24
|
-
idempotencyKey: z.string().optional(),
|
|
25
|
-
yes: z.boolean().optional(),
|
|
26
|
-
})
|
|
27
|
-
.strict();
|
|
28
|
-
const connectInput = z
|
|
29
|
-
.object({
|
|
30
|
-
$positionals: z.array(z.string()).optional(),
|
|
31
|
-
accessKeyId: z.string().optional(),
|
|
32
|
-
accountId: z.string().optional(),
|
|
33
|
-
bucket: z.string().optional(),
|
|
34
|
-
endpointUrl: z.string().optional(),
|
|
35
|
-
idempotencyKey: z.string().optional(),
|
|
36
|
-
name: z.string().optional(),
|
|
37
|
-
prefix: z.string().optional(),
|
|
38
|
-
readOnly: z.boolean().optional(),
|
|
39
|
-
readWrite: z.boolean().optional(),
|
|
40
|
-
region: z.string().optional(),
|
|
41
|
-
secretAccessKeyFile: z.string().optional(),
|
|
42
|
-
url: z.string().optional(),
|
|
43
|
-
yes: z.boolean().optional(),
|
|
44
|
-
})
|
|
45
|
-
.strict();
|
|
46
|
-
const credentialInput = z
|
|
47
|
-
.object({
|
|
48
|
-
$positionals: z.array(z.string()).optional(),
|
|
49
|
-
accessKeyId: z.string().optional(),
|
|
50
|
-
idempotencyKey: z.string().optional(),
|
|
51
|
-
secretAccessKeyFile: z.string().optional(),
|
|
52
|
-
yes: z.boolean().optional(),
|
|
53
|
-
})
|
|
54
|
-
.strict();
|
|
55
|
-
const importInput = z
|
|
56
|
-
.object({
|
|
57
|
-
$positionals: z.array(z.string()).optional(),
|
|
58
|
-
idempotencyKey: z.string().optional(),
|
|
59
|
-
noWait: z.boolean().optional(),
|
|
60
|
-
reservation: z.string().optional(),
|
|
61
|
-
timeout: z.string().optional(),
|
|
62
|
-
wait: z.boolean().optional(),
|
|
63
|
-
yes: z.boolean().optional(),
|
|
64
|
-
})
|
|
65
|
-
.strict();
|
|
66
|
-
function externalBucketExecutor(context) {
|
|
67
|
-
const interaction = context.cli?.interaction;
|
|
68
|
-
if (!interaction?.externalBuckets) {
|
|
69
|
-
throw new Error("This capability must execute through the Ornn CLI external-bucket runtime.");
|
|
70
|
-
}
|
|
71
|
-
return interaction.externalBuckets.bind(interaction);
|
|
72
|
-
}
|
|
73
|
-
function externalBucketCapability({ acceptedReferences = [], automation, command, description, human, id, input, mutation, outcome, related = [], resumableStates = [], review, }) {
|
|
74
|
-
return defineCapability({
|
|
75
|
-
id,
|
|
76
|
-
domain: "storage",
|
|
77
|
-
roles: ["user"],
|
|
78
|
-
description,
|
|
79
|
-
mutation,
|
|
80
|
-
input,
|
|
81
|
-
cli: {
|
|
82
|
-
command,
|
|
83
|
-
vnext: {
|
|
84
|
-
arguments: "semantic",
|
|
85
|
-
audience: "customer",
|
|
86
|
-
category: "resource",
|
|
87
|
-
outcome,
|
|
88
|
-
human,
|
|
89
|
-
automation,
|
|
90
|
-
acceptedReferences,
|
|
91
|
-
related,
|
|
92
|
-
resumableStates,
|
|
93
|
-
...(review ? { review } : {}),
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
mcp: false,
|
|
97
|
-
slack: false,
|
|
98
|
-
execute: async (context, commandInput) => externalBucketExecutor(context)(id, commandInput),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
const gcsImportGuidance = "GCS requires bucket-level read access for Ornn's Storage Transfer service agent, granted with gcloud. CLI 1.x GCS imports are currently blocked by unavailable source verification. Setup and version-specific steps: https://docs.ornn.com/cli#gcs-imports-and-storage-transfer-service";
|
|
102
|
-
export const externalBucketCapabilities = [
|
|
103
|
-
externalBucketCapability({
|
|
104
|
-
id: "storage.external-buckets.list",
|
|
105
|
-
command: ["external-buckets", "list"],
|
|
106
|
-
description: "List connected GCS, S3, and R2 buckets in one bounded page.",
|
|
107
|
-
mutation: "read",
|
|
108
|
-
input: pageInput,
|
|
109
|
-
outcome: "List external bucket connections without exposing stored credentials.",
|
|
110
|
-
human: "ornn external-buckets list [--limit <1-100>] [--cursor <cursor>]",
|
|
111
|
-
automation: "ornn external-buckets list --limit 50 --format json",
|
|
112
|
-
related: ["external-buckets show", "external-buckets connect"],
|
|
113
|
-
}),
|
|
114
|
-
externalBucketCapability({
|
|
115
|
-
id: "storage.external-buckets.show",
|
|
116
|
-
command: ["external-buckets", "show"],
|
|
117
|
-
description: "Inspect one connected external bucket by canonical ID or exact unique name.",
|
|
118
|
-
mutation: "read",
|
|
119
|
-
input: showInput,
|
|
120
|
-
outcome: "Inspect one credential-safe external bucket connection.",
|
|
121
|
-
human: "ornn external-buckets show <external-bucket>",
|
|
122
|
-
automation: "ornn external-buckets show <external-bucket-id> --format json",
|
|
123
|
-
acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
|
|
124
|
-
related: ["external-buckets verify", "external-buckets import"],
|
|
125
|
-
}),
|
|
126
|
-
externalBucketCapability({
|
|
127
|
-
id: "storage.external-buckets.connect",
|
|
128
|
-
command: ["external-buckets", "connect"],
|
|
129
|
-
description: "Connect a typed GCS, AWS S3, or Cloudflare R2 source without verifying it implicitly.",
|
|
130
|
-
mutation: "preview-confirm",
|
|
131
|
-
input: connectInput,
|
|
132
|
-
outcome: "Create or rediscover one external bucket connection with verification kept separate.",
|
|
133
|
-
human: "ornn external-buckets connect <gcs|s3|r2> --bucket <bucket> [--name <name>] [--prefix <prefix>] [--region <region>] [--account-id <id>|--endpoint-url <url>] [--access-key-id <id> --secret-access-key-file <path>] [--read-only|--read-write]",
|
|
134
|
-
automation: "ornn external-buckets connect <gcs|s3|r2> --bucket <bucket> <provider-inputs> --yes --idempotency-key <key> --format json",
|
|
135
|
-
review: `Review the exact source, access mode, and credential presence before connecting it. ${gcsImportGuidance}`,
|
|
136
|
-
related: ["external-buckets verify", "external-buckets import"],
|
|
137
|
-
}),
|
|
138
|
-
externalBucketCapability({
|
|
139
|
-
id: "storage.external-buckets.update-credentials",
|
|
140
|
-
command: ["external-buckets", "update-credentials"],
|
|
141
|
-
description: "Replace scoped S3 or R2 credentials without returning credential bytes.",
|
|
142
|
-
mutation: "preview-confirm",
|
|
143
|
-
input: credentialInput,
|
|
144
|
-
outcome: "Update one connection's credentials and require a separate verification.",
|
|
145
|
-
human: "ornn external-buckets update-credentials <external-bucket> --access-key-id <id> --secret-access-key-file <path>",
|
|
146
|
-
automation: "ornn external-buckets update-credentials <external-bucket-id> --access-key-id <id> --secret-access-key-file <path> --yes --idempotency-key <key> --format json",
|
|
147
|
-
acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
|
|
148
|
-
review: "Credential changes invalidate the prior verification and require renewed review.",
|
|
149
|
-
related: ["external-buckets verify"],
|
|
150
|
-
}),
|
|
151
|
-
externalBucketCapability({
|
|
152
|
-
id: "storage.external-buckets.verify",
|
|
153
|
-
command: ["external-buckets", "verify"],
|
|
154
|
-
description: "Verify current S3 or R2 source access as a separate operation.",
|
|
155
|
-
mutation: "preview-confirm",
|
|
156
|
-
input: verificationInput,
|
|
157
|
-
outcome: "Record current source-access verification without exposing credential material.",
|
|
158
|
-
human: "ornn external-buckets verify <external-bucket>",
|
|
159
|
-
automation: "ornn external-buckets verify <external-bucket-id> --idempotency-key <key> --format json",
|
|
160
|
-
acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
|
|
161
|
-
review: gcsImportGuidance,
|
|
162
|
-
related: ["external-buckets import", "external-buckets update-credentials"],
|
|
163
|
-
}),
|
|
164
|
-
externalBucketCapability({
|
|
165
|
-
id: "storage.external-buckets.import",
|
|
166
|
-
command: ["external-buckets", "import"],
|
|
167
|
-
description: "Import a verified GCS or S3 source into its isolated managed working volume.",
|
|
168
|
-
mutation: "preview-confirm",
|
|
169
|
-
input: importInput,
|
|
170
|
-
outcome: "Create or replay exactly one managed working copy with source writeback disabled.",
|
|
171
|
-
human: "ornn external-buckets import <gcs|s3|r2> <external-bucket> --reservation <canonical-reservation-id> [--no-wait] [--timeout <duration>]",
|
|
172
|
-
automation: "ornn external-buckets import <gcs|s3> <external-bucket-id> --reservation <canonical-reservation-id> --yes --idempotency-key <key> [--wait --timeout <duration>] --format json",
|
|
173
|
-
acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
|
|
174
|
-
review: `Review the isolated destination and explicit no-writeback guarantee before importing. ${gcsImportGuidance}`,
|
|
175
|
-
resumableStates: ["pending", "working", "partial", "failed", "interrupted"],
|
|
176
|
-
related: ["external-buckets show", "storage status", "volumes files list"],
|
|
177
|
-
}),
|
|
178
|
-
externalBucketCapability({
|
|
179
|
-
id: "storage.external-buckets.disconnect",
|
|
180
|
-
command: ["external-buckets", "disconnect"],
|
|
181
|
-
description: "Disconnect an external bucket record after its working volume is detached.",
|
|
182
|
-
mutation: "preview-confirm",
|
|
183
|
-
input: disconnectInput,
|
|
184
|
-
outcome: "Remove one external source connection without writing to its source bucket.",
|
|
185
|
-
human: "ornn external-buckets disconnect <external-bucket>",
|
|
186
|
-
automation: "ornn external-buckets disconnect <external-bucket-id> --yes --idempotency-key <key> --format json",
|
|
187
|
-
acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
|
|
188
|
-
review: "Disconnecting reduces access to the source and is blocked while mounts remain.",
|
|
189
|
-
related: ["storage detach", "external-buckets show"],
|
|
190
|
-
}),
|
|
191
|
-
];
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { listSupplierOrganizations, listSupplierOrganizationPage } from "../supplier-directory.js";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { defineCapability, preview } from "../capability.js";
|
|
4
|
-
function queryPath(path, params) {
|
|
5
|
-
const parts = [];
|
|
6
|
-
for (const [key, value] of Object.entries(params)) {
|
|
7
|
-
if (value?.trim())
|
|
8
|
-
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value.trim())}`);
|
|
9
|
-
}
|
|
10
|
-
return parts.length ? `${path}?${parts.join("&")}` : path;
|
|
11
|
-
}
|
|
12
|
-
const emptyInput = z.object({});
|
|
13
|
-
const suppliersInput = z.object({
|
|
14
|
-
q: z.string().optional(),
|
|
15
|
-
offset: z.number().int().min(0).optional(),
|
|
16
|
-
limit: z.number().int().min(1).max(1000).optional(),
|
|
17
|
-
});
|
|
18
|
-
const facilitiesInput = z.object({
|
|
19
|
-
organization_id: z.string().optional(),
|
|
20
|
-
organizationId: z.string().optional(),
|
|
21
|
-
cursor: z.string().optional(),
|
|
22
|
-
limit: z.number().int().min(1).max(500).optional(),
|
|
23
|
-
});
|
|
24
|
-
const nodesInput = z.object({
|
|
25
|
-
organization_id: z.string().optional(),
|
|
26
|
-
organizationId: z.string().optional(),
|
|
27
|
-
facility_id: z.string().optional(),
|
|
28
|
-
facilityId: z.string().optional(),
|
|
29
|
-
status: z.string().optional(),
|
|
30
|
-
reservation_id: z.string().optional(),
|
|
31
|
-
reservationId: z.string().optional(),
|
|
32
|
-
cursor: z.string().optional(),
|
|
33
|
-
max: z.number().int().positive().max(5000).optional(),
|
|
34
|
-
limit: z.number().int().positive().max(5000).optional(),
|
|
35
|
-
});
|
|
36
|
-
const nodeLifecycleInput = z.object({
|
|
37
|
-
node_id: z.string().min(1),
|
|
38
|
-
nodeId: z.string().optional(),
|
|
39
|
-
reason: z.string().optional(),
|
|
40
|
-
force: z.boolean().optional(),
|
|
41
|
-
});
|
|
42
|
-
const nodeExecInput = z.object({
|
|
43
|
-
node_id: z.string().min(1),
|
|
44
|
-
nodeId: z.string().optional(),
|
|
45
|
-
command: z.string().min(1),
|
|
46
|
-
timeout_seconds: z.number().int().positive(),
|
|
47
|
-
timeoutSeconds: z.number().int().positive().optional(),
|
|
48
|
-
yes: z.boolean().optional(),
|
|
49
|
-
});
|
|
50
|
-
function nodeIdOf(input) {
|
|
51
|
-
return (input.node_id || input.nodeId || "").trim();
|
|
52
|
-
}
|
|
53
|
-
export const listSuppliersCapability = defineCapability({
|
|
54
|
-
id: "supplier.list",
|
|
55
|
-
domain: "fleet",
|
|
56
|
-
roles: ["admin"],
|
|
57
|
-
description: "List supplier organizations (id, name). Resolve supplier names to organization_id with this before nodes.list or facilities.list.",
|
|
58
|
-
mutation: "read",
|
|
59
|
-
http: { method: "GET", path: "/v1/organizations" },
|
|
60
|
-
slack: {
|
|
61
|
-
parameters: {
|
|
62
|
-
type: "object",
|
|
63
|
-
properties: {
|
|
64
|
-
q: { type: "string", description: "Search supplier names." },
|
|
65
|
-
offset: { type: "integer", description: "Use next_offset to fetch another page." },
|
|
66
|
-
limit: { type: "integer", description: "Page size (Slack maximum 10)." },
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
input: suppliersInput,
|
|
71
|
-
execute: async (ctx, input) => {
|
|
72
|
-
const parsed = suppliersInput.parse(input);
|
|
73
|
-
const paged = parsed.limit !== undefined || parsed.offset !== undefined || parsed.q !== undefined;
|
|
74
|
-
const limit = parsed.limit ?? 25;
|
|
75
|
-
const offset = parsed.offset ?? 0;
|
|
76
|
-
const rows = paged
|
|
77
|
-
? await listSupplierOrganizationPage(ctx.fetch, { ...parsed, limit, offset })
|
|
78
|
-
: await listSupplierOrganizations(ctx.fetch);
|
|
79
|
-
return {
|
|
80
|
-
suppliers: rows.map((org) => ({ id: org.id, name: org.name })),
|
|
81
|
-
...(paged && rows.length === limit ? { next_offset: offset + rows.length } : {}),
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
export const listFacilitiesCapability = defineCapability({
|
|
86
|
-
id: "facilities.list",
|
|
87
|
-
domain: "fleet",
|
|
88
|
-
roles: ["admin"],
|
|
89
|
-
description: "List facilities (id, display name, region, supplier organization id). Optional organization_id filter. Resolve facility names with this before nodes.list.",
|
|
90
|
-
mutation: "read",
|
|
91
|
-
http: { method: "GET", path: "/provisioning/facilities" },
|
|
92
|
-
slack: {
|
|
93
|
-
parameters: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
organization_id: {
|
|
97
|
-
type: "string",
|
|
98
|
-
description: "Optional supplier organization UUID from supplier.list.",
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
input: facilitiesInput,
|
|
104
|
-
execute: async (ctx, input) => {
|
|
105
|
-
const parsed = facilitiesInput.parse(input);
|
|
106
|
-
return ctx.fetch(queryPath("/provisioning/facilities", {
|
|
107
|
-
organizationId: parsed.organization_id ?? parsed.organizationId,
|
|
108
|
-
cursor: parsed.cursor,
|
|
109
|
-
limit: parsed.limit === undefined ? undefined : String(parsed.limit),
|
|
110
|
-
}), { method: "GET" });
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
export const listNodesCapability = defineCapability({
|
|
114
|
-
id: "nodes.list",
|
|
115
|
-
domain: "fleet",
|
|
116
|
-
roles: ["user", "admin"],
|
|
117
|
-
description: "List nodes. Users see their own reserved machines. Admins see enrolled, ghost, and off-grid nodes. Call with no filters for the whole fleet. Optional reservation_id lists the nodes on one reservation (find a customer's reservations with reservation.list customerId). Optional organization_id (supplier), facility_id, and status (ghost, off-grid, bare-metal) narrow the same list. Paginate large fleets with cursor + max: pass the response's next_cursor back as cursor to fetch the next page; next_cursor is omitted once the page is not full. Never invent nodes. Never print private keys.",
|
|
118
|
-
mutation: "read",
|
|
119
|
-
http: { method: "GET", path: "/nodes" },
|
|
120
|
-
slack: {
|
|
121
|
-
parameters: {
|
|
122
|
-
type: "object",
|
|
123
|
-
properties: {
|
|
124
|
-
organization_id: {
|
|
125
|
-
type: "string",
|
|
126
|
-
description: "Optional supplier organization UUID from supplier.list.",
|
|
127
|
-
},
|
|
128
|
-
facility_id: {
|
|
129
|
-
type: "string",
|
|
130
|
-
description: "Optional commerce facility UUID from facilities.list.",
|
|
131
|
-
},
|
|
132
|
-
reservation_id: {
|
|
133
|
-
type: "string",
|
|
134
|
-
description: "Optional reservation UUID from reservation_list. Lists that reservation's nodes.",
|
|
135
|
-
},
|
|
136
|
-
status: {
|
|
137
|
-
type: "string",
|
|
138
|
-
enum: ["ghost", "off-grid", "bare-metal"],
|
|
139
|
-
description: "Optional orchestrator status filter. Default is all statuses.",
|
|
140
|
-
},
|
|
141
|
-
cursor: {
|
|
142
|
-
type: "string",
|
|
143
|
-
description: "Optional. Pass the previous response's next_cursor to fetch the next page.",
|
|
144
|
-
},
|
|
145
|
-
max: {
|
|
146
|
-
type: "integer",
|
|
147
|
-
description: "Optional page size (1-5000). Orchestrator default is 500.",
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
input: nodesInput,
|
|
153
|
-
execute: async (ctx, input) => {
|
|
154
|
-
const parsed = nodesInput.parse(input);
|
|
155
|
-
const pagination = {
|
|
156
|
-
cursor: parsed.cursor,
|
|
157
|
-
limit: parsed.max != null || parsed.limit != null ? String(parsed.max ?? parsed.limit) : undefined,
|
|
158
|
-
};
|
|
159
|
-
if (ctx.role === "user") {
|
|
160
|
-
return ctx.fetch(queryPath("/nodes", pagination), { method: "GET" });
|
|
161
|
-
}
|
|
162
|
-
return ctx.fetch(queryPath("/nodes", {
|
|
163
|
-
organization_id: parsed.organization_id ?? parsed.organizationId,
|
|
164
|
-
facility_id: parsed.facility_id ?? parsed.facilityId,
|
|
165
|
-
status: parsed.status,
|
|
166
|
-
reservation_id: parsed.reservation_id ?? parsed.reservationId,
|
|
167
|
-
...pagination,
|
|
168
|
-
}), { method: "GET" });
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
export const nodeOffGridCapability = defineCapability({
|
|
172
|
-
id: "node.off-grid",
|
|
173
|
-
domain: "fleet",
|
|
174
|
-
roles: ["admin"],
|
|
175
|
-
description: "Admin-only. Take a node off-grid (remove Ornn agent management, leave the host powered on). CLI asks y/N. Slack waits for a human confirm. MCP requires confirm: true.",
|
|
176
|
-
mutation: "preview-confirm",
|
|
177
|
-
http: { method: "POST", path: "/nodes/{id}/off-grid" },
|
|
178
|
-
slack: {
|
|
179
|
-
parameters: {
|
|
180
|
-
type: "object",
|
|
181
|
-
properties: {
|
|
182
|
-
node_id: { type: "string", description: "Node UUID from nodes.list." },
|
|
183
|
-
reason: { type: "string" },
|
|
184
|
-
},
|
|
185
|
-
required: ["node_id"],
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
input: nodeLifecycleInput,
|
|
189
|
-
execute: async (ctx, input) => {
|
|
190
|
-
const parsed = nodeLifecycleInput.parse(input);
|
|
191
|
-
const id = nodeIdOf(parsed);
|
|
192
|
-
const body = { ...(parsed.reason ? { reason: parsed.reason } : {}) };
|
|
193
|
-
if (!ctx.confirmed) {
|
|
194
|
-
return preview("node.off-grid", { node_id: id, ...body });
|
|
195
|
-
}
|
|
196
|
-
return ctx.fetch(`/nodes/${encodeURIComponent(id)}/off-grid`, {
|
|
197
|
-
method: "POST",
|
|
198
|
-
body,
|
|
199
|
-
});
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
export const nodeOnGridCapability = defineCapability({
|
|
203
|
-
id: "node.on-grid",
|
|
204
|
-
domain: "fleet",
|
|
205
|
-
roles: ["admin"],
|
|
206
|
-
description: "Admin-only. Re-enroll an off-grid node: orchestrator SSHs with the stored admin key and runs the installer with restore_node_id. No caller key. CLI asks y/N. Slack waits for a human confirm. MCP requires confirm: true.",
|
|
207
|
-
mutation: "preview-confirm",
|
|
208
|
-
http: { method: "POST", path: "/nodes/{id}/on-grid" },
|
|
209
|
-
slack: {
|
|
210
|
-
parameters: {
|
|
211
|
-
type: "object",
|
|
212
|
-
properties: {
|
|
213
|
-
node_id: { type: "string", description: "Off-grid node UUID from nodes.list." },
|
|
214
|
-
},
|
|
215
|
-
required: ["node_id"],
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
input: nodeLifecycleInput,
|
|
219
|
-
execute: async (ctx, input) => {
|
|
220
|
-
const parsed = nodeLifecycleInput.parse(input);
|
|
221
|
-
const id = nodeIdOf(parsed);
|
|
222
|
-
if (!ctx.confirmed) {
|
|
223
|
-
return preview("node.on-grid", { node_id: id });
|
|
224
|
-
}
|
|
225
|
-
return ctx.fetch(`/nodes/${encodeURIComponent(id)}/on-grid`, {
|
|
226
|
-
method: "POST",
|
|
227
|
-
body: {},
|
|
228
|
-
});
|
|
229
|
-
},
|
|
230
|
-
});
|
|
231
|
-
export const nodeExecCapability = defineCapability({
|
|
232
|
-
id: "node.exec",
|
|
233
|
-
domain: "fleet",
|
|
234
|
-
roles: ["admin"],
|
|
235
|
-
description: "Admin-only. Run one unrestricted command on an enrolled node over orchestrator SSH with the stored admin key. Always pass timeout_seconds. Not an interactive shell. On NVIDIA hosts use nvidia-smi; on AMD Instinct use amd-smi. Runs on the tool call — no confirm, no y/N.",
|
|
236
|
-
mutation: "read",
|
|
237
|
-
http: { method: "POST", path: "/remote" },
|
|
238
|
-
slack: {
|
|
239
|
-
parameters: {
|
|
240
|
-
type: "object",
|
|
241
|
-
properties: {
|
|
242
|
-
node_id: { type: "string", description: "Enrolled node UUID from nodes.list." },
|
|
243
|
-
command: { type: "string", description: "Exact shell command to run. No allowlist." },
|
|
244
|
-
timeout_seconds: {
|
|
245
|
-
type: "integer",
|
|
246
|
-
description: "Seconds to wait before killing the SSH command. Required. 1-900.",
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
required: ["node_id", "command", "timeout_seconds"],
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
input: nodeExecInput,
|
|
253
|
-
execute: async (ctx, input) => {
|
|
254
|
-
const parsed = nodeExecInput.parse(input);
|
|
255
|
-
const id = nodeIdOf(parsed);
|
|
256
|
-
const timeoutSeconds = parsed.timeout_seconds ?? parsed.timeoutSeconds;
|
|
257
|
-
return ctx.fetch("/remote", {
|
|
258
|
-
method: "POST",
|
|
259
|
-
body: { node_id: id, command: parsed.command, timeout_seconds: timeoutSeconds },
|
|
260
|
-
});
|
|
261
|
-
},
|
|
262
|
-
});
|
|
263
|
-
export const nodeTerminateCapability = defineCapability({
|
|
264
|
-
id: "node.terminate",
|
|
265
|
-
domain: "fleet",
|
|
266
|
-
roles: ["admin"],
|
|
267
|
-
description: "Admin-only. Terminate a node record (best-effort clean + delete). Off-grid nodes need force: true. There is no deenroll verb. CLI asks y/N. Slack waits for a human confirm. MCP requires confirm: true.",
|
|
268
|
-
mutation: "preview-confirm",
|
|
269
|
-
http: { method: "POST", path: "/nodes/{id}/terminate" },
|
|
270
|
-
slack: {
|
|
271
|
-
parameters: {
|
|
272
|
-
type: "object",
|
|
273
|
-
properties: {
|
|
274
|
-
node_id: { type: "string", description: "Node UUID from nodes.list." },
|
|
275
|
-
reason: { type: "string" },
|
|
276
|
-
force: { type: "boolean", description: "Required to delete an off-grid node." },
|
|
277
|
-
},
|
|
278
|
-
required: ["node_id"],
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
input: nodeLifecycleInput,
|
|
282
|
-
execute: async (ctx, input) => {
|
|
283
|
-
const parsed = nodeLifecycleInput.parse(input);
|
|
284
|
-
const id = nodeIdOf(parsed);
|
|
285
|
-
const body = {
|
|
286
|
-
...(parsed.reason ? { reason: parsed.reason } : {}),
|
|
287
|
-
...(parsed.force !== undefined ? { force: parsed.force } : {}),
|
|
288
|
-
};
|
|
289
|
-
if (!ctx.confirmed) {
|
|
290
|
-
return preview("node.terminate", { node_id: id, ...body });
|
|
291
|
-
}
|
|
292
|
-
return ctx.fetch(`/nodes/${encodeURIComponent(id)}/terminate`, {
|
|
293
|
-
method: "POST",
|
|
294
|
-
body,
|
|
295
|
-
});
|
|
296
|
-
},
|
|
297
|
-
});
|
|
298
|
-
export const fleetCapabilities = [
|
|
299
|
-
listSuppliersCapability,
|
|
300
|
-
listFacilitiesCapability,
|
|
301
|
-
listNodesCapability,
|
|
302
|
-
nodeOffGridCapability,
|
|
303
|
-
nodeOnGridCapability,
|
|
304
|
-
nodeExecCapability,
|
|
305
|
-
nodeTerminateCapability,
|
|
306
|
-
];
|