aether-code 0.33.2 → 0.33.4
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/bin/aether-code.js +1 -1
- package/package.json +1 -1
- package/src/box-input.js +14 -13
- package/src/repl.js +37 -35
package/bin/aether-code.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
import readline from "node:readline";
|
|
29
29
|
import { c, errorLine, divider, setTerminalTitle } from "../src/render.js";
|
|
30
30
|
|
|
31
|
-
const VERSION = "0.33.
|
|
31
|
+
const VERSION = "0.33.4";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Try to start MCP servers from ~/.aether/mcp.json. Returns a started
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aether-code",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.4",
|
|
4
4
|
"description": "Uncensored AI coding agent for your terminal — Claude Code alternative with MCP support. Reads code, writes files, runs commands. Drives IDA Pro, Roblox Studio, Wireshark, Blender, and any MCP server. No refusal layer.",
|
|
5
5
|
"homepage": "https://trynoguard.com",
|
|
6
6
|
"repository": {
|
package/src/box-input.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Minimal prompt input — raw-mode, cmd.exe-safe.
|
|
2
|
-
//
|
|
2
|
+
// Bare "> " prompt with bottom status bar, matching Claude Code's layout.
|
|
3
3
|
//
|
|
4
4
|
// Features:
|
|
5
5
|
// - Ctrl+V / Alt+V: paste image from clipboard
|
|
@@ -23,7 +23,6 @@ const HIDE = "\x1b[?25l";
|
|
|
23
23
|
const SHOW = "\x1b[?25h";
|
|
24
24
|
const INV = (s) => `\x1b[7m${s}\x1b[27m`;
|
|
25
25
|
|
|
26
|
-
// Save clipboard image to a temp file. Returns the file path or null.
|
|
27
26
|
function grabClipboardImage() {
|
|
28
27
|
const tmpFile = path.join(os.tmpdir(), `aether-paste-${Date.now()}.png`);
|
|
29
28
|
|
|
@@ -62,7 +61,7 @@ function grabClipboardImage() {
|
|
|
62
61
|
return null;
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
export function promptBox({ history = [], placeholder = "Message Aether
|
|
64
|
+
export function promptBox({ history = [], placeholder = "Message Aether...", mode = "review" } = {}) {
|
|
66
65
|
return new Promise((resolve) => {
|
|
67
66
|
if (!process.stdin.isTTY) {
|
|
68
67
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -79,16 +78,15 @@ export function promptBox({ history = [], placeholder = "Message Aether…" } =
|
|
|
79
78
|
let lastSigint = 0;
|
|
80
79
|
const clipImages = [];
|
|
81
80
|
|
|
82
|
-
const termW = () => Math.max(30, (process.stdout.columns || 80) -
|
|
81
|
+
const termW = () => Math.max(30, (process.stdout.columns || 80) - 2);
|
|
83
82
|
|
|
84
83
|
const draw = (first) => {
|
|
85
84
|
const W = termW();
|
|
86
85
|
if (!first) process.stdout.write(`\x1b[${drawn}A`);
|
|
87
86
|
process.stdout.write("\x1b[J");
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
const prefixLen = 2; // "> " visible chars
|
|
88
|
+
const prefixStr = "> ";
|
|
89
|
+
const prefixLen = 2;
|
|
92
90
|
const maxVisible = W - prefixLen;
|
|
93
91
|
const start = pos > maxVisible ? pos - maxVisible : 0;
|
|
94
92
|
const view = buf.slice(start, start + maxVisible);
|
|
@@ -112,12 +110,16 @@ export function promptBox({ history = [], placeholder = "Message Aether…" } =
|
|
|
112
110
|
content = s;
|
|
113
111
|
}
|
|
114
112
|
|
|
115
|
-
//
|
|
116
|
-
const promptLine =
|
|
113
|
+
// Bare prompt — just "> " like Claude Code
|
|
114
|
+
const promptLine = c.dim(prefixStr) + content;
|
|
117
115
|
|
|
118
|
-
//
|
|
119
|
-
const
|
|
120
|
-
const statusBar = c.dim(
|
|
116
|
+
// Bottom status bar — matches Claude's "manual mode on · ? for shortcuts · + for agents"
|
|
117
|
+
const imgNote = clipImages.length > 0 ? c.cyan(" images queued") + c.dim(" \xB7 ") : "";
|
|
118
|
+
const statusBar = c.dim(
|
|
119
|
+
mode + " mode" +
|
|
120
|
+
" \xB7 " + "? for shortcuts" +
|
|
121
|
+
" \xB7 " + "@file for images",
|
|
122
|
+
) + imgNote;
|
|
121
123
|
|
|
122
124
|
process.stdout.write(promptLine + "\n" + statusBar + "\n");
|
|
123
125
|
drawn = 2;
|
|
@@ -162,7 +164,6 @@ export function promptBox({ history = [], placeholder = "Message Aether…" } =
|
|
|
162
164
|
}
|
|
163
165
|
if (key.ctrl && k === "d") return finish(buf.length === 0 ? EXIT_SIGNAL : buf);
|
|
164
166
|
|
|
165
|
-
// Alt+V or Ctrl+V: paste image from clipboard
|
|
166
167
|
if ((key.meta && k === "v") || (key.ctrl && k === "v")) {
|
|
167
168
|
const imgPath = grabClipboardImage();
|
|
168
169
|
if (imgPath) {
|
package/src/repl.js
CHANGED
|
@@ -9,7 +9,7 @@ import { c, errorLine } from "./render.js";
|
|
|
9
9
|
import { autoUpdate } from "./update-check.js";
|
|
10
10
|
import { promptBox, EXIT_SIGNAL } from "./box-input.js";
|
|
11
11
|
|
|
12
|
-
const VERSION = "0.33.
|
|
12
|
+
const VERSION = "0.33.4";
|
|
13
13
|
const MODEL_NAME = "Aether Core";
|
|
14
14
|
|
|
15
15
|
const MODEL_ALIASES = {
|
|
@@ -49,7 +49,6 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
|
|
|
49
49
|
sessionOut: 0,
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
// Auto-update + balance fetch in parallel — zero startup latency added.
|
|
53
52
|
const updatePromise = autoUpdate().catch(() => null);
|
|
54
53
|
|
|
55
54
|
let needsSetup = false;
|
|
@@ -78,15 +77,26 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
|
|
|
78
77
|
} catch { /* tolerate */ }
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
// Clear screen — clean start, no leftover shell text (matches Claude Code)
|
|
81
|
+
process.stdout.write("\x1b[2J\x1b[H");
|
|
82
|
+
|
|
81
83
|
printBanner(state);
|
|
84
|
+
|
|
82
85
|
const updateMsg = await updatePromise;
|
|
83
|
-
|
|
84
|
-
console.log(
|
|
86
|
+
let extraLines = 0;
|
|
87
|
+
if (updateMsg) { console.log(updateMsg); extraLines++; }
|
|
88
|
+
|
|
89
|
+
// Push prompt to bottom of screen — big empty gap like Claude Code
|
|
90
|
+
const rows = process.stdout.rows || 24;
|
|
91
|
+
const bannerLines = 5; // 1 blank + 3 logo lines + 1 blank after
|
|
92
|
+
const promptLines = 2; // "> " input + status bar
|
|
93
|
+
const filler = Math.max(0, rows - bannerLines - extraLines - promptLines - 1);
|
|
94
|
+
for (let i = 0; i < filler; i++) console.log("");
|
|
85
95
|
|
|
86
96
|
const inputHistory = [];
|
|
87
97
|
|
|
88
98
|
while (true) {
|
|
89
|
-
const raw = await promptBox({ history: inputHistory });
|
|
99
|
+
const raw = await promptBox({ history: inputHistory, mode: state.autoYes ? "auto-yes" : "review" });
|
|
90
100
|
if (raw === EXIT_SIGNAL) { console.log(c.gray("bye.")); return; }
|
|
91
101
|
const line = (raw ?? "").trim();
|
|
92
102
|
if (!line) continue;
|
|
@@ -96,7 +106,6 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
|
|
|
96
106
|
if (line.startsWith("/") || line === "?") {
|
|
97
107
|
const handled = await handleSlash(line, state);
|
|
98
108
|
if (handled === "exit") return;
|
|
99
|
-
printStatusLine(state);
|
|
100
109
|
continue;
|
|
101
110
|
}
|
|
102
111
|
|
|
@@ -120,8 +129,6 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
|
|
|
120
129
|
if (!result.ok && result.error) {
|
|
121
130
|
console.log("\n" + errorLine(result.error.message || String(result.error)));
|
|
122
131
|
}
|
|
123
|
-
|
|
124
|
-
printStatusLine(state);
|
|
125
132
|
}
|
|
126
133
|
}
|
|
127
134
|
|
|
@@ -156,7 +163,7 @@ async function handleSlash(line, state) {
|
|
|
156
163
|
state.plan = me.plan || "FREE";
|
|
157
164
|
console.log(
|
|
158
165
|
c.cyan(`balance: ${me.balance.toLocaleString()} credits`) +
|
|
159
|
-
c.gray(`
|
|
166
|
+
c.gray(` \xB7 plan: ${me.plan || "FREE"} (${me.planCredits ?? 0} plan + ${me.topupCredits ?? 0} topup)`),
|
|
160
167
|
);
|
|
161
168
|
} catch (err) {
|
|
162
169
|
console.log(errorLine(err.message || String(err)));
|
|
@@ -169,7 +176,7 @@ async function handleSlash(line, state) {
|
|
|
169
176
|
try {
|
|
170
177
|
process.chdir(next);
|
|
171
178
|
state.cwd = next;
|
|
172
|
-
console.log(c.gray(`cwd
|
|
179
|
+
console.log(c.gray(`cwd -> ${state.cwd}`));
|
|
173
180
|
} catch (err) {
|
|
174
181
|
console.log(errorLine(err.message));
|
|
175
182
|
}
|
|
@@ -201,7 +208,7 @@ async function handleSlash(line, state) {
|
|
|
201
208
|
state.modelName = MODEL_ALIASES[key].name;
|
|
202
209
|
const premium = state.model !== null;
|
|
203
210
|
console.log(
|
|
204
|
-
c.gray(`model
|
|
211
|
+
c.gray(`model -> ${c.cyan(state.modelName)}`) +
|
|
205
212
|
(premium ? c.gray(" (premium — needs purchased credits, else falls back to Core)") : ""),
|
|
206
213
|
);
|
|
207
214
|
} else {
|
|
@@ -215,35 +222,30 @@ async function handleSlash(line, state) {
|
|
|
215
222
|
return null;
|
|
216
223
|
}
|
|
217
224
|
|
|
218
|
-
/* ───────── banner
|
|
225
|
+
/* ───────── banner ───────── */
|
|
219
226
|
|
|
220
227
|
const shortenPath = (p, max) => (p.length <= max ? p : "..." + p.slice(p.length - max + 3));
|
|
221
228
|
|
|
222
229
|
function printBanner(state) {
|
|
223
230
|
const credits = state.balance != null ? `${state.balance.toLocaleString()} credits` : "";
|
|
224
|
-
const
|
|
231
|
+
const plan = state.plan && state.plan !== "FREE" ? state.plan : "";
|
|
225
232
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
);
|
|
232
|
-
console.log(
|
|
233
|
-
" " + state.modelName +
|
|
234
|
-
(credits ? c.dim(" · ") + credits : "") +
|
|
235
|
-
(state.plan && state.plan !== "FREE" ? c.dim(" · ") + c.cyan(state.plan) : ""),
|
|
236
|
-
);
|
|
237
|
-
console.log(" " + c.dim(shortenPath(state.cwd, 60)));
|
|
238
|
-
}
|
|
233
|
+
// Block logo using ANSI background colors — renders correctly in ANY terminal.
|
|
234
|
+
// Each block = 2 spaces with colored background. No special chars needed.
|
|
235
|
+
const blk = (code) => `\x1b[${code}m \x1b[0m`;
|
|
236
|
+
const C = blk(46); // cyan background
|
|
237
|
+
const B = blk(44); // blue background
|
|
239
238
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
console.log(c.
|
|
239
|
+
const gap = " ";
|
|
240
|
+
|
|
241
|
+
const modelParts = [state.modelName];
|
|
242
|
+
if (credits) modelParts.push(credits);
|
|
243
|
+
if (plan) modelParts.push(c.cyan(plan));
|
|
244
|
+
const modelLine = modelParts.join(c.dim(" \xB7 "));
|
|
245
|
+
|
|
246
|
+
console.log("");
|
|
247
|
+
console.log(` ${C}${B} ${C}${gap}${c.bold("Aether Code")} ${c.dim("v" + VERSION)}`);
|
|
248
|
+
console.log(` ${B}${C} ${B}${gap}${modelLine}`);
|
|
249
|
+
console.log(` ${C}${B} ${C}${gap}${c.dim(shortenPath(state.cwd, 55))}`);
|
|
250
|
+
console.log("");
|
|
249
251
|
}
|