@mono-agent/telegram-adapter 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/adapter.d.ts +35 -57
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +37 -179
- package/dist/adapter.js.map +1 -1
- package/dist/bot.d.ts +50 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +214 -0
- package/dist/bot.js.map +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -2
- package/dist/config.js.map +1 -1
- package/dist/grammy-client.d.ts +14 -0
- package/dist/grammy-client.d.ts.map +1 -0
- package/dist/grammy-client.js +103 -0
- package/dist/grammy-client.js.map +1 -0
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/message-stream.d.ts +80 -7
- package/dist/message-stream.d.ts.map +1 -1
- package/dist/message-stream.js +381 -34
- package/dist/message-stream.js.map +1 -1
- package/dist/start.d.ts +23 -34
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +25 -43
- package/dist/start.js.map +1 -1
- package/dist/telegram-error.d.ts +34 -0
- package/dist/telegram-error.d.ts.map +1 -0
- package/dist/telegram-error.js +39 -0
- package/dist/telegram-error.js.map +1 -0
- package/dist/telegram-markdown.d.ts +17 -0
- package/dist/telegram-markdown.d.ts.map +1 -0
- package/dist/telegram-markdown.js +20 -0
- package/dist/telegram-markdown.js.map +1 -0
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -3
- package/dist/long-poller.d.ts +0 -55
- package/dist/long-poller.d.ts.map +0 -1
- package/dist/long-poller.js +0 -156
- package/dist/long-poller.js.map +0 -1
- package/dist/telegram-client.d.ts +0 -38
- package/dist/telegram-client.d.ts.map +0 -1
- package/dist/telegram-client.js +0 -183
- package/dist/telegram-client.js.map +0 -1
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ Category: `communication`
|
|
|
8
8
|
|
|
9
9
|
Telegram communication adapter for agent hosts. It provides a Bot API client, long poller, update handler, streamed message edits, cancellation, allowlist enforcement, and Telegram-owned settings helpers.
|
|
10
10
|
|
|
11
|
+
The adapter is opt-in: `telegram.enabled` / `MONO_AGENT_TELEGRAM_ENABLED` defaults to `false`. While disabled the loader skips credential validation and the channel reports `disabled` rather than `waiting_for_config`. Set `enabled: true` to turn it on; a missing bot token or allowlist then surfaces as a real `waiting_for_config` reason.
|
|
12
|
+
|
|
11
13
|
## Install / Usage
|
|
12
14
|
|
|
13
15
|
```bash
|
package/dist/adapter.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type AgentMessageStream, type TelegramMessageStreamLogger } from "./message-stream.js";
|
|
3
|
-
import type {
|
|
1
|
+
import type { AgentRequestBase, AgentResponder as SharedAgentResponder, AgentResponse } from "@mono-agent/agent-contracts";
|
|
2
|
+
import { TelegramMessageStream, type AgentMessageStream, type TelegramMessageStreamLogger } from "./message-stream.js";
|
|
3
|
+
import type { TelegramChatId, TelegramMessage, TelegramUpdate } from "./types.js";
|
|
4
4
|
export interface AgentRequest extends AgentRequestBase {
|
|
5
5
|
conversationId: string;
|
|
6
6
|
chatId: TelegramChatId;
|
|
@@ -44,68 +44,46 @@ export interface TelegramAdapterMessages {
|
|
|
44
44
|
busyText?: string;
|
|
45
45
|
unauthorizedText?: string;
|
|
46
46
|
cancelledText?: string;
|
|
47
|
-
errorText?:
|
|
47
|
+
errorText?: TelegramAdapterErrorText;
|
|
48
48
|
unsupportedText?: string;
|
|
49
49
|
}
|
|
50
|
+
export type TelegramAdapterErrorText = string | ((input: TelegramAdapterErrorTextInput) => string | Promise<string>);
|
|
51
|
+
export interface TelegramAdapterErrorTextInput {
|
|
52
|
+
readonly error: unknown;
|
|
53
|
+
readonly request: AgentRequest;
|
|
54
|
+
}
|
|
50
55
|
export interface TelegramAdapterStreamOptions {
|
|
51
56
|
initialStatusText?: string;
|
|
52
57
|
editDebounceMs?: number;
|
|
53
58
|
maxMessageChars?: number;
|
|
59
|
+
maxSendRetries?: number;
|
|
60
|
+
retryCapMs?: number;
|
|
61
|
+
retryBaseDelayMs?: number;
|
|
62
|
+
showThoughts?: boolean;
|
|
63
|
+
formatMarkdown?: boolean;
|
|
54
64
|
}
|
|
55
65
|
export interface TelegramAdapterLogger extends TelegramMessageStreamLogger {
|
|
56
66
|
info?(message: string, metadata?: Record<string, unknown>): void;
|
|
57
67
|
}
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
} | {
|
|
80
|
-
kind: "unauthorized";
|
|
81
|
-
updateId: number;
|
|
82
|
-
chatId: TelegramChatId;
|
|
83
|
-
} | {
|
|
84
|
-
kind: "busy";
|
|
85
|
-
updateId: number;
|
|
86
|
-
chatId: TelegramChatId;
|
|
87
|
-
} | {
|
|
88
|
-
kind: "cancelled";
|
|
89
|
-
updateId: number;
|
|
90
|
-
chatId: TelegramChatId;
|
|
91
|
-
} | {
|
|
92
|
-
kind: "error";
|
|
93
|
-
updateId: number;
|
|
94
|
-
chatId?: TelegramChatId;
|
|
95
|
-
error: unknown;
|
|
96
|
-
};
|
|
97
|
-
export declare class TelegramAdapter {
|
|
98
|
-
private readonly api;
|
|
99
|
-
private readonly responder;
|
|
100
|
-
private readonly allowAllChats;
|
|
101
|
-
private readonly allowedChatIds;
|
|
102
|
-
private readonly streamOptions;
|
|
103
|
-
private readonly messages;
|
|
104
|
-
private readonly logger;
|
|
105
|
-
private readonly activeRuns;
|
|
106
|
-
constructor(options: TelegramAdapterOptions);
|
|
107
|
-
handleUpdate(update: TelegramUpdate): Promise<TelegramUpdateHandlingResult>;
|
|
108
|
-
private respondToMessage;
|
|
109
|
-
private isAuthorized;
|
|
110
|
-
}
|
|
68
|
+
export declare const DEFAULT_ERROR_TEXT = "The agent failed while processing your message.";
|
|
69
|
+
export declare const DEFAULT_MESSAGES: Required<TelegramAdapterMessages>;
|
|
70
|
+
/**
|
|
71
|
+
* Build the responder-facing {@link AgentRequest} from a Telegram update. The
|
|
72
|
+
* grammY message handler passes `ctx.update` and `ctx.message`, which are
|
|
73
|
+
* structurally compatible with the wire types this reads.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildAgentRequest(update: TelegramUpdate, message: TelegramMessage, text: string, abortSignal: AbortSignal): AgentRequest;
|
|
76
|
+
/**
|
|
77
|
+
* Deliver a terminal/system message (cancelled, error, …) in place. Such copy is
|
|
78
|
+
* fixed text we author, not model output, so it is delivered as plain text
|
|
79
|
+
* (`format: false`) — no MarkdownV2 escaping — while still reusing the stream's
|
|
80
|
+
* resilient edit-or-recreate delivery.
|
|
81
|
+
*/
|
|
82
|
+
export declare function finishSafely(stream: TelegramMessageStream, text: string, logger: TelegramAdapterLogger | undefined): Promise<void>;
|
|
83
|
+
export declare function resolveErrorText(input: {
|
|
84
|
+
readonly configured: TelegramAdapterErrorText;
|
|
85
|
+
readonly error: unknown;
|
|
86
|
+
readonly request: AgentRequest;
|
|
87
|
+
readonly logger: TelegramAdapterLogger | undefined;
|
|
88
|
+
}): Promise<string>;
|
|
111
89
|
//# sourceMappingURL=adapter.d.ts.map
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
CHANGED
|
@@ -1,182 +1,20 @@
|
|
|
1
|
-
import { isAgentResponseCancelledError, } from "@mono-agent/agent-contracts";
|
|
2
1
|
import { TelegramMessageStream, } from "./message-stream.js";
|
|
3
|
-
const
|
|
2
|
+
export const DEFAULT_ERROR_TEXT = "The agent failed while processing your message.";
|
|
3
|
+
export const DEFAULT_MESSAGES = {
|
|
4
4
|
welcomeText: "Hello! Send me a text message and I will pass it to the configured agent.",
|
|
5
5
|
helpText: "Send a text message to talk to the agent. Use /cancel to stop the current response.",
|
|
6
6
|
busyText: "I am still working on your previous message. Use /cancel to stop it.",
|
|
7
7
|
unauthorizedText: "This Telegram chat is not authorized to use this bot.",
|
|
8
8
|
cancelledText: "Cancelled.",
|
|
9
|
-
errorText:
|
|
9
|
+
errorText: DEFAULT_ERROR_TEXT,
|
|
10
10
|
unsupportedText: "I can only handle text messages in this adapter for now.",
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
messages;
|
|
19
|
-
logger;
|
|
20
|
-
activeRuns = new Map();
|
|
21
|
-
constructor(options) {
|
|
22
|
-
this.api = options.api;
|
|
23
|
-
this.responder = options.responder;
|
|
24
|
-
this.allowAllChats = options.allowAllChats === true;
|
|
25
|
-
this.allowedChatIds = new Set(options.allowedChatIds?.map((chatId) => String(chatId)) ?? []);
|
|
26
|
-
this.streamOptions = options.stream ?? {};
|
|
27
|
-
this.messages = { ...DEFAULT_MESSAGES, ...options.messages };
|
|
28
|
-
this.logger = options.logger;
|
|
29
|
-
if (!this.allowAllChats && this.allowedChatIds.size === 0) {
|
|
30
|
-
throw new TypeError("TelegramAdapter requires allowedChatIds or allowAllChats: true.");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async handleUpdate(update) {
|
|
34
|
-
const message = update.message;
|
|
35
|
-
if (message === undefined) {
|
|
36
|
-
return { kind: "ignored", updateId: update.update_id, reason: "non_message_update" };
|
|
37
|
-
}
|
|
38
|
-
const chatId = message.chat.id;
|
|
39
|
-
if (!this.isAuthorized(chatId)) {
|
|
40
|
-
await this.api.sendMessage({
|
|
41
|
-
chat_id: chatId,
|
|
42
|
-
text: this.messages.unauthorizedText,
|
|
43
|
-
});
|
|
44
|
-
return { kind: "unauthorized", updateId: update.update_id, chatId };
|
|
45
|
-
}
|
|
46
|
-
const text = message.text;
|
|
47
|
-
if (typeof text !== "string") {
|
|
48
|
-
await this.api.sendMessage({
|
|
49
|
-
chat_id: chatId,
|
|
50
|
-
text: this.messages.unsupportedText,
|
|
51
|
-
});
|
|
52
|
-
return {
|
|
53
|
-
kind: "ignored",
|
|
54
|
-
updateId: update.update_id,
|
|
55
|
-
chatId,
|
|
56
|
-
reason: "unsupported_message",
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
const trimmedText = text.trim();
|
|
60
|
-
if (trimmedText.length === 0) {
|
|
61
|
-
await this.api.sendMessage({
|
|
62
|
-
chat_id: chatId,
|
|
63
|
-
text: this.messages.unsupportedText,
|
|
64
|
-
});
|
|
65
|
-
return {
|
|
66
|
-
kind: "ignored",
|
|
67
|
-
updateId: update.update_id,
|
|
68
|
-
chatId,
|
|
69
|
-
reason: "empty_text",
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const command = parseCommand(trimmedText);
|
|
73
|
-
if (command?.name === "start") {
|
|
74
|
-
await this.api.sendMessage({ chat_id: chatId, text: this.messages.welcomeText });
|
|
75
|
-
return {
|
|
76
|
-
kind: "handled",
|
|
77
|
-
updateId: update.update_id,
|
|
78
|
-
chatId,
|
|
79
|
-
action: "command",
|
|
80
|
-
command: "start",
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
if (command?.name === "help") {
|
|
84
|
-
await this.api.sendMessage({ chat_id: chatId, text: this.messages.helpText });
|
|
85
|
-
return {
|
|
86
|
-
kind: "handled",
|
|
87
|
-
updateId: update.update_id,
|
|
88
|
-
chatId,
|
|
89
|
-
action: "command",
|
|
90
|
-
command: "help",
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
const runKey = String(chatId);
|
|
94
|
-
const activeRun = this.activeRuns.get(runKey);
|
|
95
|
-
if (command?.name === "cancel") {
|
|
96
|
-
if (activeRun !== undefined) {
|
|
97
|
-
activeRun.controller.abort(new Error("Cancelled by Telegram user."));
|
|
98
|
-
}
|
|
99
|
-
await this.api.sendMessage({
|
|
100
|
-
chat_id: chatId,
|
|
101
|
-
text: this.messages.cancelledText,
|
|
102
|
-
});
|
|
103
|
-
return { kind: "cancelled", updateId: update.update_id, chatId };
|
|
104
|
-
}
|
|
105
|
-
if (activeRun !== undefined) {
|
|
106
|
-
await this.api.sendMessage({ chat_id: chatId, text: this.messages.busyText });
|
|
107
|
-
return { kind: "busy", updateId: update.update_id, chatId };
|
|
108
|
-
}
|
|
109
|
-
return await this.respondToMessage(update, message, trimmedText, runKey);
|
|
110
|
-
}
|
|
111
|
-
async respondToMessage(update, message, text, runKey) {
|
|
112
|
-
const chatId = message.chat.id;
|
|
113
|
-
const controller = new AbortController();
|
|
114
|
-
const activeRun = { controller };
|
|
115
|
-
this.activeRuns.set(runKey, activeRun);
|
|
116
|
-
const telegramStreamOptions = {
|
|
117
|
-
api: this.api,
|
|
118
|
-
chatId,
|
|
119
|
-
replyToMessageId: message.message_id,
|
|
120
|
-
};
|
|
121
|
-
if (this.streamOptions.initialStatusText !== undefined) {
|
|
122
|
-
telegramStreamOptions.initialStatusText = this.streamOptions.initialStatusText;
|
|
123
|
-
}
|
|
124
|
-
if (this.streamOptions.editDebounceMs !== undefined) {
|
|
125
|
-
telegramStreamOptions.editDebounceMs = this.streamOptions.editDebounceMs;
|
|
126
|
-
}
|
|
127
|
-
if (this.streamOptions.maxMessageChars !== undefined) {
|
|
128
|
-
telegramStreamOptions.maxMessageChars = this.streamOptions.maxMessageChars;
|
|
129
|
-
}
|
|
130
|
-
if (this.logger !== undefined) {
|
|
131
|
-
telegramStreamOptions.logger = this.logger;
|
|
132
|
-
}
|
|
133
|
-
const stream = new TelegramMessageStream(telegramStreamOptions);
|
|
134
|
-
try {
|
|
135
|
-
await stream.status(this.streamOptions.initialStatusText ?? "Thinking…");
|
|
136
|
-
if (controller.signal.aborted) {
|
|
137
|
-
await stream.finish(this.messages.cancelledText);
|
|
138
|
-
return { kind: "cancelled", updateId: update.update_id, chatId };
|
|
139
|
-
}
|
|
140
|
-
const request = buildAgentRequest(update, message, text, controller.signal);
|
|
141
|
-
const response = await this.responder.respond(request, stream);
|
|
142
|
-
if (controller.signal.aborted) {
|
|
143
|
-
await stream.finish(this.messages.cancelledText);
|
|
144
|
-
return { kind: "cancelled", updateId: update.update_id, chatId };
|
|
145
|
-
}
|
|
146
|
-
await stream.finish(response.text);
|
|
147
|
-
const result = {
|
|
148
|
-
kind: "handled",
|
|
149
|
-
updateId: update.update_id,
|
|
150
|
-
chatId,
|
|
151
|
-
action: "responded",
|
|
152
|
-
};
|
|
153
|
-
if (response.metadata !== undefined) {
|
|
154
|
-
result.metadata = response.metadata;
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
if (controller.signal.aborted || isAgentResponseCancelledError(error)) {
|
|
160
|
-
await finishSafely(stream, this.messages.cancelledText, this.logger);
|
|
161
|
-
return { kind: "cancelled", updateId: update.update_id, chatId };
|
|
162
|
-
}
|
|
163
|
-
this.logger?.error?.("Telegram adapter responder failed.", {
|
|
164
|
-
error: error instanceof Error ? error.message : String(error),
|
|
165
|
-
});
|
|
166
|
-
await finishSafely(stream, this.messages.errorText, this.logger);
|
|
167
|
-
return { kind: "error", updateId: update.update_id, chatId, error };
|
|
168
|
-
}
|
|
169
|
-
finally {
|
|
170
|
-
if (this.activeRuns.get(runKey) === activeRun) {
|
|
171
|
-
this.activeRuns.delete(runKey);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
isAuthorized(chatId) {
|
|
176
|
-
return this.allowAllChats || this.allowedChatIds.has(String(chatId));
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function buildAgentRequest(update, message, text, abortSignal) {
|
|
12
|
+
/**
|
|
13
|
+
* Build the responder-facing {@link AgentRequest} from a Telegram update. The
|
|
14
|
+
* grammY message handler passes `ctx.update` and `ctx.message`, which are
|
|
15
|
+
* structurally compatible with the wire types this reads.
|
|
16
|
+
*/
|
|
17
|
+
export function buildAgentRequest(update, message, text, abortSignal) {
|
|
180
18
|
const from = metadataFromUser(message.from);
|
|
181
19
|
const request = {
|
|
182
20
|
conversationId: `telegram:${String(message.chat.id)}`,
|
|
@@ -246,21 +84,41 @@ function metadataFromUser(user) {
|
|
|
246
84
|
}
|
|
247
85
|
return metadata;
|
|
248
86
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Deliver a terminal/system message (cancelled, error, …) in place. Such copy is
|
|
89
|
+
* fixed text we author, not model output, so it is delivered as plain text
|
|
90
|
+
* (`format: false`) — no MarkdownV2 escaping — while still reusing the stream's
|
|
91
|
+
* resilient edit-or-recreate delivery.
|
|
92
|
+
*/
|
|
93
|
+
export async function finishSafely(stream, text, logger) {
|
|
94
|
+
try {
|
|
95
|
+
await stream.finish(text, { format: false });
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
logger?.error?.("Failed to send Telegram terminal stream message.", {
|
|
99
|
+
error: error instanceof Error ? error.message : String(error),
|
|
100
|
+
});
|
|
253
101
|
}
|
|
254
|
-
return { name: match[1].toLowerCase() };
|
|
255
102
|
}
|
|
256
|
-
async function
|
|
103
|
+
export async function resolveErrorText(input) {
|
|
104
|
+
if (typeof input.configured === "string") {
|
|
105
|
+
return input.configured;
|
|
106
|
+
}
|
|
257
107
|
try {
|
|
258
|
-
await
|
|
108
|
+
const resolved = await input.configured({
|
|
109
|
+
error: input.error,
|
|
110
|
+
request: input.request,
|
|
111
|
+
});
|
|
112
|
+
if (typeof resolved === "string" && resolved.trim().length > 0) {
|
|
113
|
+
return resolved;
|
|
114
|
+
}
|
|
115
|
+
input.logger?.warn?.("Telegram adapter error text callback returned empty text.");
|
|
259
116
|
}
|
|
260
117
|
catch (error) {
|
|
261
|
-
logger?.error?.("
|
|
118
|
+
input.logger?.error?.("Telegram adapter error text callback failed.", {
|
|
262
119
|
error: error instanceof Error ? error.message : String(error),
|
|
263
120
|
});
|
|
264
121
|
}
|
|
122
|
+
return DEFAULT_ERROR_TEXT;
|
|
265
123
|
}
|
|
266
124
|
//# sourceMappingURL=adapter.js.map
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,qBAAqB,GAGtB,MAAM,qBAAqB,CAAC;AAkF7B,MAAM,CAAC,MAAM,kBAAkB,GAAG,iDAAiD,CAAC;AAEpF,MAAM,CAAC,MAAM,gBAAgB,GAAsC;IACjE,WAAW,EACT,2EAA2E;IAC7E,QAAQ,EACN,qFAAqF;IACvF,QAAQ,EAAE,sEAAsE;IAChF,gBAAgB,EAAE,uDAAuD;IACzE,aAAa,EAAE,YAAY;IAC3B,SAAS,EAAE,kBAAkB;IAC7B,eAAe,EAAE,0DAA0D;CAC5E,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAsB,EACtB,OAAwB,EACxB,IAAY,EACZ,WAAwB;IAExB,MAAM,IAAI,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAiB;QAC5B,cAAc,EAAE,YAAY,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QACrD,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;QACvB,SAAS,EAAE,OAAO,CAAC,UAAU;QAC7B,QAAQ,EAAE,MAAM,CAAC,SAAS;QAC1B,IAAI;QACJ,WAAW;QACX,QAAQ,EAAE;YACR,QAAQ,EAAE;gBACR,QAAQ,EAAE,MAAM,CAAC,SAAS;gBAC1B,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC;gBACpC,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC;aACtC;SACF;KACF,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACxC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,WAAoC;IAC5D,MAAM,IAAI,GAAoC,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC;IACrE,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;IAC/B,CAAC;IACD,IAAI,WAAW,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;IACjC,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAwB;IAExB,MAAM,QAAQ,GAAuC,EAAE,EAAE,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;IAChF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,gBAAgB,CACvB,IAA8B;IAE9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAiD,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IAC/E,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QAChC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IACpC,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QAClC,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC;IACvC,CAAC;IACD,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;IACrC,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACrC,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC;IAC7C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA6B,EAC7B,IAAY,EACZ,MAAyC;IAEzC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,KAAK,EAAE,CAAC,kDAAkD,EAAE;YAClE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAKtC;IACC,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC,UAAU,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC;YACtC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;QACH,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/D,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2DAA2D,CAAC,CAAC;IACpF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,8CAA8C,EAAE;YACpE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;IAED,OAAO,kBAAkB,CAAC;AAC5B,CAAC"}
|
package/dist/bot.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type RunnerHandle } from "@grammyjs/runner";
|
|
2
|
+
import { Bot } from "grammy";
|
|
3
|
+
import { type AgentResponder, type TelegramAdapterLogger, type TelegramAdapterMessages, type TelegramAdapterStreamOptions } from "./adapter.js";
|
|
4
|
+
import type { TelegramChatId } from "./types.js";
|
|
5
|
+
export interface CreateTelegramBotOptions {
|
|
6
|
+
readonly botToken: string;
|
|
7
|
+
readonly responder: AgentResponder;
|
|
8
|
+
readonly allowedChatIds?: readonly TelegramChatId[];
|
|
9
|
+
readonly allowAllChats?: boolean;
|
|
10
|
+
readonly stream?: TelegramAdapterStreamOptions;
|
|
11
|
+
readonly messages?: TelegramAdapterMessages;
|
|
12
|
+
readonly logger?: TelegramAdapterLogger;
|
|
13
|
+
/** Update types to long-poll for. Defaults to messages only. */
|
|
14
|
+
readonly allowedUpdates?: readonly string[];
|
|
15
|
+
/** Delete any configured webhook before polling. Defaults to true. */
|
|
16
|
+
readonly deleteWebhookOnStart?: boolean;
|
|
17
|
+
/** Drop updates queued before start. Defaults to false. */
|
|
18
|
+
readonly dropPendingUpdates?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Called when polling crashes after a successful start (the runner's task
|
|
21
|
+
* rejects). Lets a host mark the channel failed instead of leaving it running.
|
|
22
|
+
*/
|
|
23
|
+
readonly onPollingError?: (error: unknown) => void;
|
|
24
|
+
/** Test seam: build the grammY Bot (e.g. with a fake botInfo + transformer). */
|
|
25
|
+
readonly botFactory?: (token: string) => Bot;
|
|
26
|
+
/** Test seam: build the polling runner. Defaults to `@grammyjs/runner`'s `run`. */
|
|
27
|
+
readonly runnerFactory?: (bot: Bot) => RunnerHandle;
|
|
28
|
+
}
|
|
29
|
+
export interface TelegramBotController {
|
|
30
|
+
/** The configured grammY bot. Exposed mainly so tests can drive `handleUpdate`. */
|
|
31
|
+
readonly bot: Bot;
|
|
32
|
+
/** Start concurrent long polling. Idempotent while already running. */
|
|
33
|
+
start(): Promise<void>;
|
|
34
|
+
/** Stop polling and wait for the runner to settle. */
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a grammY bot that routes authorized text messages to an agent responder.
|
|
39
|
+
*
|
|
40
|
+
* grammY owns the transport and (via `@grammyjs/runner`) concurrent polling.
|
|
41
|
+
* Middleware order is: authorization gate → `/start` `/help` `/cancel` commands →
|
|
42
|
+
* agent run handler (`message:text`) → unsupported fallback (other messages).
|
|
43
|
+
*
|
|
44
|
+
* Per-chat concurrency is guarded by an `activeRuns` map: a run is recorded
|
|
45
|
+
* synchronously at handler entry, so a second message arriving for the same chat
|
|
46
|
+
* mid-run gets a "busy" reply rather than starting a competing run. The long run
|
|
47
|
+
* is intentionally NOT sequentialized, which is what makes "busy" reachable.
|
|
48
|
+
*/
|
|
49
|
+
export declare function createTelegramBot(options: CreateTelegramBotOptions): TelegramBotController;
|
|
50
|
+
//# sourceMappingURL=bot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAmB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,GAAG,EAAgB,MAAM,QAAQ,CAAC;AAE3C,OAAO,EAKL,KAAK,cAAc,EAEnB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EAClC,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,YAAY,CAAC;AAOlF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,4BAA4B,CAAC;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IACxC,gEAAgE;IAChE,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,sEAAsE;IACtE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnD,gFAAgF;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC;IAC7C,mFAAmF;IACnF,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,YAAY,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACpC,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,uEAAuE;IACvE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,sDAAsD;IACtD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,qBAAqB,CAyN1F"}
|