@mono-agent/telegram-adapter 0.2.1 → 0.3.0

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 (48) hide show
  1. package/README.md +2 -0
  2. package/dist/adapter.d.ts +35 -57
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +37 -179
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/bot.d.ts +50 -0
  7. package/dist/bot.d.ts.map +1 -0
  8. package/dist/bot.js +214 -0
  9. package/dist/bot.js.map +1 -0
  10. package/dist/config.d.ts +2 -0
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +18 -2
  13. package/dist/config.js.map +1 -1
  14. package/dist/grammy-client.d.ts +14 -0
  15. package/dist/grammy-client.d.ts.map +1 -0
  16. package/dist/grammy-client.js +103 -0
  17. package/dist/grammy-client.js.map +1 -0
  18. package/dist/index.d.ts +11 -10
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +5 -4
  21. package/dist/index.js.map +1 -1
  22. package/dist/message-stream.d.ts +80 -7
  23. package/dist/message-stream.d.ts.map +1 -1
  24. package/dist/message-stream.js +381 -34
  25. package/dist/message-stream.js.map +1 -1
  26. package/dist/start.d.ts +23 -34
  27. package/dist/start.d.ts.map +1 -1
  28. package/dist/start.js +25 -43
  29. package/dist/start.js.map +1 -1
  30. package/dist/telegram-error.d.ts +34 -0
  31. package/dist/telegram-error.d.ts.map +1 -0
  32. package/dist/telegram-error.js +39 -0
  33. package/dist/telegram-error.js.map +1 -0
  34. package/dist/telegram-markdown.d.ts +17 -0
  35. package/dist/telegram-markdown.d.ts.map +1 -0
  36. package/dist/telegram-markdown.js +20 -0
  37. package/dist/telegram-markdown.js.map +1 -0
  38. package/dist/types.d.ts +8 -1
  39. package/dist/types.d.ts.map +1 -1
  40. package/package.json +6 -3
  41. package/dist/long-poller.d.ts +0 -55
  42. package/dist/long-poller.d.ts.map +0 -1
  43. package/dist/long-poller.js +0 -156
  44. package/dist/long-poller.js.map +0 -1
  45. package/dist/telegram-client.d.ts +0 -38
  46. package/dist/telegram-client.d.ts.map +0 -1
  47. package/dist/telegram-client.js +0 -183
  48. package/dist/telegram-client.js.map +0 -1
