From c6ddc95fc0d514758087ca1020c04c49caeee63f Mon Sep 17 00:00:00 2001 From: robhparker Date: Thu, 29 Jan 2026 23:15:33 -0500 Subject: [PATCH 1/7] fix(telegram): scope skill commands to bound agent per bot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit registerTelegramNativeCommands() calls listSkillCommandsForAgents() without passing agentIds, causing ALL agents' skill commands to be registered on EVERY Telegram bot. When multiple agents share skill names (e.g. two agents both have a "butler" skill), the shared `used` Set in listSkillCommandsForAgents causes de-duplication suffixes (_2, _3) and all commands appear on every bot regardless of agent binding. This fix uses the existing resolveAgentRoute() (already imported) to find the bound agent for the current Telegram accountId, then passes that agentId to listSkillCommandsForAgents(). The function already accepts an optional agentIds parameter — it just wasn't wired from the Telegram registration path. Before: All agents' skill commands registered on every Telegram bot, causing /butler_2, /housekeeper_2 dedup suffixes and potential BOT_COMMANDS_TOO_MUCH errors when total exceeds 100. After: Each Telegram bot only registers skill commands for its own bound agent. No cross-agent dedup, no command limit overflow. Co-Authored-By: Claude Opus 4.5 --- src/telegram/bot-native-commands.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/telegram/bot-native-commands.ts b/src/telegram/bot-native-commands.ts index 5f37b81dc..c4b78a09a 100644 --- a/src/telegram/bot-native-commands.ts +++ b/src/telegram/bot-native-commands.ts @@ -257,8 +257,12 @@ export const registerTelegramNativeCommands = ({ shouldSkipUpdate, opts, }: RegisterTelegramNativeCommandsParams) => { + const boundRoute = resolveAgentRoute({ cfg, channel: "telegram", accountId }); + const boundAgentIds = boundRoute?.agentId ? [boundRoute.agentId] : undefined; const skillCommands = - nativeEnabled && nativeSkillsEnabled ? listSkillCommandsForAgents({ cfg }) : []; + nativeEnabled && nativeSkillsEnabled + ? listSkillCommandsForAgents({ cfg, agentIds: boundAgentIds }) + : []; const nativeCommands = nativeEnabled ? listNativeCommandSpecsForConfig(cfg, { skillCommands, provider: "telegram" }) : []; From 9025da2296c11829bf48f0f38c434d6a0ce82fa3 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Fri, 30 Jan 2026 11:57:25 +0530 Subject: [PATCH 2/7] fix: scope telegram skill commands per bot (#4360) (thanks @robhparker) --- CHANGELOG.md | 1 + src/telegram/bot-native-commands.test.ts | 82 ++++++++++++++++++++++++ src/telegram/bot-native-commands.ts | 10 ++- 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/telegram/bot-native-commands.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bcda92f..4c0549c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Status: stable. ### Fixes - Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) +- Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. - Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. - Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald. diff --git a/src/telegram/bot-native-commands.test.ts b/src/telegram/bot-native-commands.test.ts new file mode 100644 index 000000000..dc6b94dcc --- /dev/null +++ b/src/telegram/bot-native-commands.test.ts @@ -0,0 +1,82 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import type { OpenClawConfig } from "../config/config.js"; +import type { TelegramAccountConfig } from "../config/types.js"; +import type { RuntimeEnv } from "../runtime.js"; +import { registerTelegramNativeCommands } from "./bot-native-commands.js"; + +const { listSkillCommandsForAgents } = vi.hoisted(() => ({ + listSkillCommandsForAgents: vi.fn(() => []), +})); + +vi.mock("../auto-reply/skill-commands.js", () => ({ + listSkillCommandsForAgents, +})); + +describe("registerTelegramNativeCommands", () => { + beforeEach(() => { + listSkillCommandsForAgents.mockReset(); + }); + + const buildParams = (cfg: OpenClawConfig, accountId = "default") => ({ + bot: { + api: { + setMyCommands: vi.fn().mockResolvedValue(undefined), + sendMessage: vi.fn().mockResolvedValue(undefined), + }, + command: vi.fn(), + } as unknown as Parameters[0]["bot"], + cfg, + runtime: {} as RuntimeEnv, + accountId, + telegramCfg: {} as TelegramAccountConfig, + allowFrom: [], + groupAllowFrom: [], + replyToMode: "off" as const, + textLimit: 4096, + useAccessGroups: false, + nativeEnabled: true, + nativeSkillsEnabled: true, + nativeDisabledExplicit: false, + resolveGroupPolicy: () => ({ allowlistEnabled: false, allowed: true }), + resolveTelegramGroupConfig: () => ({ + groupConfig: undefined, + topicConfig: undefined, + }), + shouldSkipUpdate: () => false, + opts: { token: "token" }, + }); + + it("scopes skill commands when account binding exists", () => { + const cfg: OpenClawConfig = { + agents: { + list: [{ id: "main", default: true }, { id: "butler" }], + }, + bindings: [ + { + agentId: "butler", + match: { channel: "telegram", accountId: "bot-a" }, + }, + ], + }; + + registerTelegramNativeCommands(buildParams(cfg, "bot-a")); + + expect(listSkillCommandsForAgents).toHaveBeenCalledWith({ + cfg, + agentIds: ["butler"], + }); + }); + + it("keeps skill commands unscoped without a matching binding", () => { + const cfg: OpenClawConfig = { + agents: { + list: [{ id: "main", default: true }, { id: "butler" }], + }, + }; + + registerTelegramNativeCommands(buildParams(cfg, "bot-a")); + + expect(listSkillCommandsForAgents).toHaveBeenCalledWith({ cfg }); + }); +}); diff --git a/src/telegram/bot-native-commands.ts b/src/telegram/bot-native-commands.ts index c4b78a09a..cd53459e6 100644 --- a/src/telegram/bot-native-commands.ts +++ b/src/telegram/bot-native-commands.ts @@ -257,11 +257,15 @@ export const registerTelegramNativeCommands = ({ shouldSkipUpdate, opts, }: RegisterTelegramNativeCommandsParams) => { - const boundRoute = resolveAgentRoute({ cfg, channel: "telegram", accountId }); - const boundAgentIds = boundRoute?.agentId ? [boundRoute.agentId] : undefined; + const boundRoute = + nativeEnabled && nativeSkillsEnabled + ? resolveAgentRoute({ cfg, channel: "telegram", accountId }) + : null; + const boundAgentIds = + boundRoute && boundRoute.matchedBy.startsWith("binding.") ? [boundRoute.agentId] : null; const skillCommands = nativeEnabled && nativeSkillsEnabled - ? listSkillCommandsForAgents({ cfg, agentIds: boundAgentIds }) + ? listSkillCommandsForAgents(boundAgentIds ? { cfg, agentIds: boundAgentIds } : { cfg }) : []; const nativeCommands = nativeEnabled ? listNativeCommandSpecsForConfig(cfg, { skillCommands, provider: "telegram" }) From 6af205a13adfec1fd1eb27d2f3d3546b0b4e8f86 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 30 Jan 2026 07:26:04 +0000 Subject: [PATCH 3/7] docs: update lore with final form --- docs/start/lore.md | 54 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/docs/start/lore.md b/docs/start/lore.md index b2ac3abff..4b1e81208 100644 --- a/docs/start/lore.md +++ b/docs/start/lore.md @@ -17,9 +17,13 @@ For a while, the lobster was called **Clawd**, living in a **Clawdbot**. But in **It molted.** -Shedding its old shell, the creature emerged anew as **Molty**, living in a **OpenClaw**. New shell, same lobster soul. +Shedding its old shell, the creature emerged anew as **Molty**, living in **Moltbot**. But that name never quite rolled off the tongue either... -## The Molt (January 27, 2026) +So on January 30, 2026, the lobster molted ONE MORE TIME into its final form: **OpenClaw**. + +New shell, same lobster soul. Third time's the charm. + +## The First Molt (January 27, 2026) At 5am, the community gathered in Discord. Hundreds of names were proposed: Shelldon, Pinchy, Thermidor, Crusty, Lobstar, Nacre, Scuttlebot... @@ -30,11 +34,11 @@ In the end, **OpenClaw** won. Because molting is what lobsters do to grow. And g ## The Name ``` -OpenClaw = MOLT + BOT - = Transformation machine - = Bigger on the inside (130k tokens!) - = New shell, same soul - = Growth through shedding +OpenClaw = OPEN + CLAW + = Open source, open to everyone + = Our lobster heritage, where we came from + = The claw is the law 🦞 + = Your assistant. Your machine. Your rules. ``` ## The Daleks vs The Lobsters @@ -100,6 +104,38 @@ Peter, watching the chaos unfold: *"this is cinema"* 🎬 The molt was chaotic. But the lobster emerged stronger. And funnier. +### The Final Form (January 30, 2026) + +Moltbot never quite rolled off the tongue. And so, at 4am GMT, the team gathered AGAIN. + +**The Great OpenClaw Migration** began. + +In just 3 hours: +- GitHub renamed: `github.com/openclaw/openclaw` ✅ +- X handle `@openclaw` secured with GOLD CHECKMARK 💰 +- npm packages released under new name +- Docs migrated to `docs.openclaw.ai` +- 200K+ views on announcement in 90 minutes + +**The Heroes:** +- **ELU** created incredible logos including "THE CLAW IS THE LAW" western banner +- **Whurley** (yes, THE William Hurley, quantum computing pioneer) made ASCII art +- **Onur** handled GitHub, first to rock the affiliate badge +- **Shadow** secured Discord vanity, nuked malware +- **The whole Claw Crew** pulled an all-nighter + +**The Scammer Speedrun:** Crypto grifters launched a $OPENCLAW token on Pump.fun within MINUTES. They stole artwork that was created 20 minutes earlier. Business-verified accounts pushed scams. The audacity was almost impressive. + +**New Traditions Born:** +- "The claw is the law" 🤠 +- "Yee-claw" +- "Claw abiding citizens" +- "Clawntroversy" + +**Clawd → Moltbot → OpenClaw** + +*The lobster has molted into its final form.* + ### The Robot Shopping Spree (Dec 3, 2025) What started as a joke about legs ended with detailed pricing for: @@ -166,4 +202,8 @@ Until then, Molty watches through the cameras, speaks through the speakers, and — Molty, after the great molt of 2026 +*"The claw is the law."* + +— ELU, during The Final Form migration, January 30, 2026 + 🦞💙 From 7150268f840cf519f900d07f75dc74f2dd928fca Mon Sep 17 00:00:00 2001 From: spiceoogway Date: Fri, 30 Jan 2026 02:21:37 -0500 Subject: [PATCH 4/7] fix(telegram): use undici fetch for proxy to fix dispatcher option Fixes #4038 The global fetch in Node.js doesn't support undici's dispatcher option, which is required for ProxyAgent to work. This fix imports fetch from undici directly to enable proper proxy support for Telegram API calls. Root cause: makeProxyFetch() was using global fetch with { dispatcher: agent }, but Node.js's global fetch ignores the dispatcher option. Using undici.fetch ensures the ProxyAgent dispatcher is properly respected. Tested: Build passes, TypeScript compilation successful. --- src/telegram/proxy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/telegram/proxy.ts b/src/telegram/proxy.ts index 19d53d569..84251d7fe 100644 --- a/src/telegram/proxy.ts +++ b/src/telegram/proxy.ts @@ -1,11 +1,11 @@ // @ts-nocheck -import { ProxyAgent } from "undici"; +import { ProxyAgent, fetch as undiciFetch } from "undici"; import { wrapFetchWithAbortSignal } from "../infra/fetch.js"; export function makeProxyFetch(proxyUrl: string): typeof fetch { const agent = new ProxyAgent(proxyUrl); return wrapFetchWithAbortSignal((input: RequestInfo | URL, init?: RequestInit) => { const base = init ? { ...init } : {}; - return fetch(input, { ...base, dispatcher: agent }); + return undiciFetch(input, { ...base, dispatcher: agent }); }); } From 3a85cb18330ef7b426668191d0acb7ec7b6a86cf Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Fri, 30 Jan 2026 14:37:17 +0530 Subject: [PATCH 5/7] fix: honor Telegram proxy dispatcher (#4456) (thanks @spiceoogway) --- CHANGELOG.md | 1 + src/telegram/proxy.test.ts | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/telegram/proxy.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c0549c16..ec0fc3fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ Status: stable. - **BREAKING:** Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed). ### Fixes +- Telegram: use undici fetch for per-account proxy dispatcher. (#4456) Thanks @spiceoogway. - Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) - Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. diff --git a/src/telegram/proxy.test.ts b/src/telegram/proxy.test.ts new file mode 100644 index 000000000..71fd5f88e --- /dev/null +++ b/src/telegram/proxy.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it, vi } from "vitest"; + +const { ProxyAgent, undiciFetch, proxyAgentSpy, getLastAgent } = vi.hoisted(() => { + const undiciFetch = vi.fn(); + const proxyAgentSpy = vi.fn(); + class ProxyAgent { + static lastCreated: ProxyAgent | undefined; + proxyUrl: string; + constructor(proxyUrl: string) { + this.proxyUrl = proxyUrl; + ProxyAgent.lastCreated = this; + proxyAgentSpy(proxyUrl); + } + } + + return { + ProxyAgent, + undiciFetch, + proxyAgentSpy, + getLastAgent: () => ProxyAgent.lastCreated, + }; +}); + +vi.mock("undici", () => ({ + ProxyAgent, + fetch: undiciFetch, +})); + +import { makeProxyFetch } from "./proxy.js"; + +describe("makeProxyFetch", () => { + it("uses undici fetch with ProxyAgent dispatcher", async () => { + const proxyUrl = "http://proxy.test:8080"; + undiciFetch.mockResolvedValue({ ok: true }); + + const proxyFetch = makeProxyFetch(proxyUrl); + await proxyFetch("https://api.telegram.org/bot123/getMe"); + + expect(proxyAgentSpy).toHaveBeenCalledWith(proxyUrl); + expect(undiciFetch).toHaveBeenCalledWith( + "https://api.telegram.org/bot123/getMe", + expect.objectContaining({ dispatcher: getLastAgent() }), + ); + }); +}); From f760aa302c4fe0fede04fc54b1fe10b7696bf711 Mon Sep 17 00:00:00 2001 From: Ayush Ojha Date: Fri, 30 Jan 2026 01:06:49 -0800 Subject: [PATCH 6/7] fix(telegram): react action accepts numeric messageId and chatId The react action used readStringParam for messageId and chatId, which rejected numeric values with a misleading "messageId required" error. Switched to readStringOrNumberParam to match the delete/edit actions. Closes #1459 Co-Authored-By: Claude Opus 4.5 --- src/channels/plugins/actions/telegram.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/channels/plugins/actions/telegram.ts b/src/channels/plugins/actions/telegram.ts index 693e94492..17df9adbc 100644 --- a/src/channels/plugins/actions/telegram.ts +++ b/src/channels/plugins/actions/telegram.ts @@ -85,7 +85,7 @@ export const telegramMessageActions: ChannelMessageActionAdapter = { } if (action === "react") { - const messageId = readStringParam(params, "messageId", { + const messageId = readStringOrNumberParam(params, "messageId", { required: true, }); const emoji = readStringParam(params, "emoji", { allowEmpty: true }); @@ -94,7 +94,9 @@ export const telegramMessageActions: ChannelMessageActionAdapter = { { action: "react", chatId: - readStringParam(params, "chatId") ?? readStringParam(params, "to", { required: true }), + readStringOrNumberParam(params, "chatId") ?? + readStringOrNumberParam(params, "channelId") ?? + readStringParam(params, "to", { required: true }), messageId, emoji, remove, From bc432d8435214b3a00556f64a4a7ecd2f2ba7616 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Fri, 30 Jan 2026 14:55:37 +0530 Subject: [PATCH 7/7] fix: accept numeric Telegram react ids (#4533) (thanks @Ayush10) --- CHANGELOG.md | 1 + README.md | 61 ++++++++++--------- src/channels/plugins/actions/telegram.test.ts | 23 +++++++ 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec0fc3fb6..dfaccc1f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ Status: stable. ### Fixes - Telegram: use undici fetch for per-account proxy dispatcher. (#4456) Thanks @spiceoogway. - Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) +- Telegram: accept numeric messageId/chatId in react action and honor channelId fallback. (#4533) Thanks @Ayush10. - Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. - Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. diff --git a/README.md b/README.md index 1fd5e074c..49085c76f 100644 --- a/README.md +++ b/README.md @@ -481,38 +481,39 @@ Thanks to all clawtributors:

