zames_pro 2.82.69 → 2.82.71

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,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.82.71] - 2026-10-24
11
+
12
+ ### Fixed
13
+
14
+ - **prompt:** Backspace deletes a whole code point in promptOnce
15
+
16
+ ## [2.82.70] - 2026-10-24
17
+
18
+ ### Fixed
19
+
20
+ - **transcript:** keep a capped line valid JSON so the event is not lost
21
+
10
22
  ## [2.82.69] - 2026-10-24
11
23
 
12
24
  ### Fixed
package/dist/prompt.js CHANGED
@@ -139,10 +139,17 @@ export async function promptOnce(question) {
139
139
  continue;
140
140
  }
141
141
  if (code === 127 || code === 8) {
142
- // Backspace.
142
+ // Backspace deletes a CODE POINT, not one UTF-16 unit: an emoji is
143
+ // two units, and removing one left a LONE surrogate in the line — a
144
+ // broken code point the caller then received as the answer.
143
145
  if (cursor > 0) {
144
- line = line.slice(0, cursor - 1) + line.slice(cursor);
145
- cursor--;
146
+ const prev = line.charCodeAt(cursor - 1);
147
+ const low = prev >= 0xdc00 && prev <= 0xdfff;
148
+ const hi = cursor >= 2 ? line.charCodeAt(cursor - 2) : 0;
149
+ const pair = low && hi >= 0xd800 && hi <= 0xdbff;
150
+ const cut = pair ? cursor - 2 : cursor - 1;
151
+ line = line.slice(0, cut) + line.slice(cursor);
152
+ cursor = cut;
146
153
  redraw();
147
154
  }
148
155
  continue;
@@ -46,6 +46,60 @@ export function rotateTranscripts(dir, keep = MAX_TRANSCRIPT_FILES) {
46
46
  }
47
47
  return removed;
48
48
  }
49
+ /**
50
+ * Re-serialize an oversized event with its LONG STRING FIELDS cut, so the line
51
+ * stays VALID JSON. A raw slice + ellipsis produced an unparsable line and
52
+ * parseTranscript() silently dropped the whole event — /cost and /export lost
53
+ * the turn that produced a big tool result.
54
+ */
55
+ function capTranscriptLine(entry) {
56
+ const budget = TRANSCRIPT_LINE_CAP - 2;
57
+ // A binary search over the per-string allowance keeps the result close to
58
+ // the cap without serializing a 200 KB payload over and over.
59
+ let lo = 0;
60
+ let hi = budget;
61
+ let best = '';
62
+ for (let i = 0; i < 24; i++) {
63
+ const allow = Math.floor((lo + hi) / 2);
64
+ const line = JSON.stringify(trimStrings(entry, allow)) + String.fromCharCode(10);
65
+ if (line.length <= TRANSCRIPT_LINE_CAP) {
66
+ best = line;
67
+ lo = allow;
68
+ }
69
+ else {
70
+ hi = allow;
71
+ }
72
+ if (lo >= hi)
73
+ break;
74
+ }
75
+ if (best)
76
+ return best;
77
+ // Degenerate (the keys alone exceed the cap): keep a VALID minimal event.
78
+ return (JSON.stringify({ type: entry.type, truncated: true }) +
79
+ String.fromCharCode(10));
80
+ }
81
+ /** Deep-copy `entry`, cutting every string longer than `allow` (surrogate-safe). */
82
+ function trimStrings(v, allow) {
83
+ if (typeof v === 'string') {
84
+ if (v.length <= allow)
85
+ return v;
86
+ let cut = Math.max(0, allow);
87
+ const last = v.charCodeAt(cut - 1);
88
+ if (last >= 0xd800 && last <= 0xdbff)
89
+ cut--;
90
+ return v.slice(0, cut) + '…';
91
+ }
92
+ if (Array.isArray(v))
93
+ return v.map((x) => trimStrings(x, allow));
94
+ if (v && typeof v === 'object') {
95
+ const out = {};
96
+ for (const [k, x] of Object.entries(v)) {
97
+ out[k] = trimStrings(x, allow);
98
+ }
99
+ return out;
100
+ }
101
+ return v;
102
+ }
49
103
  function transcriptErrorLine(e) {
50
104
  return `transcript: failed to create file: ${e.message}`;
51
105
  }
@@ -108,11 +162,7 @@ export class Transcript {
108
162
  // transcript a LOG: cap each line with a marker (never splitting a
109
163
  // surrogate pair).
110
164
  if (line.length > TRANSCRIPT_LINE_CAP) {
111
- let cut = TRANSCRIPT_LINE_CAP - 2;
112
- const last = line.charCodeAt(cut - 1);
113
- if (last >= 0xd800 && last <= 0xdbff)
114
- cut--;
115
- line = line.slice(0, cut) + '…' + String.fromCharCode(10);
165
+ line = capTranscriptLine(entry);
116
166
  }
117
167
  // The mirror runs even when the file is disabled (jsonl mode).
118
168
  if (this.onLine) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.82.69",
3
+ "version": "2.82.71",
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": {