package/dist/bot.js ADDED
@@ -0,0 +1,214 @@
1
+ import { isAgentResponseCancelledError } from "@mono-agent/agent-contracts";
2
+ import { run } from "@grammyjs/runner";
3
+ import { Bot } from "grammy";
4
+ import { DEFAULT_MESSAGES, buildAgentRequest, finishSafely, resolveErrorText, } from "./adapter.js";
5
+ import { createGrammyTelegramApi } from "./grammy-client.js";
6
+ import { TelegramMessageStream, } from "./message-stream.js";
7
+ const DEFAULT_INITIAL_STATUS_TEXT = "Thinking…";
8
+ /**
9
+ * Build a grammY bot that routes authorized text messages to an agent responder.
10
+ *
11
+ * grammY owns the transport and (via `@grammyjs/runner`) concurrent polling.
12
+ * Middleware order is: authorization gate → `/start` `/help` `/cancel` commands →
13
+ * agent run handler (`message:text`) → unsupported fallback (other messages).
14
+ *
15
+ * Per-chat concurrency is guarded by an `activeRuns` map: a run is recorded
16
+ * synchronously at handler entry, so a second message arriving for the same chat
17
+ * mid-run gets a "busy" reply rather than starting a competing run. The long run
18
+ * is intentionally NOT sequentialized, which is what makes "busy" reachable.
19
+ */
20
+ export function createTelegramBot(options) {
21
+ const allowAllChats = options.allowAllChats === true;
22
+ const allowedChatIds = new Set((options.allowedChatIds ?? []).map((id) => String(id)));
23
+ if (!allowAllChats && allowedChatIds.size === 0) {
24
+ throw new TypeError("createTelegramBot requires allowedChatIds or allowAllChats: true.");
25
+ }
26
+ const messages = { ...DEFAULT_MESSAGES, ...options.messages };
27
+ const logger = options.logger;
28
+ const initialStatusText = options.stream?.initialStatusText ?? DEFAULT_INITIAL_STATUS_TEXT;
29
+ const activeRuns = new Map();
30
+ const bot = options.botFactory?.(options.botToken) ?? new Bot(options.botToken);
31
+ const sender = createGrammyTelegramApi(bot.api);
32
+ const isAuthorized = (chatId) => chatId !== undefined && (allowAllChats || allowedChatIds.has(String(chatId)));
33
+ bot.use(async (ctx, next) => {
34
+ const chatId = ctx.chat?.id;
35
+ if (chatId === undefined) {
36
+ return;
37
+ }
38
+ if (!isAuthorized(chatId)) {
39
+ await ctx.reply(messages.unauthorizedText);
40
+ return;
41
+ }
42
+ await next();
43
+ });
44
+ bot.command("start", async (ctx) => {
45
+ await ctx.reply(messages.welcomeText);
46
+ });
47
+ bot.command("help", async (ctx) => {
48
+ await ctx.reply(messages.helpText);
49
+ });
50
+ bot.command("cancel", async (ctx) => {
51
+ const chatId = ctx.chat?.id;
52
+ if (chatId !== undefined) {
53
+ activeRuns.get(String(chatId))?.controller.abort(new Error("Cancelled by Telegram user."));
54
+ }
55
+ await ctx.reply(messages.cancelledText);
56
+ });
57
+ bot.on("message:text", async (ctx) => {
58
+ await handleAgentMessage(ctx);
59
+ });
60
+ bot.on("message", async (ctx) => {
61
+ await ctx.reply(messages.unsupportedText);
62
+ });
63
+ async function handleAgentMessage(ctx) {
64
+ const message = ctx.message;
65
+ const chatId = ctx.chat?.id;
66
+ if (message === undefined || chatId === undefined) {
67
+ return;
68
+ }
69
+ const text = (message.text ?? "").trim();
70
+ if (text.length === 0) {
71
+ await ctx.reply(messages.unsupportedText);
72
+ return;
73
+ }
74
+ const key = String(chatId);
75
+ if (activeRuns.has(key)) {
76
+ await ctx.reply(messages.busyText);
77
+ return;
78
+ }
79
+ // Record the run synchronously, before any await, so a concurrent message for
80
+ // the same chat observes it and gets the "busy" reply above.
81
+ const controller = new AbortController();
82
+ const activeRun = { controller };
83
+ activeRuns.set(key, activeRun);
84
+ const request = buildAgentRequest(ctx.update, message, text, controller.signal);
85
+ const stream = new TelegramMessageStream(buildStreamOptions(chatId, message.message_id, controller.signal));
86
+ try {
87
+ try {
88
+ await stream.status(initialStatusText);
89
+ }
90
+ catch (statusError) {
91
+ logger?.warn?.("Telegram initial status send failed; continuing to the agent run.", {
92
+ error: errorMessage(statusError),
93
+ });
94
+ }
95
+ if (controller.signal.aborted) {
96
+ await finishSafely(stream, messages.cancelledText, logger);
97
+ return;
98
+ }
99
+ let response;
100
+ try {
101
+ response = await options.responder.respond(request, stream);
102
+ }
103
+ catch (error) {
104
+ if (controller.signal.aborted || isAgentResponseCancelledError(error)) {
105
+ await finishSafely(stream, messages.cancelledText, logger);
106
+ return;
107
+ }
108
+ logger?.error?.("Telegram bot responder failed.", { error: errorMessage(error) });
109
+ const errorText = await resolveErrorText({
110
+ configured: messages.errorText,
111
+ error,
112
+ request,
113
+ logger,
114
+ });
115
+ await finishSafely(stream, errorText, logger);
116
+ return;
117
+ }
118
+ if (controller.signal.aborted) {
119
+ await finishSafely(stream, messages.cancelledText, logger);
120
+ return;
121
+ }
122
+ try {
123
+ await stream.finish(response.text);
124
+ }
125
+ catch (error) {
126
+ if (controller.signal.aborted || isAgentResponseCancelledError(error)) {
127
+ return;
128
+ }
129
+ // The AI run succeeded; a delivery failure is degraded, never an error.
130
+ logger?.error?.("Telegram final delivery failed after a successful AI run.", {
131
+ error: errorMessage(error),
132
+ });
133
+ }
134
+ }
135
+ finally {
136
+ if (activeRuns.get(key) === activeRun) {
137
+ activeRuns.delete(key);
138
+ }
139
+ }
140
+ }
141
+ function buildStreamOptions(chatId, replyToMessageId, signal) {
142
+ const streamOptions = {
143
+ api: sender,
144
+ chatId,
145
+ replyToMessageId,
146
+ abortSignal: signal,
147
+ };
148
+ const tuning = options.stream;
149
+ if (tuning?.initialStatusText !== undefined) {
150
+ streamOptions.initialStatusText = tuning.initialStatusText;
151
+ }
152
+ if (tuning?.editDebounceMs !== undefined) {
153
+ streamOptions.editDebounceMs = tuning.editDebounceMs;
154
+ }
155
+ if (tuning?.maxMessageChars !== undefined) {
156
+ streamOptions.maxMessageChars = tuning.maxMessageChars;
157
+ }
158
+ if (tuning?.maxSendRetries !== undefined) {
159
+ streamOptions.maxSendRetries = tuning.maxSendRetries;
160
+ }
161
+ if (tuning?.retryCapMs !== undefined) {
162
+ streamOptions.retryCapMs = tuning.retryCapMs;
163
+ }
164
+ if (tuning?.retryBaseDelayMs !== undefined) {
165
+ streamOptions.retryBaseDelayMs = tuning.retryBaseDelayMs;
166
+ }
167
+ if (tuning?.showThoughts !== undefined) {
168
+ streamOptions.showThoughts = tuning.showThoughts;
169
+ }
170
+ if (tuning?.formatMarkdown !== undefined) {
171
+ streamOptions.formatMarkdown = tuning.formatMarkdown;
172
+ }
173
+ if (logger !== undefined) {
174
+ streamOptions.logger = logger;
175
+ }
176
+ return streamOptions;
177
+ }
178
+ let runnerHandle;
179
+ return {
180
+ bot,
181
+ async start() {
182
+ if (runnerHandle?.isRunning() === true) {
183
+ return;
184
+ }
185
+ if ((options.deleteWebhookOnStart ?? true) === true) {
186
+ await bot.api.deleteWebhook({ drop_pending_updates: options.dropPendingUpdates ?? false });
187
+ }
188
+ runnerHandle = (options.runnerFactory ?? defaultRunnerFactory)(bot);
189
+ // Surface a late polling crash to the shared logger and the host's
190
+ // onPollingError callback without leaving an unhandled rejection; stop()
191
+ // still settles the runner independently.
192
+ runnerHandle.task?.()?.catch((error) => {
193
+ logger?.error?.("Telegram polling stopped with an error.", {
194
+ error: errorMessage(error),
195
+ });
196
+ options.onPollingError?.(error);
197
+ });
198
+ },
199
+ async stop() {
200
+ if (runnerHandle?.isRunning() === true) {
201
+ await runnerHandle.stop();
202
+ }
203
+ runnerHandle = undefined;
204
+ },
205
+ };
206
+ function defaultRunnerFactory(target) {
207
+ const allowed = [...(options.allowedUpdates ?? ["message"])];
208
+ return run(target, { runner: { fetch: { allowed_updates: allowed } } });
209
+ }
210
+ }
211
+ function errorMessage(error) {
212
+ return error instanceof Error ? error.message : String(error);
213
+ }
214
+ //# sourceMappingURL=bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,GAAG,EAAsC,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAgB,MAAM,QAAQ,CAAC;AAE3C,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GAMjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EACL,qBAAqB,GAEtB,MAAM,qBAAqB,CAAC;AAM7B,MAAM,2BAA2B,GAAG,WAAW,CAAC;AAwChD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,KAAK,IAAI,CAAC;IACrD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvF,IAAI,CAAC,aAAa,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,SAAS,CAAC,mEAAmE,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,QAAQ,GAAsC,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IACjG,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,iBAAiB,IAAI,2BAA2B,CAAC;IAC3F,MAAM,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;IAEhD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEhD,MAAM,YAAY,GAAG,CAAC,MAAkC,EAAW,EAAE,CACnE,MAAM,KAAK,SAAS,IAAI,CAAC,aAAa,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEhF,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACjC,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACnC,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC9B,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,kBAAkB,CAAC,GAAY;QAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAClD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,8EAA8E;QAC9E,6DAA6D;QAC7D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAc,EAAE,UAAU,EAAE,CAAC;QAC5C,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,iBAAiB,CAC/B,GAAG,CAAC,MAAmC,EACvC,OAAqC,EACrC,IAAI,EACJ,UAAU,CAAC,MAAM,CAClB,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,qBAAqB,CACtC,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAClE,CAAC;QAEF,IAAI,CAAC;YACH,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,WAAW,EAAE,CAAC;gBACrB,MAAM,EAAE,IAAI,EAAE,CAAC,mEAAmE,EAAE;oBAClF,KAAK,EAAE,YAAY,CAAC,WAAW,CAAC;iBACjC,CAAC,CAAC;YACL,CAAC;YACD,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC9B,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,IAAI,QAAuB,CAAC;YAC5B,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtE,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;oBAC3D,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,KAAK,EAAE,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAClF,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC;oBACvC,UAAU,EAAE,QAAQ,CAAC,SAAS;oBAC9B,KAAK;oBACL,OAAO;oBACP,MAAM;iBACP,CAAC,CAAC;gBACH,MAAM,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gBAC9C,OAAO;YACT,CAAC;YAED,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC9B,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtE,OAAO;gBACT,CAAC;gBACD,wEAAwE;gBACxE,MAAM,EAAE,KAAK,EAAE,CAAC,2DAA2D,EAAE;oBAC3E,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBACtC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,kBAAkB,CACzB,MAAsB,EACtB,gBAAwB,EACxB,MAAmB;QAEnB,MAAM,aAAa,GAAiC;YAClD,GAAG,EAAE,MAAM;YACX,MAAM;YACN,gBAAgB;YAChB,WAAW,EAAE,MAAM;SACpB,CAAC;QACF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,MAAM,EAAE,iBAAiB,KAAK,SAAS,EAAE,CAAC;YAC5C,aAAa,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAC7D,CAAC;QACD,IAAI,MAAM,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;YACzC,aAAa,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QACvD,CAAC;QACD,IAAI,MAAM,EAAE,eAAe,KAAK,SAAS,EAAE,CAAC;YAC1C,aAAa,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;QACzD,CAAC;QACD,IAAI,MAAM,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;YACzC,aAAa,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QACvD,CAAC;QACD,IAAI,MAAM,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAC/C,CAAC;QACD,IAAI,MAAM,EAAE,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC3C,aAAa,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;QAC3D,CAAC;QACD,IAAI,MAAM,EAAE,YAAY,KAAK,SAAS,EAAE,CAAC;YACvC,aAAa,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACnD,CAAC;QACD,IAAI,MAAM,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;YACzC,aAAa,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QACvD,CAAC;QACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC;QAChC,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,IAAI,YAAsC,CAAC;IAE3C,OAAO;QACL,GAAG;QACH,KAAK,CAAC,KAAK;YACT,IAAI,YAAY,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACpD,MAAM,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,oBAAoB,EAAE,OAAO,CAAC,kBAAkB,IAAI,KAAK,EAAE,CAAC,CAAC;YAC7F,CAAC;YACD,YAAY,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC;YACpE,mEAAmE;YACnE,yEAAyE;YACzE,0CAA0C;YAC1C,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC9C,MAAM,EAAE,KAAK,EAAE,CAAC,yCAAyC,EAAE;oBACzD,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;iBAC3B,CAAC,CAAC;gBACH,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,IAAI;YACR,IAAI,YAAY,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC;gBACvC,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC;YAC5B,CAAC;YACD,YAAY,GAAG,SAAS,CAAC;QAC3B,CAAC;KACF,CAAC;IAEF,SAAS,oBAAoB,CAAC,MAAW;QACvC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,CAAC,CAA8B,CAAC;QAC1F,OAAO,GAAG,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
package/dist/config.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import type { FieldGroup, RedactedSecretValue, SettingsJson } from "@mono-agent/settings";
2
2
  export interface TelegramAdapterConfig {
3
+ readonly enabled: boolean;
3
4
  readonly botToken: string;
4
5
  readonly allowedChatIds: readonly string[];
5
6
  readonly allowAllChats: boolean;
6
7
  }
