@ornncompute/cli 0.2.24 → 1.0.34
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 +351 -426
- package/package.json +12 -6
- package/src/admin-capacity-reservations.mjs +305 -0
- package/src/admin-command-handlers.mjs +57 -0
- package/src/admin-enrollment.mjs +681 -0
- package/src/admin-mutations.mjs +187 -0
- package/src/admin-node-diagnostics.mjs +412 -0
- package/src/admin-node-lifecycle.mjs +905 -0
- package/src/admin-shell.mjs +456 -0
- package/src/api-client.mjs +81 -28
- package/src/atomic-output.mjs +112 -0
- package/src/auth-store.mjs +182 -11
- package/src/capability-catalog.mjs +7 -0
- package/src/catalog-shell.mjs +1363 -0
- package/src/cli.mjs +123 -10266
- package/src/connect-mode-handlers.mjs +170 -0
- package/src/device-auth.mjs +179 -62
- package/src/evidence-commands.mjs +1354 -0
- package/src/external-bucket-commands.mjs +1374 -0
- package/src/gpu-catalog.mjs +21 -0
- package/src/identity-file.mjs +28 -0
- package/src/interaction-runtime.mjs +310 -0
- package/src/kubernetes-commands.mjs +2235 -0
- package/src/launch-mode-handlers.mjs +119 -0
- package/src/machine-reference.mjs +285 -0
- package/src/mount-commands.mjs +1148 -0
- package/src/session-commands.mjs +565 -0
- package/src/slurm-commands.mjs +274 -0
- package/src/startup.mjs +34 -11
- package/src/storage-commands.mjs +1164 -0
- package/src/update.mjs +172 -24
- package/src/vm-commands.mjs +4308 -0
- package/src/vpn-secret-output.mjs +150 -0
- package/src/wait-runtime.mjs +231 -0
- package/vendor/capabilities/capabilities/admin-capacity-reservations.js +96 -0
- package/vendor/capabilities/capabilities/admin-enrollment.js +321 -0
- package/vendor/capabilities/capabilities/admin-node-diagnostics.js +88 -0
- package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +235 -0
- package/vendor/capabilities/capabilities/admin.js +89 -0
- package/vendor/capabilities/capabilities/cli.js +156 -0
- package/vendor/capabilities/capabilities/clusters.js +150 -1
- package/vendor/capabilities/capabilities/commerce-market.js +330 -0
- package/vendor/capabilities/capabilities/compute.js +522 -0
- package/vendor/capabilities/capabilities/evidence.js +145 -0
- package/vendor/capabilities/capabilities/external-buckets.js +191 -0
- package/vendor/capabilities/capabilities/fleet.js +77 -25
- package/vendor/capabilities/capabilities/identity.js +114 -3
- package/vendor/capabilities/capabilities/listings.js +141 -144
- package/vendor/capabilities/capabilities/market-shared.js +44 -0
- package/vendor/capabilities/capabilities/markets.js +449 -0
- package/vendor/capabilities/capabilities/mounts.js +176 -0
- package/vendor/capabilities/capabilities/networks.js +1264 -0
- package/vendor/capabilities/capabilities/observability.js +38 -8
- package/vendor/capabilities/capabilities/tokens.js +32 -17
- package/vendor/capabilities/capabilities/volumes.js +178 -0
- package/vendor/capabilities/capability.js +21 -14
- package/vendor/capabilities/cli-catalog.js +67 -0
- package/vendor/capabilities/cli-migrations.js +261 -0
- package/vendor/capabilities/cli.js +7 -0
- package/vendor/capabilities/software-catalog.js +36 -0
- package/vendor/capabilities/spec-catalog.js +28 -5
- package/vendor/capabilities/supplier-directory.js +20 -0
- package/src/catalog-dispatch.mjs +0 -605
- package/src/color.mjs +0 -71
- package/vendor/capabilities/capabilities/clusters.d.ts +0 -2
- package/vendor/capabilities/capabilities/fleet.d.ts +0 -8
- package/vendor/capabilities/capabilities/identity.d.ts +0 -3
- package/vendor/capabilities/capabilities/listings.d.ts +0 -51
- package/vendor/capabilities/capabilities/observability.d.ts +0 -5
- package/vendor/capabilities/capabilities/staff-access.d.ts +0 -29
- package/vendor/capabilities/capabilities/staff-access.js +0 -278
- package/vendor/capabilities/capabilities/staff-commerce.d.ts +0 -160
- package/vendor/capabilities/capabilities/staff-commerce.js +0 -689
- package/vendor/capabilities/capabilities/staff-fleet.d.ts +0 -140
- package/vendor/capabilities/capabilities/staff-fleet.js +0 -538
- package/vendor/capabilities/capabilities/staff-gtm.d.ts +0 -142
- package/vendor/capabilities/capabilities/staff-gtm.js +0 -521
- package/vendor/capabilities/capabilities/staff-shared.d.ts +0 -47
- package/vendor/capabilities/capabilities/staff-shared.js +0 -98
- package/vendor/capabilities/capabilities/tokens.d.ts +0 -10
- package/vendor/capabilities/capabilities/users.d.ts +0 -2
- package/vendor/capabilities/capability.d.ts +0 -93
- package/vendor/capabilities/catalog.d.ts +0 -3
- package/vendor/capabilities/catalog.js +0 -26
- package/vendor/capabilities/index.d.ts +0 -16
- package/vendor/capabilities/index.js +0 -16
- package/vendor/capabilities/names.d.ts +0 -6
- package/vendor/capabilities/role.d.ts +0 -6
- package/vendor/capabilities/role.js +0 -17
- package/vendor/capabilities/spec-catalog.d.ts +0 -78
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { defineCapability } from "../capability.js";
|
|
3
|
+
import { consent, flag, idempotencyHeaders, microUsdLabel, positionals, query, seg, } from "./market-shared.js";
|
|
4
|
+
// Commerce market verbs: one capability per role-aware `/commerce` route.
|
|
5
|
+
// Commerce decides from the caller's session what each listing or
|
|
6
|
+
// reservation reveals; these verbs return its JSON unchanged.
|
|
7
|
+
function help(command, outcome, human, automation, related, order, acceptedReferences = []) {
|
|
8
|
+
return {
|
|
9
|
+
arguments: "semantic",
|
|
10
|
+
audience: "customer",
|
|
11
|
+
category: "resource",
|
|
12
|
+
command,
|
|
13
|
+
outcome,
|
|
14
|
+
human,
|
|
15
|
+
automation,
|
|
16
|
+
acceptedReferences,
|
|
17
|
+
related,
|
|
18
|
+
order,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const microUsd = z.coerce.number().int().positive();
|
|
22
|
+
const pageLimit = z.coerce.number().int().min(1).max(200).optional();
|
|
23
|
+
const nodeIdList = z.preprocess((value) => typeof value === "string"
|
|
24
|
+
? value
|
|
25
|
+
.split(",")
|
|
26
|
+
.map((part) => part.trim())
|
|
27
|
+
.filter(Boolean)
|
|
28
|
+
: value, z.array(z.string().uuid()).min(1));
|
|
29
|
+
export const listingsListInput = z.object({
|
|
30
|
+
$positionals: positionals,
|
|
31
|
+
kind: z.enum(["primary", "secondary"]).optional(),
|
|
32
|
+
state: z.enum(["available", "internal", "delisted"]).optional(),
|
|
33
|
+
sourceReservationId: z.string().uuid().optional(),
|
|
34
|
+
sourceListingId: z.string().uuid().optional(),
|
|
35
|
+
limit: pageLimit,
|
|
36
|
+
cursor: z.string().min(1).optional(),
|
|
37
|
+
});
|
|
38
|
+
export const listingsListCapability = defineCapability({
|
|
39
|
+
id: "listings.list",
|
|
40
|
+
domain: "listings",
|
|
41
|
+
roles: ["user"],
|
|
42
|
+
description: "List Commerce listings. Primary listings are shown to approved organizations; secondary listings (relists) to every signed-in organization. Prices are micro-USD per GPU-hour.",
|
|
43
|
+
mutation: "read",
|
|
44
|
+
http: { method: "GET", path: "/commerce/listings" },
|
|
45
|
+
input: listingsListInput,
|
|
46
|
+
cli: {
|
|
47
|
+
command: ["capacity-offers", "list"],
|
|
48
|
+
vnext: help(["capacity-offers", "list"], "List primary and secondary listings with bounded pagination and no supplier provenance.", "ornn capacity-offers list [--kind primary|secondary] [--source-reservation-id <id>] [--limit <1-200>] [--cursor <opaque>]", "ornn capacity-offers list --limit 50 --format json", ["capacity-offers show", "schedules list"], 20, ["opaque page cursor"]),
|
|
49
|
+
},
|
|
50
|
+
slack: false,
|
|
51
|
+
execute: async (ctx, input) => {
|
|
52
|
+
const parsed = listingsListInput.parse(input ?? {});
|
|
53
|
+
return ctx.fetch(`/commerce/listings${query({
|
|
54
|
+
kind: parsed.kind,
|
|
55
|
+
state: parsed.state,
|
|
56
|
+
sourceReservationId: parsed.sourceReservationId,
|
|
57
|
+
sourceListingId: parsed.sourceListingId,
|
|
58
|
+
limit: parsed.limit,
|
|
59
|
+
cursor: parsed.cursor,
|
|
60
|
+
})}`, { method: "GET" });
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
export const listingShowInput = z.object({
|
|
64
|
+
$positionals: positionals,
|
|
65
|
+
listingId: z.string().uuid(),
|
|
66
|
+
});
|
|
67
|
+
export const listingShowCapability = defineCapability({
|
|
68
|
+
id: "listings.show",
|
|
69
|
+
domain: "listings",
|
|
70
|
+
roles: ["user"],
|
|
71
|
+
description: "Show one Commerce listing: specs, window, node count and its buyer price.",
|
|
72
|
+
mutation: "read",
|
|
73
|
+
http: { method: "GET", path: "/commerce/listings/{listingId}" },
|
|
74
|
+
input: listingShowInput,
|
|
75
|
+
cli: {
|
|
76
|
+
command: ["capacity-offers", "show"],
|
|
77
|
+
vnext: help(["capacity-offers", "show"], "Inspect one listing's hardware, facility, window and price.", "ornn capacity-offers show --listing-id <id>", "ornn capacity-offers show --listing-id <id> --format json", ["capacity-offers list", "schedules show"], 21, ["listing ID"]),
|
|
78
|
+
},
|
|
79
|
+
slack: false,
|
|
80
|
+
execute: async (ctx, input) => {
|
|
81
|
+
const parsed = listingShowInput.parse(input);
|
|
82
|
+
return ctx.fetch(`/commerce/listings/${seg(parsed.listingId)}`, { method: "GET" });
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
export const listingRelistInput = z
|
|
86
|
+
.object({
|
|
87
|
+
$positionals: positionals,
|
|
88
|
+
sourceReservationId: z
|
|
89
|
+
.string()
|
|
90
|
+
.uuid()
|
|
91
|
+
.optional()
|
|
92
|
+
.describe("A confirmed or active schedule reservation you hold."),
|
|
93
|
+
sourceListingId: z
|
|
94
|
+
.string()
|
|
95
|
+
.uuid()
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("A primary listing you own (suppliers relist their own listings)."),
|
|
98
|
+
nodeIds: nodeIdList.describe("The nodes to relist: a subset of the source's nodes (comma-separated on the CLI)."),
|
|
99
|
+
startsAt: z.string().min(1).describe("RFC 3339 start, inside the source's window."),
|
|
100
|
+
endsAt: z.string().min(1).describe("RFC 3339 end, inside the source's window."),
|
|
101
|
+
askPricePerGpuHourMicroUsd: microUsd.describe("Asking price in micro-USD per GPU-hour, the listing's only price: buyers buy any open window at it, and idle time sells as spot at it."),
|
|
102
|
+
sellAtMarketFirst: flag
|
|
103
|
+
.default(false)
|
|
104
|
+
.describe("Sell each node's GPUs into resting spot bids before asking at the asking price."),
|
|
105
|
+
idempotencyKey: z.string().min(1).max(200).optional(),
|
|
106
|
+
confirm: z.boolean().optional(),
|
|
107
|
+
})
|
|
108
|
+
.refine((relist) => (relist.sourceReservationId === undefined) !== (relist.sourceListingId === undefined), {
|
|
109
|
+
message: "Give exactly one of sourceReservationId or sourceListingId.",
|
|
110
|
+
path: ["sourceReservationId"],
|
|
111
|
+
});
|
|
112
|
+
export const listingRelistCapability = defineCapability({
|
|
113
|
+
id: "listings.relist",
|
|
114
|
+
domain: "listings",
|
|
115
|
+
roles: ["user"],
|
|
116
|
+
description: "Relist a time slice and/or node subset of a schedule reservation you hold (or a primary listing you own) as a secondary listing with an asking price. " +
|
|
117
|
+
"Buyers buy any open window of it at the asking price, and its unsold time goes on the spot book. Fails with node_window_sold if those nodes are already sold for part of the window, or relist_overlaps if another live relist of those nodes overlaps it. Requires confirm: true.",
|
|
118
|
+
mutation: "preview-confirm",
|
|
119
|
+
http: { method: "POST", path: "/commerce/listings" },
|
|
120
|
+
input: listingRelistInput,
|
|
121
|
+
cli: {
|
|
122
|
+
command: ["capacity-offers", "relist"],
|
|
123
|
+
vnext: help(["capacity-offers", "relist"], "Relist part of a reservation or primary listing you hold.", "ornn capacity-offers relist --source-reservation-id <id> --node-ids <id,...> --starts-at <time> --ends-at <time> --ask-price-per-gpu-hour-micro-usd <n> [--sell-at-market-first true]", "ornn capacity-offers relist --source-reservation-id <id> --node-ids <id> --starts-at <time> --ends-at <time> --ask-price-per-gpu-hour-micro-usd 2500000 --yes --format json", ["capacity-offers update", "capacity-offers delist", "reservations show"], 23, ["reservation ID", "listing ID", "node ID"]),
|
|
124
|
+
},
|
|
125
|
+
slack: false,
|
|
126
|
+
execute: async (ctx, input) => {
|
|
127
|
+
const parsed = listingRelistInput.parse(input);
|
|
128
|
+
const body = {
|
|
129
|
+
...(parsed.sourceReservationId ? { sourceReservationId: parsed.sourceReservationId } : {}),
|
|
130
|
+
...(parsed.sourceListingId ? { sourceListingId: parsed.sourceListingId } : {}),
|
|
131
|
+
nodeIds: parsed.nodeIds,
|
|
132
|
+
startsAt: parsed.startsAt,
|
|
133
|
+
endsAt: parsed.endsAt,
|
|
134
|
+
askPricePerGpuHourMicroUsd: parsed.askPricePerGpuHourMicroUsd,
|
|
135
|
+
sellAtMarketFirst: parsed.sellAtMarketFirst,
|
|
136
|
+
};
|
|
137
|
+
const gate = await consent(ctx, "listings.relist", "Relist capacity", [
|
|
138
|
+
{
|
|
139
|
+
label: "Source",
|
|
140
|
+
value: parsed.sourceReservationId
|
|
141
|
+
? `reservation ${parsed.sourceReservationId}`
|
|
142
|
+
: `listing ${parsed.sourceListingId}`,
|
|
143
|
+
},
|
|
144
|
+
{ label: "Nodes", value: parsed.nodeIds.join(", ") },
|
|
145
|
+
{ label: "Window", value: `${parsed.startsAt} to ${parsed.endsAt}` },
|
|
146
|
+
{ label: "Asking price", value: microUsdLabel(parsed.askPricePerGpuHourMicroUsd) },
|
|
147
|
+
{ label: "Sell at market first", value: parsed.sellAtMarketFirst ? "yes" : "no" },
|
|
148
|
+
], body);
|
|
149
|
+
if (gate)
|
|
150
|
+
return gate;
|
|
151
|
+
return ctx.fetch("/commerce/listings", {
|
|
152
|
+
method: "POST",
|
|
153
|
+
body,
|
|
154
|
+
headers: idempotencyHeaders(ctx, parsed.idempotencyKey),
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
export const listingUpdateInput = z.object({
|
|
159
|
+
$positionals: positionals,
|
|
160
|
+
listingId: z.string().uuid(),
|
|
161
|
+
askPricePerGpuHourMicroUsd: microUsd,
|
|
162
|
+
confirm: z.boolean().optional(),
|
|
163
|
+
});
|
|
164
|
+
export const listingUpdateCapability = defineCapability({
|
|
165
|
+
id: "listings.update",
|
|
166
|
+
domain: "listings",
|
|
167
|
+
roles: ["user"],
|
|
168
|
+
description: "Change the asking price of a secondary listing you own, its only price. Windows bought later use the new price, and the listing's spot asks are re-sent at it. Requires confirm: true.",
|
|
169
|
+
mutation: "preview-confirm",
|
|
170
|
+
http: { method: "PATCH", path: "/commerce/listings/{listingId}" },
|
|
171
|
+
input: listingUpdateInput,
|
|
172
|
+
cli: {
|
|
173
|
+
command: ["capacity-offers", "update"],
|
|
174
|
+
vnext: help(["capacity-offers", "update"], "Change the asking price of a listing you relisted.", "ornn capacity-offers update --listing-id <id> --ask-price-per-gpu-hour-micro-usd <n>", "ornn capacity-offers update --listing-id <id> --ask-price-per-gpu-hour-micro-usd 2400000 --yes --format json", ["capacity-offers relist", "capacity-offers delist"], 24, ["listing ID"]),
|
|
175
|
+
},
|
|
176
|
+
slack: false,
|
|
177
|
+
execute: async (ctx, input) => {
|
|
178
|
+
const parsed = listingUpdateInput.parse(input);
|
|
179
|
+
const body = { askPricePerGpuHourMicroUsd: parsed.askPricePerGpuHourMicroUsd };
|
|
180
|
+
const gate = await consent(ctx, "listings.update", "Update listing asking price", [
|
|
181
|
+
{ label: "Listing", value: parsed.listingId },
|
|
182
|
+
{ label: "Asking price", value: microUsdLabel(body.askPricePerGpuHourMicroUsd) },
|
|
183
|
+
], { listingId: parsed.listingId, ...body });
|
|
184
|
+
if (gate)
|
|
185
|
+
return gate;
|
|
186
|
+
return ctx.fetch(`/commerce/listings/${seg(parsed.listingId)}`, { method: "PATCH", body });
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
export const listingDelistInput = z.object({
|
|
190
|
+
$positionals: positionals,
|
|
191
|
+
listingId: z.string().uuid(),
|
|
192
|
+
confirm: z.boolean().optional(),
|
|
193
|
+
});
|
|
194
|
+
export const listingDelistCapability = defineCapability({
|
|
195
|
+
id: "listings.delist",
|
|
196
|
+
domain: "listings",
|
|
197
|
+
roles: ["user"],
|
|
198
|
+
description: "Delist a listing you own. Its unsold time leaves the market, its spot asks are cancelled and running spot reservations on it end. Windows already bought stay sold. Requires confirm: true.",
|
|
199
|
+
mutation: "preview-confirm",
|
|
200
|
+
http: { method: "DELETE", path: "/commerce/listings/{listingId}" },
|
|
201
|
+
input: listingDelistInput,
|
|
202
|
+
cli: {
|
|
203
|
+
command: ["capacity-offers", "delist"],
|
|
204
|
+
vnext: help(["capacity-offers", "delist"], "Delist a listing you relisted.", "ornn capacity-offers delist --listing-id <id>", "ornn capacity-offers delist --listing-id <id> --yes --format json", ["capacity-offers relist"], 25, ["listing ID"]),
|
|
205
|
+
},
|
|
206
|
+
slack: false,
|
|
207
|
+
execute: async (ctx, input) => {
|
|
208
|
+
const parsed = listingDelistInput.parse(input);
|
|
209
|
+
const gate = await consent(ctx, "listings.delist", "Delist listing", [
|
|
210
|
+
{ label: "Listing", value: parsed.listingId },
|
|
211
|
+
{
|
|
212
|
+
label: "Consequence",
|
|
213
|
+
value: "Unsold time and spot asks leave the market; running spot reservations on it end.",
|
|
214
|
+
},
|
|
215
|
+
], { listingId: parsed.listingId });
|
|
216
|
+
if (gate)
|
|
217
|
+
return gate;
|
|
218
|
+
return ctx.fetch(`/commerce/listings/${seg(parsed.listingId)}`, { method: "DELETE" });
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
export const reservationsListInput = z.object({
|
|
222
|
+
$positionals: positionals,
|
|
223
|
+
kind: z.enum(["schedule", "spot"]).optional(),
|
|
224
|
+
status: z
|
|
225
|
+
.enum([
|
|
226
|
+
"awaiting_down_payment",
|
|
227
|
+
"awaiting_payment",
|
|
228
|
+
"confirmed",
|
|
229
|
+
"active",
|
|
230
|
+
"completed",
|
|
231
|
+
"cancelled",
|
|
232
|
+
])
|
|
233
|
+
.optional(),
|
|
234
|
+
listingId: z.string().uuid().optional().describe("Trades on a listing you own."),
|
|
235
|
+
limit: pageLimit,
|
|
236
|
+
cursor: z.string().min(1).optional(),
|
|
237
|
+
});
|
|
238
|
+
export const reservationsListCapability = defineCapability({
|
|
239
|
+
id: "reservations.list",
|
|
240
|
+
domain: "reservations",
|
|
241
|
+
roles: ["user"],
|
|
242
|
+
description: "List this organization's reservations, schedule and spot alike (a running spot reservation has no end time). With listingId, list the trades on a listing you own.",
|
|
243
|
+
mutation: "read",
|
|
244
|
+
http: { method: "GET", path: "/commerce/reservations" },
|
|
245
|
+
input: reservationsListInput,
|
|
246
|
+
cli: {
|
|
247
|
+
command: ["reservations", "list"],
|
|
248
|
+
vnext: help(["reservations", "list"], "List your organization's schedule and spot reservations.", "ornn reservations list [--kind schedule|spot] [--status <status>] [--listing-id <id>] [--limit <1-200>] [--cursor <opaque>]", "ornn reservations list --format json", ["reservations show", "capacity-offers relist"], 26, ["opaque page cursor"]),
|
|
249
|
+
},
|
|
250
|
+
slack: false,
|
|
251
|
+
execute: async (ctx, input) => {
|
|
252
|
+
const parsed = reservationsListInput.parse(input ?? {});
|
|
253
|
+
return ctx.fetch(`/commerce/reservations${query({
|
|
254
|
+
kind: parsed.kind,
|
|
255
|
+
status: parsed.status,
|
|
256
|
+
listingId: parsed.listingId,
|
|
257
|
+
limit: parsed.limit,
|
|
258
|
+
cursor: parsed.cursor,
|
|
259
|
+
})}`, { method: "GET" });
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
export const reservationLookupInput = z.object({
|
|
263
|
+
$positionals: positionals,
|
|
264
|
+
reservationId: z.string().uuid(),
|
|
265
|
+
});
|
|
266
|
+
export const reservationsShowCapability = defineCapability({
|
|
267
|
+
id: "reservations.show",
|
|
268
|
+
domain: "reservations",
|
|
269
|
+
roles: ["user"],
|
|
270
|
+
description: "Show one reservation: kind, status, window, price and node count.",
|
|
271
|
+
mutation: "read",
|
|
272
|
+
http: { method: "GET", path: "/commerce/reservations/{reservationId}" },
|
|
273
|
+
input: reservationLookupInput,
|
|
274
|
+
cli: {
|
|
275
|
+
command: ["reservations", "show"],
|
|
276
|
+
vnext: help(["reservations", "show"], "Inspect one reservation.", "ornn reservations show --reservation-id <id>", "ornn reservations show --reservation-id <id> --format json", ["reservations list", "reservations invoices"], 27, ["reservation ID"]),
|
|
277
|
+
},
|
|
278
|
+
slack: false,
|
|
279
|
+
execute: async (ctx, input) => {
|
|
280
|
+
const parsed = reservationLookupInput.parse(input);
|
|
281
|
+
return ctx.fetch(`/commerce/reservations/${seg(parsed.reservationId)}`, { method: "GET" });
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
export const reservationInvoicesCapability = defineCapability({
|
|
285
|
+
id: "reservations.invoices",
|
|
286
|
+
domain: "billing",
|
|
287
|
+
roles: ["user"],
|
|
288
|
+
description: "List a reservation's invoices: the down payment and each billing period, with status and amount in cents.",
|
|
289
|
+
mutation: "read",
|
|
290
|
+
http: { method: "GET", path: "/commerce/reservations/{reservationId}/invoices" },
|
|
291
|
+
input: reservationLookupInput,
|
|
292
|
+
cli: {
|
|
293
|
+
command: ["reservations", "invoices"],
|
|
294
|
+
vnext: help(["reservations", "invoices"], "List one reservation's invoices.", "ornn reservations invoices --reservation-id <id>", "ornn reservations invoices --reservation-id <id> --format json", ["reservations show"], 28, ["reservation ID"]),
|
|
295
|
+
},
|
|
296
|
+
slack: false,
|
|
297
|
+
execute: async (ctx, input) => {
|
|
298
|
+
const parsed = reservationLookupInput.parse(input);
|
|
299
|
+
return ctx.fetch(`/commerce/reservations/${seg(parsed.reservationId)}/invoices`, {
|
|
300
|
+
method: "GET",
|
|
301
|
+
});
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
export const feesShowInput = z.object({ $positionals: positionals });
|
|
305
|
+
export const feesShowCapability = defineCapability({
|
|
306
|
+
id: "fees.show",
|
|
307
|
+
domain: "billing",
|
|
308
|
+
roles: ["user"],
|
|
309
|
+
description: "Show the transaction fee on spot and secondary trades, in parts per million (1000000 = 100%). The side that takes a resting order pays it; primary schedules carry no transaction fee.",
|
|
310
|
+
mutation: "read",
|
|
311
|
+
http: { method: "GET", path: "/commerce/fees" },
|
|
312
|
+
input: feesShowInput,
|
|
313
|
+
cli: {
|
|
314
|
+
command: ["fees", "show"],
|
|
315
|
+
vnext: help(["fees", "show"], "Show the transaction fee on spot and secondary trades.", "ornn fees show", "ornn fees show --format json", ["spot bid", "offers post"], 29),
|
|
316
|
+
},
|
|
317
|
+
slack: false,
|
|
318
|
+
execute: async (ctx) => ctx.fetch("/commerce/fees", { method: "GET" }),
|
|
319
|
+
});
|
|
320
|
+
export const commerceMarketCapabilities = [
|
|
321
|
+
listingsListCapability,
|
|
322
|
+
listingShowCapability,
|
|
323
|
+
listingRelistCapability,
|
|
324
|
+
listingUpdateCapability,
|
|
325
|
+
listingDelistCapability,
|
|
326
|
+
reservationsListCapability,
|
|
327
|
+
reservationsShowCapability,
|
|
328
|
+
reservationInvoicesCapability,
|
|
329
|
+
feesShowCapability,
|
|
330
|
+
];
|