@tpmjs/cli 0.1.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 (97) hide show
  1. package/README.md +127 -0
  2. package/bin/run.js +5 -0
  3. package/dist/commands/agent/chat.d.ts +23 -0
  4. package/dist/commands/agent/chat.js +608 -0
  5. package/dist/commands/agent/chat.js.map +1 -0
  6. package/dist/commands/agent/create.d.ts +22 -0
  7. package/dist/commands/agent/create.js +549 -0
  8. package/dist/commands/agent/create.js.map +1 -0
  9. package/dist/commands/agent/delete.d.ts +19 -0
  10. package/dist/commands/agent/delete.js +529 -0
  11. package/dist/commands/agent/delete.js.map +1 -0
  12. package/dist/commands/agent/list.d.ts +16 -0
  13. package/dist/commands/agent/list.js +535 -0
  14. package/dist/commands/agent/list.js.map +1 -0
  15. package/dist/commands/agent/update.d.ts +25 -0
  16. package/dist/commands/agent/update.js +547 -0
  17. package/dist/commands/agent/update.js.map +1 -0
  18. package/dist/commands/auth/login.d.ts +21 -0
  19. package/dist/commands/auth/login.js +603 -0
  20. package/dist/commands/auth/login.js.map +1 -0
  21. package/dist/commands/auth/logout.d.ts +13 -0
  22. package/dist/commands/auth/logout.js +227 -0
  23. package/dist/commands/auth/logout.js.map +1 -0
  24. package/dist/commands/auth/status.d.ts +14 -0
  25. package/dist/commands/auth/status.js +542 -0
  26. package/dist/commands/auth/status.js.map +1 -0
  27. package/dist/commands/auth/whoami.d.ts +14 -0
  28. package/dist/commands/auth/whoami.js +500 -0
  29. package/dist/commands/auth/whoami.js.map +1 -0
  30. package/dist/commands/collection/add.d.ts +18 -0
  31. package/dist/commands/collection/add.js +509 -0
  32. package/dist/commands/collection/add.js.map +1 -0
  33. package/dist/commands/collection/create.d.ts +17 -0
  34. package/dist/commands/collection/create.js +521 -0
  35. package/dist/commands/collection/create.js.map +1 -0
  36. package/dist/commands/collection/delete.d.ts +19 -0
  37. package/dist/commands/collection/delete.js +531 -0
  38. package/dist/commands/collection/delete.js.map +1 -0
  39. package/dist/commands/collection/import.d.ts +18 -0
  40. package/dist/commands/collection/import.js +546 -0
  41. package/dist/commands/collection/import.js.map +1 -0
  42. package/dist/commands/collection/list.d.ts +16 -0
  43. package/dist/commands/collection/list.js +531 -0
  44. package/dist/commands/collection/list.js.map +1 -0
  45. package/dist/commands/collection/remove.d.ts +18 -0
  46. package/dist/commands/collection/remove.js +501 -0
  47. package/dist/commands/collection/remove.js.map +1 -0
  48. package/dist/commands/collection/update.d.ts +20 -0
  49. package/dist/commands/collection/update.js +522 -0
  50. package/dist/commands/collection/update.js.map +1 -0
  51. package/dist/commands/doctor.d.ts +14 -0
  52. package/dist/commands/doctor.js +592 -0
  53. package/dist/commands/doctor.js.map +1 -0
  54. package/dist/commands/mcp/config.d.ts +19 -0
  55. package/dist/commands/mcp/config.js +265 -0
  56. package/dist/commands/mcp/config.js.map +1 -0
  57. package/dist/commands/mcp/serve.d.ts +23 -0
  58. package/dist/commands/mcp/serve.js +689 -0
  59. package/dist/commands/mcp/serve.js.map +1 -0
  60. package/dist/commands/playground.d.ts +23 -0
  61. package/dist/commands/playground.js +666 -0
  62. package/dist/commands/playground.js.map +1 -0
  63. package/dist/commands/publish/check.d.ts +17 -0
  64. package/dist/commands/publish/check.js +544 -0
  65. package/dist/commands/publish/check.js.map +1 -0
  66. package/dist/commands/publish/preview.d.ts +19 -0
  67. package/dist/commands/publish/preview.js +291 -0
  68. package/dist/commands/publish/preview.js.map +1 -0
  69. package/dist/commands/tool/execute.d.ts +21 -0
  70. package/dist/commands/tool/execute.js +574 -0
  71. package/dist/commands/tool/execute.js.map +1 -0
  72. package/dist/commands/tool/info.d.ts +18 -0
  73. package/dist/commands/tool/info.js +537 -0
  74. package/dist/commands/tool/info.js.map +1 -0
  75. package/dist/commands/tool/init.d.ts +24 -0
  76. package/dist/commands/tool/init.js +461 -0
  77. package/dist/commands/tool/init.js.map +1 -0
  78. package/dist/commands/tool/search.d.ts +20 -0
  79. package/dist/commands/tool/search.js +566 -0
  80. package/dist/commands/tool/search.js.map +1 -0
  81. package/dist/commands/tool/trending.d.ts +15 -0
  82. package/dist/commands/tool/trending.js +523 -0
  83. package/dist/commands/tool/trending.js.map +1 -0
  84. package/dist/commands/tool/validate.d.ts +15 -0
  85. package/dist/commands/tool/validate.js +555 -0
  86. package/dist/commands/tool/validate.js.map +1 -0
  87. package/dist/commands/update.d.ts +15 -0
  88. package/dist/commands/update.js +228 -0
  89. package/dist/commands/update.js.map +1 -0
  90. package/dist/hooks/init.d.ts +5 -0
  91. package/dist/hooks/init.js +8 -0
  92. package/dist/hooks/init.js.map +1 -0
  93. package/dist/index.d.ts +262 -0
  94. package/dist/index.js +473 -0
  95. package/dist/index.js.map +1 -0
  96. package/oclif.manifest.json +1699 -0
  97. package/package.json +104 -0
