@geminixiang/mama 0.1.1 → 0.1.3

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +72 -18
  3. package/dist/adapter.d.ts +50 -0
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/discord/bot.d.ts +47 -0
  7. package/dist/adapters/discord/bot.d.ts.map +1 -0
  8. package/dist/adapters/discord/bot.js +291 -0
  9. package/dist/adapters/discord/bot.js.map +1 -0
  10. package/dist/adapters/discord/context.d.ts +9 -0
  11. package/dist/adapters/discord/context.d.ts.map +1 -0
  12. package/dist/adapters/discord/context.js +148 -0
  13. package/dist/adapters/discord/context.js.map +1 -0
  14. package/dist/adapters/discord/index.d.ts +3 -0
  15. package/dist/adapters/discord/index.d.ts.map +1 -0
  16. package/dist/adapters/discord/index.js +3 -0
  17. package/dist/adapters/discord/index.js.map +1 -0
  18. package/dist/adapters/slack/bot.d.ts +7 -21
  19. package/dist/adapters/slack/bot.d.ts.map +1 -1
  20. package/dist/adapters/slack/bot.js +47 -19
  21. package/dist/adapters/slack/bot.js.map +1 -1
  22. package/dist/adapters/slack/context.d.ts +1 -3
  23. package/dist/adapters/slack/context.d.ts.map +1 -1
  24. package/dist/adapters/slack/context.js +7 -3
  25. package/dist/adapters/slack/context.js.map +1 -1
  26. package/dist/adapters/slack/tools/attach.d.ts.map +1 -1
  27. package/dist/adapters/slack/tools/attach.js.map +1 -1
  28. package/dist/adapters/telegram/bot.d.ts +35 -0
  29. package/dist/adapters/telegram/bot.d.ts.map +1 -0
  30. package/dist/adapters/telegram/bot.js +233 -0
  31. package/dist/adapters/telegram/bot.js.map +1 -0
  32. package/dist/adapters/telegram/context.d.ts +9 -0
  33. package/dist/adapters/telegram/context.d.ts.map +1 -0
  34. package/dist/adapters/telegram/context.js +144 -0
  35. package/dist/adapters/telegram/context.js.map +1 -0
  36. package/dist/adapters/telegram/index.d.ts +3 -0
  37. package/dist/adapters/telegram/index.d.ts.map +1 -0
  38. package/dist/adapters/telegram/index.js +3 -0
  39. package/dist/adapters/telegram/index.js.map +1 -0
  40. package/dist/agent.d.ts.map +1 -1
  41. package/dist/agent.js +10 -3
  42. package/dist/agent.js.map +1 -1
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js.map +1 -1
  45. package/dist/context.d.ts.map +1 -1
  46. package/dist/context.js +1 -1
  47. package/dist/context.js.map +1 -1
  48. package/dist/download.d.ts.map +1 -1
  49. package/dist/download.js.map +1 -1
  50. package/dist/events.d.ts +4 -4
  51. package/dist/events.d.ts.map +1 -1
  52. package/dist/events.js +12 -15
  53. package/dist/events.js.map +1 -1
  54. package/dist/log.d.ts.map +1 -1
  55. package/dist/log.js.map +1 -1
  56. package/dist/main.d.ts.map +1 -1
  57. package/dist/main.js +55 -36
  58. package/dist/main.js.map +1 -1
  59. package/dist/sandbox.d.ts.map +1 -1
  60. package/dist/sandbox.js +6 -2
  61. package/dist/sandbox.js.map +1 -1
  62. package/dist/store.d.ts.map +1 -1
  63. package/dist/store.js +5 -7
  64. package/dist/store.js.map +1 -1
  65. package/dist/tools/bash.d.ts.map +1 -1
  66. package/dist/tools/bash.js +4 -2
  67. package/dist/tools/bash.js.map +1 -1
  68. package/dist/tools/edit.d.ts.map +1 -1
  69. package/dist/tools/edit.js +3 -1
  70. package/dist/tools/edit.js.map +1 -1
  71. package/dist/tools/index.d.ts.map +1 -1
  72. package/dist/tools/index.js.map +1 -1
  73. package/dist/tools/read.d.ts.map +1 -1
  74. package/dist/tools/read.js +4 -2
  75. package/dist/tools/read.js.map +1 -1
  76. package/dist/tools/truncate.d.ts.map +1 -1
  77. package/dist/tools/truncate.js.map +1 -1
  78. package/dist/tools/write.d.ts.map +1 -1
  79. package/dist/tools/write.js.map +1 -1
  80. package/package.json +65 -55
