@miosa/cli 1.0.5 → 1.0.6

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.
@@ -1,7 +1,8 @@
1
1
  import chalk from "chalk";
2
2
  import { loadConfig, loadAuthCache, saveAuthCache, redactKey, } from "../config.js";
3
3
  import { MiosaClient } from "../client.js";
4
- import { handleError, printJson } from "./util.js";
4
+ import { banner, errorEnvelope, hintBlock, icon, kvPanel, } from "../ui/render.js";
5
+ import { printJson } from "./util.js";
5
6
  export function register(program) {
6
7
  program
7
8
  .command("whoami")
@@ -10,15 +11,19 @@ export function register(program) {
10
11
  .option("--refresh", "Force a network refresh of the cached identity")
11
12
  .action(async (opts) => {
12
13
  const config = loadConfig();
14
+ // ── Not signed in ────────────────────────────────────────────────
13
15
  if (!config.api_key) {
14
16
  if (opts.json) {
15
17
  printJson({ authenticated: false });
16
18
  return;
17
19
  }
18
- console.log(chalk.yellow("Not logged in. Run: miosa login"));
20
+ console.log();
21
+ console.log(` ${icon.warn} ${chalk.bold("Not signed in")}`);
22
+ console.log();
23
+ console.log(hintBlock("Sign in", ["miosa login"]));
19
24
  process.exit(1);
20
25
  }
21
- // Fast path: serve from cache unless --refresh requested
26
+ // ── Fast path: serve from cache ─────────────────────────────────
22
27
  const cached = opts.refresh ? null : loadAuthCache();
23
28
  if (cached) {
24
29
  if (opts.json) {
@@ -34,16 +39,18 @@ export function register(program) {
34
39
  });
35
40
  return;
36
41
  }
37
- const region = cached.region ?? config.region ?? "auto";
38
- console.log();
39
- console.log(` ${chalk.bold(cached.name)}` + chalk.dim(` (${cached.plan} plan)`));
40
- console.log(` Tenant: ${cached.slug}`);
41
- console.log(` API Key: ${redactKey(config.api_key)}`);
42
- console.log(` Region: ${region}`);
43
- console.log();
42
+ renderIdentity({
43
+ name: cached.name,
44
+ slug: cached.slug,
45
+ plan: cached.plan,
46
+ credit_balance: cached.credit_balance,
47
+ region: cached.region ?? config.region ?? "auto",
48
+ api_key: config.api_key,
49
+ fromCache: true,
50
+ });
44
51
  return;
45
52
  }
46
- // Slow path: fetch from API, then cache the result
53
+ // ── Slow path: fetch + cache ────────────────────────────────────
47
54
  try {
48
55
  const client = new MiosaClient(config);
49
56
  const tenant = await client.getTenant();
@@ -68,17 +75,67 @@ export function register(program) {
68
75
  });
69
76
  return;
70
77
  }
71
- const region = config.region ?? "auto";
72
- console.log();
73
- console.log(` ${chalk.bold(tenant.name)}` + chalk.dim(` (${tenant.plan} plan)`));
74
- console.log(` Tenant: ${tenant.slug}`);
75
- console.log(` API Key: ${redactKey(config.api_key)}`);
76
- console.log(` Region: ${region}`);
77
- console.log();
78
+ renderIdentity({
79
+ name: tenant.name,
80
+ slug: tenant.slug,
81
+ plan: tenant.plan,
82
+ credit_balance: tenant.credit_balance,
83
+ region: config.region ?? "auto",
84
+ api_key: config.api_key,
85
+ fromCache: false,
86
+ });
78
87
  }
79
88
  catch (err) {
80
- handleError(err);
89
+ const message = err instanceof Error ? err.message : String(err);
90
+ console.log();
91
+ console.log(errorEnvelope({
92
+ title: "Could not load identity",
93
+ body: message,
94
+ suggest: [
95
+ "miosa whoami --refresh # bypass the local cache",
96
+ "miosa login # re-authenticate if your key was revoked",
97
+ ],
98
+ withDebugHint: true,
99
+ }));
100
+ process.exit(1);
81
101
  }
82
102
  });
