

























@@ -11,14 +11,8 @@ import {
1111createChatChannelPlugin,
1212} from "openclaw/plugin-sdk/channel-core";
1313import { createAccountStatusSink } from "openclaw/plugin-sdk/channel-lifecycle";
14-import {
15-createMessageReceiptFromOutboundResults,
16-defineChannelMessageAdapter,
17-type ChannelMessageSendResult,
18-type MessageReceiptPartKind,
19-} from "openclaw/plugin-sdk/channel-message";
14+import { createChannelMessageAdapterFromOutbound } from "openclaw/plugin-sdk/channel-message";
2015import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
21-import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
2216import {
2317PAIRING_APPROVED_MESSAGE,
2418buildTokenChannelStatusSummary,
@@ -62,9 +56,8 @@ import {
6256import { resolveTelegramInlineButtonsScope } from "./inline-buttons.js";
6357import * as monitorModule from "./monitor.js";
6458import { looksLikeTelegramTargetId, normalizeTelegramMessagingTarget } from "./normalize.js";
65-import { sendTelegramPayloadMessages } from "./outbound-adapter.js";
66-import { telegramOutboundBaseAdapter } from "./outbound-base.js";
67-import { parseTelegramReplyToMessageId, parseTelegramThreadId } from "./outbound-params.js";
59+import { createTelegramOutboundAdapter } from "./outbound-adapter.js";
60+import { parseTelegramThreadId } from "./outbound-params.js";
6861import type { TelegramProbe } from "./probe.js";
6962import * as probeModule from "./probe.js";
7063import { resolveTelegramReactionLevel } from "./reaction-level.js";
@@ -108,8 +101,6 @@ async function loadTelegramUpdateOffsetRuntime() {
108101return await telegramUpdateOffsetRuntimePromise;
109102}
110103111-type TelegramSendOptions = NonNullable<Parameters<TelegramSendFn>[2]>;
112-113104function resolveTelegramProbe() {
114105return (
115106getOptionalTelegramRuntime()?.channel?.telegram?.probeTelegram ?? probeModule.probeTelegram
@@ -169,115 +160,39 @@ function resolveTelegramTokenHelper() {
169160);
170161}
171162172-function buildTelegramSendOptions(params: {
173-cfg: OpenClawConfig;
174-mediaUrl?: string | null;
175-mediaLocalRoots?: readonly string[] | null;
176-mediaReadFile?: ((filePath: string) => Promise<Buffer>) | null;
177-accountId?: string | null;
178-replyToId?: string | null;
179-threadId?: string | number | null;
180-silent?: boolean | null;
181-forceDocument?: boolean | null;
182-gatewayClientScopes?: readonly string[] | null;
183-}): TelegramSendOptions {
184-return {
185-verbose: false,
186-cfg: params.cfg,
187- ...(params.mediaUrl ? { mediaUrl: params.mediaUrl } : {}),
188- ...(params.mediaLocalRoots?.length ? { mediaLocalRoots: params.mediaLocalRoots } : {}),
189- ...(params.mediaReadFile ? { mediaReadFile: params.mediaReadFile } : {}),
190-messageThreadId: parseTelegramThreadId(params.threadId),
191-replyToMessageId: parseTelegramReplyToMessageId(params.replyToId),
192-accountId: params.accountId ?? undefined,
193-silent: params.silent ?? undefined,
194-forceDocument: params.forceDocument ?? undefined,
195- ...(Array.isArray(params.gatewayClientScopes)
196- ? { gatewayClientScopes: [...params.gatewayClientScopes] }
197- : {}),
198-};
199-}
200-201-async function sendTelegramOutbound(params: {
202-cfg: OpenClawConfig;
203-to: string;
204-text: string;
205-mediaUrl?: string | null;
206-mediaLocalRoots?: readonly string[] | null;
207-mediaReadFile?: ((filePath: string) => Promise<Buffer>) | null;
208-accountId?: string | null;
209-deps?: OutboundSendDeps;
210-replyToId?: string | null;
211-threadId?: string | number | null;
212-silent?: boolean | null;
213-forceDocument?: boolean | null;
214-gatewayClientScopes?: readonly string[] | null;
215-}) {
216-const send = await resolveTelegramSend(params.deps);
217-return await send(
218-params.to,
219-params.text,
220-buildTelegramSendOptions({
221-cfg: params.cfg,
222-mediaUrl: params.mediaUrl,
223-mediaLocalRoots: params.mediaLocalRoots,
224-mediaReadFile: params.mediaReadFile,
225-accountId: params.accountId,
226-replyToId: params.replyToId,
227-threadId: params.threadId,
228-silent: params.silent,
229-forceDocument: params.forceDocument,
230-gatewayClientScopes: params.gatewayClientScopes,
163+const telegramChannelOutbound = createTelegramOutboundAdapter({
164+resolveSend: resolveTelegramSend,
165+loadSendModule: loadTelegramSendModule,
166+shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload }) =>
167+shouldSuppressLocalTelegramExecApprovalPrompt({
168+ cfg,
169+ accountId,
170+ payload,
231171}),
232-);
233-}
234-235-type TelegramMessageSendSourceResult = {
236-messageId?: string;
237-chatId?: string;
238-receipt?: ChannelMessageSendResult["receipt"];
239-};
240-241-function toTelegramMessageSendResult(
242-result: TelegramMessageSendSourceResult,
243-kind: MessageReceiptPartKind,
244-replyToId?: string | null,
245-): ChannelMessageSendResult {
246-const receipt =
247-result.receipt ??
248-createMessageReceiptFromOutboundResults({
249-results: result.messageId
250- ? [
251-{
252-channel: "telegram",
253-messageId: result.messageId,
254-chatId: result.chatId,
255-},
256-]
257- : [],
258- kind,
259- ...(replyToId ? { replyToId } : {}),
260-});
261-return {
262-messageId: result.messageId || receipt.primaryPlatformMessageId,
263- receipt,
264-};
265-}
172+beforeDeliverPayload: async ({ cfg, target, hint }) => {
173+if (hint?.kind !== "approval-pending" || hint.approvalKind !== "exec") {
174+return;
175+}
176+const threadId =
177+typeof target.threadId === "number"
178+ ? target.threadId
179+ : typeof target.threadId === "string"
180+ ? Number.parseInt(target.threadId, 10)
181+ : undefined;
182+const { sendTypingTelegram } = await loadTelegramSendModule();
183+await sendTypingTelegram(target.to, {
184+ cfg,
185+accountId: target.accountId ?? undefined,
186+ ...(Number.isFinite(threadId) ? { messageThreadId: threadId } : {}),
187+}).catch(() => {});
188+},
189+shouldTreatDeliveredTextAsVisible: shouldTreatTelegramDeliveredTextAsVisible,
190+targetsMatchForReplySuppression: targetsMatchTelegramReplySuppression,
191+preferFinalAssistantVisibleText: true,
192+});
266193267-const telegramMessageAdapter = defineChannelMessageAdapter({
194+const telegramMessageAdapter = createChannelMessageAdapterFromOutbound<OpenClawConfig>({
268195id: "telegram",
269-durableFinal: {
270-capabilities: {
271-text: true,
272-media: true,
273-payload: true,
274-silent: true,
275-replyTo: true,
276-thread: true,
277-messageSendingHooks: true,
278-batch: true,
279-},
280-},
281196live: {
282197capabilities: {
283198draftPreview: true,
@@ -297,70 +212,7 @@ const telegramMessageAdapter = defineChannelMessageAdapter({
297212defaultAckPolicy: "after_agent_dispatch",
298213supportedAckPolicies: ["after_receive_record", "after_agent_dispatch"],
299214},
300-send: {
301-text: async (ctx) =>
302-toTelegramMessageSendResult(
303-await sendTelegramOutbound({
304-cfg: ctx.cfg,
305-to: ctx.to,
306-text: ctx.text,
307-accountId: ctx.accountId,
308-deps: ctx.deps,
309-replyToId: ctx.replyToId,
310-threadId: ctx.threadId,
311-silent: ctx.silent,
312-gatewayClientScopes: ctx.gatewayClientScopes,
313-}),
314-"text",
315-ctx.replyToId,
316-),
317-media: async (ctx) =>
318-toTelegramMessageSendResult(
319-await sendTelegramOutbound({
320-cfg: ctx.cfg,
321-to: ctx.to,
322-text: ctx.text,
323-mediaUrl: ctx.mediaUrl,
324-mediaLocalRoots: ctx.mediaLocalRoots,
325-mediaReadFile: ctx.mediaReadFile,
326-accountId: ctx.accountId,
327-deps: ctx.deps,
328-replyToId: ctx.replyToId,
329-threadId: ctx.threadId,
330-silent: ctx.silent,
331-forceDocument: ctx.forceDocument,
332-gatewayClientScopes: ctx.gatewayClientScopes,
333-}),
334-"media",
335-ctx.replyToId,
336-),
337-payload: async (ctx) => {
338-const send = await resolveTelegramSend(ctx.deps);
339-const result = attachChannelToResult(
340-"telegram",
341-await sendTelegramPayloadMessages({
342- send,
343-to: ctx.to,
344-payload: ctx.payload,
345-baseOpts: {
346- ...buildTelegramSendOptions({
347-cfg: ctx.cfg,
348-mediaUrl: ctx.mediaUrl,
349-mediaLocalRoots: ctx.mediaLocalRoots,
350-accountId: ctx.accountId,
351-replyToId: ctx.replyToId,
352-threadId: ctx.threadId,
353-silent: ctx.silent,
354-forceDocument: ctx.forceDocument,
355-gatewayClientScopes: ctx.gatewayClientScopes,
356-}),
357- ...(ctx.mediaReadFile ? { mediaReadFile: ctx.mediaReadFile } : {}),
358-},
359-}),
360-);
361-return toTelegramMessageSendResult(result, "unknown", ctx.replyToId);
362-},
363-},
215+outbound: telegramChannelOutbound,
364216});
365217366218const telegramMessageActions: ChannelMessageActionAdapter = {
@@ -1179,142 +1031,5 @@ export const telegramPlugin = createChatChannelPlugin({
11791031return to.includes(":topic:") ? to : `${to}:topic:${threadId}`;
11801032},
11811033},
1182-outbound: {
1183-base: {
1184- ...telegramOutboundBaseAdapter,
1185-shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload }) =>
1186-shouldSuppressLocalTelegramExecApprovalPrompt({
1187- cfg,
1188- accountId,
1189- payload,
1190-}),
1191-beforeDeliverPayload: async ({ cfg, target, hint }) => {
1192-if (hint?.kind !== "approval-pending" || hint.approvalKind !== "exec") {
1193-return;
1194-}
1195-const threadId =
1196-typeof target.threadId === "number"
1197- ? target.threadId
1198- : typeof target.threadId === "string"
1199- ? Number.parseInt(target.threadId, 10)
1200- : undefined;
1201-const { sendTypingTelegram } = await loadTelegramSendModule();
1202-await sendTypingTelegram(target.to, {
1203- cfg,
1204-accountId: target.accountId ?? undefined,
1205- ...(Number.isFinite(threadId) ? { messageThreadId: threadId } : {}),
1206-}).catch(() => {});
1207-},
1208-shouldSkipPlainTextSanitization: ({ payload }) => Boolean(payload.channelData),
1209-shouldTreatDeliveredTextAsVisible: shouldTreatTelegramDeliveredTextAsVisible,
1210-preferFinalAssistantVisibleText: true,
1211-targetsMatchForReplySuppression: targetsMatchTelegramReplySuppression,
1212-resolveEffectiveTextChunkLimit: ({ fallbackLimit }) =>
1213-typeof fallbackLimit === "number" ? Math.min(fallbackLimit, 4096) : 4096,
1214-supportsPollDurationSeconds: true,
1215-supportsAnonymousPolls: true,
1216-sendPayload: async ({
1217- cfg,
1218- to,
1219- payload,
1220- mediaLocalRoots,
1221- accountId,
1222- deps,
1223- replyToId,
1224- threadId,
1225- silent,
1226- forceDocument,
1227- gatewayClientScopes,
1228-}) => {
1229-const send = await resolveTelegramSend(deps);
1230-const result = await sendTelegramPayloadMessages({
1231- send,
1232- to,
1233- payload,
1234-baseOpts: buildTelegramSendOptions({
1235- cfg,
1236- mediaLocalRoots,
1237- accountId,
1238- replyToId,
1239- threadId,
1240- silent,
1241- forceDocument,
1242- gatewayClientScopes,
1243-}),
1244-});
1245-return attachChannelToResult("telegram", result);
1246-},
1247-},
1248-attachedResults: {
1249-channel: "telegram",
1250-sendText: async ({
1251- cfg,
1252- to,
1253- text,
1254- accountId,
1255- deps,
1256- replyToId,
1257- threadId,
1258- silent,
1259- gatewayClientScopes,
1260-}) =>
1261-await sendTelegramOutbound({
1262- cfg,
1263- to,
1264- text,
1265- accountId,
1266- deps,
1267- replyToId,
1268- threadId,
1269- silent,
1270- gatewayClientScopes,
1271-}),
1272-sendMedia: async ({
1273- cfg,
1274- to,
1275- text,
1276- mediaUrl,
1277- mediaLocalRoots,
1278- accountId,
1279- deps,
1280- replyToId,
1281- threadId,
1282- silent,
1283- gatewayClientScopes,
1284-}) =>
1285-await sendTelegramOutbound({
1286- cfg,
1287- to,
1288- text,
1289- mediaUrl,
1290- mediaLocalRoots,
1291- accountId,
1292- deps,
1293- replyToId,
1294- threadId,
1295- silent,
1296- gatewayClientScopes,
1297-}),
1298-sendPoll: async ({
1299- cfg,
1300- to,
1301- poll,
1302- accountId,
1303- threadId,
1304- silent,
1305- isAnonymous,
1306- gatewayClientScopes,
1307-}) => {
1308-const { sendPollTelegram } = await loadTelegramSendModule();
1309-return await sendPollTelegram(to, poll, {
1310- cfg,
1311-accountId: accountId ?? undefined,
1312-messageThreadId: parseTelegramThreadId(threadId),
1313-silent: silent ?? undefined,
1314-isAnonymous: isAnonymous ?? undefined,
1315- gatewayClientScopes,
1316-});
1317-},
1318-},
1319-},
1034+outbound: telegramChannelOutbound,
13201035});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。