@mono-agent/telegram-adapter 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-poller.d.ts","sourceRoot":"","sources":["../src/long-poller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAId,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAC7E;AAED,MAAM,WAAW,gCAAgC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjE,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,gCAAgC,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,EAAE,wBAAwB,CAAC;CACnC;AAED,MAAM,WAAW,8BAA8B;IAC7C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAOD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;IACtD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyD;IACjF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAC9D,OAAO,CAAC,gBAAgB,CAAqB;gBAEjC,OAAO,EAAE,yBAAyB;IAoC9C,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAEK,KAAK,CAAC,OAAO,GAAE,8BAAmC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkClE,QAAQ,CAAC,OAAO,GAAE,6BAAkC,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B5E,OAAO,CAAC,qBAAqB;YAcf,aAAa;CAgB5B"}
@@ -0,0 +1,156 @@
1
+ const DEFAULT_LIMIT = 100;
2
+ const DEFAULT_TIMEOUT_SECONDS = 30;
3
+ const DEFAULT_INITIAL_BACKOFF_MS = 500;
4
+ const DEFAULT_MAX_BACKOFF_MS = 10_000;
5
+ export class TelegramLongPoller {
6
+ api;
7
+ adapter;
8
+ limit;
9
+ timeoutSeconds;
10
+ allowedUpdates;
11
+ deleteWebhookOnStart;
12
+ dropPendingUpdates;
13
+ initialBackoffMs;
14
+ maxBackoffMs;
15
+ onError;
16
+ logger;
17
+ nextUpdateOffset;
18
+ constructor(options) {
19
+ if (options.api === undefined) {
20
+ throw new TypeError("TelegramLongPoller requires a Telegram Bot API client.");
21
+ }
22
+ if (typeof options.adapter?.handleUpdate !== "function") {
23
+ throw new TypeError("TelegramLongPoller requires an adapter with handleUpdate().");
24
+ }
25
+ this.api = options.api;
26
+ this.adapter = options.adapter;
27
+ this.limit = options.limit ?? DEFAULT_LIMIT;
28
+ this.timeoutSeconds = options.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;
29
+ this.allowedUpdates = options.allowedUpdates?.slice();
30
+ this.deleteWebhookOnStart = options.deleteWebhookOnStart === true;
31
+ this.dropPendingUpdates = options.dropPendingUpdates === true;
32
+ this.initialBackoffMs =
33
+ options.backoff?.initialMs ?? DEFAULT_INITIAL_BACKOFF_MS;
34
+ this.maxBackoffMs = options.backoff?.maxMs ?? DEFAULT_MAX_BACKOFF_MS;
35
+ this.onError = options.onError;
36
+ this.logger = options.logger;
37
+ this.nextUpdateOffset = options.initialOffset;
38
+ if (!Number.isInteger(this.limit) || this.limit < 1 || this.limit > 100) {
39
+ throw new RangeError("TelegramLongPoller limit must be an integer between 1 and 100.");
40
+ }
41
+ if (!Number.isFinite(this.timeoutSeconds) || this.timeoutSeconds < 0) {
42
+ throw new RangeError("TelegramLongPoller timeoutSeconds must be non-negative.");
43
+ }
44
+ if (!Number.isFinite(this.initialBackoffMs) || this.initialBackoffMs < 0) {
45
+ throw new RangeError("TelegramLongPoller initial backoff must be non-negative.");
46
+ }
47
+ if (!Number.isFinite(this.maxBackoffMs) || this.maxBackoffMs < this.initialBackoffMs) {
48
+ throw new RangeError("TelegramLongPoller max backoff must be at least the initial backoff.");
49
+ }
50
+ }
51
+ get nextOffset() {
52
+ return this.nextUpdateOffset;
53
+ }
54
+ async start(options = {}) {
55
+ if (isSignalAborted(options.signal)) {
56
+ return;
57
+ }
58
+ if (this.deleteWebhookOnStart) {
59
+ await this.deleteWebhook(options.signal);
60
+ }
61
+ let backoffMs = this.initialBackoffMs;
62
+ while (!isSignalAborted(options.signal)) {
63
+ try {
64
+ const pollOptions = {};
65
+ if (options.signal !== undefined) {
66
+ pollOptions.signal = options.signal;
67
+ }
68
+ await this.pollOnce(pollOptions);
69
+ backoffMs = this.initialBackoffMs;
70
+ }
71
+ catch (error) {
72
+ if (isSignalAborted(options.signal) || isAbortError(error)) {
73
+ return;
74
+ }
75
+ this.logger?.warn?.("Telegram long polling failed; backing off.", {
76
+ error: error instanceof Error ? error.message : String(error),
77
+ backoffMs,
78
+ });
79
+ await this.onError?.(error);
80
+ await abortableDelay(backoffMs, options.signal);
81
+ backoffMs = Math.min(this.maxBackoffMs, Math.max(backoffMs * 2, 1));
82
+ }
83
+ }
84
+ }
85
+ async pollOnce(options = {}) {
86
+ if (isSignalAborted(options.signal)) {
87
+ throw new DOMException("Telegram polling was aborted.", "AbortError");
88
+ }
89
+ const params = this.buildGetUpdatesParams();
90
+ const requestOptions = {};
91
+ if (options.signal !== undefined) {
92
+ requestOptions.signal = options.signal;
93
+ }
94
+ const updates = await this.api.getUpdates(params, requestOptions);
95
+ let handled = 0;
96
+ for (const update of updates) {
97
+ if (isSignalAborted(options.signal)) {
98
+ throw new DOMException("Telegram polling was aborted.", "AbortError");
99
+ }
100
+ await this.adapter.handleUpdate(update);
101
+ this.nextUpdateOffset = update.update_id + 1;
102
+ handled += 1;
103
+ }
104
+ return handled;
105
+ }
106
+ buildGetUpdatesParams() {
107
+ const params = {
108
+ limit: this.limit,
109
+ timeout: this.timeoutSeconds,
110
+ };
111
+ if (this.nextUpdateOffset !== undefined) {
112
+ params.offset = this.nextUpdateOffset;
113
+ }
114
+ if (this.allowedUpdates !== undefined) {
115
+ params.allowed_updates = this.allowedUpdates;
116
+ }
117
+ return params;
118
+ }
119
+ async deleteWebhook(signal) {
120
+ if (typeof this.api.deleteWebhook !== "function") {
121
+ throw new TypeError("TelegramLongPoller deleteWebhookOnStart requires api.deleteWebhook().");
122
+ }
123
+ const params = {
124
+ drop_pending_updates: this.dropPendingUpdates,
125
+ };
126
+ const requestOptions = {};
127
+ if (signal !== undefined) {
128
+ requestOptions.signal = signal;
129
+ }
130
+ await this.api.deleteWebhook(params, requestOptions);
131
+ }
132
+ }
133
+ function isAbortError(error) {
134
+ return (error instanceof DOMException && error.name === "AbortError") || (error instanceof Error && error.name === "AbortError");
135
+ }
136
+ function isSignalAborted(signal) {
137
+ return signal?.aborted === true;
138
+ }
139
+ function abortableDelay(ms, signal) {
140
+ if (ms <= 0 || signal?.aborted === true) {
141
+ return Promise.resolve();
142
+ }
143
+ return new Promise((resolve) => {
144
+ const timeout = setTimeout(() => {
145
+ signal?.removeEventListener("abort", onAbort);
146
+ resolve();
147
+ }, ms);
148
+ const onAbort = () => {
149
+ clearTimeout(timeout);
150
+ signal?.removeEventListener("abort", onAbort);
151
+ resolve();
152
+ };
153
+ signal?.addEventListener("abort", onAbort, { once: true });
154
+ });
155
+ }
156
+ //# sourceMappingURL=long-poller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-poller.js","sourceRoot":"","sources":["../src/long-poller.ts"],"names":[],"mappings":"AA+CA,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AACvC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAEtC,MAAM,OAAO,kBAAkB;IACZ,GAAG,CAAiB;IACpB,OAAO,CAAwB;IAC/B,KAAK,CAAS;IACd,cAAc,CAAS;IACvB,cAAc,CAAuB;IACrC,oBAAoB,CAAU;IAC9B,kBAAkB,CAAU;IAC5B,gBAAgB,CAAS;IACzB,YAAY,CAAS;IACrB,OAAO,CAAyD;IAChE,MAAM,CAAuC;IACtD,gBAAgB,CAAqB;IAE7C,YAAY,OAAkC;QAC5C,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,SAAS,CAAC,wDAAwD,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,OAAO,EAAE,YAAY,KAAK,UAAU,EAAE,CAAC;YACxD,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC;QAC5C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,uBAAuB,CAAC;QACxE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC;QACtD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,KAAK,IAAI,CAAC;QAClE,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,KAAK,IAAI,CAAC;QAC9D,IAAI,CAAC,gBAAgB;YACnB,OAAO,CAAC,OAAO,EAAE,SAAS,IAAI,0BAA0B,CAAC;QAC3D,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,sBAAsB,CAAC;QACrE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;QAE9C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC;YACxE,MAAM,IAAI,UAAU,CAAC,gEAAgE,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,UAAU,CAAC,yDAAyD,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACrF,MAAM,IAAI,UAAU,CAAC,sEAAsE,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,UAA0C,EAAE;QACtD,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACtC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,WAAW,GAAkC,EAAE,CAAC;gBACtD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACjC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;gBACtC,CAAC;gBACD,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBACjC,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3D,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,4CAA4C,EAAE;oBAChE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC7D,SAAS;iBACV,CAAC,CAAC;gBACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;gBAC5B,MAAM,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,UAAyC,EAAE;QACxD,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,YAAY,CAAC,+BAA+B,EAAE,YAAY,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC5C,MAAM,cAAc,GAA2B,EAAE,CAAC;QAClD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAClE,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,YAAY,CAAC,+BAA+B,EAAE,YAAY,CAAC,CAAC;YACxE,CAAC;YAED,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,qBAAqB;QAC3B,MAAM,MAAM,GAA6B;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,cAAc;SAC7B,CAAC;QACF,IAAI,IAAI,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACxC,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC;QAC/C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAA+B;QACzD,IAAI,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;YACjD,MAAM,IAAI,SAAS,CACjB,uEAAuE,CACxE,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAgC;YAC1C,oBAAoB,EAAE,IAAI,CAAC,kBAAkB;SAC9C,CAAC;QACF,MAAM,cAAc,GAA2B,EAAE,CAAC;QAClD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC;QACjC,CAAC;QACD,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvD,CAAC;CACF;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,CACL,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAC7D,IAAI,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,eAAe,CAAC,MAA+B;IACtD,OAAO,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;AAClC,CAAC;AAED,SAAS,cAAc,CACrB,EAAU,EACV,MAA+B;IAE/B,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QACxC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { AgentMessageStream as AgentMessageStreamBase } from "@mono-agent/agent-contracts";
2
+ import type { TelegramBotApi, TelegramChatId } from "./types.js";
3
+ export interface AgentMessageStream extends AgentMessageStreamBase {
4
+ status(text: string): Promise<void>;
5
+ append(delta: string): Promise<void>;
6
+ replace(text: string): Promise<void>;
7
+ finish(finalText?: string): Promise<void>;
8
+ }
9
+ export interface TelegramMessageStreamOptions {
10
+ api: TelegramBotApi;
11
+ chatId: TelegramChatId;
12
+ initialStatusText?: string;
13
+ editDebounceMs?: number;
14
+ maxMessageChars?: number;
15
+ replyToMessageId?: number;
16
+ logger?: TelegramMessageStreamLogger;
17
+ }
18
+ export interface TelegramMessageStreamLogger {
19
+ debug?(message: string, metadata?: Record<string, unknown>): void;
20
+ warn?(message: string, metadata?: Record<string, unknown>): void;
21
+ error?(message: string, metadata?: Record<string, unknown>): void;
22
+ }
23
+ export declare class TelegramMessageStream implements AgentMessageStream {
24
+ private readonly api;
25
+ private readonly chatId;
26
+ private readonly initialStatusText;
27
+ private readonly editDebounceMs;
28
+ private readonly maxMessageChars;
29
+ private readonly replyToMessageId;
30
+ private readonly logger;
31
+ private currentText;
32
+ private statusText;
33
+ private sentMessage;
34
+ private sendMessagePromise;
35
+ private editTimer;
36
+ private inFlightEdit;
37
+ private lastAsyncError;
38
+ private finished;
39
+ constructor(options: TelegramMessageStreamOptions);
40
+ status(text: string): Promise<void>;
41
+ append(delta: string): Promise<void>;
42
+ replace(text: string): Promise<void>;
43
+ finish(finalText?: string): Promise<void>;
44
+ private ensureMessage;
45
+ private scheduleEdit;
46
+ private startInFlightEdit;
47
+ private flushEdit;
48
+ private cancelScheduledEdit;
49
+ private awaitInFlightEdit;
50
+ private throwIfAsyncError;
51
+ private assertOpen;
52
+ }
53
+ export declare function splitTelegramText(text: string, maxChars: number): string[];
54
+ //# sourceMappingURL=message-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-stream.d.ts","sourceRoot":"","sources":["../src/message-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAQhG,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IAChE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,2BAA2B,CAAC;CACtC;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClE,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjE,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACnE;AAMD,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0C;IAEjE,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,kBAAkB,CAA2C;IACrE,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAS;gBAEb,OAAO,EAAE,4BAA4B;IAoB3C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAyBjC,aAAa;IAyB3B,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,iBAAiB;YAYX,SAAS;IASvB,OAAO,CAAC,mBAAmB;YAOb,iBAAiB;YAOjB,iBAAiB;IAY/B,OAAO,CAAC,UAAU;CAKnB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1E"}
@@ -0,0 +1,168 @@
1
+ import { DEFAULT_EMPTY_FINAL_TEXT, DEFAULT_MAX_MESSAGE_CHARS, buildStreamingTailPreview, normalizeTrailing, splitTextByCodePoints, } from "@mono-agent/agent-contracts";
2
+ const DEFAULT_INITIAL_STATUS_TEXT = "Thinking…";
3
+ const DEFAULT_EDIT_DEBOUNCE_MS = 750;
4
+ const EMPTY_FINAL_TEXT = DEFAULT_EMPTY_FINAL_TEXT;
5
+ export class TelegramMessageStream {
6
+ api;
7
+ chatId;
8
+ initialStatusText;
9
+ editDebounceMs;
10
+ maxMessageChars;
11
+ replyToMessageId;
12
+ logger;
13
+ currentText = "";
14
+ statusText;
15
+ sentMessage;
16
+ sendMessagePromise;
17
+ editTimer;
18
+ inFlightEdit;
19
+ lastAsyncError;
20
+ finished = false;
21
+ constructor(options) {
22
+ this.api = options.api;
23
+ this.chatId = options.chatId;
24
+ this.initialStatusText = normalizeTelegramText(options.initialStatusText ?? DEFAULT_INITIAL_STATUS_TEXT);
25
+ this.statusText = this.initialStatusText;
26
+ this.editDebounceMs = options.editDebounceMs ?? DEFAULT_EDIT_DEBOUNCE_MS;
27
+ this.maxMessageChars = options.maxMessageChars ?? DEFAULT_MAX_MESSAGE_CHARS;
28
+ this.replyToMessageId = options.replyToMessageId;
29
+ this.logger = options.logger;
30
+ if (!Number.isInteger(this.maxMessageChars) || this.maxMessageChars < 32) {
31
+ throw new RangeError("maxMessageChars must be an integer of at least 32.");
32
+ }
33
+ if (!Number.isFinite(this.editDebounceMs) || this.editDebounceMs < 0) {
34
+ throw new RangeError("editDebounceMs must be a non-negative number.");
35
+ }
36
+ }
37
+ async status(text) {
38
+ this.assertOpen();
39
+ await this.throwIfAsyncError();
40
+ this.statusText = normalizeTelegramText(text);
41
+ const hadMessage = this.sentMessage !== undefined;
42
+ await this.ensureMessage();
43
+ if (hadMessage) {
44
+ await this.flushEdit(this.statusText);
45
+ }
46
+ }
47
+ async append(delta) {
48
+ this.assertOpen();
49
+ await this.throwIfAsyncError();
50
+ if (delta.length === 0) {
51
+ return;
52
+ }
53
+ this.currentText += delta;
54
+ await this.ensureMessage();
55
+ this.scheduleEdit();
56
+ }
57
+ async replace(text) {
58
+ this.assertOpen();
59
+ await this.throwIfAsyncError();
60
+ this.currentText = text;
61
+ await this.ensureMessage();
62
+ this.scheduleEdit();
63
+ }
64
+ async finish(finalText) {
65
+ if (this.finished) {
66
+ return;
67
+ }
68
+ this.finished = true;
69
+ if (finalText !== undefined) {
70
+ this.currentText = finalText;
71
+ }
72
+ this.cancelScheduledEdit();
73
+ await this.throwIfAsyncError();
74
+ await this.awaitInFlightEdit();
75
+ await this.throwIfAsyncError();
76
+ const chunks = splitTelegramText(this.currentText, this.maxMessageChars);
77
+ const [firstChunk, ...remainingChunks] = chunks;
78
+ await this.ensureMessage();
79
+ await this.flushEdit(firstChunk ?? EMPTY_FINAL_TEXT);
80
+ for (const chunk of remainingChunks) {
81
+ await this.api.sendMessage({ chat_id: this.chatId, text: chunk });
82
+ }
83
+ }
84
+ async ensureMessage() {
85
+ if (this.sentMessage !== undefined) {
86
+ return this.sentMessage;
87
+ }
88
+ if (this.sendMessagePromise === undefined) {
89
+ const params = {
90
+ chat_id: this.chatId,
91
+ text: this.statusText,
92
+ };
93
+ if (this.replyToMessageId !== undefined) {
94
+ params.reply_to_message_id = this.replyToMessageId;
95
+ }
96
+ this.sendMessagePromise = this.api.sendMessage(params);
97
+ }
98
+ this.sentMessage = await this.sendMessagePromise;
99
+ return this.sentMessage;
100
+ }
101
+ scheduleEdit() {
102
+ this.cancelScheduledEdit();
103
+ if (this.editDebounceMs === 0) {
104
+ this.startInFlightEdit();
105
+ return;
106
+ }
107
+ this.editTimer = setTimeout(() => {
108
+ this.editTimer = undefined;
109
+ this.startInFlightEdit();
110
+ }, this.editDebounceMs);
111
+ }
112
+ startInFlightEdit() {
113
+ const text = buildStreamingPreview(this.currentText, this.maxMessageChars);
114
+ this.inFlightEdit = this.flushEdit(text).catch((error) => {
115
+ this.lastAsyncError = error;
116
+ this.logger?.error?.("Telegram stream edit failed.", {
117
+ error: error instanceof Error ? error.message : String(error),
118
+ });
119
+ throw error;
120
+ });
121
+ void this.inFlightEdit.catch(() => undefined);
122
+ }
123
+ async flushEdit(text) {
124
+ const message = await this.ensureMessage();
125
+ await this.api.editMessageText({
126
+ chat_id: this.chatId,
127
+ message_id: message.message_id,
128
+ text: normalizeTelegramText(text),
129
+ });
130
+ }
131
+ cancelScheduledEdit() {
132
+ if (this.editTimer !== undefined) {
133
+ clearTimeout(this.editTimer);
134
+ this.editTimer = undefined;
135
+ }
136
+ }
137
+ async awaitInFlightEdit() {
138
+ if (this.inFlightEdit !== undefined) {
139
+ await this.inFlightEdit;
140
+ this.inFlightEdit = undefined;
141
+ }
142
+ }
143
+ async throwIfAsyncError() {
144
+ if (this.inFlightEdit !== undefined) {
145
+ await this.awaitInFlightEdit();
146
+ }
147
+ if (this.lastAsyncError !== undefined) {
148
+ const error = this.lastAsyncError;
149
+ this.lastAsyncError = undefined;
150
+ throw error;
151
+ }
152
+ }
153
+ assertOpen() {
154
+ if (this.finished) {
155
+ throw new Error("Cannot write to a finished TelegramMessageStream.");
156
+ }
157
+ }
158
+ }
159
+ export function splitTelegramText(text, maxChars) {
160
+ return splitTextByCodePoints(normalizeTrailing(text, EMPTY_FINAL_TEXT), maxChars);
161
+ }
162
+ function buildStreamingPreview(text, maxChars) {
163
+ return buildStreamingTailPreview(normalizeTrailing(text, EMPTY_FINAL_TEXT), maxChars, "…\n");
164
+ }
165
+ function normalizeTelegramText(text) {
166
+ return text.trimEnd();
167
+ }
168
+ //# sourceMappingURL=message-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-stream.js","sourceRoot":"","sources":["../src/message-stream.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { type AgentResponder, type TelegramAdapterLogger, type TelegramAdapterMessages, type TelegramAdapterStreamOptions } from "./adapter.js";
2
+ import { type TelegramLongPollerOptions, type TelegramLongPollerStartOptions } from "./long-poller.js";
3
+ import { type TelegramBotApiClientOptions } from "./telegram-client.js";
4
+ import type { TelegramBotApi, TelegramChatId } from "./types.js";
5
+ /**
6
+ * Minimal surface a long poller must expose for {@link startTelegramAdapter} to
7
+ * drive it. The real {@link TelegramLongPoller} satisfies this, and tests can
8
+ * supply a fake via {@link TelegramAdapterStartOptions.pollerFactory}.
9
+ */
10
+ export interface TelegramPollerLike {
11
+ start(options?: TelegramLongPollerStartOptions): Promise<void>;
12
+ }
13
+ export interface TelegramAdapterStartOptions {
14
+ /** Bot API token, used to construct the default {@link TelegramBotApiClient}. */
15
+ readonly botToken: string;
16
+ /** Allowlisted chat ids. Required unless {@link allowAllChats} is true. */
17
+ readonly allowedChatIds?: readonly TelegramChatId[];
18
+ /** Explicitly permit every chat. Leave off when using an allowlist. */
19
+ readonly allowAllChats?: boolean;
20
+ /** Responder the adapter routes authorized text updates to. */
21
+ readonly responder: AgentResponder;
22
+ /** Optional per-response stream tuning forwarded to the adapter. */
23
+ readonly stream?: TelegramAdapterStreamOptions;
24
+ /** Optional message-copy overrides forwarded to the adapter. */
25
+ readonly messages?: TelegramAdapterMessages;
26
+ /** Optional logger shared by the adapter, stream, and poller. */
27
+ readonly logger?: TelegramAdapterLogger;
28
+ /** Restrict the update types requested from Telegram. Defaults to messages only. */
29
+ readonly allowedUpdates?: readonly string[];
30
+ /** Delete any configured webhook before polling. Defaults to true. */
31
+ readonly deleteWebhookOnStart?: boolean;
32
+ /**
33
+ * Override how the {@link TelegramBotApi} client is built. Defaults to a real
34
+ * {@link TelegramBotApiClient}. Tests inject a fake to avoid hitting Telegram.
35
+ */
36
+ readonly clientFactory?: (options: TelegramBotApiClientOptions) => TelegramBotApi;
37
+ /**
38
+ * Override how the long poller is built. Defaults to a real
39
+ * {@link TelegramLongPoller}. Tests inject a fake to assert wiring and stop.
40
+ */
41
+ readonly pollerFactory?: (options: TelegramLongPollerOptions) => TelegramPollerLike;
42
+ }
43
+ export interface TelegramAdapterStartResult {
44
+ /** Stops the long poller cleanly and waits for the polling loop to settle. */
45
+ stop(): Promise<void>;
46
+ }
47
+ /**
48
+ * Composition-root entrypoint: builds the Telegram client, adapter, and long
49
+ * poller from a single options bag and starts polling. Mirrors the HTTP
50
+ * adapters' `startX(options): Promise<{ stop }>` shape so a host can launch
51
+ * Telegram with one call.
52
+ *
53
+ * Fail-closed: the underlying {@link TelegramAdapter} throws when neither
54
+ * {@link TelegramAdapterStartOptions.allowedChatIds} nor
55
+ * {@link TelegramAdapterStartOptions.allowAllChats} is provided.
56
+ */
57
+ export declare function startTelegramAdapter(options: TelegramAdapterStartOptions): Promise<TelegramAdapterStartResult>;
58
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EAClC,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACpC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,OAAO,CAAC,EAAE,8BAA8B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,2BAA2B;IAC1C,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACpD,uEAAuE;IACvE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,4BAA4B,CAAC;IAC/C,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IAC5C,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IACxC,oFAAoF;IACpF,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,sEAAsE;IACtE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,cAAc,CAAC;IAClF;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,kBAAkB,CAAC;CACrF;AAED,MAAM,WAAW,0BAA0B;IACzC,8EAA8E;IAC9E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CA+CrC"}
package/dist/start.js ADDED
@@ -0,0 +1,57 @@
1
+ import { TelegramAdapter, } from "./adapter.js";
2
+ import { TelegramLongPoller, } from "./long-poller.js";
3
+ import { TelegramBotApiClient, } from "./telegram-client.js";
4
+ /**
5
+ * Composition-root entrypoint: builds the Telegram client, adapter, and long
6
+ * poller from a single options bag and starts polling. Mirrors the HTTP
7
+ * adapters' `startX(options): Promise<{ stop }>` shape so a host can launch
8
+ * Telegram with one call.
9
+ *
10
+ * Fail-closed: the underlying {@link TelegramAdapter} throws when neither
11
+ * {@link TelegramAdapterStartOptions.allowedChatIds} nor
12
+ * {@link TelegramAdapterStartOptions.allowAllChats} is provided.
13
+ */
14
+ export async function startTelegramAdapter(options) {
15
+ const buildClient = options.clientFactory ?? ((clientOptions) => new TelegramBotApiClient(clientOptions));
16
+ const buildPoller = options.pollerFactory ?? ((pollerOptions) => new TelegramLongPoller(pollerOptions));
17
+ const api = buildClient({ token: options.botToken });
18
+ const adapter = new TelegramAdapter({
19
+ api,
20
+ responder: options.responder,
21
+ ...(options.allowedChatIds === undefined ? {} : { allowedChatIds: [...options.allowedChatIds] }),
22
+ ...(options.allowAllChats === undefined ? {} : { allowAllChats: options.allowAllChats }),
23
+ ...(options.stream === undefined ? {} : { stream: options.stream }),
24
+ ...(options.messages === undefined ? {} : { messages: options.messages }),
25
+ ...(options.logger === undefined ? {} : { logger: options.logger }),
26
+ });
27
+ const poller = buildPoller({
28
+ api,
29
+ adapter,
30
+ deleteWebhookOnStart: options.deleteWebhookOnStart ?? true,
31
+ allowedUpdates: options.allowedUpdates === undefined ? ["message"] : [...options.allowedUpdates],
32
+ ...(options.logger === undefined ? {} : { logger: options.logger }),
33
+ });
34
+ const controller = new AbortController();
35
+ const running = poller.start({ signal: controller.signal });
36
+ // Surface late polling failures to the shared logger without leaving an
37
+ // unhandled rejection; stop() still awaits this same promise.
38
+ running.catch((error) => {
39
+ if (!controller.signal.aborted) {
40
+ options.logger?.error?.("Telegram polling stopped with an error.", {
41
+ error: error instanceof Error ? error.message : String(error),
42
+ });
43
+ }
44
+ });
45
+ let stopped = false;
46
+ return {
47
+ async stop() {
48
+ if (stopped) {
49
+ return;
50
+ }
51
+ stopped = true;
52
+ controller.abort();
53
+ await running.catch(() => undefined);
54
+ },
55
+ };
56
+ }
57
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../src/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { TelegramBotApi, TelegramDeleteWebhookParams, TelegramEditMessageTextParams, TelegramGetUpdatesParams, TelegramRequestOptions, TelegramSendMessageParams, TelegramSentMessage, TelegramUpdate } from "./types.js";
2
+ export type TelegramApiErrorKind = "http" | "telegram" | "malformed" | "network" | "aborted";
3
+ export interface TelegramApiErrorDetails {
4
+ kind: TelegramApiErrorKind;
5
+ method: string;
6
+ status?: number;
7
+ errorCode?: number;
8
+ telegramDescription?: string;
9
+ cause?: unknown;
10
+ }
11
+ export declare class TelegramApiError extends Error {
12
+ readonly kind: TelegramApiErrorKind;
13
+ readonly method: string;
14
+ readonly status?: number;
15
+ readonly errorCode?: number;
16
+ readonly telegramDescription?: string;
17
+ readonly cause?: unknown;
18
+ constructor(message: string, details: TelegramApiErrorDetails);
19
+ }
20
+ export interface TelegramBotApiClientOptions {
21
+ token: string;
22
+ apiBaseUrl?: string;
23
+ fetchImpl?: typeof fetch;
24
+ requestTimeoutMs?: number;
25
+ }
26
+ export declare class TelegramBotApiClient implements TelegramBotApi {
27
+ private readonly token;
28
+ private readonly apiBaseUrl;
29
+ private readonly fetchImpl;
30
+ private readonly requestTimeoutMs;
31
+ constructor(options: TelegramBotApiClientOptions);
32
+ sendMessage(params: TelegramSendMessageParams, options?: TelegramRequestOptions): Promise<TelegramSentMessage>;
33
+ editMessageText(params: TelegramEditMessageTextParams, options?: TelegramRequestOptions): Promise<TelegramSentMessage | true>;
34
+ getUpdates(params: TelegramGetUpdatesParams, options?: TelegramRequestOptions): Promise<TelegramUpdate[]>;
35
+ deleteWebhook(params?: TelegramDeleteWebhookParams, options?: TelegramRequestOptions): Promise<true>;
36
+ private request;
37
+ }
38
+ //# sourceMappingURL=telegram-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-client.d.ts","sourceRoot":"","sources":["../src/telegram-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,EACxB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACnB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,UAAU,GACV,WAAW,GACX,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,uBAAuB;CAkB9D;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkBD,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,OAAO,EAAE,2BAA2B;IAsBhD,WAAW,CACT,MAAM,EAAE,yBAAyB,EACjC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,mBAAmB,CAAC;IAI/B,eAAe,CACb,MAAM,EAAE,6BAA6B,EACrC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQtC,UAAU,CACR,MAAM,EAAE,wBAAwB,EAChC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,cAAc,EAAE,CAAC;IAI5B,aAAa,CACX,MAAM,GAAE,2BAAgC,EACxC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,IAAI,CAAC;YAIF,OAAO;CAiFtB"}