83
103
  }
104
+ function renderIdentity(s) {
105
+ console.log();
106
+ console.log(` ${banner({ subtitle: "Identity" })}`);
107
+ console.log();
108
+ console.log(kvPanel([
109
+ {
110
+ icon: icon.ok,
111
+ label: "Tenant",
112
+ value: chalk.bold(s.name) + chalk.dim(` (${s.slug})`),
113
+ },
114
+ {
115
+ label: "Plan",
116
+ value: chalk.bold(s.plan),
117
+ },
118
+ {
119
+ label: "Credits",
120
+ value: s.credit_balance > 0
121
+ ? chalk.bold(s.credit_balance.toLocaleString())
122
+ : chalk.yellow("0 — top up at https://miosa.ai/billing"),
123
+ },
124
+ {
125
+ label: "Region",
126
+ value: s.region,
127
+ },
128
+ {
129
+ label: "API key",
130
+ value: chalk.dim(redactKey(s.api_key)),
131
+ },
132
+ ]));
133
+ if (s.fromCache) {
134
+ console.log();
135
+ console.log(` ${chalk.dim("(cached — use ")}` +
136
+ chalk.cyan("miosa whoami --refresh") +
137
+ chalk.dim(" for live data)"));
138
+ }
139
+ console.log();
140
+ }
84
141
  //# sourceMappingURL=whoami.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `miosa watch` — live terminal dashboard.
