@0xmaxma/claude-gateway 1.7.4 → 1.7.6
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/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +5 -4
- package/dist/agent/runner.js.map +1 -1
- package/dist/telegram/markdown.d.ts +19 -0
- package/dist/telegram/markdown.d.ts.map +1 -1
- package/dist/telegram/markdown.js +71 -0
- package/dist/telegram/markdown.js.map +1 -1
- package/mcp/instructions.ts +2 -0
- package/mcp/tools/telegram/lib/markdown.ts +77 -0
- package/mcp/tools/telegram/module.ts +29 -34
- package/mcp/tools/telegram/pure.ts +6 -1
- package/mcp/tools/telegram/receiver-server.ts +21 -37
- package/mcp/tools/telegram/typing.ts +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/telegram/markdown.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYjD;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/telegram/markdown.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mGAAmG;AACnG,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhE;AAkBD,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYjD;AAiGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmJnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CASrD"}
|
|
@@ -4,8 +4,38 @@
|
|
|
4
4
|
* Used by AgentRunner to auto-format agent output before forwarding.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.normalizeTelegramLineBreaks = normalizeTelegramLineBreaks;
|
|
8
|
+
exports.containsTelegramHtml = containsTelegramHtml;
|
|
7
9
|
exports.hasMarkdown = hasMarkdown;
|
|
8
10
|
exports.toTelegramHtml = toTelegramHtml;
|
|
11
|
+
exports.resolveTelegramReplyFormat = resolveTelegramReplyFormat;
|
|
12
|
+
/** Telegram does not support HTML <br> tags; normalize raw and escaped variants to line breaks. */
|
|
13
|
+
function normalizeTelegramLineBreaks(text) {
|
|
14
|
+
return text.replace(/(?:<|<)br\s*\/?(?:>|>)/gi, '\n');
|
|
15
|
+
}
|
|
16
|
+
// Opening (with optional attributes) or closing form of every tag Telegram's
|
|
17
|
+
// HTML parse mode honours. Sticky so it can be tested at a given offset without
|
|
18
|
+
// slicing. `[^<>]*` keeps an attribute run from swallowing past the tag. `span`
|
|
19
|
+
// is intentionally excluded: only `<span class="tg-spoiler">` is valid Telegram
|
|
20
|
+
// HTML and pairing a class-bearing open with a bare `</span>` close is
|
|
21
|
+
// error-prone — agents should use the canonical `<tg-spoiler>` element instead.
|
|
22
|
+
const TELEGRAM_HTML_TAG = /<\/?(?:a|b|blockquote|code|del|em|i|ins|pre|s|strike|strong|tg-spoiler|u)(?:\s[^<>]*)?>/iy;
|
|
23
|
+
/** Length of a valid Telegram HTML tag starting at `i` (where text[i] === '<'), or 0 if none. */
|
|
24
|
+
function matchTelegramTag(text, i) {
|
|
25
|
+
if (text[i] !== '<')
|
|
26
|
+
return 0;
|
|
27
|
+
TELEGRAM_HTML_TAG.lastIndex = i;
|
|
28
|
+
const m = TELEGRAM_HTML_TAG.exec(text);
|
|
29
|
+
return m ? m[0].length : 0;
|
|
30
|
+
}
|
|
31
|
+
/** Whether text already contains at least one Telegram-whitelist HTML tag written directly. */
|
|
32
|
+
function containsTelegramHtml(text) {
|
|
33
|
+
for (let i = text.indexOf('<'); i !== -1; i = text.indexOf('<', i + 1)) {
|
|
34
|
+
if (matchTelegramTag(text, i) > 0)
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
9
39
|
/**
|
|
10
40
|
* Detects whether text contains markdown formatting patterns
|
|
11
41
|
* that warrant HTML rendering in Telegram.
|
|
@@ -28,6 +58,15 @@ function hasMarkdown(text) {
|
|
|
28
58
|
function escapeHtml(text) {
|
|
29
59
|
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
30
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Escapes a bare `&` (one not already opening a character entity) inside a
|
|
63
|
+
* passed-through Telegram HTML tag — Telegram rejects a raw `&` in e.g. an
|
|
64
|
+
* <a href> query string ("...?a=1&b=2"). `<`/`>` cannot occur here because the
|
|
65
|
+
* tag matcher forbids them in the attribute run, so only `&` needs escaping.
|
|
66
|
+
*/
|
|
67
|
+
function escapeTagAmp(tag) {
|
|
68
|
+
return tag.replace(/&(?!(?:amp|lt|gt|quot|apos|#\d+|#x[0-9a-fA-F]+);)/g, '&');
|
|
69
|
+
}
|
|
31
70
|
/**
|
|
32
71
|
* Escapes HTML special characters in a URL attribute value.
|
|
33
72
|
*/
|
|
@@ -214,6 +253,17 @@ function toTelegramHtml(text) {
|
|
|
214
253
|
continue;
|
|
215
254
|
}
|
|
216
255
|
}
|
|
256
|
+
// Pass through a valid Telegram HTML tag the agent wrote directly, verbatim.
|
|
257
|
+
// Non-whitelist tags (e.g. <script>) fail the match and are escaped as plain
|
|
258
|
+
// text below, so this is a controlled pass-through, not raw HTML injection.
|
|
259
|
+
if (text[i] === '<') {
|
|
260
|
+
const tagLen = matchTelegramTag(text, i);
|
|
261
|
+
if (tagLen > 0) {
|
|
262
|
+
out.push(escapeTagAmp(text.slice(i, i + tagLen)));
|
|
263
|
+
i += tagLen;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
217
267
|
// Accumulate plain text until next markdown token
|
|
218
268
|
let j = i + 1;
|
|
219
269
|
while (j < len) {
|
|
@@ -224,6 +274,7 @@ function toTelegramHtml(text) {
|
|
|
224
274
|
(c === '*' && text[j + 1] !== '*' && text[j + 1] !== ' ') ||
|
|
225
275
|
(c === '_' && text[j + 1] !== '_' && text[j + 1] !== ' ') ||
|
|
226
276
|
c === '[' ||
|
|
277
|
+
(c === '<' && matchTelegramTag(text, j) > 0) ||
|
|
227
278
|
(c === '#' && (j === 0 || text[j - 1] === '\n')) ||
|
|
228
279
|
(c === '|' && (j === 0 || text[j - 1] === '\n')))
|
|
229
280
|
break;
|
|
@@ -234,4 +285,24 @@ function toTelegramHtml(text) {
|
|
|
234
285
|
}
|
|
235
286
|
return out.join('');
|
|
236
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Resolve how a channel reply should be sent given an optional explicit format.
|
|
290
|
+
* Mirrors the auto-forward decision in src/agent/runner.ts: agent-authored
|
|
291
|
+
* Telegram HTML tags must trigger HTML mode even when the text contains no
|
|
292
|
+
* markdown, otherwise a pure-HTML reply falls through to raw text with no
|
|
293
|
+
* parse_mode and the tags render literally (e.g. a visible "<b>").
|
|
294
|
+
* - explicit 'html' + already-valid Telegram HTML -> send verbatim under HTML
|
|
295
|
+
* - explicit 'html' (not yet valid) -> convert via toTelegramHtml under HTML
|
|
296
|
+
* - explicit 'text' -> always raw, no parse_mode (caller asked for plain text)
|
|
297
|
+
* - auto (no format) -> HTML when markdown OR Telegram tags are present
|
|
298
|
+
*/
|
|
299
|
+
function resolveTelegramReplyFormat(text, explicitFormat) {
|
|
300
|
+
const inputIsHtml = explicitFormat === 'html' && containsTelegramHtml(text);
|
|
301
|
+
const useHtml = inputIsHtml ||
|
|
302
|
+
explicitFormat === 'html' ||
|
|
303
|
+
(!explicitFormat && (hasMarkdown(text) || containsTelegramHtml(text)));
|
|
304
|
+
const sendText = useHtml && !inputIsHtml ? toTelegramHtml(text) : text;
|
|
305
|
+
const parseMode = useHtml ? 'HTML' : undefined;
|
|
306
|
+
return { sendText, parseMode };
|
|
307
|
+
}
|
|
237
308
|
//# sourceMappingURL=markdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/telegram/markdown.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/telegram/markdown.ts"],"names":[],"mappings":"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"}
|
package/mcp/instructions.ts
CHANGED
|
@@ -25,6 +25,8 @@ export function buildChannelInstructions(imageEnabled: boolean): string {
|
|
|
25
25
|
'',
|
|
26
26
|
'Messages from Telegram arrive as <channel source="telegram" chat_id="..." message_id="..." user="..." ts="...">. If the tag has an image_path attribute, Read that file — it is a photo the sender attached. If the tag has attachment_file_id, call download_attachment with that file_id to fetch the file, then Read the returned path. Reply with the reply tool — pass chat_id back. Use reply_to (set to a message_id) only when replying to an earlier message; the latest message doesn\'t need a quote-reply, omit reply_to for normal responses.',
|
|
27
27
|
'',
|
|
28
|
+
'Use the current channel\'s reply tool only when you have a user-facing answer. Do not put tool-by-tool progress narration in final text output: use that channel\'s edit-message tool for interim status, then send one concise final reply so automatic forwarding cannot expose an internal worklog.',
|
|
29
|
+
'',
|
|
28
30
|
'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, and edit_message for interim progress updates. Edits don\'t trigger push notifications — when a long task completes, send a new reply so the user\'s device pings.',
|
|
29
31
|
'',
|
|
30
32
|
"Telegram's Bot API exposes no history or search — you only see messages as they arrive. If you need earlier context, ask the user to paste it or summarize.",
|
|
@@ -3,6 +3,35 @@
|
|
|
3
3
|
* Used by AgentRunner to auto-format agent output before forwarding.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/** Telegram does not support HTML <br> tags; normalize raw and escaped variants to line breaks. */
|
|
7
|
+
export function normalizeTelegramLineBreaks(text: string): string {
|
|
8
|
+
return text.replace(/(?:<|<)br\s*\/?(?:>|>)/gi, '\n')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Opening (with optional attributes) or closing form of every tag Telegram's
|
|
12
|
+
// HTML parse mode honours. Sticky so it can be tested at a given offset without
|
|
13
|
+
// slicing. `[^<>]*` keeps an attribute run from swallowing past the tag. `span`
|
|
14
|
+
// is intentionally excluded: only `<span class="tg-spoiler">` is valid Telegram
|
|
15
|
+
// HTML and pairing a class-bearing open with a bare `</span>` close is
|
|
16
|
+
// error-prone — agents should use the canonical `<tg-spoiler>` element instead.
|
|
17
|
+
const TELEGRAM_HTML_TAG = /<\/?(?:a|b|blockquote|code|del|em|i|ins|pre|s|strike|strong|tg-spoiler|u)(?:\s[^<>]*)?>/iy
|
|
18
|
+
|
|
19
|
+
/** Length of a valid Telegram HTML tag starting at `i` (where text[i] === '<'), or 0 if none. */
|
|
20
|
+
function matchTelegramTag(text: string, i: number): number {
|
|
21
|
+
if (text[i] !== '<') return 0
|
|
22
|
+
TELEGRAM_HTML_TAG.lastIndex = i
|
|
23
|
+
const m = TELEGRAM_HTML_TAG.exec(text)
|
|
24
|
+
return m ? m[0].length : 0
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Whether text already contains at least one Telegram-whitelist HTML tag written directly. */
|
|
28
|
+
export function containsTelegramHtml(text: string): boolean {
|
|
29
|
+
for (let i = text.indexOf('<'); i !== -1; i = text.indexOf('<', i + 1)) {
|
|
30
|
+
if (matchTelegramTag(text, i) > 0) return true
|
|
31
|
+
}
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
6
35
|
/**
|
|
7
36
|
* Detects whether text contains markdown formatting patterns
|
|
8
37
|
* that warrant HTML rendering in Telegram.
|
|
@@ -28,6 +57,16 @@ function escapeHtml(text: string): string {
|
|
|
28
57
|
return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
29
58
|
}
|
|
30
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Escapes a bare `&` (one not already opening a character entity) inside a
|
|
62
|
+
* passed-through Telegram HTML tag — Telegram rejects a raw `&` in e.g. an
|
|
63
|
+
* <a href> query string ("...?a=1&b=2"). `<`/`>` cannot occur here because the
|
|
64
|
+
* tag matcher forbids them in the attribute run, so only `&` needs escaping.
|
|
65
|
+
*/
|
|
66
|
+
function escapeTagAmp(tag: string): string {
|
|
67
|
+
return tag.replace(/&(?!(?:amp|lt|gt|quot|apos|#\d+|#x[0-9a-fA-F]+);)/g, '&')
|
|
68
|
+
}
|
|
69
|
+
|
|
31
70
|
/**
|
|
32
71
|
* Escapes HTML special characters in a URL attribute value.
|
|
33
72
|
*/
|
|
@@ -233,6 +272,18 @@ export function toTelegramHtml(text: string): string {
|
|
|
233
272
|
}
|
|
234
273
|
}
|
|
235
274
|
|
|
275
|
+
// Pass through a valid Telegram HTML tag the agent wrote directly, verbatim.
|
|
276
|
+
// Non-whitelist tags (e.g. <script>) fail the match and are escaped as plain
|
|
277
|
+
// text below, so this is a controlled pass-through, not raw HTML injection.
|
|
278
|
+
if (text[i] === '<') {
|
|
279
|
+
const tagLen = matchTelegramTag(text, i)
|
|
280
|
+
if (tagLen > 0) {
|
|
281
|
+
out.push(escapeTagAmp(text.slice(i, i + tagLen)))
|
|
282
|
+
i += tagLen
|
|
283
|
+
continue
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
236
287
|
// Accumulate plain text until next markdown token
|
|
237
288
|
let j = i + 1
|
|
238
289
|
while (j < len) {
|
|
@@ -244,6 +295,7 @@ export function toTelegramHtml(text: string): string {
|
|
|
244
295
|
(c === '*' && text[j + 1] !== '*' && text[j + 1] !== ' ') ||
|
|
245
296
|
(c === '_' && text[j + 1] !== '_' && text[j + 1] !== ' ') ||
|
|
246
297
|
c === '[' ||
|
|
298
|
+
(c === '<' && matchTelegramTag(text, j) > 0) ||
|
|
247
299
|
(c === '#' && (j === 0 || text[j - 1] === '\n')) ||
|
|
248
300
|
(c === '|' && (j === 0 || text[j - 1] === '\n'))
|
|
249
301
|
) break
|
|
@@ -255,3 +307,28 @@ export function toTelegramHtml(text: string): string {
|
|
|
255
307
|
|
|
256
308
|
return out.join('')
|
|
257
309
|
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Resolve how a channel reply should be sent given an optional explicit format.
|
|
313
|
+
* Mirrors the auto-forward decision in src/agent/runner.ts: agent-authored
|
|
314
|
+
* Telegram HTML tags must trigger HTML mode even when the text contains no
|
|
315
|
+
* markdown, otherwise a pure-HTML reply falls through to raw text with no
|
|
316
|
+
* parse_mode and the tags render literally (e.g. a visible "<b>").
|
|
317
|
+
* - explicit 'html' + already-valid Telegram HTML -> send verbatim under HTML
|
|
318
|
+
* - explicit 'html' (not yet valid) -> convert via toTelegramHtml under HTML
|
|
319
|
+
* - explicit 'text' -> always raw, no parse_mode (caller asked for plain text)
|
|
320
|
+
* - auto (no format) -> HTML when markdown OR Telegram tags are present
|
|
321
|
+
*/
|
|
322
|
+
export function resolveTelegramReplyFormat(
|
|
323
|
+
text: string,
|
|
324
|
+
explicitFormat?: string,
|
|
325
|
+
): { sendText: string; parseMode: 'HTML' | undefined } {
|
|
326
|
+
const inputIsHtml = explicitFormat === 'html' && containsTelegramHtml(text)
|
|
327
|
+
const useHtml =
|
|
328
|
+
inputIsHtml ||
|
|
329
|
+
explicitFormat === 'html' ||
|
|
330
|
+
(!explicitFormat && (hasMarkdown(text) || containsTelegramHtml(text)))
|
|
331
|
+
const sendText = useHtml && !inputIsHtml ? toTelegramHtml(text) : text
|
|
332
|
+
const parseMode: 'HTML' | undefined = useHtml ? 'HTML' : undefined
|
|
333
|
+
return { sendText, parseMode }
|
|
334
|
+
}
|
|
@@ -7,6 +7,7 @@ import * as path from 'path';
|
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as os from 'os';
|
|
9
9
|
import { migrateAccess, defaultAccess } from './pure';
|
|
10
|
+
import { chunkText, htmlToPlain } from './typing';
|
|
10
11
|
import type {
|
|
11
12
|
ChannelModule,
|
|
12
13
|
ChannelCapabilities,
|
|
@@ -47,6 +48,12 @@ export class TelegramModule implements ChannelModule {
|
|
|
47
48
|
private lastError?: string;
|
|
48
49
|
private _hasMarkdown?: (text: string) => boolean;
|
|
49
50
|
private _toTelegramHtml?: (text: string) => string;
|
|
51
|
+
private _normalizeTelegramLineBreaks?: (text: string) => string;
|
|
52
|
+
private _containsTelegramHtml?: (text: string) => boolean;
|
|
53
|
+
private _resolveTelegramReplyFormat?: (
|
|
54
|
+
text: string,
|
|
55
|
+
explicitFormat?: string,
|
|
56
|
+
) => { sendText: string; parseMode: 'HTML' | undefined };
|
|
50
57
|
private _InputFile?: any;
|
|
51
58
|
private _typingManager?: any;
|
|
52
59
|
|
|
@@ -97,7 +104,7 @@ export class TelegramModule implements ChannelModule {
|
|
|
97
104
|
format: {
|
|
98
105
|
type: 'string',
|
|
99
106
|
enum: ['text', 'html'],
|
|
100
|
-
description: "Rendering mode. 'html'
|
|
107
|
+
description: "Rendering mode. 'html' accepts pre-rendered Telegram HTML. Raw Markdown is detected and converted automatically. Default: auto-detect Markdown or send plain text.",
|
|
101
108
|
},
|
|
102
109
|
},
|
|
103
110
|
required: ['chat_id', 'text'],
|
|
@@ -139,7 +146,7 @@ export class TelegramModule implements ChannelModule {
|
|
|
139
146
|
format: {
|
|
140
147
|
type: 'string',
|
|
141
148
|
enum: ['text', 'html'],
|
|
142
|
-
description: "Rendering mode. 'html'
|
|
149
|
+
description: "Rendering mode. 'html' accepts pre-rendered Telegram HTML. Raw Markdown is detected and converted automatically. Default: auto-detect Markdown or send plain text.",
|
|
143
150
|
},
|
|
144
151
|
},
|
|
145
152
|
required: ['chat_id', 'message_id', 'text'],
|
|
@@ -188,7 +195,7 @@ export class TelegramModule implements ChannelModule {
|
|
|
188
195
|
});
|
|
189
196
|
|
|
190
197
|
// Import pure functions and typing manager
|
|
191
|
-
const { hasMarkdown, toTelegramHtml } = await import('./pure');
|
|
198
|
+
const { hasMarkdown, toTelegramHtml, normalizeTelegramLineBreaks, containsTelegramHtml, resolveTelegramReplyFormat } = await import('./pure');
|
|
192
199
|
const { createWorkingStateManager } = await import('./typing');
|
|
193
200
|
|
|
194
201
|
const typingManager = createWorkingStateManager(
|
|
@@ -208,6 +215,9 @@ export class TelegramModule implements ChannelModule {
|
|
|
208
215
|
|
|
209
216
|
this._hasMarkdown = hasMarkdown;
|
|
210
217
|
this._toTelegramHtml = toTelegramHtml;
|
|
218
|
+
this._normalizeTelegramLineBreaks = normalizeTelegramLineBreaks;
|
|
219
|
+
this._containsTelegramHtml = containsTelegramHtml;
|
|
220
|
+
this._resolveTelegramReplyFormat = resolveTelegramReplyFormat;
|
|
211
221
|
this._InputFile = InputFile;
|
|
212
222
|
this._typingManager = typingManager;
|
|
213
223
|
|
|
@@ -285,39 +295,18 @@ export class TelegramModule implements ChannelModule {
|
|
|
285
295
|
}
|
|
286
296
|
}
|
|
287
297
|
|
|
288
|
-
private chunk(text: string, limit: number, mode: 'length' | 'newline'): string[] {
|
|
289
|
-
if (text.length <= limit) return [text];
|
|
290
|
-
const out: string[] = [];
|
|
291
|
-
let rest = text;
|
|
292
|
-
while (rest.length > limit) {
|
|
293
|
-
let cut = limit;
|
|
294
|
-
if (mode === 'newline') {
|
|
295
|
-
const para = rest.lastIndexOf('\n\n', limit);
|
|
296
|
-
const line = rest.lastIndexOf('\n', limit);
|
|
297
|
-
const space = rest.lastIndexOf(' ', limit);
|
|
298
|
-
cut = para > limit / 2 ? para : line > limit / 2 ? line : space > 0 ? space : limit;
|
|
299
|
-
}
|
|
300
|
-
out.push(rest.slice(0, cut));
|
|
301
|
-
rest = rest.slice(cut).replace(/^\n+/, '');
|
|
302
|
-
}
|
|
303
|
-
if (rest) out.push(rest);
|
|
304
|
-
return out;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
298
|
private async handleReply(args: Record<string, unknown>): Promise<McpToolResult> {
|
|
308
299
|
const chat_id = args.chat_id as string;
|
|
309
|
-
const text = args.text as string;
|
|
300
|
+
const text = this._normalizeTelegramLineBreaks!(args.text as string);
|
|
310
301
|
const reply_to = args.reply_to != null ? Number(args.reply_to) : undefined;
|
|
311
302
|
const files = (args.files as string[] | undefined) ?? [];
|
|
312
303
|
const explicitFormat = args.format as string | undefined;
|
|
313
|
-
|
|
314
|
-
const hasMarkdown = this._hasMarkdown!;
|
|
315
|
-
const toTelegramHtml = this._toTelegramHtml!;
|
|
316
304
|
const InputFile = this._InputFile;
|
|
317
305
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
306
|
+
// Single source of truth for reply format detection (shared with receiver-server).
|
|
307
|
+
// Auto mode uses HTML when the text has markdown OR agent-authored Telegram HTML
|
|
308
|
+
// tags — the latter fixes HTML-only replies being sent raw (no parse_mode).
|
|
309
|
+
const { sendText, parseMode } = this._resolveTelegramReplyFormat!(text, explicitFormat);
|
|
321
310
|
|
|
322
311
|
this.assertAllowedChat(chat_id);
|
|
323
312
|
|
|
@@ -331,9 +320,8 @@ export class TelegramModule implements ChannelModule {
|
|
|
331
320
|
|
|
332
321
|
const access = this.readAccessFile();
|
|
333
322
|
const limit = Math.max(1, Math.min(access.textChunkLimit ?? MAX_CHUNK_LIMIT, MAX_CHUNK_LIMIT));
|
|
334
|
-
const mode = access.chunkMode ?? 'length';
|
|
335
323
|
const replyMode = access.replyToMode ?? 'first';
|
|
336
|
-
const chunks =
|
|
324
|
+
const chunks = chunkText(sendText, limit, parseMode === 'HTML');
|
|
337
325
|
const sentIds: number[] = [];
|
|
338
326
|
|
|
339
327
|
try {
|
|
@@ -342,11 +330,18 @@ export class TelegramModule implements ChannelModule {
|
|
|
342
330
|
reply_to != null &&
|
|
343
331
|
replyMode !== 'off' &&
|
|
344
332
|
(replyMode === 'all' || i === 0);
|
|
345
|
-
const
|
|
333
|
+
const opts = {
|
|
346
334
|
...(shouldReplyTo ? { reply_parameters: { message_id: reply_to } } : {}),
|
|
347
335
|
...(parseMode ? { parse_mode: parseMode } : {}),
|
|
348
|
-
}
|
|
349
|
-
|
|
336
|
+
};
|
|
337
|
+
try {
|
|
338
|
+
const sent = await this.bot.api.sendMessage(chat_id, chunks[i], opts);
|
|
339
|
+
sentIds.push(sent.message_id);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
if (!parseMode) throw err;
|
|
342
|
+
const sent = await this.bot.api.sendMessage(chat_id, htmlToPlain(chunks[i]), shouldReplyTo ? { reply_parameters: { message_id: reply_to } } : undefined);
|
|
343
|
+
sentIds.push(sent.message_id);
|
|
344
|
+
}
|
|
350
345
|
}
|
|
351
346
|
} catch (err) {
|
|
352
347
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -332,7 +332,12 @@ function countPending(access: Access, kind: 'dm' | 'group'): number {
|
|
|
332
332
|
return n
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
-
export { hasMarkdown, toTelegramHtml } from './lib/markdown'
|
|
335
|
+
export { hasMarkdown, toTelegramHtml, containsTelegramHtml, resolveTelegramReplyFormat } from './lib/markdown'
|
|
336
|
+
|
|
337
|
+
/** Telegram does not support HTML <br> tags; normalize raw and escaped variants to line breaks. */
|
|
338
|
+
export function normalizeTelegramLineBreaks(text: string): string {
|
|
339
|
+
return text.replace(/(?:<|<)br\s*\/?(?:>|>)/gi, '\n')
|
|
340
|
+
}
|
|
336
341
|
|
|
337
342
|
export function isMentionedPure(input: GateInput, extraPatterns?: string[]): boolean {
|
|
338
343
|
const entities = input.messageEntities ?? input.captionEntities ?? []
|
|
@@ -29,7 +29,7 @@ import { readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, statSync,
|
|
|
29
29
|
import { homedir } from 'os'
|
|
30
30
|
import { join, extname, sep } from 'path'
|
|
31
31
|
import { execFileSync } from 'child_process'
|
|
32
|
-
import { createWorkingStateManager, drainOrphanForwards } from './typing'
|
|
32
|
+
import { createWorkingStateManager, drainOrphanForwards, chunkText, htmlToPlain } from './typing'
|
|
33
33
|
// Import compiled dist/, not raw src/ — src/ is not published (files: ["mcp/"]),
|
|
34
34
|
// so a src/ import crashes this bun-run receiver on installed packages (the bug
|
|
35
35
|
// that silenced every bot on systemd installs). Enforced by
|
|
@@ -38,7 +38,7 @@ import { formatTurnIncident, type TurnIncident } from '../../../dist/agent/turn-
|
|
|
38
38
|
import { createIncidentStore } from '../../../dist/agent/incident-store.js'
|
|
39
39
|
import type { RecoveryOutcome } from '../../../dist/agent/incident.js'
|
|
40
40
|
import { initDedupDir, isDuplicate as _isDuplicate, pruneDedup as _pruneDedup } from './dedup'
|
|
41
|
-
import {
|
|
41
|
+
import { normalizeTelegramLineBreaks, resolveTelegramReplyFormat, migrateAccess, telegramDisplayName } from './pure'
|
|
42
42
|
|
|
43
43
|
// Standalone fallback: default state dir to ~/.claude/channels/telegram
|
|
44
44
|
const STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join(homedir(), '.claude', 'channels', 'telegram')
|
|
@@ -565,29 +565,6 @@ function checkApprovals(): void {
|
|
|
565
565
|
|
|
566
566
|
setInterval(checkApprovals, 5000).unref()
|
|
567
567
|
|
|
568
|
-
// Telegram caps messages at 4096 chars. Split long replies, preferring
|
|
569
|
-
// paragraph boundaries when chunkMode is 'newline'.
|
|
570
|
-
function chunk(text: string, limit: number, mode: 'length' | 'newline'): string[] {
|
|
571
|
-
if (text.length <= limit) return [text]
|
|
572
|
-
const out: string[] = []
|
|
573
|
-
let rest = text
|
|
574
|
-
while (rest.length > limit) {
|
|
575
|
-
let cut = limit
|
|
576
|
-
if (mode === 'newline') {
|
|
577
|
-
// Prefer the last double-newline (paragraph), then single newline,
|
|
578
|
-
// then space. Fall back to hard cut.
|
|
579
|
-
const para = rest.lastIndexOf('\n\n', limit)
|
|
580
|
-
const line = rest.lastIndexOf('\n', limit)
|
|
581
|
-
const space = rest.lastIndexOf(' ', limit)
|
|
582
|
-
cut = para > limit / 2 ? para : line > limit / 2 ? line : space > 0 ? space : limit
|
|
583
|
-
}
|
|
584
|
-
out.push(rest.slice(0, cut))
|
|
585
|
-
rest = rest.slice(cut).replace(/^\n+/, '')
|
|
586
|
-
}
|
|
587
|
-
if (rest) out.push(rest)
|
|
588
|
-
return out
|
|
589
|
-
}
|
|
590
|
-
|
|
591
568
|
// .jpg/.jpeg/.png/.gif/.webp go as photos (Telegram compresses + shows inline);
|
|
592
569
|
// everything else goes as documents (raw file, no compression).
|
|
593
570
|
const PHOTO_EXTS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp'])
|
|
@@ -678,7 +655,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
678
655
|
format: {
|
|
679
656
|
type: 'string',
|
|
680
657
|
enum: ['text', 'html'],
|
|
681
|
-
description: "Rendering mode. 'html'
|
|
658
|
+
description: "Rendering mode. 'html' accepts pre-rendered Telegram HTML. Raw Markdown is detected and converted automatically. Default: auto-detect Markdown or send plain text.",
|
|
682
659
|
},
|
|
683
660
|
},
|
|
684
661
|
required: ['chat_id', 'text'],
|
|
@@ -720,7 +697,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
720
697
|
format: {
|
|
721
698
|
type: 'string',
|
|
722
699
|
enum: ['text', 'html'],
|
|
723
|
-
description: "Rendering mode. 'html'
|
|
700
|
+
description: "Rendering mode. 'html' accepts pre-rendered Telegram HTML. Raw Markdown is detected and converted automatically. Default: auto-detect Markdown or send plain text.",
|
|
724
701
|
},
|
|
725
702
|
},
|
|
726
703
|
required: ['chat_id', 'message_id', 'text'],
|
|
@@ -735,14 +712,11 @@ mcp.setRequestHandler(CallToolRequestSchema, async req => {
|
|
|
735
712
|
switch (req.params.name) {
|
|
736
713
|
case 'reply': {
|
|
737
714
|
const chat_id = args.chat_id as string
|
|
738
|
-
const text = args.text as string
|
|
715
|
+
const text = normalizeTelegramLineBreaks(args.text as string)
|
|
739
716
|
const reply_to = args.reply_to != null ? Number(args.reply_to) : undefined
|
|
740
717
|
const files = (args.files as string[] | undefined) ?? []
|
|
741
718
|
const explicitFormat = args.format as string | undefined
|
|
742
|
-
|
|
743
|
-
const useHtml = explicitFormat === 'html' || (!explicitFormat && hasMarkdown(text))
|
|
744
|
-
const sendText = useHtml && !explicitFormat ? toTelegramHtml(text) : text
|
|
745
|
-
const parseMode = useHtml ? 'HTML' as const : undefined
|
|
719
|
+
const { sendText, parseMode } = resolveTelegramReplyFormat(text, explicitFormat)
|
|
746
720
|
|
|
747
721
|
assertAllowedChat(chat_id)
|
|
748
722
|
|
|
@@ -756,9 +730,8 @@ mcp.setRequestHandler(CallToolRequestSchema, async req => {
|
|
|
756
730
|
|
|
757
731
|
const access = loadAccess()
|
|
758
732
|
const limit = Math.max(1, Math.min(access.textChunkLimit ?? MAX_CHUNK_LIMIT, MAX_CHUNK_LIMIT))
|
|
759
|
-
const mode = access.chunkMode ?? 'length'
|
|
760
733
|
const replyMode = access.replyToMode ?? 'first'
|
|
761
|
-
const chunks =
|
|
734
|
+
const chunks = chunkText(sendText, limit, parseMode === 'HTML')
|
|
762
735
|
const sentIds: number[] = []
|
|
763
736
|
|
|
764
737
|
try {
|
|
@@ -767,11 +740,22 @@ mcp.setRequestHandler(CallToolRequestSchema, async req => {
|
|
|
767
740
|
reply_to != null &&
|
|
768
741
|
replyMode !== 'off' &&
|
|
769
742
|
(replyMode === 'all' || i === 0)
|
|
770
|
-
const
|
|
743
|
+
const opts = {
|
|
771
744
|
...(shouldReplyTo ? { reply_parameters: { message_id: reply_to } } : {}),
|
|
772
745
|
...(parseMode ? { parse_mode: parseMode } : {}),
|
|
773
|
-
}
|
|
774
|
-
|
|
746
|
+
}
|
|
747
|
+
try {
|
|
748
|
+
const sent = await bot.api.sendMessage(chat_id, chunks[i], opts)
|
|
749
|
+
sentIds.push(sent.message_id)
|
|
750
|
+
} catch (err) {
|
|
751
|
+
if (!parseMode) throw err
|
|
752
|
+
const sent = await bot.api.sendMessage(
|
|
753
|
+
chat_id,
|
|
754
|
+
htmlToPlain(chunks[i]),
|
|
755
|
+
shouldReplyTo ? { reply_parameters: { message_id: reply_to } } : undefined,
|
|
756
|
+
)
|
|
757
|
+
sentIds.push(sent.message_id)
|
|
758
|
+
}
|
|
775
759
|
}
|
|
776
760
|
} catch (err) {
|
|
777
761
|
const msg = err instanceof Error ? err.message : String(err)
|
|
@@ -66,6 +66,7 @@ export function openTagStack(html: string): string[] {
|
|
|
66
66
|
/** Strip Telegram-HTML tags and unescape entities → plain-text equivalent. */
|
|
67
67
|
export function htmlToPlain(html: string): string {
|
|
68
68
|
return html
|
|
69
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
69
70
|
.replace(/<[^>]+>/g, '')
|
|
70
71
|
.replace(/</g, '<')
|
|
71
72
|
.replace(/>/g, '>')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmaxma/claude-gateway",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.6",
|
|
4
4
|
"description": "Multi-agent gateway for Claude",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"start": "node --no-warnings=ExperimentalWarning --env-file-if-exists=.env dist/index.js",
|
|
32
32
|
"postinstall": "if command -v bun >/dev/null 2>&1; then bun install --cwd mcp; else echo 'Warning: bun not found. Run `cd mcp && bun install` manually to enable MCP tools.'; fi",
|
|
33
33
|
"pretest": "npm run build",
|
|
34
|
-
"test": "jest",
|
|
34
|
+
"test": "NODE_OPTIONS=--max-old-space-size=2560 jest",
|
|
35
35
|
"pretest:unit": "npm run build",
|
|
36
36
|
"test:unit": "jest --testPathPattern=unit",
|
|
37
37
|
"test:e2e": "jest --testPathPattern=tests/e2e --forceExit",
|