zames_pro 2.49.4 → 2.49.5

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/dist/i18n.js CHANGED
@@ -814,6 +814,66 @@ const CATALOG = {
814
814
  ru: 'Использование: /self-apply <name>',
815
815
  en: 'Usage: /self-apply <name>',
816
816
  },
817
+ 'self.no_src': {
818
+ ru: 'Самообзор отменён: в {dir} нет .ts файлов. Проверь, что src/ не пуст и ты запускаешь агента из корня проекта.',
819
+ en: 'Self-review aborted: no .ts files in {dir}. Check that src/ is not empty and you run the agent from the project root.',
820
+ },
821
+ 'self.no_src_err': {
822
+ ru: 'SRC_DIR пуст — нечего ревьюить',
823
+ en: 'SRC_DIR is empty - nothing to review',
824
+ },
825
+ 'self.snapshot': { ru: '📸 Снапшот: {dir}', en: '📸 Snapshot: {dir}' },
826
+ 'self.files': { ru: 'Файлов: {n} — {list}', en: 'Files: {n} — {list}' },
827
+ 'self.starting': {
828
+ ru: 'Начинаю самообзор...',
829
+ en: 'Starting self-review...',
830
+ },
831
+ 'self.report': { ru: '📋 Отчёт:', en: '📋 Report:' },
832
+ 'self.report_empty': { ru: '(пусто)', en: '(empty)' },
833
+ 'self.report_path': { ru: 'Отчёт: {v}', en: 'Report: {v}' },
834
+ 'self.snapshot_path': { ru: 'Снапшот: {v}', en: 'Snapshot: {v}' },
835
+ 'self.changed': {
836
+ ru: 'Изменено: {n} файл(ов): {list}',
837
+ en: 'Changed: {n} file(s): {list}',
838
+ },
839
+ 'self.changed_none': {
840
+ ru: 'Изменено: (ничего — только отчёт)',
841
+ en: 'Changed: (nothing - report only)',
842
+ },
843
+ 'self.next': { ru: 'Дальше:', en: 'Next:' },
844
+ 'self.diff_hint': {
845
+ ru: ' /self-diff {name} — посмотреть различия',
846
+ en: ' /self-diff {name} — view the diff',
847
+ },
848
+ 'self.apply_hint': {
849
+ ru: ' /self-apply {name} — применить к живому src/',
850
+ en: ' /self-apply {name} — apply to the live src/',
851
+ },
852
+ 'self.no_diff': { ru: 'Различий нет.', en: 'No differences.' },
853
+ 'self.apply_no_ts': {
854
+ ru: 'В снапшоте {dir} нет .ts файлов. Apply отменён, чтобы не стирать src/.',
855
+ en: 'Snapshot {dir} has no .ts files. Apply aborted to avoid wiping src/.',
856
+ },
857
+ 'self.applied': {
858
+ ru: '✅ Применено: {n} файл(ов)',
859
+ en: '✅ Applied: {n} file(s)',
860
+ },
861
+ 'self.backup': { ru: 'Бэкап: {dir}', en: 'Backup: {dir}' },
862
+ 'self.restart_hint': {
863
+ ru: 'Перезапусти агента, чтобы изменения вступили в силу.',
864
+ en: 'Restart the agent for the changes to take effect.',
865
+ },
866
+ 'self.no_snapshots': { ru: 'Снапшотов нет.', en: 'No snapshots.' },
867
+ 'self.list_title': {
868
+ ru: 'Снапшоты самообзора:',
869
+ en: 'Self-review snapshots:',
870
+ },
871
+ 'self.list_changed': { ru: '[{n} изменено]', en: '[{n} changed]' },
872
+ 'self.list_unchanged': { ru: '[без правок]', en: '[no changes]' },
873
+ 'self.list_commands': {
874
+ ru: 'Команды: /self-diff <name>, /self-apply <name>',
875
+ en: 'Commands: /self-diff <name>, /self-apply <name>',
876
+ },
817
877
  'self.fix_hint': {
818
878
  ru: '\n💡 Режим ревью по снапшоту {name}. Пиши агенту задачу или /self-done.\n',
819
879
  en: '\n💡 Review mode on snapshot {name}. Send the agent a task or /self-done.\n',
package/dist/index.js CHANGED
@@ -2149,6 +2149,7 @@ async function main() {
2149
2149
  config,
2150
2150
  focus: focus || undefined,
2151
2151
  transcript,
2152
+ locale: currentLocale,
2152
2153
  });