7
8
  export interface RedactedTelegramAdapterConfig {
9
+ readonly enabled: boolean;
8
10
  readonly botToken: RedactedSecretValue;
9
11
  readonly allowedChatIds: {
10
12
  readonly count: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,UAAU,EACV,mBAAmB,EACnB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,8BAA8B,GACtC,yBAAyB,GACzB,gBAAgB,CAAC;AAErB,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;gBAGlD,IAAI,EAAE,8BAA8B,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iCAAsC;CAOlD;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAcD,eAAO,MAAM,kBAAkB,EAAE,UA4B/B,CAAC;AAEH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAwBhC;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,qBAAqB,GAC5B,6BAA6B,CAM/B"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,UAAU,EACV,mBAAmB,EACnB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,cAAc,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,8BAA8B,GACtC,yBAAyB,GACzB,gBAAgB,CAAC;AAErB,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,8BAA8B,CAAC;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;gBAGlD,IAAI,EAAE,8BAA8B,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iCAAsC;CAOlD;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAcD,eAAO,MAAM,kBAAkB,EAAE,UAmC/B,CAAC;AAEH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAsChC;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,qBAAqB,GAC5B,6BAA6B,CAO/B"}
package/dist/config.js CHANGED
@@ -16,6 +16,13 @@ export const telegramFieldGroup = defineFieldGroup({
16
16
  label: "Telegram",
17
17
  description: "Optional Telegram adapter configuration. The token is write-only.",
18
18
  fields: [
19
+ {
20
+ id: "telegram.enabled",
21
+ label: "Enable Telegram",
22
+ description: "Start the Telegram adapter with the app. Off by default.",
23
+ kind: "switch",
24
+ path: ["telegram", "enabled"],
25
+ },
19
26
  {
20
27
  id: "telegram.botToken",
21
28
  label: "Bot token",
@@ -43,16 +50,24 @@ export const telegramFieldGroup = defineFieldGroup({
43
50
  export async function loadTelegramAdapterConfig(input) {
44
51
  const json = input.json ?? (input.jsonPath === undefined ? {} : (await readSettingsJson(input.jsonPath)).json);
45
52
  const env = layerTelegramJsonOntoEnv(json, input.env);
46
- const botToken = readRequired(env.MONO_AGENT_TELEGRAM_BOT_TOKEN, "MONO_AGENT_TELEGRAM_BOT_TOKEN", missingRequiredConfig);
53
+ const enabled = readBoolean(env.MONO_AGENT_TELEGRAM_ENABLED, "MONO_AGENT_TELEGRAM_ENABLED", false, invalidConfig);
47
54
  const allowedChatIds = readCsv(env.MONO_AGENT_TELEGRAM_ALLOWED_CHAT_IDS);
48
55
  const allowAllChats = readBoolean(env.MONO_AGENT_TELEGRAM_ALLOW_ALL_CHATS, "MONO_AGENT_TELEGRAM_ALLOW_ALL_CHATS", false, invalidConfig);
56
+ // A disabled channel never validates its credentials: the status surface reads
57
+ // it as "disabled", not "waiting for config". Only an enabled channel demands
58
+ // its required fields (a missing token then becomes a real "waiting" reason).
59
+ if (!enabled) {
60
+ return { enabled: false, botToken: "", allowedChatIds, allowAllChats };
61
+ }
62
+ const botToken = readRequired(env.MONO_AGENT_TELEGRAM_BOT_TOKEN, "MONO_AGENT_TELEGRAM_BOT_TOKEN", missingRequiredConfig);
49
63
  if (!allowAllChats && allowedChatIds.length === 0) {
50
64
  throw missingRequiredConfig("Telegram adapter requires MONO_AGENT_TELEGRAM_ALLOWED_CHAT_IDS or MONO_AGENT_TELEGRAM_ALLOW_ALL_CHATS=true.", { env: "MONO_AGENT_TELEGRAM_ALLOWED_CHAT_IDS" });
51
65
  }
52
- return { botToken, allowedChatIds, allowAllChats };
66
+ return { enabled: true, botToken, allowedChatIds, allowAllChats };
53
67
  }
54
68
  export function redactTelegramAdapterConfig(config) {
55
69
  return {
70
+ enabled: config.enabled,
56
71
  botToken: redactedSecret(config.botToken),
57
72
  allowedChatIds: { count: config.allowedChatIds.length },
58
73
  allowAllChats: config.allowAllChats,
@@ -61,6 +76,7 @@ export function redactTelegramAdapterConfig(config) {
61
76
  function layerTelegramJsonOntoEnv(json, env) {
62
77
  const section = readJsonSection(json, "telegram");
63
78
  return layerJsonOntoEnv(env, [
79
+ { env: "MONO_AGENT_TELEGRAM_ENABLED", value: section.enabled, kind: "boolean" },
64
80
  { env: "MONO_AGENT_TELEGRAM_BOT_TOKEN", value: section.botToken },
65
81
  { env: "MONO_AGENT_TELEGRAM_ALLOWED_CHAT_IDS", value: section.allowedChatIds, kind: "csv" },
66
82
  { env: "MONO_AGENT_TELEGRAM_ALLOW_ALL_CHATS", value: section.allowAllChats, kind: "boolean" },
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type Api } from "grammy";
2
+ import type { TelegramMessageSender } from "./types.js";
3
+ /**
4
+ * Adapt a grammY {@link Api} to the {@link TelegramMessageSender} the streaming
5
+ * delivery layer depends on.
6
+ *
7
+ * Two responsibilities: translate our params-object calls into grammY's
8
+ * positional `(chat_id, text, other, signal)` form, and translate grammY's
9
+ * thrown errors (`GrammyError`, `HttpError`) back into {@link TelegramApiError}
10
+ * so the existing recovery policy (`classifyTelegramError`) keeps working
11
+ * unchanged.
12
+ */
13
+ export declare function createGrammyTelegramApi(api: Api): TelegramMessageSender;
14
+ //# sourceMappingURL=grammy-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grammy-client.d.ts","sourceRoot":"","sources":["../src/grammy-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,GAAG,EAAE,MAAM,QAAQ,CAAC;AAM1D,OAAO,KAAK,EAEV,qBAAqB,EAItB,MAAM,YAAY,CAAC;AAYpB;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,qBAAqB,CAoDvE"}
@@ -0,0 +1,103 @@
1
+ import { GrammyError, HttpError } from "grammy";
2
+ import { TelegramApiError, } from "./telegram-error.js";
3
+ // grammY's `Api` types its `signal` parameter with the `abort-controller` shim's
4
+ // AbortSignal rather than the global one; the runtime value is identical, so we
5
+ // cast through this helper at the call boundary.
6
+ function asGrammySignal(signal) {
7
+ return signal;
8
+ }
9
+ /**
10
+ * Adapt a grammY {@link Api} to the {@link TelegramMessageSender} the streaming
11
+ * delivery layer depends on.
12
+ *
13
+ * Two responsibilities: translate our params-object calls into grammY's
14
+ * positional `(chat_id, text, other, signal)` form, and translate grammY's
15
+ * thrown errors (`GrammyError`, `HttpError`) back into {@link TelegramApiError}
16
+ * so the existing recovery policy (`classifyTelegramError`) keeps working
17
+ * unchanged.
18
+ */
19
+ export function createGrammyTelegramApi(api) {
20
+ return {
21
+ async sendMessage(params, options) {
22
+ try {
23
+ const message = await api.sendMessage(params.chat_id, params.text, buildSendOther(params), asGrammySignal(options?.signal));
24
+ return message;
25
+ }
26
+ catch (error) {
27
+ throw toTelegramApiError("sendMessage", error, options?.signal);
28
+ }
29
+ },
30
+ async editMessageText(params, options) {
31
+ try {
32
+ if (params.inline_message_id !== undefined) {
33
+ const result = await api.editMessageTextInline(params.inline_message_id, params.text, buildEditOther(params), asGrammySignal(options?.signal));
34
+ return result === true ? true : result;
35
+ }
36
+ if (params.chat_id !== undefined && params.message_id !== undefined) {
37
+ const result = await api.editMessageText(params.chat_id, params.message_id, params.text, buildEditOther(params), asGrammySignal(options?.signal));
38
+ return result === true ? true : result;
39
+ }
40
+ }
41
+ catch (error) {
42
+ throw toTelegramApiError("editMessageText", error, options?.signal);
43
+ }
44
+ throw new TelegramApiError("grammY editMessageText requires inline_message_id, or chat_id and message_id.", { kind: "telegram", method: "editMessageText" });
45
+ },
46
+ };
47
+ }
48
+ function buildSendOther(params) {
49
+ const other = {};
50
+ if (params.parse_mode !== undefined) {
51
+ other.parse_mode = params.parse_mode;
52
+ }
53
+ if (params.reply_to_message_id !== undefined) {
54
+ other.reply_parameters = { message_id: params.reply_to_message_id };
55
+ }
56
+ if (params.disable_web_page_preview !== undefined) {
57
+ other.link_preview_options = { is_disabled: params.disable_web_page_preview };
58
+ }
59
+ return other;
60
+ }
61
+ function buildEditOther(params) {
62
+ const other = {};
63
+ if (params.parse_mode !== undefined) {
64
+ other.parse_mode = params.parse_mode;
65
+ }
66
+ if (params.disable_web_page_preview !== undefined) {
67
+ other.link_preview_options = { is_disabled: params.disable_web_page_preview };
68
+ }
69
+ return other;
70
+ }
71
+ function toTelegramApiError(method, error, signal) {
72
+ if (error instanceof TelegramApiError) {
73
+ return error;
74
+ }
75
+ if (signal?.aborted === true || isAbortError(error)) {
76
+ return new TelegramApiError(`Telegram API ${method} request was aborted.`, {
77
+ kind: "aborted",
78
+ method,
79
+ });
80
+ }
81
+ if (error instanceof GrammyError) {
82
+ const details = {
83
+ kind: "telegram",
84
+ method,
85
+ errorCode: error.error_code,
86
+ telegramDescription: error.description,
87
+ };
88
+ const retryAfter = error.parameters.retry_after;
89
+ if (typeof retryAfter === "number" && Number.isFinite(retryAfter)) {
90
+ details.retryAfterMs = Math.max(0, retryAfter) * 1000;
91
+ }
92
+ return new TelegramApiError(`Telegram API ${method} rejected the request.`, details);
93
+ }
94
+ if (error instanceof HttpError) {
95
+ return new TelegramApiError(`Network failure while calling Telegram API ${method}.`, { kind: "network", method, cause: error });
96
+ }
97
+ return new TelegramApiError(`Unexpected failure while calling Telegram API ${method}.`, { kind: "network", method, cause: error });
98
+ }
99
+ function isAbortError(value) {
100
+ return ((value instanceof DOMException && value.name === "AbortError") ||
101
+ (value instanceof Error && value.name === "AbortError"));
102
+ }
103
+ //# sourceMappingURL=grammy-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grammy-client.js","sourceRoot":"","sources":["../src/grammy-client.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,15 @@
1
- export type { TelegramBotApi, TelegramChat, TelegramChatId, TelegramDeleteWebhookParams, TelegramEditMessageTextParams, TelegramGetUpdatesParams, TelegramMessage, TelegramRequestOptions, TelegramSendMessageParams, TelegramSentMessage, TelegramUpdate, TelegramUser, } from "./types.js";
2
- export { TelegramApiError, TelegramBotApiClient, } from "./telegram-client.js";
3
- export type { TelegramApiErrorDetails, TelegramApiErrorKind, TelegramBotApiClientOptions, } from "./telegram-client.js";
4
- export { TelegramMessageStream } from "./message-stream.js";
5
- export type { TelegramMessageStreamLogger, TelegramMessageStreamOptions, } from "./message-stream.js";
6
- export { TelegramAdapter } from "./adapter.js";
7
- export type { AgentRequest, AgentResponder, AgentResponse, TelegramAdapterLogger, TelegramAdapterMessages, TelegramAdapterOptions, TelegramAdapterStreamOptions, TelegramRequestMetadata, TelegramUpdateHandlingResult, } from "./adapter.js";
8
- export { TelegramLongPoller } from "./long-poller.js";
9
- export type { TelegramLongPollerBackoffOptions, TelegramLongPollerLogger, TelegramLongPollerOptions, TelegramLongPollerPollOptions, TelegramLongPollerStartOptions, TelegramUpdateHandler, } from "./long-poller.js";
1
+ export type { TelegramBotApi, TelegramChat, TelegramChatId, TelegramDeleteWebhookParams, TelegramEditMessageTextParams, TelegramGetUpdatesParams, TelegramMessage, TelegramMessageSender, TelegramRequestOptions, TelegramSendMessageParams, TelegramSentMessage, TelegramUpdate, TelegramUser, } from "./types.js";
2
+ export { TelegramApiError } from "./telegram-error.js";
3
+ export type { TelegramApiErrorDetails, TelegramApiErrorKind, } from "./telegram-error.js";
4
+ export { TelegramDeliveryError, TelegramMessageStream, classifyTelegramError, } from "./message-stream.js";
5
+ export type { AgentMessageStream, TelegramMessageStreamLogger, TelegramMessageStreamOptions, TelegramSendOutcome, } from "./message-stream.js";
6
+ export { renderTelegramMarkdown } from "./telegram-markdown.js";
7
+ export { createGrammyTelegramApi } from "./grammy-client.js";
8
+ export { createTelegramBot } from "./bot.js";
9
+ export type { CreateTelegramBotOptions, TelegramBotController, } from "./bot.js";
10
+ export type { AgentRequest, AgentResponder, AgentResponse, TelegramAdapterErrorText, TelegramAdapterErrorTextInput, TelegramAdapterLogger, TelegramAdapterMessages, TelegramAdapterStreamOptions, TelegramRequestMetadata, } from "./adapter.js";
10
11
  export { startTelegramAdapter } from "./start.js";
11
- export type { TelegramAdapterStartOptions, TelegramAdapterStartResult, TelegramPollerLike, } from "./start.js";
12
+ export type { TelegramAdapterStartOptions, TelegramAdapterStartResult, } from "./start.js";
12
13
  export { loadTelegramAdapterConfig, redactTelegramAdapterConfig, TelegramAdapterConfigError, telegramFieldGroup, } from "./config.js";
13
14
  export type { LoadTelegramAdapterConfigInput, RedactedTelegramAdapterConfig, TelegramAdapterConfig, TelegramAdapterConfigErrorCode, TelegramAdapterConfigErrorDetails, } from "./config.js";
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,uBAAuB,EACvB,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,uBAAuB,EACvB,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EACV,gCAAgC,EAChC,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,EACxB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EACV,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,kBAAkB,EAClB,2BAA2B,EAC3B,4BAA4B,EAC5B,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EACV,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,wBAAwB,EACxB,6BAA6B,EAC7B,qBAAqB,EACrB,uBAAuB,EACvB,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,8BAA8B,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,8BAA8B,EAC9B,iCAAiC,GAClC,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- export { TelegramApiError, TelegramBotApiClient, } from "./telegram-client.js";
2
- export { TelegramMessageStream } from "./message-stream.js";
3
- export { TelegramAdapter } from "./adapter.js";
4
- export { TelegramLongPoller } from "./long-poller.js";
1
+ export { TelegramApiError } from "./telegram-error.js";
2
+ export { TelegramDeliveryError, TelegramMessageStream, classifyTelegramError, } from "./message-stream.js";
3
+ export { renderTelegramMarkdown } from "./telegram-markdown.js";
4
+ export { createGrammyTelegramApi } from "./grammy-client.js";
5
+ export { createTelegramBot } from "./bot.js";
5
6
  export { startTelegramAdapter } from "./start.js";
6
7
  export { loadTelegramAdapterConfig, redactTelegramAdapterConfig, TelegramAdapterConfigError, telegramFieldGroup, } from "./config.js";
7
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,OAAO,EACL,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAK5D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAY/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAStD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMlD,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAMvD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAkB7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMlD,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
@@ -1,18 +1,31 @@
1
- import type { AgentMessageStream as AgentMessageStreamBase } from "@mono-agent/agent-contracts";
2
- import type { TelegramBotApi, TelegramChatId } from "./types.js";
1
+ import type { AgentMessageStream as AgentMessageStreamBase, AgentStreamEvent } from "@mono-agent/agent-contracts";
2
+ import type { TelegramChatId, TelegramMessageSender } from "./types.js";
3
3
  export interface AgentMessageStream extends AgentMessageStreamBase {
4
4
  status(text: string): Promise<void>;
5
5
  append(delta: string): Promise<void>;
6
6
  replace(text: string): Promise<void>;
7
+ event(event: AgentStreamEvent): Promise<void>;
7
8
  finish(finalText?: string): Promise<void>;
8
9
  }
9
10
  export interface TelegramMessageStreamOptions {
10
- api: TelegramBotApi;
11
+ api: TelegramMessageSender;
11
12
  chatId: TelegramChatId;
12
13
  initialStatusText?: string;
13
14
  editDebounceMs?: number;
14
15
  maxMessageChars?: number;
15
16
  replyToMessageId?: number;
17
+ /** Maximum retries for a *final* delivery before giving up. Default 3. */
18
+ maxSendRetries?: number;
19
+ /** Upper bound on any honored `retry_after`/backoff wait, in ms. Default 60000. */
20
+ retryCapMs?: number;
21
+ /** Base delay for exponential backoff between final-delivery retries. Default 500. */
22
+ retryBaseDelayMs?: number;
23
+ /** Render accumulated reasoning as a live "💭" message. Default true. */
24
+ showThoughts?: boolean;
25
+ /** Render the final answer as Telegram MarkdownV2 (plain fallback). Default true. */
26
+ formatMarkdown?: boolean;
27
+ /** Aborts in-flight retry waits (e.g. on /cancel). */
28
+ abortSignal?: AbortSignal;
16
29
  logger?: TelegramMessageStreamLogger;
17
30
  }
18
31
  export interface TelegramMessageStreamLogger {
@@ -20,6 +33,32 @@ export interface TelegramMessageStreamLogger {
20
33
  warn?(message: string, metadata?: Record<string, unknown>): void;
21
34
  error?(message: string, metadata?: Record<string, unknown>): void;
22
35
  }
36
+ /**
37
+ * Raised only when a *final* delivery cannot reach Telegram after retries and
38
+ * the last-resort fresh send. The AI request itself already succeeded, so the
39
+ * adapter treats this as a degraded delivery — never as an agent failure.
40
+ */
41
+ export declare class TelegramDeliveryError extends Error {
42
+ readonly cause: unknown;
43
+ readonly attempts: number;
44
+ constructor(message: string, details: {
45
+ cause: unknown;
46
+ attempts: number;
47
+ });
48
+ }
49
+ /** How a failed Telegram send/edit should be handled. */
50
+ export type TelegramSendOutcome = {
51
+ kind: "not_modified";
52
+ } | {
53
+ kind: "recreate";
54
+ } | {
55
+ kind: "reformat_plain";
56
+ } | {
57
+ kind: "retry";
58
+ retryAfterMs?: number;
59
+ } | {
60
+ kind: "fatal";
61
+ };
23
62
  export declare class TelegramMessageStream implements AgentMessageStream {
24
63
  private readonly api;
25
64
  private readonly chatId;
@@ -27,28 +66,62 @@ export declare class TelegramMessageStream implements AgentMessageStream {
27
66
  private readonly editDebounceMs;
28
67
  private readonly maxMessageChars;
29
68
  private readonly replyToMessageId;
69
+ private readonly maxSendRetries;
70
+ private readonly retryCapMs;
71
+ private readonly retryBaseDelayMs;
72
+ private readonly showThoughts;
73
+ private readonly formatMarkdown;
74
+ private readonly abortSignal;
30
75
  private readonly logger;
31
76
  private currentText;
77
+ private thinkingText;
78
+ private hasAnswerText;
32
79
  private statusText;
33
80
  private sentMessage;
34
81
  private sendMessagePromise;
35
82
  private editTimer;
36
83
  private inFlightEdit;
37
- private lastAsyncError;
84
+ private lastFlushedText;
85
+ private lastFlushedMarkdown;
38
86
  private finished;
39
87
  constructor(options: TelegramMessageStreamOptions);
40
88
  status(text: string): Promise<void>;
41
89
  append(delta: string): Promise<void>;
42
90
  replace(text: string): Promise<void>;
43
- finish(finalText?: string): Promise<void>;
91
+ event(event: AgentStreamEvent): Promise<void>;
92
+ finish(finalText?: string, options?: {
93
+ format?: boolean;
94
+ }): Promise<void>;
95
+ private interimDisplayText;
44
96
  private ensureMessage;
45
97
  private scheduleEdit;
46
98
  private startInFlightEdit;
47
- private flushEdit;
99
+ /**
100
+ * Send `sourceText` to Telegram, classifying failures and recovering where
101
+ * possible. Interim edits (`final: false`) are best-effort and never throw;
102
+ * final delivery retries transient failures and throws TelegramDeliveryError
103
+ * only when every path is exhausted.
104
+ */
105
+ private deliverText;
106
+ /**
107
+ * The streamed message could not be edited or recreated in place. Post the
108
+ * final answer as a brand-new plain message so the user still receives it.
109
+ */
110
+ private lastResortSend;
111
+ /** Overflow continuation chunks are best-effort: the primary answer already landed. */
112
+ private sendOverflowChunk;
113
+ private buildEditParams;
114
+ private buildSendParams;
115
+ private retryDelayMs;
116
+ private sleep;
48
117
  private cancelScheduledEdit;
49
118
  private awaitInFlightEdit;
50
- private throwIfAsyncError;
51
119
  private assertOpen;
52
120
  }
121
+ /**
122
+ * Classify a Telegram send/edit failure into a recovery strategy. Pure and
123
+ * exported so the recovery policy can be unit-tested directly.
124
+ */
125
+ export declare function classifyTelegramError(error: unknown): TelegramSendOutcome;
53
126
  export declare function splitTelegramText(text: string, maxChars: number): string[];
54
127
  //# sourceMappingURL=message-stream.d.ts.map