Translate dashes to underscores for Telegram bot commands

Pi command names like compact-now were silently dropped from
setMyCommands because Telegram requires names to match
^[a-z0-9_]{1,32}$ - no dashes. They showed up in /help (which
iterates pi.getCommands() directly) but were untypable via
autocomplete and, even when typed manually, fell through to the
agent as plain text rather than dispatching.

Now: register the underscore-translated form with Telegram, show the
underscore form in /help so it matches what the user sees in the
menu, and on dispatch rewrite the message text from /foo_bar back to
/foo-bar before enqueueing so the harness's slash-command parser
finds the registered command.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wassname
2026-05-01 18:58:32 +08:00
parent b2444fd3cd
commit a2cfde2b25
2 changed files with 43 additions and 2 deletions
+24 -1
View File
@@ -76,9 +76,11 @@ import {
} from "./lib/queue.ts";
import {
buildTelegramBotCommands,
fromTelegramCommandName,
registerTelegramAttachmentTool,
registerTelegramCommands,
registerTelegramLifecycleHooks,
toTelegramCommandName,
} from "./lib/registration.ts";
import {
MAX_MESSAGE_LENGTH,
@@ -1892,7 +1894,9 @@ export default function (pi: ExtensionAPI) {
);
for (const c of sorted) {
const desc = c.description ? `${c.description}` : "";
lines.push(`/${c.name}${desc}`);
// Show the Telegram-form (dashes -> underscores) since that's what
// the user has to type. The bridge translates back on dispatch.
lines.push(`/${toTelegramCommandName(c.name)}${desc}`);
}
}
lines.push("", "/help re-syncs Telegram's command menu.");
@@ -1973,6 +1977,25 @@ export default function (pi: ExtensionAPI) {
);
if (handled) return;
// Pi commands with dashes are exposed in Telegram with underscores
// (Telegram bot command names disallow dashes). If the user typed the
// underscore form, rewrite the message text to the original dashed form
// so the harness's slash-command parser dispatches it correctly.
if (command) {
const piCommandNames = new Set(pi.getCommands().map((c) => c.name));
const original = fromTelegramCommandName(command.name, piCommandNames);
if (original !== command.name) {
const rewritten = command.args
? `/${original} ${command.args}`
: `/${original}`;
if (firstMessage.text !== undefined) {
firstMessage.text = rewritten;
} else if (firstMessage.caption !== undefined) {
firstMessage.caption = rewritten;
}
}
}
await enqueueTelegramTurn(messages, ctx);
}