@vavio/cli 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/vavio.mjs +64 -22
  2. package/package.json +1 -1
package/dist/vavio.mjs CHANGED
@@ -10,7 +10,7 @@ import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/cli
10
10
 
11
11
  // src/constants.ts
12
12
  var CLI_NAME = "@vavio/cli";
13
- var CLI_VERSION = "0.1.0";
13
+ var CLI_VERSION = "0.1.2";
14
14
  var CONTRACT_VERSION = 1;
15
15
  var CONTRACT_HEADER = "Vavio-Contract";
16
16
  var CONTRACT_MIN_HEADER = "Vavio-Contract-Min";
@@ -606,10 +606,14 @@ var COMMANDS = {
606
606
  summary: "Remove this computer's sign-in and revoke it on Vavio.",
607
607
  details: ["Exit code 3 means the local sign-in is removed but Vavio could not revoke it from here: next.text says what to do."]
608
608
  },
609
- whoami: { usage: "vavio whoami", summary: "Show the signed-in workspace. Same result as vavio account." },
609
+ status: {
610
+ usage: "vavio status",
611
+ summary: "Show your account: workspace, Hermes instances and their state, and open operations. Plain vavio does the same once signed in."
612
+ },
613
+ whoami: { usage: "vavio whoami", summary: "Show the signed-in workspace." },
610
614
  account: {
611
615
  usage: "vavio account",
612
- summary: "Read the account: workspace, Hermes instances, offerings, included Hermes and open operations."
616
+ summary: "Read the account: workspace, Hermes instances, offerings, included Hermes and open operations. Same as vavio status."
613
617
  },
614
618
  "instances list": { usage: "vavio instances list", summary: "List the workspace's Hermes instances with their ids and access state." },
