zames_pro 1.2.1 → 2.0.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/dist/agent-loop.js +652 -0
- package/dist/agent-loop.js.map +1 -0
- package/dist/browser.js +573 -0
- package/dist/browser.js.map +1 -0
- package/dist/config.js +74 -0
- package/dist/config.js.map +1 -0
- package/dist/confirm.js +82 -0
- package/dist/confirm.js.map +1 -0
- package/dist/diff.js +38 -0
- package/dist/diff.js.map +1 -0
- package/dist/gitTools.js +219 -0
- package/dist/gitTools.js.map +1 -0
- package/dist/index.js +1365 -0
- package/dist/index.js.map +1 -0
- package/dist/input.js +524 -0
- package/dist/input.js.map +1 -0
- package/dist/markdown.js +48 -0
- package/dist/markdown.js.map +1 -0
- package/dist/self-review.js +281 -0
- package/dist/self-review.js.map +1 -0
- package/dist/sessions.js +123 -0
- package/dist/sessions.js.map +1 -0
- package/dist/spinner.js +138 -0
- package/dist/spinner.js.map +1 -0
- package/{src → dist}/system-prompt.js +10 -14
- package/dist/system-prompt.js.map +1 -0
- package/{src → dist}/theme.js +17 -19
- package/dist/theme.js.map +1 -0
- package/dist/tools.js +189 -0
- package/dist/tools.js.map +1 -0
- package/dist/transcript.js +51 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/undo.js +100 -0
- package/dist/undo.js.map +1 -0
- package/dist/web.js +220 -0
- package/dist/web.js.map +1 -0
- package/dist/xml-toolcall.js +68 -0
- package/dist/xml-toolcall.js.map +1 -0
- package/package.json +13 -5
- package/src/agent-loop.js +0 -634
- package/src/browser.js +0 -627
- package/src/config.js +0 -81
- package/src/confirm.js +0 -85
- package/src/diff.js +0 -32
- package/src/gitTools.js +0 -256
- package/src/index.js +0 -1515
- package/src/input.js +0 -447
- package/src/markdown.js +0 -49
- package/src/self-review.js +0 -319
- package/src/sessions.js +0 -110
- package/src/spinner.js +0 -144
- package/src/tools.js +0 -206
- package/src/transcript.js +0 -46
- package/src/undo.js +0 -101
- package/src/web.js +0 -266
- package/src/xml-toolcall.js +0 -69
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
export function buildSystemPrompt({ workdir, tools, gitContext = null }) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const gitSection = gitContext
|
|
10
|
-
? `\n## Git context\n\n${gitContext}\n`
|
|
11
|
-
: '\n## Git context\n\nNot a git repository (or git is not installed).\n'
|
|
12
|
-
|
|
13
|
-
return `You are a coding agent running in a terminal. You help the user with software engineering tasks by reading files, writing code, running commands, and iterating until the task is done.
|
|
1
|
+
export function buildSystemPrompt({ workdir, tools, gitContext = null, }) {
|
|
2
|
+
const toolDescriptions = tools
|
|
3
|
+
.map((t) => `### ${t.name}\n${t.description}\nПараметры: ${JSON.stringify(t.parameters)}`)
|
|
4
|
+
.join('\n\n');
|
|
5
|
+
const gitSection = gitContext
|
|
6
|
+
? `\n## Git context\n\n${gitContext}\n`
|
|
7
|
+
: '\n## Git context\n\nNot a git repository (or git is not installed).\n';
|
|
8
|
+
return `You are a coding agent running in a terminal. You help the user with software engineering tasks by reading files, writing code, running commands, and iterating until the task is done.
|
|
14
9
|
|
|
15
10
|
You work in the directory: ${workdir}
|
|
16
11
|
|
|
@@ -124,5 +119,6 @@ Anything you write outside that one respond is not read by the operator.
|
|
|
124
119
|
- WebFetch strips HTML. If a page is JS-rendered and text comes back empty, call WebFetch again with render=true.
|
|
125
120
|
- Do NOT fetch the same URL repeatedly. If content is missing, report that instead.
|
|
126
121
|
- Do NOT use WebFetch on localhost, private IPs, or 'file://' — it will fail.
|
|
127
|
-
|
|
122
|
+
`;
|
|
128
123
|
}
|
|
124
|
+
//# sourceMappingURL=system-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../src/system-prompt.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,iBAAiB,CAAC,EAChC,OAAO,EACP,KAAK,EACL,UAAU,GAAG,IAAI,GACQ;IACzB,MAAM,gBAAgB,GAAG,KAAK;SAC3B,GAAG,CACF,CAAC,CAAU,EAAE,EAAE,CACb,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAChF;SACA,IAAI,CAAC,MAAM,CAAC,CAAA;IAEf,MAAM,UAAU,GAAG,UAAU;QAC3B,CAAC,CAAC,uBAAuB,UAAU,IAAI;QACvC,CAAC,CAAC,uEAAuE,CAAA;IAE3E,OAAO;;6BAEoB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgClC,gBAAgB;EAChB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+EX,CAAA;AACD,CAAC"}
|
package/{src → dist}/theme.js
RENAMED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import chalk from 'chalk'
|
|
2
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
3
2
|
// Спокойная палитра для тёмного терминала.
|
|
4
3
|
// Приглушённые, слегка «выцветшие» тона без высокой насыщенности
|
|
5
4
|
// (в духе Tokyo Night / Nord). Задача — комфортное чтение длинных
|
|
@@ -15,21 +14,20 @@ import chalk from 'chalk'
|
|
|
15
14
|
// - system — нейтральный серый
|
|
16
15
|
// - warn — спокойный охра
|
|
17
16
|
// - error — приглушённый терракот
|
|
18
|
-
|
|
19
17
|
export const theme = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
user: chalk.hex('#b4b8d0'), // мягкий лавандово-серый
|
|
19
|
+
prompt: chalk.hex('#c8b06a').bold, // приглашение ввода — тёплое золотистое, заметное
|
|
20
|
+
dir: chalk.hex('#7fc4f0'), // имя рабочей директории — заметно голубое
|
|
21
|
+
assistant: chalk.hex('#cfc9b0'), // тёплый песочный
|
|
22
|
+
tool: chalk.hex('#c6a97e'), // приглушённый янтарный
|
|
23
|
+
toolResult: chalk.hex('#8a9bb5'), // серо-голубой
|
|
24
|
+
system: chalk.hex('#808896'), // нейтральный серый
|
|
25
|
+
dim: chalk.hex('#5b616e'), // тёмно-серый
|
|
26
|
+
warn: chalk.hex('#c9a86a'), // спокойный охра
|
|
27
|
+
error: chalk.hex('#c98a80'), // приглушённый терракот
|
|
28
|
+
success: chalk.hex('#a9c08c'), // мягкий шалфейный
|
|
29
|
+
brown: chalk.hex('#a1723f'), // коричневый (статус/спиннер)
|
|
30
|
+
bold: chalk.bold,
|
|
31
|
+
};
|
|
32
|
+
export default theme;
|
|
33
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,2CAA2C;AAC3C,iEAAiE;AACjE,kEAAkE;AAClE,4CAA4C;AAC5C,EAAE;AACF,QAAQ;AACR,iEAAiE;AACjE,oEAAoE;AACpE,4DAA4D;AAC5D,oDAAoD;AACpD,0CAA0C;AAC1C,iCAAiC;AACjC,sCAAsC;AACtC,mCAAmC;AACnC,0CAA0C;AAE1C,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,yBAAyB;IACrD,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,kDAAkD;IACrF,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,2CAA2C;IACtE,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,kBAAkB;IACnD,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,wBAAwB;IACpD,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,eAAe;IACjD,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,oBAAoB;IAClD,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,cAAc;IACzC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,iBAAiB;IAC7C,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,wBAAwB;IACrD,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,mBAAmB;IAClD,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,8BAA8B;IAC3D,IAAI,EAAE,KAAK,CAAC,IAAI;CACjB,CAAA;AAED,eAAe,KAAK,CAAA"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { createGitTools } from './gitTools.js';
|
|
5
|
+
import { createWebTools } from './web.js';
|
|
6
|
+
export function createTools(workdir, { undo } = {}) {
|
|
7
|
+
const root = path.resolve(workdir);
|
|
8
|
+
const safe = (p) => {
|
|
9
|
+
const resolved = path.resolve(root, p);
|
|
10
|
+
// startsWith(root) пропускал бы соседние пути с общим префиксом
|
|
11
|
+
// (C:\work\proj vs C:\work\proj-old). Считаем через relative().
|
|
12
|
+
const rel = path.relative(root, resolved);
|
|
13
|
+
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
14
|
+
throw new Error(`Доступ за пределы рабочей директории: ${p}`);
|
|
15
|
+
}
|
|
16
|
+
return resolved;
|
|
17
|
+
};
|
|
18
|
+
// Sandbox (вариант A): не даём команде выйти выше root.
|
|
19
|
+
// Это защитный барьер, а не полноценная изоляция ОС.
|
|
20
|
+
const assertCommandInsideRoot = (command) => {
|
|
21
|
+
const cmd = String(command || '');
|
|
22
|
+
const cdRe = /(?:^|[;&|]|\s)(?:cd|pushd)\s+([^;&|]+)/gi;
|
|
23
|
+
let m;
|
|
24
|
+
while ((m = cdRe.exec(cmd))) {
|
|
25
|
+
const raw = m[1].trim();
|
|
26
|
+
if (!raw || raw === '-')
|
|
27
|
+
continue;
|
|
28
|
+
const target = path.resolve(root, raw);
|
|
29
|
+
const rel = path.relative(root, target);
|
|
30
|
+
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
31
|
+
throw new Error('Sandbox: выход за пределы ' + root + ' запрещён (cd ' + raw + ')');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const runShell = (command, timeout = 30_000) => new Promise((resolve) => {
|
|
36
|
+
const options = {
|
|
37
|
+
cwd: workdir,
|
|
38
|
+
timeout,
|
|
39
|
+
maxBuffer: 1024 * 1024 * 8,
|
|
40
|
+
windowsHide: true,
|
|
41
|
+
env: { ...process.env },
|
|
42
|
+
};
|
|
43
|
+
if (process.platform === 'win32') {
|
|
44
|
+
options.shell = process.env.ComSpec || 'C:\\Windows\\System32\\cmd.exe';
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
options.shell = '/bin/sh';
|
|
48
|
+
}
|
|
49
|
+
exec(command, options, (err, stdout, stderr) => {
|
|
50
|
+
const out = (stdout || '').toString();
|
|
51
|
+
const errStr = (stderr || '').toString();
|
|
52
|
+
if (!err) {
|
|
53
|
+
const combined = (out + errStr).trim();
|
|
54
|
+
resolve(combined || '(команда выполнена без вывода)');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const parts = [];
|
|
58
|
+
if (err.killed) {
|
|
59
|
+
parts.push(`⏱ Таймаут после ${timeout}ms — процесс убит.`);
|
|
60
|
+
}
|
|
61
|
+
else if (err.code !== undefined && err.code !== null) {
|
|
62
|
+
parts.push(`Exit code: ${err.code}`);
|
|
63
|
+
}
|
|
64
|
+
else if (err.signal) {
|
|
65
|
+
parts.push(`Убит сигналом: ${err.signal}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
parts.push(`Ошибка: ${err.message}`);
|
|
69
|
+
}
|
|
70
|
+
if (out.trim())
|
|
71
|
+
parts.push(`stdout:\n${out.trim()}`);
|
|
72
|
+
if (errStr.trim())
|
|
73
|
+
parts.push(`stderr:\n${errStr.trim()}`);
|
|
74
|
+
resolve(parts.join('\n'));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
const baseTools = [
|
|
78
|
+
{
|
|
79
|
+
name: 'Read',
|
|
80
|
+
description: 'Прочитать содержимое файла. Опционально: offset и limit (строки).',
|
|
81
|
+
parameters: { path: 'string', offset: 'number?', limit: 'number?' },
|
|
82
|
+
fn: async ({ path: p, offset, limit }) => {
|
|
83
|
+
const file = safe(String(p));
|
|
84
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
85
|
+
const lines = content.split('\n');
|
|
86
|
+
const start = offset ?? 0;
|
|
87
|
+
const end = limit ? start + limit : lines.length;
|
|
88
|
+
return lines.slice(start, end).join('\n');
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'Write',
|
|
93
|
+
description: 'Создать или перезаписать файл.',
|
|
94
|
+
parameters: { path: 'string', content: 'string' },
|
|
95
|
+
fn: async ({ path: p, content }) => {
|
|
96
|
+
const file = safe(String(p));
|
|
97
|
+
if (undo)
|
|
98
|
+
await undo.backup(file);
|
|
99
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
100
|
+
await fs.writeFile(file, String(content), 'utf-8');
|
|
101
|
+
return `Файл записан: ${p}`;
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'Edit',
|
|
106
|
+
description: 'Точечная замена строки в файле. old_string должен встречаться один раз.',
|
|
107
|
+
parameters: {
|
|
108
|
+
path: 'string',
|
|
109
|
+
old_string: 'string',
|
|
110
|
+
new_string: 'string',
|
|
111
|
+
},
|
|
112
|
+
fn: async ({ path: p, old_string, new_string }) => {
|
|
113
|
+
const file = safe(String(p));
|
|
114
|
+
if (typeof old_string !== 'string' || old_string === '') {
|
|
115
|
+
throw new Error('old_string пустой — нечего заменять.');
|
|
116
|
+
}
|
|
117
|
+
let content = await fs.readFile(file, 'utf-8');
|
|
118
|
+
const occurrences = content.split(old_string).length - 1;
|
|
119
|
+
if (occurrences === 0) {
|
|
120
|
+
throw new Error(`Строка не найдена в ${p}: "${old_string.slice(0, 60)}..."`);
|
|
121
|
+
}
|
|
122
|
+
if (occurrences > 1) {
|
|
123
|
+
throw new Error(`Строка встречается ${occurrences} раз в ${p}. Уточните old_string.`);
|
|
124
|
+
}
|
|
125
|
+
if (undo)
|
|
126
|
+
await undo.backup(file);
|
|
127
|
+
content = content.replace(old_string, String(new_string));
|
|
128
|
+
await fs.writeFile(file, content, 'utf-8');
|
|
129
|
+
return `Отредактирован: ${p}`;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'Bash',
|
|
134
|
+
description: 'Выполнить shell-команду в рабочей директории (cmd.exe на Windows, sh на Linux/macOS). ' +
|
|
135
|
+
'Не использовать для long-running процессов (серверы) — уйдут в таймаут. ' +
|
|
136
|
+
'Не использовать для команд, требующих интерактивного ввода. ' +
|
|
137
|
+
'Для git — инструменты Git*. Для интернета — WebFetch / WebSearch.',
|
|
138
|
+
parameters: { command: 'string', timeout: 'number?' },
|
|
139
|
+
fn: async ({ command, timeout }) => {
|
|
140
|
+
assertCommandInsideRoot(String(command));
|
|
141
|
+
return runShell(String(command), timeout);
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'Glob',
|
|
146
|
+
description: 'Найти файлы по glob-паттерну (например, "**/*.js").',
|
|
147
|
+
parameters: { pattern: 'string' },
|
|
148
|
+
fn: async ({ pattern }) => {
|
|
149
|
+
const { glob } = await import('fs/promises');
|
|
150
|
+
const results = [];
|
|
151
|
+
for await (const f of glob(String(pattern), { cwd: workdir })) {
|
|
152
|
+
// Sandbox: игнорируем всё, что выходит за пределы root.
|
|
153
|
+
const abs = path.resolve(workdir, f);
|
|
154
|
+
const rel = path.relative(root, abs);
|
|
155
|
+
if (rel.startsWith('..') || path.isAbsolute(rel))
|
|
156
|
+
continue;
|
|
157
|
+
results.push(f);
|
|
158
|
+
}
|
|
159
|
+
return results.length ? results.join('\n') : 'Ничего не найдено.';
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'Grep',
|
|
164
|
+
description: 'Поиск по содержимому файлов (регулярное выражение).',
|
|
165
|
+
parameters: { pattern: 'string', path: 'string?' },
|
|
166
|
+
fn: async ({ pattern, path: searchPath }) => {
|
|
167
|
+
const target = searchPath ? safe(String(searchPath)) : workdir;
|
|
168
|
+
if (process.platform === 'win32') {
|
|
169
|
+
const escaped = String(pattern).replace(/"/g, '\\"');
|
|
170
|
+
const scope = searchPath
|
|
171
|
+
? '"' + target + '\\*'
|
|
172
|
+
: '*';
|
|
173
|
+
return runShell(`findstr /s /n /r /c:"${escaped}" ` + scope);
|
|
174
|
+
}
|
|
175
|
+
return runShell(`grep -rn -E ${JSON.stringify(pattern)} ${JSON.stringify(target)} || true`);
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
const gitTools = createGitTools(workdir);
|
|
180
|
+
const webTools = createWebTools();
|
|
181
|
+
const respondTool = {
|
|
182
|
+
name: 'respond',
|
|
183
|
+
description: 'Дать финальный ответ пользователю и завершить задачу.',
|
|
184
|
+
parameters: { message: 'string' },
|
|
185
|
+
fn: async ({ message }) => message,
|
|
186
|
+
};
|
|
187
|
+
return [...baseTools, ...gitTools, ...webTools, respondTool];
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export class Transcript {
|
|
4
|
+
enabled;
|
|
5
|
+
file;
|
|
6
|
+
stream;
|
|
7
|
+
startedAt;
|
|
8
|
+
constructor({ dir, enabled = true, sessionName = 'session', }) {
|
|
9
|
+
this.enabled = enabled;
|
|
10
|
+
this.file = null;
|
|
11
|
+
this.stream = null;
|
|
12
|
+
this.startedAt = Date.now();
|
|
13
|
+
if (!enabled)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
17
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
18
|
+
this.file = path.join(dir, `${sessionName}-${stamp}.jsonl`);
|
|
19
|
+
this.stream = fs.createWriteStream(this.file, { flags: 'a' });
|
|
20
|
+
// Ошибки записи (диск переполнен, файл удалён и т.п.) приходят
|
|
21
|
+
// событием 'error'; без слушателя это uncaught exception.
|
|
22
|
+
this.stream.on('error', (e) => {
|
|
23
|
+
console.error(`transcript: ошибка записи: ${e.message}`);
|
|
24
|
+
this.enabled = false;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
console.error(`transcript: не удалось создать файл: ${e.message}`);
|
|
29
|
+
this.enabled = false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
log(type, data = {}) {
|
|
33
|
+
if (!this.enabled || !this.stream)
|
|
34
|
+
return;
|
|
35
|
+
const entry = {
|
|
36
|
+
ts: new Date().toISOString(),
|
|
37
|
+
elapsed: Date.now() - this.startedAt,
|
|
38
|
+
type,
|
|
39
|
+
...data,
|
|
40
|
+
};
|
|
41
|
+
try {
|
|
42
|
+
this.stream.write(JSON.stringify(entry) + String.fromCharCode(10));
|
|
43
|
+
}
|
|
44
|
+
catch { }
|
|
45
|
+
}
|
|
46
|
+
close() {
|
|
47
|
+
if (this.stream)
|
|
48
|
+
this.stream.end();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AASvB,MAAM,OAAO,UAAU;IACrB,OAAO,CAAS;IAChB,IAAI,CAAe;IACnB,MAAM,CAAoB;IAC1B,SAAS,CAAQ;IAEjB,YAAY,EACV,GAAG,EACH,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,SAAS,GACL;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAE3B,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACtC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,IAAI,KAAK,QAAQ,CAAC,CAAA;YAC3D,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;YAC7D,+DAA+D;YAC/D,0DAA0D;YAC1D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;gBACnC,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;gBACxD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;YACtB,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CACX,wCAAyC,CAAW,CAAC,OAAO,EAAE,CAC/D,CAAA;YACD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACtB,CAAC;IACH,CAAC;IAED,GAAG,CAAC,IAAY,EAAE,IAAI,GAA4B,EAAE;QAClD,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAM;QACzC,MAAM,KAAK,GAAG;YACZ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;YACpC,IAAI;YACJ,GAAG,IAAI;SACR,CAAA;QACD,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAA;QACpE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA;IACpC,CAAC;CACF"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,6DAA6D"}
|
package/dist/undo.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
const UNDO_DIR = path.join(os.homedir(), '.zames', 'undo');
|
|
5
|
+
const INDEX = path.join(UNDO_DIR, 'index.json');
|
|
6
|
+
export class UndoStore {
|
|
7
|
+
enabled;
|
|
8
|
+
maxBackups;
|
|
9
|
+
constructor({ enabled = true, maxBackups = 200, } = {}) {
|
|
10
|
+
this.enabled = enabled;
|
|
11
|
+
this.maxBackups = maxBackups;
|
|
12
|
+
}
|
|
13
|
+
async _ensure() {
|
|
14
|
+
await fs.mkdir(UNDO_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
async _readIndex() {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(await fs.readFile(INDEX, 'utf-8'));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async _writeIndex(history) {
|
|
25
|
+
await fs.writeFile(INDEX, JSON.stringify(history, null, 2));
|
|
26
|
+
}
|
|
27
|
+
async backup(filePath) {
|
|
28
|
+
if (!this.enabled)
|
|
29
|
+
return null;
|
|
30
|
+
await this._ensure();
|
|
31
|
+
let content = null;
|
|
32
|
+
let existed = false;
|
|
33
|
+
try {
|
|
34
|
+
content = await fs.readFile(filePath);
|
|
35
|
+
existed = true;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
if (e.code !== 'ENOENT')
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
const stamp = Date.now();
|
|
42
|
+
const hash = Buffer.from(filePath).toString('hex').slice(0, 16);
|
|
43
|
+
let backupFile = null;
|
|
44
|
+
if (existed) {
|
|
45
|
+
backupFile = path.join(UNDO_DIR, `${stamp}-${hash}.bak`);
|
|
46
|
+
await fs.writeFile(backupFile, content);
|
|
47
|
+
}
|
|
48
|
+
const history = await this._readIndex();
|
|
49
|
+
history.push({ originalPath: filePath, existed, stamp, backupFile });
|
|
50
|
+
while (history.length > this.maxBackups) {
|
|
51
|
+
const old = history.shift();
|
|
52
|
+
if (old && old.backupFile) {
|
|
53
|
+
try {
|
|
54
|
+
await fs.unlink(old.backupFile);
|
|
55
|
+
}
|
|
56
|
+
catch { }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
await this._writeIndex(history);
|
|
60
|
+
return { originalPath: filePath, existed, stamp };
|
|
61
|
+
}
|
|
62
|
+
async undoLast() {
|
|
63
|
+
if (!this.enabled)
|
|
64
|
+
return { ok: false, reason: 'undo отключён в конфиге' };
|
|
65
|
+
await this._ensure();
|
|
66
|
+
const history = await this._readIndex();
|
|
67
|
+
if (!history.length)
|
|
68
|
+
return { ok: false, reason: 'история пуста' };
|
|
69
|
+
const record = history.pop();
|
|
70
|
+
if (!record)
|
|
71
|
+
return { ok: false, reason: 'история пуста' };
|
|
72
|
+
const { originalPath, existed, backupFile } = record;
|
|
73
|
+
try {
|
|
74
|
+
if (existed && backupFile) {
|
|
75
|
+
const data = await fs.readFile(backupFile);
|
|
76
|
+
await fs.writeFile(originalPath, data);
|
|
77
|
+
try {
|
|
78
|
+
await fs.unlink(backupFile);
|
|
79
|
+
}
|
|
80
|
+
catch { }
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
try {
|
|
84
|
+
await fs.unlink(originalPath);
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
}
|
|
88
|
+
await this._writeIndex(history);
|
|
89
|
+
return { ok: true, record };
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
return { ok: false, reason: e.message };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async list(count = 10) {
|
|
96
|
+
const history = await this._readIndex();
|
|
97
|
+
return history.slice(-count).reverse();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=undo.js.map
|
package/dist/undo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo.js","sourceRoot":"","sources":["../src/undo.ts"],"names":[],"mappings":"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"}
|