dsh-telegram-multiagent 1.1.0 → 1.2.1
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/README.md +18 -0
- package/package.json +1 -1
- package/src/client.js +44 -16
- package/src/index.js +6 -2
package/README.md
CHANGED
|
@@ -142,3 +142,21 @@ MIT.
|
|
|
142
142
|
внезапно раскрыть переписку в чужой канал. Ошибка чтения = `personal`, и о ней говорится в журнал.
|
|
143
143
|
|
|
144
144
|
Копируются и вопросы, и ответы: половина разговора без второй половины нечитаема.
|
|
145
|
+
|
|
146
|
+
## 1.2.0 — отправка переживает сбой сети
|
|
147
|
+
|
|
148
|
+
🔴 **Отправка теперь повторяется.** До этой версии одна неудачная попытка теряла сообщение
|
|
149
|
+
НАВСЕГДА и не оставляла следа — снаружи это неотличимо от «агент промолчал».
|
|
150
|
+
|
|
151
|
+
Поймано числами: на нашей машине `fetch failed` случается 6-10 раз в час. Копия вопроса не
|
|
152
|
+
дошла, а соседняя отправка четырьмя секундами позже прошла — то есть терялось не по логике, а по
|
|
153
|
+
случайности. Мы к тому моменту полдня искали причину молчания агента в коде, в настройках и в
|
|
154
|
+
чужих ботах.
|
|
155
|
+
|
|
156
|
+
Как сделано: три попытки с растущей паузой (0.4 с, 0.8 с), в журнал пишется, с какой попытки
|
|
157
|
+
удалось. Повторяются **только сетевые сбои**; отказ Telegram по существу (нет прав, чат не найден,
|
|
158
|
+
пустой текст) не повторяется — он воспроизведётся. Длинный опрос намеренно оставлен без повторов:
|
|
159
|
+
у него свой цикл, повтор лишь задержал бы следующий заход.
|
|
160
|
+
|
|
161
|
+
**Урок общий:** канал доставки без повтора — это тихая потеря. Отказ, о котором никто не узнал,
|
|
162
|
+
дороже отказа громкого: его невозможно даже сосчитать.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-telegram-multiagent",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Telegram channel for DeepSeek Harness — one shared module serving several agents, with unforgeable sender marks, merged owner+coordinator memory, and a delivery mode you switch in a file outside the code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/client.js
CHANGED
|
@@ -15,22 +15,50 @@ export class TelegramClient {
|
|
|
15
15
|
this.offset = 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 🔴 ПОВТОРЫ ОБЯЗАТЕЛЬНЫ (21.08.2026). Сеть до Telegram бывает дёрганой:
|
|
20
|
+
* у нас `fetch failed` случается 6-10 раз в час. Отправка без повтора теряет
|
|
21
|
+
* сообщение НАВСЕГДА с одной неудачной попытки, и снаружи это выглядит как
|
|
22
|
+
* «агент не ответил» — мы потратили вечер, ища причину в коде и в чужих ботах,
|
|
23
|
+
* а терялись именно отправки. Поймано на копии вопроса, которая не дошла,
|
|
24
|
+
* когда соседняя отправка четырьмя секундами позже прошла.
|
|
25
|
+
*
|
|
26
|
+
* Повторяем только СЕТЕВЫЕ сбои и 5xx. Отказ самого Telegram (ok:false —
|
|
27
|
+
* нет прав, чат не найден, текст пуст) повторять бессмысленно: он воспроизведётся.
|
|
28
|
+
* Длинный опрос НЕ повторяем: он и так вызывается в цикле, повтор лишь
|
|
29
|
+
* задержит следующий заход.
|
|
30
|
+
*/
|
|
31
|
+
async call(method, payload, timeoutMs = 15000, attempts = 3) {
|
|
32
|
+
let lastErr;
|
|
33
|
+
for (let n = 1; n <= attempts; n++) {
|
|
34
|
+
const ctl = new AbortController();
|
|
35
|
+
const t = setTimeout(() => ctl.abort(), timeoutMs);
|
|
36
|
+
try {
|
|
37
|
+
const res = await fetch(`${API}${this.token}/${method}`, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: { 'Content-Type': 'application/json' },
|
|
40
|
+
body: JSON.stringify(payload ?? {}),
|
|
41
|
+
signal: ctl.signal,
|
|
42
|
+
});
|
|
43
|
+
const data = await res.json();
|
|
44
|
+
if (!data.ok) {
|
|
45
|
+
const err = new Error(`${method}: ${data.description ?? 'неизвестная ошибка'}`);
|
|
46
|
+
err.fromTelegram = true; // отказ по существу — не повторяем
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
if (n > 1) this.log(`${method}: удалось с попытки ${n}`);
|
|
50
|
+
return data.result;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
lastErr = e;
|
|
53
|
+
if (e?.fromTelegram || n === attempts) break;
|
|
54
|
+
const wait = 400 * n; // 0.4с, 0.8с — растущая пауза
|
|
55
|
+
this.log(`${method}: попытка ${n} не удалась (${e?.message ?? e}), повтор через ${wait} мс`);
|
|
56
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
57
|
+
} finally {
|
|
58
|
+
clearTimeout(t);
|
|
59
|
+
}
|
|
33
60
|
}
|
|
61
|
+
throw lastErr;
|
|
34
62
|
}
|
|
35
63
|
|
|
36
64
|
/** Длинный опрос. Возвращает пришедшие обновления и двигает смещение. */
|
|
@@ -38,7 +66,7 @@ export class TelegramClient {
|
|
|
38
66
|
// timeout запроса больше, чем у сервера, иначе рвём его же длинный опрос
|
|
39
67
|
const updates = await this.call('getUpdates',
|
|
40
68
|
{ offset: this.offset, timeout: timeoutSec, allowed_updates: ['message'] },
|
|
41
|
-
(timeoutSec + 10) * 1000);
|
|
69
|
+
(timeoutSec + 10) * 1000, 1);
|
|
42
70
|
for (const u of updates) {
|
|
43
71
|
if (u.update_id >= this.offset) this.offset = u.update_id + 1;
|
|
44
72
|
}
|
package/src/index.js
CHANGED
|
@@ -453,8 +453,12 @@ export function apply(ctx, config = {}) {
|
|
|
453
453
|
const url = `https://api.telegram.org/file/bot${token}/${filePath}`;
|
|
454
454
|
const ext = path.extname(filePath) || '.oga';
|
|
455
455
|
const tmp = path.join(os.tmpdir(), `dsh-voice-${Date.now()}${ext}`);
|
|
456
|
-
//
|
|
457
|
-
|
|
456
|
+
// 🔴 Скачиваем ВСТРОЕННЫМ fetch, а не curl: адрес содержит токен бота, а
|
|
457
|
+
// строка запуска процесса (/proc/<pid>/cmdline) читается ЛЮБЫМ пользователем
|
|
458
|
+
// машины. Через curl токен утекал бы при КАЖДОМ голосовом сообщении.
|
|
459
|
+
const res = await fetch(url);
|
|
460
|
+
if (!res.ok) throw new Error(`telegram file download: HTTP ${res.status}`);
|
|
461
|
+
fs.writeFileSync(tmp, Buffer.from(await res.arrayBuffer()));
|
|
458
462
|
return tmp;
|
|
459
463
|
}
|
|
460
464
|
|