zames_pro 2.82.38 → 2.82.41

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 CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.82.41] - 2026-10-22
11
+
12
+ ### Fixed
13
+
14
+ - **telemetry:** accept a stringified blockMs in the average
15
+
16
+ ## [2.82.40] - 2026-10-22
17
+
18
+ ### Fixed
19
+
20
+ - **transcript:** cap a single logged payload
21
+
22
+ ## [2.82.39] - 2026-10-22
23
+
24
+ ### Fixed
25
+
26
+ - **config:** do not mask a whitespace-only password
27
+
10
28
  ## [2.82.38] - 2026-10-22
11
29
 
12
30
  ### Fixed
@@ -26,8 +26,11 @@ export function configListValue(field, value, t) {
26
26
  export function configGetValue(path, value, t) {
27
27
  if (value === undefined)
28
28
  return t('cfg.menu.default');
29
- if (/password/i.test(path) && String(value).length > 0)
29
+ // Mask a real secret, but NOT a whitespace-only one: it cannot log in, and
30
+ // hiding it makes `/config get` look like a password is configured.
31
+ if (/password/i.test(path) && String(value).trim().length > 0) {
30
32
  return '********';
33
+ }
31
34
  return JSON.stringify(value);
32
35
  }
33
36
  /**
@@ -45,12 +45,12 @@ export function summarizeSends(events, now = Date.now()) {
45
45
  const t = Date.parse(e.at);
46
46
  return Number.isFinite(t) && now - t <= ms;
47
47
  }).length;
48
+ // `blockMs` may arrive as a NUMBER (the writer) or a string (an older
49
+ // build, a hand-edited file): a numeric string is accepted so the average
50
+ // is not silently 0 for a file that records the block.
48
51
  const blocks = events
49
- .filter((e) => e.outcome === 'rate_limit' &&
50
- typeof e.blockMs === 'number' &&
51
- Number.isFinite(e.blockMs) &&
52
- e.blockMs >= 0)
53
- .map((e) => e.blockMs);
52
+ .map((e) => Number(e.blockMs))
53
+ .filter((n) => Number.isFinite(n) && n >= 0);
54
54
  const avgBlockMs = blocks.length
55
55
  ? Math.round(blocks.reduce((a, b) => a + b, 0) / blocks.length)
56
56
  : 0;
@@ -34,6 +34,8 @@ export function rotateTranscripts(dir, keep = MAX_TRANSCRIPT_FILES) {
34
34
  function transcriptErrorLine(e) {
35
35
  return `transcript: failed to create file: ${e.message}`;
36
36
  }
37
+ /** Hard cap on one transcript line (a single `log` payload). */
38
+ export const TRANSCRIPT_LINE_CAP = 100_000;
37
39
  export class Transcript {
38
40
  enabled;
39
41
  file;
@@ -84,7 +86,19 @@ export class Transcript {
84
86
  type,
85
87
  ...data,
86
88
  };
87
- const line = JSON.stringify(entry) + String.fromCharCode(10);
89
+ let line = JSON.stringify(entry) + String.fromCharCode(10);
90
+ // One `log` call may carry a tool result, a page dump or a fetched
91
+ // document; an uncapped line makes the transcript grow by megabytes per
92
+ // event, and /cost + /export then load it all into memory. Keep the
93
+ // transcript a LOG: cap each line with a marker (never splitting a
94
+ // surrogate pair).
95
+ if (line.length > TRANSCRIPT_LINE_CAP) {
96
+ let cut = TRANSCRIPT_LINE_CAP - 2;
97
+ const last = line.charCodeAt(cut - 1);
98
+ if (last >= 0xd800 && last <= 0xdbff)
99
+ cut--;
100
+ line = line.slice(0, cut) + '…' + String.fromCharCode(10);
101
+ }
88
102
  // The mirror runs even when the file is disabled (jsonl mode).
89
103
  if (this.onLine) {
90
104
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.82.38",
3
+ "version": "2.82.41",
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": {