zames_pro 2.29.6 → 2.29.8
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/browser.js +52 -30
- package/dist/config.js +7 -0
- package/dist/i18n.js +4 -0
- package/dist/index.js +15 -5
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -167,9 +167,10 @@ const STOP_SELECTORS = [
|
|
|
167
167
|
// The agent must click it so the reasoning/answer keeps flowing, otherwise the
|
|
168
168
|
// turn sits idle until the operator presses Continue by hand.
|
|
169
169
|
//
|
|
170
|
-
// The button is found by
|
|
171
|
-
//
|
|
172
|
-
//
|
|
170
|
+
// The button is found by Playwright's accessible name (getByRole) with an
|
|
171
|
+
// EXACT match, falling back to a raw DOM scan. The class names change between
|
|
172
|
+
// builds, so we do not rely on them.
|
|
173
|
+
const CONTINUE_NAMES = ['Continue', 'Продолжить', 'Продолжение'];
|
|
173
174
|
// DeepSeek UI service statuses that are NOT the model's answer.
|
|
174
175
|
// Otherwise the agent takes a status (Reading...) for an answer and breaks parsing.
|
|
175
176
|
const STATUS_RE = /^(reading|thinking|searching|analyzing|generating|stop|остановить|читаю|думаю|поиск|анализ)[\s.…]*$/i;
|
|
@@ -1109,28 +1110,37 @@ export class DeepSeekBrowser {
|
|
|
1109
1110
|
// text there is exactly the "agent stopped with a Continue button" bug.
|
|
1110
1111
|
async _continueButtonVisible() {
|
|
1111
1112
|
try {
|
|
1112
|
-
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
const cands = Array.from(document.querySelectorAll('div[role="button"], button'));
|
|
1118
|
-
for (const e of cands) {
|
|
1119
|
-
if (!isExact(labelOf(e)))
|
|
1120
|
-
continue;
|
|
1121
|
-
const st = getComputedStyle(e);
|
|
1122
|
-
if (st.display === 'none' || st.visibility === 'hidden')
|
|
1123
|
-
continue;
|
|
1124
|
-
if (!e.offsetParent && st.position !== 'fixed')
|
|
1125
|
-
continue;
|
|
1113
|
+
for (const name of CONTINUE_NAMES) {
|
|
1114
|
+
const loc = this.page.getByRole('button', { name }).first();
|
|
1115
|
+
if ((await loc.count().catch(() => 0)) === 0)
|
|
1116
|
+
continue;
|
|
1117
|
+
if (await loc.isVisible().catch(() => false))
|
|
1126
1118
|
return true;
|
|
1127
|
-
|
|
1128
|
-
return false;
|
|
1129
|
-
});
|
|
1119
|
+
}
|
|
1130
1120
|
}
|
|
1131
|
-
catch {
|
|
1121
|
+
catch { }
|
|
1122
|
+
// Fallback: the raw DOM scan (older/newer DeepSeek builds where the role
|
|
1123
|
+
// is absent).
|
|
1124
|
+
return this.page
|
|
1125
|
+
.evaluate(() => {
|
|
1126
|
+
const labelOf = (b) => ((b.textContent || '') + ' ' + (b.getAttribute('aria-label') || ''))
|
|
1127
|
+
.replace(/\s+/g, ' ')
|
|
1128
|
+
.trim();
|
|
1129
|
+
const isExact = (t) => /^(continue|продолжить|продолжение)\s*[.!…]?$/i.test(t);
|
|
1130
|
+
const cands = Array.from(document.querySelectorAll('div[role="button"], button'));
|
|
1131
|
+
for (const e of cands) {
|
|
1132
|
+
if (!isExact(labelOf(e)))
|
|
1133
|
+
continue;
|
|
1134
|
+
const st = getComputedStyle(e);
|
|
1135
|
+
if (st.display === 'none' || st.visibility === 'hidden')
|
|
1136
|
+
continue;
|
|
1137
|
+
const r = e.getBoundingClientRect();
|
|
1138
|
+
if (r.width > 0 && r.height > 0)
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1132
1141
|
return false;
|
|
1133
|
-
}
|
|
1142
|
+
})
|
|
1143
|
+
.catch(() => false);
|
|
1134
1144
|
}
|
|
1135
1145
|
// Click the DeepSeek "Continue" button when it is visible (reasoning/answer
|
|
1136
1146
|
// paused by the server). Returns true when a click happened.
|
|
@@ -1141,14 +1151,29 @@ export class DeepSeekBrowser {
|
|
|
1141
1151
|
// only act on an EXACT short label so a random "Continue" in prose (a button
|
|
1142
1152
|
// inside a rendered answer, etc.) is never clicked.
|
|
1143
1153
|
async _clickContinueIfVisible() {
|
|
1154
|
+
// 1) Playwright's OWN click on the accessible name — this is a TRUSTED
|
|
1155
|
+
// event and reliably triggers React handlers. The old in-page
|
|
1156
|
+
// dispatchEvent/click often did nothing, which is exactly why the
|
|
1157
|
+
// operator saw the button and the "жму Continue" message but no resume.
|
|
1158
|
+
for (const name of CONTINUE_NAMES) {
|
|
1159
|
+
try {
|
|
1160
|
+
const loc = this.page.getByRole('button', { name }).first();
|
|
1161
|
+
if ((await loc.count().catch(() => 0)) === 0)
|
|
1162
|
+
continue;
|
|
1163
|
+
if (!(await loc.isVisible().catch(() => false)))
|
|
1164
|
+
continue;
|
|
1165
|
+
await loc.click({ timeout: 2000 });
|
|
1166
|
+
return true;
|
|
1167
|
+
}
|
|
1168
|
+
catch { }
|
|
1169
|
+
}
|
|
1170
|
+
// 2) Fallback: raw DOM scan + full pointer/mouse event sequence (an older
|
|
1171
|
+
// build without a proper role, or a click intercepted by an overlay).
|
|
1144
1172
|
try {
|
|
1145
1173
|
const clicked = await this.page.evaluate(() => {
|
|
1146
|
-
// Normalize a label: textContent + aria-label, whitespace collapsed.
|
|
1147
1174
|
const labelOf = (b) => ((b.textContent || '') + ' ' + (b.getAttribute('aria-label') || ''))
|
|
1148
1175
|
.replace(/\s+/g, ' ')
|
|
1149
1176
|
.trim();
|
|
1150
|
-
// The button must be a SHORT exact label, otherwise a paragraph or a
|
|
1151
|
-
// rendered "Continue" inside the answer could be clicked by mistake.
|
|
1152
1177
|
const isExact = (t) => /^(continue|продолжить|продолжение)\s*[.!…]?$/i.test(t);
|
|
1153
1178
|
const cands = Array.from(document.querySelectorAll('div[role="button"], button'));
|
|
1154
1179
|
for (const e of cands) {
|
|
@@ -1158,12 +1183,9 @@ export class DeepSeekBrowser {
|
|
|
1158
1183
|
const st = getComputedStyle(e);
|
|
1159
1184
|
if (st.display === 'none' || st.visibility === 'hidden')
|
|
1160
1185
|
continue;
|
|
1161
|
-
if (!e.offsetParent && st.position !== 'fixed')
|
|
1162
|
-
continue;
|
|
1163
|
-
// DeepSeek's button is a React component listening for POINTER/mouse
|
|
1164
|
-
// events, not just a bare click(). A plain e.click() sometimes does
|
|
1165
|
-
// nothing; dispatching the full sequence is what a real press does.
|
|
1166
1186
|
const rect = e.getBoundingClientRect();
|
|
1187
|
+
if (rect.width === 0 || rect.height === 0)
|
|
1188
|
+
continue;
|
|
1167
1189
|
const cx = rect.left + rect.width / 2;
|
|
1168
1190
|
const cy = rect.top + rect.height / 2;
|
|
1169
1191
|
const opts = {
|
package/dist/config.js
CHANGED
|
@@ -46,6 +46,7 @@ export const DEFAULTS = {
|
|
|
46
46
|
maxIncompleteRetries: 4,
|
|
47
47
|
incompleteWaitMs: 2000,
|
|
48
48
|
autoContinue: true,
|
|
49
|
+
resendPromptOnResume: false,
|
|
49
50
|
deepThinking: false,
|
|
50
51
|
webSearch: true,
|
|
51
52
|
auth: {
|
|
@@ -255,6 +256,12 @@ export const CONFIG_SCHEMA = [
|
|
|
255
256
|
labelKey: 'cfg.f.browser_autoContinue',
|
|
256
257
|
groupKey: 'cfg.group.browser',
|
|
257
258
|
},
|
|
259
|
+
{
|
|
260
|
+
path: 'browser.resendPromptOnResume',
|
|
261
|
+
type: 'boolean',
|
|
262
|
+
labelKey: 'cfg.f.browser_resendPromptOnResume',
|
|
263
|
+
groupKey: 'cfg.group.browser',
|
|
264
|
+
},
|
|
258
265
|
{
|
|
259
266
|
path: 'browser.deepThinking',
|
|
260
267
|
type: 'boolean',
|
package/dist/i18n.js
CHANGED
|
@@ -878,6 +878,10 @@ const CATALOG = {
|
|
|
878
878
|
ru: 'Автонажатие кнопки Continue (режим размышления)',
|
|
879
879
|
en: 'Auto-click Continue (reasoning mode)',
|
|
880
880
|
},
|
|
881
|
+
'cfg.f.browser_resendPromptOnResume': {
|
|
882
|
+
ru: 'Пересылать системный промпт при возобновлении чата',
|
|
883
|
+
en: 'Resend the system prompt on chat resume',
|
|
884
|
+
},
|
|
881
885
|
'cfg.f.browser_deepThinking': {
|
|
882
886
|
ru: 'Глубокое мышление (долго; размышления не выводятся)',
|
|
883
887
|
en: 'Deep thinking (slow; reasoning is hidden)',
|
package/dist/index.js
CHANGED
|
@@ -1114,7 +1114,8 @@ async function main() {
|
|
|
1114
1114
|
console.log(theme.system(t('msg.opening_chat', { id: resumeId })));
|
|
1115
1115
|
await browser.openChat(resumeId);
|
|
1116
1116
|
freshChat = false;
|
|
1117
|
-
sendSystemPrompt =
|
|
1117
|
+
sendSystemPrompt =
|
|
1118
|
+
resendPrompt || config.browser.resendPromptOnResume === true;
|
|
1118
1119
|
saveLastChat(resumeId, currentWorkdir);
|
|
1119
1120
|
}
|
|
1120
1121
|
catch (e) {
|
|
@@ -1142,6 +1143,11 @@ async function main() {
|
|
|
1142
1143
|
console.log(theme.system(t('msg.queue_hint')));
|
|
1143
1144
|
let freshChatNext = true;
|
|
1144
1145
|
let sendSystemPromptNext = true;
|
|
1146
|
+
// Resuming an existing chat already has the system-prompt at its start, so
|
|
1147
|
+
// resending it is wasteful and pollutes the context. Default: do NOT resend.
|
|
1148
|
+
// `--resend-prompt` or `browser.resendPromptOnResume` forces it (e.g. when
|
|
1149
|
+
// the prompt/tools changed).
|
|
1150
|
+
const promptOnResume = () => resendPrompt || config.browser.resendPromptOnResume === true;
|
|
1145
1151
|
let lastChats = [];
|
|
1146
1152
|
let currentChatId = null;
|
|
1147
1153
|
let running = true;
|
|
@@ -1187,7 +1193,7 @@ async function main() {
|
|
|
1187
1193
|
await browser.openChat(resumeId);
|
|
1188
1194
|
currentChatId = resumeId;
|
|
1189
1195
|
freshChatNext = false;
|
|
1190
|
-
sendSystemPromptNext =
|
|
1196
|
+
sendSystemPromptNext = promptOnResume();
|
|
1191
1197
|
saveLastChat(resumeId, currentWorkdir);
|
|
1192
1198
|
console.log(theme.system(t('msg.chat_opened') + ' ' + resumeId + String.fromCharCode(10)));
|
|
1193
1199
|
await printRestoredHistory(browser, null, resumeId);
|
|
@@ -1892,11 +1898,15 @@ async function main() {
|
|
|
1892
1898
|
await browser.openChat(pick.id);
|
|
1893
1899
|
currentChatId = pick.id;
|
|
1894
1900
|
freshChatNext = false;
|
|
1895
|
-
sendSystemPromptNext =
|
|
1901
|
+
sendSystemPromptNext = promptOnResume();
|
|
1896
1902
|
saveLastChat(pick.id, currentWorkdir, pick.title);
|
|
1897
1903
|
transcript.log('resume_chat', { id: pick.id, title: pick.title });
|
|
1898
1904
|
console.log(theme.assistant(t('msg.chat_opened')) +
|
|
1899
|
-
theme.system(
|
|
1905
|
+
theme.system(sendSystemPromptNext
|
|
1906
|
+
? String.fromCharCode(10) +
|
|
1907
|
+
' Системный промпт будет переслан на следующей задаче.\n'
|
|
1908
|
+
: String.fromCharCode(10) +
|
|
1909
|
+
' Системный промпт НЕ пересылается (он уже в начале чата). Включить: /config set browser.resendPromptOnResume true.\n'));
|
|
1900
1910
|
await printRestoredHistory(browser, editor, pick.id);
|
|
1901
1911
|
}
|
|
1902
1912
|
catch (e) {
|
|
@@ -1950,7 +1960,7 @@ async function main() {
|
|
|
1950
1960
|
await browser.openChat(id);
|
|
1951
1961
|
currentChatId = id;
|
|
1952
1962
|
freshChatNext = false;
|
|
1953
|
-
sendSystemPromptNext =
|
|
1963
|
+
sendSystemPromptNext = promptOnResume();
|
|
1954
1964
|
saveLastChat(id, currentWorkdir);
|
|
1955
1965
|
transcript.log('resume_chat', { id });
|
|
1956
1966
|
console.log(theme.assistant('Чат открыт.') +
|