@krishivpb60/aether-ai-cli 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cli.js CHANGED
@@ -210,6 +210,16 @@ export function createCLI(argv) {
210
210
  await handleCommit();
211
211
  });
212
212
 
213
+ // ── Dashboard Command ───────────────────────────────────
214
+ program
215
+ .command("dashboard")
216
+ .alias("telemetry")
217
+ .description("Launch visual telemetry dashboard HUD in browser")
218
+ .option("-p, --port <port>", "Port to run the dashboard server on", "5050")
219
+ .action(async (opts) => {
220
+ await handleDashboard(opts);
221
+ });
222
+
213
223
  // ── Default: Show help ──────────────────────────────────
214
224
  program.action(() => {
215
225
  showMiniBanner();
@@ -775,3 +785,24 @@ function handleThemesList() {
775
785
  }
776
786
  console.log("");
777
787
  }
788
+
789
+ async function handleDashboard(opts) {
790
+ const { startTelemetryServer, openBrowser } = await import("./telemetry-server.js");
791
+ const parsedPort = parseInt(opts.port, 10) || 5050;
792
+
793
+ console.log("");
794
+ console.log(label.system + " " + colors.brand("Initializing Aether Visual Telemetry HUD..."));
795
+
796
+ try {
797
+ const { port } = await startTelemetryServer(parsedPort);
798
+ const url = `http://localhost:${port}`;
799
+ console.log(" " + colors.success(`✓ Telemetry Server active at ${colors.accent(url)}`));
800
+ console.log(" " + colors.muted("Press Ctrl+C to terminate dashboard server."));
801
+ console.log("");
802
+
803
+ openBrowser(url);
804
+ } catch (err) {
805
+ console.log("\n" + label.error + " " + colors.danger(`Failed to start telemetry server: ${err.message}\n`));
806
+ process.exit(1);
807
+ }
808
+ }
@@ -0,0 +1,112 @@
1
+ // ═══════════════════════════════════════════════════════════
2
+ // AETHER AI CLI — Cyberpunk Web Telemetry Dashboard Server
3
+ // Lightweight server using node:http to host dashboard diagnostics
4
+ // ═══════════════════════════════════════════════════════════
5
+
6
+ import http from "node:http";
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import { getTelemetryData } from "./ai/telemetry.js";
11
+ import { getAIConfig } from "./config.js";
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ let server = null;
17
+ let currentPort = 4567;
18
+
19
+ /**
20
+ * Starts the telemetry HTTP server.
21
+ * If the preferred port is occupied, automatically increments and tries the next port.
22
+ * @param {number} preferredPort
23
+ * @returns {Promise<{ port: number, server: http.Server }>}
24
+ */
25
+ export async function startDashboardServer(preferredPort = 4567) {
26
+ return new Promise((resolve, reject) => {
27
+ let port = preferredPort;
28
+
29
+ function attemptListen() {
30
+ server = http.createServer(async (req, res) => {
31
+ const url = new URL(req.url, `http://${req.headers.host}`);
32
+
33
+ // CORS headers
34
+ res.setHeader("Access-Control-Allow-Origin", "*");
35
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
36
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
37
+
38
+ if (req.method === "OPTIONS") {
39
+ res.writeHead(200);
40
+ res.end();
41
+ return;
42
+ }
43
+
44
+ // Serve HTML dashboard
45
+ if (url.pathname === "/" || url.pathname === "/index.html") {
46
+ try {
47
+ const htmlPath = path.join(__dirname, "ui", "dashboard.html");
48
+ const html = fs.readFileSync(htmlPath, "utf8");
49
+ res.writeHead(200, { "Content-Type": "text/html" });
50
+ res.end(html);
51
+ } catch (err) {
52
+ res.writeHead(500, { "Content-Type": "text/plain" });
53
+ res.end("Error loading telemetry dashboard UI: " + err.message);
54
+ }
55
+ return;
56
+ }
57
+
58
+ // API Endpoint: /api/telemetry
59
+ if (url.pathname === "/api/telemetry") {
60
+ try {
61
+ const config = await getAIConfig();
62
+ const data = getTelemetryData(config);
63
+ res.writeHead(200, { "Content-Type": "application/json" });
64
+ res.end(JSON.stringify(data));
65
+ } catch (err) {
66
+ res.writeHead(500, { "Content-Type": "application/json" });
67
+ res.end(JSON.stringify({ error: err.message }));
68
+ }
69
+ return;
70
+ }
71
+
72
+ // Default 404
73
+ res.writeHead(404, { "Content-Type": "text/plain" });
74
+ res.end("Not Found");
75
+ });
76
+
77
+ server.on("error", (err) => {
78
+ if (err.code === "EADDRINUSE") {
79
+ port++;
80
+ attemptListen();
81
+ } else {
82
+ reject(err);
83
+ }
84
+ });
85
+
86
+ server.listen(port, () => {
87
+ currentPort = port;
88
+ resolve({ port, server });
89
+ });
90
+ }
91
+
92
+ attemptListen();
93
+ });
94
+ }
95
+
96
+ /**
97
+ * Stops the dashboard server if active.
98
+ */
99
+ export function stopDashboardServer() {
100
+ if (server) {
101
+ server.close();
102
+ server = null;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Gets the active port.
108
+ * @returns {number}
109
+ */
110
+ export function getDashboardPort() {
111
+ return currentPort;
112
+ }