zames_pro 2.6.0 → 2.7.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.
@@ -1,16 +1,16 @@
1
- // Интерактивное меню настроек для команды /config.
1
+ // Interactive settings menu for the /config command.
2
2
  //
3
- // Меню рисует список параметров, сгруппированных по секциям, и позволяет
4
- // менять их стрелками: boolean/enum переключаются на месте, number/string
5
- // запрашивают ввод. Все строки берутся из i18n (cfg.*), поэтому меню
6
- // полностью локализовано.
3
+ // The menu renders a list of parameters grouped by sections and lets you
4
+ // change them with the arrow keys: boolean/enum toggle in place, number/string
5
+ // prompt for input. All strings come from i18n (cfg.*), so the menu is
6
+ // fully localized.
7
7
  //
8
- // Модуль не знает про config.ts напрямую (кроме типов схемы): чтение и
9
- // запись значений делает вызывающий через колбэки. Так меню легко тестировать
10
- // и переиспользовать.
8
+ // The module doesn't know about config.ts directly (except for the schema
9
+ // types): the caller reads and writes values through callbacks. This makes the
10
+ // menu easy to test and reuse.
11
11
  import { theme } from './theme.js';
12
12
  const ESC = String.fromCharCode(27);
13
- // Убираем ANSI-последовательности, чтобы посчитать видимую длину строки.
13
+ // Strip ANSI sequences to compute the visible length of a line.
14
14
  function stripAnsi(s) {
15
15
  return s.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, '');
16
16
  }
@@ -25,9 +25,9 @@ function groupLabel(field, t) {
25
25
  return t(field.groupKey);
26
26
  }
27
27
  /**
28
- * Показать интерактивное меню. Возвращает промис, который резолвится, когда
29
- * пользователь вышел (q/Esc/Ctrl+C). В не-TTY бросает ошибку — вызывающий
30
- * должен показать текстовый список.
28
+ * Show the interactive menu. Returns a promise that resolves when the
29
+ * user exits (q/Esc/Ctrl+C). In a non-TTY it throws — the caller
30
+ * must show a text list.
31
31
  */
