aether-code 0.35.9 → 0.36.1

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.35.9";
31
+ const VERSION = "0.36.1";
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.35.9",
3
+ "version": "0.36.1",
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
@@ -80,14 +80,19 @@ export function promptBox({ history = [], placeholder = "", mode = "review", sup
80
80
 
81
81
  const termW = () => Math.max(30, (process.stdout.columns || 80) - 2);
82
82
 
83
+ const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
84
+ const rowsFor = (line, cols) => Math.max(1, Math.ceil((stripAnsi(line).length || 1) / cols));
85
+
83
86
  const draw = (first) => {
84
87
  const W = termW();
88
+ const termCols = process.stdout.columns || 80;
85
89
  if (!first) process.stdout.write(`\x1b[${drawn}A`);
86
90
  process.stdout.write("\x1b[J");
87
91
 
88
92
  const prefixStr = "> ";
89
93
  const prefixLen = 2;
90
- const maxVisible = W - prefixLen;
94
+ const imgSuffix = clipImages.length > 0 ? ` [+${clipImages.length} img]` : "";
95
+ const maxVisible = Math.max(8, W - prefixLen - imgSuffix.length);
91
96
  const start = pos > maxVisible ? pos - maxVisible : 0;
92
97
  const view = buf.slice(start, start + maxVisible);
93
98
  const rel = pos - start;
@@ -104,29 +109,26 @@ export function promptBox({ history = [], placeholder = "", mode = "review", sup
104
109
  const ch = view[i] ?? " ";
105
110
  s += i === rel ? INV(ch) : ch;
106
111
  }
107
- if (clipImages.length > 0) {
108
- s += " " + c.cyan(`[+${clipImages.length} img]`);
109
- }
112
+ if (imgSuffix) s += c.cyan(imgSuffix);
110
113
  content = s;
111
114
  }
112
115
 
113
- // Bare prompt — just "> " like Claude Code
114
116
  const promptLine = c.dim(prefixStr) + content;
115
117
 
116
- // Bottom status bar — colored block prefix like Claude's
117
118
  const blk = (code) => `\x1b[${code}m \x1b[0m`;
118
119
  const barPrefix = blk(46) + blk(44);
119
120
  const imgNote = clipImages.length > 0 ? c.cyan(" images queued") + c.dim(" \xB7 ") : "";
120
- const statusText = c.dim(
121
- " " + mode + " mode" +
122
- " \xB7 " + "? for shortcuts" +
123
- " \xB7 " + "@file for images",
124
- ) + imgNote;
125
-
126
- const termCols = process.stdout.columns || 80;
127
- const rule = c.cyan(" " + "─".repeat(termCols - 2));
128
- process.stdout.write(rule + "\n" + promptLine + "\n" + rule + "\n" + barPrefix + statusText + "\n");
129
- drawn = 4;
121
+ const baseStatus = " " + mode + " mode \xB7 ? for shortcuts \xB7 @file for images";
122
+ const barPrefixLen = 2;
123
+ const imgNoteLen = clipImages.length > 0 ? 17 : 0;
124
+ const maxStatusLen = Math.max(10, termCols - barPrefixLen - imgNoteLen - 1);
125
+ const truncStatus = baseStatus.length > maxStatusLen ? baseStatus.slice(0, maxStatusLen) : baseStatus;
126
+ const statusText = c.dim(truncStatus) + imgNote;
127
+
128
+ const rule = c.cyan(" " + "─".repeat(Math.max(0, termCols - 2)));
129
+ const lines = [rule, promptLine, rule, barPrefix + statusText];
130
+ drawn = lines.reduce((sum, l) => sum + rowsFor(l, termCols), 0);
131
+ process.stdout.write(lines.join("\n") + "\n");
130
132
  };
131
133
 
132
134
  const finish = (result) => {
package/src/repl.js CHANGED
@@ -9,7 +9,7 @@ import { c, errorLine, turnStats } 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.35.9";
12
+ const VERSION = "0.36.1";
13
13
  const MODEL_NAME = "Aether Core";
14
14
 
15
15
  const MODEL_ALIASES = {
@@ -88,15 +88,6 @@ export async function runRepl({ cwd: initialCwd, autoYes: initialAutoYes, unsafe
88
88
  let extraLines = 0;
89
89
  if (updateMsg) { console.log(updateMsg); extraLines++; }
90
90
 
91
- // Push prompt to bottom — use cursor positioning (not filler) so the banner
92
- // stays visible. Filler breaks on cmd.exe when process.stdout.rows returns
93
- // the scroll-buffer height (~300) instead of the visible window height (~25).
94
- const rows = process.stdout.rows || 24;
95
- const promptHeight = 4; // rule + "> " input + rule + status bar
96
- const contentEnd = bannerLineCount + extraLines + 1;
97
- const promptRow = Math.max(contentEnd + 1, rows - promptHeight + 1);
98
- process.stdout.write(`\x1b[${promptRow};1H`);
99
-
100
91
  const inputHistory = [];
101
92
 
102
93
  while (true) {
package/src/tools.js CHANGED
@@ -200,7 +200,7 @@ export const TOOL_DEFINITIONS = [
200
200
  function: {
201
201
  name: "ask_user",
202
202
  description:
203
- "Ask the user a single multiple-choice question and wait for their answer. Use this ONLY when the request is genuinely ambiguous AND the answer materially changes what you build — e.g. which platform/framework/language, the scope, or an irreversible decision. Ask BEFORE building when a wrong assumption would waste real work. Give 2–5 concrete options, each with a short description; put the best default first. Do NOT use it for trivial choices, things you can infer, or to confirm permission to act — just build when the task is clear.",
203
+ "Ask the user a single multiple-choice question ONLY when you literally cannot proceed without their input — e.g. the task names two incompatible platforms and you don't know which one. NEVER use this tool to answer a question the user asked YOU — if they ask 'what color is this?', 'what does this code do?', 'explain X', etc., respond with TEXT, not a quiz. NEVER use it to present analysis, findings, or answers as multiple-choice options. NEVER use it for trivial choices, things you can infer, or to confirm permission — just act. The ONLY valid use is: a genuinely ambiguous BUILD request where picking wrong wastes real work (which framework, which language, which scope). Give 2–5 concrete options with short descriptions; put the best default first.",
204
204
  parameters: {
205
205
  type: "object",
206
206
  properties: {