@ornncompute/cli 0.2.6 → 0.2.7

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 CHANGED
@@ -72,7 +72,7 @@ ornn nodes keys attach <node-id> --key <path|id|label> [--json]
72
72
  ornn nodes keys list <node-id> [--json]
73
73
  ornn node health <node-id> [--json]
74
74
  ornn node diagnose <node-id> [--json]
75
- ornn node list [--operator <id-or-slug>] [--facility <id>] [--json]
75
+ ornn node list [--operator <id-or-slug>] [--facility <id>] [--email <email>] [--json]
76
76
  ornn node reboot <node-id> [--json]
77
77
  ornn node hard-reset <node-id> [--json]
78
78
  ornn node off-grid <node-id> [--reason <text>] [--yes] [--json]
@@ -138,6 +138,14 @@ ornn storage buckets connect gcs|s3|r2 --bucket <bucket>|--url <url> [--name <na
138
138
  ornn storage buckets update-credentials <drive-id> --access-key-id <id> --secret-access-key-file <path> [--json]
139
139
  ornn storage buckets verify <drive-id> [--json]
140
140
  ornn storage buckets disconnect <drive-id> [--json]
141
+ ornn storage filesystem deploy --reservation <reservation-id> [--performance-tier <tier>] [--capacity-gib <gib>] [--json]
142
+ ornn storage filesystem status --reservation <reservation-id> [--json]
143
+ ornn storage filesystem delete --reservation <reservation-id> [--json]
144
+ ornn telemetry latest <node-id> [--span 15m] [--start <iso>] [--end <iso>] [--max-points <n>] [--json]
145
+ ornn telemetry tail <node-id> [--duration <seconds>] [--json]
146
+ ornn logs latest <node-id> [--stream kernel] [--count <n>] [--before <iso>] [--cursor <token>] [--json]
147
+ ornn logs tail <node-id> [--stream kernel] [--duration <seconds>] [--json]
148
+ ornn users query [--name <name>] [--email <email>] [--organization <name>] [--max <n>]
141
149
  ornn keys list [--json]
142
150
  ornn keys add [<public-key-file>] --label <label> [--public-key <key>] [--json]
143
151
  ornn keys delete <key-id> [--json]
@@ -236,14 +244,15 @@ path.
236
244
  - `ornn node health <node-id>` shows launch readiness (ready/blocked plus
237
245
  reasons), passive fault reasons, and the last validation status.
238
246
  - `ornn node diagnose <node-id>` queues a manual node validation test.
239
- - `ornn node list [--operator <id-or-slug>] [--facility <id>]` lists GPU nodes,
240
- optionally filtered by operator and/or facility. A UUID operator is matched by
241
- id; anything else is treated as the operator slug.
242
- - `ornn node reboot <node-id>` queues an OS reboot of the host backing the node
243
- (storage and SSH keys preserved).
247
+ - `ornn node list [--operator <id-or-slug>] [--facility <id>] [--email <email>]` lists GPU nodes.
248
+ Orchestrator applies facility id and an operator UUID. Non-UUID `--operator`
249
+ slugs and `--email` are forwarded today and do not filter the fleet.
250
+ - `ornn node reboot <node-id>` queues an OS reboot of the node's resolved
251
+ instance (its host for bare-metal, its VM for a virtual-machine instance id;
252
+ storage and SSH keys preserved).
244
253
  - `ornn node hard-reset <node-id>` wipes tenant storage/users and reboots, then
245
254
  re-pushes the tenant's keys on reconnect. The tenant keeps ownership of the
246
- host.
255
+ instance.
247
256
  - `ornn node off-grid <node-id> [--reason <text>] [--yes]` takes a node off-grid
248
257
  (remove Ornn agent management, leave the host powered on). Asks y/N unless `--yes`.
249
258
  - `ornn node on-grid <node-id> [--yes]` re-enrolls an off-grid host: orchestrator
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ornncompute/cli",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Command-line interface for Ornn compute access workflows.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
2
+ import { defineCapability, preview } from "../capability.js";
3
3
  const reservationInput = z.object({
4
4
  reservation_id: z.string().min(1),
5
5
  reservationId: z.string().optional(),
@@ -51,7 +51,7 @@ function clusterPair(kind, domain) {
51
51
  return { ok: false, error: "other_cluster", reason: "other_cluster" };
52
52
  }
53
53
  if (!ctx.confirmed) {
54
- return { ok: true, action: `${kind}.launch`, reservation_id: id };
54
+ return preview(`${kind}.launch`, { reservation_id: id });
55
55
  }
56
56
  return ctx.fetch(clusterPath(kind, id, "cluster/launch"), {
57
57
  method: "POST",
@@ -75,7 +75,7 @@ function clusterPair(kind, domain) {
75
75
  const parsed = reservationInput.parse(input);
76
76
  const id = reservationId(parsed);
77
77
  if (!ctx.confirmed) {
78
- return { ok: true, action: `${kind}.teardown`, reservation_id: id };
78
+ return preview(`${kind}.teardown`, { reservation_id: id });
79
79
  }
80
80
  return ctx.fetch(clusterPath(kind, id, "cluster/teardown"), { method: "POST" });
81
81
  },
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
2
+ import { defineCapability, preview } from "../capability.js";
3
3
  function queryPath(path, params) {
4
4
  const parts = [];
5
5
  for (const [key, value] of Object.entries(params)) {
@@ -138,7 +138,7 @@ export const nodeOffGridCapability = defineCapability({
138
138
  const id = nodeIdOf(parsed);
139
139
  const body = { ...(parsed.reason ? { reason: parsed.reason } : {}) };
140
140
  if (!ctx.confirmed) {
141
- return { ok: true, action: "node.off-grid", payload: { node_id: id, ...body } };
141
+ return preview("node.off-grid", { node_id: id, ...body });
142
142
  }
143
143
  return ctx.fetch(`/internal/nodes/${encodeURIComponent(id)}/off-grid`, {
144
144
  method: "POST",
@@ -167,7 +167,7 @@ export const nodeOnGridCapability = defineCapability({
167
167
  const parsed = nodeLifecycleInput.parse(input);
168
168
  const id = nodeIdOf(parsed);
169
169
  if (!ctx.confirmed) {
170
- return { ok: true, action: "node.on-grid", payload: { node_id: id } };
170
+ return preview("node.on-grid", { node_id: id });
171
171
  }
172
172
  return ctx.fetch(`/internal/nodes/${encodeURIComponent(id)}/on-grid`, {
173
173
  method: "POST",
@@ -234,7 +234,7 @@ export const nodeTerminateCapability = defineCapability({
234
234
  ...(parsed.force !== undefined ? { force: parsed.force } : {}),
235
235
  };
236
236
  if (!ctx.confirmed) {
237
- return { ok: true, action: "node.terminate", payload: { node_id: id, ...body } };
237
+ return preview("node.terminate", { node_id: id, ...body });
238
238
  }
239
239
  return ctx.fetch(`/internal/nodes/${encodeURIComponent(id)}/terminate`, {
240
240
  method: "POST",
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
2
+ import { defineCapability, preview } from "../capability.js";
3
3
  import { bindHardwareFields, HARDWARE_LISTING_FIELDS, HARDWARE_LISTING_FILTERS, loadHardwareCatalog, projectCatalogTerms, } from "../spec-catalog.js";
4
4
  export const listingCreateInput = z.object({
5
5
  kind: z.enum(["gpu", "cpu", "node", "link"]).optional(),
@@ -147,7 +147,7 @@ export const createListingCapability = defineCapability({
147
147
  return bound;
148
148
  const payload = { backing_mode: "forward", ...bound.payload };
149
149
  if (!ctx.confirmed) {
150
- return { ok: true, action: "create_listing", payload };
150
+ return preview("create_listing", payload);
151
151
  }
152
152
  return ctx.fetch("/inventory", { method: "POST", body: payload });
153
153
  },
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { defineCapability } from "../capability.js";
2
+ import { defineCapability, preview } from "../capability.js";
3
3
  const optionalText = z.string().nullish();
4
4
  const tokenCreateInput = z.object({
5
5
  operator_id: z.string().min(1),
@@ -107,7 +107,7 @@ export const tokensCreateCapability = defineCapability({
107
107
  remote: hosts.length > 0 && privateKey.length > 0,
108
108
  };
109
109
  if (!ctx.confirmed) {
110
- return { ok: true, action: "tokens.create", payload: { ...payload, private_key: privateKey ? "[redacted]" : "" } };
110
+ return preview("tokens.create", { ...payload, private_key: privateKey ? "[redacted]" : "" });
111
111
  }
112
112
  const minted = (await ctx.fetch("/internal/enrollment-tokens", {
113
113
  method: "POST",
@@ -19,6 +19,24 @@ export type CapabilityContext = {
19
19
  /** Human (or MCP) confirmed a preview-confirm mutation. Execute never POSTs without this. */
20
20
  confirmed?: boolean;
21
21
  };
22
+ /** The un-executed result of a `preview-confirm` capability. */
23
+ export type PreviewResult = {
24
+ status: "preview";
25
+ requiresConfirm: true;
26
+ confirmed: false;
27
+ action: string;
28
+ payload: unknown;
29
+ };
30
+ /**
31
+ * Build a preview-confirm capability's un-executed result.
32
+ *
33
+ * Previews used to return `{ ok: true, action, payload }`, which is
34
+ * indistinguishable from a completed mutation to anyone skimming the JSON --
35
+ * a human, or an LLM deciding whether its call took effect. ORN-3417 recorded
36
+ * a live `node.off-grid` preview as a confirm-gate failure for exactly that
37
+ * reason. `status: "preview"` states it outright, and carries no `ok`.
38
+ */
39
+ export declare function preview(action: string, payload: unknown): PreviewResult;
22
40
  export type JsonSchema = {
23
41
  type: "object";
24
42
  properties?: Record<string, unknown>;
@@ -16,6 +16,18 @@ export const DOMAINS = [
16
16
  "billing",
17
17
  "observability",
18
18
  ];
19
+ /**
20
+ * Build a preview-confirm capability's un-executed result.
21
+ *
22
+ * Previews used to return `{ ok: true, action, payload }`, which is
23
+ * indistinguishable from a completed mutation to anyone skimming the JSON --
24
+ * a human, or an LLM deciding whether its call took effect. ORN-3417 recorded
25
+ * a live `node.off-grid` preview as a confirm-gate failure for exactly that
26
+ * reason. `status: "preview"` states it outright, and carries no `ok`.
27
+ */
28
+ export function preview(action, payload) {
29
+ return { status: "preview", requiresConfirm: true, confirmed: false, action, payload };
30
+ }
19
31
  /** Fill CLI/MCP/Slack names from `id`. Slack parameters stay optional. */
20
32
  export function defineCapability(spec) {
21
33
  const names = namesFromId(spec.id);
@@ -1,4 +1,4 @@
1
- export { byCliCommand, byMcpName, bySlackName, defineCapability, forRole, slackStaffVisible, visibleToClient, type Capability, type CapabilityBindings, type CapabilityContext, type CapabilitySpec, type JsonSchema, type CapabilityTransport, type Domain, type HttpSpec, type Mutation, } from "./capability.ts";
1
+ export { byCliCommand, byMcpName, bySlackName, defineCapability, forRole, preview, slackStaffVisible, visibleToClient, type Capability, type CapabilityBindings, type CapabilityContext, type CapabilitySpec, type JsonSchema, type CapabilityTransport, type Domain, type HttpSpec, type Mutation, type PreviewResult, } from "./capability.ts";
2
2
  export { namesFromId } from "./names.ts";
3
3
  export { catalog } from "./catalog.ts";
4
4
  export { fleetCapabilities, listFacilitiesCapability, listNodesCapability, listOperatorsCapability, nodeExecCapability, nodeOffGridCapability, nodeOnGridCapability, nodeTerminateCapability, } from "./capabilities/fleet.ts";
@@ -1,4 +1,4 @@
1
- export { byCliCommand, byMcpName, bySlackName, defineCapability, forRole, slackStaffVisible, visibleToClient, } from "./capability.js";
1
+ export { byCliCommand, byMcpName, bySlackName, defineCapability, forRole, preview, slackStaffVisible, visibleToClient, } from "./capability.js";
2
2
  export { namesFromId } from "./names.js";
3
3
  export { catalog } from "./catalog.js";
4
4
  export { fleetCapabilities, listFacilitiesCapability, listNodesCapability, listOperatorsCapability, nodeExecCapability, nodeOffGridCapability, nodeOnGridCapability, nodeTerminateCapability, } from "./capabilities/fleet.js";