zames_pro 2.84.0 → 2.85.0

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,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.85.0] - 2026-10-27
11
+
12
+ ### Added
13
+
14
+ - **ui:** theme the window background, keep the unsent draft, drop the extra prompt caret
15
+
10
16
  ## [2.84.0] - 2026-10-27
11
17
 
12
18
  ### Added
package/README.md CHANGED
@@ -38,7 +38,7 @@ lock-in. Install with `npm install -g zames_pro`, run `zames` in any project
38
38
  folder, and describe the task in plain language.
39
39
 
40
40
  <p align="center">
41
- <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/demo.png" alt="zames terminal coding agent session — an AI coding agent working in the command line without an API key" width="860">
41
+ <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/shots/theme-zames.png" alt="zames terminal coding agent session — an AI coding agent working in the command line without an API key" width="860">
42
42
  </p>
43
43
 
44
44
  ## Quick start
@@ -635,7 +635,12 @@ are ports of well-known editor schemes:
635
635
  `rose-pine`, `everforest`, `kanagawa`.
636
636
 
637
637
  A theme repaints EVERYTHING: the interface, the agent's answers, the code
638
- highlighting inside them, the status row and the input frame. To make the choice
638
+ highlighting inside them, the status row and the input frame. The terminal's
639
+ BACKGROUND follows too: the theme emits OSC-11 with the palette's `bg`
640
+ (supported by iTerm2, Windows Terminal, kitty, WezTerm, Alacritty, GNOME
641
+ Terminal and others; where it is not supported nothing happens). Opt out with
642
+ `ZAMES_NO_BG=1` or `NO_COLOR`.
643
+ To make the choice
639
644
  concrete, a SAMPLE SESSION in that palette is shown before you pick (in `/theme`
640
645
  below the list, in `/config` press `p` on the theme row); after
641
646
  `/theme <id>` the sample is printed too. The frame itself is a separate
@@ -761,7 +766,7 @@ Qwen или GLM) в агента для командной строки в ду
761
766
  можно описать обычным языком.
762
767
 
763
768
  <p align="center">
764
- <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/demo.png" alt="сессия zames в терминале — терминальный coding-агент и AI-ассистент программиста без API-ключа" width="860">
769
+ <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/shots/theme-zames.png" alt="сессия zames в терминале — терминальный coding-агент и AI-ассистент программиста без API-ключа" width="860">
765
770
  </p>
766
771
 
767
772
  ## Быстрый старт
@@ -1367,7 +1372,11 @@ enum переключаются на месте; числа и строки от
1367
1372
  `rose-pine`, `everforest`, `kanagawa`.
1368
1373
 
1369
1374
  Тема перекрашивает ВСЁ: интерфейс, ответы агента, подсветку кода в ответах,
1370
- строку статуса и рамку ввода. Чтобы было видно, ЧТО меняется, перед выбором
1375
+ строку статуса и рамку ввода. ФОН окна терминала тоже перекрашивается: тема
1376
+ шлёт OSC-11 с цветом `bg` палитры (поддерживают iTerm2, Windows Terminal,
1377
+ kitty, WezTerm, Alacritty, GNOME Terminal и др.; где не поддерживается — просто
1378
+ ничего не происходит). Отключить фон: `ZAMES_NO_BG=1` или `NO_COLOR`.
1379
+ Чтобы было видно, ЧТО меняется, перед выбором
1371
1380
  показывается образец сессии в этой палитре (в `/theme` — под списком, в
1372
1381
  `/config` — клавиша `p` на строке темы). После применения `/theme <id>`
1373
1382
  образец печатается в терминал. Саму рамку можно менять отдельно:
package/dist/index.js CHANGED
@@ -1519,8 +1519,9 @@ async function main() {
1519
1519
  theme.dim(') '));
1520
1520
  }
1521
1521
  // No working-directory tail: it ate input width and is already in the
1522
- // header / /pwd. A bare prompt keeps room for the task text.
1523
- return theme.prompt('❯ ') + theme.dim('› ');
1522
+ // header / /pwd. A bare `❯ ` keeps room for the task text and does not
1523
+ // read as a SECOND prompt marker next to the cursor.
1524
+ return theme.prompt('❯ ');
1524
1525
  };
1525
1526
  await refreshDynamicCommands(currentWorkdir);
1526
1527
  if (process.stdin.isTTY && process.stdout.isTTY) {
@@ -2446,9 +2447,6 @@ async function main() {
2446
2447
  theme.dir(reviewMode.snapName) +
2447
2448
  theme.dim(') ');
2448
2449
  }
2449
- else {
2450
- tail = theme.dim('› ');
2451
- }
2452
2450
  input = await promptOnce(theme.prompt('❯ ') + tail);
2453
2451
  }
2454
2452
  }
package/dist/theme.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { contentWidth } from './width.js';
3
+ import { applyBackground } from './tui/background.js';
3
4
  // Respect NO_COLOR (https://no-color.org): when the operator sets it (any
4
5
  // non-empty value) drop ALL SGR codes so the output can be piped into a file
5
6
  // or a log viewer without escape noise. chalk 5 only auto-detects TTY/CI, it