2153
2154
  // Switch to review mode:
2154
2155
  // - working directory = snapshot
@@ -2262,7 +2263,7 @@ async function main() {
2262
2263
  }
2263
2264
  if (lower === '/self-list') {
2264
2265
  try {
2265
- await mod.selfList({ config });
2266
+ await mod.selfList({ config, locale: currentLocale });
2266
2267
  }
2267
2268
  catch (e) {
2268
2269
  console.error(theme.error(t('msg.error')), e.message);
@@ -1,6 +1,7 @@
1
1
  import path from 'path';
2
2
  import fs from 'fs/promises';
3
3
  import { theme } from './theme.js';
4
+ import { translate, DEFAULT_LOCALE } from './i18n.js';
4
5
  import { fileURLToPath } from 'url';
5
6
  import { ZAMES_HOME } from './config.js';
6
7
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -22,6 +23,12 @@ function resolveSrcDir() {
22
23
  }
23
24
  const SRC_DIR = resolveSrcDir();
24
25
  const SNAP_ROOT = path.join(ZAMES_HOME, 'snapshots');
26
+ // Localization for everything the OPERATOR sees. The locale is passed in from
27
+ // the caller (src/index.ts holds currentLocale); without it we fall back to the
28
+ // default so a direct call never breaks.
29
+ function translator(locale) {
30
+ return translate(locale || DEFAULT_LOCALE);
31
+ }
25
32
  // Dynamic import of the logic with a timestamp — so that on /reload (or
26
33
  // auto-reload) self-review uses FRESH tools/agent-loop, not the ones cached on
27
34
  // first load. Otherwise reload wouldn't reach self-review's dependencies.
@@ -54,7 +61,8 @@ async function copyDirJsFiles(from, to) {
54
61
  return copied;
55
62
  }
56
63
  // ---------- /self-review ----------
57
- export async function selfReview({ browser, focus, transcript, }) {
64
+ export async function selfReview({ browser, focus, transcript, locale, }) {
65
+ const t = translator(locale);
58
66
  const stamp = new Date().toISOString().replace(/[:.]/g, '-');
59
67
  const snapRoot = path.join(SNAP_ROOT);
60
68
  const snapDir = path.join(snapRoot, `run-${stamp}`);
@@ -62,9 +70,8 @@ export async function selfReview({ browser, focus, transcript, }) {
62
70
  await ensureDir(snapDir);
63
71
  const copied = await copyDirJsFiles(SRC_DIR, snapDir);
64
72
  if (copied.length === 0) {
65
- console.error(theme.error(`\n✖ Самообзор отменён: в ${SRC_DIR} нет .ts файлов.\n` +
66
- `Проверь, что src/ не пуст и ты запускаешь агента из корня проекта.\n`));
67
- throw new Error('SRC_DIR пуст — нечего ревьюить');
73
+ console.error(theme.error('\n✖ ' + t('self.no_src', { dir: SRC_DIR })));
74
+ throw new Error(t('self.no_src_err'));
68
75
  }
69
76
  // Copy package.json for context — so the agent sees the dependencies
70
77
  try {
@@ -72,9 +79,9 @@ export async function selfReview({ browser, focus, transcript, }) {
72
79
  await fs.writeFile(path.join(snapDir, 'package.json'), pkg, 'utf-8');
73
80
  }
74
81
  catch { }
75
- console.log(theme.system(`\n📸 Снапшот: ${snapDir}`));
76
- console.log(theme.system(`Файлов: ${copied.length} — ${copied.join(', ')}`));
77
- console.log(theme.system('Начинаю самообзор...\n'));
82
+ console.log(theme.system('\n' + t('self.snapshot', { dir: snapDir })));
83
+ console.log(theme.system(t('self.files', { n: copied.length, list: copied.join(', ') })));
84
+ console.log(theme.system(t('self.starting') + '\n'));
78
85
  const taskPrompt = buildReviewPrompt({ focus, snapDir });
79
86
  const { createTools, runAgentLoop } = await loadFresh();
80
87
  const tools = createTools(snapDir, { undo: null });
@@ -94,42 +101,43 @@ export async function selfReview({ browser, focus, transcript, }) {
94
101
  console.log(theme.warn(`🔧 ${name}`), theme.system(preview));
95
102
  },
96
103
  onToolResult: (r) => {
97
- const t = typeof r === 'string' ? r : JSON.stringify(r);
98
- console.log(theme.system(` → ${t.slice(0, 200).replace(/\n/g, ' ↵ ')}\n`));
104
+ const text = typeof r === 'string' ? r : JSON.stringify(r);
105
+ console.log(theme.system(` → ${text.slice(0, 200).replace(/\n/g, ' ↵ ')}\n`));
99
106
  },
100
107
  onAssistantMessage: (msg) => {
101
108
  finalMessage = msg;
102
- console.log(theme.assistant('\n📋 Отчёт:\n'));
109
+ console.log(theme.assistant('\n' + t('self.report') + '\n'));
103
110
  console.log(msg);
104
111
  console.log();
105
112
  },
106
113
  });
107
114
  // Save the report
108
115
  const reportPath = path.join(snapDir, '_report.md');
109
- await fs.writeFile(reportPath, finalMessage || '(пусто)', 'utf-8');
116
+ await fs.writeFile(reportPath, finalMessage || t('self.report_empty'), 'utf-8');
110
117
  // Compute what changed
111
118
  const changed = await diffFiles(SRC_DIR, snapDir);
112
119
  console.log(theme.system('─'.repeat(60)));
113
- console.log(theme.system(`Отчёт: ${reportPath}`));
114
- console.log(theme.system(`Снапшот: ${snapDir}`));
120
+ console.log(theme.system(t('self.report_path', { v: reportPath })));
121
+ console.log(theme.system(t('self.snapshot_path', { v: snapDir })));
115
122
  if (changed.length) {
116
- console.log(theme.assistant(`Изменено: ${changed.length} файл(ов): ${changed.join(', ')}`));
123
+ console.log(theme.assistant(t('self.changed', { n: changed.length, list: changed.join(', ') })));
117
124
  }
118
125
  else {
119
- console.log(theme.system('Изменено: (ничего — только отчёт)'));
126
+ console.log(theme.system(t('self.changed_none')));
120
127
  }
121
- console.log(theme.user(`\nДальше:`));
122
- console.log(theme.user(` /self-diff ${path.basename(snapDir)} — посмотреть различия`));
123
- console.log(theme.user(` /self-apply ${path.basename(snapDir)} — применить к живому src/`));
128
+ console.log(theme.user('\n' + t('self.next')));
129
+ console.log(theme.user(t('self.diff_hint', { name: path.basename(snapDir) })));
130
+ console.log(theme.user(t('self.apply_hint', { name: path.basename(snapDir) })));
124
131
  console.log();
125
132
  return { snapDir, reportPath, changed };
126
133
  }
127
134
  // ---------- /self-diff ----------
128
- export async function selfDiff({ name, }) {
135
+ export async function selfDiff({ name, locale, }) {
136
+ const t = translator(locale);
129
137
  const snapDir = path.join(SNAP_ROOT, name);
130
138
  const snapStat = await fs.stat(snapDir).catch(() => null);
131
139
  if (!snapStat)
132
- throw new Error(`Снапшот не найден: ${snapDir}`);
140
+ throw new Error(t('self.snapshot_not_found', { dir: snapDir }));
133
141
  const { unifiedDiff, colorDiff } = await import('./diff.js');
134
142
  const files = await fs.readdir(snapDir);
135
143
  let anyDiff = false;
@@ -150,15 +158,16 @@ export async function selfDiff({ name, }) {
150
158
  console.log(colorDiff(diff));
151
159
  }
152
160
  if (!anyDiff) {
153
- console.log(theme.system('Различий нет.'));
161
+ console.log(theme.system(t('self.no_diff')));
154
162
  }
155
163
  }
156
164
  // ---------- /self-apply ----------
157
- export async function selfApply({ name, }) {
165
+ export async function selfApply({ name, locale, }) {
166
+ const t = translator(locale);
158
167
  const snapDir = path.join(SNAP_ROOT, name);
159
168
  const snapStat = await fs.stat(snapDir).catch(() => null);
160
169
  if (!snapStat)
161
- throw new Error(`Снапшот не найден: ${snapDir}`);
170
+ throw new Error(t('self.snapshot_not_found', { dir: snapDir }));
162
171
  // Back up the current src before overwriting
163
172
  const stamp = new Date().toISOString().replace(/[:.]/g, '-');
164
173
  const backupDir = path.join(SNAP_ROOT, `backup-before-apply-${stamp}`);
@@ -166,7 +175,7 @@ export async function selfApply({ name, }) {
166
175
  const files = await fs.readdir(snapDir);
167
176
  const jsFiles = files.filter((f) => f.endsWith('.ts'));
168
177
  if (jsFiles.length === 0) {
169
- throw new Error(`В снапшоте ${snapDir} нет .ts файлов. Apply отменён, чтобы не стирать src/.`);
178
+ throw new Error(t('self.apply_no_ts', { dir: snapDir }));
170
179
  }
171
180
  const applied = [];
172
181
  for (const f of jsFiles) {
@@ -174,28 +183,29 @@ export async function selfApply({ name, }) {
174
183
  await fs.writeFile(path.join(SRC_DIR, f), data, 'utf-8');
175
184
  applied.push(f);
176
185
  }
177
- console.log(theme.assistant(`\n✅ Применено: ${applied.length} файл(ов)`));
186
+ console.log(theme.assistant('\n' + t('self.applied', { n: applied.length })));
178
187
  console.log(theme.system(applied.join(', ')));
179
- console.log(theme.system(`Бэкап: ${backupDir}`));
180
- console.log(theme.warn(`\nПерезапусти агента, чтобы изменения вступили в силу.\n`));
188
+ console.log(theme.system(t('self.backup', { dir: backupDir })));
189
+ console.log(theme.warn('\n' + t('self.restart_hint') + '\n'));
181
190
  }
182
191
  // ---------- /self-list ----------
183
- export async function selfList({ config: _config, } = {}) {
192
+ export async function selfList({ locale, } = {}) {
193
+ const t = translator(locale);
184
194
  const snapRoot = path.join(SNAP_ROOT);
185
195
  let entries;
186
196
  try {
187
197
  entries = await fs.readdir(snapRoot);
188
198
  }
189
199
  catch {
190
- console.log(theme.system('Снапшотов нет.'));
200
+ console.log(theme.system(t('self.no_snapshots')));
191
201
  return;
192
202
  }
193
203
  if (!entries.length) {
194
- console.log(theme.system('Снапшотов нет.'));
204
+ console.log(theme.system(t('self.no_snapshots')));
195
205
  return;
196
206
  }
197
207
  entries.sort();
198
- console.log(theme.system('Снапшоты самообзора:'));
208
+ console.log(theme.system(t('self.list_title')));
199
209
  for (const e of entries) {
200
210
  const full = path.join(snapRoot, e);
201
211
  const stat = await fs.stat(full).catch(() => null);
@@ -208,13 +218,13 @@ export async function selfList({ config: _config, } = {}) {
208
218
  .catch(() => false);
209
219
  const changedCount = (await diffFiles(SRC_DIR, full)).length;
210
220
  const tag = changedCount
211
- ? theme.assistant(`[${changedCount} изменено]`)
212
- : theme.system('[без правок]');
221
+ ? theme.assistant(t('self.list_changed', { n: changedCount }))
222
+ : theme.system(t('self.list_unchanged'));
213
223
  const rep = hasReport ? theme.user('📋') : ' ';
214
224
  console.log(` ${rep} ${e} ${tag}`);
215
225
  }
216
226
  console.log();
217
- console.log(theme.system('Команды: /self-diff <name>, /self-apply <name>\n'));
227
+ console.log(theme.system(t('self.list_commands') + '\n'));
218
228
  }
219
229
  // ---------- helpers ----------
220
230
  async function diffFiles(origDir, newDir) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.49.4",
3
+ "version": "2.49.5",
4
4
  "description": "Terminal coding agent over chat.deepseek.com via Playwright",
5
5
  "type": "module",
6
6
  "bin": {