@calltelemetry/cli 0.3.8 → 0.4.0

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 (89) hide show
  1. package/README.md +13 -1
  2. package/dist/commands/diag.d.ts.map +1 -1
  3. package/dist/commands/diag.js +7 -0
  4. package/dist/commands/diag.js.map +1 -1
  5. package/dist/commands/jtapi.d.ts.map +1 -1
  6. package/dist/commands/jtapi.js +10 -9
  7. package/dist/commands/jtapi.js.map +1 -1
  8. package/dist/commands/secrets.d.ts.map +1 -1
  9. package/dist/commands/secrets.js +12 -0
  10. package/dist/commands/secrets.js.map +1 -1
  11. package/dist/commands/users.d.ts +3 -0
  12. package/dist/commands/users.d.ts.map +1 -0
  13. package/dist/commands/users.js +24 -0
  14. package/dist/commands/users.js.map +1 -0
  15. package/dist/index.js +6 -3
  16. package/dist/index.js.map +1 -1
  17. package/dist/lib/compose.d.ts.map +1 -1
  18. package/dist/lib/compose.js +1 -3
  19. package/dist/lib/compose.js.map +1 -1
  20. package/dist/lib/env.d.ts +14 -0
  21. package/dist/lib/env.d.ts.map +1 -0
  22. package/dist/lib/env.js +74 -0
  23. package/dist/lib/env.js.map +1 -0
  24. package/dist/lib/jtapi.d.ts +67 -2
  25. package/dist/lib/jtapi.d.ts.map +1 -1
  26. package/dist/lib/jtapi.js +261 -14
  27. package/dist/lib/jtapi.js.map +1 -1
  28. package/dist/lib/paths.d.ts +1 -1
  29. package/dist/lib/paths.d.ts.map +1 -1
  30. package/dist/lib/paths.js +1 -1
  31. package/dist/lib/paths.js.map +1 -1
  32. package/dist/lib/redact.d.ts +10 -0
  33. package/dist/lib/redact.d.ts.map +1 -0
  34. package/dist/lib/redact.js +45 -0
  35. package/dist/lib/redact.js.map +1 -0
  36. package/dist/lib/secrets.d.ts +16 -1
  37. package/dist/lib/secrets.d.ts.map +1 -1
  38. package/dist/lib/secrets.js +48 -1
  39. package/dist/lib/secrets.js.map +1 -1
  40. package/dist/lib/showtech-steps.d.ts +7 -0
  41. package/dist/lib/showtech-steps.d.ts.map +1 -0
  42. package/dist/lib/showtech-steps.js +351 -0
  43. package/dist/lib/showtech-steps.js.map +1 -0
  44. package/dist/lib/users.d.ts +33 -0
  45. package/dist/lib/users.d.ts.map +1 -0
  46. package/dist/lib/users.js +67 -0
  47. package/dist/lib/users.js.map +1 -0
  48. package/dist/ui/components/AppShell.d.ts +3 -1
  49. package/dist/ui/components/AppShell.d.ts.map +1 -1
  50. package/dist/ui/components/AppShell.js +5 -2
  51. package/dist/ui/components/AppShell.js.map +1 -1
  52. package/dist/ui/components/MetricsFooter.d.ts +7 -0
  53. package/dist/ui/components/MetricsFooter.d.ts.map +1 -0
  54. package/dist/ui/components/MetricsFooter.js +36 -0
  55. package/dist/ui/components/MetricsFooter.js.map +1 -0
  56. package/dist/ui/components/index.d.ts +1 -0
  57. package/dist/ui/components/index.d.ts.map +1 -1
  58. package/dist/ui/components/index.js +1 -0
  59. package/dist/ui/components/index.js.map +1 -1
  60. package/dist/ui/context/MetricsContext.d.ts +7 -0
  61. package/dist/ui/context/MetricsContext.d.ts.map +1 -0
  62. package/dist/ui/context/MetricsContext.js +13 -0
  63. package/dist/ui/context/MetricsContext.js.map +1 -0
  64. package/dist/ui/views/DiagDatabaseView.d.ts.map +1 -1
  65. package/dist/ui/views/DiagDatabaseView.js +36 -28
  66. package/dist/ui/views/DiagDatabaseView.js.map +1 -1
  67. package/dist/ui/views/DiagServiceView.d.ts.map +1 -1
  68. package/dist/ui/views/DiagServiceView.js +29 -18
  69. package/dist/ui/views/DiagServiceView.js.map +1 -1
  70. package/dist/ui/views/DiagShowTechView.d.ts +6 -0
  71. package/dist/ui/views/DiagShowTechView.d.ts.map +1 -0
  72. package/dist/ui/views/DiagShowTechView.js +68 -0
  73. package/dist/ui/views/DiagShowTechView.js.map +1 -0
  74. package/dist/ui/views/JtapiView.d.ts +7 -0
  75. package/dist/ui/views/JtapiView.d.ts.map +1 -0
  76. package/dist/ui/views/JtapiView.js +405 -0
  77. package/dist/ui/views/JtapiView.js.map +1 -0
  78. package/dist/ui/views/MainMenu.d.ts.map +1 -1
  79. package/dist/ui/views/MainMenu.js +25 -22
  80. package/dist/ui/views/MainMenu.js.map +1 -1
  81. package/dist/ui/views/SecretsResetPasswordView.d.ts +11 -0
  82. package/dist/ui/views/SecretsResetPasswordView.d.ts.map +1 -0
  83. package/dist/ui/views/SecretsResetPasswordView.js +205 -0
  84. package/dist/ui/views/SecretsResetPasswordView.js.map +1 -0
  85. package/dist/ui/views/UserResetPasswordView.d.ts +10 -0
  86. package/dist/ui/views/UserResetPasswordView.d.ts.map +1 -0
  87. package/dist/ui/views/UserResetPasswordView.js +220 -0
  88. package/dist/ui/views/UserResetPasswordView.js.map +1 -0
  89. package/package.json +1 -1
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Show Tech support bundle collection pipeline.
3
+ * Returns UpdateStep[] consumed by useStepRunner (TUI) or runStepsCli (CLI).
4
+ */
5
+ import { hostname, platform, release, cpus, totalmem, freemem, uptime as osUptime } from 'node:os';
6
+ import { join, dirname, basename } from 'node:path';
7
+ import { mkdir, writeFile, readFile, readdir, stat } from 'node:fs/promises';
8
+ import { existsSync } from 'node:fs';
9
+ import { execa } from 'execa';
10
+ import { compose, composeExec } from './compose.js';
11
+ import { getNetworkInterfaceList, getDefaultGateway, getSystemHostname } from './network.js';
12
+ import { getDockerVersion } from './system.js';
13
+ import { getAppHealth } from './rpc.js';
14
+ import { rpc, rpcOk } from './rpc.js';
15
+ import { MIGRATION_STATUS_RPC } from './rpc-scripts.js';
16
+ import { DB_USER, DB_NAME, PG_ENV } from './db.js';
17
+ import { getPaths } from './paths.js';
18
+ import { loadPrefs } from './prefs.js';
19
+ import { exec } from './exec.js';
20
+ import { redactSecrets } from './redact.js';
21
+ import { formatBytes } from './system.js';
22
+ /** All known compose services to collect logs from. */
23
+ const LOG_SERVICES = ['web', 'db', 'nats', 'minio', 'jtapi-sidecar', 'ct-media'];
24
+ /** Helper: write text to a file in the bundle directory. */
25
+ async function writeBundle(bundleDir, filename, content) {
26
+ await writeFile(join(bundleDir, filename), content, 'utf-8');
27
+ }
28
+ /** Helper: safely collect container logs. Returns output + whether the service was reachable. */
29
+ async function safeComposeLogs(service) {
30
+ try {
31
+ const result = await compose(['logs', '--tail=100000', service], { pipe: true });
32
+ const output = result.stdout ?? '';
33
+ return { output, available: output.trim().length > 0 };
34
+ }
35
+ catch (err) {
36
+ const msg = err.message || String(err);
37
+ const notFound = msg.includes('no such service') || msg.includes('not found') || msg.includes('No such container');
38
+ const label = notFound ? `service "${service}" not deployed` : msg;
39
+ return { output: `[${label}]`, available: false };
40
+ }
41
+ }
42
+ export function showtechSteps(bundleDir) {
43
+ return [
44
+ // 0. Prepare bundle directory
45
+ {
46
+ label: 'Prepare bundle directory',
47
+ run: async (ctx) => {
48
+ await mkdir(bundleDir, { recursive: true });
49
+ ctx?.log(bundleDir);
50
+ return bundleDir;
51
+ },
52
+ },
53
+ // 1. System info
54
+ {
55
+ label: 'System info',
56
+ run: async (ctx) => {
57
+ const info = [
58
+ `Hostname: ${hostname()}`,
59
+ `Platform: ${platform()} ${release()}`,
60
+ `Architecture: ${process.arch}`,
61
+ `Node.js: ${process.version}`,
62
+ `CPUs: ${cpus().length} cores (${cpus()[0]?.model ?? 'unknown'})`,
63
+ `Total RAM: ${formatBytes(totalmem())}`,
64
+ `Free RAM: ${formatBytes(freemem())}`,
65
+ `Docker: ${(await getDockerVersion()) ?? 'not found'}`,
66
+ `Uptime: ${Math.floor(process.uptime())}s (process), ${Math.floor(osUptime())}s (system)`,
67
+ `Date: ${new Date().toISOString()}`,
68
+ ];
69
+ ctx?.log(`${hostname()} — ${platform()} ${release()}`);
70
+ await writeBundle(bundleDir, '01-system-info.txt', info.join('\n') + '\n');
71
+ return `${platform()} ${release()}, ${formatBytes(totalmem())} RAM`;
72
+ },
73
+ },
74
+ // 2. Network interfaces
75
+ {
76
+ label: 'Network interfaces',
77
+ run: async (ctx) => {
78
+ const ifaces = getNetworkInterfaceList();
79
+ const gateway = await getDefaultGateway();
80
+ const host = getSystemHostname();
81
+ const lines = [
82
+ `Hostname: ${host}`,
83
+ `Default Gateway: ${gateway ?? 'unknown'}`,
84
+ '',
85
+ 'Interfaces:',
86
+ ...ifaces.map(i => ` ${i.name}: ${i.address} (${i.family}) mac=${i.mac} internal=${i.internal}`),
87
+ ];
88
+ ctx?.log(`${ifaces.length} interfaces found`);
89
+ await writeBundle(bundleDir, '02-network.txt', lines.join('\n') + '\n');
90
+ return `${ifaces.length} interfaces`;
91
+ },
92
+ },
93
+ // 3. Docker container status
94
+ {
95
+ label: 'Docker container status',
96
+ run: async (ctx) => {
97
+ let output;
98
+ try {
99
+ const result = await compose(['ps'], { pipe: true });
100
+ output = result.stdout ?? '';
101
+ }
102
+ catch (err) {
103
+ output = `[Error: ${err.message}]`;
104
+ }
105
+ const lineCount = output.split('\n').filter(l => l.trim()).length;
106
+ ctx?.log(`${lineCount} lines`);
107
+ await writeBundle(bundleDir, '03-docker-ps.txt', output);
108
+ return `${lineCount} lines`;
109
+ },
110
+ },
111
+ // 4–9. Container logs
112
+ ...LOG_SERVICES.map((service, idx) => ({
113
+ label: `Application logs (${service})`,
114
+ run: async (ctx) => {
115
+ const { output, available } = await safeComposeLogs(service);
116
+ const fileNum = String(idx + 4).padStart(2, '0');
117
+ await writeBundle(bundleDir, `${fileNum}-logs-${service}.txt`, output);
118
+ if (!available) {
119
+ const detail = output.includes('not deployed') ? 'not deployed' : 'unavailable';
120
+ ctx?.log(`${service}: ${detail}`);
121
+ return detail;
122
+ }
123
+ const lineCount = output.split('\n').length;
124
+ ctx?.log(`${lineCount} lines`);
125
+ return `${lineCount} lines`;
126
+ },
127
+ })),
128
+ // 10. Systemd journal
129
+ {
130
+ label: 'Systemd journal',
131
+ run: async (ctx) => {
132
+ let output;
133
+ try {
134
+ const result = await execa('sudo', [
135
+ 'journalctl', '-u', 'docker-compose-app.service',
136
+ '-n', '10000', '--no-pager',
137
+ ], { stdout: 'pipe', stderr: 'pipe' });
138
+ output = result.stdout ?? '';
139
+ }
140
+ catch (err) {
141
+ output = `[Not available: ${err.message}]`;
142
+ }
143
+ const lineCount = output.split('\n').length;
144
+ ctx?.log(`${lineCount} lines`);
145
+ await writeBundle(bundleDir, '10-systemd.txt', output);
146
+ return `${lineCount} lines`;
147
+ },
148
+ },
149
+ // 11. Database diagnostics
150
+ {
151
+ label: 'Database diagnostics',
152
+ run: async (ctx) => {
153
+ const queries = [
154
+ ['Active Running Queries', `SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state, wait_event_type FROM pg_stat_activity WHERE state <> 'idle' AND query NOT ILIKE '%pg_stat_activity%' ORDER BY duration DESC LIMIT 20;`],
155
+ ['Connection Count by State', `SELECT count(*) as total_connections, state, usename FROM pg_stat_activity GROUP BY state, usename ORDER BY count(*) DESC;`],
156
+ ['Blocked Queries', `SELECT blocked_locks.pid AS blocked_pid, blocking_locks.pid AS blocking_pid, LEFT(blocked_activity.query,50) AS blocked_stmt FROM pg_catalog.pg_locks blocked_locks JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation AND blocking_locks.pid <> blocked_locks.pid JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid WHERE NOT blocked_locks.granted;`],
157
+ ['Tables with High Sequential Scans', `SELECT relname, seq_scan, idx_scan, n_tup_ins, n_tup_upd, n_tup_del FROM pg_stat_user_tables ORDER BY seq_scan DESC LIMIT 15;`],
158
+ ['Dead Tuples (needs vacuum)', `SELECT relname, n_dead_tup, n_live_tup, last_vacuum, last_autovacuum FROM pg_stat_user_tables WHERE n_dead_tup > 1000 ORDER BY n_dead_tup DESC LIMIT 10;`],
159
+ ['Active MV Refreshes / Index Builds / Vacuum', `SELECT pid, now() - query_start AS duration, state, LEFT(query, 80) as operation FROM pg_stat_activity WHERE query ILIKE '%REFRESH MATERIALIZED%' OR query ILIKE '%CREATE INDEX%' OR query ILIKE '%VACUUM%' OR query ILIKE '%ANALYZE%';`],
160
+ ['Materialized Views', `SELECT matviewname, hasindexes, ispopulated FROM pg_matviews ORDER BY matviewname;`],
161
+ ['PostgreSQL Version', `SELECT version();`],
162
+ ['Database Size', `SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) as size FROM pg_database ORDER BY pg_database_size(pg_database.datname) DESC;`],
163
+ ['Extensions', `SELECT extname, extversion FROM pg_extension ORDER BY extname;`],
164
+ ['Replication Status', `SELECT * FROM pg_stat_replication;`],
165
+ ];
166
+ try {
167
+ const sections = [];
168
+ let queryCount = 0;
169
+ for (const [title, query] of queries) {
170
+ ctx?.log(title);
171
+ try {
172
+ const result = await composeExec('db', ['psql', '-U', DB_USER, '-d', DB_NAME, '-c', query], { env: PG_ENV, pipe: true });
173
+ sections.push(`=== ${title} ===\n${result.stdout ?? ''}\n`);
174
+ queryCount++;
175
+ }
176
+ catch (err) {
177
+ sections.push(`=== ${title} ===\n[Error: ${err.message}]\n`);
178
+ }
179
+ }
180
+ await writeBundle(bundleDir, '11-database.txt', sections.join('\n'));
181
+ return `${queryCount}/${queries.length} queries`;
182
+ }
183
+ catch (err) {
184
+ // Database container may not exist at all
185
+ ctx?.log(`Database unavailable: ${err.message}`);
186
+ await writeBundle(bundleDir, '11-database.txt', `[Database container unavailable: ${err.message}]\n`);
187
+ return 'unavailable';
188
+ }
189
+ },
190
+ },
191
+ // 12. App health
192
+ {
193
+ label: 'App health check',
194
+ run: async (ctx) => {
195
+ let output;
196
+ try {
197
+ const health = await getAppHealth();
198
+ output = JSON.stringify(health, null, 2);
199
+ ctx?.log(`Status: ${health.overall}`);
200
+ await writeBundle(bundleDir, '12-health.txt', output);
201
+ return health.overall;
202
+ }
203
+ catch (err) {
204
+ output = `[Error: ${err.message}]`;
205
+ await writeBundle(bundleDir, '12-health.txt', output);
206
+ return 'unavailable';
207
+ }
208
+ },
209
+ },
210
+ // 13. Migration status
211
+ {
212
+ label: 'Migration status',
213
+ run: async (ctx) => {
214
+ const sections = [];
215
+ // RPC migration status (may fail if web container is down)
216
+ try {
217
+ if (await rpcOk()) {
218
+ ctx?.log('Querying RPC migration status...');
219
+ const rpcOutput = await rpc(MIGRATION_STATUS_RPC);
220
+ sections.push('=== RPC Migration Status ===\n' + rpcOutput);
221
+ }
222
+ else {
223
+ sections.push('=== RPC Migration Status ===\n[Web container RPC not available]\n');
224
+ }
225
+ }
226
+ catch (err) {
227
+ sections.push(`=== RPC Migration Status ===\n[Error: ${err.message}]\n`);
228
+ }
229
+ // SQL migration history (direct from db container)
230
+ try {
231
+ ctx?.log('Querying schema_migrations table...');
232
+ const result = await composeExec('db', ['psql', '-U', DB_USER, '-d', DB_NAME, '-c',
233
+ 'SELECT version, inserted_at FROM schema_migrations ORDER BY version DESC;'], { env: PG_ENV, pipe: true });
234
+ sections.push('\n=== Full Migration History (schema_migrations) ===\n' + (result.stdout ?? ''));
235
+ }
236
+ catch (err) {
237
+ sections.push(`\n=== Full Migration History ===\n[Error: ${err.message}]\n`);
238
+ }
239
+ // Pending count
240
+ try {
241
+ const result = await composeExec('db', ['psql', '-U', DB_USER, '-d', DB_NAME, '-c',
242
+ 'SELECT COUNT(*) as total_migrations FROM schema_migrations;'], { env: PG_ENV, pipe: true });
243
+ sections.push('\n=== Migration Count ===\n' + (result.stdout ?? ''));
244
+ }
245
+ catch {
246
+ // non-critical
247
+ }
248
+ await writeBundle(bundleDir, '13-migrations.txt', sections.join('\n'));
249
+ return 'captured';
250
+ },
251
+ },
252
+ // 14. Install directory listing
253
+ {
254
+ label: 'Install directory listing',
255
+ run: async (ctx) => {
256
+ const { installDir } = getPaths();
257
+ let output;
258
+ try {
259
+ const result = await execa('ls', ['-la', installDir], { stdout: 'pipe', stderr: 'pipe' });
260
+ output = result.stdout ?? '';
261
+ }
262
+ catch (err) {
263
+ output = `[Error: ${err.message}]`;
264
+ }
265
+ ctx?.log(installDir);
266
+ await writeBundle(bundleDir, '14-directory-listing.txt', `Directory: ${installDir}\n\n${output}\n`);
267
+ return installDir;
268
+ },
269
+ },
270
+ // 15. Docker compose files
271
+ {
272
+ label: 'Docker compose files',
273
+ run: async (ctx) => {
274
+ const paths = getPaths();
275
+ const composeFiles = [
276
+ { path: paths.composeFile, name: '15-docker-compose.yml' },
277
+ { path: paths.overrideFile, name: '15-docker-compose.override.yml' },
278
+ { path: paths.secretsOverlayFile, name: '15-docker-compose.secrets.yml' },
279
+ ];
280
+ let count = 0;
281
+ for (const { path, name } of composeFiles) {
282
+ if (existsSync(path)) {
283
+ try {
284
+ const content = await readFile(path, 'utf-8');
285
+ await writeBundle(bundleDir, name, content);
286
+ ctx?.log(basename(path));
287
+ count++;
288
+ }
289
+ catch {
290
+ // skip unreadable files
291
+ }
292
+ }
293
+ }
294
+ return `${count} files`;
295
+ },
296
+ },
297
+ // 16. CLI preferences
298
+ {
299
+ label: 'CLI preferences',
300
+ run: async (ctx) => {
301
+ const prefs = loadPrefs();
302
+ const content = prefs
303
+ ? JSON.stringify(prefs, null, 2)
304
+ : JSON.stringify({ status: 'no preferences file (first run)' }, null, 2);
305
+ ctx?.log(prefs ? 'preferences loaded' : 'first run (no prefs)');
306
+ await writeBundle(bundleDir, '16-cli-preferences.json', content + '\n');
307
+ return prefs ? 'loaded' : 'first run';
308
+ },
309
+ },
310
+ // 17. Redact secrets
311
+ {
312
+ label: 'Redacting secrets',
313
+ run: async (ctx) => {
314
+ const files = await readdir(bundleDir);
315
+ const textFiles = files.filter(f => f.endsWith('.txt') || f.endsWith('.yml') || f.endsWith('.json'));
316
+ let redactedCount = 0;
317
+ for (const file of textFiles) {
318
+ const filePath = join(bundleDir, file);
319
+ const content = await readFile(filePath, 'utf-8');
320
+ const redacted = redactSecrets(content);
321
+ if (redacted !== content) {
322
+ await writeFile(filePath, redacted, 'utf-8');
323
+ redactedCount++;
324
+ ctx?.log(`Redacted: ${file}`);
325
+ }
326
+ }
327
+ return `${redactedCount} files redacted`;
328
+ },
329
+ },
330
+ // 18. Create archive
331
+ {
332
+ label: 'Creating archive',
333
+ run: async (ctx) => {
334
+ const parentDir = dirname(bundleDir);
335
+ const dirName = basename(bundleDir);
336
+ const archiveName = `${dirName}.tar.gz`;
337
+ const archivePath = join(parentDir, archiveName);
338
+ ctx?.log(`Archiving to ${archiveName}...`);
339
+ await exec('tar', ['-czf', archivePath, '-C', parentDir, dirName]);
340
+ // Get archive size
341
+ const stats = await stat(archivePath);
342
+ const sizeStr = formatBytes(stats.size);
343
+ // Clean up the bundle directory
344
+ await exec('rm', ['-rf', bundleDir]);
345
+ ctx?.log(`Archive: ${archivePath} (${sizeStr})`);
346
+ return `${archivePath} (${sizeStr})`;
347
+ },
348
+ },
349
+ ];
350
+ }
351
+ //# sourceMappingURL=showtech-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showtech-steps.js","sourceRoot":"","sources":["../../src/lib/showtech-steps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ export interface OrgInfo {
2
+ id: number;
3
+ name: string;
4
+ }
5
+ export interface UserInfo {
6
+ id: number;
7
+ email: string;
8
+ role: string;
9
+ roles: string[];
10
+ }
11
+ /**
12
+ * Escape a string for safe embedding in an Elixir double-quoted string literal.
13
+ * Prevents interpolation injection (#{...}) and other escaping issues.
14
+ */
15
+ export declare function escapeElixirString(s: string): string;
16
+ /**
17
+ * List all organizations via RPC.
18
+ */
19
+ export declare function listOrgs(): Promise<OrgInfo[]>;
20
+ /**
21
+ * List users in an organization via RPC.
22
+ */
23
+ export declare function listOrgUsers(orgId: number): Promise<UserInfo[]>;
24
+ /**
25
+ * Reset a user's password via RPC.
26
+ * The Elixir function handles Pow PBKDF2-SHA512 hashing internally.
27
+ */
28
+ export declare function resetUserPassword(userId: number, password: string): Promise<void>;
29
+ /**
30
+ * Generate a cryptographically random password.
31
+ */
32
+ export declare function generateUserPassword(length?: number): string;
33
+ //# sourceMappingURL=users.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAYnD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAarE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQvF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,SAAK,GAAG,MAAM,CAExD"}
@@ -0,0 +1,67 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { rpc } from './rpc.js';
3
+ /**
4
+ * Escape a string for safe embedding in an Elixir double-quoted string literal.
5
+ * Prevents interpolation injection (#{...}) and other escaping issues.
6
+ */
7
+ export function escapeElixirString(s) {
8
+ return s
9
+ .replace(/\0/g, '') // strip null bytes
10
+ .replace(/\\/g, '\\\\') // \ → \\
11
+ .replace(/"/g, '\\"') // " → \"
12
+ .replace(/#\{/g, '\\#{') // #{ → \#{ (Elixir interpolation)
13
+ .replace(/\n/g, '\\n') // newline → \n
14
+ .replace(/\r/g, '\\r'); // carriage return → \r
15
+ }
16
+ /**
17
+ * List all organizations via RPC.
18
+ */
19
+ export async function listOrgs() {
20
+ const code = `
21
+ Cdrcisco.Identity.get_all_orgs()
22
+ |> Enum.map(fn o -> %{id: o.id, name: o.name} end)
23
+ |> Jason.encode!()
24
+ |> IO.puts()
25
+ `.trim();
26
+ const stdout = await rpc(code);
27
+ const trimmed = stdout.trim();
28
+ if (!trimmed || trimmed === '[]')
29
+ return [];
30
+ return JSON.parse(trimmed);
31
+ }
32
+ /**
33
+ * List users in an organization via RPC.
34
+ */
35
+ export async function listOrgUsers(orgId) {
36
+ const code = `
37
+ org = Cdrcisco.Identity.get_org(${orgId})
38
+ org.users
39
+ |> Enum.map(fn u -> %{id: u.id, email: u.email, role: u.role, roles: u.roles || []} end)
40
+ |> Jason.encode!()
41
+ |> IO.puts()
42
+ `.trim();
43
+ const stdout = await rpc(code);
44
+ const trimmed = stdout.trim();
45
+ if (!trimmed || trimmed === '[]')
46
+ return [];
47
+ return JSON.parse(trimmed);
48
+ }
49
+ /**
50
+ * Reset a user's password via RPC.
51
+ * The Elixir function handles Pow PBKDF2-SHA512 hashing internally.
52
+ */
53
+ export async function resetUserPassword(userId, password) {
54
+ const escaped = escapeElixirString(password);
55
+ const code = `Cdrcisco.Identity.Users.reset_password(${userId}, "${escaped}") |> IO.inspect()`;
56
+ const stdout = await rpc(code);
57
+ if (!stdout.includes('{:ok,')) {
58
+ throw new Error(stdout.trim() || 'Password reset failed');
59
+ }
60
+ }
61
+ /**
62
+ * Generate a cryptographically random password.
63
+ */
64
+ export function generateUserPassword(length = 24) {
65
+ return randomBytes(length).toString('base64url').slice(0, length);
66
+ }
67
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/lib/users.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAc/B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,OAAO,CAAC;SACL,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAQ,mBAAmB;SAC7C,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAG,SAAS;SAClC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAM,SAAS;SACnC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAG,oCAAoC;SAC9D,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAK,eAAe;SACzC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAI,uBAAuB;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,IAAI,GAAG;;;;;GAKZ,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAc,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,MAAM,IAAI,GAAG;sCACuB,KAAK;;;;;GAKxC,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAAgB;IACtE,MAAM,OAAO,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,0CAA0C,MAAM,MAAM,OAAO,oBAAoB,CAAC;IAE/F,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,uBAAuB,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAM,GAAG,EAAE;IAC9C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}
@@ -9,7 +9,9 @@ interface AppShellProps {
9
9
  breadcrumb?: string;
10
10
  /** Current log level — shows a colored badge in the header when non-normal. */
11
11
  logLevel?: LogLevel;
12
+ /** Suppress the metrics footer (e.g. when the view already shows full meter bars). */
13
+ hideMetrics?: boolean;
12
14
  }
13
- export declare function AppShell({ title, command, children, onBack, isComplete, breadcrumb, logLevel, }: AppShellProps): import("react/jsx-runtime").JSX.Element;
15
+ export declare function AppShell({ title, command, children, onBack, isComplete, breadcrumb, logLevel, hideMetrics, }: AppShellProps): import("react/jsx-runtime").JSX.Element;
14
16
  export {};
15
17
  //# sourceMappingURL=AppShell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../../src/ui/components/AppShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAA2B,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,GACT,EAAE,aAAa,2CAiDf"}
1
+ {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../../src/ui/components/AppShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEjD,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAA2B,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,GACZ,EAAE,aAAa,2CAuDf"}
@@ -2,8 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useEffect } from 'react';
3
3
  import { Box, Text, useApp, useInput } from 'ink';
4
4
  import { LogLevelBadge } from './LogLevelBadge.js';
5
- export function AppShell({ title = 'CallTelemetry CLI', command, children, onBack, isComplete, breadcrumb, logLevel, }) {
5
+ import { MetricsFooter } from './MetricsFooter.js';
6
+ import { useMetrics } from '../context/MetricsContext.js';
7
+ export function AppShell({ title = 'CallTelemetry CLI', command, children, onBack, isComplete, breadcrumb, logLevel, hideMetrics, }) {
6
8
  const { exit } = useApp();
9
+ const metrics = useMetrics();
7
10
  // Auto-exit when complete with no back handler (standalone mode)
8
11
  useEffect(() => {
9
12
  if (isComplete && !onBack) {
@@ -16,6 +19,6 @@ export function AppShell({ title = 'CallTelemetry CLI', command, children, onBac
16
19
  onBack();
17
20
  }
18
21
  }, { isActive: Boolean(isComplete && onBack) });
19
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { borderStyle: "single", paddingX: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: title }), breadcrumb && _jsxs(Text, { dimColor: true, children: [" ", breadcrumb] }), logLevel && logLevel !== 'normal' && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(LogLevelBadge, { level: logLevel })] }))] }), command && _jsx(Text, { dimColor: true, children: command })] }), _jsx(Box, { flexDirection: "column", paddingTop: 1, children: children }), isComplete && onBack && (_jsx(Box, { paddingTop: 1, children: _jsx(Text, { dimColor: true, children: "q Back" }) }))] }));
22
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { borderStyle: "single", paddingX: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: title }), breadcrumb && _jsxs(Text, { dimColor: true, children: [" ", breadcrumb] }), logLevel && logLevel !== 'normal' && (_jsxs(_Fragment, { children: [_jsx(Text, { children: " " }), _jsx(LogLevelBadge, { level: logLevel })] }))] }), command && _jsx(Text, { dimColor: true, children: command })] }), _jsx(Box, { flexDirection: "column", paddingTop: 1, children: children }), isComplete && onBack && (_jsx(Box, { paddingTop: 1, children: _jsx(Text, { dimColor: true, children: "q Back" }) })), !hideMetrics && metrics && (_jsx(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, marginTop: 1, children: _jsx(MetricsFooter, { metrics: metrics }) }))] }));
20
23
  }