615
619
  "instance status": {
@@ -651,6 +655,8 @@ function mainHelp() {
651
655
  "",
652
656
  "Usage: vavio <command> [options]",
653
657
  "",
658
+ "Start: vavio login, then vavio status.",
659
+ "",
654
660
  "Commands:",
655
661
  ...lines,
656
662
  "",
@@ -722,21 +728,37 @@ function table(rows) {
722
728
  return rows.map((row) => row.map((cell, i) => i === row.length - 1 ? cell : cell.padEnd(widths[i])).join(" ")).join("\n");
723
729
  }
724
730
  var str = (value) => value === null || value === void 0 ? "-" : String(value);
731
+ function priceText(price) {
732
+ if (!price) return null;
733
+ const amount = typeof price.amount === "number" ? price.amount.toFixed(2) : str(price.amount);
734
+ const currency = str(price.currency).toUpperCase();
735
+ return `${currency === "USD" ? `$${amount}` : `${amount} ${currency}`}/${str(price.interval)}`;
736
+ }
737
+ function orderText(o) {
738
+ return o.purchasable ? "available to order" : `not available to order yet${o.reason ? `: ${str(o.reason)}` : ""}`;
739
+ }
740
+ var indent = (text) => text.split("\n").map((line) => ` ${line}`).join("\n");
741
+ function accountText(v) {
742
+ const ws = v.workspace ?? {};
743
+ const instances = v.instances ?? [];
744
+ const offerings = v.offerings ?? [];
745
+ const ent = v.entitlements?.hermes ?? {};
746
+ const lines = [`Workspace ${ws.name ? `${str(ws.name)} (${str(ws.id)})` : str(ws.id)}`, `Role ${str(v.role)}`];
747
+ if (instances.length) {
748
+ lines.push(`Hermes ${instances.length === 1 ? "1 instance" : `${instances.length} instances`} (included ${str(ent.used)} of ${str(ent.granted)})`);
749
+ lines.push(indent(table([["ID", "ACCESS", "STATE", "ADDRESS"], ...instances.map((i) => [str(i.id), str(i.access), str(i.lifecycle_state), str(i.address)])])));
750
+ } else {
751
+ lines.push("Hermes none yet");
752
+ for (const o of offerings) {
753
+ const price = priceText(o.price);
754
+ lines.push(`Hosting ${str(o.title)}${price ? `, ${price}` : ""}: ${orderText(o)}`);
755
+ }
756
+ }
757
+ lines.push(`Open operations ${str(v.open_operations)}`);
758
+ return lines.join("\n");
759
+ }
725
760
  var FORMAT = {
726
- account(v) {
727
- const ws = v.workspace ?? {};
728
- const instances = v.instances ?? [];
729
- const offerings = v.offerings ?? [];
730
- const ent = v.entitlements?.hermes ?? {};
731
- return [
732
- `Workspace ${str(ws.name)} (${str(ws.id)})`,
733
- `Role ${str(v.role)}`,
734
- `Hermes ${instances.length} instance(s); included ${str(ent.used)} of ${str(ent.granted)}`,
735
- ...instances.map((i) => ` ${str(i.id)} ${str(i.access)} ${str(i.address)}`),
736
- `Offerings ${offerings.map((o) => `${str(o.title)}: ${o.purchasable ? "for sale" : "not for sale yet"}`).join("; ") || "none"}`,
737
- `Open operations ${str(v.open_operations)}`
738
- ].join("\n");
739
- },
761
+ account: accountText,
740
762
  whoami(v) {
741
763
  const ws = v.workspace ?? {};
742
764
  return `Signed in as the ${str(v.role)} of workspace ${str(ws.name)} (${str(ws.id)}).`;
@@ -768,7 +790,7 @@ Older: vavio operations list --before ${str(v.next_before)}` : "";
768
790
  offerings(v) {
769
791
  const rows = (v.offerings ?? []).map((o) => {
770
792
  const price = o.price;
771
- return [str(o.id), str(o.title), price ? `${str(price.amount)} ${str(price.currency)}/${str(price.interval)}` : "no price set", o.purchasable ? "for sale" : `not for sale${o.reason ? `: ${str(o.reason)}` : ""}`];
793
+ return [str(o.id), str(o.title), priceText(price) ?? "no price set", orderText(o)];
772
794
  });
773
795
  return rows.length ? table([["ID", "TITLE", "PRICE", "STATUS"], ...rows]) : "No offerings.";
774
796
  },
@@ -817,6 +839,18 @@ async function connect(ctx) {
817
839
  if (!await provider.signIn()) throw notSignedIn();
818
840
  return openSession({ url: ctx.url, fetchFn: ctx.fetch.fetchFn, seen: ctx.fetch.seen, era, auth: provider });
819
841
  }
842
+ async function isSignedIn(ctx) {
843
+ if (accessTokenOf(ctx)) return true;
844
+ const provider = new CliOAuthProvider({
845
+ serverUrl: ctx.key,
846
+ config: ctx.config,
847
+ store: await storeFor(ctx),
848
+ redactor: ctx.redactor,
849
+ interactive: false,
850
+ redirectUri: loopbackRedirect(registeredPort(ctx.config.server(ctx.key).client))
851
+ });
852
+ return await provider.signIn() !== null;
853
+ }
820
854
  async function withSession(ctx, work) {
821
855
  const session = await connect(ctx);
822
856
  try {
@@ -934,7 +968,9 @@ async function cmdLogin(ctx) {
934
968
  if (ctx.out.json) ctx.out.value(value);
935
969
  else {
936
970
  const where = store.kind === "file" ? "a private file" : store.kind === "keychain" ? "the macOS keychain" : "the Secret Service keyring";
937
- ctx.out.out(`Signed in to Vavio${workspace ? `: workspace ${str(workspace.name)} (${str(workspace.id)})` : ""}. Saved in ${where}.`);
971
+ const raw = typeof workspace?.name === "string" ? workspace.name.replace(/\s+/g, " ").trim() : "";
972
+ const name = raw && !/^workspace [0-9a-f]{8}$/i.test(raw) ? raw.slice(0, 80) : null;
973
+ ctx.out.out(`Signed in to Vavio${name ? ` (workspace ${name})` : ""}. Saved in ${where}.`);
938
974
  }
939
975
  return EXIT.ok;
940
976
  }
@@ -1084,6 +1120,9 @@ function route(positionals) {
1084
1120
  case "account":
1085
1121
  exact(1);
1086
1122
  return { key: "account", run: (ctx) => callAndReport(ctx, "account_overview", {}, FORMAT.account) };
1123
+ case "status":
1124
+ exact(1);
1125
+ return { key: "status", run: (ctx) => callAndReport(ctx, "account_overview", {}, FORMAT.account) };
1087
1126
  case "offerings":
1088
1127
  exact(1);
1089
1128
  return { key: "offerings", run: (ctx) => callAndReport(ctx, "list_offerings", {}, FORMAT.offerings) };
@@ -1150,13 +1189,15 @@ async function runCli(argv, io = {}) {
1150
1189
  else out().out(`${CLI_NAME} ${CLI_VERSION} (contract ${CONTRACT_VERSION})`);
1151
1190
  return EXIT.ok;
1152
1191
  }
1153
- if (flags.help || positionals.length === 0 || positionals[0] === "help") {
1192
+ const showHelp = () => {
1154
1193
  const text = helpFor(positionals);
1155
1194
  if (json) out().value({ outcome: "ok", help: text });
1156
1195
  else out().out(text);
1157
1196
  return EXIT.ok;
1158
- }
1159
- const target = route(positionals);
1197
+ };
1198
+ if (flags.help || positionals[0] === "help") return showHelp();
1199
+ const bare = positionals.length === 0;
1200
+ const target = route(bare ? ["status"] : positionals);
1160
1201
  const allowed = /* @__PURE__ */ new Set([...GLOBAL_FLAGS, ...COMMANDS[target.key].flags ?? []]);
1161
1202
  for (const name of Object.keys(flags)) {
1162
1203
  if (!allowed.has(name)) throw usage(`--${name} does not apply to vavio ${target.key}. See vavio ${target.key.split(" ")[0]} --help.`);
@@ -1178,6 +1219,7 @@ async function runCli(argv, io = {}) {
1178
1219
  platform,
1179
1220
  fetch: contractFetch(io.fetch ?? globalThis.fetch, url)
1180
1221
  };
1222
+ if (bare && !await isSignedIn(ctx)) return showHelp();
1181
1223
  return await target.run(ctx);
1182
1224
  } catch (error) {
1183
1225
  const failure = error instanceof CliError ? error : new CliError("failed", `Unexpected error: ${(error instanceof Error ? error.message : String(error)).slice(0, 200)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vavio/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "vavio: operate your Vavio account and Hermes instances from a terminal or your own AI assistant, over Vavio's MCP server.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://vavio.ai",