@ornncompute/cli 1.0.123 → 1.0.125
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 +4 -1
- package/package.json +1 -1
- package/src/catalog-shell.mjs +2 -0
- package/src/network-commands.mjs +1187 -0
- package/src/vm-commands.mjs +2 -2
- package/vendor/api-client/orchestrator.js +72 -0
- package/vendor/capabilities/cli.js +141 -994
|
@@ -203,6 +203,52 @@ function updateNodeSanitize(request, nodeId3, jobId, body2) {
|
|
|
203
203
|
return request(sanitizePath(nodeId3, jobId), { method: "PATCH", body: body2 });
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
// ../../packages/api-client/dist/orchestrator/networks.js
|
|
207
|
+
var networks = "/v1/orchestrator/networks";
|
|
208
|
+
function networkPath(id) {
|
|
209
|
+
return `${networks}/${encodeURIComponent(id)}`;
|
|
210
|
+
}
|
|
211
|
+
function listNetworks(request, signal) {
|
|
212
|
+
return request(networks, { method: "GET", ...signal ? { signal } : {} });
|
|
213
|
+
}
|
|
214
|
+
function getNetwork(request, id, query3 = {}, signal) {
|
|
215
|
+
const params = new URLSearchParams();
|
|
216
|
+
if (query3.overlay !== void 0)
|
|
217
|
+
params.set("overlay", String(query3.overlay));
|
|
218
|
+
return request(`${networkPath(id)}${params.size ? `?${params}` : ""}`, {
|
|
219
|
+
method: "GET",
|
|
220
|
+
...signal ? { signal } : {}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function createNetwork(request, body2, options = {}) {
|
|
224
|
+
return request(networks, { method: "POST", body: body2, ...options });
|
|
225
|
+
}
|
|
226
|
+
function updateNetwork(request, id, body2, options = {}) {
|
|
227
|
+
return request(networkPath(id), { method: "PATCH", body: body2, ...options });
|
|
228
|
+
}
|
|
229
|
+
function deleteNetwork(request, id, options = {}) {
|
|
230
|
+
return request(networkPath(id), { method: "DELETE", ...options });
|
|
231
|
+
}
|
|
232
|
+
function listNetworkPeerConfigs(request, networkId, signal) {
|
|
233
|
+
return request(`${networkPath(networkId)}/peers`, {
|
|
234
|
+
method: "GET",
|
|
235
|
+
...signal ? { signal } : {}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function createNetworkPeer(request, networkId, body2, options = {}) {
|
|
239
|
+
return request(`${networkPath(networkId)}/peers`, {
|
|
240
|
+
method: "POST",
|
|
241
|
+
body: body2,
|
|
242
|
+
...options
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
function deleteNetworkPeer(request, networkId, peerId, options = {}) {
|
|
246
|
+
return request(`${networkPath(networkId)}/peers/${encodeURIComponent(peerId)}`, {
|
|
247
|
+
method: "DELETE",
|
|
248
|
+
...options
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
206
252
|
// ../../packages/capabilities/dist/capabilities/admin-ssh.js
|
|
207
253
|
import { z } from "zod";
|
|
208
254
|
|
|
@@ -457,11 +503,11 @@ function listOrganizations(request, query3 = {}, signal) {
|
|
|
457
503
|
async function listSupplierOrganizations(request, signal) {
|
|
458
504
|
const rows = [];
|
|
459
505
|
for (let offset = 0; offset < 5e4; offset += 1e3) {
|
|
460
|
-
const
|
|
461
|
-
if (!Array.isArray(
|
|
506
|
+
const page = await listOrganizations(request, { role: "supplier", limit: 1e3, offset, sort: "created_at", direction: "asc" }, signal);
|
|
507
|
+
if (!Array.isArray(page))
|
|
462
508
|
throw new Error("Invalid supplier directory response.");
|
|
463
|
-
rows.push(...
|
|
464
|
-
if (
|
|
509
|
+
rows.push(...page);
|
|
510
|
+
if (page.length < 1e3)
|
|
465
511
|
return rows;
|
|
466
512
|
}
|
|
467
513
|
throw new Error("The supplier directory is too large to load completely.");
|
|
@@ -1443,8 +1489,8 @@ function query(params) {
|
|
|
1443
1489
|
for (const [key, value] of Object.entries(params))
|
|
1444
1490
|
if (value)
|
|
1445
1491
|
search.set(key, value);
|
|
1446
|
-
const
|
|
1447
|
-
return
|
|
1492
|
+
const text = search.toString();
|
|
1493
|
+
return text ? `?${text}` : "";
|
|
1448
1494
|
}
|
|
1449
1495
|
var MARKETS_SOCKET_PATH = `${BASE3}/ws`;
|
|
1450
1496
|
function scope({ saleType: saleType2, region: region2 } = {}) {
|
|
@@ -1574,11 +1620,11 @@ function resolveIdempotencyKey(ctx, supplied) {
|
|
|
1574
1620
|
return ctx.cli?.interaction?.idempotencyKey(supplied) ?? supplied?.trim();
|
|
1575
1621
|
}
|
|
1576
1622
|
async function consent(ctx, action, title, terms, payload) {
|
|
1577
|
-
const
|
|
1578
|
-
if (
|
|
1579
|
-
if (await
|
|
1623
|
+
const interaction = ctx.cli?.interaction;
|
|
1624
|
+
if (interaction) {
|
|
1625
|
+
if (await interaction.review({ title, terms }))
|
|
1580
1626
|
return null;
|
|
1581
|
-
return
|
|
1627
|
+
return interaction.result({
|
|
1582
1628
|
data: null,
|
|
1583
1629
|
errors: [{ code: "action_declined", message: "No changes were made.", retryable: false }],
|
|
1584
1630
|
exitCode: 1,
|
|
@@ -3532,31 +3578,31 @@ var machineMaintenanceInput = z17.object({
|
|
|
3532
3578
|
yes: z17.boolean().optional()
|
|
3533
3579
|
}).strict();
|
|
3534
3580
|
function runtime(context) {
|
|
3535
|
-
const
|
|
3536
|
-
if (!
|
|
3581
|
+
const interaction = context.cli?.interaction;
|
|
3582
|
+
if (!interaction)
|
|
3537
3583
|
throw new Error("This capability must execute through the Ornn CLI runtime.");
|
|
3538
|
-
return
|
|
3584
|
+
return interaction;
|
|
3539
3585
|
}
|
|
3540
3586
|
async function executeLaunch(context, input) {
|
|
3541
|
-
const
|
|
3542
|
-
if (!
|
|
3587
|
+
const interaction = runtime(context);
|
|
3588
|
+
if (!interaction.launch)
|
|
3543
3589
|
throw new Error("No launch mode handlers are registered.");
|
|
3544
|
-
return
|
|
3590
|
+
return interaction.launch({ context, input, interaction });
|
|
3545
3591
|
}
|
|
3546
3592
|
function executeSshKeys(command) {
|
|
3547
3593
|
return async (context, input) => {
|
|
3548
|
-
const
|
|
3549
|
-
if (!
|
|
3594
|
+
const interaction = runtime(context);
|
|
3595
|
+
if (!interaction.sshKeys)
|
|
3550
3596
|
throw new Error("SSH-key commands are unavailable.");
|
|
3551
|
-
return
|
|
3597
|
+
return interaction.sshKeys(command, input, context);
|
|
3552
3598
|
};
|
|
3553
3599
|
}
|
|
3554
3600
|
function executeMachines(command) {
|
|
3555
3601
|
return async (context, input) => {
|
|
3556
|
-
const
|
|
3557
|
-
if (!
|
|
3602
|
+
const interaction = runtime(context);
|
|
3603
|
+
if (!interaction.machines)
|
|
3558
3604
|
throw new Error("Machine commands are unavailable.");
|
|
3559
|
-
return
|
|
3605
|
+
return interaction.machines(command, input, context);
|
|
3560
3606
|
};
|
|
3561
3607
|
}
|
|
3562
3608
|
function cliOnly(specification) {
|
|
@@ -4824,11 +4870,11 @@ var importInput = z21.object({
|
|
|
4824
4870
|
yes: z21.boolean().optional()
|
|
4825
4871
|
}).strict();
|
|
4826
4872
|
function externalBucketExecutor(context) {
|
|
4827
|
-
const
|
|
4828
|
-
if (!
|
|
4873
|
+
const interaction = context.cli?.interaction;
|
|
4874
|
+
if (!interaction?.externalBuckets) {
|
|
4829
4875
|
throw new Error("This capability must execute through the Ornn CLI external-bucket runtime.");
|
|
4830
4876
|
}
|
|
4831
|
-
return
|
|
4877
|
+
return interaction.externalBuckets.bind(interaction);
|
|
4832
4878
|
}
|
|
4833
4879
|
function externalBucketCapability({ acceptedReferences = [], automation, command, description, human, id, input, mutation, outcome, related = [], resumableStates = [], review }) {
|
|
4834
4880
|
return defineCapability({
|
|
@@ -4969,10 +5015,10 @@ var evidenceInput = z22.object({
|
|
|
4969
5015
|
timeout: z22.string().optional()
|
|
4970
5016
|
}).strict();
|
|
4971
5017
|
function runtime2(context) {
|
|
4972
|
-
const
|
|
4973
|
-
if (!
|
|
5018
|
+
const interaction = context.cli?.interaction;
|
|
5019
|
+
if (!interaction?.evidence)
|
|
4974
5020
|
throw new Error("The CLI evidence runtime is unavailable.");
|
|
4975
|
-
return
|
|
5021
|
+
return interaction;
|
|
4976
5022
|
}
|
|
4977
5023
|
function execute(command) {
|
|
4978
5024
|
return (context, input) => runtime2(context).evidence(command, input, context);
|
|
@@ -5109,11 +5155,11 @@ var mountInput = z23.object({
|
|
|
5109
5155
|
yes: z23.boolean().optional()
|
|
5110
5156
|
}).strict();
|
|
5111
5157
|
function mountExecutor(context) {
|
|
5112
|
-
const
|
|
5113
|
-
if (!
|
|
5158
|
+
const interaction = context.cli?.interaction;
|
|
5159
|
+
if (!interaction?.mounts) {
|
|
5114
5160
|
throw new Error("This capability must execute through the Ornn CLI mount runtime.");
|
|
5115
5161
|
}
|
|
5116
|
-
return
|
|
5162
|
+
return interaction.mounts.bind(interaction);
|
|
5117
5163
|
}
|
|
5118
5164
|
function mountCapability({ acceptedReferences = [], automation, command, description, human, id, mutation, order, outcome, related = [], resumableStates = [], review }) {
|
|
5119
5165
|
return defineCapability({
|
|
@@ -5754,11 +5800,7 @@ var organizationInviteCapability = defineCapability({
|
|
|
5754
5800
|
|
|
5755
5801
|
// ../../packages/capabilities/dist/capabilities/networks.js
|
|
5756
5802
|
import { z as z27 } from "zod";
|
|
5757
|
-
var
|
|
5758
|
-
var DEFAULT_LIMIT = 50;
|
|
5759
|
-
var unknownRecordSchema = z27.record(z27.string(), z27.unknown());
|
|
5760
|
-
var MAX_LIMIT = 500;
|
|
5761
|
-
var NETWORKS_PATH = "/v1/workflows/compute/networks";
|
|
5803
|
+
var NETWORKS_PATH = "/v1/orchestrator/networks";
|
|
5762
5804
|
var globalInput = {
|
|
5763
5805
|
$positionals: z27.array(z27.string()).optional(),
|
|
5764
5806
|
guided: z27.boolean().optional(),
|
|
@@ -5786,892 +5828,11 @@ var vpnConfigureInput = z27.object({
|
|
|
5786
5828
|
output: z27.string().optional(),
|
|
5787
5829
|
privateKey: z27.string().optional()
|
|
5788
5830
|
}).strict();
|
|
5789
|
-
function
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
function interaction(context) {
|
|
5795
|
-
const cli = context.cli;
|
|
5796
|
-
const runtime3 = cli?.interaction;
|
|
5797
|
-
if (!runtime3)
|
|
5798
|
-
throw new Error("This capability must execute through the Ornn CLI interaction runtime.");
|
|
5799
|
-
return runtime3;
|
|
5800
|
-
}
|
|
5801
|
-
function text(value) {
|
|
5802
|
-
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
5803
|
-
}
|
|
5804
|
-
function shellQuote(value) {
|
|
5805
|
-
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
5806
|
-
}
|
|
5807
|
-
function record(value) {
|
|
5808
|
-
const parsed = unknownRecordSchema.safeParse(value);
|
|
5809
|
-
return parsed.success ? parsed.data : {};
|
|
5810
|
-
}
|
|
5811
|
-
function integer(value) {
|
|
5812
|
-
return typeof value === "number" && Number.isInteger(value) ? value : null;
|
|
5813
|
-
}
|
|
5814
|
-
function normalizedName(value) {
|
|
5815
|
-
return value.normalize("NFKC").trim().replace(/\s+/g, " ").toLocaleLowerCase("en-US");
|
|
5816
|
-
}
|
|
5817
|
-
function normalizedCidr(value) {
|
|
5818
|
-
const [address, rawPrefix, ...extra] = value.trim().split("/");
|
|
5819
|
-
const octets = address?.split(".").map(Number) ?? [];
|
|
5820
|
-
const prefix = Number(rawPrefix);
|
|
5821
|
-
if (extra.length || octets.length !== 4 || octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255) || !Number.isInteger(prefix) || prefix < 0 || prefix > 32) {
|
|
5822
|
-
return value.trim();
|
|
5823
|
-
}
|
|
5824
|
-
const numeric = ((octets[0] * 256 + octets[1]) * 256 + octets[2]) * 256 + octets[3] >>> 0;
|
|
5825
|
-
const mask = prefix === 0 ? 0 : 4294967295 << 32 - prefix >>> 0;
|
|
5826
|
-
const network = (numeric & mask) >>> 0;
|
|
5827
|
-
return `${network >>> 24}.${network >>> 16 & 255}.${network >>> 8 & 255}.${network & 255}/${prefix}`;
|
|
5828
|
-
}
|
|
5829
|
-
function requiredOption(runtime3, value, option, usage) {
|
|
5830
|
-
const parsed = text(value);
|
|
5831
|
-
if (!parsed)
|
|
5832
|
-
runtime3.usage(`${option} is required.
|
|
5833
|
-
${usage}`, { field: option.slice(2) });
|
|
5834
|
-
return parsed;
|
|
5835
|
-
}
|
|
5836
|
-
function exactPositionals(runtime3, positionals4, count, usage) {
|
|
5837
|
-
const values = positionals4 ?? [];
|
|
5838
|
-
if (values.length !== count || values.some((value) => !value.trim()))
|
|
5839
|
-
runtime3.usage(usage);
|
|
5840
|
-
return values.map((value) => value.trim());
|
|
5841
|
-
}
|
|
5842
|
-
function requireCanonicalTarget(runtime3, value) {
|
|
5843
|
-
if (!CANONICAL_ID.test(value)) {
|
|
5844
|
-
runtime3.usage("Private targets currently require a canonical capacity-reservation identifier so connect cannot select an ambiguous resource.", { code: "canonical_reference_required", field: "target" });
|
|
5845
|
-
}
|
|
5846
|
-
return value;
|
|
5847
|
-
}
|
|
5848
|
-
function requireMutationKey(runtime3, input) {
|
|
5849
|
-
if (!runtime3.machine)
|
|
5850
|
-
return text(input.idempotencyKey);
|
|
5851
|
-
const key = text(input.idempotencyKey);
|
|
5852
|
-
if (!key) {
|
|
5853
|
-
runtime3.usage("Machine mutations require --idempotency-key <caller-stable-key> before API I/O.", {
|
|
5854
|
-
code: "idempotency_key_required",
|
|
5855
|
-
field: "idempotencyKey"
|
|
5856
|
-
});
|
|
5857
|
-
}
|
|
5858
|
-
return key;
|
|
5859
|
-
}
|
|
5860
|
-
function mutationHeaders(key) {
|
|
5861
|
-
return key ? { "Idempotency-Key": key } : void 0;
|
|
5862
|
-
}
|
|
5863
|
-
function ownerErrorCode(error) {
|
|
5864
|
-
if (!error || typeof error !== "object" || !("detail" in error))
|
|
5865
|
-
return null;
|
|
5866
|
-
const detail = record(error.detail);
|
|
5867
|
-
const nested = detail.detail ?? detail.error;
|
|
5868
|
-
if (typeof nested === "string")
|
|
5869
|
-
return nested;
|
|
5870
|
-
return text(record(nested).code) ?? text(detail.code);
|
|
5871
|
-
}
|
|
5872
|
-
function lifecycle(statusValue) {
|
|
5873
|
-
const status = text(statusValue)?.toLowerCase() ?? "unknown";
|
|
5874
|
-
if (["active", "ready", "applied", "connected"].includes(status)) {
|
|
5875
|
-
return { class: "ready", phase: "available" };
|
|
5876
|
-
}
|
|
5877
|
-
if (["failed", "degraded", "error"].includes(status)) {
|
|
5878
|
-
return { class: "failed", phase: "needs_attention" };
|
|
5879
|
-
}
|
|
5880
|
-
if (["deleted", "revoked", "disconnected"].includes(status)) {
|
|
5881
|
-
return { class: "ended", phase: "disconnected" };
|
|
5882
|
-
}
|
|
5883
|
-
if (["deleting", "revoking"].includes(status)) {
|
|
5884
|
-
return { class: "working", phase: "disconnecting" };
|
|
5885
|
-
}
|
|
5886
|
-
return { class: "pending", phase: "configuring" };
|
|
5887
|
-
}
|
|
5888
|
-
function reservationTargetLifecycle(statusValue) {
|
|
5889
|
-
const status = text(statusValue)?.toLowerCase() ?? "unknown";
|
|
5890
|
-
if (status === "active")
|
|
5891
|
-
return { class: "ready", phase: "active" };
|
|
5892
|
-
if (["failed", "payment_failed", "error"].includes(status)) {
|
|
5893
|
-
return { class: "failed", phase: status };
|
|
5894
|
-
}
|
|
5895
|
-
if (["cancelled", "canceled", "completed", "ended", "expired", "rejected", "terminated"].includes(status)) {
|
|
5896
|
-
return { class: "ended", phase: status };
|
|
5897
|
-
}
|
|
5898
|
-
return { class: "pending", phase: status };
|
|
5899
|
-
}
|
|
5900
|
-
function projectNetwork(value) {
|
|
5901
|
-
const source = record(value);
|
|
5902
|
-
const attachmentIds = Array.isArray(source.attached_reservation_ids) ? source.attached_reservation_ids.map((value2) => text(value2)).filter((value2) => Boolean(value2 && CANONICAL_ID.test(value2))) : [];
|
|
5903
|
-
return {
|
|
5904
|
-
id: text(source.id),
|
|
5905
|
-
name: text(source.name) ?? "Unnamed private network",
|
|
5906
|
-
cidr: text(source.cidr),
|
|
5907
|
-
lifecycle: lifecycle(source.status),
|
|
5908
|
-
attachment_count: integer(source.attached_reservation_count) ?? attachmentIds.length,
|
|
5909
|
-
attached_reservation_ids: [...new Set(attachmentIds)],
|
|
5910
|
-
created_at: text(source.created_at),
|
|
5911
|
-
updated_at: text(source.updated_at)
|
|
5912
|
-
};
|
|
5913
|
-
}
|
|
5914
|
-
function networkRows(payload) {
|
|
5915
|
-
const source = record(payload);
|
|
5916
|
-
const values = Array.isArray(payload) ? payload : Array.isArray(source.networks) ? source.networks : [];
|
|
5917
|
-
return values.flatMap((value) => {
|
|
5918
|
-
const parsed = unknownRecordSchema.safeParse(value);
|
|
5919
|
-
return parsed.success ? [parsed.data] : [];
|
|
5920
|
-
}).sort((left, right) => {
|
|
5921
|
-
const byName = normalizedName(text(left.name) ?? "").localeCompare(normalizedName(text(right.name) ?? ""));
|
|
5922
|
-
return byName || (text(left.id) ?? "").localeCompare(text(right.id) ?? "");
|
|
5923
|
-
});
|
|
5924
|
-
}
|
|
5925
|
-
function networkFromMutation(payload) {
|
|
5926
|
-
const source = record(payload);
|
|
5927
|
-
return projectNetwork(source.network ?? source);
|
|
5928
|
-
}
|
|
5929
|
-
async function fetchNetworks(context) {
|
|
5930
|
-
return networkRows(await context.fetch(NETWORKS_PATH));
|
|
5931
|
-
}
|
|
5932
|
-
async function resolveNetwork(context, runtime3, reference) {
|
|
5933
|
-
if (CANONICAL_ID.test(reference)) {
|
|
5934
|
-
return record(await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(reference)}`));
|
|
5935
|
-
}
|
|
5936
|
-
const wanted = normalizedName(reference);
|
|
5937
|
-
const matches = (await fetchNetworks(context)).filter((candidate) => normalizedName(text(candidate.name) ?? "") === wanted);
|
|
5938
|
-
if (matches.length === 0) {
|
|
5939
|
-
runtime3.error(`Private network not found: ${reference}.`, {
|
|
5940
|
-
code: "private_network_not_found"
|
|
5941
|
-
});
|
|
5942
|
-
}
|
|
5943
|
-
if (matches.length > 1) {
|
|
5944
|
-
runtime3.usage(`More than one private network has the exact name "${reference}"; use a canonical identifier.`, {
|
|
5945
|
-
code: "private_network_ambiguous",
|
|
5946
|
-
field: "network"
|
|
5947
|
-
});
|
|
5948
|
-
}
|
|
5949
|
-
return matches[0];
|
|
5950
|
-
}
|
|
5951
|
-
function encodeCursor(command, offset) {
|
|
5952
|
-
return encodeURIComponent(JSON.stringify({ command, offset }));
|
|
5953
|
-
}
|
|
5954
|
-
function decodeCursor(runtime3, command, cursor) {
|
|
5955
|
-
if (!cursor)
|
|
5956
|
-
return 0;
|
|
5957
|
-
try {
|
|
5958
|
-
const parsed = record(JSON.parse(decodeURIComponent(cursor)));
|
|
5959
|
-
if (parsed.command === command && Number.isInteger(parsed.offset) && Number(parsed.offset) >= 0) {
|
|
5960
|
-
return Number(parsed.offset);
|
|
5961
|
-
}
|
|
5962
|
-
} catch {
|
|
5963
|
-
}
|
|
5964
|
-
runtime3.usage("The pagination cursor is invalid or belongs to another command.", {
|
|
5965
|
-
code: "invalid_cursor",
|
|
5966
|
-
field: "cursor"
|
|
5967
|
-
});
|
|
5968
|
-
}
|
|
5969
|
-
function pageLimit2(runtime3, raw) {
|
|
5970
|
-
if (raw === void 0)
|
|
5971
|
-
return DEFAULT_LIMIT;
|
|
5972
|
-
const limit = Number(raw);
|
|
5973
|
-
if (!Number.isInteger(limit) || limit < 1 || limit > MAX_LIMIT) {
|
|
5974
|
-
runtime3.usage(`--limit must be an integer from 1 to ${MAX_LIMIT}.`, { field: "limit" });
|
|
5975
|
-
}
|
|
5976
|
-
return limit;
|
|
5977
|
-
}
|
|
5978
|
-
function page(runtime3, command, rows, input) {
|
|
5979
|
-
const limit = pageLimit2(runtime3, input.limit);
|
|
5980
|
-
const offset = decodeCursor(runtime3, command, input.cursor);
|
|
5981
|
-
const items = rows.slice(offset, offset + limit);
|
|
5982
|
-
const nextOffset = offset + items.length;
|
|
5983
|
-
return {
|
|
5984
|
-
items,
|
|
5985
|
-
page: {
|
|
5986
|
-
limit,
|
|
5987
|
-
returned: items.length,
|
|
5988
|
-
next_cursor: nextOffset < rows.length ? encodeCursor(command, nextOffset) : null
|
|
5989
|
-
}
|
|
5990
|
-
};
|
|
5991
|
-
}
|
|
5992
|
-
function declined(runtime3) {
|
|
5993
|
-
return runtime3.result({
|
|
5994
|
-
data: null,
|
|
5995
|
-
errors: [{ code: "action_declined", message: "No changes were made.", retryable: false }],
|
|
5996
|
-
exitCode: 1,
|
|
5997
|
-
outcome: { class: "ended", phase: "declined" },
|
|
5998
|
-
presentation: { lines: ["No changes were made."] }
|
|
5999
|
-
});
|
|
6000
|
-
}
|
|
6001
|
-
function networkLines(network) {
|
|
6002
|
-
const state = record(network.lifecycle);
|
|
6003
|
-
return [
|
|
6004
|
-
`${String(network.name)} (${String(network.id ?? "unknown")})`,
|
|
6005
|
-
` CIDR: ${String(network.cidr ?? "pending")}`,
|
|
6006
|
-
` State: ${state.class} (${state.phase})`
|
|
6007
|
-
];
|
|
6008
|
-
}
|
|
6009
|
-
function networkMutationExecution(runtime3, network, replayed) {
|
|
6010
|
-
const state = record(network.lifecycle);
|
|
6011
|
-
const stateClass = String(state.class);
|
|
6012
|
-
const ready = stateClass === "ready";
|
|
6013
|
-
const failed = stateClass === "failed";
|
|
6014
|
-
const command = ready ? "ornn connect" : `ornn private-networks show ${String(network.id)}`;
|
|
6015
|
-
return runtime3.result({
|
|
6016
|
-
action: {
|
|
6017
|
-
command,
|
|
6018
|
-
description: ready ? "Continue to an exact compute target." : "Inspect private-network readiness before attaching or connecting.",
|
|
6019
|
-
type: "command"
|
|
6020
|
-
},
|
|
6021
|
-
data: { private_network: network, replayed },
|
|
6022
|
-
exitCode: ready ? 0 : failed ? 4 : 3,
|
|
6023
|
-
outcome: ready ? { class: "ready", phase: "active" } : { class: String(state.class), phase: String(state.phase) },
|
|
6024
|
-
presentation: {
|
|
6025
|
-
lines: [
|
|
6026
|
-
ready ? replayed ? "Private network already satisfies this request." : "Private network created." : failed ? "Private network exists, but provisioning failed." : "Private network creation was accepted and is still provisioning.",
|
|
6027
|
-
...networkLines(network)
|
|
6028
|
-
],
|
|
6029
|
-
next: command
|
|
6030
|
-
},
|
|
6031
|
-
resume: ready ? null : { kind: "private_network", ref: String(network.id) }
|
|
6032
|
-
});
|
|
6033
|
-
}
|
|
6034
|
-
async function listPrivateNetworks(context, input) {
|
|
6035
|
-
const runtime3 = interaction(context);
|
|
6036
|
-
exactPositionals(runtime3, input.$positionals, 0, "Usage: ornn private-networks list [--limit <1-500>] [--cursor <cursor>]");
|
|
6037
|
-
const rows = (await fetchNetworks(context)).map(projectNetwork);
|
|
6038
|
-
const selected = page(runtime3, "private-networks list", rows, input);
|
|
6039
|
-
return runtime3.result({
|
|
6040
|
-
data: { private_networks: selected.items },
|
|
6041
|
-
page: selected.page,
|
|
6042
|
-
presentation: {
|
|
6043
|
-
lines: selected.items.length ? selected.items.flatMap(networkLines) : ["No private networks found."],
|
|
6044
|
-
...selected.page.next_cursor ? { next: `ornn private-networks list --cursor ${selected.page.next_cursor}` } : {}
|
|
6045
|
-
}
|
|
6046
|
-
});
|
|
6047
|
-
}
|
|
6048
|
-
async function showPrivateNetwork(context, input) {
|
|
6049
|
-
const runtime3 = interaction(context);
|
|
6050
|
-
const [reference] = exactPositionals(runtime3, input.$positionals, 1, "Usage: ornn private-networks show <exact-name-or-id>");
|
|
6051
|
-
const network = projectNetwork(await resolveNetwork(context, runtime3, reference));
|
|
6052
|
-
return runtime3.result({
|
|
6053
|
-
data: { private_network: network },
|
|
6054
|
-
presentation: { lines: networkLines(network) }
|
|
6055
|
-
});
|
|
6056
|
-
}
|
|
6057
|
-
async function createPrivateNetwork(context, input) {
|
|
6058
|
-
const runtime3 = interaction(context);
|
|
6059
|
-
const usage = "Usage: ornn private-networks create --name <name> [--cidr <cidr>]";
|
|
6060
|
-
exactPositionals(runtime3, input.$positionals, 0, usage);
|
|
6061
|
-
if (!text(input.name) && input.guided === true && !runtime3.machine) {
|
|
6062
|
-
input.name = await runtime3.ask({ label: "Private network name" });
|
|
6063
|
-
}
|
|
6064
|
-
const name = requiredOption(runtime3, input.name, "--name", usage).normalize("NFKC").trim().replace(/\s+/g, " ");
|
|
6065
|
-
const cidr = text(input.cidr) ? normalizedCidr(String(input.cidr)) : null;
|
|
6066
|
-
const idempotencyKey = requireMutationKey(runtime3, input);
|
|
6067
|
-
const matches = (await fetchNetworks(context)).filter((candidate) => normalizedName(text(candidate.name) ?? "") === normalizedName(name));
|
|
6068
|
-
if (matches.length > 1) {
|
|
6069
|
-
runtime3.usage(`More than one private network has the exact name "${name}"; use a different name.`, {
|
|
6070
|
-
code: "private_network_ambiguous",
|
|
6071
|
-
field: "name"
|
|
6072
|
-
});
|
|
6073
|
-
}
|
|
6074
|
-
if (matches.length === 1) {
|
|
6075
|
-
const existingCidr = text(matches[0].cidr);
|
|
6076
|
-
if (cidr && (!existingCidr || normalizedCidr(existingCidr) !== cidr)) {
|
|
6077
|
-
runtime3.usage(`Private network "${name}" already exists with different effective input. Use a new idempotency key and name after review.`, { code: "private_network_replay_conflict", field: "cidr" });
|
|
6078
|
-
}
|
|
6079
|
-
return networkMutationExecution(runtime3, projectNetwork(matches[0]), true);
|
|
6080
|
-
}
|
|
6081
|
-
if (!await runtime3.review({
|
|
6082
|
-
title: "Create private network",
|
|
6083
|
-
terms: [
|
|
6084
|
-
{ label: "Name", value: name },
|
|
6085
|
-
{ label: "CIDR", value: cidr ?? "Automatically assigned" }
|
|
6086
|
-
]
|
|
6087
|
-
}))
|
|
6088
|
-
return declined(runtime3);
|
|
6089
|
-
const created = await context.fetch(NETWORKS_PATH, {
|
|
6090
|
-
body: { name, ...cidr ? { cidr } : {} },
|
|
6091
|
-
headers: mutationHeaders(idempotencyKey),
|
|
6092
|
-
method: "POST"
|
|
6093
|
-
});
|
|
6094
|
-
return networkMutationExecution(runtime3, networkFromMutation(created), false);
|
|
6095
|
-
}
|
|
6096
|
-
async function updatePrivateNetwork(context, input) {
|
|
6097
|
-
const runtime3 = interaction(context);
|
|
6098
|
-
const usage = "Usage: ornn private-networks update <exact-name-or-id> --name <new-name>";
|
|
6099
|
-
const [reference] = exactPositionals(runtime3, input.$positionals, 1, usage);
|
|
6100
|
-
const name = requiredOption(runtime3, input.name, "--name", usage).normalize("NFKC").trim().replace(/\s+/g, " ");
|
|
6101
|
-
const idempotencyKey = requireMutationKey(runtime3, input);
|
|
6102
|
-
const current = await resolveNetwork(context, runtime3, reference);
|
|
6103
|
-
if (normalizedName(text(current.name) ?? "") === normalizedName(name)) {
|
|
6104
|
-
const network2 = projectNetwork(current);
|
|
6105
|
-
return runtime3.result({
|
|
6106
|
-
data: { private_network: network2, replayed: true },
|
|
6107
|
-
presentation: {
|
|
6108
|
-
lines: ["Private network already has the requested name.", ...networkLines(network2)]
|
|
6109
|
-
}
|
|
6110
|
-
});
|
|
6111
|
-
}
|
|
6112
|
-
if ((await fetchNetworks(context)).some((candidate) => normalizedName(text(candidate.name) ?? "") === normalizedName(name))) {
|
|
6113
|
-
runtime3.usage(`Another private network already has the exact name "${name}".`, {
|
|
6114
|
-
code: "private_network_name_conflict",
|
|
6115
|
-
field: "name"
|
|
6116
|
-
});
|
|
6117
|
-
}
|
|
6118
|
-
if (!await runtime3.review({
|
|
6119
|
-
title: "Update private network",
|
|
6120
|
-
terms: [
|
|
6121
|
-
{
|
|
6122
|
-
label: "Private network",
|
|
6123
|
-
value: `${text(current.name) ?? reference} (${text(current.id) ?? reference})`
|
|
6124
|
-
},
|
|
6125
|
-
{ label: "New name", value: name }
|
|
6126
|
-
]
|
|
6127
|
-
}))
|
|
6128
|
-
return declined(runtime3);
|
|
6129
|
-
const updated = await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(String(current.id))}`, {
|
|
6130
|
-
body: { name },
|
|
6131
|
-
headers: mutationHeaders(idempotencyKey),
|
|
6132
|
-
method: "PATCH"
|
|
6133
|
-
});
|
|
6134
|
-
const network = networkFromMutation(updated);
|
|
6135
|
-
return runtime3.result({
|
|
6136
|
-
data: { private_network: network, replayed: false },
|
|
6137
|
-
presentation: { lines: ["Private network updated.", ...networkLines(network)] }
|
|
6138
|
-
});
|
|
6139
|
-
}
|
|
6140
|
-
async function deletePrivateNetwork(context, input) {
|
|
6141
|
-
const runtime3 = interaction(context);
|
|
6142
|
-
const [reference] = exactPositionals(runtime3, input.$positionals, 1, "Usage: ornn private-networks delete <exact-name-or-id>");
|
|
6143
|
-
const idempotencyKey = requireMutationKey(runtime3, input);
|
|
6144
|
-
const projected = projectNetwork(await resolveNetwork(context, runtime3, reference));
|
|
6145
|
-
if (!await runtime3.review({
|
|
6146
|
-
title: "Delete private network",
|
|
6147
|
-
terms: [
|
|
6148
|
-
{ label: "Private network", value: `${String(projected.name)} (${String(projected.id)})` },
|
|
6149
|
-
{
|
|
6150
|
-
label: "Consequence",
|
|
6151
|
-
value: "Permanently delete this organization private network when the owner permits deletion."
|
|
6152
|
-
}
|
|
6153
|
-
],
|
|
6154
|
-
prompt: "Delete this private network?"
|
|
6155
|
-
}))
|
|
6156
|
-
return declined(runtime3);
|
|
6157
|
-
try {
|
|
6158
|
-
await context.fetch(`${NETWORKS_PATH}/${encodeURIComponent(String(projected.id))}`, {
|
|
6159
|
-
headers: mutationHeaders(idempotencyKey),
|
|
6160
|
-
method: "DELETE"
|
|
6161
|
-
});
|
|
6162
|
-
} catch (error) {
|
|
6163
|
-
if (ownerErrorCode(error) === "network_in_use") {
|
|
6164
|
-
throw error;
|
|
6165
|
-
}
|
|
6166
|
-
throw error;
|
|
6167
|
-
}
|
|
6168
|
-
return runtime3.result({
|
|
6169
|
-
data: { deleted: true, private_network: projected },
|
|
6170
|
-
outcome: { class: "ended", phase: "deleted" },
|
|
6171
|
-
presentation: {
|
|
6172
|
-
lines: [`Private network deleted: ${String(projected.name)} (${String(projected.id)})`]
|
|
6173
|
-
}
|
|
6174
|
-
});
|
|
6175
|
-
}
|
|
6176
|
-
function vpnPath(reservationId) {
|
|
6177
|
-
return `/v1/workflows/compute/nodes/reservations/${encodeURIComponent(reservationId)}/vpn/peers`;
|
|
6178
|
-
}
|
|
6179
|
-
function vpnPayloadRows(payload) {
|
|
6180
|
-
const source = record(payload);
|
|
6181
|
-
const peers = Array.isArray(source.peers) ? source.peers : [];
|
|
6182
|
-
return peers.flatMap((value) => {
|
|
6183
|
-
const parsed = unknownRecordSchema.safeParse(value);
|
|
6184
|
-
return parsed.success ? [parsed.data] : [];
|
|
6185
|
-
});
|
|
6186
|
-
}
|
|
6187
|
-
function vpnPeer(payload) {
|
|
6188
|
-
const peer = record(payload.peer);
|
|
6189
|
-
return Object.keys(peer).length ? peer : payload;
|
|
6190
|
-
}
|
|
6191
|
-
function projectVpnConnection(payload, reservationId) {
|
|
6192
|
-
const peer = vpnPeer(payload);
|
|
6193
|
-
const network = record(payload.network);
|
|
6194
|
-
return {
|
|
6195
|
-
id: text(peer.id),
|
|
6196
|
-
name: text(peer.label) ?? "VPN connection",
|
|
6197
|
-
reservation_id: reservationId,
|
|
6198
|
-
private_network_id: text(network.network_id) ?? text(network.id),
|
|
6199
|
-
assigned_address: text(peer.assigned_ip),
|
|
6200
|
-
lifecycle: lifecycle(peer.status),
|
|
6201
|
-
created_at: text(peer.created_at)
|
|
6202
|
-
};
|
|
6203
|
-
}
|
|
6204
|
-
function vpnLines(connection) {
|
|
6205
|
-
const state = record(connection.lifecycle);
|
|
6206
|
-
return [
|
|
6207
|
-
`${String(connection.name)} (${String(connection.id ?? "unknown")})`,
|
|
6208
|
-
` Private target: ${String(connection.reservation_id)}`,
|
|
6209
|
-
` State: ${state.class} (${state.phase})`
|
|
6210
|
-
];
|
|
6211
|
-
}
|
|
6212
|
-
async function listVpnPayloads(context, target) {
|
|
6213
|
-
return vpnPayloadRows(await context.fetch(vpnPath(target)));
|
|
6214
|
-
}
|
|
6215
|
-
async function listVpnConnections(context, input) {
|
|
6216
|
-
const runtime3 = interaction(context);
|
|
6217
|
-
const [rawTarget] = exactPositionals(runtime3, input.$positionals, 1, "Usage: ornn vpn-connections list <canonical-reservation-id> [--limit <1-500>] [--cursor <cursor>]");
|
|
6218
|
-
const target = requireCanonicalTarget(runtime3, rawTarget);
|
|
6219
|
-
const connections = (await listVpnPayloads(context, target)).map((payload) => projectVpnConnection(payload, target)).sort((left, right) => normalizedName(String(left.name)).localeCompare(normalizedName(String(right.name))));
|
|
6220
|
-
const selected = page(runtime3, "vpn-connections list", connections, input);
|
|
6221
|
-
return runtime3.result({
|
|
6222
|
-
data: { vpn_connections: selected.items },
|
|
6223
|
-
page: selected.page,
|
|
6224
|
-
presentation: {
|
|
6225
|
-
lines: selected.items.length ? selected.items.flatMap(vpnLines) : [`No VPN connections found for private target ${target}.`],
|
|
6226
|
-
...selected.page.next_cursor ? { next: `ornn vpn-connections list ${target} --cursor ${selected.page.next_cursor}` } : {}
|
|
6227
|
-
}
|
|
6228
|
-
});
|
|
6229
|
-
}
|
|
6230
|
-
function validateSecretExport(runtime3, input) {
|
|
6231
|
-
const hasOutput = Boolean(text(input.output));
|
|
6232
|
-
const shouldPrint = input.print === true;
|
|
6233
|
-
if (hasOutput === shouldPrint) {
|
|
6234
|
-
runtime3.usage("Choose exactly one explicit VPN configuration destination: --print or --output <path>.", {
|
|
6235
|
-
code: "secret_destination_required",
|
|
6236
|
-
field: "output"
|
|
6237
|
-
});
|
|
6238
|
-
}
|
|
6239
|
-
if (shouldPrint && runtime3.formatProvided) {
|
|
6240
|
-
runtime3.usage("--print is incompatible with an explicit --format.", {
|
|
6241
|
-
code: "secret_print_format_conflict",
|
|
6242
|
-
field: "format"
|
|
6243
|
-
});
|
|
6244
|
-
}
|
|
6245
|
-
if (runtime3.machine && shouldPrint) {
|
|
6246
|
-
runtime3.usage("Machine mode cannot mix secret bytes with a result envelope; use --output <path>.", {
|
|
6247
|
-
code: "secret_print_unsupported_in_machine_mode",
|
|
6248
|
-
field: "print"
|
|
6249
|
-
});
|
|
6250
|
-
}
|
|
6251
|
-
if (!runtime3.exportSecret || !runtime3.prepareSecretExport || !runtime3.wireGuardPublicKeyFromFile) {
|
|
6252
|
-
runtime3.error("The CLI secret-output service is unavailable.", {
|
|
6253
|
-
code: "secret_output_unavailable",
|
|
6254
|
-
exitCode: 6,
|
|
6255
|
-
retryable: true
|
|
6256
|
-
});
|
|
6257
|
-
}
|
|
6258
|
-
}
|
|
6259
|
-
async function prepareVpnExport(runtime3, input) {
|
|
6260
|
-
try {
|
|
6261
|
-
await runtime3.prepareSecretExport({
|
|
6262
|
-
outputPath: text(input.output) ?? void 0,
|
|
6263
|
-
overwrite: input.overwrite === true,
|
|
6264
|
-
print: input.print === true
|
|
6265
|
-
});
|
|
6266
|
-
} catch (error) {
|
|
6267
|
-
const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
|
|
6268
|
-
const message = error instanceof Error && error.message ? error.message : "Could not prepare the VPN configuration destination.";
|
|
6269
|
-
runtime3.error(message, { code: code ?? "vpn_configuration_export_failed" });
|
|
6270
|
-
}
|
|
6271
|
-
}
|
|
6272
|
-
async function exportVpnConfig(runtime3, input, content, privateKeyPath, publicKey) {
|
|
6273
|
-
const config = typeof content === "string" && content.length > 0 ? content : null;
|
|
6274
|
-
if (!config) {
|
|
6275
|
-
runtime3.error("Ornn did not return a usable VPN configuration.", {
|
|
6276
|
-
code: "vpn_configuration_unavailable",
|
|
6277
|
-
exitCode: 6,
|
|
6278
|
-
retryable: true
|
|
6279
|
-
});
|
|
6280
|
-
}
|
|
6281
|
-
try {
|
|
6282
|
-
return await runtime3.exportSecret({
|
|
6283
|
-
content: config,
|
|
6284
|
-
outputPath: text(input.output) ?? void 0,
|
|
6285
|
-
overwrite: input.overwrite === true,
|
|
6286
|
-
print: input.print === true,
|
|
6287
|
-
privateKeyPath,
|
|
6288
|
-
publicKey
|
|
6289
|
-
});
|
|
6290
|
-
} catch (error) {
|
|
6291
|
-
const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
|
|
6292
|
-
const message = error instanceof Error && error.message ? error.message : "Could not export the VPN configuration.";
|
|
6293
|
-
runtime3.error(message, { code: code ?? "vpn_configuration_export_failed" });
|
|
6294
|
-
}
|
|
6295
|
-
}
|
|
6296
|
-
function vpnConfigureExecution(runtime3, target, connection, exported, replayed) {
|
|
6297
|
-
const state = record(connection.lifecycle);
|
|
6298
|
-
const stateClass = String(state.class);
|
|
6299
|
-
const ready = stateClass === "ready";
|
|
6300
|
-
const failed = stateClass === "failed";
|
|
6301
|
-
const activationCommand = exported.path ? `sudo wg-quick up ${shellQuote(exported.path)}` : "sudo wg-quick up <saved-configuration-path>";
|
|
6302
|
-
const action = ready ? {
|
|
6303
|
-
command: activationCommand,
|
|
6304
|
-
description: "Activate the completed local WireGuard configuration before connecting.",
|
|
6305
|
-
type: "command"
|
|
6306
|
-
} : {
|
|
6307
|
-
command: `ornn vpn-connections configure ${target} --guided`,
|
|
6308
|
-
description: failed ? "Retry applying this exact VPN peer with its original private key." : "Reapply this pending VPN peer after gateway readiness is restored.",
|
|
6309
|
-
type: "command"
|
|
6310
|
-
};
|
|
6311
|
-
return runtime3.result({
|
|
6312
|
-
action,
|
|
6313
|
-
data: { export: exported, replayed, vpn_connection: connection },
|
|
6314
|
-
exitCode: ready ? 3 : failed ? 4 : 3,
|
|
6315
|
-
outcome: ready ? { class: "action_required", phase: "local_vpn_activation_required" } : { class: String(state.class), phase: String(state.phase) },
|
|
6316
|
-
presentation: {
|
|
6317
|
-
lines: [
|
|
6318
|
-
ready ? replayed ? "VPN configuration exported again; local tunnel activation is still required." : "VPN peer is active and the complete local configuration was exported." : failed ? "VPN connection was saved, but the gateway rejected or could not apply it." : "VPN connection was saved and is waiting for gateway application.",
|
|
6319
|
-
...vpnLines(connection),
|
|
6320
|
-
`Configuration fingerprint: ${exported.fingerprint}`,
|
|
6321
|
-
...exported.path ? [`Configuration written to ${exported.path} (${exported.mode}).`] : []
|
|
6322
|
-
],
|
|
6323
|
-
next: action.command
|
|
6324
|
-
},
|
|
6325
|
-
resume: ready ? { kind: "connect", ref: target } : { kind: "vpn_connection", ref: String(connection.id) }
|
|
6326
|
-
});
|
|
6327
|
-
}
|
|
6328
|
-
async function configureVpnConnection(context, input) {
|
|
6329
|
-
const runtime3 = interaction(context);
|
|
6330
|
-
const usage = "Usage: ornn vpn-connections configure <canonical-reservation-id> --name <name> --private-key <path> (--print | --output <path>)";
|
|
6331
|
-
const [rawTarget] = exactPositionals(runtime3, input.$positionals, 1, usage);
|
|
6332
|
-
const target = requireCanonicalTarget(runtime3, rawTarget);
|
|
6333
|
-
if (input.guided === true && !runtime3.machine) {
|
|
6334
|
-
input.name ??= await runtime3.ask({ label: "VPN connection name" });
|
|
6335
|
-
input.privateKey ??= await runtime3.ask({ label: "WireGuard private-key path" });
|
|
6336
|
-
if (input.print !== true && !text(input.output)) {
|
|
6337
|
-
input.output = await runtime3.ask({ label: "VPN configuration output path" });
|
|
6338
|
-
}
|
|
6339
|
-
}
|
|
6340
|
-
const name = requiredOption(runtime3, input.name, "--name", usage).normalize("NFKC").trim().replace(/\s+/g, " ");
|
|
6341
|
-
const privateKeyPath = requiredOption(runtime3, input.privateKey, "--private-key", usage);
|
|
6342
|
-
validateSecretExport(runtime3, input);
|
|
6343
|
-
await prepareVpnExport(runtime3, input);
|
|
6344
|
-
let publicKey = "";
|
|
6345
|
-
try {
|
|
6346
|
-
publicKey = await runtime3.wireGuardPublicKeyFromFile(privateKeyPath);
|
|
6347
|
-
} catch (error) {
|
|
6348
|
-
const code = error && typeof error === "object" && "code" in error ? text(error.code) : null;
|
|
6349
|
-
const message = error instanceof Error && error.message ? error.message : "Could not read the WireGuard private key.";
|
|
6350
|
-
runtime3.error(message, { code: code ?? "invalid_wireguard_private_key", field: "privateKey" });
|
|
6351
|
-
}
|
|
6352
|
-
const idempotencyKey = requireMutationKey(runtime3, input);
|
|
6353
|
-
const existing = await listVpnPayloads(context, target);
|
|
6354
|
-
const sameKey = existing.find((payload) => text(vpnPeer(payload).public_key) === publicKey);
|
|
6355
|
-
let effectiveName = name;
|
|
6356
|
-
if (sameKey) {
|
|
6357
|
-
const existingName = text(vpnPeer(sameKey).label) ?? "VPN connection";
|
|
6358
|
-
effectiveName = existingName;
|
|
6359
|
-
if (normalizedName(existingName) !== normalizedName(name)) {
|
|
6360
|
-
runtime3.usage("This public key already identifies a VPN connection with a different name. Use the original effective input or a new key after review.", { code: "vpn_connection_replay_conflict", field: "name" });
|
|
6361
|
-
}
|
|
6362
|
-
} else if (existing.some((payload) => normalizedName(text(vpnPeer(payload).label) ?? "VPN connection") === normalizedName(name))) {
|
|
6363
|
-
runtime3.usage(`A VPN connection named "${name}" already exists with different key material.`, {
|
|
6364
|
-
code: "vpn_connection_name_conflict",
|
|
6365
|
-
field: "name"
|
|
6366
|
-
});
|
|
6367
|
-
}
|
|
6368
|
-
if (sameKey && lifecycle(text(vpnPeer(sameKey).status)).class === "ready") {
|
|
6369
|
-
const exported2 = await exportVpnConfig(runtime3, input, sameKey.config, privateKeyPath, publicKey);
|
|
6370
|
-
return vpnConfigureExecution(runtime3, target, projectVpnConnection(sameKey, target), exported2, true);
|
|
6371
|
-
}
|
|
6372
|
-
if (!await runtime3.review({
|
|
6373
|
-
title: sameKey ? "Retry VPN connection" : "Configure VPN connection",
|
|
6374
|
-
terms: [
|
|
6375
|
-
{ label: "Private target", value: target },
|
|
6376
|
-
{ label: "VPN connection", value: name },
|
|
6377
|
-
{ label: "WireGuard public key", value: publicKey },
|
|
6378
|
-
{
|
|
6379
|
-
label: "Configuration destination",
|
|
6380
|
-
value: input.print ? "Terminal (explicit --print)" : String(input.output)
|
|
6381
|
-
}
|
|
6382
|
-
]
|
|
6383
|
-
}))
|
|
6384
|
-
return declined(runtime3);
|
|
6385
|
-
const applied = record(await context.fetch(vpnPath(target), {
|
|
6386
|
-
body: { label: effectiveName, public_key: publicKey },
|
|
6387
|
-
headers: mutationHeaders(idempotencyKey),
|
|
6388
|
-
method: "POST"
|
|
6389
|
-
}));
|
|
6390
|
-
const exported = await exportVpnConfig(runtime3, input, applied.config, privateKeyPath, publicKey);
|
|
6391
|
-
const connection = projectVpnConnection(applied, target);
|
|
6392
|
-
return vpnConfigureExecution(runtime3, target, connection, exported, Boolean(sameKey));
|
|
6393
|
-
}
|
|
6394
|
-
async function disconnectVpnConnection(context, input) {
|
|
6395
|
-
const runtime3 = interaction(context);
|
|
6396
|
-
const [rawTarget, reference] = exactPositionals(runtime3, input.$positionals, 2, "Usage: ornn vpn-connections disconnect <canonical-reservation-id> <exact-name-or-id>");
|
|
6397
|
-
const target = requireCanonicalTarget(runtime3, rawTarget);
|
|
6398
|
-
const idempotencyKey = requireMutationKey(runtime3, input);
|
|
6399
|
-
const matches = (await listVpnPayloads(context, target)).filter((payload) => {
|
|
6400
|
-
const peer = vpnPeer(payload);
|
|
6401
|
-
return CANONICAL_ID.test(reference) ? text(peer.id) === reference : normalizedName(text(peer.label) ?? "VPN connection") === normalizedName(reference);
|
|
6402
|
-
});
|
|
6403
|
-
if (matches.length === 0)
|
|
6404
|
-
runtime3.error(`VPN connection not found: ${reference}.`, { code: "vpn_connection_not_found" });
|
|
6405
|
-
if (matches.length > 1) {
|
|
6406
|
-
runtime3.usage(`More than one VPN connection has the exact name "${reference}"; use a canonical identifier.`, {
|
|
6407
|
-
code: "vpn_connection_ambiguous",
|
|
6408
|
-
field: "connection"
|
|
6409
|
-
});
|
|
6410
|
-
}
|
|
6411
|
-
const connection = projectVpnConnection(matches[0], target);
|
|
6412
|
-
if (!await runtime3.review({
|
|
6413
|
-
title: "Disconnect VPN connection",
|
|
6414
|
-
terms: [
|
|
6415
|
-
{ label: "Private target", value: target },
|
|
6416
|
-
{ label: "VPN connection", value: `${String(connection.name)} (${String(connection.id)})` },
|
|
6417
|
-
{
|
|
6418
|
-
label: "Consequence",
|
|
6419
|
-
value: "Private access through this VPN connection ends; the private network remains."
|
|
6420
|
-
}
|
|
6421
|
-
]
|
|
6422
|
-
}))
|
|
6423
|
-
return declined(runtime3);
|
|
6424
|
-
await context.fetch(`${vpnPath(target)}/${encodeURIComponent(String(connection.id))}`, {
|
|
6425
|
-
headers: mutationHeaders(idempotencyKey),
|
|
6426
|
-
method: "DELETE"
|
|
6427
|
-
});
|
|
6428
|
-
return runtime3.result({
|
|
6429
|
-
data: { disconnected: true, vpn_connection: connection },
|
|
6430
|
-
outcome: { class: "ended", phase: "disconnected" },
|
|
6431
|
-
presentation: {
|
|
6432
|
-
lines: [`VPN connection disconnected: ${String(connection.name)} (${String(connection.id)})`]
|
|
6433
|
-
}
|
|
6434
|
-
});
|
|
6435
|
-
}
|
|
6436
|
-
function normalizedConnectAccessMode(value) {
|
|
6437
|
-
const mode = text(value)?.toLowerCase();
|
|
6438
|
-
return mode === "virtual-machine" ? "vm" : mode ?? null;
|
|
6439
|
-
}
|
|
6440
|
-
function validateKnownConnectMode(runtime3, input, mode) {
|
|
6441
|
-
if (mode === "vm" || mode === "bare-metal" || mode === "slurm") {
|
|
6442
|
-
if (input.output || input.overwrite) {
|
|
6443
|
-
runtime3.usage(`${mode === "slurm" ? "Slurm" : mode === "vm" ? "VM" : "Bare Metal"} connect uses native SSH and does not write an output file.`, {
|
|
6444
|
-
code: mode === "slurm" ? "slurm_output_unsupported" : "direct_machine_output_unsupported",
|
|
6445
|
-
field: input.output ? "output" : "overwrite"
|
|
6446
|
-
});
|
|
6447
|
-
}
|
|
6448
|
-
return;
|
|
6449
|
-
}
|
|
6450
|
-
if (mode === "kubernetes" && (input.identityFile || input.user || input.print)) {
|
|
6451
|
-
runtime3.usage("Kubernetes connect writes a kubeconfig and does not accept SSH identity, user, or print options.", {
|
|
6452
|
-
code: input.print ? "kubeconfig_output_required" : "kubernetes_ssh_options_unsupported",
|
|
6453
|
-
field: input.identityFile ? "identityFile" : input.user ? "user" : "output"
|
|
6454
|
-
});
|
|
6455
|
-
}
|
|
6456
|
-
}
|
|
6457
|
-
function blockedPrivateTransport(runtime3, lifecycleValue, action, data, reservationId) {
|
|
6458
|
-
const state = record(lifecycleValue);
|
|
6459
|
-
const outcome = {
|
|
6460
|
-
class: text(state.class) ?? "pending",
|
|
6461
|
-
phase: text(state.phase) ?? "configuring"
|
|
6462
|
-
};
|
|
6463
|
-
return runtime3.result({
|
|
6464
|
-
action,
|
|
6465
|
-
data,
|
|
6466
|
-
exitCode: ["failed", "ended"].includes(outcome.class) ? 1 : 3,
|
|
6467
|
-
outcome,
|
|
6468
|
-
resume: { kind: "connect", ref: reservationId }
|
|
6469
|
-
});
|
|
6470
|
-
}
|
|
6471
|
-
function compareVpnConnections(left, right) {
|
|
6472
|
-
return (text(left.created_at) ?? "").localeCompare(text(right.created_at) ?? "") || (text(left.id) ?? "").localeCompare(text(right.id) ?? "") || normalizedName(text(left.name) ?? "").localeCompare(normalizedName(text(right.name) ?? ""));
|
|
6473
|
-
}
|
|
6474
|
-
async function connectPrivateTarget(context, input) {
|
|
6475
|
-
const runtime3 = interaction(context);
|
|
6476
|
-
const values = input.$positionals ?? [];
|
|
6477
|
-
if (values.length > 1) {
|
|
6478
|
-
runtime3.usage("Usage: ornn connect [<exact-hostname-or-canonical-machine-id>]", {
|
|
6479
|
-
code: "usage_error"
|
|
6480
|
-
});
|
|
6481
|
-
}
|
|
6482
|
-
const rawTarget = text(values[0]);
|
|
6483
|
-
let resolved = null;
|
|
6484
|
-
let target = rawTarget;
|
|
6485
|
-
if (runtime3.resolveConnectTarget) {
|
|
6486
|
-
resolved = await runtime3.resolveConnectTarget({
|
|
6487
|
-
context,
|
|
6488
|
-
input,
|
|
6489
|
-
interaction: runtime3,
|
|
6490
|
-
reference: rawTarget
|
|
6491
|
-
});
|
|
6492
|
-
if (resolved) {
|
|
6493
|
-
validateKnownConnectMode(runtime3, input, normalizedConnectAccessMode(resolved.mode));
|
|
6494
|
-
}
|
|
6495
|
-
if (resolved && resolved.privateTransportRequired !== true && runtime3.continueConnect) {
|
|
6496
|
-
const direct = await runtime3.continueConnect(resolved);
|
|
6497
|
-
if (direct)
|
|
6498
|
-
return runtime3.result(direct);
|
|
6499
|
-
}
|
|
6500
|
-
if (resolved)
|
|
6501
|
-
target = resolved.reservationId;
|
|
6502
|
-
}
|
|
6503
|
-
if (!resolved && rawTarget && CANONICAL_ID.test(rawTarget)) {
|
|
6504
|
-
try {
|
|
6505
|
-
const reservation = await getReservation(context.fetch, rawTarget);
|
|
6506
|
-
const reservationId = text(reservation.reservationId);
|
|
6507
|
-
if (reservationId && reservationId !== rawTarget) {
|
|
6508
|
-
runtime3.error("The gateway returned a different capacity reservation.", {
|
|
6509
|
-
code: "reservation_correlation_changed"
|
|
6510
|
-
});
|
|
6511
|
-
}
|
|
6512
|
-
const status = text(reservation.status)?.toLowerCase() ?? "unknown";
|
|
6513
|
-
const mode = normalizedConnectAccessMode(reservation.provisioningType);
|
|
6514
|
-
if (status !== "active") {
|
|
6515
|
-
const state = reservationTargetLifecycle(status);
|
|
6516
|
-
const waiting = state.class === "pending" || state.class === "working";
|
|
6517
|
-
return runtime3.result({
|
|
6518
|
-
action: waiting ? {
|
|
6519
|
-
command: `ornn reservations show ${reservationId ?? rawTarget}`,
|
|
6520
|
-
description: "Wait for the capacity reservation to become active before launching native compute.",
|
|
6521
|
-
type: "command"
|
|
6522
|
-
} : null,
|
|
6523
|
-
data: {
|
|
6524
|
-
capacity_reservation: {
|
|
6525
|
-
id: reservationId ?? rawTarget,
|
|
6526
|
-
access_mode: mode,
|
|
6527
|
-
lifecycle: state
|
|
6528
|
-
}
|
|
6529
|
-
},
|
|
6530
|
-
exitCode: waiting ? 3 : 1,
|
|
6531
|
-
outcome: state,
|
|
6532
|
-
presentation: {
|
|
6533
|
-
lines: [
|
|
6534
|
-
waiting ? `Capacity reservation ${reservationId ?? rawTarget} is not active yet; it has no native-access target.` : `Capacity reservation ${reservationId ?? rawTarget} is ${state.phase}; it has no launchable native-access target.`
|
|
6535
|
-
]
|
|
6536
|
-
},
|
|
6537
|
-
resume: waiting ? { kind: "reservation", ref: reservationId ?? rawTarget } : null
|
|
6538
|
-
});
|
|
6539
|
-
}
|
|
6540
|
-
validateKnownConnectMode(runtime3, input, mode);
|
|
6541
|
-
return runtime3.actionRequired({
|
|
6542
|
-
action: {
|
|
6543
|
-
command: "ornn launch",
|
|
6544
|
-
description: "Launch compute for this capacity reservation before requesting native access.",
|
|
6545
|
-
type: "command"
|
|
6546
|
-
},
|
|
6547
|
-
data: {
|
|
6548
|
-
capacity_reservation: {
|
|
6549
|
-
id: reservationId ?? rawTarget,
|
|
6550
|
-
access_mode: mode
|
|
6551
|
-
}
|
|
6552
|
-
},
|
|
6553
|
-
resume: { kind: "reservation", ref: reservationId ?? rawTarget }
|
|
6554
|
-
});
|
|
6555
|
-
} catch (error) {
|
|
6556
|
-
if (![400, 404, 422].includes(responseStatus(error) ?? 0))
|
|
6557
|
-
throw error;
|
|
6558
|
-
}
|
|
6559
|
-
}
|
|
6560
|
-
const privateTarget = target ?? "";
|
|
6561
|
-
if (!privateTarget || !CANONICAL_ID.test(privateTarget)) {
|
|
6562
|
-
runtime3.usage("Connect requires an exact unique hostname, canonical machine ID, or eligible guided choice.", {
|
|
6563
|
-
code: "invalid_reference",
|
|
6564
|
-
field: "machine"
|
|
6565
|
-
});
|
|
6566
|
-
}
|
|
6567
|
-
if (!resolved) {
|
|
6568
|
-
runtime3.error("No accessible machine, cluster, or capacity reservation matches this target.", {
|
|
6569
|
-
code: "connect_target_not_found"
|
|
6570
|
-
});
|
|
6571
|
-
}
|
|
6572
|
-
const shared = record(await context.fetch(`${NETWORKS_PATH}/shared?overlay=true`));
|
|
6573
|
-
const privateNetwork = projectNetwork({
|
|
6574
|
-
...record(shared.network),
|
|
6575
|
-
id: "shared",
|
|
6576
|
-
name: "Organization private network"
|
|
6577
|
-
});
|
|
6578
|
-
const networkState = record(privateNetwork.lifecycle);
|
|
6579
|
-
if (networkState.class !== "ready") {
|
|
6580
|
-
const recoverable = ["failed", "ended"].includes(String(networkState.class));
|
|
6581
|
-
return blockedPrivateTransport(runtime3, networkState, {
|
|
6582
|
-
command: `ornn vpn-connections list ${privateTarget}`,
|
|
6583
|
-
description: recoverable ? "Inspect organization VPN connectivity before retrying." : "Wait for organization networking to become ready, then retry connect.",
|
|
6584
|
-
type: "command"
|
|
6585
|
-
}, {
|
|
6586
|
-
private_network: privateNetwork,
|
|
6587
|
-
private_target: { reservation_id: privateTarget },
|
|
6588
|
-
vpn_connection: null
|
|
6589
|
-
}, privateTarget);
|
|
6590
|
-
}
|
|
6591
|
-
const connections = (await listVpnPayloads(context, privateTarget)).map((payload) => projectVpnConnection(payload, privateTarget)).sort(compareVpnConnections);
|
|
6592
|
-
if (connections.length === 0) {
|
|
6593
|
-
return runtime3.actionRequired({
|
|
6594
|
-
action: {
|
|
6595
|
-
command: `ornn vpn-connections configure ${privateTarget} --guided`,
|
|
6596
|
-
description: "Provide one VPN peer and explicit configuration destination, then retry connect.",
|
|
6597
|
-
type: "command"
|
|
6598
|
-
},
|
|
6599
|
-
data: {
|
|
6600
|
-
private_network: privateNetwork,
|
|
6601
|
-
private_target: { reservation_id: privateTarget },
|
|
6602
|
-
vpn_connection: null
|
|
6603
|
-
},
|
|
6604
|
-
resume: { kind: "connect", ref: privateTarget }
|
|
6605
|
-
});
|
|
6606
|
-
}
|
|
6607
|
-
const readyConnections = connections.filter((connection2) => record(connection2.lifecycle).class === "ready");
|
|
6608
|
-
if (readyConnections.length === 0) {
|
|
6609
|
-
const connection2 = connections.find((candidate) => ["pending", "working"].includes(String(record(candidate.lifecycle).class))) ?? connections.find((candidate) => record(candidate.lifecycle).class === "failed") ?? connections[0];
|
|
6610
|
-
const state = record(connection2.lifecycle);
|
|
6611
|
-
const stateClass = String(state.class);
|
|
6612
|
-
const id = text(connection2.id);
|
|
6613
|
-
const failed = stateClass === "failed";
|
|
6614
|
-
const ended = stateClass === "ended";
|
|
6615
|
-
const action = failed && id ? {
|
|
6616
|
-
command: `ornn vpn-connections disconnect ${privateTarget} ${id}`,
|
|
6617
|
-
description: "Remove the failed VPN connection before configuring a replacement.",
|
|
6618
|
-
type: "command"
|
|
6619
|
-
} : ended ? {
|
|
6620
|
-
command: `ornn vpn-connections configure ${privateTarget} --guided`,
|
|
6621
|
-
description: "Configure a new VPN connection, then retry connect.",
|
|
6622
|
-
type: "command"
|
|
6623
|
-
} : {
|
|
6624
|
-
command: `ornn vpn-connections configure ${privateTarget} --guided`,
|
|
6625
|
-
description: "Reapply the pending VPN connection, then retry connect.",
|
|
6626
|
-
type: "command"
|
|
6627
|
-
};
|
|
6628
|
-
return blockedPrivateTransport(runtime3, state, action, {
|
|
6629
|
-
private_network: privateNetwork,
|
|
6630
|
-
private_target: { reservation_id: privateTarget },
|
|
6631
|
-
vpn_connection: connection2
|
|
6632
|
-
}, privateTarget);
|
|
6633
|
-
}
|
|
6634
|
-
const connection = readyConnections.find((candidate) => {
|
|
6635
|
-
const address = text(candidate.assigned_address);
|
|
6636
|
-
return Boolean(address && runtime3.hasLocalNetworkAddress?.(address) === true);
|
|
6637
|
-
}) ?? readyConnections[0];
|
|
6638
|
-
const assignedAddress = text(connection.assigned_address);
|
|
6639
|
-
if (!assignedAddress || runtime3.hasLocalNetworkAddress?.(assignedAddress) !== true) {
|
|
6640
|
-
return runtime3.actionRequired({
|
|
6641
|
-
action: {
|
|
6642
|
-
command: `ornn vpn-connections configure ${privateTarget} --guided`,
|
|
6643
|
-
description: "Export a complete WireGuard configuration, activate it locally, then retry connect.",
|
|
6644
|
-
type: "command"
|
|
6645
|
-
},
|
|
6646
|
-
data: {
|
|
6647
|
-
private_network: privateNetwork,
|
|
6648
|
-
private_target: { reservation_id: privateTarget },
|
|
6649
|
-
vpn_connection: connection
|
|
6650
|
-
},
|
|
6651
|
-
resume: { kind: "connect", ref: privateTarget }
|
|
6652
|
-
});
|
|
6653
|
-
}
|
|
6654
|
-
if (runtime3.continueConnect) {
|
|
6655
|
-
const continuation = await runtime3.continueConnect({
|
|
6656
|
-
...resolved ?? {},
|
|
6657
|
-
privateNetwork,
|
|
6658
|
-
reservationId: privateTarget,
|
|
6659
|
-
vpnConnection: connection
|
|
6660
|
-
});
|
|
6661
|
-
if (continuation)
|
|
6662
|
-
return runtime3.result(continuation);
|
|
6663
|
-
}
|
|
6664
|
-
return runtime3.result({
|
|
6665
|
-
data: {
|
|
6666
|
-
private_network: privateNetwork,
|
|
6667
|
-
private_target: { reservation_id: privateTarget },
|
|
6668
|
-
vpn_connection: connection
|
|
6669
|
-
},
|
|
6670
|
-
outcome: { class: "ready", phase: "private_transport_ready" },
|
|
6671
|
-
presentation: {
|
|
6672
|
-
lines: ["VPN connection is ready for private access.", ...vpnLines(connection)]
|
|
6673
|
-
}
|
|
6674
|
-
});
|
|
5831
|
+
function networkExecutor(context) {
|
|
5832
|
+
const runtime3 = context.cli?.interaction;
|
|
5833
|
+
if (!runtime3?.networks)
|
|
5834
|
+
throw new Error("This capability must execute through the Ornn CLI network runtime.");
|
|
5835
|
+
return runtime3.networks.bind(runtime3);
|
|
6675
5836
|
}
|
|
6676
5837
|
function customerResource(specification) {
|
|
6677
5838
|
return defineCapability({ ...specification, mcp: false, slack: false });
|
|
@@ -6696,7 +5857,7 @@ var privateNetworkListCapability = customerResource({
|
|
|
6696
5857
|
related: ["private-networks show"]
|
|
6697
5858
|
}
|
|
6698
5859
|
},
|
|
6699
|
-
execute:
|
|
5860
|
+
execute: (ctx, input) => networkExecutor(ctx)("private-networks list", input, ctx)
|
|
6700
5861
|
});
|
|
6701
5862
|
var privateNetworkShowCapability = customerResource({
|
|
6702
5863
|
id: "networks.show",
|
|
@@ -6719,7 +5880,7 @@ var privateNetworkShowCapability = customerResource({
|
|
|
6719
5880
|
related: ["private-networks list"]
|
|
6720
5881
|
}
|
|
6721
5882
|
},
|
|
6722
|
-
execute:
|
|
5883
|
+
execute: (ctx, input) => networkExecutor(ctx)("private-networks show", input, ctx)
|
|
6723
5884
|
});
|
|
6724
5885
|
var privateNetworkCreateCapability = customerResource({
|
|
6725
5886
|
id: "networks.create",
|
|
@@ -6743,7 +5904,7 @@ var privateNetworkCreateCapability = customerResource({
|
|
|
6743
5904
|
related: ["private-networks list"]
|
|
6744
5905
|
}
|
|
6745
5906
|
},
|
|
6746
|
-
execute:
|
|
5907
|
+
execute: (ctx, input) => networkExecutor(ctx)("private-networks create", input, ctx)
|
|
6747
5908
|
});
|
|
6748
5909
|
var privateNetworkUpdateCapability = customerResource({
|
|
6749
5910
|
id: "networks.update",
|
|
@@ -6767,7 +5928,7 @@ var privateNetworkUpdateCapability = customerResource({
|
|
|
6767
5928
|
related: ["private-networks show"]
|
|
6768
5929
|
}
|
|
6769
5930
|
},
|
|
6770
|
-
execute:
|
|
5931
|
+
execute: (ctx, input) => networkExecutor(ctx)("private-networks update", input, ctx)
|
|
6771
5932
|
});
|
|
6772
5933
|
var privateNetworkDeleteCapability = customerResource({
|
|
6773
5934
|
id: "networks.delete",
|
|
@@ -6791,7 +5952,7 @@ var privateNetworkDeleteCapability = customerResource({
|
|
|
6791
5952
|
related: ["private-networks list"]
|
|
6792
5953
|
}
|
|
6793
5954
|
},
|
|
6794
|
-
execute:
|
|
5955
|
+
execute: (ctx, input) => networkExecutor(ctx)("private-networks delete", input, ctx)
|
|
6795
5956
|
});
|
|
6796
5957
|
var vpnConnectionListCapability = customerResource({
|
|
6797
5958
|
id: "vpn.connections.list",
|
|
@@ -6814,7 +5975,7 @@ var vpnConnectionListCapability = customerResource({
|
|
|
6814
5975
|
related: ["vpn-connections configure", "connect"]
|
|
6815
5976
|
}
|
|
6816
5977
|
},
|
|
6817
|
-
execute:
|
|
5978
|
+
execute: (ctx, input) => networkExecutor(ctx)("vpn-connections list", input, ctx)
|
|
6818
5979
|
});
|
|
6819
5980
|
var vpnConnectionConfigureCapability = customerResource({
|
|
6820
5981
|
id: "vpn.connections.configure",
|
|
@@ -6839,7 +6000,7 @@ var vpnConnectionConfigureCapability = customerResource({
|
|
|
6839
6000
|
related: ["connect", "vpn-connections disconnect"]
|
|
6840
6001
|
}
|
|
6841
6002
|
},
|
|
6842
|
-
execute:
|
|
6003
|
+
execute: (ctx, input) => networkExecutor(ctx)("vpn-connections configure", input, ctx)
|
|
6843
6004
|
});
|
|
6844
6005
|
var vpnConnectionDisconnectCapability = customerResource({
|
|
6845
6006
|
id: "vpn.connections.disconnect",
|
|
@@ -6867,7 +6028,7 @@ var vpnConnectionDisconnectCapability = customerResource({
|
|
|
6867
6028
|
related: ["vpn-connections configure"]
|
|
6868
6029
|
}
|
|
6869
6030
|
},
|
|
6870
|
-
execute:
|
|
6031
|
+
execute: (ctx, input) => networkExecutor(ctx)("vpn-connections disconnect", input, ctx)
|
|
6871
6032
|
});
|
|
6872
6033
|
var connectCapability = customerResource({
|
|
6873
6034
|
id: "vpn.connect",
|
|
@@ -6897,7 +6058,7 @@ var connectCapability = customerResource({
|
|
|
6897
6058
|
related: ["launch", "vpn-connections configure", "clusters show"]
|
|
6898
6059
|
}
|
|
6899
6060
|
},
|
|
6900
|
-
execute:
|
|
6061
|
+
execute: (ctx, input) => networkExecutor(ctx)("connect", input, ctx)
|
|
6901
6062
|
});
|
|
6902
6063
|
var networkCapabilities = [
|
|
6903
6064
|
privateNetworkListCapability,
|
|
@@ -6910,12 +6071,6 @@ var networkCapabilities = [
|
|
|
6910
6071
|
vpnConnectionDisconnectCapability,
|
|
6911
6072
|
connectCapability
|
|
6912
6073
|
];
|
|
6913
|
-
function networkPath(networkId) {
|
|
6914
|
-
return `${NETWORKS_PATH}/${encodeURIComponent(networkId)}`;
|
|
6915
|
-
}
|
|
6916
|
-
function vpnPeersPath(reservationId) {
|
|
6917
|
-
return `/v1/workflows/compute/nodes/reservations/${encodeURIComponent(reservationId)}/vpn/peers`;
|
|
6918
|
-
}
|
|
6919
6074
|
var networkUpdateFields = z27.object({
|
|
6920
6075
|
networkId: z27.string(),
|
|
6921
6076
|
name: z27.string().optional(),
|
|
@@ -6936,7 +6091,7 @@ var networkVerbCapabilities = [
|
|
|
6936
6091
|
input: z27.object({}),
|
|
6937
6092
|
mcp: { name: "networks_list" },
|
|
6938
6093
|
slack: false,
|
|
6939
|
-
execute: (ctx) => ctx.fetch
|
|
6094
|
+
execute: (ctx) => listNetworks(ctx.fetch)
|
|
6940
6095
|
}),
|
|
6941
6096
|
defineCapability({
|
|
6942
6097
|
id: "network.show",
|
|
@@ -6948,7 +6103,7 @@ var networkVerbCapabilities = [
|
|
|
6948
6103
|
input: z27.object({ networkId: z27.string() }),
|
|
6949
6104
|
mcp: { name: "networks_show" },
|
|
6950
6105
|
slack: false,
|
|
6951
|
-
execute: (ctx, input) => ctx.fetch
|
|
6106
|
+
execute: (ctx, input) => getNetwork(ctx.fetch, input.networkId)
|
|
6952
6107
|
}),
|
|
6953
6108
|
defineCapability({
|
|
6954
6109
|
id: "network.create",
|
|
@@ -6965,13 +6120,10 @@ var networkVerbCapabilities = [
|
|
|
6965
6120
|
}),
|
|
6966
6121
|
mcp: { name: "networks_create" },
|
|
6967
6122
|
slack: false,
|
|
6968
|
-
execute: (ctx, input) => ctx.fetch
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
cidr: input.cidr ?? null,
|
|
6973
|
-
description: input.description ?? null
|
|
6974
|
-
}
|
|
6123
|
+
execute: (ctx, input) => createNetwork(ctx.fetch, {
|
|
6124
|
+
name: input.name,
|
|
6125
|
+
cidr: input.cidr ?? null,
|
|
6126
|
+
description: input.description ?? null
|
|
6975
6127
|
})
|
|
6976
6128
|
}),
|
|
6977
6129
|
defineCapability({
|
|
@@ -6984,12 +6136,9 @@ var networkVerbCapabilities = [
|
|
|
6984
6136
|
input: networkUpdateFields,
|
|
6985
6137
|
mcp: { name: "networks_update" },
|
|
6986
6138
|
slack: false,
|
|
6987
|
-
execute: (ctx, input) => ctx.fetch
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
...input.name !== void 0 ? { name: input.name } : {},
|
|
6991
|
-
...input.clearDescription ? { description: null } : input.description !== void 0 ? { description: input.description } : {}
|
|
6992
|
-
}
|
|
6139
|
+
execute: (ctx, input) => updateNetwork(ctx.fetch, input.networkId, {
|
|
6140
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
6141
|
+
...input.clearDescription ? { description: null } : input.description !== void 0 ? { description: input.description } : {}
|
|
6993
6142
|
})
|
|
6994
6143
|
}),
|
|
6995
6144
|
defineCapability({
|
|
@@ -7004,7 +6153,7 @@ var networkVerbCapabilities = [
|
|
|
7004
6153
|
slack: false,
|
|
7005
6154
|
// The route answers 204, so report which network went.
|
|
7006
6155
|
execute: async (ctx, input) => {
|
|
7007
|
-
await ctx.fetch
|
|
6156
|
+
await deleteNetwork(ctx.fetch, input.networkId);
|
|
7008
6157
|
return { deleted: true, network_id: input.networkId };
|
|
7009
6158
|
}
|
|
7010
6159
|
}),
|
|
@@ -7016,12 +6165,12 @@ var networkVerbCapabilities = [
|
|
|
7016
6165
|
mutation: "read",
|
|
7017
6166
|
http: {
|
|
7018
6167
|
method: "GET",
|
|
7019
|
-
path: "/v1/
|
|
6168
|
+
path: "/v1/orchestrator/networks/shared/peers"
|
|
7020
6169
|
},
|
|
7021
6170
|
input: z27.object({ reservationId: z27.string() }),
|
|
7022
6171
|
mcp: { name: "vpn_peers_list" },
|
|
7023
6172
|
slack: false,
|
|
7024
|
-
execute: (ctx
|
|
6173
|
+
execute: (ctx) => listNetworkPeerConfigs(ctx.fetch, "shared")
|
|
7025
6174
|
}),
|
|
7026
6175
|
defineCapability({
|
|
7027
6176
|
id: "vpn.peers.create",
|
|
@@ -7031,7 +6180,7 @@ var networkVerbCapabilities = [
|
|
|
7031
6180
|
mutation: "preview-confirm",
|
|
7032
6181
|
http: {
|
|
7033
6182
|
method: "POST",
|
|
7034
|
-
path: "/v1/
|
|
6183
|
+
path: "/v1/orchestrator/networks/shared/peers"
|
|
7035
6184
|
},
|
|
7036
6185
|
input: z27.object({
|
|
7037
6186
|
reservationId: z27.string(),
|
|
@@ -7041,9 +6190,9 @@ var networkVerbCapabilities = [
|
|
|
7041
6190
|
}),
|
|
7042
6191
|
mcp: { name: "vpn_peers_create" },
|
|
7043
6192
|
slack: false,
|
|
7044
|
-
execute: (ctx, input) => ctx.fetch
|
|
7045
|
-
|
|
7046
|
-
|
|
6193
|
+
execute: (ctx, input) => createNetworkPeer(ctx.fetch, "shared", {
|
|
6194
|
+
public_key: input.publicKey,
|
|
6195
|
+
label: input.label ?? null
|
|
7047
6196
|
})
|
|
7048
6197
|
}),
|
|
7049
6198
|
defineCapability({
|
|
@@ -7054,7 +6203,7 @@ var networkVerbCapabilities = [
|
|
|
7054
6203
|
mutation: "preview-confirm",
|
|
7055
6204
|
http: {
|
|
7056
6205
|
method: "DELETE",
|
|
7057
|
-
path: "/v1/
|
|
6206
|
+
path: "/v1/orchestrator/networks/shared/peers/{peerId}"
|
|
7058
6207
|
},
|
|
7059
6208
|
input: z27.object({
|
|
7060
6209
|
reservationId: z27.string(),
|
|
@@ -7063,9 +6212,7 @@ var networkVerbCapabilities = [
|
|
|
7063
6212
|
}),
|
|
7064
6213
|
mcp: { name: "vpn_peers_delete" },
|
|
7065
6214
|
slack: false,
|
|
7066
|
-
execute: async (ctx, input) => await ctx.fetch
|
|
7067
|
-
method: "DELETE"
|
|
7068
|
-
}) ?? { deleted: true }
|
|
6215
|
+
execute: async (ctx, input) => await deleteNetworkPeer(ctx.fetch, "shared", input.peerId) ?? { deleted: true }
|
|
7069
6216
|
})
|
|
7070
6217
|
];
|
|
7071
6218
|
|
|
@@ -7108,12 +6255,12 @@ function formatBytes(bytes) {
|
|
|
7108
6255
|
}
|
|
7109
6256
|
return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;
|
|
7110
6257
|
}
|
|
7111
|
-
function repositoryArgument(input,
|
|
6258
|
+
function repositoryArgument(input, interaction) {
|
|
7112
6259
|
const raw = input.repository ?? input.$positionals[0];
|
|
7113
6260
|
if (!raw) {
|
|
7114
6261
|
const message = "Name a repository, such as trainer.";
|
|
7115
|
-
if (
|
|
7116
|
-
|
|
6262
|
+
if (interaction)
|
|
6263
|
+
interaction.usage(message, { code: "repository_required", field: "repository" });
|
|
7117
6264
|
throw new Error(message);
|
|
7118
6265
|
}
|
|
7119
6266
|
const reference = raw.trim();
|
|
@@ -7147,10 +6294,10 @@ var registryShowCapability = defineCapability({
|
|
|
7147
6294
|
slack: false,
|
|
7148
6295
|
execute: async (context) => {
|
|
7149
6296
|
const registry = await getContainerRegistry(context.fetch);
|
|
7150
|
-
const
|
|
7151
|
-
if (!
|
|
6297
|
+
const interaction = cliInteraction(context);
|
|
6298
|
+
if (!interaction)
|
|
7152
6299
|
return registry;
|
|
7153
|
-
return
|
|
6300
|
+
return interaction.result({
|
|
7154
6301
|
data: registry,
|
|
7155
6302
|
presentation: {
|
|
7156
6303
|
lines: [`Image prefix: ${registry.host}/${registry.namespace}`],
|
|
@@ -7182,11 +6329,11 @@ var registryRepositoriesListCapability = defineCapability({
|
|
|
7182
6329
|
slack: false,
|
|
7183
6330
|
execute: async (context) => {
|
|
7184
6331
|
const listed = await listRegistryRepositories(context.fetch);
|
|
7185
|
-
const
|
|
7186
|
-
if (!
|
|
6332
|
+
const interaction = cliInteraction(context);
|
|
6333
|
+
if (!interaction)
|
|
7187
6334
|
return listed;
|
|
7188
6335
|
const registry = await getContainerRegistry(context.fetch);
|
|
7189
|
-
return
|
|
6336
|
+
return interaction.result({
|
|
7190
6337
|
data: listed,
|
|
7191
6338
|
presentation: {
|
|
7192
6339
|
lines: listed.repositories.length ? listed.repositories.map((repository) => `${shortName(repository.name, registry)} ${repository.tag_count} ${repository.tag_count === 1 ? "tag" : "tags"}`) : ["No images yet. Push one with docker push after ornn registry login."]
|
|
@@ -7218,13 +6365,13 @@ var registryTagsListCapability = defineCapability({
|
|
|
7218
6365
|
},
|
|
7219
6366
|
slack: false,
|
|
7220
6367
|
execute: async (context, input) => {
|
|
7221
|
-
const
|
|
6368
|
+
const interaction = cliInteraction(context);
|
|
7222
6369
|
const registry = await getContainerRegistry(context.fetch);
|
|
7223
|
-
const repository = qualifiedRepository(repositoryArgument(input,
|
|
6370
|
+
const repository = qualifiedRepository(repositoryArgument(input, interaction).repository, registry);
|
|
7224
6371
|
const listed = await listRegistryTags(context.fetch, repository);
|
|
7225
|
-
if (!
|
|
6372
|
+
if (!interaction)
|
|
7226
6373
|
return listed;
|
|
7227
|
-
return
|
|
6374
|
+
return interaction.result({
|
|
7228
6375
|
data: listed,
|
|
7229
6376
|
presentation: {
|
|
7230
6377
|
lines: listed.tags.map((tag) => `${tag.tag} ${tag.digest.slice(0, 19)} ${formatBytes(tag.size_bytes)}${tag.created_at ? ` built ${tag.created_at}` : ""}`)
|
|
@@ -7257,20 +6404,20 @@ var registryTagsDeleteCapability = defineCapability({
|
|
|
7257
6404
|
},
|
|
7258
6405
|
slack: false,
|
|
7259
6406
|
execute: async (context, input) => {
|
|
7260
|
-
const
|
|
6407
|
+
const interaction = cliInteraction(context);
|
|
7261
6408
|
const registry = await getContainerRegistry(context.fetch);
|
|
7262
|
-
const argument = repositoryArgument(input,
|
|
6409
|
+
const argument = repositoryArgument(input, interaction);
|
|
7263
6410
|
const repository = qualifiedRepository(argument.repository, registry);
|
|
7264
6411
|
if (!argument.tag) {
|
|
7265
6412
|
const message = "Name the tag to delete, such as trainer:v1.";
|
|
7266
|
-
if (
|
|
7267
|
-
|
|
6413
|
+
if (interaction)
|
|
6414
|
+
interaction.usage(message, { code: "tag_required", field: "tag" });
|
|
7268
6415
|
throw new Error(message);
|
|
7269
6416
|
}
|
|
7270
6417
|
const target = { repository, tag: argument.tag };
|
|
7271
|
-
if (
|
|
6418
|
+
if (interaction) {
|
|
7272
6419
|
if (!input.yes) {
|
|
7273
|
-
const approved = await
|
|
6420
|
+
const approved = await interaction.review({
|
|
7274
6421
|
title: "Delete this image tag?",
|
|
7275
6422
|
terms: [
|
|
7276
6423
|
{ label: "Image", value: `${registry.host}/${repository}:${argument.tag}` },
|
|
@@ -7282,7 +6429,7 @@ var registryTagsDeleteCapability = defineCapability({
|
|
|
7282
6429
|
prompt: "Delete it?"
|
|
7283
6430
|
});
|
|
7284
6431
|
if (!approved) {
|
|
7285
|
-
return
|
|
6432
|
+
return interaction.result({
|
|
7286
6433
|
data: target,
|
|
7287
6434
|
outcome: { class: "cancelled", phase: "review" },
|
|
7288
6435
|
presentation: { lines: ["Nothing was deleted."] }
|
|
@@ -7294,9 +6441,9 @@ var registryTagsDeleteCapability = defineCapability({
|
|
|
7294
6441
|
}
|
|
7295
6442
|
await deleteRegistryTag(context.fetch, target.repository, target.tag);
|
|
7296
6443
|
const deleted = { deleted: true, ...target };
|
|
7297
|
-
if (!
|
|
6444
|
+
if (!interaction)
|
|
7298
6445
|
return deleted;
|
|
7299
|
-
return
|
|
6446
|
+
return interaction.result({
|
|
7300
6447
|
data: deleted,
|
|
7301
6448
|
presentation: { lines: [`Deleted ${shortName(repository, registry)}:${argument.tag}.`] }
|
|
7302
6449
|
});
|
|
@@ -7325,10 +6472,10 @@ var registryUsageCapability = defineCapability({
|
|
|
7325
6472
|
slack: false,
|
|
7326
6473
|
execute: async (context) => {
|
|
7327
6474
|
const usage = await getRegistryUsage(context.fetch);
|
|
7328
|
-
const
|
|
7329
|
-
if (!
|
|
6475
|
+
const interaction = cliInteraction(context);
|
|
6476
|
+
if (!interaction)
|
|
7330
6477
|
return usage;
|
|
7331
|
-
return
|
|
6478
|
+
return interaction.result({
|
|
7332
6479
|
data: usage,
|
|
7333
6480
|
presentation: { lines: [`Storage used: ${formatBytes(usage.bytes)}`] }
|
|
7334
6481
|
});
|
|
@@ -7379,11 +6526,11 @@ var registryLoginCapability = defineCapability({
|
|
|
7379
6526
|
mcp: false,
|
|
7380
6527
|
slack: false,
|
|
7381
6528
|
execute: async (context, input) => {
|
|
7382
|
-
const
|
|
7383
|
-
if (!
|
|
6529
|
+
const interaction = context.cli?.interaction;
|
|
6530
|
+
if (!interaction?.registry) {
|
|
7384
6531
|
throw new Error("ornn registry login runs only in the Ornn CLI.");
|
|
7385
6532
|
}
|
|
7386
|
-
return
|
|
6533
|
+
return interaction.registry.call(interaction, "registry.login", input);
|
|
7387
6534
|
}
|
|
7388
6535
|
});
|
|
7389
6536
|
var registryCapabilities = [
|
|
@@ -7472,11 +6619,11 @@ var storageCliInput = z30.object({
|
|
|
7472
6619
|
yes: z30.boolean().optional()
|
|
7473
6620
|
}).strict();
|
|
7474
6621
|
function storageExecutor(context) {
|
|
7475
|
-
const
|
|
7476
|
-
if (!
|
|
6622
|
+
const interaction = context.cli?.interaction;
|
|
6623
|
+
if (!interaction?.storage) {
|
|
7477
6624
|
throw new Error("This capability must execute through the Ornn CLI storage runtime.");
|
|
7478
6625
|
}
|
|
7479
|
-
return
|
|
6626
|
+
return interaction.storage.bind(interaction);
|
|
7480
6627
|
}
|
|
7481
6628
|
function storageCapability({ id, command, description, mutation, outcome, human, automation, acceptedReferences = [], review, related = [] }) {
|
|
7482
6629
|
return defineCapability({
|