21
24
  //# sourceMappingURL=AppShell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppShell.js","sourceRoot":"","sources":["../../../src/ui/components/AppShell.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAcnD,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,GAAG,mBAAmB,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,GACM;IACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAE1B,iEAAiE;IACjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1B,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAE/B,gEAAgE;IAChE,QAAQ,CACN,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACb,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YACjD,MAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EACD,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,EAAE,CAC5C,CAAC;IAEF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,MAAC,GAAG,IACF,WAAW,EAAC,QAAQ,EACpB,QAAQ,EAAE,CAAC,EACX,cAAc,EAAC,eAAe,aAE9B,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,MAAM,YAAE,KAAK,GAAQ,EACrC,UAAU,IAAI,MAAC,IAAI,IAAC,QAAQ,yBAAI,UAAU,IAAQ,EAClD,QAAQ,IAAI,QAAQ,KAAK,QAAQ,IAAI,CACpC,8BACE,KAAC,IAAI,oBAAS,EACd,KAAC,aAAa,IAAC,KAAK,EAAE,QAAQ,GAAI,IACjC,CACJ,IACG,EACL,OAAO,IAAI,KAAC,IAAI,IAAC,QAAQ,kBAAE,OAAO,GAAQ,IACvC,EACN,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,UAAU,EAAE,CAAC,YACtC,QAAQ,GACL,EACL,UAAU,IAAI,MAAM,IAAI,CACvB,KAAC,GAAG,IAAC,UAAU,EAAE,CAAC,YAChB,KAAC,IAAI,IAAC,QAAQ,6BAAc,GACxB,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"AppShell.js","sourceRoot":"","sources":["../../../src/ui/components/AppShell.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAgB1D,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,GAAG,mBAAmB,EAC3B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,GACG;IACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,iEAAiE;IACjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1B,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAE/B,gEAAgE;IAChE,QAAQ,CACN,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACb,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YACjD,MAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EACD,EAAE,QAAQ,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,EAAE,CAC5C,CAAC;IAEF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,MAAC,GAAG,IACF,WAAW,EAAC,QAAQ,EACpB,QAAQ,EAAE,CAAC,EACX,cAAc,EAAC,eAAe,aAE9B,MAAC,GAAG,eACF,KAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,MAAM,YAAE,KAAK,GAAQ,EACrC,UAAU,IAAI,MAAC,IAAI,IAAC,QAAQ,yBAAI,UAAU,IAAQ,EAClD,QAAQ,IAAI,QAAQ,KAAK,QAAQ,IAAI,CACpC,8BACE,KAAC,IAAI,oBAAS,EACd,KAAC,aAAa,IAAC,KAAK,EAAE,QAAQ,GAAI,IACjC,CACJ,IACG,EACL,OAAO,IAAI,KAAC,IAAI,IAAC,QAAQ,kBAAE,OAAO,GAAQ,IACvC,EACN,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,UAAU,EAAE,CAAC,YACtC,QAAQ,GACL,EACL,UAAU,IAAI,MAAM,IAAI,CACvB,KAAC,GAAG,IAAC,UAAU,EAAE,CAAC,YAChB,KAAC,IAAI,IAAC,QAAQ,6BAAc,GACxB,CACP,EACA,CAAC,WAAW,IAAI,OAAO,IAAI,CAC1B,KAAC,GAAG,IAAC,WAAW,EAAC,QAAQ,EAAC,WAAW,EAAC,MAAM,EAAC,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,YACpE,KAAC,aAAa,IAAC,OAAO,EAAE,OAAO,GAAI,GAC/B,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SystemMetrics } from '../../lib/system.js';