@@ -0,0 +1,592 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import * as fs from 'fs';
3
+ import * as os from 'os';
4
+ import Conf from 'conf';
5
+ import * as path from 'path';
6
+ import Table from 'cli-table3';
7
+ import ora from 'ora';
8
+ import pc from 'picocolors';
9
+
10
+ // src/commands/doctor.ts
11
+ var CONFIG_DIR = path.join(os.homedir(), ".tpmjs");
12
+ var CREDENTIALS_FILE = path.join(CONFIG_DIR, "credentials.json");
13
+ path.join(CONFIG_DIR, "history");
14
+ function ensureConfigDir() {
15
+ if (!fs.existsSync(CONFIG_DIR)) {
16
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
17
+ }
18
+ }
19
+ var configStore = new Conf({
20
+ projectName: "tpmjs",
21
+ cwd: CONFIG_DIR,
22
+ configName: "config",
23
+ defaults: {
24
+ apiUrl: "https://tpmjs.com/api",
25
+ defaultOutput: "human",
26
+ verbose: false,
27
+ analytics: false
28
+ }
29
+ });
30
+ function getConfig() {
31
+ return configStore.store;
32
+ }
33
+ function getConfigValue(key) {
34
+ return configStore.get(key);
35
+ }
36
+ function loadCredentials() {
37
+ ensureConfigDir();
38
+ if (!fs.existsSync(CREDENTIALS_FILE)) {
39
+ return null;
40
+ }
41
+ try {
42
+ const content = fs.readFileSync(CREDENTIALS_FILE, "utf-8");
43
+ return JSON.parse(content);
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ function hasCredentials() {
49
+ const creds = loadCredentials();
50
+ return creds !== null && !!creds.apiKey;
51
+ }
52
+ function getApiKey() {
53
+ if (process.env.TPMJS_API_KEY) {
54
+ return process.env.TPMJS_API_KEY;
55
+ }
56
+ const creds = loadCredentials();
57
+ if (creds?.apiKey) {
58
+ return creds.apiKey;
59
+ }
60
+ return void 0;
61
+ }
62
+ function getApiUrl() {
63
+ return process.env.TPMJS_API_URL ?? getConfigValue("apiUrl") ?? "https://tpmjs.com/api";
64
+ }
65
+ function getConfigDir() {
66
+ ensureConfigDir();
67
+ return CONFIG_DIR;
68
+ }
69
+
70
+ // src/lib/api-client.ts
71
+ var TpmClient = class {
72
+ baseUrl;
73
+ apiKey;
74
+ timeout;
75
+ constructor(options = {}) {
76
+ this.baseUrl = options.baseUrl ?? getApiUrl();
77
+ this.apiKey = options.apiKey ?? getApiKey();
78
+ this.timeout = options.timeout ?? 3e4;
79
+ }
80
+ async request(endpoint, options = {}) {
81
+ const url = `${this.baseUrl}${endpoint}`;
82
+ const headers = {
83
+ "Content-Type": "application/json",
84
+ ...options.headers
85
+ };
86
+ if (this.apiKey) {
87
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
88
+ }
89
+ const controller = new AbortController();
90
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
91
+ try {
92
+ const response = await fetch(url, {
93
+ ...options,
94
+ headers,
95
+ signal: controller.signal
96
+ });
97
+ const data = await response.json();
98
+ if (!response.ok) {
99
+ throw new ApiError(
100
+ data.message || data.error || `HTTP ${response.status}`,
101
+ response.status,
102
+ data
103
+ );
104
+ }
105
+ return data;
106
+ } finally {
107
+ clearTimeout(timeoutId);
108
+ }
109
+ }
110
+ // Health check
111
+ async health() {
112
+ return this.request("/health");
113
+ }
114
+ // Stats
115
+ async getStats() {
116
+ return this.request("/stats");
117
+ }
118
+ // Tools
119
+ async searchTools(options = {}) {
120
+ const params = new URLSearchParams();
121
+ if (options.query) params.set("q", options.query);
122
+ if (options.category) params.set("category", options.category);
123
+ if (options.limit) params.set("limit", String(options.limit));
124
+ if (options.offset) params.set("offset", String(options.offset));
125
+ const queryString = params.toString();
126
+ const endpoint = queryString ? `/tools?${queryString}` : "/tools";
127
+ return this.request(endpoint);
128
+ }
129
+ async getTool(packageName, toolName) {
130
+ return this.request(`/tools/${encodeURIComponent(packageName)}/${encodeURIComponent(toolName)}`);
131
+ }
132
+ async getToolBySlug(slug) {
133
+ const searchResult = await this.searchTools({ query: slug, limit: 1 });
134
+ if (searchResult.data && searchResult.data.length > 0) {
135
+ const tool = searchResult.data.find((t) => t.slug === slug) || searchResult.data[0];
136
+ return { success: true, data: tool };
137
+ }
138
+ return { success: false, error: "Tool not found" };
139
+ }
140
+ async getTrendingTools(options = {}) {
141
+ const params = new URLSearchParams();
142
+ if (options.limit) params.set("limit", String(options.limit));
143
+ if (options.offset) params.set("offset", String(options.offset));
144
+ const queryString = params.toString();
145
+ const endpoint = queryString ? `/tools/trending?${queryString}` : "/tools/trending";
146
+ return this.request(endpoint);
147
+ }
148
+ async validateTpmjsField(field) {
149
+ return this.request("/tools/validate", {
150
+ method: "POST",
151
+ body: JSON.stringify(field)
152
+ });
153
+ }
154
+ async executeTool(slug, params) {
155
+ return this.request(`/tools/${encodeURIComponent(slug)}/execute`, {
156
+ method: "POST",
157
+ body: JSON.stringify(params)
158
+ });
159
+ }
160
+ async *executeToolStream(slug, params) {
161
+ const url = `${this.baseUrl}/tools/${encodeURIComponent(slug)}/execute`;
162
+ const headers = {
163
+ "Content-Type": "application/json",
164
+ "Accept": "text/event-stream"
165
+ };
166
+ if (this.apiKey) {
167
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
168
+ }
169
+ const response = await fetch(url, {
170
+ method: "POST",
171
+ headers,
172
+ body: JSON.stringify({ ...params, stream: true })
173
+ });
174
+ if (!response.ok) {
175
+ const errorText = await response.text();
176
+ throw new ApiError(errorText || `HTTP ${response.status}`, response.status);
177
+ }
178
+ if (!response.body) {
179
+ throw new ApiError("No response body", 0);
180
+ }
181
+ const reader = response.body.getReader();
182
+ const decoder = new TextDecoder();
183
+ let buffer = "";
184
+ try {
185
+ while (true) {
186
+ const { done, value } = await reader.read();
187
+ if (done) {
188
+ yield { type: "done", data: "" };
189
+ break;
190
+ }
191
+ buffer += decoder.decode(value, { stream: true });
192
+ const lines = buffer.split("\n");
193
+ buffer = lines.pop() ?? "";
194
+ for (const line of lines) {
195
+ if (line.startsWith("data: ")) {
196
+ const data = line.slice(6);
197
+ if (data === "[DONE]") {
198
+ yield { type: "done", data: "" };
199
+ return;
200
+ }
201
+ try {
202
+ const parsed = JSON.parse(data);
203
+ yield { type: parsed.type || "text", data: parsed.content || parsed.data || data };
204
+ } catch {
205
+ yield { type: "text", data };
206
+ }
207
+ }
208
+ }
209
+ }
210
+ } finally {
211
+ reader.releaseLock();
212
+ }
213
+ }
214
+ // Agents
215
+ async listAgents(options = {}) {
216
+ const params = new URLSearchParams();
217
+ if (options.limit) params.set("limit", String(options.limit));
218
+ if (options.offset) params.set("offset", String(options.offset));
219
+ const queryString = params.toString();
220
+ const endpoint = queryString ? `/agents?${queryString}` : "/agents";
221
+ return this.request(endpoint);
222
+ }
223
+ async getAgent(id) {
224
+ return this.request(`/agents/${id}`);
225
+ }
226
+ async createAgent(input) {
227
+ return this.request("/agents", {
228
+ method: "POST",
229
+ body: JSON.stringify(input)
230
+ });
231
+ }
232
+ async updateAgent(id, input) {
233
+ return this.request(`/agents/${id}`, {
234
+ method: "PATCH",
235
+ body: JSON.stringify(input)
236
+ });
237
+ }
238
+ async deleteAgent(id) {
239
+ return this.request(`/agents/${id}`, {
240
+ method: "DELETE"
241
+ });
242
+ }
243
+ // Collections
244
+ async listCollections(options = {}) {
245
+ const params = new URLSearchParams();
246
+ if (options.limit) params.set("limit", String(options.limit));
247
+ if (options.offset) params.set("offset", String(options.offset));
248
+ const queryString = params.toString();
249
+ const endpoint = queryString ? `/collections?${queryString}` : "/collections";
250
+ return this.request(endpoint);
251
+ }
252
+ async getCollection(id) {
253
+ return this.request(`/collections/${id}`);
254
+ }
255
+ async createCollection(input) {
256
+ return this.request("/collections", {
257
+ method: "POST",
258
+ body: JSON.stringify(input)
259
+ });
260
+ }
261
+ async updateCollection(id, input) {
262
+ return this.request(`/collections/${id}`, {
263
+ method: "PATCH",
264
+ body: JSON.stringify(input)
265
+ });
266
+ }
267
+ async deleteCollection(id) {
268
+ return this.request(`/collections/${id}`, {
269
+ method: "DELETE"
270
+ });
271
+ }
272
+ async addToolsToCollection(id, toolIds) {
273
+ for (const toolId of toolIds) {
274
+ await this.request(`/collections/${id}/tools/${toolId}`, {
275
+ method: "POST"
276
+ });
277
+ }
278
+ return { success: true };
279
+ }
280
+ async removeToolFromCollection(id, toolId) {
281
+ return this.request(`/collections/${id}/tools/${toolId}`, {
282
+ method: "DELETE"
283
+ });
284
+ }
285
+ // User
286
+ async whoami() {
287
+ return this.request("/user/profile");
288
+ }
289
+ async listApiKeys() {
290
+ return this.request("/user/tpmjs-api-keys");
291
+ }
292
+ // Check if authenticated
293
+ isAuthenticated() {
294
+ return !!this.apiKey;
295
+ }
296
+ };
297
+ var ApiError = class extends Error {
298
+ constructor(message, statusCode, data) {
299
+ super(message);
300
+ this.statusCode = statusCode;
301
+ this.data = data;
302
+ this.name = "ApiError";
303
+ }
304
+ };
305
+ var OutputFormatter = class {
306
+ options;
307
+ constructor(options = {}) {
308
+ this.options = options;
309
+ }
310
+ // Output as JSON
311
+ json(data) {
312
+ console.log(JSON.stringify(data, null, 2));
313
+ }
314
+ // Output a table
315
+ table(data, columns) {
316
+ if (this.options.json) {
317
+ this.json(data);
318
+ return;
319
+ }
320
+ const table = new Table({
321
+ head: columns.map((col) => pc.bold(col.header)),
322
+ colWidths: columns.map((col) => col.width ?? null),
323
+ style: {
324
+ head: [],
325
+ border: []
326
+ }
327
+ });
328
+ for (const row of data) {
329
+ table.push(columns.map((col) => String(row[col.key] ?? "")));
330
+ }
331
+ console.log(table.toString());
332
+ }
333
+ // Success message
334
+ success(message) {
335
+ if (this.options.json) return;
336
+ console.log(pc.green("\u2713"), message);
337
+ }
338
+ // Error message
339
+ error(message, details) {
340
+ if (this.options.json) {
341
+ this.json({ error: message, details });
342
+ return;
343
+ }
344
+ console.error(pc.red("\u2717"), message);
345
+ if (details && this.options.verbose) {
346
+ console.error(pc.dim(details));
347
+ }
348
+ }
349
+ // Warning message
350
+ warning(message) {
351
+ if (this.options.json) return;
352
+ console.log(pc.yellow("\u26A0"), message);
353
+ }
354
+ // Info message
355
+ info(message) {
356
+ if (this.options.json) return;
357
+ console.log(pc.blue("\u2139"), message);
358
+ }
359
+ // Debug message (only in verbose mode)
360
+ debug(message) {
361
+ if (this.options.json) return;
362
+ if (this.options.verbose) {
363
+ console.log(pc.dim(`[debug] ${message}`));
364
+ }
365
+ }
366
+ // Plain text output
367
+ text(message) {
368
+ if (this.options.json) return;
369
+ console.log(message);
370
+ }
371
+ // Heading
372
+ heading(text) {
373
+ if (this.options.json) return;
374
+ console.log();
375
+ console.log(pc.bold(pc.underline(text)));
376
+ console.log();
377
+ }
378
+ // Subheading
379
+ subheading(text) {
380
+ if (this.options.json) return;
381
+ console.log(pc.bold(text));
382
+ }
383
+ // Key-value pair
384
+ keyValue(key, value) {
385
+ if (this.options.json) return;
386
+ console.log(`${pc.dim(key + ":")} ${value ?? pc.dim("(not set)")}`);
387
+ }
388
+ // List item
389
+ listItem(text, indent = 0) {
390
+ if (this.options.json) return;
391
+ const prefix = " ".repeat(indent) + "\u2022";
392
+ console.log(`${prefix} ${text}`);
393
+ }
394
+ // Spinner
395
+ spinner(message) {
396
+ return ora({
397
+ text: message,
398
+ isSilent: this.options.json
399
+ }).start();
400
+ }
401
+ // Blank line
402
+ newLine() {
403
+ if (this.options.json) return;
404
+ console.log();
405
+ }
406
+ // Horizontal rule
407
+ hr() {
408
+ if (this.options.json) return;
409
+ console.log(pc.dim("\u2500".repeat(50)));
410
+ }
411
+ // Alias for hr
412
+ divider() {
413
+ this.hr();
414
+ }
415
+ // Code block
416
+ code(text, language) {
417
+ if (this.options.json) {
418
+ this.json({ code: text, language });
419
+ return;
420
+ }
421
+ console.log(pc.dim("```" + (language ?? "")));
422
+ console.log(text);
423
+ console.log(pc.dim("```"));
424
+ }
425
+ // Highlight text
426
+ highlight(text) {
427
+ return pc.cyan(text);
428
+ }
429
+ // Dim text
430
+ dim(text) {
431
+ return pc.dim(text);
432
+ }
433
+ // Bold text
434
+ bold(text) {
435
+ return pc.bold(text);
436
+ }
437
+ // Link (just returns text in terminal)
438
+ link(text, url) {
439
+ return `\x1B]8;;${url}\x07${pc.underline(pc.blue(text))}\x1B]8;;\x07`;
440
+ }
441
+ };
442
+ function createOutput(flags) {
443
+ return new OutputFormatter({
444
+ json: flags.json,
445
+ verbose: flags.verbose
446
+ });
447
+ }
448
+
449
+ // src/commands/doctor.ts
450
+ var Doctor = class _Doctor extends Command {
451
+ static description = "Run diagnostic checks for TPMJS CLI";
452
+ static examples = ["<%= config.bin %> <%= command.id %>"];
453
+ static flags = {
454
+ json: Flags.boolean({
455
+ description: "Output in JSON format",
456
+ default: false
457
+ }),
458
+ verbose: Flags.boolean({
459
+ char: "v",
460
+ description: "Show verbose output",
461
+ default: false
462
+ })
463
+ };
464
+ async run() {
465
+ const { flags } = await this.parse(_Doctor);
466
+ const output = createOutput(flags);
467
+ const checks = [];
468
+ output.heading("TPMJS CLI Diagnostics");
469
+ const nodeVersion = process.version;
470
+ const nodeVersionNum = parseInt(nodeVersion.slice(1).split(".")[0] ?? "0", 10);
471
+ checks.push({
472
+ name: "Node.js Version",
473
+ status: nodeVersionNum >= 18 ? "ok" : "error",
474
+ message: nodeVersion,
475
+ details: nodeVersionNum < 18 ? "Node.js 18+ is required" : void 0
476
+ });
477
+ const configDir = getConfigDir();
478
+ const configExists = fs.existsSync(configDir);
479
+ checks.push({
480
+ name: "Config Directory",
481
+ status: configExists ? "ok" : "warning",
482
+ message: configDir,
483
+ details: configExists ? void 0 : "Config directory will be created on first use"
484
+ });
485
+ const hasAuth = hasCredentials() || !!process.env.TPMJS_API_KEY;
486
+ const authSource = process.env.TPMJS_API_KEY ? "environment" : hasCredentials() ? "config file" : "none";
487
+ checks.push({
488
+ name: "Authentication",
489
+ status: hasAuth ? "ok" : "warning",
490
+ message: hasAuth ? `Configured via ${authSource}` : "Not configured",
491
+ details: hasAuth ? void 0 : "Run `tpm auth login` to authenticate"
492
+ });
493
+ const apiUrl = getApiUrl();
494
+ try {
495
+ const client = new TpmClient();
496
+ const healthResponse = await client.health();
497
+ checks.push({
498
+ name: "API Connectivity",
499
+ status: "ok",
500
+ message: `Connected to ${apiUrl}`,
501
+ details: `Server status: ${healthResponse.status}`
502
+ });
503
+ } catch (error) {
504
+ checks.push({
505
+ name: "API Connectivity",
506
+ status: "error",
507
+ message: `Cannot connect to ${apiUrl}`,
508
+ details: error instanceof Error ? error.message : "Unknown error"
509
+ });
510
+ }
511
+ if (hasAuth) {
512
+ const apiKey = getApiKey();
513
+ if (apiKey) {
514
+ try {
515
+ const client = new TpmClient({ apiKey });
516
+ const whoamiResponse = await client.whoami();
517
+ if (whoamiResponse.success && whoamiResponse.data) {
518
+ checks.push({
519
+ name: "API Authentication",
520
+ status: "ok",
521
+ message: `Authenticated as ${whoamiResponse.data.email}`
522
+ });
523
+ } else {
524
+ checks.push({
525
+ name: "API Authentication",
526
+ status: "error",
527
+ message: "API key is invalid",
528
+ details: "Run `tpm auth login` to re-authenticate"
529
+ });
530
+ }
531
+ } catch (error) {
532
+ checks.push({
533
+ name: "API Authentication",
534
+ status: "error",
535
+ message: "Failed to verify API key",
536
+ details: error instanceof Error ? error.message : "Unknown error"
537
+ });
538
+ }
539
+ }
540
+ }
541
+ const config = getConfig();
542
+ checks.push({
543
+ name: "Configuration",
544
+ status: "ok",
545
+ message: "Loaded",
546
+ details: flags.verbose ? JSON.stringify(config, null, 2) : void 0
547
+ });
548
+ try {
549
+ const homeDir = os.homedir();
550
+ const stats = fs.statfsSync(homeDir);
551
+ const freeSpaceBytes = stats.bavail * stats.bsize;
552
+ const freeSpaceMB = Math.floor(freeSpaceBytes / (1024 * 1024));
553
+ checks.push({
554
+ name: "Disk Space",
555
+ status: freeSpaceMB > 100 ? "ok" : "warning",
556
+ message: `${freeSpaceMB} MB available`,
557
+ details: freeSpaceMB <= 100 ? "Low disk space may cause issues" : void 0
558
+ });
559
+ } catch {
560
+ }
561
+ if (flags.json) {
562
+ const summary = {
563
+ ok: checks.filter((c) => c.status === "ok").length,
564
+ warnings: checks.filter((c) => c.status === "warning").length,
565
+ errors: checks.filter((c) => c.status === "error").length
566
+ };
567
+ output.json({ checks, summary });
568
+ return;
569
+ }
570
+ for (const check of checks) {
571
+ const icon = check.status === "ok" ? "\u2713" : check.status === "warning" ? "\u26A0" : "\u2717";
572
+ output.text(`${icon} ${output.bold(check.name)}: ${check.message}`);
573
+ if (check.details && (flags.verbose || check.status !== "ok")) {
574
+ output.text(` ${output.dim(check.details)}`);
575
+ }
576
+ }
577
+ output.newLine();
578
+ const errorCount = checks.filter((c) => c.status === "error").length;
579
+ const warningCount = checks.filter((c) => c.status === "warning").length;
580
+ if (errorCount > 0) {
581
+ output.error(`${errorCount} error(s) found`);
582
+ } else if (warningCount > 0) {
583
+ output.warning(`${warningCount} warning(s) found`);
584
+ } else {
585
+ output.success("All checks passed");
586
+ }
587
+ }
588
+ };
589
+
590
+ export { Doctor as default };
591
+ //# sourceMappingURL=doctor.js.map
592
+ //# sourceMappingURL=doctor.js.map