aether-code 0.43.3 → 0.43.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/package.json +1 -1
- package/src/agent.js +17 -5
- package/src/render.js +4 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aether-code",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.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
|
@@ -160,6 +160,8 @@ export async function runAgent({
|
|
|
160
160
|
const announced = new Set();
|
|
161
161
|
let lastWasText = false;
|
|
162
162
|
const stripper = makeTokenStripper();
|
|
163
|
+
let textEmitted = false; // track if real content has been emitted this turn
|
|
164
|
+
const CHANNEL_WORD_SET = new Set(["thought","analysis","final","commentary","thinking","return","assistant","user","system","developer","tool"]);
|
|
163
165
|
|
|
164
166
|
// Select skills for this turn against the current user prompt + any
|
|
165
167
|
// paths the model has read so far. Prepend the matching skills' bodies
|
|
@@ -180,12 +182,19 @@ export async function runAgent({
|
|
|
180
182
|
tools,
|
|
181
183
|
model,
|
|
182
184
|
onDelta: (text) => {
|
|
183
|
-
// Buffered strip of leaked model channel/control tokens (which can
|
|
184
|
-
// be split across stream chunks) before display.
|
|
185
185
|
const clean = stripper.push(text);
|
|
186
186
|
if (!clean) return;
|
|
187
|
-
//
|
|
188
|
-
//
|
|
187
|
+
// Before any real content, strip stray channel name words that leak
|
|
188
|
+
// as the first tokens (e.g. "thought\nthought\n" from harmony).
|
|
189
|
+
if (!textEmitted) {
|
|
190
|
+
const stripped = clean.replace(/^[\s]*(thought|analysis|final|commentary|thinking|return|assistant|user|system|developer|tool)[\s]*/gi, "");
|
|
191
|
+
if (!stripped.trim()) return;
|
|
192
|
+
textEmitted = true;
|
|
193
|
+
stopSpin();
|
|
194
|
+
process.stdout.write("\n" + stripped);
|
|
195
|
+
lastWasText = true;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
189
198
|
if (!lastWasText && !clean.trim()) return;
|
|
190
199
|
stopSpin();
|
|
191
200
|
if (!lastWasText) {
|
|
@@ -216,7 +225,10 @@ export async function runAgent({
|
|
|
216
225
|
stopSpin(); // ensure it's cleared even if the turn produced no output
|
|
217
226
|
|
|
218
227
|
// Flush any held-back partial token, then close the line.
|
|
219
|
-
|
|
228
|
+
let tail = stripper.flush();
|
|
229
|
+
if (tail && !textEmitted) {
|
|
230
|
+
tail = tail.replace(/^[\s]*(thought|analysis|final|commentary|thinking|return|assistant|user|system|developer|tool)[\s]*/gi, "");
|
|
231
|
+
}
|
|
220
232
|
if (tail && (lastWasText || tail.trim())) {
|
|
221
233
|
if (!lastWasText) { process.stdout.write("\n"); lastWasText = true; }
|
|
222
234
|
process.stdout.write(tail);
|
package/src/render.js
CHANGED
|
@@ -199,9 +199,10 @@ export function toolSummary(name, result) {
|
|
|
199
199
|
// (<|channel|>, <|tool_response|>, <channel|>) always have one. Real code like
|
|
200
200
|
// <div>, Vec<T>, a < b has no pipe and is left untouched.
|
|
201
201
|
const MODEL_TOKEN_RE = /<\|[a-z_]*\|?>|<[a-z_]+\|>/gi;
|
|
202
|
+
const CHANNEL_NAMES_RE = /^[ \t]*(thought|analysis|final|commentary|thinking|return|assistant|user|system|developer|tool)[ \t]*$/gim;
|
|
202
203
|
|
|
203
204
|
export function stripModelTokens(text) {
|
|
204
|
-
return text.replace(MODEL_TOKEN_RE, "");
|
|
205
|
+
return text.replace(MODEL_TOKEN_RE, "").replace(CHANNEL_NAMES_RE, "");
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
// Streaming-safe stripper: the leaked tokens (<|channel|>, <|tool_response|>, …)
|
|
@@ -212,7 +213,7 @@ export function makeTokenStripper() {
|
|
|
212
213
|
let buf = "";
|
|
213
214
|
return {
|
|
214
215
|
push(text) {
|
|
215
|
-
buf = (buf + text).replace(MODEL_TOKEN_RE, "");
|
|
216
|
+
buf = (buf + text).replace(MODEL_TOKEN_RE, "").replace(CHANNEL_NAMES_RE, "");
|
|
216
217
|
const partial = buf.match(/<[|a-z_/]*$/i); // possible token start at the tail
|
|
217
218
|
if (partial) {
|
|
218
219
|
const emit = buf.slice(0, partial.index);
|
|
@@ -224,7 +225,7 @@ export function makeTokenStripper() {
|
|
|
224
225
|
return emit;
|
|
225
226
|
},
|
|
226
227
|
flush() {
|
|
227
|
-
const out = buf.replace(MODEL_TOKEN_RE, "");
|
|
228
|
+
const out = buf.replace(MODEL_TOKEN_RE, "").replace(CHANNEL_NAMES_RE, "");
|
|
228
229
|
buf = "";
|
|
229
230
|
return out;
|
|
230
231
|
},
|