zames_pro 2.10.1 → 2.10.2
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 +32 -11
- package/package.json +1 -1
package/dist/agent-loop.js
CHANGED
|
@@ -3,6 +3,27 @@ import { getGitContext, formatGitContext } from './gitTools.js';
|
|
|
3
3
|
import { parseXmlToolCalls } from './xml-toolcall.js';
|
|
4
4
|
import { translate } from './i18n.js';
|
|
5
5
|
export async function runAgentLoop({ browser, tools, task, workdir, maxIterations = 40, freshChat = false, sendSystemPrompt = false, transcript = null, attachments = [], onThinking = () => { }, onAssistantThought = () => { }, onToolCall = () => { }, onToolResult = () => { }, onAssistantMessage = () => { }, onChatReady = () => { }, onWarning = () => { }, debugLog = false, locale = 'ru', }) {
|
|
6
|
+
// UI callbacks must NEVER break the agent loop. A rendering error (a huge
|
|
7
|
+
// tool result, a broken markdown frame, a closed terminal) used to throw
|
|
8
|
+
// out of the loop right after a tool call — the session looked "stopped
|
|
9
|
+
// after a tool call", with a tool_call but no tool_result in the log. We
|
|
10
|
+
// wrap every callback so a UI failure is swallowed and the loop continues.
|
|
11
|
+
const safe = (fn) => {
|
|
12
|
+
return (...a) => {
|
|
13
|
+
try {
|
|
14
|
+
fn(...a);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Intentionally ignored: the loop must survive UI failures.
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const safeThinking = safe(onThinking);
|
|
22
|
+
const safeAssistantThought = safe(onAssistantThought);
|
|
23
|
+
const safeToolCall = safe(onToolCall);
|
|
24
|
+
const safeToolResult = safe(onToolResult);
|
|
25
|
+
const safeAssistantMessage = safe(onAssistantMessage);
|
|
26
|
+
const safeWarning = safe(onWarning);
|
|
6
27
|
if (freshChat) {
|
|
7
28
|
await browser.newChat();
|
|
8
29
|
transcript?.log('new_chat');
|
|
@@ -42,7 +63,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
42
63
|
length: systemPrompt.length,
|
|
43
64
|
gitContext: gitText,
|
|
44
65
|
});
|
|
45
|
-
|
|
66
|
+
safeThinking();
|
|
46
67
|
// system-prompt is an agent send: throttled (agent: true).
|
|
47
68
|
await browser.ask(systemPrompt, { timeout: 60_000, agent: true });
|
|
48
69
|
await reportChat();
|
|
@@ -104,7 +125,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
104
125
|
let afterToolRetries = 0;
|
|
105
126
|
const MAX_AFTER_TOOL_RETRIES = 6;
|
|
106
127
|
for (let i = 0; i < maxIterations; i++) {
|
|
107
|
-
|
|
128
|
+
safeThinking();
|
|
108
129
|
// The first message (task) is user input: no throttle.
|
|
109
130
|
// Subsequent ones (tool-result and resend requests) are agent sends:
|
|
110
131
|
// throttled so we don't hit the rate limit.
|
|
@@ -139,7 +160,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
139
160
|
attempt: afterToolRetries,
|
|
140
161
|
error: e.message,
|
|
141
162
|
});
|
|
142
|
-
|
|
163
|
+
safeWarning('browser.ask() не вернул ответ за ' +
|
|
143
164
|
Math.round(askDeadlineMs / 1000) +
|
|
144
165
|
'с — повторяю запрос.');
|
|
145
166
|
if (afterToolRetries < MAX_AFTER_TOOL_RETRIES) {
|
|
@@ -150,7 +171,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
150
171
|
transcript?.log('ask_timeout_exhausted', {
|
|
151
172
|
message: 'ask() не вернул ответ и лимит повторов исчерпан',
|
|
152
173
|
});
|
|
153
|
-
|
|
174
|
+
safeWarning('browser.ask() перестал отвечать; лимит повторов исчерпан, ' +
|
|
154
175
|
'останавливаюсь. Ответа модели нет — проверьте чат DeepSeek вручную.');
|
|
155
176
|
return 'ask() watchdog: ответ модели не получен';
|
|
156
177
|
}
|
|
@@ -205,7 +226,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
205
226
|
if (parsed) {
|
|
206
227
|
const thought = extractPreToolText(rawResponse);
|
|
207
228
|
if (thought)
|
|
208
|
-
|
|
229
|
+
safeAssistantThought(thought);
|
|
209
230
|
}
|
|
210
231
|
const parsedCalls = Array.isArray(parsed) ? parsed : parsed ? [parsed] : [];
|
|
211
232
|
if (parsedCalls.some((p) => p && p._permissive)) {
|
|
@@ -341,7 +362,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
341
362
|
// not be turned into a tool call even after all retries: warn the
|
|
342
363
|
// operator instead of silently printing e.g. "Stale. Let me verify".
|
|
343
364
|
transcript?.log('suspicious_final', { response: rawResponse });
|
|
344
|
-
|
|
365
|
+
safeWarning(translate(locale)('msg.suspicious_stop'));
|
|
345
366
|
}
|
|
346
367
|
// A meaningful plain-text answer (e.g. a final report the model forgot to
|
|
347
368
|
// wrap in respond) is surfaced as-is WITHOUT a warning: after the bounded
|
|
@@ -393,11 +414,11 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
393
414
|
// the task normally.
|
|
394
415
|
if (!isMeaningfulRespond(msg)) {
|
|
395
416
|
transcript?.log('empty_respond_exhausted', { response: rawResponse });
|
|
396
|
-
|
|
417
|
+
safeWarning('Модель вызвала respond без текста, и лимит повторов исчерпан. ' +
|
|
397
418
|
'Проверьте чат DeepSeek вручную.');
|
|
398
419
|
return 'Модель не сформировала итоговое сообщение (пустой respond).';
|
|
399
420
|
}
|
|
400
|
-
|
|
421
|
+
safeAssistantMessage(msg);
|
|
401
422
|
transcript?.log('assistant_final', { message: msg });
|
|
402
423
|
return msg;
|
|
403
424
|
}
|
|
@@ -410,12 +431,12 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
410
431
|
const tool = tools.find((t) => t.name === call.tool);
|
|
411
432
|
if (!tool) {
|
|
412
433
|
const err = `Неизвестный инструмент: ${call.tool}`;
|
|
413
|
-
|
|
434
|
+
safeToolResult(err);
|
|
414
435
|
transcript?.log('tool_error', { tool: call.tool, error: err });
|
|
415
436
|
results.push({ tool: call.tool, result: err });
|
|
416
437
|
continue;
|
|
417
438
|
}
|
|
418
|
-
|
|
439
|
+
safeToolCall(call.tool, call.args);
|
|
419
440
|
transcript?.log('tool_call', { tool: call.tool, args: call.args });
|
|
420
441
|
let result;
|
|
421
442
|
try {
|
|
@@ -424,7 +445,7 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
424
445
|
catch (e) {
|
|
425
446
|
result = `Ошибка: ${e.message}`;
|
|
426
447
|
}
|
|
427
|
-
|
|
448
|
+
safeToolResult(result);
|
|
428
449
|
transcript?.log('tool_result', {
|
|
429
450
|
tool: call.tool,
|
|
430
451
|
result: String(result),
|