@@ -0,0 +1,233 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from "fs";
2
+ import { basename, join } from "path";
3
+ import { Bot as GrammyBot, InputFile } from "grammy";
4
+ import * as log from "../../log.js";
5
+ import { createTelegramAdapters } from "./context.js";
6
+ class ChannelQueue {
7
+ constructor() {
8
+ this.queue = [];
9
+ this.processing = false;
10
+ }
11
+ enqueue(work) {
12
+ this.queue.push(work);
13
+ this.processNext();
14
+ }
15
+ size() {
16
+ return this.queue.length;
17
+ }
18
+ async processNext() {
19
+ if (this.processing || this.queue.length === 0)
20
+ return;
21
+ this.processing = true;
22
+ const work = this.queue.shift();
23
+ try {
24
+ await work();
25
+ }
26
+ catch (err) {
27
+ log.logWarning("Telegram queue error", err instanceof Error ? err.message : String(err));
28
+ }
29
+ this.processing = false;
30
+ this.processNext();
31
+ }
32
+ }
33
+ // ============================================================================
34
+ // TelegramBot
35
+ // ============================================================================
36
+ export class TelegramBot {
37
+ constructor(handler, config) {
38
+ this.botUserId = null;
39
+ this.botUsername = null;
40
+ this.queues = new Map();
41
+ this.startupTime = 0;
42
+ this.handler = handler;
43
+ this.workingDir = config.workingDir;
44
+ this.client = new GrammyBot(config.token);
45
+ this.client.catch((err) => {
46
+ log.logWarning("Telegram error", err instanceof Error ? err.message : String(err));
47
+ });
48
+ }
49
+ // ==========================================================================
50
+ // Public API (implements Bot)
51
+ // ==========================================================================
52
+ async start() {
53
+ const me = await this.client.api.getMe();
54
+ this.botUserId = String(me.id);
55
+ this.botUsername = me.username ?? null;
56
+ this.startupTime = Date.now();
57
+ this.setupEventHandlers();
58
+ // Start polling in background (bot.start() runs indefinitely)
59
+ this.client.start().catch((err) => {
60
+ log.logWarning("Telegram polling error", err instanceof Error ? err.message : String(err));
61
+ });
62
+ log.logConnected();
63
+ log.logInfo(`Telegram bot started as @${this.botUsername ?? this.botUserId}`);
64
+ }
65
+ async postMessage(channel, text) {
66
+ const result = await this.postMessageRaw(parseInt(channel), text);
67
+ return String(result);
68
+ }
69
+ async updateMessage(channel, ts, text) {
70
+ try {
71
+ await this.client.api.editMessageText(parseInt(channel), parseInt(ts), text, {
72
+ parse_mode: "HTML",
73
+ });
74
+ }
75
+ catch (err) {
76
+ const msg = err instanceof Error ? err.message : String(err);
77
+ if (!msg.includes("message is not modified")) {
78
+ throw err;
79
+ }
80
+ }
81
+ }
82
+ enqueueEvent(event) {
83
+ const queue = this.getQueue(event.channel);
84
+ if (queue.size() >= 5) {
85
+ log.logWarning(`Event queue full for ${event.channel}, discarding: ${event.text.substring(0, 50)}`);
86
+ return false;
87
+ }
88
+ log.logInfo(`Enqueueing event for ${event.channel}: ${event.text.substring(0, 50)}`);
89
+ queue.enqueue(() => {
90
+ const adapters = createTelegramAdapters(event, this, true);
91
+ return this.handler.handleEvent(event, this, adapters, true);
92
+ });
93
+ return true;
94
+ }
95
+ getPlatformInfo() {
96
+ return {
97
+ name: "telegram",
98
+ formattingGuide: '## Telegram Formatting (HTML mode)\nBold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>\nLinks: <a href="url">text</a>',
99
+ channels: [],
100
+ users: [],
101
+ };
102
+ }
103
+ // ==========================================================================
104
+ // Internal helpers (used by context.ts)
105
+ // ==========================================================================
106
+ async postMessageRaw(chatId, text) {
107
+ const result = await this.client.api.sendMessage(chatId, text, { parse_mode: "HTML" });
108
+ return result.message_id;
109
+ }
110
+ async postReply(chatId, replyToMessageId, text) {
111
+ const result = await this.client.api.sendMessage(chatId, text, {
112
+ parse_mode: "HTML",
113
+ reply_parameters: { message_id: replyToMessageId },
114
+ });
115
+ return result.message_id;
116
+ }
117
+ async deleteMessageRaw(chatId, messageId) {
118
+ await this.client.api.deleteMessage(chatId, messageId);
119
+ }
120
+ async sendTyping(chatId) {
121
+ await this.client.api.sendChatAction(chatId, "typing");
122
+ }
123
+ async uploadFile(channel, filePath, title) {
124
+ const fileName = title ?? basename(filePath);
125
+ const fileContent = readFileSync(filePath);
126
+ await this.client.api.sendDocument(parseInt(channel), new InputFile(fileContent, fileName));
127
+ }
128
+ logToFile(channel, entry) {
129
+ const dir = join(this.workingDir, channel);
130
+ if (!existsSync(dir))
131
+ mkdirSync(dir, { recursive: true });
132
+ appendFileSync(join(dir, "log.jsonl"), `${JSON.stringify(entry)}\n`);
133
+ }
134
+ logBotResponse(channel, text, ts) {
135
+ this.logToFile(channel, {
136
+ date: new Date().toISOString(),
137
+ ts,
138
+ user: "bot",
139
+ text,
140
+ attachments: [],
141
+ isBot: true,
142
+ });
143
+ }
144
+ // ==========================================================================
145
+ // Private - Event Handlers
146
+ // ==========================================================================
147
+ getQueue(channelId) {
148
+ let queue = this.queues.get(channelId);
149
+ if (!queue) {
150
+ queue = new ChannelQueue();
151
+ this.queues.set(channelId, queue);
152
+ }
153
+ return queue;
154
+ }
155
+ isAddressedToBot(text, chatType) {
156
+ if (chatType === "private")
157
+ return true;
158
+ if (!this.botUsername)
159
+ return false;
160
+ return text.includes(`@${this.botUsername}`);
161
+ }
162
+ cleanText(text) {
163
+ if (!this.botUsername)
164
+ return text.trim();
165
+ return text.replace(new RegExp(`@${this.botUsername}`, "g"), "").trim();
166
+ }
167
+ setupEventHandlers() {
168
+ this.client.on("message", (ctx) => {
169
+ const msg = ctx.message;
170
+ // Skip messages from before startup (Telegram replays recent messages on poll start)
171
+ if (msg.date * 1000 < this.startupTime)
172
+ return;
173
+ // Skip bot messages
174
+ if (msg.from?.is_bot)
175
+ return;
176
+ const text = msg.text ?? msg.caption ?? "";
177
+ if (!text && !msg.document && !msg.photo)
178
+ return;
179
+ const chatId = String(msg.chat.id);
180
+ const chatType = msg.chat.type;
181
+ const userId = String(msg.from?.id ?? "unknown");
182
+ const userName = msg.from?.username ?? msg.from?.first_name ?? userId;
183
+ const msgId = String(msg.message_id);
184
+ // Determine thread: if this is a reply, use parent message_id as thread_ts
185
+ const replyToId = msg.reply_to_message?.message_id;
186
+ const threadTs = replyToId ? String(replyToId) : undefined;
187
+ // Check if addressed to bot
188
+ if (!this.isAddressedToBot(text, chatType))
189
+ return;
190
+ const cleanedText = this.cleanText(text);
191
+ const sessionKey = `${chatId}:${threadTs ?? msgId}`;
192
+ const event = {
193
+ type: "message",
194
+ channel: chatId,
195
+ ts: msgId,
196
+ thread_ts: threadTs,
197
+ user: userId,
198
+ userName,
199
+ text: cleanedText,
200
+ };
201
+ // Log the message
202
+ this.logToFile(chatId, {
203
+ date: new Date(msg.date * 1000).toISOString(),
204
+ ts: msgId,
205
+ user: userId,
206
+ userName,
207
+ text: cleanedText,
208
+ attachments: [],
209
+ isBot: false,
210
+ });
211
+ // Handle /stop command
212
+ if (cleanedText.toLowerCase() === "/stop" || cleanedText.toLowerCase() === "stop") {
213
+ if (this.handler.isRunning(sessionKey)) {
214
+ this.handler.handleStop(sessionKey, chatId, this);
215
+ }
216
+ else {
217
+ this.postMessage(chatId, "Nothing running.");
218
+ }
219
+ return;
220
+ }
221
+ if (this.handler.isRunning(sessionKey)) {
222
+ this.postMessage(chatId, "Already working. Say <code>stop</code> to cancel.");
223
+ }
224
+ else {
225
+ this.getQueue(sessionKey).enqueue(() => {
226
+ const adapters = createTelegramAdapters(event, this, false);
227
+ return this.handler.handleEvent(event, this, adapters, false);
228
+ });
229
+ }
230
+ });
231
+ }
232
+ }
233
+ //# sourceMappingURL=bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/telegram/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,GAAG,IAAI,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAErD,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAiBtD,MAAM,YAAY;IAAlB;QACU,UAAK,GAAiB,EAAE,CAAC;QACzB,eAAU,GAAG,KAAK,CAAC;IAuB7B,CAAC;IArBC,OAAO,CAAC,IAAgB;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CAAC,sBAAsB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;CACF;AAED,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,MAAM,OAAO,WAAW;IAStB,YAAY,OAAmB,EAAE,MAA6C;QALtE,cAAS,GAAkB,IAAI,CAAC;QAChC,gBAAW,GAAkB,IAAI,CAAC;QAClC,WAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;QACzC,gBAAW,GAAW,CAAC,CAAC;QAG9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,UAAU,CAAC,gBAAgB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAC7E,8BAA8B;IAC9B,6EAA6E;IAE7E,KAAK,CAAC,KAAK;QACT,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,QAAQ,IAAI,IAAI,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE9B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAE1B,8DAA8D;QAC9D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAChC,GAAG,CAAC,UAAU,CAAC,wBAAwB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,YAAY,EAAE,CAAC;QACnB,GAAG,CAAC,OAAO,CAAC,4BAA4B,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAAY;QAC7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;QAClE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,EAAU,EAAE,IAAY;QAC3D,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE;gBAC3E,UAAU,EAAE,MAAM;aACnB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,CAAC;gBAC7C,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY,CAAC,KAAe;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,UAAU,CACZ,wBAAwB,KAAK,CAAC,OAAO,iBAAiB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CACpF,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,wBAAwB,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACrF,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAsB,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe;QACb,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,eAAe,EACb,0JAA0J;YAC5J,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;SACV,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,wCAAwC;IACxC,6EAA6E;IAE7E,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,IAAY;QAC/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,gBAAwB,EAAE,IAAY;QACpE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE;YAC7D,UAAU,EAAE,MAAM;YAClB,gBAAgB,EAAE,EAAE,UAAU,EAAE,gBAAgB,EAAE;SACnD,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,SAAiB;QACtD,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,QAAgB,EAAE,KAAc;QAChE,MAAM,QAAQ,GAAG,KAAK,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,SAAS,CAAC,OAAe,EAAE,KAAa;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvE,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,IAAY,EAAE,EAAU;QACtD,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;YACtB,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC9B,EAAE;YACF,IAAI,EAAE,KAAK;YACX,IAAI;YACJ,WAAW,EAAE,EAAE;YACf,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAC7E,2BAA2B;IAC3B,6EAA6E;IAErE,QAAQ,CAAC,SAAiB;QAChC,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,YAAY,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,gBAAgB,CAAC,IAAY,EAAE,QAAgB;QACrD,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QACpC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/C,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1E,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;YAChC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;YAExB,qFAAqF;YACrF,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,WAAW;gBAAE,OAAO;YAC/C,oBAAoB;YACpB,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM;gBAAE,OAAO;YAE7B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,KAAK;gBAAE,OAAO;YAEjD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,SAAS,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,UAAU,IAAI,MAAM,CAAC;YACtE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAErC,2EAA2E;YAC3E,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC;YACnD,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAE3D,4BAA4B;YAC5B,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAAE,OAAO;YAEnD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACzC,MAAM,UAAU,GAAG,GAAG,MAAM,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAEpD,MAAM,KAAK,GAAkB;gBAC3B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,MAAM;gBACf,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,QAAQ;gBACnB,IAAI,EAAE,MAAM;gBACZ,QAAQ;gBACR,IAAI,EAAE,WAAW;aAClB,CAAC;YAEF,kBAAkB;YAClB,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE;gBACrB,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;gBAC7C,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,MAAM;gBACZ,QAAQ;gBACR,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,EAAE;gBACf,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YAEH,uBAAuB;YACvB,IAAI,WAAW,CAAC,WAAW,EAAE,KAAK,OAAO,IAAI,WAAW,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;gBAClF,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;oBACvC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;gBACpD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;gBAC/C,CAAC;gBACD,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,mDAAmD,CAAC,CAAC;YAChF,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;oBACrC,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;oBAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAChE,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { appendFileSync, existsSync, mkdirSync, readFileSync } from \"fs\";\nimport { basename, join } from \"path\";\nimport { Bot as GrammyBot, InputFile } from \"grammy\";\nimport type { Bot, BotEvent, BotHandler, PlatformInfo } from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { createTelegramAdapters } from \"./context.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TelegramEvent extends BotEvent {\n type: \"message\" | \"command\";\n userName?: string;\n}\n\n// ============================================================================\n// Per-channel queue for sequential processing\n// ============================================================================\n\ntype QueuedWork = () => Promise<void>;\n\nclass ChannelQueue {\n private queue: QueuedWork[] = [];\n private processing = false;\n\n enqueue(work: QueuedWork): void {\n this.queue.push(work);\n this.processNext();\n }\n\n size(): number {\n return this.queue.length;\n }\n\n private async processNext(): Promise<void> {\n if (this.processing || this.queue.length === 0) return;\n this.processing = true;\n const work = this.queue.shift()!;\n try {\n await work();\n } catch (err) {\n log.logWarning(\"Telegram queue error\", err instanceof Error ? err.message : String(err));\n }\n this.processing = false;\n this.processNext();\n }\n}\n\n// ============================================================================\n// TelegramBot\n// ============================================================================\n\nexport class TelegramBot implements Bot {\n private client: GrammyBot;\n private handler: BotHandler;\n private workingDir: string;\n private botUserId: string | null = null;\n private botUsername: string | null = null;\n private queues = new Map<string, ChannelQueue>();\n private startupTime: number = 0;\n\n constructor(handler: BotHandler, config: { token: string; workingDir: string }) {\n this.handler = handler;\n this.workingDir = config.workingDir;\n this.client = new GrammyBot(config.token);\n this.client.catch((err) => {\n log.logWarning(\"Telegram error\", err instanceof Error ? err.message : String(err));\n });\n }\n\n // ==========================================================================\n // Public API (implements Bot)\n // ==========================================================================\n\n async start(): Promise<void> {\n const me = await this.client.api.getMe();\n this.botUserId = String(me.id);\n this.botUsername = me.username ?? null;\n this.startupTime = Date.now();\n\n this.setupEventHandlers();\n\n // Start polling in background (bot.start() runs indefinitely)\n this.client.start().catch((err) => {\n log.logWarning(\"Telegram polling error\", err instanceof Error ? err.message : String(err));\n });\n\n log.logConnected();\n log.logInfo(`Telegram bot started as @${this.botUsername ?? this.botUserId}`);\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n const result = await this.postMessageRaw(parseInt(channel), text);\n return String(result);\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n try {\n await this.client.api.editMessageText(parseInt(channel), parseInt(ts), text, {\n parse_mode: \"HTML\",\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes(\"message is not modified\")) {\n throw err;\n }\n }\n }\n\n enqueueEvent(event: BotEvent): boolean {\n const queue = this.getQueue(event.channel);\n if (queue.size() >= 5) {\n log.logWarning(\n `Event queue full for ${event.channel}, discarding: ${event.text.substring(0, 50)}`,\n );\n return false;\n }\n log.logInfo(`Enqueueing event for ${event.channel}: ${event.text.substring(0, 50)}`);\n queue.enqueue(() => {\n const adapters = createTelegramAdapters(event as TelegramEvent, this, true);\n return this.handler.handleEvent(event, this, adapters, true);\n });\n return true;\n }\n\n getPlatformInfo(): PlatformInfo {\n return {\n name: \"telegram\",\n formattingGuide:\n '## Telegram Formatting (HTML mode)\\nBold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>\\nLinks: <a href=\"url\">text</a>',\n channels: [],\n users: [],\n };\n }\n\n // ==========================================================================\n // Internal helpers (used by context.ts)\n // ==========================================================================\n\n async postMessageRaw(chatId: number, text: string): Promise<number> {\n const result = await this.client.api.sendMessage(chatId, text, { parse_mode: \"HTML\" });\n return result.message_id;\n }\n\n async postReply(chatId: number, replyToMessageId: number, text: string): Promise<number> {\n const result = await this.client.api.sendMessage(chatId, text, {\n parse_mode: \"HTML\",\n reply_parameters: { message_id: replyToMessageId },\n });\n return result.message_id;\n }\n\n async deleteMessageRaw(chatId: number, messageId: number): Promise<void> {\n await this.client.api.deleteMessage(chatId, messageId);\n }\n\n async sendTyping(chatId: number): Promise<void> {\n await this.client.api.sendChatAction(chatId, \"typing\");\n }\n\n async uploadFile(channel: string, filePath: string, title?: string): Promise<void> {\n const fileName = title ?? basename(filePath);\n const fileContent = readFileSync(filePath);\n await this.client.api.sendDocument(parseInt(channel), new InputFile(fileContent, fileName));\n }\n\n logToFile(channel: string, entry: object): void {\n const dir = join(this.workingDir, channel);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n appendFileSync(join(dir, \"log.jsonl\"), `${JSON.stringify(entry)}\\n`);\n }\n\n logBotResponse(channel: string, text: string, ts: string): void {\n this.logToFile(channel, {\n date: new Date().toISOString(),\n ts,\n user: \"bot\",\n text,\n attachments: [],\n isBot: true,\n });\n }\n\n // ==========================================================================\n // Private - Event Handlers\n // ==========================================================================\n\n private getQueue(channelId: string): ChannelQueue {\n let queue = this.queues.get(channelId);\n if (!queue) {\n queue = new ChannelQueue();\n this.queues.set(channelId, queue);\n }\n return queue;\n }\n\n private isAddressedToBot(text: string, chatType: string): boolean {\n if (chatType === \"private\") return true;\n if (!this.botUsername) return false;\n return text.includes(`@${this.botUsername}`);\n }\n\n private cleanText(text: string): string {\n if (!this.botUsername) return text.trim();\n return text.replace(new RegExp(`@${this.botUsername}`, \"g\"), \"\").trim();\n }\n\n private setupEventHandlers(): void {\n this.client.on(\"message\", (ctx) => {\n const msg = ctx.message;\n\n // Skip messages from before startup (Telegram replays recent messages on poll start)\n if (msg.date * 1000 < this.startupTime) return;\n // Skip bot messages\n if (msg.from?.is_bot) return;\n\n const text = msg.text ?? msg.caption ?? \"\";\n if (!text && !msg.document && !msg.photo) return;\n\n const chatId = String(msg.chat.id);\n const chatType = msg.chat.type;\n const userId = String(msg.from?.id ?? \"unknown\");\n const userName = msg.from?.username ?? msg.from?.first_name ?? userId;\n const msgId = String(msg.message_id);\n\n // Determine thread: if this is a reply, use parent message_id as thread_ts\n const replyToId = msg.reply_to_message?.message_id;\n const threadTs = replyToId ? String(replyToId) : undefined;\n\n // Check if addressed to bot\n if (!this.isAddressedToBot(text, chatType)) return;\n\n const cleanedText = this.cleanText(text);\n const sessionKey = `${chatId}:${threadTs ?? msgId}`;\n\n const event: TelegramEvent = {\n type: \"message\",\n channel: chatId,\n ts: msgId,\n thread_ts: threadTs,\n user: userId,\n userName,\n text: cleanedText,\n };\n\n // Log the message\n this.logToFile(chatId, {\n date: new Date(msg.date * 1000).toISOString(),\n ts: msgId,\n user: userId,\n userName,\n text: cleanedText,\n attachments: [],\n isBot: false,\n });\n\n // Handle /stop command\n if (cleanedText.toLowerCase() === \"/stop\" || cleanedText.toLowerCase() === \"stop\") {\n if (this.handler.isRunning(sessionKey)) {\n this.handler.handleStop(sessionKey, chatId, this);\n } else {\n this.postMessage(chatId, \"Nothing running.\");\n }\n return;\n }\n\n if (this.handler.isRunning(sessionKey)) {\n this.postMessage(chatId, \"Already working. Say <code>stop</code> to cancel.\");\n } else {\n this.getQueue(sessionKey).enqueue(() => {\n const adapters = createTelegramAdapters(event, this, false);\n return this.handler.handleEvent(event, this, adapters, false);\n });\n }\n });\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import type { ChatMessage, ChatResponseContext, PlatformInfo } from "../../adapter.js";
2
+ import type { TelegramBot, TelegramEvent } from "./bot.js";
3
+ export declare const TELEGRAM_FORMATTING_GUIDE = "## Telegram Formatting (HTML mode)\nBold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>\nLinks: <a href=\"url\">text</a>\nDo NOT use Markdown asterisks or backtick syntax.";
4
+ export declare function createTelegramAdapters(event: TelegramEvent, bot: TelegramBot, isEvent?: boolean): {
5
+ message: ChatMessage;
6
+ responseCtx: ChatResponseContext;
7
+ platform: PlatformInfo;
8
+ };
9
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvF,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE3D,eAAO,MAAM,yBAAyB,kNAGY,CAAC;AAEnD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB;IACD,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,mBAAmB,CAAC;IACjC,QAAQ,EAAE,YAAY,CAAC;CACxB,CA+JA","sourcesContent":["import type { ChatMessage, ChatResponseContext, PlatformInfo } from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport type { TelegramBot, TelegramEvent } from \"./bot.js\";\n\nexport const TELEGRAM_FORMATTING_GUIDE = `## Telegram Formatting (HTML mode)\nBold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>\nLinks: <a href=\"url\">text</a>\nDo NOT use Markdown asterisks or backtick syntax.`;\n\nexport function createTelegramAdapters(\n event: TelegramEvent,\n bot: TelegramBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageId: number | null = null;\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n const replyToId = event.thread_ts ? parseInt(event.thread_ts) : null;\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: `${event.channel}:${event.thread_ts ?? event.ts}`,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n };\n\n const platform: PlatformInfo = {\n name: \"telegram\",\n formattingGuide: TELEGRAM_FORMATTING_GUIDE,\n channels: [],\n users: [],\n };\n\n // Telegram message length limit is 4096 chars; use 3800 for safety\n const MAX_LENGTH = 3800;\n const truncationNote = \"\\n\\n<i>(message truncated, ask me to elaborate on specific parts)</i>\";\n\n function truncate(text: string, limit: number, note: string): string {\n if (text.length > limit) {\n return text.substring(0, limit - note.length) + note;\n }\n return text;\n }\n\n const responseCtx: ChatResponseContext = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n const displayText = truncate(\n isWorking ? accumulatedText + workingIndicator : accumulatedText,\n MAX_LENGTH,\n truncationNote,\n );\n\n if (messageId !== null) {\n await bot.updateMessage(event.channel, String(messageId), displayText);\n } else if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n\n if (messageId !== null) {\n bot.logBotResponse(event.channel, text, String(messageId));\n }\n } catch (err) {\n log.logWarning(\n \"Telegram respond error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = truncate(text, MAX_LENGTH, truncationNote);\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageId !== null) {\n await bot.updateMessage(event.channel, String(messageId), displayText);\n } else if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n } catch (err) {\n log.logWarning(\n \"Telegram replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n // Telegram has no threads — discard thread-only messages (e.g. usage summary)\n respondInThread: async (_text: string) => {},\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && messageId === null) {\n updatePromise = updatePromise.then(async () => {\n try {\n if (messageId === null) {\n await bot.sendTyping(parseInt(event.channel));\n const initialText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n accumulatedText = initialText;\n const displayText = accumulatedText + workingIndicator;\n if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n }\n } catch (err) {\n log.logWarning(\n \"Telegram setTyping error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n }\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageId !== null) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n await bot.updateMessage(event.channel, String(messageId), displayText);\n }\n } catch (err) {\n log.logWarning(\n \"Telegram setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await bot.uploadFile(event.channel, filePath, title);\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n if (messageId !== null) {\n try {\n await bot.deleteMessageRaw(parseInt(event.channel), messageId);\n } catch {\n // Ignore errors\n }\n messageId = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
@@ -0,0 +1,144 @@
1
+ import * as log from "../../log.js";
2
+ export const TELEGRAM_FORMATTING_GUIDE = `## Telegram Formatting (HTML mode)
3
+ Bold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>
4
+ Links: <a href="url">text</a>
5
+ Do NOT use Markdown asterisks or backtick syntax.`;
6
+ export function createTelegramAdapters(event, bot, isEvent) {
7
+ let messageId = null;
8
+ let accumulatedText = "";
9
+ let isWorking = true;
10
+ const workingIndicator = " ...";
11
+ let updatePromise = Promise.resolve();
12
+ const eventFilename = isEvent ? event.text.match(/^\[EVENT:([^:]+):/)?.[1] : undefined;
13
+ const replyToId = event.thread_ts ? parseInt(event.thread_ts) : null;
14
+ const message = {
15
+ id: event.ts,
16
+ sessionKey: `${event.channel}:${event.thread_ts ?? event.ts}`,
17
+ userId: event.user,
18
+ userName: event.userName,
19
+ text: event.text,
20
+ attachments: event.attachments,
21
+ };
22
+ const platform = {
23
+ name: "telegram",
24
+ formattingGuide: TELEGRAM_FORMATTING_GUIDE,
25
+ channels: [],
26
+ users: [],
27
+ };
28
+ // Telegram message length limit is 4096 chars; use 3800 for safety
29
+ const MAX_LENGTH = 3800;
30
+ const truncationNote = "\n\n<i>(message truncated, ask me to elaborate on specific parts)</i>";
31
+ function truncate(text, limit, note) {
32
+ if (text.length > limit) {
33
+ return text.substring(0, limit - note.length) + note;
34
+ }
35
+ return text;
36
+ }
37
+ const responseCtx = {
38
+ respond: async (text) => {
39
+ updatePromise = updatePromise.then(async () => {
40
+ try {
41
+ accumulatedText = accumulatedText ? `${accumulatedText}\n${text}` : text;
42
+ const displayText = truncate(isWorking ? accumulatedText + workingIndicator : accumulatedText, MAX_LENGTH, truncationNote);
43
+ if (messageId !== null) {
44
+ await bot.updateMessage(event.channel, String(messageId), displayText);
45
+ }
46
+ else if (replyToId !== null) {
47
+ messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);
48
+ }
49
+ else {
50
+ messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);
51
+ }
52
+ if (messageId !== null) {
53
+ bot.logBotResponse(event.channel, text, String(messageId));
54
+ }
55
+ }
56
+ catch (err) {
57
+ log.logWarning("Telegram respond error", err instanceof Error ? err.message : String(err));
58
+ }
59
+ });
60
+ await updatePromise;
61
+ },
62
+ replaceResponse: async (text) => {
63
+ updatePromise = updatePromise.then(async () => {
64
+ try {
65
+ accumulatedText = truncate(text, MAX_LENGTH, truncationNote);
66
+ const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;
67
+ if (messageId !== null) {
68
+ await bot.updateMessage(event.channel, String(messageId), displayText);
69
+ }
70
+ else if (replyToId !== null) {
71
+ messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);
72
+ }
73
+ else {
74
+ messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);
75
+ }
76
+ }
77
+ catch (err) {
78
+ log.logWarning("Telegram replaceResponse error", err instanceof Error ? err.message : String(err));
79
+ }
80
+ });
81
+ await updatePromise;
82
+ },
83
+ // Telegram has no threads — discard thread-only messages (e.g. usage summary)
84
+ respondInThread: async (_text) => { },
85
+ setTyping: async (isTyping) => {
86
+ if (isTyping && messageId === null) {
87
+ updatePromise = updatePromise.then(async () => {
88
+ try {
89
+ if (messageId === null) {
90
+ await bot.sendTyping(parseInt(event.channel));
91
+ const initialText = eventFilename ? `Starting event: ${eventFilename}` : "Thinking";
92
+ accumulatedText = initialText;
93
+ const displayText = accumulatedText + workingIndicator;
94
+ if (replyToId !== null) {
95
+ messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);
96
+ }
97
+ else {
98
+ messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);
99
+ }
100
+ }
101
+ }
102
+ catch (err) {
103
+ log.logWarning("Telegram setTyping error", err instanceof Error ? err.message : String(err));
104
+ }
105
+ });
106
+ await updatePromise;
107
+ }
108
+ },
109
+ setWorking: async (working) => {
110
+ updatePromise = updatePromise.then(async () => {
111
+ try {
112
+ isWorking = working;
113
+ if (messageId !== null) {
114
+ const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;
115
+ await bot.updateMessage(event.channel, String(messageId), displayText);
116
+ }
117
+ }
118
+ catch (err) {
119
+ log.logWarning("Telegram setWorking error", err instanceof Error ? err.message : String(err));
120
+ }
121
+ });
122
+ await updatePromise;
123
+ },
124
+ uploadFile: async (filePath, title) => {
125
+ await bot.uploadFile(event.channel, filePath, title);
126
+ },
127
+ deleteResponse: async () => {
128
+ updatePromise = updatePromise.then(async () => {
129
+ if (messageId !== null) {
130
+ try {
131
+ await bot.deleteMessageRaw(parseInt(event.channel), messageId);
132
+ }
133
+ catch {
134
+ // Ignore errors
135
+ }
136
+ messageId = null;
137
+ }
138
+ });
139
+ await updatePromise;
140
+ },
141
+ };
142
+ return { message, responseCtx, platform };
143
+ }
144
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/telegram/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChatMessage, ChatResponseContext, PlatformInfo } from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport type { TelegramBot, TelegramEvent } from \"./bot.js\";\n\nexport const TELEGRAM_FORMATTING_GUIDE = `## Telegram Formatting (HTML mode)\nBold: <b>text</b>, Italic: <i>text</i>, Code: <code>code</code>, Pre: <pre>code</pre>\nLinks: <a href=\"url\">text</a>\nDo NOT use Markdown asterisks or backtick syntax.`;\n\nexport function createTelegramAdapters(\n event: TelegramEvent,\n bot: TelegramBot,\n isEvent?: boolean,\n): {\n message: ChatMessage;\n responseCtx: ChatResponseContext;\n platform: PlatformInfo;\n} {\n let messageId: number | null = null;\n let accumulatedText = \"\";\n let isWorking = true;\n const workingIndicator = \" ...\";\n let updatePromise = Promise.resolve();\n\n const eventFilename = isEvent ? event.text.match(/^\\[EVENT:([^:]+):/)?.[1] : undefined;\n const replyToId = event.thread_ts ? parseInt(event.thread_ts) : null;\n\n const message: ChatMessage = {\n id: event.ts,\n sessionKey: `${event.channel}:${event.thread_ts ?? event.ts}`,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n };\n\n const platform: PlatformInfo = {\n name: \"telegram\",\n formattingGuide: TELEGRAM_FORMATTING_GUIDE,\n channels: [],\n users: [],\n };\n\n // Telegram message length limit is 4096 chars; use 3800 for safety\n const MAX_LENGTH = 3800;\n const truncationNote = \"\\n\\n<i>(message truncated, ask me to elaborate on specific parts)</i>\";\n\n function truncate(text: string, limit: number, note: string): string {\n if (text.length > limit) {\n return text.substring(0, limit - note.length) + note;\n }\n return text;\n }\n\n const responseCtx: ChatResponseContext = {\n respond: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = accumulatedText ? `${accumulatedText}\\n${text}` : text;\n const displayText = truncate(\n isWorking ? accumulatedText + workingIndicator : accumulatedText,\n MAX_LENGTH,\n truncationNote,\n );\n\n if (messageId !== null) {\n await bot.updateMessage(event.channel, String(messageId), displayText);\n } else if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n\n if (messageId !== null) {\n bot.logBotResponse(event.channel, text, String(messageId));\n }\n } catch (err) {\n log.logWarning(\n \"Telegram respond error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n replaceResponse: async (text: string) => {\n updatePromise = updatePromise.then(async () => {\n try {\n accumulatedText = truncate(text, MAX_LENGTH, truncationNote);\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n\n if (messageId !== null) {\n await bot.updateMessage(event.channel, String(messageId), displayText);\n } else if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n } catch (err) {\n log.logWarning(\n \"Telegram replaceResponse error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n // Telegram has no threads — discard thread-only messages (e.g. usage summary)\n respondInThread: async (_text: string) => {},\n\n setTyping: async (isTyping: boolean) => {\n if (isTyping && messageId === null) {\n updatePromise = updatePromise.then(async () => {\n try {\n if (messageId === null) {\n await bot.sendTyping(parseInt(event.channel));\n const initialText = eventFilename ? `Starting event: ${eventFilename}` : \"Thinking\";\n accumulatedText = initialText;\n const displayText = accumulatedText + workingIndicator;\n if (replyToId !== null) {\n messageId = await bot.postReply(parseInt(event.channel), replyToId, displayText);\n } else {\n messageId = await bot.postMessageRaw(parseInt(event.channel), displayText);\n }\n }\n } catch (err) {\n log.logWarning(\n \"Telegram setTyping error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n }\n },\n\n setWorking: async (working: boolean) => {\n updatePromise = updatePromise.then(async () => {\n try {\n isWorking = working;\n if (messageId !== null) {\n const displayText = isWorking ? accumulatedText + workingIndicator : accumulatedText;\n await bot.updateMessage(event.channel, String(messageId), displayText);\n }\n } catch (err) {\n log.logWarning(\n \"Telegram setWorking error\",\n err instanceof Error ? err.message : String(err),\n );\n }\n });\n await updatePromise;\n },\n\n uploadFile: async (filePath: string, title?: string) => {\n await bot.uploadFile(event.channel, filePath, title);\n },\n\n deleteResponse: async () => {\n updatePromise = updatePromise.then(async () => {\n if (messageId !== null) {\n try {\n await bot.deleteMessageRaw(parseInt(event.channel), messageId);\n } catch {\n // Ignore errors\n }\n messageId = null;\n }\n });\n await updatePromise;\n },\n };\n\n return { message, responseCtx, platform };\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./bot.js";
2
+ export * from "./context.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./bot.js\";\nexport * from \"./context.js\";\n"]}
@@ -0,0 +1,3 @@
1
+ export * from "./bot.js";
2
+ export * from "./context.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/telegram/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./bot.js\";\nexport * from \"./context.js\";\n"]}