32
32
  export function runConfigMenu(opts) {
33
33
  const input = opts.input || process.stdin;
@@ -45,9 +45,9 @@ export function runConfigMenu(opts) {
45
45
  const wasRaw = input.isRaw;
46
46
  input.setRawMode(true);
47
47
  input.resume();
48
- output.write(ESC + '[?25l'); // прячем курсор на время отрисовки
49
- // Отрисовка меню: строки идут сверху вниз, курсор возвращаем в начало
50
- // блока через относительные перемещения, чтобы не плодить пустые строки.
48
+ output.write(ESC + '[?25l'); // hide the cursor while rendering
49
+ // Menu rendering: lines go top to bottom, and we return the cursor to the
50
+ // start of the block via relative moves so we don't spawn blank lines.
51
51
  let lastRows = 0;
52
52
  const render = () => {
53
53
  const lines = [];
@@ -81,9 +81,9 @@ export function runConfigMenu(opts) {
81
81
  lines.push('');
82
82
  lines.push(theme.dim(t('cfg.menu.hint')));
83
83
  }
84
- // Стираем прошлый блок и печатаем новый. Считаем ВИЗУАЛЬНЫЕ строки
85
- // (с учётом переноса по ширине терминала), иначе на узких терминалах
86
- // остаётся «мусор» из нестёртых хвостов.
84
+ // Erase the previous block and print the new one. We count VISUAL lines
85
+ // (accounting for wrapping by terminal width), otherwise on narrow
86
+ // terminals you get "garbage" from unerased tails.
87
87
  const cols = output.columns || 80;
88
88
  const rowsOf = (s) => {
89
89
  const len = stripAnsi(s).length;
@@ -106,7 +106,7 @@ export function runConfigMenu(opts) {
106
106
  input.removeListener('data', onData);
107
107
  if (input.setRawMode)
108
108
  input.setRawMode(wasRaw || false);
109
- output.write(ESC + '[?25h'); // возвращаем курсор
109
+ output.write(ESC + '[?25h'); // restore the cursor
110
110
  if (resolveDone)
111
111
  resolveDone();
112
112
  };
@@ -146,15 +146,15 @@ export function runConfigMenu(opts) {
146
146
  message = null;
147
147
  return;
148
148
  }
149
- // number/string — запрашиваем ввод.
149
+ // number/string — prompt for input.
150
150
  editing = true;
151
151
  editBuf = get(f.path) === undefined ? '' : String(get(f.path));
152
152
  };
153
153
  const onData = (buf) => {
154
154
  const s = buf.toString('utf-8');
155
155
  if (editing) {
156
- // Обрабатываем ввод посимвольно: терминал может прислать несколько
157
- // байт сразу (вставка, авто-повтор), Enter — 0x0d/0x0a, backspace — 0x7f.
156
+ // Process input character by character: the terminal may send several
157
+ // bytes at once (paste, auto-repeat), Enter is 0x0d/0x0a, backspace is 0x7f.
158
158
  for (const ch of s) {
159
159
  if (ch === '\r' || ch === '\n') {
160
160
  commitEdit();
@@ -180,9 +180,9 @@ export function runConfigMenu(opts) {
180
180
  render();
181
181
  return;
182
182
  }
183
- // Терминал может прислать несколько клавиш одним пакетом (быстрый набор,
184
- // авто-повтор, автоматизация). Разбираем буфер по токенам: сначала
185
- // escape-последовательности (стрелки), затем одиночные символы.
183
+ // The terminal may send several keys in one packet (fast typing,
184
+ // auto-repeat, automation). We parse the buffer into tokens: first
185
+ // escape sequences (arrows), then single characters.
186
186
  let i = 0;
187
187
  while (i < s.length) {
188
188
  if (s.startsWith('\x1b[A', i)) {
package/dist/config.js CHANGED
@@ -157,8 +157,8 @@ export function configPathFor(scope) {
157
157
  return scope === 'project' ? PROJECT_CONFIG : HOME_CONFIG;
158
158
  }
159
159
  /**
160
- * Прочитать только тот файл конфига, что указан (без слияния с дефолтами),
161
- * чтобы запись не «замораживала» все дефолты в файле пользователя.
160
+ * Read only the specified config file (without merging with defaults), so that
161
+ * writing does not "freeze" all defaults into the user's file.
162
162
  */
163
163
  export function readConfigFile(file) {
164
164
  try {
@@ -176,8 +176,8 @@ export function readConfigFile(file) {
176
176
  return {};
177
177
  }
178
178
  /**
179
- * Записать значение настройки в файл. Возвращает итоговый объект, который
180
- * лёг в файл. Значение сперва валидируется по схеме.
179
+ * Write a setting value to the file. Returns the final object that was
180
+ * written. The value is first validated against the schema.
181
181
  */
182
182
  export function writeConfigValue(scope, key, raw) {
183
183
  const field = getConfigField(key);
@@ -191,7 +191,7 @@ export function writeConfigValue(scope, key, raw) {
191
191
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n', 'utf-8');
192
192
  return { value, file };
193
193
  }
194
- /** Сбросить настройку к дефолту (удалить ключ из файла). */
194
+ /** Reset a setting to the default (remove the key from the file). */
195
195
  export function resetConfigValue(scope, key) {
196
196
  const field = getConfigField(key);
197
197
  if (!field)
package/dist/gitTools.js CHANGED
@@ -36,8 +36,8 @@ export function runGit(cmd, cwd, timeout = 15_000) {
36
36
  });
37
37
  });
38
38
  }
39
- // Безопасно квотит пути/аргументы для передачи в shell.
40
- // Строка или массив -> строка с двойными кавычками и экранированием.
39
+ // Safely quotes paths/arguments for passing to the shell.
40
+ // String or array -> a string with double quotes and escaping.
41
41
  function quoteArgs(input) {
42
42
  const list = Array.isArray(input) ? input : [input];
43
43
  return list
@@ -46,7 +46,7 @@ function quoteArgs(input) {
46
46
  .map((v) => JSON.stringify(v))
47
47
  .join(' ');
48
48
  }
49
- // Проверяет, является ли директория git-репозиторием, и собирает контекст.
49
+ // Checks whether the directory is a git repository and gathers the context.
50
50
  export async function getGitContext(workdir) {
51
51
  const probe = await runGit('git rev-parse --is-inside-work-tree', workdir, 5000);
52
52
  if (probe.trim() !== 'true')
@@ -175,7 +175,7 @@ export function createGitTools(workdir) {
175
175
  if (!msg.trim()) {
176
176
  return 'Ошибка: message пустой.';
177
177
  }
178
- // Индексируем всё только если в индексе пусто (как обещает описание).
178
+ // We stage everything only if the index is empty (as the description promises).
179
179
  const staged = await runGit('git diff --cached --name-only', workdir, 10_000);
180
180
  const hasStaged = !/^\s*/.test(staged) &&
181
181
  staged.trim() !== '(команда выполнена, вывода нет)';
package/dist/i18n.js CHANGED
@@ -1,12 +1,12 @@
1
1
  // Localization (i18n).
2
2
  //
3
- // Задачи:
4
- // * менять язык интерфейса (справка, служебные сообщения);
5
- // * язык ответов агента — через system-prompt;
6
- // * язык ответов агента на обычный язык.
3
+ // Goals:
4
+ // * change the interface language (help, service messages);
5
+ // * the agent's answer language — via the system-prompt;
6
+ // * the agent's answer language for a plain language.
7
7
  //
8
- // Стратегия: единая карта переводов по ключам. Новые ключи легко добавить.
9
- // Тексты на русском (ru) — дефолт, английский (en) — альтернатива.
8
+ // Strategy: a single key->translation map. New keys are easy to add.
9
+ // Russian texts (ru) are the default, English (en) is the alternative.
10
10
  export const DEFAULT_LOCALE = 'ru';
11
11
  export const LOCALES = [
12
12
  { code: 'ru', name: 'Русский', englishName: 'Russian' },
@@ -25,7 +25,7 @@ export function normalizeLocale(v) {
25
25
  return 'en';
26
26
  return DEFAULT_LOCALE;
27
27
  }
28
- // Каталог строк. Ключ -> { ru, en }. Если ключа нет — вернём сам ключ.
28
+ // String catalog. Key -> { ru, en }. If a key is missing — we return the key itself.
29
29
  const CATALOG = {
30
30
  'app.tagline': {
31
31
  ru: 'агент поверх chat.deepseek.com через Playwright',
@@ -135,6 +135,10 @@ const CATALOG = {
135
135
  'msg.queued': { ru: '📨 В очередь ({n}): ', en: '📨 Queued ({n}): ' },
136
136
  'msg.from_queue': { ru: '▶ Из очереди: ', en: '▶ From queue: ' },
137
137
  'msg.agent_error': { ru: '✖ Ошибка агента:', en: '✖ Agent error:' },
138
+ 'msg.suspicious_stop': {
139
+ ru: 'агент, похоже, остановился, не распознав вызов инструмента. Ответ сохранён в транскрипте (событие suspicious_final). Можно попросить продолжить или переотправить задачу.',
140
+ en: 'the agent seems to have stopped without recognizing a tool call. The response is saved in the transcript (suspicious_final event). You can ask it to continue or resend the task.',
141
+ },
138
142
  'msg.critical': { ru: 'Критическая ошибка:', en: 'Critical error:' },
139
143
  'msg.not_dir': { ru: 'Не директория: {v}', en: 'Not a directory: {v}' },
140
144
  'prompt.review': { ru: 'REVIEW', en: 'REVIEW' },