aether-code 0.16.3 → 0.16.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/agent.js +11 -4
- package/src/render.js +33 -4
- package/src/repl.js +1 -1
package/bin/aether-code.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aether-code",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.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/agent.js
CHANGED
|
@@ -6,7 +6,7 @@ import { agentTurnStream, AetherError } from "./api.js";
|
|
|
6
6
|
import { TOOL_DEFINITIONS, executeTool } from "./tools.js";
|
|
7
7
|
import { unnamespaceToolName } from "./mcp.js";
|
|
8
8
|
import { loadAllSkills, selectSkills, renderSkillsBlock } from "./skills.js";
|
|
9
|
-
import { c, divider, turn, toolLabel, toolSummary,
|
|
9
|
+
import { c, divider, turn, toolLabel, toolSummary, makeTokenStripper, errorLine } from "./render.js";
|
|
10
10
|
|
|
11
11
|
const DEFAULT_MAX_TURNS = 25;
|
|
12
12
|
|
|
@@ -59,6 +59,7 @@ export async function runAgent({
|
|
|
59
59
|
// calling a particular tool (i.e. the `name` arrives in the stream).
|
|
60
60
|
const announced = new Set();
|
|
61
61
|
let lastWasText = false;
|
|
62
|
+
const stripper = makeTokenStripper();
|
|
62
63
|
|
|
63
64
|
// Select skills for this turn against the current user prompt + any
|
|
64
65
|
// paths the model has read so far. Prepend the matching skills' bodies
|
|
@@ -73,8 +74,9 @@ export async function runAgent({
|
|
|
73
74
|
messages: turnMessages,
|
|
74
75
|
tools,
|
|
75
76
|
onDelta: (text) => {
|
|
76
|
-
//
|
|
77
|
-
|
|
77
|
+
// Buffered strip of leaked model channel/control tokens (which can
|
|
78
|
+
// be split across stream chunks) before display.
|
|
79
|
+
const clean = stripper.push(text);
|
|
78
80
|
if (!clean) return;
|
|
79
81
|
if (!lastWasText) {
|
|
80
82
|
process.stdout.write(" ");
|
|
@@ -100,7 +102,12 @@ export async function runAgent({
|
|
|
100
102
|
throw err;
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
//
|
|
105
|
+
// Flush any held-back partial token, then close the line.
|
|
106
|
+
const tail = stripper.flush();
|
|
107
|
+
if (tail) {
|
|
108
|
+
if (!lastWasText) { process.stdout.write(" "); lastWasText = true; }
|
|
109
|
+
process.stdout.write(tail);
|
|
110
|
+
}
|
|
104
111
|
if (lastWasText) process.stdout.write("\n");
|
|
105
112
|
totalCredits += res.creditsCharged ?? 0;
|
|
106
113
|
totalIn += res.usage?.prompt_tokens ?? 0;
|
package/src/render.js
CHANGED
|
@@ -92,11 +92,40 @@ export function toolSummary(name, result) {
|
|
|
92
92
|
// Strip model "harmony"/channel control tokens (<|channel|>, <|message|>,
|
|
93
93
|
// <|tool_response|>, <channel|>, …) that occasionally leak into the text
|
|
94
94
|
// stream. Belt-and-suspenders alongside the server-side scrub.
|
|
95
|
+
// Only strips tokens containing a PIPE — the harmony/channel control tokens
|
|
96
|
+
// (<|channel|>, <|tool_response|>, <channel|>) always have one. Real code like
|
|
97
|
+
// <div>, Vec<T>, a < b has no pipe and is left untouched.
|
|
98
|
+
const MODEL_TOKEN_RE = /<\|[a-z_]*\|?>|<[a-z_]+\|>/gi;
|
|
99
|
+
|
|
95
100
|
export function stripModelTokens(text) {
|
|
96
|
-
return text
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
return text.replace(MODEL_TOKEN_RE, "");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Streaming-safe stripper: the leaked tokens (<|channel|>, <|tool_response|>, …)
|
|
105
|
+
// can be split across stream chunks ("<chann" then "el|>"), which a per-delta
|
|
106
|
+
// regex misses. This buffers any trailing "<…" that might be the start of a
|
|
107
|
+
// token and only emits it once it's confirmed not-a-token (or on flush).
|
|
108
|
+
export function makeTokenStripper() {
|
|
109
|
+
let buf = "";
|
|
110
|
+
return {
|
|
111
|
+
push(text) {
|
|
112
|
+
buf = (buf + text).replace(MODEL_TOKEN_RE, "");
|
|
113
|
+
const partial = buf.match(/<[|a-z_/]*$/i); // possible token start at the tail
|
|
114
|
+
if (partial) {
|
|
115
|
+
const emit = buf.slice(0, partial.index);
|
|
116
|
+
buf = buf.slice(partial.index);
|
|
117
|
+
return emit;
|
|
118
|
+
}
|
|
119
|
+
const emit = buf;
|
|
120
|
+
buf = "";
|
|
121
|
+
return emit;
|
|
122
|
+
},
|
|
123
|
+
flush() {
|
|
124
|
+
const out = buf.replace(MODEL_TOKEN_RE, "");
|
|
125
|
+
buf = "";
|
|
126
|
+
return out;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
100
129
|
}
|
|
101
130
|
|
|
102
131
|
export function toolResult(text, ok = true) {
|
package/src/repl.js
CHANGED
|
@@ -17,7 +17,7 @@ import { c, errorLine } from "./render.js";
|
|
|
17
17
|
import { checkForUpdate } from "./update-check.js";
|
|
18
18
|
import { promptBoxed, EXIT_SIGNAL } from "./ink-input.js";
|
|
19
19
|
|
|
20
|
-
const VERSION = "0.16.
|
|
20
|
+
const VERSION = "0.16.4";
|
|
21
21
|
const MODEL_NAME = "Aether Core";
|
|
22
22
|
|
|
23
23
|
const SHORTCUTS = `
|