@ornncompute/cli 1.0.75 → 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.
Files changed (52) hide show
  1. package/README.md +32 -5
  2. package/package.json +4 -2
  3. package/src/admin-capacity-reservations.mjs +4 -1
  4. package/src/admin-command-handlers.mjs +2 -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/catalog-shell.mjs +6 -6
  9. package/src/evidence-commands.mjs +4 -6
  10. package/src/external-bucket-commands.mjs +71 -23
  11. package/src/interaction-runtime.mjs +3 -0
  12. package/src/kubernetes-commands.mjs +16 -83
  13. package/src/machine-reference.mjs +33 -56
  14. package/src/slurm-commands.mjs +13 -2
  15. package/src/vm-commands.mjs +39 -59
  16. package/vendor/api-client/commerce.js +743 -0
  17. package/vendor/capabilities/cli.js +7688 -7
  18. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +0 -101
  19. package/vendor/capabilities/capabilities/admin-enrollment.js +0 -322
  20. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +0 -88
  21. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +0 -137
  22. package/vendor/capabilities/capabilities/admin.js +0 -91
  23. package/vendor/capabilities/capabilities/cli.js +0 -156
  24. package/vendor/capabilities/capabilities/clusters.js +0 -248
  25. package/vendor/capabilities/capabilities/commerce-market.js +0 -405
  26. package/vendor/capabilities/capabilities/compute.js +0 -523
  27. package/vendor/capabilities/capabilities/credits.js +0 -83
  28. package/vendor/capabilities/capabilities/evidence.js +0 -145
  29. package/vendor/capabilities/capabilities/external-buckets.js +0 -191
  30. package/vendor/capabilities/capabilities/fleet.js +0 -386
  31. package/vendor/capabilities/capabilities/identity.js +0 -129
  32. package/vendor/capabilities/capabilities/listings.js +0 -398
  33. package/vendor/capabilities/capabilities/locality.js +0 -42
  34. package/vendor/capabilities/capabilities/market-shared.js +0 -46
  35. package/vendor/capabilities/capabilities/markets.js +0 -482
  36. package/vendor/capabilities/capabilities/mounts.js +0 -176
  37. package/vendor/capabilities/capabilities/native-listing.js +0 -99
  38. package/vendor/capabilities/capabilities/networks.js +0 -1264
  39. package/vendor/capabilities/capabilities/observability.js +0 -253
  40. package/vendor/capabilities/capabilities/organization-invites.js +0 -53
  41. package/vendor/capabilities/capabilities/reservation-list.js +0 -68
  42. package/vendor/capabilities/capabilities/staff-shared.js +0 -64
  43. package/vendor/capabilities/capabilities/tokens.js +0 -161
  44. package/vendor/capabilities/capabilities/users.js +0 -157
  45. package/vendor/capabilities/capabilities/volumes.js +0 -178
  46. package/vendor/capabilities/capability.js +0 -99
  47. package/vendor/capabilities/cli-catalog.js +0 -73
  48. package/vendor/capabilities/cli-migrations.js +0 -264
  49. package/vendor/capabilities/names.js +0 -6
  50. package/vendor/capabilities/software-catalog.js +0 -82
  51. package/vendor/capabilities/spec-catalog.js +0 -151
  52. package/vendor/capabilities/supplier-directory.js +0 -20