2
+ interface MetricsFooterProps {
3
+ metrics: SystemMetrics;
4
+ }
5
+ export declare function MetricsFooter({ metrics }: MetricsFooterProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=MetricsFooter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsFooter.d.ts","sourceRoot":"","sources":["../../../src/ui/components/MetricsFooter.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,UAAU,kBAAkB;IAC1B,OAAO,EAAE,aAAa,CAAC;CACxB;AAcD,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,kBAAkB,2CA8D5D"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text, useStdout } from 'ink';
3
+ function barColor(percent) {
4
+ if (percent >= 90)
5
+ return 'red';
6
+ if (percent >= 70)
7
+ return 'yellow';
8
+ return 'green';
9
+ }
10
+ function miniBar(percent, width) {
11
+ const clamped = Math.max(0, Math.min(100, percent));
12
+ const filledCount = Math.round((clamped / 100) * width);
13
+ return { filled: '█'.repeat(filledCount), empty: '░'.repeat(width - filledCount) };
14
+ }
15
+ export function MetricsFooter({ metrics }) {
16
+ const { stdout } = useStdout();
17
+ const width = stdout?.columns ?? 80;
18
+ const barWidth = 10;
19
+ const ramBar = miniBar(metrics.ram.percent, barWidth);
20
+ const diskBar = miniBar(metrics.disk.usedPercent, barWidth);
21
+ const cpuBar = miniBar(metrics.cpu.percent, barWidth);
22
+ const ramColor = barColor(metrics.ram.percent);
23
+ const diskColor = barColor(metrics.disk.usedPercent);
24
+ const cpuColor = barColor(metrics.cpu.percent);
25
+ // Very narrow: percentages only
26
+ if (width < 50) {
27
+ return (_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "RAM " }), _jsxs(Text, { color: ramColor, bold: true, children: [metrics.ram.percent, "%"] }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Disk " }), _jsxs(Text, { color: diskColor, bold: true, children: [metrics.disk.usedPercent, "%"] }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "CPU " }), _jsxs(Text, { color: cpuColor, bold: true, children: [metrics.cpu.percent, "%"] })] }));
28
+ }
29
+ // Narrow: bars + percentages, no detail labels
30
+ if (width < 70) {
31
+ return (_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "RAM " }), _jsx(Text, { color: ramColor, children: ramBar.filled }), _jsx(Text, { dimColor: true, children: ramBar.empty }), _jsxs(Text, { color: ramColor, bold: true, children: [" ", metrics.ram.percent, "%"] }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "Disk " }), _jsx(Text, { color: diskColor, children: diskBar.filled }), _jsx(Text, { dimColor: true, children: diskBar.empty }), _jsxs(Text, { color: diskColor, bold: true, children: [" ", metrics.disk.usedPercent, "%"] }), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "CPU " }), _jsx(Text, { color: cpuColor, children: cpuBar.filled }), _jsx(Text, { dimColor: true, children: cpuBar.empty }), _jsxs(Text, { color: cpuColor, bold: true, children: [" ", metrics.cpu.percent, "%"] })] }));
32
+ }
33
+ // Full: bars + percentages + detail labels
34
+ return (_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "RAM " }), _jsx(Text, { color: ramColor, children: ramBar.filled }), _jsx(Text, { dimColor: true, children: ramBar.empty }), _jsxs(Text, { color: ramColor, bold: true, children: [" ", `${metrics.ram.percent}%`.padEnd(4)] }), _jsxs(Text, { dimColor: true, children: [metrics.ram.label, " "] }), _jsx(Text, { bold: true, children: "Disk " }), _jsx(Text, { color: diskColor, children: diskBar.filled }), _jsx(Text, { dimColor: true, children: diskBar.empty }), _jsxs(Text, { color: diskColor, bold: true, children: [" ", `${metrics.disk.usedPercent}%`.padEnd(4)] }), _jsxs(Text, { dimColor: true, children: [metrics.disk.label, " "] }), _jsx(Text, { bold: true, children: "CPU " }), _jsx(Text, { color: cpuColor, children: cpuBar.filled }), _jsx(Text, { dimColor: true, children: cpuBar.empty }), _jsxs(Text, { color: cpuColor, bold: true, children: [" ", `${metrics.cpu.percent}%`.padEnd(4)] }), _jsx(Text, { dimColor: true, children: metrics.cpu.label })] }));
35
+ }
36
+ //# sourceMappingURL=MetricsFooter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsFooter.js","sourceRoot":"","sources":["../../../src/ui/components/MetricsFooter.tsx"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ export { SelectMenu } from './SelectMenu.js';
14
14
  export type { MenuItem } from '../types.js';
15
15
  export { TextInput } from './TextInput.js';
16
16
  export { MeterBar } from './MeterBar.js';
17
+ export { MetricsFooter } from './MetricsFooter.js';
17
18
  export { LogLevelBadge } from './LogLevelBadge.js';
18
19
  export { ErrorBoundary } from './ErrorBoundary.js';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -13,6 +13,7 @@ export { Divider } from './Divider.js';
13
13
  export { SelectMenu } from './SelectMenu.js';
14
14
  export { TextInput } from './TextInput.js';
15
15
  export { MeterBar } from './MeterBar.js';
16
+ export { MetricsFooter } from './MetricsFooter.js';
16
17
  export { LogLevelBadge } from './LogLevelBadge.js';
17
18
  export { ErrorBoundary } from './ErrorBoundary.js';
18
19
  //# sourceMappingURL=index.js.map