zames_pro 2.80.5 → 2.80.8
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/CHANGELOG.md +20 -0
- package/README.md +8 -0
- package/dist/net-capture.js +60 -7
- package/dist/transcript.js +34 -0
- package/dist/tui/edit.js +9 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.80.8] - 2026-10-20
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Internal improvements.
|
|
15
|
+
|
|
16
|
+
## [2.80.7] - 2026-10-20
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- stop filling the disk with temp dirs, coverage dumps and unbounded logs
|
|
21
|
+
- word delete and word-left stop at a newline
|
|
22
|
+
|
|
23
|
+
## [2.80.6] - 2026-10-20
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- stop filling the disk with temp dirs, coverage dumps and unbounded logs
|
|
28
|
+
- word delete and word-left stop at a newline
|
|
29
|
+
|
|
10
30
|
## [2.80.5] - 2026-10-20
|
|
11
31
|
|
|
12
32
|
### Fixed
|
package/README.md
CHANGED
|
@@ -124,6 +124,10 @@ Key pieces:
|
|
|
124
124
|
|
|
125
125
|
## Why zames?
|
|
126
126
|
|
|
127
|
+
- **Built with itself** — `zames_pro` is developed by `zames_pro`. No other
|
|
128
|
+
coding agent is used on this repository: the agent in this very terminal
|
|
129
|
+
reads the sources, runs the tests, fixes the bugs and commits the result.
|
|
130
|
+
That is the daily proof that it works and is actually used.
|
|
127
131
|
- **No API key, no per-token bill** — it uses your own DeepSeek or Qwen chat
|
|
128
132
|
account, not the paid API. Good for long, tool-heavy tasks.
|
|
129
133
|
- **Same workflow as Claude Code / Codex** — tools, `AGENTS.md`, skills, MCP
|
|
@@ -707,6 +711,10 @@ zames не вызывает API модели. Он запускает headless C
|
|
|
707
711
|
|
|
708
712
|
## Почему zames?
|
|
709
713
|
|
|
714
|
+
- **Разрабатывается сам собой** — над `zames_pro` работает `zames_pro`, а не
|
|
715
|
+
какой-то другой кодинг-агент: агент в этом самом терминале читает исходники,
|
|
716
|
+
гоняет тесты, чинит баги и коммитит результат. Это ежедневное доказательство,
|
|
717
|
+
что он работает и реально используется.
|
|
710
718
|
- **Нет API-ключа и счёта за токены** — используется ваш собственный аккаунт
|
|
711
719
|
чата DeepSeek или Qwen, а не платный API. Удобно для долгих задач с
|
|
712
720
|
инструментами.
|
package/dist/net-capture.js
CHANGED
|
@@ -348,19 +348,72 @@ export function extractTokenUsage(body) {
|
|
|
348
348
|
return found;
|
|
349
349
|
}
|
|
350
350
|
// Saves the DeepSeek network response body to disk for post-mortem analysis.
|
|
351
|
-
//
|
|
352
|
-
//
|
|
353
|
-
//
|
|
354
|
-
//
|
|
351
|
+
// DEBUG ONLY: disabled unless ZAMES_NET_DEBUG=1.
|
|
352
|
+
//
|
|
353
|
+
// The dumps live in ~/.zames/net-log and one file PER RESPONSE is written, so
|
|
354
|
+
// an unattended `npm run dev` (which sets ZAMES_NET_DEBUG=1) used to grow the
|
|
355
|
+
// directory without bound: 77k files / 800 MB after a few days. On WSL that
|
|
356
|
+
// directory sits inside ext4.vhdx, and the space of thousands of tiny deleted
|
|
357
|
+
// files is never returned to Windows — the host disk fills up. So the log is
|
|
358
|
+
// ROTATED here: `NET_LOG_KEEP` newest dumps are kept and a rotation runs at
|
|
359
|
+
// most once every `NET_LOG_ROTATE_MS` (listing the dir on every response would
|
|
360
|
+
// itself cost time on a huge directory).
|
|
361
|
+
const NET_LOG_KEEP = 200;
|
|
362
|
+
const NET_LOG_ROTATE_MS = 5 * 60_000;
|
|
363
|
+
const NET_LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
364
|
+
let netLogDir = null;
|
|
365
|
+
let netLogLastRotate = 0;
|
|
366
|
+
function netLogDirectory() {
|
|
367
|
+
if (netLogDir === null) {
|
|
368
|
+
netLogDir = path.join(os.homedir(), '.zames', 'net-log');
|
|
369
|
+
}
|
|
370
|
+
return netLogDir;
|
|
371
|
+
}
|
|
372
|
+
/** A stamp prefix (`YYYY-MM-DDTHH-MM-SS-mmmZ_`) sorts chronologically. */
|
|
373
|
+
function netLogStamp() {
|
|
374
|
+
return new Date().toISOString().replace(/[:.]/g, '-');
|
|
375
|
+
}
|
|
355
376
|
export async function dumpNetBody(url, body) {
|
|
356
377
|
if (!process.env.ZAMES_NET_DEBUG)
|
|
357
378
|
return;
|
|
358
379
|
try {
|
|
359
|
-
const dir =
|
|
380
|
+
const dir = netLogDirectory();
|
|
360
381
|
await fs.mkdir(dir, { recursive: true });
|
|
361
|
-
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
362
382
|
const safe = url.replace(/[^a-zA-Z0-9_.-]/g, '_').slice(0, 80);
|
|
363
|
-
await fs.writeFile(path.join(dir,
|
|
383
|
+
await fs.writeFile(path.join(dir, netLogStamp() + '_' + safe + '.txt'), body.slice(0, NET_LOG_MAX_BYTES), 'utf-8');
|
|
384
|
+
await rotateNetLogThrottled(dir);
|
|
364
385
|
}
|
|
365
386
|
catch { }
|
|
366
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Keeps only the newest `NET_LOG_KEEP` dumps. Exported for the test: the
|
|
390
|
+
* rotation is the only thing standing between `ZAMES_NET_DEBUG=1` and an
|
|
391
|
+
* unbounded directory, so it is checked directly.
|
|
392
|
+
*/
|
|
393
|
+
export async function rotateNetLog(dir, keep = NET_LOG_KEEP, now = Date.now()) {
|
|
394
|
+
// The stamp prefix sorts the names chronologically, so a plain sort is
|
|
395
|
+
// enough — no stat() per file (a directory with 77k entries would make
|
|
396
|
+
// 77k syscalls on every response).
|
|
397
|
+
const names = (await fs.readdir(dir).catch(() => [])).filter((n) => n.endsWith('.txt'));
|
|
398
|
+
if (names.length <= keep)
|
|
399
|
+
return 0;
|
|
400
|
+
names.sort();
|
|
401
|
+
const stale = names.slice(0, names.length - keep);
|
|
402
|
+
let removed = 0;
|
|
403
|
+
for (const n of stale) {
|
|
404
|
+
await fs
|
|
405
|
+
.rm(path.join(dir, n), { force: true })
|
|
406
|
+
.then(() => removed++)
|
|
407
|
+
.catch(() => { });
|
|
408
|
+
}
|
|
409
|
+
netLogLastRotate = now;
|
|
410
|
+
return removed;
|
|
411
|
+
}
|
|
412
|
+
/** Throttled rotation used by dumpNetBody (at most once per interval). */
|
|
413
|
+
async function rotateNetLogThrottled(dir) {
|
|
414
|
+
const now = Date.now();
|
|
415
|
+
if (now - netLogLastRotate < NET_LOG_ROTATE_MS)
|
|
416
|
+
return;
|
|
417
|
+
netLogLastRotate = now;
|
|
418
|
+
await rotateNetLog(dir, NET_LOG_KEEP, now);
|
|
419
|
+
}
|
package/dist/transcript.js
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
// A transcript file is appended per RUN and never deleted, so ~/.zames/logs
|
|
4
|
+
// grew without bound (177 files / 138 MB observed). On WSL the directory sits
|
|
5
|
+
// inside ext4.vhdx: the space of deleted files is not returned to the Windows
|
|
6
|
+
// host, so a big log dir is also a host-disk problem. Rotate on start-up: keep
|
|
7
|
+
// the newest MAX_TRANSCRIPT_FILES and drop the rest.
|
|
8
|
+
const MAX_TRANSCRIPT_FILES = 200;
|
|
9
|
+
// The constructor is SYNCHRONOUS (it opens the stream right away), so the
|
|
10
|
+
// rotation that must happen before the create has to be sync as well.
|
|
11
|
+
export function rotateTranscripts(dir, keep = MAX_TRANSCRIPT_FILES) {
|
|
12
|
+
let names;
|
|
13
|
+
try {
|
|
14
|
+
names = fs.readdirSync(dir).filter((n) => n.endsWith('.jsonl'));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// A missing/unreadable dir must not break the run: the transcript is
|
|
18
|
+
// created right after and mkdirSync has its own error handling.
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
if (names.length <= keep)
|
|
22
|
+
return 0;
|
|
23
|
+
names.sort();
|
|
24
|
+
let removed = 0;
|
|
25
|
+
for (const n of names.slice(0, names.length - keep)) {
|
|
26
|
+
try {
|
|
27
|
+
fs.rmSync(path.join(dir, n), { force: true });
|
|
28
|
+
removed++;
|
|
29
|
+
}
|
|
30
|
+
catch { }
|
|
31
|
+
}
|
|
32
|
+
return removed;
|
|
33
|
+
}
|
|
3
34
|
function transcriptErrorLine(e) {
|
|
4
35
|
return `transcript: failed to create file: ${e.message}`;
|
|
5
36
|
}
|
|
@@ -27,6 +58,9 @@ export class Transcript {
|
|
|
27
58
|
const safeName = String(sessionName)
|
|
28
59
|
.replace(/[\\/:*?"<>|\u0000-\u001f]/g, '_')
|
|
29
60
|
.trim() || 'session';
|
|
61
|
+
// Rotation BEFORE the create: the new file then has the newest stamp,
|
|
62
|
+
// so the current run's transcript is never a deletion candidate.
|
|
63
|
+
rotateTranscripts(dir);
|
|
30
64
|
this.file = path.join(dir, `${safeName}-${stamp}.jsonl`);
|
|
31
65
|
this.stream = fs.createWriteStream(this.file, { flags: 'a' });
|
|
32
66
|
// Write errors (disk full, file deleted, etc.) arrive as an 'error'
|
package/dist/tui/edit.js
CHANGED
|
@@ -74,9 +74,12 @@ export function del(s) {
|
|
|
74
74
|
export function deleteWordLeft(s) {
|
|
75
75
|
const chars = charsOf(s);
|
|
76
76
|
let i = s.cursor;
|
|
77
|
-
|
|
77
|
+
// A NEWLINE is a hard boundary: at the start of a line the key does
|
|
78
|
+
// nothing instead of eating the break and the previous line's word
|
|
79
|
+
// (deleteWordRight and wordLeft already stop at a newline).
|
|
80
|
+
while (i > 0 && chars[i - 1] !== NL && /\s/.test(chars[i - 1]))
|
|
78
81
|
i--;
|
|
79
|
-
while (i > 0 && !/\s/.test(chars[i - 1]))
|
|
82
|
+
while (i > 0 && chars[i - 1] !== NL && !/\s/.test(chars[i - 1]))
|
|
80
83
|
i--;
|
|
81
84
|
chars.splice(i, s.cursor - i);
|
|
82
85
|
return { ...s, buf: chars.join(''), cursor: i };
|
|
@@ -137,9 +140,11 @@ export function moveEnd(s) {
|
|
|
137
140
|
export function wordLeft(s) {
|
|
138
141
|
const chars = charsOf(s);
|
|
139
142
|
let i = s.cursor;
|
|
140
|
-
|
|
143
|
+
// Stop at a newline (mirrors deleteWordLeft/deleteWordRight): the cursor
|
|
144
|
+
// must not jump to the previous LINE, only to the previous word.
|
|
145
|
+
while (i > 0 && chars[i - 1] !== NL && /\s/.test(chars[i - 1]))
|
|
141
146
|
i--;
|
|
142
|
-
while (i > 0 && !/\s/.test(chars[i - 1]))
|
|
147
|
+
while (i > 0 && chars[i - 1] !== NL && !/\s/.test(chars[i - 1]))
|
|
143
148
|
i--;
|
|
144
149
|
return i === s.cursor ? s : { ...s, cursor: i };
|
|
145
150
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zames_pro",
|
|
3
|
-
"version": "2.80.
|
|
3
|
+
"version": "2.80.8",
|
|
4
4
|
"description": "Terminal coding agent that drives a real browser to chat with DeepSeek, Qwen and other web LLMs — no API key required. Reads and edits files, runs commands, commits to git, like Claude Code / Codex CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|