@@ -367,6 +368,9 @@ export function applyTheme(name) {
367
368
  theme[key] = built[key];
368
369
  }
369
370
  activeName = next;
371
+ // The window background is part of the look: paint it (best effort) so a
372
+ // dark palette does not sit on a light terminal background.
373
+ applyBackground(next);
370
374
  return next;
371
375
  }
372
376
  /**
@@ -12,7 +12,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
12
12
  import { Box, Text, useInput, usePaste, useCursor, useWindowSize, useStdin, } from 'ink';
13
13
  import { translate } from '../i18n.js';
14
14
  import { expandPastes, inputInnerCols, layoutInput, SUGGEST_PAGE, } from '../input/layout.js';
15
- import { insertText, insertPaste, insertNewline, backspace, del, moveLeft, moveRight, moveHome, moveEnd, wordLeft, wordRight, deleteWordLeft, deleteWordRight, killToLineEnd, moveVisualRows, pushUndo, undoEdit, historyUp, historyDown, searchStart, searchNext, searchAccept, searchCancel, searchInput, searchBackspace, recordHistory, afterSubmit, } from './edit.js';
15
+ import { insertText, insertPaste, insertNewline, backspace, del, moveLeft, moveRight, moveHome, moveEnd, wordLeft, wordRight, deleteWordLeft, deleteWordRight, killToLineEnd, moveVisualRows, pushUndo, undoEdit, historyUp, historyDown, searchStart, searchNext, searchAccept, searchCancel, searchInput, searchBackspace, recordHistory, afterSubmit, rememberDraft, } from './edit.js';
16
16
  import { dispatchKey, parseCsiU } from './keys.js';
17
17
  import { useSyncExternalStore } from 'react';
18
18
  import { matchSlashCommands, suggestWindow, completeSlashCommand, } from '../input/suggest.js';
@@ -125,17 +125,20 @@ export function InputLine(props) {
125
125
  case 'submit':
126
126
  doSubmit();
127
127
  return;
128
+ // The EDIT actions first write the line into the draft slot, so a
129
+ // remembered draft is replaced only by a REAL edit and an accidental
130
+ // Up cannot lose the typed message.
128
131
  case 'newline':
129
- apply(insertNewline);
132
+ apply((s) => pushUndo(rememberDraft(insertNewline(s)), true));
130
133
  return;
131
134
  case 'insert':
132
- apply((s) => pushUndo(insertText(s, action.text), true));
135
+ apply((s) => pushUndo(rememberDraft(insertText(s, action.text)), true));
133
136
  return;
134
137
  case 'backspace':
135
- apply((s) => backspace(pushUndo(s, true)));
138
+ apply((s) => backspace(pushUndo(rememberDraft(s), true)));
136
139
  return;
137
140
  case 'delete':
138
- apply((s) => del(pushUndo(s, true)));
141
+ apply((s) => del(pushUndo(rememberDraft(s), true)));
139
142
  return;
140
143
  case 'left':
141
144
  apply(moveLeft);
@@ -0,0 +1,42 @@
1
+ // Terminal BACKGROUND handling.
2
+ //
3
+ // A terminal cannot be told to paint "the background" — only the cells an app
4
+ // writes are styled. So a theme's `bg` reaches the screen by
5
+ // 1. emitting an OSC-11 background colour for the whole window (most modern
6
+ // terminals support it; a terminal that does not answers nothing), and
7
+ // 2. re-emitting it AFTER a full-screen app exits: the alternate screen keeps
8
+ // the window's background, and Ink's exit sequence resets attributes
9
+ // (SGR reset does not touch OSC-11, but some terminals do reset the colour
10
+ // on 1049l). Re-emitting is harmless where unsupported.
11
+ //
12
+ // The OSC sequence is written STRAIGHT to stdout (not through chalk), because
13
+ // it is not an SGR attribute: `\x1b]11;rgb:rr/gg/bb\x07`.
14
+ import { PALETTES, isThemeName, DEFAULT_THEME } from '../theme.js';
15
+ /** `#rrggbb` -> the `rr/gg/bb` part of an OSC-11 payload. */
16
+ function hexToOsc(hex) {
17
+ const h = hex.replace('#', '');
18
+ return `${h.slice(0, 2)}/${h.slice(2, 4)}/${h.slice(4, 6)}`;
19
+ }
20
+ /**
21
+ * The OSC-11 sequence that sets the window background, or '' when the operator
22
+ * opted out (NO_COLOR / ZAMES_NO_BG). Exported pure, so the encoding is
23
+ * testable without a terminal.
24
+ */
25
+ export function backgroundOsc(name) {
26
+ if (process.env.NO_COLOR || process.env.ZAMES_NO_BG)
27
+ return '';
28
+ const id = isThemeName(name) ? name : DEFAULT_THEME;
29
+ return '\x1b]11;rgb:' + hexToOsc(PALETTES[id].bg) + '\x07';
30
+ }
31
+ /** Paint the window background for the palette `name` (best effort). */
32
+ export function applyBackground(name) {
33
+ const seq = backgroundOsc(name);
34
+ if (!seq)
35
+ return;
36
+ try {
37
+ process.stdout.write(seq);
38
+ }
39
+ catch {
40
+ // A closed/redirected stdout must not break a theme switch.
41
+ }
42
+ }
package/dist/tui/edit.js CHANGED
@@ -249,9 +249,11 @@ export function historyUp(s) {
249
249
  if (!s.history.length)
250
250
  return s;
251
251
  let histIndex = s.histIndex;
252
- let histDraft = s.histDraft;
253
- if (histIndex === s.history.length)
254
- histDraft = s.buf;
252
+ // Snapshot the unsent line when the browse STARTS (histIndex is at the end),
253
+ // but NEVER replace the remembered draft with a RECALLED entry's text: a
254
+ // second Up after a Down used to overwrite it, and the operator's typed
255
+ // message was lost ("pressed Up by accident").
256
+ const histDraft = histIndex === s.history.length ? s.buf : s.histDraft;
255
257
  if (histIndex > 0) {
256
258
  histIndex--;
257
259
  const buf = s.history[histIndex];
@@ -269,6 +271,10 @@ export function historyDown(s) {
269
271
  if (!s.history.length)
270
272
  return s;
271
273
  let histIndex = s.histIndex;
274
+ // The CURRENT line is the operator's, not a history entry: leaving the
275
+ // history must bring it back. Without this, editing a recalled line and then
276
+ // pressing Down restored the OLD draft and dropped the edit.
277
+ const draft = browsingHistory(s) ? s.histDraft : s.buf;
272
278
  let buf;
273
279
  if (histIndex < s.history.length - 1) {
274
280
  histIndex++;
@@ -276,9 +282,38 @@ export function historyDown(s) {
276
282
  }
277
283
  else {
278
284
  histIndex = s.history.length;
279
- buf = s.histDraft;
285
+ buf = draft;
280
286
  }
281
- return { ...s, histIndex, buf, cursor: Array.from(buf).length };
287
+ return {
288
+ ...s,
289
+ histIndex,
290
+ histDraft: draft,
291
+ buf,
292
+ cursor: Array.from(buf).length,
293
+ };
294
+ }
295
+ // ---------- draft guard ----------
296
+ //
297
+ // The operator's UNSUBMITTED line must survive a history browse, arrow-key
298
+ // scrolling and every other non-typing transition. `histDraft` alone did not:
299
+ // it is snapshotted only when the browse STARTS (histIndex === history.length),
300
+ // so once the cursor was inside the history an edit or a second Up path could
301
+ // replace it — a real report was "I pressed Up by accident and my typed message
302
+ // was gone".
303
+ //
304
+ // The rule: typing/recalling may change the visible buffer, but a transition
305
+ // that is NOT an explicit edit must keep the draft; leaving the history restores
306
+ // it. `typingRun` is true while the operator types (so a real edit adopts the new
307
+ // text as the draft on the next browse).
308
+ /** True while the buffer is a RECALLED history entry (not the draft). */
309
+ export function browsingHistory(s) {
310
+ return s.history.length > 0 && s.histIndex < s.history.length;
311
+ }
312
+ /** Remember the current buffer as the draft when it is NOT a history entry. */
313
+ export function rememberDraft(s) {
314
+ if (s.buf === s.histDraft)
315
+ return s;
316
+ return { ...s, histDraft: s.buf };
282
317
  }
283
318
  export function searchStart(s) {
284
319
  if (!s.history.length)
package/llms-full.txt CHANGED
@@ -23,7 +23,7 @@ lock-in. Install with `npm install -g zames_pro`, run `zames` in any project
23
23
  folder, and describe the task in plain language.
24
24
 
25
25
  <p align="center">
26
- <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/demo.png" alt="zames terminal coding agent session — an AI coding agent working in the command line without an API key" width="860">
26
+ <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/shots/theme-zames.png" alt="zames terminal coding agent session — an AI coding agent working in the command line without an API key" width="860">
27
27
  </p>
28
28
 
29
29
  ## Quick start
@@ -620,7 +620,12 @@ are ports of well-known editor schemes:
620
620
  `rose-pine`, `everforest`, `kanagawa`.
621
621
 
622
622
  A theme repaints EVERYTHING: the interface, the agent's answers, the code
623
- highlighting inside them, the status row and the input frame. To make the choice
623
+ highlighting inside them, the status row and the input frame. The terminal's
624
+ BACKGROUND follows too: the theme emits OSC-11 with the palette's `bg`
625
+ (supported by iTerm2, Windows Terminal, kitty, WezTerm, Alacritty, GNOME
626
+ Terminal and others; where it is not supported nothing happens). Opt out with
627
+ `ZAMES_NO_BG=1` or `NO_COLOR`.
628
+ To make the choice
624
629
  concrete, a SAMPLE SESSION in that palette is shown before you pick (in `/theme`
625
630
  below the list, in `/config` press `p` on the theme row); after
626
631
  `/theme <id>` the sample is printed too. The frame itself is a separate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.84.0",
3
+ "version": "2.85.0",
4
4
  "description": "Terminal coding agent that drives a real browser to chat with DeepSeek, Qwen or GLM — 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": {