@wrongstack/telegram 0.287.0 → 0.291.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.
- package/README.md +24 -18
- package/dist/api-client.d.ts +119 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/bot-queue.d.ts +27 -0
- package/dist/bot-queue.d.ts.map +1 -0
- package/dist/bot.d.ts +50 -67
- package/dist/bot.d.ts.map +1 -1
- package/dist/config-classifier.d.ts +64 -0
- package/dist/config-classifier.d.ts.map +1 -0
- package/dist/config.d.ts +45 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/inbox-cursor-store.d.ts +54 -0
- package/dist/inbox-cursor-store.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1254 -415
- package/dist/index.js.map +4 -4
- package/dist/offset-store.d.ts +40 -0
- package/dist/offset-store.d.ts.map +1 -0
- package/dist/outbound-queue.d.ts +52 -0
- package/dist/outbound-queue.d.ts.map +1 -0
- package/dist/security/outbound.d.ts +25 -0
- package/dist/security/outbound.d.ts.map +1 -0
- package/dist/slash-commands/index.d.ts +8 -2
- package/dist/slash-commands/index.d.ts.map +1 -1
- package/dist/tools/telegram-approve.d.ts +15 -3
- package/dist/tools/telegram-approve.d.ts.map +1 -1
- package/dist/tools/telegram-send.d.ts +6 -4
- package/dist/tools/telegram-send.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Send messages, receive instructions, get notified when long tasks finish.
|
|
|
7
7
|
|
|
8
8
|
- **`telegram_read`** — Agent reads incoming Telegram messages (newest first, filtered by chat, with ack support)
|
|
9
9
|
- **`telegram_send`** — Agent sends messages via Telegram (HTML formatting, confirm permission)
|
|
10
|
-
- **
|
|
10
|
+
- **Metadata-only inbox notice** — The system prompt reports only an unread count; message content stays behind the explicit `telegram_read` tool boundary
|
|
11
11
|
- **Slash commands** — `/telegram`, `/telegram-health`, `/telegram:send`, `/telegram:chatid` in the TUI
|
|
12
12
|
- **Event notifications** — Session end summaries and long tool completions forwarded to Telegram
|
|
13
13
|
- **Allowlist filtering** — Restrict which users/chats can interact with the bot
|
|
@@ -24,16 +24,7 @@ Message [@BotFather](https://t.me/BotFather) on Telegram:
|
|
|
24
24
|
|
|
25
25
|
Copy the token (looks like `123456789:ABCdef...`).
|
|
26
26
|
|
|
27
|
-
### 2.
|
|
28
|
-
|
|
29
|
-
Message your new bot, then visit:
|
|
30
|
-
```
|
|
31
|
-
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Find your `chat.id` in the response.
|
|
35
|
-
|
|
36
|
-
### 3. Enable the official plugin
|
|
27
|
+
### 2. Enable the official plugin
|
|
37
28
|
|
|
38
29
|
```bash
|
|
39
30
|
wstack plugin install telegram
|
|
@@ -51,9 +42,17 @@ CLI package, add it like a normal public package:
|
|
|
51
42
|
npm install @wrongstack/telegram
|
|
52
43
|
```
|
|
53
44
|
|
|
54
|
-
###
|
|
45
|
+
### 3. Pair a private chat securely
|
|
46
|
+
|
|
47
|
+
Run `/telegram-setup` in WrongStack. Enter the bot token in the masked prompt,
|
|
48
|
+
message the bot once from the private Telegram account you want to pair, then
|
|
49
|
+
explicitly select that discovered identity. WrongStack does not print or ask
|
|
50
|
+
you to open a credential-bearing Bot API URL.
|
|
51
|
+
|
|
52
|
+
### 4. Configure manually (optional)
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
The setup command writes this configuration securely. For custom hosts, the
|
|
55
|
+
equivalent shape in `~/.wrongstack/config.json` or `.wrongstack/config.json` is:
|
|
57
56
|
|
|
58
57
|
```jsonc
|
|
59
58
|
{
|
|
@@ -65,7 +64,10 @@ In `~/.wrongstack/config.json` or `.wrongstack/config.json`:
|
|
|
65
64
|
"telegram": {
|
|
66
65
|
"botToken": "123456789:ABCdefGHIjkl...",
|
|
67
66
|
"notifyChatId": "987654321",
|
|
67
|
+
"inboundMode": "paired",
|
|
68
68
|
"allowedUsers": [987654321],
|
|
69
|
+
"allowedChats": [987654321],
|
|
70
|
+
"allowedOutboundChats": [987654321],
|
|
69
71
|
"notifyOnSessionEnd": true,
|
|
70
72
|
"longToolThresholdMs": 30000,
|
|
71
73
|
"pollIntervalSec": 2
|
|
@@ -87,9 +89,13 @@ the Telegram options.
|
|
|
87
89
|
| Field | Type | Required | Default | Description |
|
|
88
90
|
|---|---|---|---|---|
|
|
89
91
|
| `botToken` | `string` | **yes** | — | Bot token from @BotFather |
|
|
90
|
-
| `notifyChatId` | `string \| number` | no | — | Default chat for outgoing messages and notifications |
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
92
|
+
| `notifyChatId` | `string \| number` | no | — | Default chat for outgoing messages and notifications; it is also the paired chat when `inboundMode` is `paired` |
|
|
93
|
+
| `inboundMode` | `disabled \| paired \| allowlist \| public` | no | `disabled` | Inbound authorization policy. `public` must be selected explicitly. |
|
|
94
|
+
| `allowedUsers` | `(string \| number)[]` | no | `[]` | Immutable user IDs accepted by paired/allowlist authorization and remote approvals |
|
|
95
|
+
| `allowedChats` | `(string \| number)[]` | no | `[]` | Chat IDs accepted when `inboundMode` is `allowlist` |
|
|
96
|
+
| `allowedOutboundChats` | `(string \| number)[]` | no | `[]` | Additional explicitly trusted outbound targets beyond `notifyChatId` |
|
|
97
|
+
| `allowGroupChats` | `boolean` | no | `false` | Let `/telegram-settings chat` select a negative group/channel ID as an outbound-only target |
|
|
98
|
+
| `allowGroupApprovals` | `boolean` | no | `false` | Permit approvals in a group target; still requires explicit `allowedUsers` identity binding |
|
|
93
99
|
| `pollIntervalSec` | `number` | no | `2` | How often to poll Telegram for new messages (1–60) |
|
|
94
100
|
| `notifyOnSessionEnd` | `boolean` | no | `false` | Send token usage summary when a session ends |
|
|
95
101
|
| `longToolThresholdMs` | `number` | no | `30000` | Notify when a tool runs longer than this (ms). `0` = off |
|
|
@@ -163,8 +169,8 @@ Message text supports Telegram HTML: `<b>bold</b>`, `<i>italic</i>`, `<code>mono
|
|
|
163
169
|
|
|
164
170
|
1. Bot polls Telegram every N seconds via `getUpdates`
|
|
165
171
|
2. Incoming messages go into a circular buffer (50 max)
|
|
166
|
-
3. A system prompt contributor
|
|
167
|
-
4. Agent reads with `telegram_read`, responds with `telegram_send`
|
|
172
|
+
3. A system prompt contributor exposes only the bounded unread count
|
|
173
|
+
4. Agent explicitly reads content with `telegram_read`, then responds with `telegram_send`
|
|
168
174
|
5. Custom event `telegram:message_received` fires for TUI panels / other plugins
|
|
169
175
|
|
|
170
176
|
## Events
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export interface TelegramApiUser {
|
|
2
|
+
id: number;
|
|
3
|
+
is_bot: boolean;
|
|
4
|
+
first_name: string;
|
|
5
|
+
username?: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export type TelegramApiChatType = 'private' | 'group' | 'supergroup' | 'channel';
|
|
8
|
+
export interface TelegramApiChat {
|
|
9
|
+
id: number;
|
|
10
|
+
type: TelegramApiChatType;
|
|
11
|
+
title?: string | undefined;
|
|
12
|
+
username?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
export interface TelegramApiMessage {
|
|
15
|
+
message_id: number;
|
|
16
|
+
from?: TelegramApiUser | undefined;
|
|
17
|
+
chat: TelegramApiChat;
|
|
18
|
+
date: number;
|
|
19
|
+
text?: string | undefined;
|
|
20
|
+
}
|
|
21
|
+
export interface TelegramApiCallbackQuery {
|
|
22
|
+
id: string;
|
|
23
|
+
from?: TelegramApiUser | undefined;
|
|
24
|
+
message?: {
|
|
25
|
+
message_id: number;
|
|
26
|
+
chat: TelegramApiChat;
|
|
27
|
+
} | undefined;
|
|
28
|
+
data?: string | undefined;
|
|
29
|
+
}
|
|
30
|
+
export interface TelegramApiUpdate {
|
|
31
|
+
update_id: number;
|
|
32
|
+
message?: TelegramApiMessage | undefined;
|
|
33
|
+
edited_message?: TelegramApiMessage | undefined;
|
|
34
|
+
callback_query?: TelegramApiCallbackQuery | undefined;
|
|
35
|
+
}
|
|
36
|
+
export interface TelegramInlineKeyboardButton {
|
|
37
|
+
text: string;
|
|
38
|
+
callback_data: string;
|
|
39
|
+
}
|
|
40
|
+
export type TelegramApiClientErrorKind = 'network' | 'http' | 'parse' | 'api';
|
|
41
|
+
export declare abstract class TelegramApiClientError extends Error {
|
|
42
|
+
readonly kind: TelegramApiClientErrorKind;
|
|
43
|
+
readonly method: string;
|
|
44
|
+
protected constructor(kind: TelegramApiClientErrorKind, method: string, message: string);
|
|
45
|
+
}
|
|
46
|
+
export declare class TelegramNetworkError extends TelegramApiClientError {
|
|
47
|
+
readonly detail: string;
|
|
48
|
+
readonly aborted: boolean;
|
|
49
|
+
constructor(method: string, detail: string, aborted?: boolean);
|
|
50
|
+
}
|
|
51
|
+
export declare class TelegramHttpError extends TelegramApiClientError {
|
|
52
|
+
readonly status: number;
|
|
53
|
+
constructor(method: string, status: number, statusText?: string | undefined);
|
|
54
|
+
}
|
|
55
|
+
export declare class TelegramResponseParseError extends TelegramApiClientError {
|
|
56
|
+
constructor(method: string, detail: string);
|
|
57
|
+
}
|
|
58
|
+
export declare class TelegramBotApiError extends TelegramApiClientError {
|
|
59
|
+
readonly errorCode?: number | undefined;
|
|
60
|
+
readonly httpStatus?: number | undefined;
|
|
61
|
+
readonly description: string;
|
|
62
|
+
readonly retryAfterSeconds?: number | undefined;
|
|
63
|
+
readonly migrateToChatId?: number | undefined;
|
|
64
|
+
constructor(method: string, opts: {
|
|
65
|
+
errorCode?: number | undefined;
|
|
66
|
+
httpStatus?: number | undefined;
|
|
67
|
+
description: string;
|
|
68
|
+
retryAfterSeconds?: number | undefined;
|
|
69
|
+
migrateToChatId?: number | undefined;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export interface RetryDecision {
|
|
73
|
+
/** Whether to retry the request. */
|
|
74
|
+
retry: boolean;
|
|
75
|
+
/** Milliseconds to wait before retrying. 0 when retry is false. */
|
|
76
|
+
delayMs: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Classify a caught error and decide whether to retry, and how long to wait.
|
|
80
|
+
* @param err The error thrown by api-client methods.
|
|
81
|
+
* @param attempt 1-based attempt counter.
|
|
82
|
+
* @returns A RetryDecision.
|
|
83
|
+
*/
|
|
84
|
+
export declare function classifyRetry(err: unknown, attempt: number): RetryDecision;
|
|
85
|
+
type TelegramFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
86
|
+
export interface TelegramApiClientOptions {
|
|
87
|
+
token: string;
|
|
88
|
+
/** Override used by deterministic tests or Bot API proxies. */
|
|
89
|
+
apiRoot?: string | undefined;
|
|
90
|
+
/** Optional transport injection. Defaults to globalThis.fetch at call time. */
|
|
91
|
+
fetch?: TelegramFetch | undefined;
|
|
92
|
+
}
|
|
93
|
+
export interface TelegramRequestOptions {
|
|
94
|
+
signal?: AbortSignal | undefined;
|
|
95
|
+
}
|
|
96
|
+
export interface TelegramGetUpdatesOptions extends TelegramRequestOptions {
|
|
97
|
+
deadlineMs?: number | undefined;
|
|
98
|
+
offset: number;
|
|
99
|
+
timeoutSeconds: number;
|
|
100
|
+
}
|
|
101
|
+
/** Build the one canonical, token-bearing Bot API base URL. Never log this value. */
|
|
102
|
+
export declare function buildTelegramBotApiBaseUrl(token: string, apiRoot?: string): string;
|
|
103
|
+
export declare function abortableSleep(ms: number, signal?: AbortSignal | undefined): Promise<void>;
|
|
104
|
+
export declare class TelegramApiClient {
|
|
105
|
+
readonly safeBaseUrl: string;
|
|
106
|
+
private readonly token;
|
|
107
|
+
private readonly baseUrl;
|
|
108
|
+
private readonly fetchOverride?;
|
|
109
|
+
constructor(opts: TelegramApiClientOptions);
|
|
110
|
+
getMe(opts?: TelegramRequestOptions): Promise<TelegramApiUser>;
|
|
111
|
+
getUpdates(opts: TelegramGetUpdatesOptions): Promise<TelegramApiUpdate[]>;
|
|
112
|
+
sendMessage(chatId: string | number, text: string, opts?: TelegramRequestOptions): Promise<TelegramApiMessage>;
|
|
113
|
+
sendMessageWithKeyboard(chatId: string | number, text: string, buttons: readonly TelegramInlineKeyboardButton[], opts?: TelegramRequestOptions): Promise<TelegramApiMessage>;
|
|
114
|
+
answerCallbackQuery(callbackQueryId: string, text: string, showAlert: boolean, opts?: TelegramRequestOptions): Promise<boolean>;
|
|
115
|
+
private request;
|
|
116
|
+
private redact;
|
|
117
|
+
}
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Logger } from '@wrongstack/core';
|
|
2
|
+
import type { TelegramApiMessage } from './api-client.js';
|
|
3
|
+
import type { TelegramBot, TelegramBotResponse } from './bot.js';
|
|
4
|
+
export interface BotOutboundOptions {
|
|
5
|
+
readonly bot: TelegramBot;
|
|
6
|
+
/** Pass-through logger (defaults to bot's internal logger via the bot's debug hook). */
|
|
7
|
+
readonly log: Logger;
|
|
8
|
+
/** Optional override; defaults to 32 entries per chat. */
|
|
9
|
+
readonly maxPerChat?: number;
|
|
10
|
+
/** Optional override; defaults to 4 concurrent sends. */
|
|
11
|
+
readonly maxConcurrency?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class TelegramBotOutbound {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(opts: BotOutboundOptions);
|
|
16
|
+
/** Manual send (telegram_send tool, /telegram:send): never silently dropped. */
|
|
17
|
+
sendManual(chatId: string | number, text: string): Promise<TelegramBotResponse<TelegramApiMessage>>;
|
|
18
|
+
/**
|
|
19
|
+
* Notification send (session ended, long tool, delegate): fire-and-forget.
|
|
20
|
+
* The returned promise resolves as soon as the queue accepts the entry;
|
|
21
|
+
* downstream send failures are logged and counted but not surfaced.
|
|
22
|
+
*/
|
|
23
|
+
enqueueNotification(chatId: string | number, text: string): void;
|
|
24
|
+
stats(): import("./outbound-queue.js").OutboundQueueStats;
|
|
25
|
+
stop(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=bot-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-queue.d.ts","sourceRoot":"","sources":["../src/bot-queue.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGjE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,wFAAwF;IACxF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,mBAAmB;;IAM9B,YAAY,IAAI,EAAE,kBAAkB,EAenC;IAED,gFAAgF;IAC1E,UAAU,CACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,CASlD;IAED;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAW/D;IAED,KAAK,qDAEJ;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1B;CACF"}
|
package/dist/bot.d.ts
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
1
|
import type { Logger } from '@wrongstack/core';
|
|
2
|
+
import { type TelegramApiMessage } from './api-client.js';
|
|
3
|
+
import type { OffsetStore } from './offset-store.js';
|
|
2
4
|
import type { PollLock } from './poll-lock.js';
|
|
3
|
-
interface
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
first_name: string;
|
|
7
|
-
username?: string | undefined;
|
|
8
|
-
}
|
|
9
|
-
interface TgChat {
|
|
10
|
-
id: number;
|
|
11
|
-
type: 'private' | 'group' | 'supergroup' | 'channel';
|
|
12
|
-
title?: string | undefined;
|
|
13
|
-
username?: string | undefined;
|
|
14
|
-
}
|
|
15
|
-
interface TgMessage {
|
|
16
|
-
message_id: number;
|
|
17
|
-
from?: TgUser | undefined;
|
|
18
|
-
chat: TgChat;
|
|
19
|
-
date: number;
|
|
20
|
-
text?: string | undefined;
|
|
21
|
-
}
|
|
22
|
-
interface TgResponse<T> {
|
|
23
|
-
ok: boolean;
|
|
24
|
-
result?: T | undefined;
|
|
25
|
-
description?: string | undefined;
|
|
26
|
-
error_code?: number | undefined;
|
|
5
|
+
export interface TelegramBotResponse<T> {
|
|
6
|
+
ok: true;
|
|
7
|
+
result: T;
|
|
27
8
|
}
|
|
28
9
|
export interface TelegramIncomingMessage {
|
|
29
10
|
messageId: number;
|
|
@@ -34,6 +15,22 @@ export interface TelegramIncomingMessage {
|
|
|
34
15
|
text: string;
|
|
35
16
|
timestamp: number;
|
|
36
17
|
}
|
|
18
|
+
export interface TelegramApprovalResult {
|
|
19
|
+
approved: boolean;
|
|
20
|
+
fromUser: string;
|
|
21
|
+
fromUserId?: number | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface TelegramApprovalRequestInput {
|
|
24
|
+
requestId: string;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
expectedChatId: string | number;
|
|
27
|
+
expectedUserIds: readonly (string | number)[];
|
|
28
|
+
/** Group/supergroup callbacks are rejected unless this was explicitly enabled. */
|
|
29
|
+
allowGroup: boolean;
|
|
30
|
+
expiresAt: number;
|
|
31
|
+
/** Cancels the request when its owning tool execution is aborted. */
|
|
32
|
+
signal?: AbortSignal | undefined;
|
|
33
|
+
}
|
|
37
34
|
export interface TelegramBotOptions {
|
|
38
35
|
token: string;
|
|
39
36
|
pollIntervalSec: number;
|
|
@@ -45,11 +42,11 @@ export interface TelegramBotOptions {
|
|
|
45
42
|
/** Called for each incoming message that passes allowlist checks. */
|
|
46
43
|
onMessage(msg: TelegramIncomingMessage): void;
|
|
47
44
|
/**
|
|
48
|
-
* Optional
|
|
49
|
-
*
|
|
50
|
-
*
|
|
45
|
+
* Optional typed offset store. When provided, the polling offset is persisted
|
|
46
|
+
* atomically on every successful poll and restored on startup, preventing
|
|
47
|
+
* message replay after crashes or restarts.
|
|
51
48
|
*/
|
|
52
|
-
|
|
49
|
+
offsetStore?: OffsetStore | undefined;
|
|
53
50
|
/**
|
|
54
51
|
* Optional cross-process single-poller lock. Telegram allows one
|
|
55
52
|
* `getUpdates` consumer per token; when another wstack instance holds the
|
|
@@ -61,9 +58,7 @@ export interface TelegramBotOptions {
|
|
|
61
58
|
standbyRetryMs?: number | undefined;
|
|
62
59
|
}
|
|
63
60
|
export declare class TelegramBot {
|
|
64
|
-
private readonly
|
|
65
|
-
/** Base URL with token redacted, safe to use in log calls. */
|
|
66
|
-
private readonly safeBaseUrl;
|
|
61
|
+
private readonly api;
|
|
67
62
|
private readonly pollIntervalMs;
|
|
68
63
|
private readonly allowedUsers;
|
|
69
64
|
private readonly allowedChats;
|
|
@@ -84,8 +79,8 @@ export declare class TelegramBot {
|
|
|
84
79
|
private static readonly CONFLICT_BACKOFF_AFTER;
|
|
85
80
|
private static readonly CONFLICT_POLL_MS;
|
|
86
81
|
private _startedAt;
|
|
87
|
-
/**
|
|
88
|
-
private readonly
|
|
82
|
+
/** Typed offset store for atomic polling-cursor persistence. */
|
|
83
|
+
private readonly offsetStore?;
|
|
89
84
|
/** Single-poller election across wstack instances sharing this token. */
|
|
90
85
|
private readonly lock?;
|
|
91
86
|
private readonly standbyRetryMs;
|
|
@@ -118,7 +113,7 @@ export declare class TelegramBot {
|
|
|
118
113
|
/** Drop messages older than the given message ID from the buffer. */
|
|
119
114
|
acknowledge(lastMessageId: number): number;
|
|
120
115
|
get bufferCount(): number;
|
|
121
|
-
sendMessage(chatId: string | number, text: string): Promise<
|
|
116
|
+
sendMessage(chatId: string | number, text: string, signal?: AbortSignal | undefined): Promise<TelegramBotResponse<TelegramApiMessage>>;
|
|
122
117
|
/**
|
|
123
118
|
* Send a message that has up to one row of inline buttons (Telegram's
|
|
124
119
|
* `inline_keyboard`). Used by `telegram_approve` to present a
|
|
@@ -128,28 +123,26 @@ export declare class TelegramBot {
|
|
|
128
123
|
sendMessageWithKeyboard(chatId: string | number, text: string, buttons: Array<{
|
|
129
124
|
text: string;
|
|
130
125
|
callback_data: string;
|
|
131
|
-
}
|
|
132
|
-
health(): Promise<{
|
|
126
|
+
}>, signal?: AbortSignal | undefined): Promise<TelegramBotResponse<TelegramApiMessage>>;
|
|
127
|
+
health(signal?: AbortSignal | undefined): Promise<{
|
|
133
128
|
ok: boolean;
|
|
134
129
|
username?: string | undefined;
|
|
135
130
|
error?: string | undefined;
|
|
136
131
|
}>;
|
|
137
132
|
private schedulePoll;
|
|
138
133
|
private poll;
|
|
139
|
-
private processMessage;
|
|
140
134
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
135
|
+
* Apply the inbound identity policy to every update type. A non-empty set is
|
|
136
|
+
* a mandatory constraint: missing identity fails closed instead of bypassing
|
|
137
|
+
* the allowlist. An empty set leaves that identity dimension unrestricted.
|
|
144
138
|
*/
|
|
139
|
+
private inboundDenialReason;
|
|
140
|
+
private processMessage;
|
|
145
141
|
/**
|
|
146
|
-
* Resolve
|
|
147
|
-
*
|
|
148
|
-
* etc.). Returns true if a waiter was found and resolved, false otherwise.
|
|
149
|
-
* This helper centralizes the race-safe `delete → resolve` pattern in one
|
|
150
|
-
* place so the deny and shutdown paths don't drift out of sync.
|
|
142
|
+
* Resolve a pending approval request exactly once and record its terminal
|
|
143
|
+
* state before removing it from the live registry.
|
|
151
144
|
*/
|
|
152
|
-
private
|
|
145
|
+
private settleApproval;
|
|
153
146
|
private dispatchCallback;
|
|
154
147
|
/**
|
|
155
148
|
* POST /answerCallbackQuery for a callback. Best-effort: failures are
|
|
@@ -159,34 +152,24 @@ export declare class TelegramBot {
|
|
|
159
152
|
*/
|
|
160
153
|
private answerCallback;
|
|
161
154
|
/**
|
|
162
|
-
* Register
|
|
163
|
-
*
|
|
164
|
-
* with `{ approved: false, fromUser: 'timeout' }` after `timeoutMs`.
|
|
165
|
-
*
|
|
166
|
-
* Callers are responsible for not registering the same key twice — a
|
|
167
|
-
* second `awaitCallback` for an in-flight key is undefined.
|
|
155
|
+
* Register one approval request before its prompt is sent. The returned
|
|
156
|
+
* promise owns the request's only timer and resolves on one terminal event.
|
|
168
157
|
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
158
|
+
awaitApproval(input: TelegramApprovalRequestInput): Promise<TelegramApprovalResult>;
|
|
159
|
+
/**
|
|
160
|
+
* Attach the Bot API response's prompt message ID to an existing request.
|
|
161
|
+
* Any callback that arrived during the send is replayed against the fully
|
|
162
|
+
* bound identity without allocating a second waiter or timer.
|
|
163
|
+
*/
|
|
164
|
+
bindApprovalPrompt(requestId: string, promptMessageId: number): boolean;
|
|
165
|
+
/** Cancel a request that cannot reach a valid terminal callback. */
|
|
166
|
+
cancelApproval(requestId: string, fromUser?: string): boolean;
|
|
173
167
|
private loadOffset;
|
|
174
168
|
private saveOffset;
|
|
175
169
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Truncate text to fit Telegram's 4096-char message limit.
|
|
178
|
-
* Preserves semantic boundaries in this priority order:
|
|
179
|
-
* 1. Paragraph break (double newline)
|
|
180
|
-
* 2. Sentence break (. ! ? followed by space/newline)
|
|
181
|
-
* 3. Word break (space)
|
|
182
|
-
* 4. Hard cut with ellipsis
|
|
183
|
-
*
|
|
184
|
-
* When a clean boundary is found, appends "…" to signal intentional truncation.
|
|
185
|
-
*/
|
|
186
170
|
export declare function truncateForTelegram(text: string, maxLen?: number): string;
|
|
187
171
|
/**
|
|
188
172
|
* Escape HTML special chars for Telegram's HTML parse mode.
|
|
189
173
|
*/
|
|
190
174
|
export declare function escapeHtml(text: string): string;
|
|
191
|
-
export {};
|
|
192
175
|
//# sourceMappingURL=bot.d.ts.map
|
package/dist/bot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { TelegramPluginConfig } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Keys the Telegram plugin can apply live without restarting the bot.
|
|
4
|
+
*
|
|
5
|
+
* Rationale per key:
|
|
6
|
+
* - `inboundMode` / `allowedUsers` / `allowedChats` — `processMessage`
|
|
7
|
+
* and `dispatchCallback` re-read the allowlist on every inbound call,
|
|
8
|
+
* so toggling the mode or editing the lists takes effect immediately.
|
|
9
|
+
* - `notifyOnSessionEnd` / `notifyOnDelegate` — re-evaluated on each
|
|
10
|
+
* event subscription; no in-flight state to restart.
|
|
11
|
+
* - `longToolThresholdMs` — pure threshold read inside the tool-notify
|
|
12
|
+
* handler; the next long-tool event uses the new value.
|
|
13
|
+
* - `maxMessageLength` / `allowedOutboundChats` — re-read on every
|
|
14
|
+
* `sendMessage` / outbound-target resolution, so the next send reflects
|
|
15
|
+
* the change.
|
|
16
|
+
* - `pollIntervalSec` — the poller reads this on each iteration of its
|
|
17
|
+
* wait loop; the next tick uses the new interval.
|
|
18
|
+
* - `outboundQueuePerChat` / `outboundQueueConcurrency` — the outbound
|
|
19
|
+
* queue reads these only at construction. They are documented as
|
|
20
|
+
* hot-reload in spirit (the queue can be re-evaluated) but the live
|
|
21
|
+
* queue owns a stable copy. Marking them HOT would silently mislead,
|
|
22
|
+
* so they are intentionally EXCLUDED until the queue supports
|
|
23
|
+
* mid-flight reconfiguration. See `restart-required` below.
|
|
24
|
+
*/
|
|
25
|
+
export declare const HOT_RELOAD_KEYS: Set<keyof TelegramPluginConfig>;
|
|
26
|
+
/**
|
|
27
|
+
* Keys that require restarting the Telegram plugin (or wstack itself)
|
|
28
|
+
* for the new value to take effect.
|
|
29
|
+
*
|
|
30
|
+
* - `botToken` — every Telegram transport object is constructed once with
|
|
31
|
+
* the token baked into the base URL; changing it requires a new
|
|
32
|
+
* `TelegramBot` instance.
|
|
33
|
+
* - `notifyChatId` — bound into the optional-allowedUsers fallback at
|
|
34
|
+
* setup (`inboundAllowlist`) and read by every notification callback;
|
|
35
|
+
* the inbound allowlist does not rebuild without a setup re-run.
|
|
36
|
+
* - `offsetStoragePath` — the `OffsetStore` is opened once at setup;
|
|
37
|
+
* changing the path would orphan any persisted cursor.
|
|
38
|
+
* - `singleInstanceLock` — the cross-process `PollLock` is acquired at
|
|
39
|
+
* startup; flipping this flag requires a fresh setup to acquire /
|
|
40
|
+
* release the right lock file.
|
|
41
|
+
* - `outboundQueuePerChat` / `outboundQueueConcurrency` — the
|
|
42
|
+
* `OutboundQueue` reads these at construction only.
|
|
43
|
+
*/
|
|
44
|
+
export declare const RESTART_REQUIRED_KEYS: Set<keyof TelegramPluginConfig>;
|
|
45
|
+
export type ConfigReloadClass = 'hot' | 'restart-required';
|
|
46
|
+
/**
|
|
47
|
+
* Classify a single key. Returns `'hot'` for keys in `HOT_RELOAD_KEYS`,
|
|
48
|
+
* `'restart-required'` for keys in `RESTART_REQUIRED_KEYS`, and
|
|
49
|
+
* `'restart-required'` as a conservative default for keys that are not
|
|
50
|
+
* registered in either set — preventing a new field from silently
|
|
51
|
+
* pretending to be hot-reloadable before the classifier is updated.
|
|
52
|
+
*/
|
|
53
|
+
export declare function classifyReload(key: keyof TelegramPluginConfig): ConfigReloadClass;
|
|
54
|
+
/**
|
|
55
|
+
* Diff two configs and return the keys whose values differ, each tagged
|
|
56
|
+
* with its reload classification. Keys present in `previous` but absent in
|
|
57
|
+
* `next` (or vice versa) are reported as `'restart-required'` so a stale
|
|
58
|
+
* removal is never silently applied as a live change.
|
|
59
|
+
*/
|
|
60
|
+
export declare function diffConfigKeys(previous: TelegramPluginConfig, next: TelegramPluginConfig): Array<{
|
|
61
|
+
key: keyof TelegramPluginConfig;
|
|
62
|
+
classification: ConfigReloadClass;
|
|
63
|
+
}>;
|
|
64
|
+
//# sourceMappingURL=config-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-classifier.d.ts","sourceRoot":"","sources":["../src/config-classifier.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,eAAe,iCAU1B,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,qBAAqB,iCAOhC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,kBAAkB,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,oBAAoB,GAAG,iBAAiB,CAGjF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,oBAAoB,EAC9B,IAAI,EAAE,oBAAoB,GACzB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;IAAC,cAAc,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAc/E"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PluginAPI } from '@wrongstack/core';
|
|
2
2
|
export declare const PLUGIN_NAME = "telegram";
|
|
3
|
+
export type TelegramInboundMode = 'disabled' | 'paired' | 'allowlist' | 'public';
|
|
3
4
|
export interface TelegramPluginConfig {
|
|
4
5
|
/** Telegram Bot API token (from @BotFather). */
|
|
5
6
|
botToken: string;
|
|
@@ -9,15 +10,17 @@ export interface TelegramPluginConfig {
|
|
|
9
10
|
*/
|
|
10
11
|
notifyChatId?: string | number | undefined;
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* Controls who may send inbound messages to the bot. Defaults to `disabled`
|
|
14
|
+
* for new/unpaired configurations. Legacy configurations are migrated to
|
|
15
|
+
* `allowlist` when IDs exist, or `paired` when `notifyChatId` exists.
|
|
14
16
|
*/
|
|
17
|
+
inboundMode?: TelegramInboundMode | undefined;
|
|
18
|
+
/** List of user IDs accepted when `inboundMode` is `allowlist`. */
|
|
15
19
|
allowedUsers?: Array<string | number> | undefined;
|
|
16
|
-
/**
|
|
17
|
-
* List of group/chat IDs the bot is allowed to read from.
|
|
18
|
-
* Empty = allow all. Narrow this to prevent noise.
|
|
19
|
-
*/
|
|
20
|
+
/** List of chat IDs accepted when `inboundMode` is `allowlist`. */
|
|
20
21
|
allowedChats?: Array<string | number> | undefined;
|
|
22
|
+
/** Additional trusted targets for outbound sends beyond `notifyChatId`. */
|
|
23
|
+
allowedOutboundChats?: Array<string | number> | undefined;
|
|
21
24
|
/** Polling interval in seconds (default: 2). */
|
|
22
25
|
pollIntervalSec?: number | undefined;
|
|
23
26
|
/** Notify on Telegram when a session ends. */
|
|
@@ -43,6 +46,14 @@ export interface TelegramPluginConfig {
|
|
|
43
46
|
* Set false only if this is guaranteed to be the sole consumer.
|
|
44
47
|
*/
|
|
45
48
|
singleInstanceLock?: boolean | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Per-chat pending-message cap for the outbound queue. Older pending
|
|
51
|
+
* notification entries are dropped when this is exceeded; manual
|
|
52
|
+
* telegram_send entries surface the overflow as an error. Default: 32.
|
|
53
|
+
*/
|
|
54
|
+
outboundQueuePerChat?: number | undefined;
|
|
55
|
+
/** Maximum concurrent outbound sends across all chats. Default: 4. */
|
|
56
|
+
outboundQueueConcurrency?: number | undefined;
|
|
46
57
|
}
|
|
47
58
|
export declare const DEFAULT_CONFIG: Required<Omit<TelegramPluginConfig, 'botToken' | 'notifyChatId' | 'offsetStoragePath'>>;
|
|
48
59
|
export declare const telegramConfigSchema: {
|
|
@@ -58,6 +69,12 @@ export declare const telegramConfigSchema: {
|
|
|
58
69
|
}[];
|
|
59
70
|
description: string;
|
|
60
71
|
};
|
|
72
|
+
inboundMode: {
|
|
73
|
+
type: string;
|
|
74
|
+
enum: ("allowlist" | "disabled" | "paired" | "public")[];
|
|
75
|
+
default: string;
|
|
76
|
+
description: string;
|
|
77
|
+
};
|
|
61
78
|
allowedUsers: {
|
|
62
79
|
type: string;
|
|
63
80
|
items: {
|
|
@@ -76,6 +93,15 @@ export declare const telegramConfigSchema: {
|
|
|
76
93
|
};
|
|
77
94
|
description: string;
|
|
78
95
|
};
|
|
96
|
+
allowedOutboundChats: {
|
|
97
|
+
type: string;
|
|
98
|
+
items: {
|
|
99
|
+
oneOf: {
|
|
100
|
+
type: string;
|
|
101
|
+
}[];
|
|
102
|
+
};
|
|
103
|
+
description: string;
|
|
104
|
+
};
|
|
79
105
|
pollIntervalSec: {
|
|
80
106
|
type: string;
|
|
81
107
|
minimum: number;
|
|
@@ -101,8 +127,20 @@ export declare const telegramConfigSchema: {
|
|
|
101
127
|
type: string;
|
|
102
128
|
description: string;
|
|
103
129
|
};
|
|
130
|
+
outboundQueuePerChat: {
|
|
131
|
+
type: string;
|
|
132
|
+
minimum: number;
|
|
133
|
+
maximum: number;
|
|
134
|
+
description: string;
|
|
135
|
+
};
|
|
136
|
+
outboundQueueConcurrency: {
|
|
137
|
+
type: string;
|
|
138
|
+
minimum: number;
|
|
139
|
+
maximum: number;
|
|
140
|
+
description: string;
|
|
141
|
+
};
|
|
104
142
|
};
|
|
105
143
|
required: string[];
|
|
106
144
|
};
|
|
107
|
-
export declare function readTelegramConfig(api: Pick<PluginAPI, 'config'>): Required<Omit<TelegramPluginConfig, 'notifyChatId' | 'offsetStoragePath'>> & Pick<TelegramPluginConfig, 'notifyChatId' | 'offsetStoragePath'>;
|
|
145
|
+
export declare function readTelegramConfig(api: Pick<PluginAPI, 'config'> & Partial<Pick<PluginAPI, 'log'>>): Required<Omit<TelegramPluginConfig, 'notifyChatId' | 'offsetStoragePath'>> & Pick<TelegramPluginConfig, 'notifyChatId' | 'offsetStoragePath'>;
|
|
108
146
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,eAAO,MAAM,WAAW,aAAa,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3C
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,eAAO,MAAM,WAAW,aAAa,CAAC;AAEtC,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAIjF,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3C;;;;OAIG;IACH,WAAW,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC9C,mEAAmE;IACnE,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IAClD,mEAAmE;IACnE,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IAClD,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IAC1D,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,sEAAsE;IACtE,wBAAwB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CACnC,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,cAAc,GAAG,mBAAmB,CAAC,CAc9E,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;YAGjB,IAAI;YAAY,WAAW;;;;;;;;;YAMrC,IAAI;YACJ,IAAI;YACJ,OAAO;YACP,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAmBX,IAAI;YACJ,OAAO;YACP,OAAO;YACP,WAAW;;;YAES,IAAI;;;YACH,IAAI;YAAa,OAAO;;;YAC3B,IAAI;;;YACJ,IAAI;YAAa,OAAO;YAAO,OAAO;;;YAExD,IAAI;YACJ,WAAW;;;YAIX,IAAI;YACJ,OAAO;YACP,OAAO;YACP,WAAW;;;YAGX,IAAI;YACJ,OAAO;YACP,OAAO;YACP,WAAW;;;;CAIhB,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,GAC/D,QAAQ,CAAC,IAAI,CAAC,oBAAoB,EAAE,cAAc,GAAG,mBAAmB,CAAC,CAAC,GAC3E,IAAI,CAAC,oBAAoB,EAAE,cAAc,GAAG,mBAAmB,CAAC,CAuBjE"}
|