@@ -1,482 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
3
- import { gpuDisplay, loadHardwareCatalog } from "../spec-catalog.js";
4
- import { consent, idempotencyHeaders, microUsd, microUsdLabel, positionals, query, seg, } from "./market-shared.js";
5
- // Markets verbs: one capability per `/v1/markets` route. Order books are
6
- // per GPU slug, sale type (Spot or On-demand) and region; Spot and On-demand
7
- // trade GPUs. Clients buy a number of nodes at market for now; Markets also
8
- // takes GPU counts and limit bids. Offers are per primary listing. Prices are
9
- // integer micro-USD per GPU-hour, exactly as Markets reads and writes them.
10
- const BASE = "/v1/markets";
11
- const saleType = z
12
- .enum(["spot", "on-demand"])
13
- .optional()
14
- .describe("spot (the default) yields to scheduled bookings; on-demand runs until stopped or the listing ends.");
15
- const region = z
16
- .string()
17
- .min(1)
18
- .optional()
19
- .describe("A region slug, for example us-east-11. Omit for every region.");
20
- const nodes = z.coerce
21
- .number()
22
- .int()
23
- .min(1)
24
- .describe("Nodes to buy, each the GPUs of one whole machine.");
25
- function bookQuery(input) {
26
- return query({ saleType: input.saleType, region: input.region });
27
- }
28
- function help(command, outcome, human, automation, related, order, acceptedReferences = []) {
29
- return {
30
- arguments: "semantic",
31
- audience: "customer",
32
- category: "resource",
33
- command,
34
- outcome,
35
- human,
36
- automation,
37
- acceptedReferences,
38
- related,
39
- order,
40
- };
41
- }
42
- export const marketBooksInput = z.object({
43
- $positionals: positionals,
44
- gpuSlug: z.string().min(1).optional().describe("Only this catalog GPU slug."),
45
- saleType,
46
- region: z
47
- .string()
48
- .min(1)
49
- .optional()
50
- .describe("Only this region slug, or any for the books of bids in any region."),
51
- });
52
- export const marketBooksCapability = defineCapability({
53
- id: "market.books",
54
- domain: "markets",
55
- roles: ["user"],
56
- description: "List the order books, one per GPU type, sale type (Spot or On-demand) and region, with the best bid and ask in micro-USD per GPU-hour.",
57
- mutation: "read",
58
- http: { method: "GET", path: `${BASE}/books` },
59
- input: marketBooksInput,
60
- cli: {
61
- command: ["market", "books"],
62
- vnext: help(["market", "books"], "List order books by GPU type, sale type and region with their best bid and ask.", "ornn market books [--gpu-slug <slug>] [--sale-type spot|on-demand] [--region <slug>]", "ornn market books --sale-type on-demand --format json", ["market book", "market quote", "market bid"], 31),
63
- },
64
- slack: false,
65
- execute: async (ctx, input) => {
66
- const parsed = marketBooksInput.parse(input);
67
- return ctx.fetch(`${BASE}/books${query({ gpuSlug: parsed.gpuSlug, saleType: parsed.saleType, region: parsed.region })}`, {
68
- method: "GET",
69
- });
70
- },
71
- });
72
- export const marketBookInput = z.object({
73
- $positionals: positionals,
74
- gpuSlug: z.string().min(1).describe("Catalog GPU slug, for example nvidia_h100_sxm."),
75
- saleType,
76
- region,
77
- });
78
- export const marketBookCapability = defineCapability({
79
- id: "market.book",
80
- domain: "markets",
81
- roles: ["user"],
82
- description: "Show one GPU type's depth for a sale type, in one region or across all of them: nodes and order counts at each bid and ask price level (ask levels also count their GPUs).",
83
- mutation: "read",
84
- http: { method: "GET", path: `${BASE}/books/{gpuSlug}` },
85
- input: marketBookInput,
86
- cli: {
87
- command: ["market", "book"],
88
- vnext: help(["market", "book"], "Show bid and ask depth for one GPU type, sale type and region.", "ornn market book --gpu-slug <slug> [--sale-type spot|on-demand] [--region <slug>]", "ornn market book --gpu-slug <slug> --region us-east-11 --format json", ["market books", "market trades", "market quote"], 32, ["catalog GPU slug", "region slug"]),
89
- },
90
- slack: false,
91
- execute: async (ctx, input) => {
92
- const parsed = marketBookInput.parse(input);
93
- return ctx.fetch(`${BASE}/books/${seg(parsed.gpuSlug)}${bookQuery(parsed)}`, {
94
- method: "GET",
95
- });
96
- },
97
- });
98
- export const marketTradesCapability = defineCapability({
99
- id: "market.trades",
100
- domain: "markets",
101
- roles: ["user"],
102
- description: "List recent trades for one GPU type and sale type, in one region or all: price, nodes, GPUs, region and time, with no identities.",
103
- mutation: "read",
104
- http: { method: "GET", path: `${BASE}/books/{gpuSlug}/trades` },
105
- input: marketBookInput,
106
- cli: {
107
- command: ["market", "trades"],
108
- vnext: help(["market", "trades"], "List recent fills for one GPU type, sale type and region.", "ornn market trades --gpu-slug <slug> [--sale-type spot|on-demand] [--region <slug>]", "ornn market trades --gpu-slug <slug> --format json", ["market book"], 33, ["catalog GPU slug", "region slug"]),
109
- },
110
- slack: false,
111
- execute: async (ctx, input) => {
112
- const parsed = marketBookInput.parse(input);
113
- return ctx.fetch(`${BASE}/books/${seg(parsed.gpuSlug)}/trades${bookQuery(parsed)}`, {
114
- method: "GET",
115
- });
116
- },
117
- });
118
- export const marketQuoteInput = z.object({
119
- $positionals: positionals,
120
- gpuSlug: z.string().min(1).describe("Catalog GPU slug, for example nvidia_h100_sxm."),
121
- saleType,
122
- region: z
123
- .string()
124
- .min(1)
125
- .optional()
126
- .describe("A region with an order book (see market books). Omit for any region."),
127
- nodes,
128
- });
129
- export const marketQuoteCapability = defineCapability({
130
- id: "market.quote",
131
- domain: "markets",
132
- roles: ["user"],
133
- description: "Preview a market bid for nodes without placing it: each node it would take now, cheapest first, with its price per GPU-hour, the GPUs taken there, its region and when it is next scheduled to stop. Fewer nodes than asked means the rest would be cancelled.",
134
- mutation: "read",
135
- http: { method: "GET", path: `${BASE}/books/{gpuSlug}/quote` },
136
- input: marketQuoteInput,
137
- cli: {
138
- command: ["market", "quote"],
139
- vnext: help(["market", "quote"], "Preview which nodes a bid would take now and what each costs.", "ornn market quote --gpu-slug <slug> --nodes <n> [--sale-type spot|on-demand] [--region <slug>]", "ornn market quote --gpu-slug <slug> --nodes 2 --format json", ["market book", "market bid"], 34, ["catalog GPU slug", "region slug"]),
140
- },
141
- slack: false,
142
- execute: async (ctx, input) => {
143
- const parsed = marketQuoteInput.parse(input);
144
- return ctx.fetch(`${BASE}/books/${seg(parsed.gpuSlug)}/quote${query({
145
- nodes: String(parsed.nodes),
146
- orderType: "market",
147
- saleType: parsed.saleType,
148
- region: parsed.region,
149
- })}`, { method: "GET" });
150
- },
151
- });
152
- export const marketBidInput = z.object({
153
- $positionals: positionals,
154
- gpuSlug: z.string().min(1).describe("Catalog GPU slug, for example nvidia_h100_sxm."),
155
- saleType,
156
- region: z
157
- .string()
158
- .min(1)
159
- .optional()
160
- .describe("A region with an order book (see market books), for example us-east-11. Omit to fill in any region."),
161
- nodes,
162
- diskId: z
163
- .string()
164
- .uuid()
165
- .optional()
166
- .describe("The disk every VM boots. Omit to boot your newest disk, else Ornn's newest."),
167
- idempotencyKey: z.string().min(1).max(200).optional(),
168
- confirm: z.boolean().optional(),
169
- });
170
- export const marketBidCapability = defineCapability({
171
- id: "market.bid",
172
- domain: "markets",
173
- roles: ["user"],
174
- description: "Buy nodes at market, each the GPUs of one whole machine, as Spot (the default; a scheduled booking that needs the GPUs can stop it) or On-demand (runs until stopped or the listing ends), " +
175
- "in one region or any. The bid takes the cheapest nodes for sale now and cancels the rest. What one listing sells becomes a running reservation (a fill), prepaid hourly from Ornn credits first and then the saved card. " +
176
- "Book prices are what you pay per GPU-hour..",
177
- mutation: "preview-confirm",
178
- http: { method: "POST", path: `${BASE}/orders` },
179
- input: marketBidInput,
180
- cli: {
181
- command: ["market", "bid"],
182
- vnext: help(["market", "bid"], "Buy nodes at market.", "ornn market bid --gpu-slug <slug> --nodes <n> [--sale-type spot|on-demand] [--region <slug>] [--disk-id <id>]", "ornn market bid --gpu-slug <slug> --nodes 2 --format json", ["market quote", "market orders", "market fills", "market cancel"], 35, ["catalog GPU slug"]),
183
- },
184
- slack: false,
185
- execute: async (ctx, input) => {
186
- const parsed = marketBidInput.parse(input);
187
- const body = {
188
- gpuSlug: parsed.gpuSlug,
189
- ...(parsed.saleType ? { saleType: parsed.saleType } : {}),
190
- ...(parsed.region ? { region: parsed.region } : {}),
191
- nodes: parsed.nodes,
192
- orderType: "market",
193
- ...(parsed.diskId ? { diskId: parsed.diskId } : {}),
194
- };
195
- // Only the CLI review renders terms; MCP and Slack preview the payload.
196
- const hardware = ctx.cli?.interaction
197
- ? await loadHardwareCatalog(ctx.fetch).catch(() => null)
198
- : null;
199
- const gate = await consent(ctx, "market.bid", "Place bid", [
200
- { label: "GPU type", value: gpuDisplay(hardware?.terms ?? [], parsed.gpuSlug) },
201
- { label: "Sale type", value: parsed.saleType === "on-demand" ? "On-demand" : "Spot" },
202
- { label: "Location", value: parsed.region ?? "Any location" },
203
- { label: "Nodes", value: String(parsed.nodes) },
204
- { label: "Order", value: "Market: the cheapest nodes for sale now" },
205
- ], body);
206
- if (gate)
207
- return gate;
208
- return ctx.fetch(`${BASE}/orders`, {
209
- method: "POST",
210
- body,
211
- headers: idempotencyHeaders(ctx, parsed.idempotencyKey),
212
- });
213
- },
214
- });
215
- export const marketOrdersInput = z.object({ $positionals: positionals });
216
- export const marketOrdersCapability = defineCapability({
217
- id: "market.orders",
218
- domain: "markets",
219
- roles: ["user"],
220
- description: "List this organization's bids (resting, filled and cancelled, each with its fill IDs) and the asks its listings have on the books.",
221
- mutation: "read",
222
- http: { method: "GET", path: `${BASE}/orders` },
223
- input: marketOrdersInput,
224
- cli: {
225
- command: ["market", "orders"],
226
- vnext: help(["market", "orders"], "List your organization's bids and listing asks.", "ornn market orders", "ornn market orders --format json", ["market bid", "market fills", "market cancel"], 36),
227
- },
228
- slack: false,
229
- execute: async (ctx) => ctx.fetch(`${BASE}/orders`, { method: "GET" }),
230
- });
231
- export const marketCancelInput = z.object({
232
- $positionals: positionals,
233
- orderId: z.string().uuid().describe("A resting bid ID."),
234
- confirm: z.boolean().optional(),
235
- });
236
- export const marketCancelCapability = defineCapability({
237
- id: "market.cancel",
238
- domain: "markets",
239
- roles: ["user"],
240
- description: "Cancel what a resting bid has not bought yet. Its fills keep running; end them with market end..",
241
- mutation: "preview-confirm",
242
- http: { method: "DELETE", path: `${BASE}/orders/{orderId}` },
243
- input: marketCancelInput,
244
- cli: {
245
- command: ["market", "cancel"],
246
- vnext: help(["market", "cancel"], "Cancel the rest of a resting bid.", "ornn market cancel --order-id <id>", "ornn market cancel --order-id <id> --format json", ["market orders", "market end"], 37, ["order ID"]),
247
- },
248
- slack: false,
249
- execute: async (ctx, input) => {
250
- const parsed = marketCancelInput.parse(input);
251
- const gate = await consent(ctx, "market.cancel", "Cancel bid", [
252
- { label: "Order", value: parsed.orderId },
253
- {
254
- label: "Consequence",
255
- value: "The bid stops buying. What it already bought keeps running.",
256
- },
257
- ], { orderId: parsed.orderId });
258
- if (gate)
259
- return gate;
260
- return ctx.fetch(`${BASE}/orders/${seg(parsed.orderId)}`, { method: "DELETE" });
261
- },
262
- });
263
- export const marketFillsInput = z.object({
264
- $positionals: positionals,
265
- orderId: z.string().uuid().optional().describe("Only this bid's fills."),
266
- });
267
- export const marketFillsCapability = defineCapability({
268
- id: "market.fills",
269
- domain: "markets",
270
- roles: ["user"],
271
- description: "List this organization's fills, newest first, or one bid's: each is one trade of GPUs from one listing at one price. Its ID is the reservation it runs as; read its status from the reservation.",
272
- mutation: "read",
273
- http: { method: "GET", path: `${BASE}/fills` },
274
- input: marketFillsInput,
275
- cli: {
276
- command: ["market", "fills"],
277
- vnext: help(["market", "fills"], "List the nodes your bids bought, one reservation per fill.", "ornn market fills [--order-id <id>]", "ornn market fills --format json", ["market orders", "market end"], 38, ["order ID"]),
278
- },
279
- slack: false,
280
- execute: async (ctx, input) => {
281
- const parsed = marketFillsInput.parse(input ?? {});
282
- return ctx.fetch(`${BASE}/fills${query({ orderId: parsed.orderId })}`, { method: "GET" });
283
- },
284
- });
285
- export const marketEndInput = z.object({
286
- $positionals: positionals,
287
- fillId: z.string().uuid().describe("A fill ID; it is also its reservation ID."),
288
- confirm: z.boolean().optional(),
289
- });
290
- export const marketEndCapability = defineCapability({
291
- id: "market.end",
292
- domain: "markets",
293
- roles: ["user"],
294
- description: "End a running fill: its reservation stops, its VMs stop, and its GPUs go back on the book..",
295
- mutation: "preview-confirm",
296
- http: { method: "DELETE", path: "/commerce/reservations/{fillId}" },
297
- input: marketEndInput,
298
- cli: {
299
- command: ["market", "end"],
300
- vnext: help(["market", "end"], "End a running fill and stop its VMs.", "ornn market end --fill-id <id>", "ornn market end --fill-id <id> --format json", ["market fills"], 39, ["fill ID", "reservation ID"]),
301
- },
302
- slack: false,
303
- execute: async (ctx, input) => {
304
- const parsed = marketEndInput.parse(input);
305
- const gate = await consent(ctx, "market.end", "End fill", [
306
- { label: "Fill", value: parsed.fillId },
307
- { label: "Consequence", value: "The reservation ends and its VMs stop." },
308
- ], { fillId: parsed.fillId });
309
- if (gate)
310
- return gate;
311
- return ctx.fetch(`/commerce/reservations/${seg(parsed.fillId)}`, { method: "DELETE" });
312
- },
313
- });
314
- export const offersListInput = z.object({
315
- $positionals: positionals,
316
- listingId: z
317
- .string()
318
- .uuid()
319
- .optional()
320
- .describe("A primary listing whose offer book to read. Omit for your organization's offers."),
321
- });
322
- export const offersListCapability = defineCapability({
323
- id: "offers.list",
324
- domain: "markets",
325
- roles: ["user"],
326
- description: "List offers with their status. Without listingId: the offers this organization made and the offers on listings it owns (onMyListing: true, with netPricePerGpuHourMicroUsd, what it receives). With listingId: that listing's offer book.",
327
- mutation: "read",
328
- http: { method: "GET", path: `${BASE}/offers` },
329
- input: offersListInput,
330
- cli: {
331
- command: ["offers", "list"],
332
- vnext: help(["offers", "list"], "List offers your organization made or received, or one listing's offer book.", "ornn offers list [--listing-id <id>]", "ornn offers list --format json", ["offers post", "offers accept", "offers cancel"], 42, ["listing ID"]),
333
- },
334
- slack: false,
335
- execute: async (ctx, input) => {
336
- const parsed = offersListInput.parse(input ?? {});
337
- return ctx.fetch(`${BASE}/offers${query({ listingId: parsed.listingId })}`, {
338
- method: "GET",
339
- });
340
- },
341
- });
342
- export const offerPostInput = z.object({
343
- $positionals: positionals,
344
- listingId: z.string().uuid().describe("A primary listing."),
345
- listingTermId: z
346
- .string()
347
- .uuid()
348
- .describe("The listingTermsId of a non-spot term of that listing, from listings.terms."),
349
- durationSeconds: z.coerce
350
- .number()
351
- .int()
352
- .positive()
353
- .optional()
354
- .describe("How long the reservation runs, within the term's minimum and maximum duration. Omit only when they are equal, or when the term has none (the rest of the listing)."),
355
- pricePerGpuHourMicroUsd: microUsd.describe("Offer price in micro-USD per GPU-hour (1000000 = $1.00). Covers every node on the listing."),
356
- downPaymentCents: z.coerce
357
- .number()
358
- .int()
359
- .min(0)
360
- .optional()
361
- .describe("The down payment you offer, in cents."),
362
- idempotencyKey: z.string().min(1).max(200).optional(),
363
- confirm: z.boolean().optional(),
364
- });
365
- export const offerPostCapability = defineCapability({
366
- id: "offers.post",
367
- domain: "markets",
368
- roles: ["user"],
369
- description: "Offer a price for a whole primary listing on one of its terms: every node, from the later of the listing's start and now, for durationSeconds. The listing owner accepts it to create your reservation. Relisted (secondary) capacity takes no offers: buy its windows with reservations.purchase..",
370
- mutation: "preview-confirm",
371
- http: { method: "POST", path: `${BASE}/offers` },
372
- input: offerPostInput,
373
- cli: {
374
- command: ["offers", "post"],
375
- vnext: help(["offers", "post"], "Offer a price for a whole primary listing on one of its terms.", "ornn offers post --listing-id <id> --listing-term-id <id> [--duration-seconds <n>] --price-per-gpu-hour-micro-usd <n> [--down-payment-cents <n>]", "ornn offers post --listing-id <id> --listing-term-id <id> --duration-seconds 2592000 --price-per-gpu-hour-micro-usd 2500000 --format json", ["capacity-offers terms", "offers list", "offers cancel"], 43, ["listing ID", "listingTermsId from capacity-offers terms"]),
376
- },
377
- slack: false,
378
- execute: async (ctx, input) => {
379
- const parsed = offerPostInput.parse(input);
380
- const body = {
381
- listingId: parsed.listingId,
382
- listingTermId: parsed.listingTermId,
383
- ...(parsed.durationSeconds !== undefined ? { durationSeconds: parsed.durationSeconds } : {}),
384
- pricePerGpuHourMicroUsd: parsed.pricePerGpuHourMicroUsd,
385
- ...(parsed.downPaymentCents !== undefined
386
- ? { downPaymentCents: parsed.downPaymentCents }
387
- : {}),
388
- };
389
- const gate = await consent(ctx, "offers.post", "Post offer", [
390
- { label: "Listing", value: parsed.listingId },
391
- { label: "Term", value: parsed.listingTermId },
392
- {
393
- label: "Duration",
394
- value: parsed.durationSeconds !== undefined
395
- ? `${parsed.durationSeconds} seconds from the later of the listing's start and now`
396
- : "The term's only duration, or the rest of the listing",
397
- },
398
- { label: "Price", value: microUsdLabel(parsed.pricePerGpuHourMicroUsd) },
399
- ...(parsed.downPaymentCents !== undefined
400
- ? [{ label: "Down payment", value: `$${(parsed.downPaymentCents / 100).toFixed(2)}` }]
401
- : []),
402
- ], body);
403
- if (gate)
404
- return gate;
405
- return ctx.fetch(`${BASE}/offers`, {
406
- method: "POST",
407
- body,
408
- headers: idempotencyHeaders(ctx, parsed.idempotencyKey),
409
- });
410
- },
411
- });
412
- export const offerDecisionInput = z.object({
413
- $positionals: positionals,
414
- offerId: z.string().uuid(),
415
- confirm: z.boolean().optional(),
416
- });
417
- export const offerAcceptCapability = defineCapability({
418
- id: "offers.accept",
419
- domain: "markets",
420
- roles: ["user"],
421
- description: "Accept an offer on a primary listing you own. The buyer's reservation is booked and the listing's overlapping open offers are cancelled..",
422
- mutation: "preview-confirm",
423
- http: { method: "POST", path: `${BASE}/offers/{offerId}/accept` },
424
- input: offerDecisionInput,
425
- cli: {
426
- command: ["offers", "accept"],
427
- vnext: help(["offers", "accept"], "Accept one offer on a listing you own.", "ornn offers accept --offer-id <id>", "ornn offers accept --offer-id <id> --format json", ["offers list"], 44, ["offer ID"]),
428
- },
429
- slack: false,
430
- execute: async (ctx, input) => {
431
- const parsed = offerDecisionInput.parse(input);
432
- const gate = await consent(ctx, "offers.accept", "Accept offer", [
433
- { label: "Offer", value: parsed.offerId },
434
- {
435
- label: "Consequence",
436
- value: "The buyer's reservation is booked; this listing's overlapping open offers are cancelled.",
437
- },
438
- ], { offerId: parsed.offerId });
439
- if (gate)
440
- return gate;
441
- return ctx.fetch(`${BASE}/offers/${seg(parsed.offerId)}/accept`, {
442
- method: "POST",
443
- body: {},
444
- });
445
- },
446
- });
447
- export const offerCancelCapability = defineCapability({
448
- id: "offers.cancel",
449
- domain: "markets",
450
- roles: ["user"],
451
- description: "Cancel an open offer you made, or one on a listing you own..",
452
- mutation: "preview-confirm",
453
- http: { method: "DELETE", path: `${BASE}/offers/{offerId}` },
454
- input: offerDecisionInput,
455
- cli: {
456
- command: ["offers", "cancel"],
457
- vnext: help(["offers", "cancel"], "Cancel one open offer.", "ornn offers cancel --offer-id <id>", "ornn offers cancel --offer-id <id> --format json", ["offers list"], 45, ["offer ID"]),
458
- },
459
- slack: false,
460
- execute: async (ctx, input) => {
461
- const parsed = offerDecisionInput.parse(input);
462
- const gate = await consent(ctx, "offers.cancel", "Cancel offer", [{ label: "Offer", value: parsed.offerId }], { offerId: parsed.offerId });
463
- if (gate)
464
- return gate;
465
- return ctx.fetch(`${BASE}/offers/${seg(parsed.offerId)}`, { method: "DELETE" });
466
- },
467
- });
468
- export const marketCapabilities = [
469
- marketBooksCapability,
470
- marketBookCapability,
471
- marketTradesCapability,
472
- marketQuoteCapability,
473
- marketBidCapability,
474
- marketOrdersCapability,
475
- marketCancelCapability,
476
- marketFillsCapability,
477
- marketEndCapability,
478
- offersListCapability,
479
- offerPostCapability,
480
- offerAcceptCapability,
481
- offerCancelCapability,
482
- ];
@@ -1,176 +0,0 @@
1
- import { z } from "zod";
2
- import { defineCapability, } from "../capability.js";
3
- const mountInput = z
4
- .object({
5
- $positionals: z.array(z.string()).default([]),
6
- access: z.string().optional(),
7
- capacityGib: z.union([z.string(), z.number()]).optional(),
8
- cursor: z.string().optional(),
9
- idempotencyKey: z.string().optional(),
10
- limit: z.union([z.string(), z.number()]).optional(),
11
- noWait: z.boolean().optional(),
12
- performanceTier: z.string().optional(),
13
- timeout: z.string().optional(),
14
- volume: z.string().optional(),
15
- wait: z.boolean().optional(),
16
- yes: z.boolean().optional(),
17
- })
18
- .strict();
19
- function mountExecutor(context) {
20
- const interaction = context.cli?.interaction;
21
- if (!interaction?.mounts) {
22
- throw new Error("This capability must execute through the Ornn CLI mount runtime.");
23
- }
24
- return interaction.mounts.bind(interaction);
25
- }
26
- function mountCapability({ acceptedReferences = [], automation, command, description, human, id, mutation, order, outcome, related = [], resumableStates = [], review, }) {
27
- return defineCapability({
28
- id,
29
- domain: "storage",
30
- roles: ["user"],
31
- description,
32
- mutation,
33
- input: mountInput,
34
- cli: {
35
- command,
36
- vnext: {
37
- arguments: "semantic",
38
- audience: "customer",
39
- category: "resource",
40
- order,
41
- outcome,
42
- human,
43
- automation,
44
- acceptedReferences,
45
- related,
46
- resumableStates,
47
- ...(review ? { review } : {}),
48
- },
49
- },
50
- mcp: false,
51
- slack: false,
52
- execute: async (context, input) => mountExecutor(context)(id, input),
53
- });
54
- }
55
- export const mountCapabilities = [
56
- mountCapability({
57
- id: "storage.volume-mounts.candidates",
58
- command: ["volume-mounts", "candidates"],
59
- description: "List capacity reservations eligible for a managed-volume mount.",
60
- mutation: "read",
61
- order: 540,
62
- outcome: "List one bounded page of safe Bare Metal volume-mount candidates.",
63
- human: "ornn volume-mounts candidates [--limit <1-500>] [--cursor <cursor>]",
64
- automation: "ornn volume-mounts candidates --limit 50 --format json",
65
- related: ["volume-mounts attach", "volumes list"],
66
- }),
67
- mountCapability({
68
- id: "storage.volume-mounts.show",
69
- command: ["volume-mounts", "show"],
70
- description: "Show one reservation's exact managed-volume relationship and per-machine readiness.",
71
- mutation: "read",
72
- order: 541,
73
- outcome: "Show actual per-machine mount state without rewriting volume lifecycle.",
74
- human: "ornn volume-mounts show <canonical-reservation-id>",
75
- automation: "ornn volume-mounts show <canonical-reservation-id> --format json",
76
- acceptedReferences: ["canonical capacity-reservation ID"],
77
- related: ["volume-mounts wait", "volumes show"],
78
- }),
79
- mountCapability({
80
- id: "storage.volume-mounts.attach",
81
- command: ["volume-mounts", "attach"],
82
- description: "Attach one exact managed volume to every machine in one exact capacity reservation.",
83
- mutation: "preview-confirm",
84
- order: 542,
85
- outcome: "Reconcile one exact volume-mount goal and preserve per-machine readiness.",
86
- human: "ornn volume-mounts attach <canonical-reservation-id> --volume <exact-name-or-id> --access read-only|read-write [--no-wait]",
87
- automation: "ornn volume-mounts attach <canonical-reservation-id> --volume <canonical-volume-id> --access read-only|read-write --idempotency-key <key> --format json",
88
- acceptedReferences: [
89
- "canonical capacity-reservation ID",
90
- "canonical or exact unique managed-volume reference",
91
- ],
92
- review: "Review the exact capacity reservation, volume, and access mode.",
93
- resumableStates: ["accepted", "partial", "ready"],
94
- related: ["volume-mounts wait", "volume-mounts detach"],
95
- }),
96
- mountCapability({
97
- id: "storage.volume-mounts.wait",
98
- command: ["volume-mounts", "wait"],
99
- description: "Wait locally for every requested machine mount to reach a durable terminal state.",
100
- mutation: "read",
101
- order: 543,
102
- outcome: "Wait with a bounded deadline while preserving useful per-machine partial data.",
103
- human: "ornn volume-mounts wait <canonical-reservation-id> [--timeout <duration>]",
104
- automation: "ornn volume-mounts wait <canonical-reservation-id> --timeout <duration> --format json",
105
- acceptedReferences: ["canonical capacity-reservation ID"],
106
- resumableStates: ["partial", "ready"],
107
- related: ["volume-mounts show", "volume-mounts detach"],
108
- }),
109
- mountCapability({
110
- id: "storage.volume-mounts.detach",
111
- command: ["volume-mounts", "detach"],
112
- description: "Detach one exact reservation relationship without deleting its volume.",
113
- mutation: "preview-confirm",
114
- order: 544,
115
- outcome: "Reconcile an exact detached goal and preserve the underlying volume.",
116
- human: "ornn volume-mounts detach <canonical-reservation-id>",
117
- automation: "ornn volume-mounts detach <canonical-reservation-id> --idempotency-key <key> --format json",
118
- acceptedReferences: ["canonical capacity-reservation ID"],
119
- review: "Review the exact relationship and access loss; the managed volume remains.",
120
- resumableStates: ["detaching", "ended"],
121
- related: ["volumes show", "private-networks list"],
122
- }),
123
- mountCapability({
124
- id: "storage.filesystems.deploy",
125
- command: ["filesystems", "deploy"],
126
- description: "Deploy one managed filesystem for an exact capacity reservation.",
127
- mutation: "preview-confirm",
128
- order: 550,
129
- outcome: "Create or rediscover one filesystem deployment and expose every machine mount.",
130
- human: "ornn filesystems deploy <canonical-reservation-id> --performance-tier <tier> --capacity-gib <gib> [--no-wait]",
131
- automation: "ornn filesystems deploy <canonical-reservation-id> --performance-tier <tier> --capacity-gib <gib> --idempotency-key <key> --format json",
132
- acceptedReferences: ["canonical capacity-reservation ID"],
133
- review: "Review the exact reservation, performance tier, capacity, and managed filesystem consequence.",
134
- resumableStates: ["accepted", "partial", "ready"],
135
- related: ["filesystems wait", "filesystems delete"],
136
- }),
137
- mountCapability({
138
- id: "storage.filesystems.show",
139
- command: ["filesystems", "show"],
140
- description: "Summarize one filesystem deployment from its underlying per-machine mounts.",
141
- mutation: "read",
142
- order: 551,
143
- outcome: "Show actual per-machine filesystem readiness without changing volume state.",
144
- human: "ornn filesystems show <canonical-reservation-id>",
145
- automation: "ornn filesystems show <canonical-reservation-id> --format json",
146
- acceptedReferences: ["canonical capacity-reservation ID"],
147
- related: ["filesystems wait", "volume-mounts show"],
148
- }),
149
- mountCapability({
150
- id: "storage.filesystems.wait",
151
- command: ["filesystems", "wait"],
152
- description: "Wait locally for a filesystem deployment's per-machine mount goal.",
153
- mutation: "read",
154
- order: 552,
155
- outcome: "Wait for every filesystem member while retaining partial member data.",
156
- human: "ornn filesystems wait <canonical-reservation-id> [--timeout <duration>]",
157
- automation: "ornn filesystems wait <canonical-reservation-id> --timeout <duration> --format json",
158
- acceptedReferences: ["canonical capacity-reservation ID"],
159
- resumableStates: ["partial", "ready"],
160
- related: ["filesystems show", "filesystems delete"],
161
- }),
162
- mountCapability({
163
- id: "storage.filesystems.delete",
164
- command: ["filesystems", "delete"],
165
- description: "Remove one filesystem deployment relationship without deleting its managed volume.",
166
- mutation: "preview-confirm",
167
- order: 553,
168
- outcome: "Detach every filesystem member while preserving the underlying managed volume.",
169
- human: "ornn filesystems delete <canonical-reservation-id>",
170
- automation: "ornn filesystems delete <canonical-reservation-id> --idempotency-key <key> --format json",
171
- acceptedReferences: ["canonical capacity-reservation ID"],
172
- review: "Review the exact deployment and access loss; its managed volume remains.",
173
- resumableStates: ["detaching", "ended"],
174
- related: ["volumes show", "filesystems deploy"],
175
- }),
176
- ];