@spinabot/brigade 1.0.2 → 1.2.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/convex/channels.d.ts +5 -5
- package/convex/schema.d.ts +2 -2
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +27 -4
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/approval-callback-codec.d.ts +107 -0
- package/dist/agents/channels/approval-callback-codec.d.ts.map +1 -0
- package/dist/agents/channels/approval-callback-codec.js +173 -0
- package/dist/agents/channels/approval-callback-codec.js.map +1 -0
- package/dist/agents/channels/approval-router.d.ts +77 -20
- package/dist/agents/channels/approval-router.d.ts.map +1 -1
- package/dist/agents/channels/approval-router.js +163 -37
- package/dist/agents/channels/approval-router.js.map +1 -1
- package/dist/agents/channels/backoff.d.ts +55 -0
- package/dist/agents/channels/backoff.d.ts.map +1 -0
- package/dist/agents/channels/backoff.js +47 -0
- package/dist/agents/channels/backoff.js.map +1 -0
- package/dist/agents/channels/channel-secrets.d.ts +45 -0
- package/dist/agents/channels/channel-secrets.d.ts.map +1 -0
- package/dist/agents/channels/channel-secrets.js +69 -0
- package/dist/agents/channels/channel-secrets.js.map +1 -0
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +67 -3
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/channels/last-sent-message.d.ts +46 -0
- package/dist/agents/channels/last-sent-message.d.ts.map +1 -0
- package/dist/agents/channels/last-sent-message.js +55 -0
- package/dist/agents/channels/last-sent-message.js.map +1 -0
- package/dist/agents/channels/manager.d.ts +52 -0
- package/dist/agents/channels/manager.d.ts.map +1 -1
- package/dist/agents/channels/manager.js +141 -31
- package/dist/agents/channels/manager.js.map +1 -1
- package/dist/agents/channels/plugin-channel-manager-facade.d.ts +13 -2
- package/dist/agents/channels/plugin-channel-manager-facade.d.ts.map +1 -1
- package/dist/agents/channels/plugin-channel-manager-facade.js +21 -0
- package/dist/agents/channels/plugin-channel-manager-facade.js.map +1 -1
- package/dist/agents/channels/sdk.d.ts +426 -0
- package/dist/agents/channels/sdk.d.ts.map +1 -0
- package/dist/agents/channels/sdk.js +274 -0
- package/dist/agents/channels/sdk.js.map +1 -0
- package/dist/agents/channels/telegram/account-config.d.ts +92 -0
- package/dist/agents/channels/telegram/account-config.d.ts.map +1 -0
- package/dist/agents/channels/telegram/account-config.js +192 -0
- package/dist/agents/channels/telegram/account-config.js.map +1 -0
- package/dist/agents/channels/telegram/adapter.d.ts +79 -0
- package/dist/agents/channels/telegram/adapter.d.ts.map +1 -0
- package/dist/agents/channels/telegram/adapter.js +475 -0
- package/dist/agents/channels/telegram/adapter.js.map +1 -0
- package/dist/agents/channels/telegram/allowed-updates.d.ts +44 -0
- package/dist/agents/channels/telegram/allowed-updates.d.ts.map +1 -0
- package/dist/agents/channels/telegram/allowed-updates.js +52 -0
- package/dist/agents/channels/telegram/allowed-updates.js.map +1 -0
- package/dist/agents/channels/telegram/approval-authorize.d.ts +41 -0
- package/dist/agents/channels/telegram/approval-authorize.d.ts.map +1 -0
- package/dist/agents/channels/telegram/approval-authorize.js +69 -0
- package/dist/agents/channels/telegram/approval-authorize.js.map +1 -0
- package/dist/agents/channels/telegram/approval-native.d.ts +68 -0
- package/dist/agents/channels/telegram/approval-native.d.ts.map +1 -0
- package/dist/agents/channels/telegram/approval-native.js +94 -0
- package/dist/agents/channels/telegram/approval-native.js.map +1 -0
- package/dist/agents/channels/telegram/command-menu.d.ts +35 -0
- package/dist/agents/channels/telegram/command-menu.d.ts.map +1 -0
- package/dist/agents/channels/telegram/command-menu.js +59 -0
- package/dist/agents/channels/telegram/command-menu.js.map +1 -0
- package/dist/agents/channels/telegram/connection.d.ts +359 -0
- package/dist/agents/channels/telegram/connection.d.ts.map +1 -0
- package/dist/agents/channels/telegram/connection.js +865 -0
- package/dist/agents/channels/telegram/connection.js.map +1 -0
- package/dist/agents/channels/telegram/format.d.ts +48 -0
- package/dist/agents/channels/telegram/format.d.ts.map +1 -0
- package/dist/agents/channels/telegram/format.js +256 -0
- package/dist/agents/channels/telegram/format.js.map +1 -0
- package/dist/agents/channels/telegram/inbound-extras.d.ts +73 -0
- package/dist/agents/channels/telegram/inbound-extras.d.ts.map +1 -0
- package/dist/agents/channels/telegram/inbound-extras.js +231 -0
- package/dist/agents/channels/telegram/inbound-extras.js.map +1 -0
- package/dist/agents/channels/telegram/index.d.ts +14 -0
- package/dist/agents/channels/telegram/index.d.ts.map +1 -0
- package/dist/agents/channels/telegram/index.js +14 -0
- package/dist/agents/channels/telegram/index.js.map +1 -0
- package/dist/agents/channels/telegram/media.d.ts +68 -0
- package/dist/agents/channels/telegram/media.d.ts.map +1 -0
- package/dist/agents/channels/telegram/media.js +143 -0
- package/dist/agents/channels/telegram/media.js.map +1 -0
- package/dist/agents/channels/telegram/module.d.ts +15 -0
- package/dist/agents/channels/telegram/module.d.ts.map +1 -0
- package/dist/agents/channels/telegram/module.js +36 -0
- package/dist/agents/channels/telegram/module.js.map +1 -0
- package/dist/agents/channels/telegram/plugin.d.ts +76 -0
- package/dist/agents/channels/telegram/plugin.d.ts.map +1 -0
- package/dist/agents/channels/telegram/plugin.js +314 -0
- package/dist/agents/channels/telegram/plugin.js.map +1 -0
- package/dist/agents/channels/telegram/probe.d.ts +54 -0
- package/dist/agents/channels/telegram/probe.d.ts.map +1 -0
- package/dist/agents/channels/telegram/probe.js +95 -0
- package/dist/agents/channels/telegram/probe.js.map +1 -0
- package/dist/agents/channels/telegram/webhook.d.ts +55 -0
- package/dist/agents/channels/telegram/webhook.d.ts.map +1 -0
- package/dist/agents/channels/telegram/webhook.js +141 -0
- package/dist/agents/channels/telegram/webhook.js.map +1 -0
- package/dist/agents/extensions/modules/index.d.ts.map +1 -1
- package/dist/agents/extensions/modules/index.js +4 -0
- package/dist/agents/extensions/modules/index.js.map +1 -1
- package/dist/agents/extensions/types.d.ts +72 -2
- package/dist/agents/extensions/types.d.ts.map +1 -1
- package/dist/agents/extensions/types.js.map +1 -1
- package/dist/agents/tools/connect-channel-tool.d.ts +86 -0
- package/dist/agents/tools/connect-channel-tool.d.ts.map +1 -0
- package/dist/agents/tools/connect-channel-tool.js +398 -0
- package/dist/agents/tools/connect-channel-tool.js.map +1 -0
- package/dist/agents/tools/message-action-tool.d.ts +67 -0
- package/dist/agents/tools/message-action-tool.d.ts.map +1 -0
- package/dist/agents/tools/message-action-tool.js +216 -0
- package/dist/agents/tools/message-action-tool.js.map +1 -0
- package/dist/agents/tools/registry.d.ts.map +1 -1
- package/dist/agents/tools/registry.js +19 -0
- package/dist/agents/tools/registry.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/channels.d.ts.map +1 -1
- package/dist/cli/commands/channels.js +27 -2
- package/dist/cli/commands/channels.js.map +1 -1
- package/dist/cli/commands/convex-cmd.d.ts +27 -0
- package/dist/cli/commands/convex-cmd.d.ts.map +1 -0
- package/dist/cli/commands/convex-cmd.js +162 -0
- package/dist/cli/commands/convex-cmd.js.map +1 -0
- package/dist/cli/program/build-program.d.ts.map +1 -1
- package/dist/cli/program/build-program.js +64 -0
- package/dist/cli/program/build-program.js.map +1 -1
- package/dist/config/paths.d.ts +3 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +39 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +77 -27
- package/dist/core/server.js.map +1 -1
- package/dist/cron/service/state.d.ts +10 -0
- package/dist/cron/service/state.d.ts.map +1 -1
- package/dist/cron/service/state.js.map +1 -1
- package/dist/cron/service/timer.d.ts.map +1 -1
- package/dist/cron/service/timer.js +43 -14
- package/dist/cron/service/timer.js.map +1 -1
- package/dist/cron/session-reaper.d.ts +27 -0
- package/dist/cron/session-reaper.d.ts.map +1 -1
- package/dist/cron/session-reaper.js +81 -0
- package/dist/cron/session-reaper.js.map +1 -1
- package/dist/system-prompt/assembler.d.ts +14 -0
- package/dist/system-prompt/assembler.d.ts.map +1 -1
- package/dist/system-prompt/assembler.js +36 -14
- package/dist/system-prompt/assembler.js.map +1 -1
- package/package.json +16 -3
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram channel adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the Brigade `ChannelAdapter` contract on top of the grammY
|
|
5
|
+
* long-polling connection. Unlike WhatsApp (QR pairing), Telegram is
|
|
6
|
+
* TOKEN-based: the operator pastes a Bot API token from @BotFather, so this
|
|
7
|
+
* adapter declares a `setup` wizard (single `botToken` credential) and has NO
|
|
8
|
+
* `link`/QR flow. Enablement is explicit — `channels.telegram.enabled: true`
|
|
9
|
+
* plus a resolvable token.
|
|
10
|
+
*
|
|
11
|
+
* Modeled directly on `whatsapp/adapter.ts`: same health-flag mirroring, same
|
|
12
|
+
* deferred-media passthrough on inbound, same chunk-then-send outbound shape
|
|
13
|
+
* (chunk markdown ≤4096, convert each chunk to Telegram HTML, send with
|
|
14
|
+
* `parse_mode: HTML`, and on a parse / empty-text error RETRY as plain text).
|
|
15
|
+
*
|
|
16
|
+
* Scope cut (v1): single account, and `callback_query` inline buttons are not
|
|
17
|
+
* handled (Brigade approvals are central text replies).
|
|
18
|
+
*/
|
|
19
|
+
import { type ChannelAdapter, type ChannelCapabilities, type OutboundSendOptions } from "../sdk.js";
|
|
20
|
+
import { type ConnectTelegramArgs, type TelegramConnection, type TelegramPollSpec } from "./connection.js";
|
|
21
|
+
/** Adapter construction options — all optional for back-compat. */
|
|
22
|
+
export interface CreateTelegramAdapterOptions {
|
|
23
|
+
/** Per-account scope. Defaults to `"default"` (single-account v1). */
|
|
24
|
+
accountId?: string;
|
|
25
|
+
/**
|
|
26
|
+
* TEST SEAM: override how the connection is built. Production leaves this
|
|
27
|
+
* undefined and `connectTelegram` lazy-loads grammY. Tests inject a fake.
|
|
28
|
+
*/
|
|
29
|
+
connectImpl?: (args: ConnectTelegramArgs) => Promise<TelegramConnection>;
|
|
30
|
+
/**
|
|
31
|
+
* The bot's `/` command menu to register on connect (Brigade's central
|
|
32
|
+
* commands, already mapped to `{ command, description }` via
|
|
33
|
+
* `buildTelegramCommandMenu`). Empty/omitted → no menu sync. The manager
|
|
34
|
+
* supplies this from `buildBundledCommands(adapter)`.
|
|
35
|
+
*/
|
|
36
|
+
commandMenu?: Array<{
|
|
37
|
+
command: string;
|
|
38
|
+
description: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Widen the `allowed_updates` poller subscription beyond the default
|
|
42
|
+
* `message` + `callback_query`. Omitted → the minimal set.
|
|
43
|
+
*/
|
|
44
|
+
allowedUpdates?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Enable forum-topic auto-labeling: when set, the FIRST message seen on a
|
|
47
|
+
* forum thread renames that topic from the message text. Off by default —
|
|
48
|
+
* the plugin path enables it from `channels.telegram.autoLabelTopics`.
|
|
49
|
+
*/
|
|
50
|
+
autoLabelTopics?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export declare function createTelegramAdapter(opts?: CreateTelegramAdapterOptions): ChannelAdapter;
|
|
53
|
+
/** Static Telegram capability flags (shared by the legacy adapter + plugin meta). */
|
|
54
|
+
export declare const TELEGRAM_CAPABILITIES: ChannelCapabilities;
|
|
55
|
+
/**
|
|
56
|
+
* The Telegram adapter shape with its poll extension. `createTelegramAdapter`
|
|
57
|
+
* returns a `ChannelAdapter`, but the concrete object ALSO carries `sendPoll`
|
|
58
|
+
* (not in the base contract). Callers that want polls cast through this type.
|
|
59
|
+
*/
|
|
60
|
+
export interface TelegramAdapter extends ChannelAdapter {
|
|
61
|
+
sendPoll(conversationId: string, poll: TelegramPollSpec, opts?: OutboundSendOptions): Promise<{
|
|
62
|
+
messageId?: string;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Feed a raw Telegram `Update` (webhook mode). The gateway HTTP route calls
|
|
66
|
+
* this after verifying the secret-token header. No-op when not started or in
|
|
67
|
+
* polling mode. The argument is the parsed JSON body Telegram POSTed.
|
|
68
|
+
*/
|
|
69
|
+
feedWebhookUpdate(update: unknown): void;
|
|
70
|
+
/** The transport mode this adapter's connection runs (`"polling"` | `"webhook"`). */
|
|
71
|
+
transportMode(): "polling" | "webhook" | "unstarted";
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Derive a forum-topic name from a message's first line. Telegram caps topic
|
|
75
|
+
* names at 128 chars; we use the first line, collapsed + trimmed, clamped to a
|
|
76
|
+
* readable length. Returns "" when nothing usable remains.
|
|
77
|
+
*/
|
|
78
|
+
export declare function deriveTopicName(text: string): string;
|
|
79
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/telegram/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,OAAO,EACN,KAAK,cAAc,EAEnB,KAAK,mBAAmB,EAMxB,KAAK,mBAAmB,EAExB,MAAM,WAAW,CAAC;AAUnB,OAAO,EAAmB,KAAK,mBAAmB,EAA4B,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAUtJ,mEAAmE;AACnE,MAAM,WAAW,4BAA4B;IAC5C,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,4BAAiC,GAAG,cAAc,CAkZ7F;AAED,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,EAAE,mBAUnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtH;;;;OAIG;IACH,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACzC,qFAAqF;IACrF,aAAa,IAAI,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;CACrD;AAgBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD"}
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram channel adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements the Brigade `ChannelAdapter` contract on top of the grammY
|
|
5
|
+
* long-polling connection. Unlike WhatsApp (QR pairing), Telegram is
|
|
6
|
+
* TOKEN-based: the operator pastes a Bot API token from @BotFather, so this
|
|
7
|
+
* adapter declares a `setup` wizard (single `botToken` credential) and has NO
|
|
8
|
+
* `link`/QR flow. Enablement is explicit — `channels.telegram.enabled: true`
|
|
9
|
+
* plus a resolvable token.
|
|
10
|
+
*
|
|
11
|
+
* Modeled directly on `whatsapp/adapter.ts`: same health-flag mirroring, same
|
|
12
|
+
* deferred-media passthrough on inbound, same chunk-then-send outbound shape
|
|
13
|
+
* (chunk markdown ≤4096, convert each chunk to Telegram HTML, send with
|
|
14
|
+
* `parse_mode: HTML`, and on a parse / empty-text error RETRY as plain text).
|
|
15
|
+
*
|
|
16
|
+
* Scope cut (v1): single account, and `callback_query` inline buttons are not
|
|
17
|
+
* handled (Brigade approvals are central text replies).
|
|
18
|
+
*/
|
|
19
|
+
import { loadConfig } from "../../../core/config.js";
|
|
20
|
+
// Channel SDK barrel — the single import surface for the channel-authoring
|
|
21
|
+
// contract + shared helpers. Telegram is the proving ground: contract types
|
|
22
|
+
// (ChannelAdapter / ChannelHealth / ChannelStartContext / OutboundMedia /
|
|
23
|
+
// OutboundSendOptions) and `chunkText` now come from one place instead of
|
|
24
|
+
// scattered `../../extensions/types.js` + `../whatsapp/chunk.js` paths.
|
|
25
|
+
import { chunkText, } from "../sdk.js";
|
|
26
|
+
import { listTelegramAccountIds, resolveTelegramBotToken, telegramChannelEnabled, telegramWebhookConfig, TELEGRAM_CHANNEL_ID, TELEGRAM_DEFAULT_ACCOUNT_ID, } from "./account-config.js";
|
|
27
|
+
import { buildTelegramApprovalKeyboard, buildTelegramApprovalText } from "./approval-native.js";
|
|
28
|
+
import { connectTelegram } from "./connection.js";
|
|
29
|
+
import { markdownToTelegramHtml, telegramHtmlIsEmpty } from "./format.js";
|
|
30
|
+
import { resolveTelegramApprover } from "./approval-authorize.js";
|
|
31
|
+
/** Telegram's per-message text limit. */
|
|
32
|
+
const TELEGRAM_TEXT_LIMIT = 4096;
|
|
33
|
+
/** Errors Telegram returns when HTML failed to parse / produced an empty body. */
|
|
34
|
+
const PARSE_ERROR_RE = /can't parse entities|parse entities|find end of the entity|message text is empty/i;
|
|
35
|
+
export function createTelegramAdapter(opts = {}) {
|
|
36
|
+
const accountId = opts.accountId?.trim() || TELEGRAM_DEFAULT_ACCOUNT_ID;
|
|
37
|
+
const connectImpl = opts.connectImpl ?? connectTelegram;
|
|
38
|
+
let connection = null;
|
|
39
|
+
// Forum threads we've already auto-labeled this process, so the rename fires
|
|
40
|
+
// only on the FIRST message of a topic (keyed `${chatId}:${threadId}`).
|
|
41
|
+
const autoLabeledThreads = new Set();
|
|
42
|
+
// The ChannelStartContext doesn't carry the config, but the manager ALWAYS
|
|
43
|
+
// calls `isConfigured(cfg, env)` immediately before `start(ctx)` — so we
|
|
44
|
+
// capture the config + env it passed there and read the token from them in
|
|
45
|
+
// start(). This avoids a second config load and keeps the adapter pure.
|
|
46
|
+
let lastConfig = null;
|
|
47
|
+
let lastEnv = process.env;
|
|
48
|
+
// Health flags mirrored from the connection lifecycle so health() never has
|
|
49
|
+
// to round-trip Telegram on the hot path (cron timer / send pre-flight).
|
|
50
|
+
// - `connected` flips true on a successful getMe + poll start.
|
|
51
|
+
// - `tokenInvalid` is STICKY: a 401 means the token is dead and the only
|
|
52
|
+
// recovery is `brigade channels add --channel telegram` with a new token.
|
|
53
|
+
let connected = false;
|
|
54
|
+
let tokenInvalid = false;
|
|
55
|
+
const adapter = {
|
|
56
|
+
id: TELEGRAM_CHANNEL_ID,
|
|
57
|
+
label: "Telegram",
|
|
58
|
+
isConfigured(cfg, env) {
|
|
59
|
+
// Capture for start() — the manager calls this right before start(ctx).
|
|
60
|
+
lastConfig = cfg;
|
|
61
|
+
lastEnv = env ?? process.env;
|
|
62
|
+
if (!telegramChannelEnabled(cfg))
|
|
63
|
+
return false;
|
|
64
|
+
// Need a resolvable bot token (config `${VAR}` ref or TELEGRAM_BOT_TOKEN env).
|
|
65
|
+
if (!resolveTelegramBotToken(cfg, accountId, env ?? process.env))
|
|
66
|
+
return false;
|
|
67
|
+
// Multi-account follow-up: when the operator declares >1 account, the
|
|
68
|
+
// (future) plugin path owns lifecycle and the legacy single adapter
|
|
69
|
+
// steps aside. v1 only ever runs the default account.
|
|
70
|
+
const isLegacyAdapter = accountId === TELEGRAM_DEFAULT_ACCOUNT_ID;
|
|
71
|
+
if (isLegacyAdapter && listTelegramAccountIds(cfg).length > 1)
|
|
72
|
+
return false;
|
|
73
|
+
return true;
|
|
74
|
+
},
|
|
75
|
+
async start(ctx) {
|
|
76
|
+
// Resolve the token from the config the manager handed isConfigured().
|
|
77
|
+
// Fall back to a fresh load defensively (e.g. a direct start() in a test
|
|
78
|
+
// that skipped isConfigured).
|
|
79
|
+
const cfg = lastConfig ?? (await loadStartConfig());
|
|
80
|
+
const token = resolveTelegramBotToken(cfg, accountId, lastEnv);
|
|
81
|
+
if (!token) {
|
|
82
|
+
// Defensive — isConfigured already gates this, but never start a bot
|
|
83
|
+
// with an empty token (grammY would throw an opaque error).
|
|
84
|
+
ctx.log("Telegram not started — no bot token resolved (set channels.telegram.botToken or TELEGRAM_BOT_TOKEN).");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Resolve transport mode (polling default; webhook opt-in). Webhook mode
|
|
88
|
+
// registers the webhook on connect; the gateway HTTP route feeds updates
|
|
89
|
+
// via `feedWebhookUpdate` (wired by the module when webhook is active).
|
|
90
|
+
const transport = telegramWebhookConfig(cfg, lastEnv);
|
|
91
|
+
connection = await connectImpl({
|
|
92
|
+
token,
|
|
93
|
+
accountId,
|
|
94
|
+
...(opts.commandMenu && opts.commandMenu.length > 0 ? { commandMenu: opts.commandMenu } : {}),
|
|
95
|
+
...(opts.allowedUpdates && opts.allowedUpdates.length > 0 ? { allowedUpdates: opts.allowedUpdates } : {}),
|
|
96
|
+
...(transport.mode === "webhook"
|
|
97
|
+
? {
|
|
98
|
+
mode: "webhook",
|
|
99
|
+
webhook: {
|
|
100
|
+
...(transport.url ? { url: transport.url } : {}),
|
|
101
|
+
...(transport.secretToken ? { secretToken: transport.secretToken } : {}),
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
: {}),
|
|
105
|
+
log: ctx.log,
|
|
106
|
+
onConnected: () => {
|
|
107
|
+
connected = true;
|
|
108
|
+
tokenInvalid = false;
|
|
109
|
+
ctx.log("Telegram ready");
|
|
110
|
+
ctx.onConnected?.();
|
|
111
|
+
},
|
|
112
|
+
onTokenInvalid: () => {
|
|
113
|
+
connected = false;
|
|
114
|
+
tokenInvalid = true;
|
|
115
|
+
ctx.log("Telegram bot token was rejected. Run `brigade channels add --channel telegram` with a fresh @BotFather token.");
|
|
116
|
+
ctx.onLoggedOut?.();
|
|
117
|
+
},
|
|
118
|
+
onMessage: (msg) => {
|
|
119
|
+
// Forum-topic auto-labeling: rename a topic from its first message.
|
|
120
|
+
// Fire-and-forget + best-effort — never blocks inbound delivery.
|
|
121
|
+
if (opts.autoLabelTopics && msg.threadId && msg.chatType === "group" && msg.text.trim()) {
|
|
122
|
+
maybeAutoLabelThread(msg.conversationId, msg.threadId, msg.text);
|
|
123
|
+
}
|
|
124
|
+
void ctx.onInbound({
|
|
125
|
+
channel: TELEGRAM_CHANNEL_ID,
|
|
126
|
+
accountId,
|
|
127
|
+
conversationId: msg.conversationId,
|
|
128
|
+
messageId: msg.messageId,
|
|
129
|
+
messageTimestampMs: msg.messageTimestampMs,
|
|
130
|
+
from: msg.from,
|
|
131
|
+
fromName: msg.fromName,
|
|
132
|
+
text: msg.text,
|
|
133
|
+
chatType: msg.chatType,
|
|
134
|
+
isGroup: msg.chatType === "group",
|
|
135
|
+
threadId: msg.threadId,
|
|
136
|
+
mentions: msg.mentions,
|
|
137
|
+
replyTo: msg.replyTo,
|
|
138
|
+
// Deferred media thunk rides through untouched — the pipeline
|
|
139
|
+
// resolves it only after the access gate admits the sender.
|
|
140
|
+
resolveMedia: msg.resolveMedia,
|
|
141
|
+
raw: msg.raw,
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
// Inline-button press → emit an InboundMessage carrying `callbackQuery`
|
|
145
|
+
// so the central pipeline's approval-callback path resolves it. The
|
|
146
|
+
// connection has already acked the press via `answerCallbackQuery`.
|
|
147
|
+
onCallbackQuery: (msg) => {
|
|
148
|
+
if (!msg.callbackQuery)
|
|
149
|
+
return;
|
|
150
|
+
void ctx.onInbound({
|
|
151
|
+
channel: TELEGRAM_CHANNEL_ID,
|
|
152
|
+
accountId,
|
|
153
|
+
conversationId: msg.conversationId,
|
|
154
|
+
from: msg.from,
|
|
155
|
+
...(msg.fromName !== undefined ? { fromName: msg.fromName } : {}),
|
|
156
|
+
text: "",
|
|
157
|
+
chatType: msg.chatType,
|
|
158
|
+
isGroup: msg.chatType === "group",
|
|
159
|
+
...(msg.threadId !== undefined ? { threadId: msg.threadId } : {}),
|
|
160
|
+
callbackQuery: msg.callbackQuery,
|
|
161
|
+
raw: msg.raw,
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
async stop() {
|
|
167
|
+
await connection?.close();
|
|
168
|
+
connection = null;
|
|
169
|
+
connected = false;
|
|
170
|
+
},
|
|
171
|
+
/**
|
|
172
|
+
* Synchronous read of the cached connection state:
|
|
173
|
+
* - `{ ok: true }` once polling is live.
|
|
174
|
+
* - `{ ok: false, kind: "logged-out" }` after a 401 (sticky; re-token).
|
|
175
|
+
* - `{ ok: false, kind: "starting" }` between start() and first connect.
|
|
176
|
+
* - `{ ok: false, kind: "disconnected" }` for a transient drop mid-reconnect.
|
|
177
|
+
*/
|
|
178
|
+
health() {
|
|
179
|
+
if (tokenInvalid || connection?.isTokenInvalid()) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
kind: "logged-out",
|
|
183
|
+
reason: "Telegram bot token was rejected — Brigade can't send until a new token is set.",
|
|
184
|
+
remediation: "Run `brigade channels add --channel telegram` and paste a fresh @BotFather token.",
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (!connection) {
|
|
188
|
+
return { ok: false, kind: "starting", reason: "Telegram adapter is not started yet." };
|
|
189
|
+
}
|
|
190
|
+
if (!connected || !connection.isConnected()) {
|
|
191
|
+
return {
|
|
192
|
+
ok: false,
|
|
193
|
+
kind: "disconnected",
|
|
194
|
+
reason: "Telegram is reconnecting — sends will fail until polling resumes.",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return { ok: true };
|
|
198
|
+
},
|
|
199
|
+
async sendText(conversationId, text, opts) {
|
|
200
|
+
if (!connection)
|
|
201
|
+
throw new Error("Telegram channel is not started");
|
|
202
|
+
if (tokenInvalid || connection.isTokenInvalid()) {
|
|
203
|
+
throw new Error("Telegram token is invalid — run `brigade channels add --channel telegram` with a new token, then retry.");
|
|
204
|
+
}
|
|
205
|
+
const threadId = opts?.threadId;
|
|
206
|
+
// Chunk on the RAW markdown so fences/paragraphs aren't shredded, then
|
|
207
|
+
// convert each chunk to Telegram HTML and send. A chunk whose HTML is
|
|
208
|
+
// empty (syntax-only) or that Telegram rejects with a parse error is
|
|
209
|
+
// re-sent as plain text.
|
|
210
|
+
const chunks = chunkText(text, { limit: TELEGRAM_TEXT_LIMIT });
|
|
211
|
+
for (const chunk of chunks) {
|
|
212
|
+
const html = markdownToTelegramHtml(chunk);
|
|
213
|
+
if (telegramHtmlIsEmpty(html)) {
|
|
214
|
+
// Nothing renderable — send the raw chunk as plain text (if it has any).
|
|
215
|
+
if (chunk.trim().length > 0) {
|
|
216
|
+
await connection.sendText(conversationId, chunk, { threadId });
|
|
217
|
+
}
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
await connection.sendText(conversationId, html, { html: true, threadId });
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
225
|
+
if (PARSE_ERROR_RE.test(msg) && chunk.trim().length > 0) {
|
|
226
|
+
// HTML failed to parse — fall back to the plain chunk.
|
|
227
|
+
await connection.sendText(conversationId, chunk, { threadId });
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
throw err;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
// Telegram ids are numeric user/chat ids and @usernames, so the pairing
|
|
236
|
+
// challenge card uses the "Your username" line.
|
|
237
|
+
pairing: { idLabel: "username" },
|
|
238
|
+
// Token-based setup wizard — `brigade channels add --channel telegram`
|
|
239
|
+
// prompts for the bot token and writes `channels.telegram.botToken`.
|
|
240
|
+
setup: {
|
|
241
|
+
credentialKeys: [
|
|
242
|
+
{
|
|
243
|
+
key: "botToken",
|
|
244
|
+
prompt: "Telegram bot token (from @BotFather)",
|
|
245
|
+
secret: true,
|
|
246
|
+
envVar: "TELEGRAM_BOT_TOKEN",
|
|
247
|
+
docsUrl: "https://core.telegram.org/bots#botfather",
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
validateInput(key, value) {
|
|
251
|
+
if (key !== "botToken")
|
|
252
|
+
return null;
|
|
253
|
+
const v = value.trim();
|
|
254
|
+
// @BotFather tokens look like `<digits>:<35-ish base64url chars>`.
|
|
255
|
+
if (/^\d{6,}:[A-Za-z0-9_-]{30,}$/.test(v))
|
|
256
|
+
return null;
|
|
257
|
+
// Allow a `${VAR}` ref through (resolved at runtime).
|
|
258
|
+
if (/^\$\{[A-Z_][A-Z0-9_]*\}$/.test(v))
|
|
259
|
+
return null;
|
|
260
|
+
return "That doesn't look like a bot token — expected `123456:ABC-DEF…` from @BotFather.";
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
async sendMedia(conversationId, media) {
|
|
264
|
+
if (!connection)
|
|
265
|
+
throw new Error("Telegram channel is not started");
|
|
266
|
+
await connection.sendMedia(conversationId, media);
|
|
267
|
+
},
|
|
268
|
+
// Outbound poll. Not part of the base `ChannelAdapter` contract — exposed as
|
|
269
|
+
// an extra method the plugin outbound + a typed accessor reach. Returns the
|
|
270
|
+
// poll message's id (string) so the agent can later act on it.
|
|
271
|
+
async sendPoll(conversationId, poll, opts) {
|
|
272
|
+
if (!connection)
|
|
273
|
+
throw new Error("Telegram channel is not started");
|
|
274
|
+
const normalized = normalizePollSpec(poll);
|
|
275
|
+
const sent = await connection.sendPoll(conversationId, normalized, {
|
|
276
|
+
...(opts?.threadId !== undefined ? { threadId: opts.threadId } : {}),
|
|
277
|
+
});
|
|
278
|
+
return { messageId: String(sent.messageId) };
|
|
279
|
+
},
|
|
280
|
+
async react(conversationId, messageId, emoji) {
|
|
281
|
+
if (!connection)
|
|
282
|
+
return; // cosmetic — refuse silently when not started
|
|
283
|
+
await connection.react(conversationId, messageId, emoji);
|
|
284
|
+
},
|
|
285
|
+
async setComposing(conversationId, state) {
|
|
286
|
+
if (!connection)
|
|
287
|
+
return;
|
|
288
|
+
await connection.setComposing(conversationId, state);
|
|
289
|
+
},
|
|
290
|
+
// Static capability flags. The central `message_action` tool PRE-CHECKS the
|
|
291
|
+
// relevant flag here before calling `handleAction`, so an unsupported action
|
|
292
|
+
// fails cleanly without touching the adapter. Telegram supports edit
|
|
293
|
+
// (editMessageText), unsend (deleteMessage), reactions (setMessageReaction),
|
|
294
|
+
// reply (sendText with a thread), threads (forum topics), media, polls, and
|
|
295
|
+
// the native command menu.
|
|
296
|
+
capabilities: TELEGRAM_CAPABILITIES,
|
|
297
|
+
// Native inline-button approvals. When a channel-routed turn raises an
|
|
298
|
+
// approval, the central router calls `sendApprovalPrompt` to render the
|
|
299
|
+
// question as buttons (payloads from the central codec); the press comes
|
|
300
|
+
// back as `InboundMessage.callbackQuery` and is resolved centrally. A
|
|
301
|
+
// pathological approval id that can't fit the 64-byte button budget falls
|
|
302
|
+
// back to the text prompt (the router sends text when this throws/returns
|
|
303
|
+
// without a keyboard — here we throw so the router's catch path runs).
|
|
304
|
+
approvalCapability: {
|
|
305
|
+
async sendApprovalPrompt(params) {
|
|
306
|
+
if (!connection)
|
|
307
|
+
throw new Error("Telegram channel is not started");
|
|
308
|
+
const keyboard = buildTelegramApprovalKeyboard({ approvalId: params.approvalId });
|
|
309
|
+
if (!keyboard) {
|
|
310
|
+
// Too few byte-safe buttons — let the router fall back to text.
|
|
311
|
+
throw new Error("telegram approval prompt: approval id too long for inline buttons");
|
|
312
|
+
}
|
|
313
|
+
const text = buildTelegramApprovalText({
|
|
314
|
+
command: params.command,
|
|
315
|
+
approvalKind: params.approvalKind,
|
|
316
|
+
...(params.toolName !== undefined ? { toolName: params.toolName } : {}),
|
|
317
|
+
});
|
|
318
|
+
// Send with the inline keyboard via the dedicated interactive path.
|
|
319
|
+
await connection.sendInteractive(params.conversationId, text, keyboard, {
|
|
320
|
+
...(params.threadId !== undefined ? { threadId: params.threadId } : {}),
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
authorizeApprover(p) {
|
|
324
|
+
return resolveTelegramApprover({
|
|
325
|
+
cfg: p.cfg,
|
|
326
|
+
...(p.senderId !== undefined ? { senderId: p.senderId } : {}),
|
|
327
|
+
...(p.accountId !== undefined ? { accountId: p.accountId } : {}),
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
// Edit / delete / react / pin / unpin a message. The manager pre-checks the
|
|
332
|
+
// capability flag (above) before calling, so an action only reaches here
|
|
333
|
+
// when Telegram advertised support for it. Edit text is already sanitized +
|
|
334
|
+
// HTML-formatted centrally? No — `message_action` sanitizes <think> leaks
|
|
335
|
+
// but the HTML formatting is ours, so run `edit` text through the same
|
|
336
|
+
// markdown→HTML converter the reply path uses.
|
|
337
|
+
async handleAction(p) {
|
|
338
|
+
if (!connection)
|
|
339
|
+
return { ok: false, error: "Telegram channel is not started" };
|
|
340
|
+
if (tokenInvalid || connection.isTokenInvalid()) {
|
|
341
|
+
return { ok: false, error: "Telegram token is invalid — re-token before acting on messages." };
|
|
342
|
+
}
|
|
343
|
+
const a = p.action;
|
|
344
|
+
try {
|
|
345
|
+
switch (a.kind) {
|
|
346
|
+
case "edit": {
|
|
347
|
+
// Run the new text through the Telegram HTML formatter (same as
|
|
348
|
+
// the reply path); fall back to plain text on a parse error.
|
|
349
|
+
const html = markdownToTelegramHtml(a.text);
|
|
350
|
+
if (telegramHtmlIsEmpty(html)) {
|
|
351
|
+
await connection.editMessageText(p.conversationId, a.messageId, a.text);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
try {
|
|
355
|
+
await connection.editMessageText(p.conversationId, a.messageId, html, { html: true });
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
const m = err instanceof Error ? err.message : String(err);
|
|
359
|
+
if (PARSE_ERROR_RE.test(m)) {
|
|
360
|
+
await connection.editMessageText(p.conversationId, a.messageId, a.text);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
throw err;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return { ok: true, messageId: a.messageId };
|
|
368
|
+
}
|
|
369
|
+
case "delete":
|
|
370
|
+
await connection.deleteMessage(p.conversationId, a.messageId);
|
|
371
|
+
return { ok: true, messageId: a.messageId };
|
|
372
|
+
case "react":
|
|
373
|
+
await connection.react(p.conversationId, a.messageId, a.emoji);
|
|
374
|
+
return { ok: true, messageId: a.messageId };
|
|
375
|
+
case "pin":
|
|
376
|
+
await connection.pinMessage(p.conversationId, a.messageId);
|
|
377
|
+
return { ok: true, messageId: a.messageId };
|
|
378
|
+
case "unpin":
|
|
379
|
+
await connection.unpinMessage(p.conversationId, a.messageId);
|
|
380
|
+
return { ok: true, messageId: a.messageId };
|
|
381
|
+
case "reply": {
|
|
382
|
+
// A reply is just a threaded send; surface the new id.
|
|
383
|
+
const sent = await connection.sendText(p.conversationId, a.text, {
|
|
384
|
+
...(a.threadId !== undefined ? { threadId: a.threadId } : {}),
|
|
385
|
+
});
|
|
386
|
+
return { ok: true, messageId: String(sent.messageId) };
|
|
387
|
+
}
|
|
388
|
+
default:
|
|
389
|
+
return { ok: false, error: `unsupported action kind` };
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
selfId() {
|
|
397
|
+
return connection?.selfId() ?? undefined;
|
|
398
|
+
},
|
|
399
|
+
connectedAt() {
|
|
400
|
+
return connection?.connectedAt() ?? null;
|
|
401
|
+
},
|
|
402
|
+
feedWebhookUpdate(update) {
|
|
403
|
+
// Defensive: only dispatch a plausibly-shaped update object.
|
|
404
|
+
if (!connection || !update || typeof update !== "object")
|
|
405
|
+
return;
|
|
406
|
+
connection.feedUpdate(update);
|
|
407
|
+
},
|
|
408
|
+
transportMode() {
|
|
409
|
+
return connection ? connection.mode() : "unstarted";
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
/**
|
|
413
|
+
* Best-effort forum-topic auto-label: on the FIRST message seen on a thread
|
|
414
|
+
* (this process), rename the topic from the message text. Fire-and-forget so
|
|
415
|
+
* it never delays inbound delivery; the connection swallows API errors.
|
|
416
|
+
*/
|
|
417
|
+
function maybeAutoLabelThread(conversationId, threadId, text) {
|
|
418
|
+
const key = `${conversationId}:${threadId}`;
|
|
419
|
+
if (autoLabeledThreads.has(key))
|
|
420
|
+
return;
|
|
421
|
+
autoLabeledThreads.add(key);
|
|
422
|
+
const name = deriveTopicName(text);
|
|
423
|
+
if (!name)
|
|
424
|
+
return;
|
|
425
|
+
void connection?.editForumTopic(conversationId, threadId, name);
|
|
426
|
+
}
|
|
427
|
+
return adapter;
|
|
428
|
+
}
|
|
429
|
+
/** Static Telegram capability flags (shared by the legacy adapter + plugin meta). */
|
|
430
|
+
export const TELEGRAM_CAPABILITIES = {
|
|
431
|
+
chatTypes: ["direct", "group", "thread"],
|
|
432
|
+
reactions: true,
|
|
433
|
+
edit: true,
|
|
434
|
+
unsend: true,
|
|
435
|
+
reply: true,
|
|
436
|
+
threads: true,
|
|
437
|
+
media: true,
|
|
438
|
+
polls: true,
|
|
439
|
+
nativeCommands: true,
|
|
440
|
+
};
|
|
441
|
+
/** Telegram allows 2–10 poll options; clamp + require a non-empty question. */
|
|
442
|
+
function normalizePollSpec(poll) {
|
|
443
|
+
const question = (poll.question ?? "").trim();
|
|
444
|
+
if (!question)
|
|
445
|
+
throw new Error("Telegram poll: a non-empty question is required.");
|
|
446
|
+
const options = (poll.options ?? []).map((o) => String(o).trim()).filter(Boolean).slice(0, 10);
|
|
447
|
+
if (options.length < 2)
|
|
448
|
+
throw new Error("Telegram poll: at least 2 options are required.");
|
|
449
|
+
return {
|
|
450
|
+
question: question.length > 300 ? question.slice(0, 300) : question,
|
|
451
|
+
options,
|
|
452
|
+
...(poll.isAnonymous !== undefined ? { isAnonymous: poll.isAnonymous } : {}),
|
|
453
|
+
...(poll.allowsMultipleAnswers !== undefined ? { allowsMultipleAnswers: poll.allowsMultipleAnswers } : {}),
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Derive a forum-topic name from a message's first line. Telegram caps topic
|
|
458
|
+
* names at 128 chars; we use the first line, collapsed + trimmed, clamped to a
|
|
459
|
+
* readable length. Returns "" when nothing usable remains.
|
|
460
|
+
*/
|
|
461
|
+
export function deriveTopicName(text) {
|
|
462
|
+
const firstLine = (text.split(/\r?\n/, 1)[0] ?? "").replace(/\s+/g, " ").trim();
|
|
463
|
+
if (!firstLine)
|
|
464
|
+
return "";
|
|
465
|
+
return firstLine.length > 64 ? `${firstLine.slice(0, 63)}…` : firstLine;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Defensive config fallback for a direct `start()` that skipped `isConfigured`
|
|
469
|
+
* (the manager always calls isConfigured first, so this is the rare path). Sync
|
|
470
|
+
* + cached — `loadConfig` carries no heavy deps.
|
|
471
|
+
*/
|
|
472
|
+
async function loadStartConfig() {
|
|
473
|
+
return loadConfig();
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../src/agents/channels/telegram/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram `allowed_updates` resolver.
|
|
3
|
+
*
|
|
4
|
+
* Telegram's `getUpdates` / `setWebhook` take an `allowed_updates` allow-list:
|
|
5
|
+
* only the named update kinds are delivered. Brigade subscribes the MINIMAL set
|
|
6
|
+
* its central pipeline actually consumes — keeping the firehose narrow means a
|
|
7
|
+
* chatty group never floods the poller with update kinds Brigade ignores
|
|
8
|
+
* (business messages, channel posts, inline queries, shipping/checkout, …, all
|
|
9
|
+
* of which the reference upstream subscribes but Brigade has no consumer for).
|
|
10
|
+
*
|
|
11
|
+
* The base set is always:
|
|
12
|
+
* - `message` — the inbound text/media path (the core surface).
|
|
13
|
+
* - `callback_query` — inline-button presses (interactive approvals). Without
|
|
14
|
+
* this in the list, a button tap is silently never delivered and the
|
|
15
|
+
* approval prompt hangs for its full timeout. Subscribed unconditionally so
|
|
16
|
+
* a button rendered by `sendApprovalPrompt` is always answerable.
|
|
17
|
+
*
|
|
18
|
+
* Conditionally added:
|
|
19
|
+
* - `message_reaction` — only when the channel opts into reaction inbound
|
|
20
|
+
* handling (`opts.reactions`). Brigade does not route inbound reactions to a
|
|
21
|
+
* turn today, so it is OFF by default; the flag exists so a future reaction-
|
|
22
|
+
* trigger feature can switch it on without touching the poller wiring.
|
|
23
|
+
* - `edited_message` — only when `opts.editedMessages` (off by default;
|
|
24
|
+
* Brigade treats an edit as a no-op rather than re-running the turn).
|
|
25
|
+
*
|
|
26
|
+
* Output is always a DEDUPED, STABLE-ORDER array of plain lowercase ASCII update
|
|
27
|
+
* names (no NUL / control bytes — these are fixed string literals).
|
|
28
|
+
*/
|
|
29
|
+
/** One Telegram update kind Brigade may subscribe. */
|
|
30
|
+
export type TelegramAllowedUpdate = "message" | "callback_query" | "message_reaction" | "edited_message";
|
|
31
|
+
/** Options gating the conditional update kinds. */
|
|
32
|
+
export interface ResolveTelegramAllowedUpdatesOptions {
|
|
33
|
+
/** Subscribe `message_reaction` (inbound reaction events). Default false. */
|
|
34
|
+
reactions?: boolean;
|
|
35
|
+
/** Subscribe `edited_message` (inbound message edits). Default false. */
|
|
36
|
+
editedMessages?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the `allowed_updates` list Brigade's Telegram poller/webhook should
|
|
40
|
+
* request. `message` + `callback_query` are always present; reactions / edited
|
|
41
|
+
* messages are added only when explicitly enabled. Deduped + stable order.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveTelegramAllowedUpdates(opts?: ResolveTelegramAllowedUpdatesOptions): TelegramAllowedUpdate[];
|
|
44
|
+
//# sourceMappingURL=allowed-updates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowed-updates.d.ts","sourceRoot":"","sources":["../../../../src/agents/channels/telegram/allowed-updates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,sDAAsD;AACtD,MAAM,MAAM,qBAAqB,GAC9B,SAAS,GACT,gBAAgB,GAChB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,mDAAmD;AACnD,MAAM,WAAW,oCAAoC;IACpD,6EAA6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC5C,IAAI,GAAE,oCAAyC,GAC7C,qBAAqB,EAAE,CAczB"}
|