zames_pro 2.83.4 → 2.84.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 +6 -0
- package/README.md +16 -7
- package/dist/i18n/deepseek.js +8 -0
- package/dist/index.js +8 -0
- package/dist/theme.js +128 -0
- package/dist/tui/ConfigMenu.js +33 -1
- package/dist/tui/ThemePicker.js +2 -16
- package/dist/tui/theme-preview.js +45 -0
- package/llms-full.txt +6 -2
- package/package.json +3 -2
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.84.0] - 2026-10-27
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **ui:** theme previews, 6 more palettes, inline /config preview
|
|
15
|
+
|
|
10
16
|
## [2.83.4] - 2026-10-27
|
|
11
17
|
|
|
12
18
|
### Fixed
|
package/README.md
CHANGED
|
@@ -631,10 +631,14 @@ The switch is instant, no restart. `zames` is the default; the bundled palettes
|
|
|
631
631
|
are ports of well-known editor schemes:
|
|
632
632
|
|
|
633
633
|
`zames` (default), `one-dark`, `dracula`, `gruvbox`, `nord`, `monokai`,
|
|
634
|
-
`solarized-dark`, `tokyo-night
|
|
634
|
+
`solarized-dark`, `tokyo-night`, `catppuccin`, `github-dark`, `ayu`,
|
|
635
|
+
`rose-pine`, `everforest`, `kanagawa`.
|
|
635
636
|
|
|
636
637
|
A theme repaints EVERYTHING: the interface, the agent's answers, the code
|
|
637
|
-
highlighting inside them and the input frame.
|
|
638
|
+
highlighting inside them, the status row and the input frame. To make the choice
|
|
639
|
+
concrete, a SAMPLE SESSION in that palette is shown before you pick (in `/theme`
|
|
640
|
+
below the list, in `/config` press `p` on the theme row); after
|
|
641
|
+
`/theme <id>` the sample is printed too. The frame itself is a separate
|
|
638
642
|
setting: `/config set ui.inputBorder <round|single|double|bold|none>`
|
|
639
643
|
(default `round`; `none` removes it).
|
|
640
644
|
|
|
@@ -1359,11 +1363,16 @@ enum переключаются на месте; числа и строки от
|
|
|
1359
1363
|
редакторов:
|
|
1360
1364
|
|
|
1361
1365
|
`zames` (по умолчанию), `one-dark`, `dracula`, `gruvbox`, `nord`, `monokai`,
|
|
1362
|
-
`solarized-dark`, `tokyo-night
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1366
|
+
`solarized-dark`, `tokyo-night`, `catppuccin`, `github-dark`, `ayu`,
|
|
1367
|
+
`rose-pine`, `everforest`, `kanagawa`.
|
|
1368
|
+
|
|
1369
|
+
Тема перекрашивает ВСЁ: интерфейс, ответы агента, подсветку кода в ответах,
|
|
1370
|
+
строку статуса и рамку ввода. Чтобы было видно, ЧТО меняется, перед выбором
|
|
1371
|
+
показывается образец сессии в этой палитре (в `/theme` — под списком, в
|
|
1372
|
+
`/config` — клавиша `p` на строке темы). После применения `/theme <id>`
|
|
1373
|
+
образец печатается в терминал. Саму рамку можно менять отдельно:
|
|
1374
|
+
`/config set ui.inputBorder <round|single|double|bold|none>` (по умолчанию
|
|
1375
|
+
`round`, `none` — без рамки).
|
|
1367
1376
|
|
|
1368
1377
|
Данные агента хранятся в `~/.zames`: профиль браузера, логи, история undo,
|
|
1369
1378
|
сессии.
|
package/dist/i18n/deepseek.js
CHANGED
|
@@ -212,6 +212,14 @@ export const deepseekMessages = {
|
|
|
212
212
|
ru: '✔ Сохранено: {v} = {value}',
|
|
213
213
|
en: '✔ Saved: {v} = {value}',
|
|
214
214
|
},
|
|
215
|
+
'cfg.menu.theme_preview': {
|
|
216
|
+
ru: 'Так тема выглядит в работе:',
|
|
217
|
+
en: 'How the theme looks in a session:',
|
|
218
|
+
},
|
|
219
|
+
'cfg.menu.theme_preview_key': {
|
|
220
|
+
ru: 'пример темы',
|
|
221
|
+
en: 'theme sample',
|
|
222
|
+
},
|
|
215
223
|
'cfg.menu.default': { ru: 'по умолчанию', en: 'default' },
|
|
216
224
|
'cfg.menu.filter_hint': {
|
|
217
225
|
ru: '/ — поиск по настройкам, d — сбросить (дважды), * — изменено от дефолта',
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from 'fs/promises';
|
|
|
5
5
|
import { readFileSync, statSync } from 'fs';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { theme, applyTheme, themeColors, themeNames, currentThemeName, isThemeName, } from './theme.js';
|
|
8
|
+
import { themePreviewAnsi } from './tui/theme-preview.js';
|
|
8
9
|
import { setInputBorder } from './tui/ui-colors.js';
|
|
9
10
|
import { DeepSeekBrowser, headlessUACacheReady } from './browser.js';
|
|
10
11
|
import { QwenBrowser } from './qwen-browser.js';
|
|
@@ -2249,6 +2250,11 @@ async function main() {
|
|
|
2249
2250
|
return;
|
|
2250
2251
|
}
|
|
2251
2252
|
emit(theme.assistant(t('theme.set', { v: applyThemeById(arg) })));
|
|
2253
|
+
// A terminal can only show colors it can paint, and the operator asked
|
|
2254
|
+
// "what exactly changes?" — print a sample of every role in the new
|
|
2255
|
+
// palette right below the confirmation.
|
|
2256
|
+
emit('');
|
|
2257
|
+
emit(themePreviewAnsi(arg));
|
|
2252
2258
|
return;
|
|
2253
2259
|
}
|
|
2254
2260
|
// No argument: a pick list in the TUI, the id list otherwise. The cursor
|
|
@@ -2278,6 +2284,8 @@ async function main() {
|
|
|
2278
2284
|
}
|
|
2279
2285
|
if (picked) {
|
|
2280
2286
|
emit(theme.assistant(t('theme.set', { v: applyThemeById(picked) })));
|
|
2287
|
+
emit('');
|
|
2288
|
+
emit(themePreviewAnsi(picked));
|
|
2281
2289
|
}
|
|
2282
2290
|
else {
|
|
2283
2291
|
// Cancelled: the previews must not stick. Restore WITHOUT persisting.
|
package/dist/theme.js
CHANGED
|
@@ -179,6 +179,134 @@ export const PALETTES = {
|
|
|
179
179
|
brown: '#ff9e64',
|
|
180
180
|
toggleOn: '#73daca',
|
|
181
181
|
},
|
|
182
|
+
// Catppuccin Mocha — the soft pastel palette that took over the editor
|
|
183
|
+
// ecosystem (Neovim, VS Code, terminals).
|
|
184
|
+
catppuccin: {
|
|
185
|
+
bg: '#1e1e2e',
|
|
186
|
+
user: '#89b4fa',
|
|
187
|
+
userBar: '#5477a8',
|
|
188
|
+
turnRule: '#313244',
|
|
189
|
+
turnLabel: '#6c7086',
|
|
190
|
+
prompt: '#f9e2af',
|
|
191
|
+
dir: '#89dceb',
|
|
192
|
+
assistant: '#cdd6f4',
|
|
193
|
+
tool: '#fab387',
|
|
194
|
+
toolResult: '#a6adc8',
|
|
195
|
+
system: '#9399b2',
|
|
196
|
+
dim: '#6c7086',
|
|
197
|
+
taskSummary: '#89b4fa',
|
|
198
|
+
warn: '#f9e2af',
|
|
199
|
+
error: '#f38ba8',
|
|
200
|
+
success: '#a6e3a1',
|
|
201
|
+
brown: '#eba0ac',
|
|
202
|
+
toggleOn: '#94e2d5',
|
|
203
|
+
},
|
|
204
|
+
// GitHub Dark — the palette of GitHub's dark UI (familiar to anyone who
|
|
205
|
+
// reads diffs all day).
|
|
206
|
+
'github-dark': {
|
|
207
|
+
bg: '#0d1117',
|
|
208
|
+
user: '#58a6ff',
|
|
209
|
+
userBar: '#3a6ea8',
|
|
210
|
+
turnRule: '#21262d',
|
|
211
|
+
turnLabel: '#6e7681',
|
|
212
|
+
prompt: '#d29922',
|
|
213
|
+
dir: '#79c0ff',
|
|
214
|
+
assistant: '#c9d1d9',
|
|
215
|
+
tool: '#ffa657',
|
|
216
|
+
toolResult: '#8b949e',
|
|
217
|
+
system: '#8b949e',
|
|
218
|
+
dim: '#6e7681',
|
|
219
|
+
taskSummary: '#a5d6ff',
|
|
220
|
+
warn: '#d29922',
|
|
221
|
+
error: '#f85149',
|
|
222
|
+
success: '#3fb950',
|
|
223
|
+
brown: '#db6d28',
|
|
224
|
+
toggleOn: '#56d4dd',
|
|
225
|
+
},
|
|
226
|
+
// Ayu Dark — the minimal warm-accent scheme from the Ayu editor theme.
|
|
227
|
+
ayu: {
|
|
228
|
+
bg: '#0f1419',
|
|
229
|
+
user: '#59c2ff',
|
|
230
|
+
userBar: '#35789e',
|
|
231
|
+
turnRule: '#1f2430',
|
|
232
|
+
turnLabel: '#5c6773',
|
|
233
|
+
prompt: '#ffb454',
|
|
234
|
+
dir: '#59c2ff',
|
|
235
|
+
assistant: '#c7ccd1',
|
|
236
|
+
tool: '#ff8f40',
|
|
237
|
+
toolResult: '#a0a8b0',
|
|
238
|
+
system: '#8a9199',
|
|
239
|
+
dim: '#5c6773',
|
|
240
|
+
taskSummary: '#39bae6',
|
|
241
|
+
warn: '#ffb454',
|
|
242
|
+
error: '#f07178',
|
|
243
|
+
success: '#aad94c',
|
|
244
|
+
brown: '#e6b450',
|
|
245
|
+
toggleOn: '#95e6cb',
|
|
246
|
+
},
|
|
247
|
+
// Rosé Pine — muted rose-pine tones, a calmer alternative to Dracula.
|
|
248
|
+
'rose-pine': {
|
|
249
|
+
bg: '#191724',
|
|
250
|
+
user: '#9ccfd8',
|
|
251
|
+
userBar: '#5b8490',
|
|
252
|
+
turnRule: '#26233a',
|
|
253
|
+
turnLabel: '#6e6a86',
|
|
254
|
+
prompt: '#f6c177',
|
|
255
|
+
dir: '#9ccfd8',
|
|
256
|
+
assistant: '#e0def4',
|
|
257
|
+
tool: '#ebbcba',
|
|
258
|
+
toolResult: '#908caa',
|
|
259
|
+
system: '#908caa',
|
|
260
|
+
dim: '#6e6a86',
|
|
261
|
+
taskSummary: '#c4a7e7',
|
|
262
|
+
warn: '#f6c177',
|
|
263
|
+
error: '#eb6f92',
|
|
264
|
+
success: '#31748f',
|
|
265
|
+
brown: '#ebbcba',
|
|
266
|
+
toggleOn: '#9ccfd8',
|
|
267
|
+
},
|
|
268
|
+
// Everforest — the soft green forest palette (low contrast, easy on eyes).
|
|
269
|
+
everforest: {
|
|
270
|
+
bg: '#2d353b',
|
|
271
|
+
user: '#7fbbb3',
|
|
272
|
+
userBar: '#5a8b85',
|
|
273
|
+
turnRule: '#3d484d',
|
|
274
|
+
turnLabel: '#859289',
|
|
275
|
+
prompt: '#dbbc7f',
|
|
276
|
+
dir: '#7fbbb3',
|
|
277
|
+
assistant: '#d3c6aa',
|
|
278
|
+
tool: '#e69875',
|
|
279
|
+
toolResult: '#9da9a0',
|
|
280
|
+
system: '#859289',
|
|
281
|
+
dim: '#7a8478',
|
|
282
|
+
taskSummary: '#a7c080',
|
|
283
|
+
warn: '#dbbc7f',
|
|
284
|
+
error: '#e67e80',
|
|
285
|
+
success: '#a7c080',
|
|
286
|
+
brown: '#e69875',
|
|
287
|
+
toggleOn: '#83c092',
|
|
288
|
+
},
|
|
289
|
+
// Kanagawa — Hokusai-inspired muted indigo (the "wave" theme).
|
|
290
|
+
kanagawa: {
|
|
291
|
+
bg: '#1f1f28',
|
|
292
|
+
user: '#7e9cd8',
|
|
293
|
+
userBar: '#55709e',
|
|
294
|
+
turnRule: '#2a2a37',
|
|
295
|
+
turnLabel: '#727169',
|
|
296
|
+
prompt: '#e6c384',
|
|
297
|
+
dir: '#7fb4ca',
|
|
298
|
+
assistant: '#dcd7ba',
|
|
299
|
+
tool: '#ffa066',
|
|
300
|
+
toolResult: '#a6a69c',
|
|
301
|
+
system: '#c8c093',
|
|
302
|
+
dim: '#727169',
|
|
303
|
+
taskSummary: '#957fb8',
|
|
304
|
+
warn: '#e6c384',
|
|
305
|
+
error: '#e46876',
|
|
306
|
+
success: '#98bb6c',
|
|
307
|
+
brown: '#d27e59',
|
|
308
|
+
toggleOn: '#7aa89f',
|
|
309
|
+
},
|
|
182
310
|
};
|
|
183
311
|
/** The palette id used when the configured theme is unknown/missing. */
|
|
184
312
|
export const DEFAULT_THEME = 'zames';
|
package/dist/tui/ConfigMenu.js
CHANGED
|
@@ -14,6 +14,7 @@ import { useMemo, useState } from 'react';
|
|
|
14
14
|
import { Box, Text, useInput, useApp, useWindowSize } from 'ink';
|
|
15
15
|
import { translate } from '../i18n.js';
|
|
16
16
|
import { Checkbox, Select, UI, HintBar } from './widgets.js';
|
|
17
|
+
import { ThemePreview } from './theme-preview.js';
|
|
17
18
|
/** Strip ANSI to measure a line's visible width. */
|
|
18
19
|
function stripAnsi(s) {
|
|
19
20
|
return s.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, '');
|
|
@@ -52,6 +53,8 @@ export function ConfigMenuApp(opts) {
|
|
|
52
53
|
const [editBuf, setEditBuf] = useState('');
|
|
53
54
|
const [pendingReset, setPendingReset] = useState(null);
|
|
54
55
|
const [message, setMessage] = useState(null);
|
|
56
|
+
// Inline palette preview of the theme row ('p').
|
|
57
|
+
const [previewTheme, setPreviewTheme] = useState(false);
|
|
55
58
|
// `get`/`set` mutate the LIVE config object in place, so React has no state
|
|
56
59
|
// change to react to and the row kept the OLD value on screen after a
|
|
57
60
|
// toggle/cycle (the operator saw «ru» while the config already held «en»).
|
|
@@ -216,12 +219,14 @@ export function ConfigMenuApp(opts) {
|
|
|
216
219
|
setCursor((c) => visible.length ? (c - 1 + visible.length) % visible.length : 0);
|
|
217
220
|
setPendingReset(null);
|
|
218
221
|
setMessage(null);
|
|
222
|
+
setPreviewTheme(false);
|
|
219
223
|
return;
|
|
220
224
|
}
|
|
221
225
|
if (key.downArrow || input === 'j') {
|
|
222
226
|
setCursor((c) => (visible.length ? (c + 1) % visible.length : 0));
|
|
223
227
|
setPendingReset(null);
|
|
224
228
|
setMessage(null);
|
|
229
|
+
setPreviewTheme(false);
|
|
225
230
|
return;
|
|
226
231
|
}
|
|
227
232
|
if (input === 'g') {
|
|
@@ -238,6 +243,30 @@ export function ConfigMenuApp(opts) {
|
|
|
238
243
|
setMessage(null);
|
|
239
244
|
return;
|
|
240
245
|
}
|
|
246
|
+
if (input === 'p' || input === 'P') {
|
|
247
|
+
// Inline palette PREVIEW for the theme row: the settings list is where
|
|
248
|
+
// most operators meet ui.theme, and cycling the enum only shows the id.
|
|
249
|
+
// 'p' opens the sample session painted with the CURRENT palette, so the
|
|
250
|
+
// choice can be judged without leaving /config. Other rows: no-op.
|
|
251
|
+
const f = visible[cursor];
|
|
252
|
+
if (f && f.path === 'ui.theme') {
|
|
253
|
+
setPreviewTheme((v) => !v);
|
|
254
|
+
setMessage(null);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (input === 'p' || input === 'P') {
|
|
259
|
+
// Inline palette PREVIEW on the theme row: /config is where most
|
|
260
|
+
// operators meet ui.theme, and cycling the enum only shows the id. 'p'
|
|
261
|
+
// toggles a sample session painted with the CURRENT palette, so the
|
|
262
|
+
// choice can be judged without leaving the menu. Other rows: no-op.
|
|
263
|
+
const f = visible[cursor];
|
|
264
|
+
if (f && f.path === 'ui.theme') {
|
|
265
|
+
setPreviewTheme((v) => !v);
|
|
266
|
+
setMessage(null);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
241
270
|
if (key.return || input === ' ') {
|
|
242
271
|
activate();
|
|
243
272
|
return;
|
|
@@ -336,10 +365,13 @@ export function ConfigMenuApp(opts) {
|
|
|
336
365
|
if (!visible.length) {
|
|
337
366
|
items.push(_jsx(Text, { color: UI.dim, children: ' ' + t('cfg.menu.no_match') }, "none"));
|
|
338
367
|
}
|
|
339
|
-
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: UI.border, paddingX: 1, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { bold: true, color: UI.title, children: t('cfg.menu.title') }), _jsx(Text, { color: UI.dim, children: (visible.length ? cursor + 1 : 0) + '/' + visible.length })] }), _jsx(Text, { color: UI.border, children: '─'.repeat(Math.max(10, (columns || 80) - 6)) }), items, _jsx(Text, { color: UI.border, children: '─'.repeat(Math.max(10, (columns || 80) - 6)) }), editing ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: UI.text, children: t('cfg.menu.edit_hint') }), _jsx(Text, { color: UI.accent, children: '❯ ' + editBuf })] })) : filterMode ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: UI.text, children: t('cfg.menu.filter_hint') }), _jsx(Text, { color: UI.accent, children: '❯ ' + filterQuery })] })) : message ? (_jsx(Text, { color: UI.ok, children: message })) : filterQuery ? (_jsx(Text, { color: UI.dim, children: t('cfg.menu.filter_active', { q: filterQuery }) })) : null, _jsx(HintBar, { hints: [
|
|
368
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: UI.border, paddingX: 1, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { bold: true, color: UI.title, children: t('cfg.menu.title') }), _jsx(Text, { color: UI.dim, children: (visible.length ? cursor + 1 : 0) + '/' + visible.length })] }), _jsx(Text, { color: UI.border, children: '─'.repeat(Math.max(10, (columns || 80) - 6)) }), items, _jsx(Text, { color: UI.border, children: '─'.repeat(Math.max(10, (columns || 80) - 6)) }), previewTheme && visible[cursor]?.path === 'ui.theme' ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: UI.dim, children: t('cfg.menu.theme_preview') }), _jsx(ThemePreview, { name: String(get('ui.theme') ?? 'zames'), compact: true })] })) : null, editing ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: UI.text, children: t('cfg.menu.edit_hint') }), _jsx(Text, { color: UI.accent, children: '❯ ' + editBuf })] })) : filterMode ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: UI.text, children: t('cfg.menu.filter_hint') }), _jsx(Text, { color: UI.accent, children: '❯ ' + filterQuery })] })) : message ? (_jsx(Text, { color: UI.ok, children: message })) : filterQuery ? (_jsx(Text, { color: UI.dim, children: t('cfg.menu.filter_active', { q: filterQuery }) })) : null, _jsx(HintBar, { hints: [
|
|
340
369
|
['↑/↓', hint('tui.hint.select')],
|
|
341
370
|
['←/→', hint('tui.hint.change')],
|
|
342
371
|
['Enter', hint('tui.hint.edit')],
|
|
372
|
+
...(visible[cursor]?.path === 'ui.theme'
|
|
373
|
+
? [['p', hint('cfg.menu.theme_preview_key')]]
|
|
374
|
+
: []),
|
|
343
375
|
['/', hint('tui.hint.search')],
|
|
344
376
|
['d', hint('tui.hint.reset')],
|
|
345
377
|
['q', hint('tui.hint.quit')],
|
package/dist/tui/ThemePicker.js
CHANGED
|
@@ -10,7 +10,7 @@ import { useState } from 'react';
|
|
|
10
10
|
import { Box, Text, useInput, useApp, useWindowSize } from 'ink';
|
|
11
11
|
import { UI } from './ui-colors.js';
|
|
12
12
|
import { HintBar } from './widgets.js';
|
|
13
|
-
import {
|
|
13
|
+
import { ThemePreview } from './theme-preview.js';
|
|
14
14
|
import { translate } from '../i18n.js';
|
|
15
15
|
export function ThemePicker({ themes, initial, onPreview, locale = 'en', onDone, }) {
|
|
16
16
|
const { exit } = useApp();
|
|
@@ -30,20 +30,6 @@ export function ThemePicker({ themes, initial, onPreview, locale = 'en', onDone,
|
|
|
30
30
|
setCursor(next);
|
|
31
31
|
onPreview(themes[next]);
|
|
32
32
|
};
|
|
33
|
-
// A sample line of every important role, colored through `theme` (chalk):
|
|
34
|
-
// Ink's <Text color> takes a hex STRING, not a formatter, so a gradient like
|
|
35
|
-
// this has to be pre-rendered ANSI.
|
|
36
|
-
const preview = () => [
|
|
37
|
-
theme.user('user'),
|
|
38
|
-
theme.assistant('answer'),
|
|
39
|
-
theme.tool('tool'),
|
|
40
|
-
theme.toolResult('result'),
|
|
41
|
-
theme.system('system'),
|
|
42
|
-
theme.warn('warn'),
|
|
43
|
-
theme.error('error'),
|
|
44
|
-
theme.success('ok'),
|
|
45
|
-
theme.toggleOn('on'),
|
|
46
|
-
].join(' ');
|
|
47
33
|
useInput((input, key) => {
|
|
48
34
|
if (key.escape || (key.ctrl && input === 'c') || input === 'q') {
|
|
49
35
|
finish(null);
|
|
@@ -63,7 +49,7 @@ export function ThemePicker({ themes, initial, onPreview, locale = 'en', onDone,
|
|
|
63
49
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: UI.border, paddingX: 1, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { color: UI.title, bold: true, children: '◆ ' + t('theme.pick_title') }), _jsx(Text, { color: UI.dim, children: themes.length })] }), _jsx(Text, { color: UI.border, children: '─'.repeat(innerCols) }), themes.map((name, idx) => {
|
|
64
50
|
const sel = idx === cursor;
|
|
65
51
|
return (_jsxs(Text, { children: [_jsx(Text, { color: UI.accent, children: sel ? '❯ ' : ' ' }), _jsx(Text, { color: sel ? UI.accent : undefined, bold: sel, children: name }), idx === start ? (_jsx(Text, { color: UI.dim, children: ' ' + t('tui.list.current') })) : null] }, name));
|
|
66
|
-
}), _jsx(Text, { color: UI.border, children: '─'.repeat(innerCols) }), _jsx(
|
|
52
|
+
}), _jsx(Text, { color: UI.border, children: '─'.repeat(innerCols) }), _jsx(ThemePreview, { name: themes[cursor] ?? initial, compact: true }), _jsx(HintBar, { hints: [
|
|
67
53
|
['↑/↓', t('theme.pick_move')],
|
|
68
54
|
['Enter', t('tui.hint.ok')],
|
|
69
55
|
['Esc', t('theme.pick_cancel')],
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { PALETTES, DEFAULT_THEME, isThemeName } from '../theme.js';
|
|
5
|
+
/**
|
|
6
|
+
* The sample lines. Kept PURE DATA so tests can assert the preview covers the
|
|
7
|
+
* important roles and the Ink/plain renderers cannot drift apart.
|
|
8
|
+
*/
|
|
9
|
+
export function previewLines() {
|
|
10
|
+
return [
|
|
11
|
+
{ role: 'dir', text: '~/project' },
|
|
12
|
+
{ role: 'prompt', text: '❯ объясни этот код', bold: true },
|
|
13
|
+
{ role: 'assistant', text: '● Ответ: функция читает файл и парсит JSON.' },
|
|
14
|
+
{ role: 'tool', text: '🔧 Read {"path":"package.json"}' },
|
|
15
|
+
{ role: 'toolResult', text: '→ ✔ 42 строки' },
|
|
16
|
+
{ role: 'taskSummary', text: '· duration: 6s · tools: 1' },
|
|
17
|
+
{ role: 'warn', text: '▲ предупреждение' },
|
|
18
|
+
{ role: 'error', text: '✖ ошибка' },
|
|
19
|
+
{ role: 'success', text: '✔ готово' },
|
|
20
|
+
{ role: 'toggleOn', text: '🌐 поиск вкл' },
|
|
21
|
+
{ role: 'system', text: '● сервисное сообщение' },
|
|
22
|
+
{ role: 'dim', text: '· подсказка' },
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
function paletteOf(name) {
|
|
26
|
+
return PALETTES[isThemeName(name) ? name : DEFAULT_THEME];
|
|
27
|
+
}
|
|
28
|
+
/** The preview as one chalk-painted string (for a plain terminal line). */
|
|
29
|
+
export function themePreviewAnsi(name) {
|
|
30
|
+
const p = paletteOf(name);
|
|
31
|
+
return previewLines()
|
|
32
|
+
.map((l) => {
|
|
33
|
+
const c = chalk.hex(p[l.role]);
|
|
34
|
+
return l.bold ? c.bold(l.text) : c(l.text);
|
|
35
|
+
})
|
|
36
|
+
.join('\n');
|
|
37
|
+
}
|
|
38
|
+
/** The preview as an Ink block (for the picker / the config menu). */
|
|
39
|
+
export function ThemePreview({ name, compact = false, }) {
|
|
40
|
+
const p = paletteOf(name);
|
|
41
|
+
const lines = compact
|
|
42
|
+
? previewLines().filter((l) => ['prompt', 'assistant', 'tool', 'error', 'success', 'dim'].includes(l.role))
|
|
43
|
+
: previewLines();
|
|
44
|
+
return (_jsx(Box, { flexDirection: "column", children: lines.map((l, i) => (_jsx(Text, { color: p[l.role], bold: l.bold, children: l.text }, i))) }));
|
|
45
|
+
}
|
package/llms-full.txt
CHANGED
|
@@ -616,10 +616,14 @@ The switch is instant, no restart. `zames` is the default; the bundled palettes
|
|
|
616
616
|
are ports of well-known editor schemes:
|
|
617
617
|
|
|
618
618
|
`zames` (default), `one-dark`, `dracula`, `gruvbox`, `nord`, `monokai`,
|
|
619
|
-
`solarized-dark`, `tokyo-night
|
|
619
|
+
`solarized-dark`, `tokyo-night`, `catppuccin`, `github-dark`, `ayu`,
|
|
620
|
+
`rose-pine`, `everforest`, `kanagawa`.
|
|
620
621
|
|
|
621
622
|
A theme repaints EVERYTHING: the interface, the agent's answers, the code
|
|
622
|
-
highlighting inside them and the input frame.
|
|
623
|
+
highlighting inside them, the status row and the input frame. To make the choice
|
|
624
|
+
concrete, a SAMPLE SESSION in that palette is shown before you pick (in `/theme`
|
|
625
|
+
below the list, in `/config` press `p` on the theme row); after
|
|
626
|
+
`/theme <id>` the sample is printed too. The frame itself is a separate
|
|
623
627
|
setting: `/config set ui.inputBorder <round|single|double|bold|none>`
|
|
624
628
|
(default `round`; `none` removes it).
|
|
625
629
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zames_pro",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.84.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": {
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"postinstall": "node scripts/postinstall.mjs",
|
|
48
48
|
"prepare": "husky",
|
|
49
49
|
"glm-smoke": "tsx scripts/glm-smoke.mts",
|
|
50
|
-
"seo:topics": "tsx scripts/seo-topics.mts"
|
|
50
|
+
"seo:topics": "tsx scripts/seo-topics.mts",
|
|
51
|
+
"ui-smoke": "tsx scripts/ui-smoke.mts"
|
|
51
52
|
},
|
|
52
53
|
"keywords": [
|
|
53
54
|
"zames",
|