aether-code 0.33.5 → 0.33.7

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.
@@ -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.5";
31
+ const VERSION = "0.33.7";
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.5",
3
+ "version": "0.33.7",
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
@@ -113,15 +113,17 @@ export function promptBox({ history = [], placeholder = "Message Aether...", mod
113
113
  // Bare prompt — just "> " like Claude Code
114
114
  const promptLine = c.dim(prefixStr) + content;
115
115
 
116
- // Bottom status bar — matches Claude's "manual mode on · ? for shortcuts · + for agents"
116
+ // Bottom status bar — colored block prefix like Claude's
117
+ const blk = (code) => `\x1b[${code}m \x1b[0m`;
118
+ const barPrefix = blk(46) + blk(44);
117
119
  const imgNote = clipImages.length > 0 ? c.cyan(" images queued") + c.dim(" \xB7 ") : "";
118
- const statusBar = c.dim(
119
- mode + " mode" +
120
+ const statusText = c.dim(
121
+ " " + mode + " mode" +
120
122
  " \xB7 " + "? for shortcuts" +
121
123
  " \xB7 " + "@file for images",
122
124
  ) + imgNote;
123
125
 
124
- process.stdout.write(promptLine + "\n" + statusBar + "\n");
126
+ process.stdout.write(promptLine + "\n" + barPrefix + statusText + "\n");
125
127
  drawn = 2;
126
128
  };
127
129
 
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.5";
12
+ const VERSION = "0.33.7";
13
13
  const MODEL_NAME = "Aether Core";
14
14
 
15
15
  const MODEL_ALIASES = {
@@ -33,6 +33,8 @@ ${c.gray("Anything else is sent to the agent as your next message.")}
33
33
  ${c.gray("Conversation history is kept across messages until you /clear.")}
34
34
  `;
35
35
 
36
+ const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
37
+
36
38
  export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafePaths: initialUnsafePaths, maxTurns: initialMaxTurns, model: initialModel = null, mcpManager = null }) {
37
39
  const initialAlias = Object.values(MODEL_ALIASES).find((a) => a.id === initialModel);
38
40
  const state = {
@@ -80,7 +82,7 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
80
82
  // Clear screen — clean start, no leftover shell text (matches Claude Code)
81
83
  process.stdout.write("\x1b[2J\x1b[H");
82
84
 
83
- printBanner(state);
85
+ const bannerLineCount = printBanner(state);
84
86
 
85
87
  const updateMsg = await updatePromise;
86
88
  let extraLines = 0;
@@ -88,9 +90,8 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
88
90
 
89
91
  // Push prompt to bottom of screen — big empty gap like Claude Code
90
92
  const rows = process.stdout.rows || 24;
91
- const bannerLines = 5; // 1 blank + 3 logo lines + 1 blank after
92
93
  const promptLines = 2; // "> " input + status bar
93
- const filler = Math.max(0, rows - bannerLines - extraLines - promptLines - 1);
94
+ const filler = Math.max(0, rows - bannerLineCount - extraLines - promptLines - 1);
94
95
  for (let i = 0; i < filler; i++) console.log("");
95
96
 
96
97
  const inputHistory = [];
@@ -131,7 +132,6 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
131
132
  }
132
133
 
133
134
  // Push prompt back toward the bottom — content scrolls UP like Claude Code.
134
- // We leave a few lines visible so the tail of the response stays on screen.
135
135
  const rowsNow = process.stdout.rows || 24;
136
136
  const gap = Math.max(0, Math.floor(rowsNow * 0.4));
137
137
  for (let g = 0; g < gap; g++) console.log("");
@@ -228,30 +228,77 @@ async function handleSlash(line, state) {
228
228
  return null;
229
229
  }
230
230
 
231
- /* ───────── banner ───────── */
231
+ /* ───────── banner (two-column like Claude Code) ───────── */
232
232
 
233
233
  const shortenPath = (p, max) => (p.length <= max ? p : "..." + p.slice(p.length - max + 3));
234
234
 
235
+ function padRight(str, width) {
236
+ const visible = stripAnsi(str).length;
237
+ const need = Math.max(0, width - visible);
238
+ return str + " ".repeat(need);
239
+ }
240
+
235
241
  function printBanner(state) {
242
+ const cols = process.stdout.columns || 80;
236
243
  const credits = state.balance != null ? `${state.balance.toLocaleString()} credits` : "";
237
244
  const plan = state.plan && state.plan !== "FREE" ? state.plan : "";
238
245
 
239
- // Block logo using ANSI background colors — renders correctly in ANY terminal.
240
- // Each block = 2 spaces with colored background. No special chars needed.
241
246
  const blk = (code) => `\x1b[${code}m \x1b[0m`;
242
- const C = blk(46); // cyan background
243
- const B = blk(44); // blue background
244
-
245
- const gap = " ";
247
+ const C = blk(46);
248
+ const B = blk(44);
246
249
 
247
250
  const modelParts = [state.modelName];
248
251
  if (credits) modelParts.push(credits);
249
252
  if (plan) modelParts.push(c.cyan(plan));
250
253
  const modelLine = modelParts.join(c.dim(" \xB7 "));
251
254
 
255
+ const leftW = Math.min(Math.floor(cols * 0.5), 45);
256
+
257
+ // Two-column rows: logo on left, tips+changelog on right.
258
+ // Model info goes BELOW the logo on its own full-width line (like Claude Code)
259
+ // so long text like "Aether Core · 34,988 credits · UNLIMITED" never overflows.
260
+ const pairedLeft = [
261
+ c.dim("──") + " " + c.bold("Aether Code") + " " + c.dim("v" + VERSION),
262
+ " " + c.bold("Welcome back!"),
263
+ "",
264
+ ` ${C}${B} ${C}`,
265
+ ` ${B}${C} ${B}`,
266
+ ` ${C}${B} ${C}`,
267
+ ];
268
+
269
+ const pairedRight = [
270
+ c.bold("Tips for getting started"),
271
+ c.dim("Ask Aether to build, debug, or refactor code"),
272
+ "",
273
+ c.yellow("What's new"),
274
+ c.dim("Creative thinking words while processing"),
275
+ c.dim("Prompt pins to bottom, content scrolls up"),
276
+ ];
277
+
278
+ const twoCol = cols >= 70;
279
+ let printed = 0;
280
+
252
281
  console.log("");
253
- console.log(` ${C}${B} ${C}${gap}${c.bold("Aether Code")} ${c.dim("v" + VERSION)}`);
254
- console.log(` ${B}${C} ${B}${gap}${modelLine}`);
255
- console.log(` ${C}${B} ${C}${gap}${c.dim(shortenPath(state.cwd, 55))}`);
282
+ printed++;
283
+
284
+ if (twoCol) {
285
+ for (let i = 0; i < pairedLeft.length; i++) {
286
+ console.log(" " + padRight(pairedLeft[i] || "", leftW) + (pairedRight[i] || ""));
287
+ printed++;
288
+ }
289
+ } else {
290
+ for (const line of pairedLeft) {
291
+ console.log(" " + line);
292
+ printed++;
293
+ }
294
+ }
295
+
296
+ // Full-width rows below logo — model, path (no right column so they can be long)
297
+ console.log("");
298
+ console.log(" " + modelLine);
299
+ console.log(" " + c.dim(shortenPath(state.cwd, 60)));
256
300
  console.log("");
301
+ printed += 4;
302
+
303
+ return printed;
257
304
  }