@krishivpb60/aether-ai-cli 1.3.4 → 1.3.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.
@@ -0,0 +1,91 @@
1
+ import { test, before, after } from "node:test";
2
+ import assert from "node:assert";
3
+ import { join } from "node:path";
4
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
5
+
6
+ const tempHome = join(process.cwd(), "temp-test-home-autopilot");
7
+ process.env.USERPROFILE = tempHome;
8
+ process.env.HOME = tempHome;
9
+ process.env.NODE_ENV = "test";
10
+
11
+ const originalFetch = globalThis.fetch;
12
+ const { handleAutopilotDebug } = await import("../src/chat.js");
13
+
14
+ test("Autopilot Self-Correcting Debug Suite", async (t) => {
15
+ before(() => {
16
+ mkdirSync(tempHome, { recursive: true });
17
+ });
18
+
19
+ after(() => {
20
+ rmSync(tempHome, { recursive: true, force: true });
21
+ globalThis.fetch = originalFetch;
22
+ });
23
+
24
+ await t.test("handleAutopilotDebug stops immediately if test command passes", async () => {
25
+ const ctx = {
26
+ aiConfig: { DIAGNOSE_CMD: "node -e \"process.exit(0)\"" },
27
+ rl: { pause: () => {}, resume: () => {} },
28
+ history: [],
29
+ currentMode: { name: "titan" }
30
+ };
31
+
32
+ let logged = [];
33
+ const origLog = console.log;
34
+ console.log = (m) => logged.push(m);
35
+
36
+ try {
37
+ await handleAutopilotDebug("node -e \"process.exit(0)\"", ctx);
38
+
39
+ const hasSuccess = logged.some(l => l && l.includes("passed successfully"));
40
+ assert.ok(hasSuccess);
41
+ } finally {
42
+ console.log = origLog;
43
+ }
44
+ });
45
+
46
+ await t.test("handleAutopilotDebug enters loop, applies write fix, and passes", async () => {
47
+ // We will run a command that checks for the existence of a file we write.
48
+ // If the file exists, it passes; if not, it fails.
49
+ const checkFile = join(tempHome, "fix.txt");
50
+ const testCmd = `node -e "const fs = require('fs'); if (fs.existsSync('${checkFile.replace(/\\/g, '\\\\')}')) { process.exit(0); } else { process.exit(1); }"`;
51
+
52
+ // Mock fetch to simulate AI response writing the file
53
+ globalThis.fetch = async (url, options) => {
54
+ // Simulate writing fix.txt using write block
55
+ return {
56
+ ok: true,
57
+ json: async () => ({
58
+ choices: [{
59
+ message: {
60
+ content: `Let me fix this by writing the missing file.\n[WRITE_FILE: ${checkFile}]\nfixed content\n[END_WRITE]`
61
+ }
62
+ }]
63
+ })
64
+ };
65
+ };
66
+
67
+ const ctx = {
68
+ aiConfig: {
69
+ GROQ_API_KEY: "mock-key",
70
+ AUTOPILOT: "machine"
71
+ },
72
+ rl: { pause: () => {}, resume: () => {} },
73
+ history: [],
74
+ currentMode: { name: "titan" }
75
+ };
76
+
77
+ let logged = [];
78
+ const origLog = console.log;
79
+ console.log = (m) => logged.push(m);
80
+
81
+ try {
82
+ await handleAutopilotDebug(testCmd, ctx);
83
+
84
+ // The test command should succeed on the second attempt
85
+ const hasCorrectedSuccess = logged.some(l => l && l.includes("Diagnostics passed successfully"));
86
+ assert.ok(hasCorrectedSuccess);
87
+ } finally {
88
+ console.log = origLog;
89
+ }
90
+ });
91
+ });
@@ -0,0 +1,94 @@
1
+ import { test, before, after } from "node:test";
2
+ import assert from "node:assert";
3
+ import { tmpdir } from "node:os";
4
+
5
+ // Stub only setRawMode globally for handleGitTUI to prevent crashes in non-TTY environments
6
+ const origSetRawMode = process.stdin.setRawMode;
7
+ process.stdin.setRawMode = () => {};
8
+
9
+ const originalCwd = process.cwd();
10
+ const nonGitDir = tmpdir();
11
+
12
+ // We import handleGitTUI
13
+ const { handleGitTUI } = await import("../src/chat.js");
14
+
15
+ test("Git TUI Suite", async (t) => {
16
+ after(() => {
17
+ // Restore Cwd and stdin setRawMode stub
18
+ process.chdir(originalCwd);
19
+ process.stdin.setRawMode = origSetRawMode;
20
+ if (typeof process.stdin.unref === "function") {
21
+ process.stdin.unref();
22
+ }
23
+ });
24
+
25
+ await t.test("handleGitTUI fails gracefully outside git repository", async () => {
26
+ let logged = [];
27
+ const origLog = console.log;
28
+ console.log = (m) => logged.push(m);
29
+
30
+ // Force git commands to fail by pointing GIT_DIR to a non-existent directory
31
+ const oldGitDir = process.env.GIT_DIR;
32
+ process.env.GIT_DIR = "C:\\non_existent_directory_xxx";
33
+
34
+ try {
35
+ await handleGitTUI({});
36
+ const hasErrorMsg = logged.some(l => l && l.includes("Not a git repository"));
37
+ assert.ok(hasErrorMsg);
38
+ } catch (err) {
39
+ console.error("SUBTEST 1 ERROR:", err);
40
+ throw err;
41
+ } finally {
42
+ console.log = origLog;
43
+ if (oldGitDir === undefined) {
44
+ delete process.env.GIT_DIR;
45
+ } else {
46
+ process.env.GIT_DIR = oldGitDir;
47
+ }
48
+ }
49
+ });
50
+
51
+ await t.test("handleGitTUI renders commit graph and parsed files status correctly", async () => {
52
+ let logged = [];
53
+ const origLog = console.log;
54
+ console.log = (m) => logged.push(m);
55
+
56
+ const origWrite = process.stdout.write;
57
+ let written = [];
58
+ process.stdout.write = (chunk) => {
59
+ written.push(chunk);
60
+ return true;
61
+ };
62
+
63
+ const ctx = {
64
+ rl: { pause: () => {}, resume: () => {} }
65
+ };
66
+
67
+ try {
68
+ const initialCount = process.stdin.listeners("data").length;
69
+ const p = handleGitTUI(ctx);
70
+
71
+ // Poll until handleGitTUI registers its data listener on stdin (increases listener count)
72
+ while (process.stdin.listeners("data").length <= initialCount) {
73
+ await new Promise(resolve => setTimeout(resolve, 10));
74
+ }
75
+
76
+ // Trigger ESC/Q keypress on stdin to quit the TUI loop immediately
77
+ process.stdin.emit("data", "q");
78
+
79
+ await p;
80
+
81
+ const fullOutput = written.join("");
82
+ assert.ok(fullOutput.includes("🌿 AETHER INTERACTIVE GIT TUI"));
83
+ assert.ok(fullOutput.includes("Commit Graph & History:"));
84
+ assert.ok(fullOutput.includes("Modified Files:"));
85
+ assert.ok(fullOutput.includes("Hotkeys:"));
86
+ } catch (err) {
87
+ console.error("SUBTEST 2 ERROR:", err);
88
+ throw err;
89
+ } finally {
90
+ console.log = origLog;
91
+ process.stdout.write = origWrite;
92
+ }
93
+ });
94
+ });
@@ -0,0 +1,104 @@
1
+ import { test, before, after } from "node:test";
2
+ import assert from "node:assert";
3
+ import { join } from "node:path";
4
+ import { mkdir, rm } from "node:fs/promises";
5
+
6
+ // Redirect homedir for testing
7
+ const tempHome = join(process.cwd(), "temp-test-home-telemetry");
8
+ process.env.USERPROFILE = tempHome;
9
+ process.env.HOME = tempHome;
10
+ process.env.NODE_ENV = "test";
11
+
12
+ const { recordLatency, getLatencyLogs, clearTelemetryLogs, getTelemetryData } = await import("../src/ai/telemetry.js");
13
+ const { startTelemetryServer } = await import("../src/telemetry-server.js");
14
+
15
+ test("Visual Telemetry and Dashboard Suite", async (t) => {
16
+ before(async () => {
17
+ await mkdir(tempHome, { recursive: true });
18
+ });
19
+
20
+ after(async () => {
21
+ await rm(tempHome, { recursive: true, force: true });
22
+ });
23
+
24
+ await t.test("recordLatency saves metrics to memory and disk, getLatencyLogs returns them", () => {
25
+ clearTelemetryLogs();
26
+
27
+ assert.strictEqual(getLatencyLogs().length, 0);
28
+
29
+ recordLatency("openai", "gpt-4o", 150, 20, 15, true);
30
+ recordLatency("google", "gemini-1.5", 300, 30, 25, false);
31
+
32
+ const logs = getLatencyLogs();
33
+ assert.strictEqual(logs.length, 2);
34
+
35
+ assert.strictEqual(logs[0].provider, "openai");
36
+ assert.strictEqual(logs[0].model, "gpt-4o");
37
+ assert.strictEqual(logs[0].latencyMs, 150);
38
+ assert.strictEqual(logs[0].promptTokens, 20);
39
+ assert.strictEqual(logs[0].completionTokens, 15);
40
+ assert.strictEqual(logs[0].success, true);
41
+
42
+ assert.strictEqual(logs[1].provider, "google");
43
+ assert.strictEqual(logs[1].success, false);
44
+ });
45
+
46
+ await t.test("clearTelemetryLogs clears all saved logs", () => {
47
+ assert.ok(getLatencyLogs().length > 0);
48
+ clearTelemetryLogs();
49
+ assert.strictEqual(getLatencyLogs().length, 0);
50
+ });
51
+
52
+ await t.test("getTelemetryData returns structured data for visual HUD", () => {
53
+ clearTelemetryLogs();
54
+ recordLatency("groq", "llama-3", 100, 10, 5, true);
55
+
56
+ const data = getTelemetryData({ GROQ_API_KEY: "fake-key" });
57
+
58
+ assert.ok(data.tokenStats);
59
+ assert.ok(data.modelBreakdown);
60
+ assert.strictEqual(data.latencyLogs.length, 1);
61
+ assert.strictEqual(data.latencyLogs[0].provider, "groq");
62
+
63
+ // Mesh structure verification
64
+ assert.ok(Array.isArray(data.meshStructure));
65
+ const groqItem = data.meshStructure.find(m => m.id === "groq");
66
+ assert.ok(groqItem);
67
+ assert.strictEqual(groqItem.configured, true);
68
+ });
69
+
70
+ await t.test("startTelemetryServer serves HTTP endpoints correctly", async () => {
71
+ const { server, port } = await startTelemetryServer(5500);
72
+ const baseUrl = `http://localhost:${port}`;
73
+
74
+ try {
75
+ // 1. Fetch dashboard HTML
76
+ const htmlRes = await fetch(`${baseUrl}/`);
77
+ assert.strictEqual(htmlRes.status, 200);
78
+ const htmlText = await htmlRes.text();
79
+ assert.ok(htmlText.includes("Telemetry HUD"));
80
+
81
+ // 2. Fetch telemetry JSON API
82
+ const apiRes = await fetch(`${baseUrl}/api/telemetry`);
83
+ assert.strictEqual(apiRes.status, 200);
84
+ const apiData = await apiRes.json();
85
+ assert.ok(apiData.latencyLogs);
86
+ assert.ok(apiData.meshStructure);
87
+
88
+ // 3. POST clear logs API
89
+ const clearRes = await fetch(`${baseUrl}/api/clear`, { method: "POST" });
90
+ assert.strictEqual(clearRes.status, 200);
91
+ const clearData = await clearRes.json();
92
+ assert.strictEqual(clearData.success, true);
93
+ assert.strictEqual(getLatencyLogs().length, 0);
94
+
95
+ // 4. POST shutdown server API
96
+ const shutdownRes = await fetch(`${baseUrl}/api/shutdown`, { method: "POST" });
97
+ assert.strictEqual(shutdownRes.status, 200);
98
+ const shutdownData = await shutdownRes.json();
99
+ assert.strictEqual(shutdownData.success, true);
100
+ } finally {
101
+ server.close();
102
+ }
103
+ });
104
+ });