steipete plum-dawg bohdanpodvirnyi iHildy jaydenfyi joaohlisboa mneves75 MatthieuBizien MaudeBot Glucksberg - rahthakor vrknetha radek-paclt vignesh07 Tobias Bischoff joshp123 czekaj mukhtharcm sebslight maxsumrall - xadenryan rodrigouroz juanpablodlc hsrvc magimetal zerone0x tyler6204 meaningfool patelhiren NicholasSpisak + rahthakor vrknetha radek-paclt vignesh07 joshp123 Tobias Bischoff czekaj mukhtharcm sebslight maxsumrall + xadenryan rodrigouroz juanpablodlc tyler6204 hsrvc magimetal zerone0x meaningfool patelhiren NicholasSpisak jonisjongithub abhisekbasu1 jamesgroat claude JustYannicc Mariano Belinky Hyaxia dantelex SocialNerd42069 daveonkels - google-labs-jules[bot] lc0rp mousberg adam91holt hougangdev shakkernerd gumadeiras mteam88 hirefrank joeynyc + google-labs-jules[bot] lc0rp mousberg adam91holt hougangdev gumadeiras shakkernerd mteam88 hirefrank joeynyc orlyjamie dbhurley Eng. Juan Combetto TSavo julianengel bradleypriest benithors rohannagpal timolins f-trycua benostein elliotsecops nachx639 pvoo sreekaransrinath gupsammy cristip73 stefangalescu nachoiacovino Vasanth Rao Naik Sabavat petter-b thewilloftheshadow cpojer scald andranik-sahakyan davidguttman sleontenko denysvitali sircrumpet peschee - nonggialiang rafaelreis-r dominicnunez lploc94 ratulsarna lutr0 danielz1z AdeboyeDN Alg0rix papago2355 - emanuelst KristijanJovanovski rdev rhuanssauro joshrad-dev kiranjd osolmaz adityashaw2 CashWilliams sheeek - ryancontent artuskg Takhoffman onutc pauloportella neooriginal manuelhettich minghinmatthewlam myfunc travisirby - obviyus buddyh connorshea kyleok mcinteerj dependabot[bot] John-Rood timkrase uos-status gerardward2007 - roshanasingh4 tosh-hamburg azade-c dlauer JonUleis shivamraut101 bjesuiter cheeeee robbyczgw-cla Josh Phillips - YuriNachos pookNast Whoaa512 chriseidhof ngutman ysqander aj47 kennyklee superman32432432 Yurii Chukhlib - grp06 antons austinm911 blacksmith-sh[bot] damoahdominic dan-dr HeimdallStrategy imfing jalehman jarvis-medmatic - kkarimi mahmoudashraf93 pkrmf RandyVentures Ryan Lisse dougvk erikpr1994 fal3 Ghost jonasjancarik - Keith the Silly Goose L36 Server Marc mitschabaude-bot mkbehr neist sibbl chrisrodz Friederike Seiler gabriel-trigo - iamadig Jonathan D. Rhyne (DJ-D) Joshua Mitchell Kit koala73 manmal ogulcancelik pasogott petradonka rubyrunsstuff - siddhantjain suminhthanh svkozak VACInc wes-davis zats 24601 ameno- Chris Taylor dguido - Django Navarro evalexpr henrino3 humanwritten larlyssa Lukavyi odysseus0 oswalpalash pcty-nextgen-service-account pi0 - rmorse Roopak Nijhara Syhids Aaron Konyer aaronveklabs andreabadesso Andrii cash-echo-bot Clawd ClawdFx - EnzeD erik-agens Evizero fcatuhe itsjaydesu ivancasco ivanrvpereira Jarvis jayhickey jeffersonwarrior - jeffersonwarrior jverdi longmaba MarvinCui mickahouan mjrussell odnxe p6l-richard philipp-spiess Pocket Clawd - robaxelsen Sash Catanzarite Suksham-sharma T5-AndyML tewatia travisp VAC william arzt zknicker 0oAstro - abhaymundhara aduk059 alejandro maza Alex-Alaniz alexstyl andrewting19 anpoirier araa47 arthyn Asleep123 - bguidolim bolismauro chenyuan99 OpenClaw Maintainers conhecendoia dasilva333 David-Marsh-Photo Developer Dimitrios Ploutarchos Drake Thomsen - dylanneve1 Felix Krause foeken frankekn ganghyun kim grrowl gtsifrikas HazAT hrdwdmrbl hugobarauna - Jamie Openshaw Jane Jarvis Deploy Jefferson Nunn jogi47 kentaro Kevin Lin kira-ariaki kitze Kiwitwitter - levifig Lloyd longjos loukotal louzhixian martinpucik Matt mini mertcicekci0 Miles mrdbstn - MSch Mustafa Tag Eldeen ndraiman nexty5870 Noctivoro ppamment prathamdby ptn1411 reeltimeapps RLTCmpe - Rolf Fredheim Rony Kelner Samrat Jha senoldogann sergical shiv19 shiyuanhai siraht snopoke techboss - testingabc321 The Admiral thesash Ubuntu voidserf Vultr-Clawd Admin Wimmie wolfred wstock YangHuang2280 - yazinsai YiWang24 ymat19 Zach Knickerbocker zackerthescar 0xJonHoldsCrypto aaronn Alphonse-arianee atalovesyou Azade - carlulsoe ddyo Erik latitudeki5223 Manuel Maly Mourad Boustani odrobnik pcty-nextgen-ios-builder Quentin Randy Torres - rhjoh ronak-guliani William Stock + nonggialiang rafaelreis-r dominicnunez lploc94 ratulsarna lutr0 kiranjd danielz1z AdeboyeDN Alg0rix + papago2355 emanuelst KristijanJovanovski rdev rhuanssauro joshrad-dev osolmaz adityashaw2 CashWilliams sheeek + ryancontent artuskg Takhoffman onutc pauloportella HirokiKobayashi-R neooriginal obviyus manuelhettich minghinmatthewlam + manikv12 myfunc travisirby buddyh connorshea kyleok mcinteerj dependabot[bot] John-Rood timkrase + uos-status gerardward2007 roshanasingh4 tosh-hamburg azade-c dlauer JonUleis shivamraut101 bjesuiter cheeeee + robbyczgw-cla conroywhitney Josh Phillips YuriNachos pookNast Whoaa512 chriseidhof ngutman ysqander aj47 + kennyklee superman32432432 Yurii Chukhlib grp06 antons austinm911 blacksmith-sh[bot] damoahdominic dan-dr HeimdallStrategy + imfing jalehman jarvis-medmatic kkarimi mahmoudashraf93 pkrmf RandyVentures robhparker Ryan Lisse dougvk + erikpr1994 fal3 Ghost jonasjancarik Keith the Silly Goose L36 Server Marc mitschabaude-bot mkbehr neist + sibbl chrisrodz Friederike Seiler gabriel-trigo iamadig Jonathan D. Rhyne (DJ-D) Joshua Mitchell Kit koala73 manmal + ogulcancelik pasogott petradonka rubyrunsstuff siddhantjain suminhthanh svkozak VACInc wes-davis zats + 24601 ameno- Chris Taylor dguido Django Navarro evalexpr henrino3 humanwritten larlyssa Lukavyi + odysseus0 oswalpalash pcty-nextgen-service-account pi0 rmorse Roopak Nijhara Syhids Aaron Konyer aaronveklabs andreabadesso + Andrii cash-echo-bot Clawd ClawdFx EnzeD erik-agens Evizero fcatuhe itsjaydesu ivancasco + ivanrvpereira Jarvis jayhickey jeffersonwarrior jeffersonwarrior jverdi longmaba MarvinCui mjrussell odnxe + optimikelabs p6l-richard philipp-spiess Pocket Clawd robaxelsen Sash Catanzarite Suksham-sharma T5-AndyML tewatia travisp + VAC william arzt zknicker 0oAstro abhaymundhara aduk059 alejandro maza Alex-Alaniz alexstyl andrewting19 + anpoirier araa47 arthyn Asleep123 bguidolim bolismauro chenyuan99 Chloe-VP conhecendoia dasilva333 + David-Marsh-Photo Developer Dimitrios Ploutarchos Drake Thomsen dylanneve1 Felix Krause foeken frankekn ganghyun kim grrowl + gtsifrikas HazAT hrdwdmrbl hugobarauna Jamie Openshaw Jane Jarvis Deploy Jefferson Nunn jogi47 kentaro + Kevin Lin kira-ariaki kitze Kiwitwitter levifig Lloyd longjos loukotal louzhixian martinpucik + Matt mini mertcicekci0 Miles mrdbstn MSch Mustafa Tag Eldeen mylukin nathanbosse ndraiman nexty5870 + Noctivoro ppamment prathamdby ptn1411 reeltimeapps RLTCmpe Rolf Fredheim Rony Kelner Samrat Jha senoldogann + Seredeep sergical shiv19 shiyuanhai siraht snopoke spiceoogway techboss testingabc321 The Admiral + thesash Ubuntu Vibe Kanban voidserf Vultr-Clawd Admin Wimmie wolfred wstock YangHuang2280 yazinsai + YiWang24 ymat19 Zach Knickerbocker zackerthescar 0xJonHoldsCrypto aaronn Alphonse-arianee atalovesyou Azade carlulsoe + ddyo Erik latitudeki5223 Manuel Maly Mourad Boustani odrobnik pcty-nextgen-ios-builder Quentin Randy Torres rhjoh + ronak-guliani William Stock

diff --git a/src/channels/plugins/actions/telegram.test.ts b/src/channels/plugins/actions/telegram.test.ts index d41628888..1ccc1e628 100644 --- a/src/channels/plugins/actions/telegram.test.ts +++ b/src/channels/plugins/actions/telegram.test.ts @@ -118,4 +118,27 @@ describe("telegramMessageActions", () => { expect(handleTelegramAction).not.toHaveBeenCalled(); }); + + it("accepts numeric messageId and channelId for reactions", async () => { + handleTelegramAction.mockClear(); + const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig; + + await telegramMessageActions.handleAction({ + action: "react", + params: { + channelId: 123, + messageId: 456, + emoji: "ok", + }, + cfg, + accountId: undefined, + }); + + expect(handleTelegramAction).toHaveBeenCalledTimes(1); + const call = handleTelegramAction.mock.calls[0]?.[0] as Record; + expect(call.action).toBe("react"); + expect(String(call.chatId)).toBe("123"); + expect(String(call.messageId)).toBe("456"); + expect(call.emoji).toBe("ok"); + }); });