3
+ *
4
+ * React component (rendered by ink) that polls the MIOSA API every few
5
+ * seconds and shows a single-screen snapshot:
6
+ *
7
+ * - Sign-in identity (tenant + plan)
8
+ * - Counts: running computers, sandboxes, deployments
9
+ * - Last fetch time + auto-refresh interval
10
+ * - Recent activity (most recent N rows from computers/sandboxes/deps)
11
+ * - Quit hint
12
+ *
13
+ * The component is self-contained — bin/miosa.ts is unchanged; the new
14
+ * watch.ts command just mounts this with `ink.render()`.
15
+ */
16
+ import React from "react";
17
+ import type { MiosaConfig } from "../types.js";
18
+ interface DashboardProps {
19
+ config: MiosaConfig;
20
+ }
21
+ interface ResourceRow {
22
+ id: string;
23
+ name?: string;
24
+ status?: string;
25
+ state?: string;
26
+ template_type?: string;
27
+ updated_at?: string;
28
+ created_at?: string;
29
+ }
30
+ declare function isActive(row: ResourceRow): boolean;
31
+ declare function timeAgo(iso?: string): string;
32
+ declare function sortRecent(rows: ResourceRow[]): ResourceRow[];
33
+ export declare const Dashboard: React.FC<DashboardProps>;
34
+ export { sortRecent, timeAgo, isActive };
35
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/tui/dashboard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAuC,MAAM,OAAO,CAAC;AAG5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,UAAU,cAAc;IACtB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAqCD,iBAAS,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAG3C;AAED,iBAAS,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAQrC;AAED,iBAAS,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAMtD;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAuN9C,CAAC;AAmEF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,191 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * `miosa watch` — live terminal dashboard.
4
+ *
5
+ * React component (rendered by ink) that polls the MIOSA API every few
6
+ * seconds and shows a single-screen snapshot:
7
+ *
8
+ * - Sign-in identity (tenant + plan)
9
+ * - Counts: running computers, sandboxes, deployments
10
+ * - Last fetch time + auto-refresh interval
11
+ * - Recent activity (most recent N rows from computers/sandboxes/deps)
12
+ * - Quit hint
13
+ *
14
+ * The component is self-contained — bin/miosa.ts is unchanged; the new
15
+ * watch.ts command just mounts this with `ink.render()`.
16
+ */
17
+ import { useEffect, useMemo, useState } from "react";
18
+ import { Box, Text, useApp, useInput } from "ink";
19
+ import { MiosaClient } from "../client.js";
20
+ const POLL_INTERVAL_MS = 5_000;
21
+ async function safeList(client, path) {
22
+ try {
23
+ const result = await client.apiGet(path);
24
+ if (Array.isArray(result))
25
+ return result;
26
+ if (result && typeof result === "object") {
27
+ const rec = result;
28
+ for (const key of [
29
+ "data",
30
+ "computers",
31
+ "sandboxes",
32
+ "deployments",
33
+ "items",
34
+ ]) {
35
+ if (Array.isArray(rec[key]))
36
+ return rec[key];
37
+ }
38
+ }
39
+ return [];
40
+ }
41
+ catch {
42
+ // Snapshot stays consistent even if one endpoint is flaky.
43
+ return [];
44
+ }
45
+ }
46
+ function isActive(row) {
47
+ const s = (row.status ?? row.state ?? "").toLowerCase();
48
+ return s === "active" || s === "running" || s === "ready";
49
+ }
50
+ function timeAgo(iso) {
51
+ if (!iso)
52
+ return "—";
53
+ const ms = Date.now() - new Date(iso).getTime();
54
+ if (Number.isNaN(ms) || ms < 0)
55
+ return "—";
56
+ if (ms < 60_000)
57
+ return `${Math.floor(ms / 1000)}s ago`;
58
+ if (ms < 3_600_000)
59
+ return `${Math.floor(ms / 60_000)}m ago`;
60
+ if (ms < 86_400_000)
61
+ return `${Math.floor(ms / 3_600_000)}h ago`;
62
+ return `${Math.floor(ms / 86_400_000)}d ago`;
63
+ }
64
+ function sortRecent(rows) {
65
+ return [...rows].sort((a, b) => {
66
+ const ta = new Date(a.updated_at ?? a.created_at ?? 0).getTime();
67
+ const tb = new Date(b.updated_at ?? b.created_at ?? 0).getTime();
68
+ return tb - ta;
69
+ });
70
+ }
71
+ export const Dashboard = ({ config }) => {
72
+ const { exit } = useApp();
73
+ const [snapshot, setSnapshot] = useState({
74
+ fetchedAt: 0,
75
+ computers: [],
76
+ sandboxes: [],
77
+ deployments: [],
78
+ });
79
+ const [tick, setTick] = useState(0);
80
+ // Quit handling
81
+ useInput((input, key) => {
82
+ if (input === "q" || (key.ctrl && input === "c")) {
83
+ exit();
84
+ }
85
+ });
86
+ const client = useMemo(() => new MiosaClient(config), [config]);
87
+ // Initial load + interval poll
88
+ useEffect(() => {
89
+ let cancelled = false;
90
+ const fetch = async () => {
91
+ try {
92
+ const [computers, sandboxes, deployments, tenant] = await Promise.all([
93
+ safeList(client, "/api/v1/computers"),
94
+ safeList(client, "/api/v1/sandboxes"),
95
+ safeList(client, "/api/v1/deployments"),
96
+ client.getTenant().catch(() => null),
97
+ ]);
98
+ if (cancelled)
99
+ return;
100
+ setSnapshot({
101
+ fetchedAt: Date.now(),
102
+ tenant: tenant
103
+ ? {
104
+ name: tenant.name,
105
+ plan: tenant.plan,
106
+ slug: tenant.slug,
107
+ credit_balance: tenant.credit_balance,
108
+ }
109
+ : undefined,
110
+ computers,
111
+ sandboxes,
112
+ deployments,
113
+ });
114
+ }
115
+ catch (err) {
116
+ if (cancelled)
117
+ return;
118
+ setSnapshot((prev) => ({
119
+ ...prev,
120
+ fetchedAt: Date.now(),
121
+ error: err instanceof Error ? err.message : String(err),
122
+ }));
123
+ }
124
+ };
125
+ void fetch();
126
+ const id = setInterval(() => void fetch(), POLL_INTERVAL_MS);
127
+ return () => {
128
+ cancelled = true;
129
+ clearInterval(id);
130
+ };
131
+ }, [client]);
132
+ // Local clock tick so "1s ago" labels stay fresh between polls
133
+ useEffect(() => {
134
+ const id = setInterval(() => setTick((t) => t + 1), 1000);
135
+ return () => clearInterval(id);
136
+ }, []);
137
+ const computeActive = snapshot.computers.filter(isActive).length;
138
+ const sandboxActive = snapshot.sandboxes.filter(isActive).length;
139
+ const deployActive = snapshot.deployments.filter(isActive).length;
140
+ const recent = useMemo(() => [
141
+ ...snapshot.computers.map((r) => ({
142
+ kind: "computer",
143
+ row: r,
144
+ })),
145
+ ...snapshot.sandboxes.map((r) => ({
146
+ kind: "sandbox",
147
+ row: r,
148
+ })),
149
+ ...snapshot.deployments.map((r) => ({
150
+ kind: "deployment",
151
+ row: r,
152
+ })),
153
+ ]
154
+ .sort((a, b) => {
155
+ const ta = new Date(a.row.updated_at ?? a.row.created_at ?? 0).getTime();
156
+ const tb = new Date(b.row.updated_at ?? b.row.created_at ?? 0).getTime();
157
+ return tb - ta;
158
+ })
159
+ .slice(0, 6), [snapshot, tick]);
160
+ const lastFetchAgo = snapshot.fetchedAt === 0
161
+ ? "—"
162
+ : `${Math.max(0, Math.floor((Date.now() - snapshot.fetchedAt) / 1000))}s ago`;
163
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, paddingY: 0, children: [_jsxs(Box, { justifyContent: "space-between", marginBottom: 1, children: [_jsxs(Text, { children: [_jsx(Text, { color: "cyan", bold: true, children: "\u25AE\u25AE\u25AE MIOSA \u25AE\u25AE\u25AE" }), snapshot.tenant ? (_jsxs(_Fragment, { children: [" ", _jsx(Text, { bold: true, children: snapshot.tenant.name }), _jsxs(Text, { dimColor: true, children: [" \u00B7 ", snapshot.tenant.plan] })] })) : (_jsx(Text, { dimColor: true, children: " (loading identity\u2026)" }))] }), _jsxs(Text, { dimColor: true, children: ["last fetch ", lastFetchAgo, " \u00B7 refresh ", POLL_INTERVAL_MS / 1000, "s"] })] }), _jsxs(Box, { flexDirection: "row", marginBottom: 1, children: [_jsx(CountTile, { label: "COMPUTERS", total: snapshot.computers.length, active: computeActive, accent: "green" }), _jsx(Box, { marginLeft: 2, children: _jsx(CountTile, { label: "SANDBOXES", total: snapshot.sandboxes.length, active: sandboxActive, accent: "blue" }) }), _jsx(Box, { marginLeft: 2, children: _jsx(CountTile, { label: "DEPLOYMENTS", total: snapshot.deployments.length, active: deployActive, accent: "magenta" }) }), snapshot.tenant && (_jsx(Box, { marginLeft: 2, children: _jsx(CountTile, { label: "CREDITS", total: snapshot.tenant.credit_balance, active: null, accent: snapshot.tenant.credit_balance > 0 ? "yellow" : "red" }) }))] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { dimColor: true, bold: true, children: "RECENT" }), recent.length === 0 ? (_jsxs(Text, { dimColor: true, children: [" ", "(no resources yet \u2014 run `miosa login` then create a sandbox)"] })) : (recent.map((item, idx) => (_jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: kindGlyph(item.kind) }), _jsx(Text, { children: " " }), _jsx(Text, { children: (item.row.name ?? item.row.id).slice(0, 32).padEnd(32) }), _jsx(Text, { children: " " }), _jsx(Text, { color: statusColor(item.row), children: (item.row.status ?? item.row.state ?? "—").padEnd(12) }), _jsx(Text, { dimColor: true, children: timeAgo(item.row.updated_at ?? item.row.created_at) })] }, `${item.kind}-${item.row.id}-${idx}`))))] }), snapshot.error && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: "red", children: "\u2717 " }), _jsx(Text, { color: "red", children: snapshot.error })] })), _jsx(Box, { children: _jsxs(Text, { dimColor: true, children: ["press ", _jsx(Text, { bold: true, children: "q" }), " to quit \u00B7 ", _jsx(Text, { bold: true, children: "r" }), " to refresh now (auto every ", POLL_INTERVAL_MS / 1000, "s)"] }) })] }));
164
+ };
165
+ const CountTile = ({ label, total, active, accent, }) => {
166
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: accent, paddingX: 1, minWidth: 18, children: [_jsx(Text, { dimColor: true, bold: true, children: label }), _jsxs(Text, { children: [_jsx(Text, { color: accent, bold: true, children: total }), active !== null && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: " total \u00B7 " }), _jsx(Text, { color: accent, children: active }), _jsx(Text, { dimColor: true, children: " active" })] }))] })] }));
167
+ };
168
+ // ── Helpers ────────────────────────────────────────────────────────────────
169
+ function kindGlyph(kind) {
170
+ switch (kind) {
171
+ case "computer":
172
+ return "◆";
173
+ case "sandbox":
174
+ return "□";
175
+ case "deployment":
176
+ return "▲";
177
+ }
178
+ }
179
+ function statusColor(row) {
180
+ const s = (row.status ?? row.state ?? "").toLowerCase();
181
+ if (s === "active" || s === "running" || s === "ready")
182
+ return "green";
183
+ if (s === "provisioning" || s === "building" || s === "pending")
184
+ return "yellow";
185
+ if (s === "error" || s === "failed")
186
+ return "red";
187
+ return "gray";
188
+ }
189
+ // Re-export for any future TUI command that wants to reuse helpers.
190
+ export { sortRecent, timeAgo, isActive };
191
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/tui/dashboard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * MIOSA CLI resource picker.
3
+ *
4
+ * When a user runs a command that needs a sandbox / computer / deployment
5
+ * id and they didn't supply one, we present a searchable list instead of
6
+ * forcing them to grep `miosa computers list | awk …`.
7
+ *
8
+ * Built on the existing `inquirer` dep — no new packages. Dynamic import
9
+ * keeps the cold-start fast for commands that never prompt.
10
+ */
11
+ export interface PickItem<T = unknown> {
12
+ /** Stable id used as the prompt return value. */
13
+ id: string;
14
+ /** First line of the choice as rendered. */
15
+ label: string;
16
+ /** Dim second-line metadata: status, region, age, etc. */
17
+ hint?: string;
18
+ /** Original record, returned to the caller for convenience. */
19
+ data: T;
20
+ }
21
+ /**
22
+ * Show a list, return the selected item. Throws `UserError` when the
23
+ * list is empty so the caller can print a friendly "create one first"
24
+ * message instead of an inquirer crash.
25
+ *
26
+ * @param items Choices to render. Pre-filter to what's relevant for
27
+ * the command (e.g. `status === "active"` for `exec`).
28
+ * @param prompt The question shown above the list.
29
+ */
30
+ export declare function pickOne<T>(items: PickItem<T>[], prompt: string): Promise<PickItem<T>>;
31
+ /**
32
+ * Convenience helper for confirm dialogs. Returns the user's answer
33
+ * (defaulting to `false`) and prints "Cancelled." + exits the parent
34
+ * promise chain naturally when the user says no.
35
+ *
36
+ * Use this for any destructive action (`destroy`, `revoke`, `delete`).
37
+ */
38
+ export declare function confirm(message: string, opts?: {
39
+ default?: boolean;
40
+ }): Promise<boolean>;
41
+ //# sourceMappingURL=picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.d.ts","sourceRoot":"","sources":["../../src/ui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,IAAI,EAAE,CAAC,CAAC;CACT;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAC7B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAwCtB;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,OAAO,CAAC,CAelB"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * MIOSA CLI resource picker.
3
+ *
4
+ * When a user runs a command that needs a sandbox / computer / deployment
5
+ * id and they didn't supply one, we present a searchable list instead of
6
+ * forcing them to grep `miosa computers list | awk …`.
7
+ *
8
+ * Built on the existing `inquirer` dep — no new packages. Dynamic import
9
+ * keeps the cold-start fast for commands that never prompt.
10
+ */
11
+ import chalk from "chalk";
12
+ import { UserError } from "../errors.js";
13
+ /**
14
+ * Show a list, return the selected item. Throws `UserError` when the
15
+ * list is empty so the caller can print a friendly "create one first"
16
+ * message instead of an inquirer crash.
17
+ *
18
+ * @param items Choices to render. Pre-filter to what's relevant for
19
+ * the command (e.g. `status === "active"` for `exec`).
20
+ * @param prompt The question shown above the list.
21
+ */
22
+ export async function pickOne(items, prompt) {
23
+ if (items.length === 0) {
24
+ throw new UserError("Nothing to pick from.", "Create a resource first, then re-run this command.");
25
+ }
26
+ // If we're not on a TTY (CI, pipe), refuse to prompt — the caller
27
+ // should have supplied the id explicitly. Surfacing the error here
28
+ // is friendlier than hanging on stdin.
29
+ if (!process.stdin.isTTY) {
30
+ throw new UserError("Cannot prompt for selection in a non-interactive shell.", "Pass the resource id explicitly.");
31
+ }
32
+ const { default: inquirer } = await import("inquirer");
33
+ const { picked } = await inquirer.prompt([
34
+ {
35
+ type: "list",
36
+ name: "picked",
37
+ message: prompt,
38
+ pageSize: Math.min(10, items.length),
39
+ choices: items.map((it) => ({
40
+ name: it.hint ? `${it.label} ${chalk.dim(it.hint)}` : it.label,
41
+ value: it.id,
42
+ short: it.label,
43
+ })),
44
+ },
45
+ ]);
46
+ const found = items.find((it) => it.id === picked);
47
+ if (!found) {
48
+ // Defensive — inquirer should always return one of the supplied
49
+ // values. If it doesn't, something is structurally wrong.
50
+ throw new Error(`Picker returned unknown id: ${picked}`);
51
+ }
52
+ return found;
53
+ }
54
+ /**
55
+ * Convenience helper for confirm dialogs. Returns the user's answer
56
+ * (defaulting to `false`) and prints "Cancelled." + exits the parent
57
+ * promise chain naturally when the user says no.
58
+ *
59
+ * Use this for any destructive action (`destroy`, `revoke`, `delete`).
60
+ */
61
+ export async function confirm(message, opts = {}) {
62
+ if (!process.stdin.isTTY) {
63
+ // No TTY → assume "no" so scripts don't accidentally proceed.
64
+ return false;
65
+ }
66
+ const { default: inquirer } = await import("inquirer");
67
+ const { ok } = await inquirer.prompt([
68
+ {
69
+ type: "confirm",
70
+ name: "ok",
71
+ message,
72
+ default: opts.default ?? false,
73
+ },
74
+ ]);
75
+ return ok;
76
+ }
77
+ //# sourceMappingURL=picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picker.js","sourceRoot":"","sources":["../../src/ui/picker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,KAAoB,EACpB,MAAc;IAEd,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CACjB,uBAAuB,EACvB,oDAAoD,CACrD,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,mEAAmE;IACnE,uCAAuC;IACvC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CACjB,yDAAyD,EACzD,kCAAkC,CACnC,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAqB;QAC3D;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC;YACpC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC1B,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK;gBAC/D,KAAK,EAAE,EAAE,CAAC,EAAE;gBACZ,KAAK,EAAE,EAAE,CAAC,KAAK;aAChB,CAAC,CAAC;SACJ;KACF,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,gEAAgE;QAChE,0DAA0D;QAC1D,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAe,EACf,OAA8B,EAAE;IAEhC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACzB,8DAA8D;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAkB;QACpD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,IAAI;YACV,OAAO;YACP,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;SAC/B;KACF,CAAC,CAAC;IACH,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * MIOSA CLI render vocabulary.
3
+ *
4
+ * Single source of truth for the visible look-and-feel: banner, status
5
+ * icons, key/value panels, hint blocks, error envelopes, and elapsed
6
+ * timing. Every command should compose its output from these primitives
7
+ * so the brand stays consistent.
8
+ *
9
+ * Design rules:
10
+ * - One accent color (cyan) for the brand.
11
+ * - Semantic colors for status (green/yellow/red/dim).
12
+ * - Never print colors when not a TTY (CI, pipes) — chalk handles
13
+ * this automatically via FORCE_COLOR=0 / NO_COLOR; we just call it.
14
+ * - Plain ASCII only. No unicode that breaks in cmd.exe / Putty.
15
+ * - Every "section" the user sees should fit inside one of these
16
+ * primitives; the command does NOT reach for raw `console.log` +
17
+ * ad-hoc chalk except for the body of a tool result.
18
+ */
19
+ export declare const icon: {
20
+ ok: string;
21
+ fail: string;
22
+ warn: string;
23
+ info: string;
24
+ bullet: string;
25
+ arrow: string;
26
+ pending: string;
27
+ };
28
+ /**
29
+ * Single-line MIOSA banner used at the top of lifecycle commands
30
+ * (login / logout / mcp install). Compact and unobtrusive.
31
+ *
32
+ * ▮▮▮ MIOSA ▮▮▮ v1.0.4
33
+ */
34
+ export declare function banner(opts?: {
35
+ version?: string;
36
+ subtitle?: string;
37
+ }): string;
38
+ export interface KVRow {
39
+ /** Left column label. Will be bolded. */
40
+ label: string;
41
+ /** Right column value. Pre-formatted; no further styling applied. */
42
+ value: string;
43
+ /** Optional leading icon (e.g. `icon.ok`). */
44
+ icon?: string;
45
+ }
46
+ /**
47
+ * Render a list of key/value rows with aligned columns. Used for the
48
+ * "✓ Authenticated ClinicIQ · Pro plan" output blocks.
49
+ */
50
+ export declare function kvPanel(rows: KVRow[]): string;
51
+ /**
52
+ * Suggest what the user can do next. Rendered as:
53
+ *
54
+ * → Next: miosa computers list
55
+ * miosa mcp install
56
+ */
57
+ export declare function hintBlock(label: string, commands: string[]): string;
58
+ export interface ErrorEnvelope {
59
+ title: string;
60
+ body?: string;
61
+ /** Suggested commands or doc URL. */
62
+ suggest?: string[];
63
+ /** Show "Run with --debug for full trace" hint. */
64
+ withDebugHint?: boolean;
65
+ }
66
+ /**
67
+ * Format an error in the brand's red envelope. Use this in the catch
68
+ * block of every command instead of bare `console.error`.
69
+ */
70
+ export declare function errorEnvelope(env: ErrorEnvelope): string;
71
+ /**
72
+ * Wrap an async block and append a "Took 1.2s" line on success.
73
+ * On error, re-throws so the caller can format its own envelope.
74
+ */
75
+ export declare function withElapsed<T>(fn: () => Promise<T>): Promise<{
76
+ result: T;
77
+ elapsed: string;
78
+ }>;
79
+ export declare function formatDuration(ms: number): string;
80
+ /** Insert a blank line. Cheap readability tool. */
81
+ export declare const blank: () => void;
82
+ /** Print the banner — convenience over `console.log(banner(...))`. */
83
+ export declare function printBanner(opts?: {
84
+ version?: string;
85
+ subtitle?: string;
86
+ }): void;
87
+ /** Print the elapsed line in dim text below a successful command. */
88
+ export declare function printElapsed(elapsed: string): void;
89
+ /** Print a section header (dim small-caps). */
90
+ export declare function sectionHeader(label: string): void;
91
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/ui/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,eAAO,MAAM,IAAI;;;;;;;;CAQhB,CAAC;AAIF;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,MAAM,CAMR;AAID,MAAM,WAAW,KAAK;IACpB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAU7C;AAID;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAQnE;AAID,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,mDAAmD;IACnD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgBxD;AAID;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAClE,MAAM,EAAE,CAAC,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAKD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOjD;AAID,mDAAmD;AACnD,eAAO,MAAM,KAAK,QAAO,IAAqB,CAAC;AAE/C,sEAAsE;AACtE,wBAAgB,WAAW,CACzB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,IAAI,CAIN;AAED,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGlD;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGjD"}