From 58989b1ec5d7891cfcd53eb67f94773b1049da3a Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 19 Mar 2026 11:14:05 +0000 Subject: [PATCH 1/3] Initial commit with task details Adding .gitkeep for PR creation (default mode). This file will be removed when the task is complete. Issue: https://github.com/xlabtg/teleton-plugins/issues/23 --- .gitkeep | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitkeep b/.gitkeep index c46a5b9..38fc7dd 100644 --- a/.gitkeep +++ b/.gitkeep @@ -1 +1,2 @@ -# .gitkeep file auto-generated at 2026-03-19T10:37:13.073Z for PR creation at branch issue-19-f54b585823d1 for issue https://github.com/xlabtg/teleton-plugins/issues/19 \ No newline at end of file +# .gitkeep file auto-generated at 2026-03-19T10:37:13.073Z for PR creation at branch issue-19-f54b585823d1 for issue https://github.com/xlabtg/teleton-plugins/issues/19 +# Updated: 2026-03-19T11:14:05.626Z \ No newline at end of file From de942870a74dee9b2cb6eb8d3c25a8688bd10ad5 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 19 Mar 2026 11:17:59 +0000 Subject: [PATCH 2/3] fix(ton-bridge): send button directly via sdk.telegram.sendMessage, remove buttonEmoji MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the plugin returned reply_markup in tool data and relied on the runtime/agent to render the button, which did not work correctly in DMs, groups, or channels. Changes: - All three tools now call sdk.telegram.sendMessage() with an inlineKeyboard URL button, sending the message directly to the chat - Add optional buttonText parameter to each tool so the LLM can control the button label (including omitting emoji) per call - Remove buttonEmoji from defaultConfig and inline manifest — emoji should be opt-in via the buttonText parameter, not hardcoded - Use PluginSDKError-aware error handling as per patterns.md - Update README to document new behavior and buttonText parameter Co-Authored-By: Claude Sonnet 4.6 --- plugins/ton-bridge/README.md | 35 ++++++---- plugins/ton-bridge/index.js | 107 ++++++++++++++++++++++--------- plugins/ton-bridge/manifest.json | 1 - 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/plugins/ton-bridge/README.md b/plugins/ton-bridge/README.md index cd67307..dab9a28 100644 --- a/plugins/ton-bridge/README.md +++ b/plugins/ton-bridge/README.md @@ -1,22 +1,23 @@ # TON Bridge -Share the TON Bridge Mini App link with a beautiful inline button in Telegram chats. +Share the TON Bridge Mini App link with an inline button in Telegram chats. +Works in DMs, groups, and channels. TON Bridge works with support from TONBANKCARD. ## Features -- Inline button for TON Bridge Mini App access -- Customizable button text and emoji +- Sends a message with a URL inline button directly to the current chat +- Button text controllable per tool call (the LLM can omit or include emoji) +- Customizable default button text via config - Custom message support -- Easy integration with AI agents ## Tools | Tool | Description | Category | |------|-------------|----------| -| `ton_bridge_open` | Send a message with a TON Bridge Mini App link | action | -| `ton_bridge_about` | Send info about TON Bridge with a link to the Mini App | data-bearing | +| `ton_bridge_open` | Send a message with a TON Bridge Mini App button | action | +| `ton_bridge_about` | Send info about TON Bridge with a Mini App button | data-bearing | | `ton_bridge_custom_message` | Send a custom message alongside a TON Bridge button | action | ## Installation @@ -32,11 +33,12 @@ cp -r plugins/ton-bridge ~/.teleton/plugins/ # ~/.teleton/config.yaml plugins: ton_bridge: - buttonText: "TON Bridge No1" # Button text (default: "TON Bridge No1") - buttonEmoji: "🌉" # Emoji on button (default: "🌉") - startParam: "" # Optional start parameter + buttonText: "TON Bridge No1" # Default button label (default: "TON Bridge No1") + startParam: "" # Optional start parameter appended to the Mini App URL ``` +> **Note:** Emoji on the button is controlled by the agent at call time via the `buttonText` parameter, not by config. This allows the agent to send buttons with or without emoji as requested by the user. + ## Usage Examples ### Open TON Bridge @@ -44,7 +46,14 @@ plugins: Open TON Bridge ``` -Will send a message with a button linking to https://t.me/TONBridge_robot?startapp +Sends a message with a button linking to `https://t.me/TONBridge_robot?startapp`. + +### Open TON Bridge without emoji on button +``` +Open TON Bridge, no emoji on the button +``` + +The agent will call `ton_bridge_open` with `buttonText: "TON Bridge No1"` (no emoji). ### Get Info About TON Bridge ``` @@ -63,16 +72,20 @@ Send "Transfer your assets via TON Bridge" with a TON Bridge button | Param | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `message` | string | No | — | Optional message text to show with the button | +| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. | ### `ton_bridge_about` -No parameters required. +| Param | Type | Required | Default | Description | +|-------|------|----------|---------|-------------| +| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. | ### `ton_bridge_custom_message` | Param | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | `customMessage` | string | Yes | — | Custom message text to display with the button | +| `buttonText` | string | No | config default | Button label. Do not include emoji unless user requested it. | --- diff --git a/plugins/ton-bridge/index.js b/plugins/ton-bridge/index.js index 8e32906..1d3f672 100644 --- a/plugins/ton-bridge/index.js +++ b/plugins/ton-bridge/index.js @@ -2,7 +2,10 @@ * TON Bridge plugin * * Provides LLM-callable tools to share the TON Bridge Mini App link. - * Pattern B (SDK) — uses sdk.pluginConfig, sdk.log + * Pattern B (SDK) — uses sdk.pluginConfig, sdk.log, sdk.telegram.sendMessage + * + * Actively sends messages with URL inline buttons so the button renders + * correctly in DMs, groups, and channels. */ // ─── Manifest (inline) ──────────────────────────────────────────────────────── @@ -16,7 +19,6 @@ export const manifest = { description: "Share TON Bridge Mini App link with a button. Opens https://t.me/TONBridge_robot?startapp", defaultConfig: { buttonText: "TON Bridge No1", - buttonEmoji: "🌉", startParam: "", }, }; @@ -25,14 +27,10 @@ export const manifest = { const MINI_APP_URL = "https://t.me/TONBridge_robot?startapp"; -function buildReplyMarkup(buttonText, buttonEmoji, startParam) { - const label = buttonEmoji ? `${buttonEmoji} ${buttonText}` : buttonText; - const url = startParam +function buildUrl(startParam) { + return startParam ? `${MINI_APP_URL}=${encodeURIComponent(startParam)}` : MINI_APP_URL; - return { - inline_keyboard: [[{ text: label, url }]], - }; } // ─── Tools ──────────────────────────────────────────────────────────────────── @@ -42,7 +40,7 @@ export const tools = (sdk) => [ { name: "ton_bridge_open", description: - "Send a message with a TON Bridge Mini App link. Use when the user asks to open or access TON Bridge.", + "Send a message with a TON Bridge Mini App button. Use when the user asks to open or access TON Bridge. Sends the message directly to the current chat.", category: "action", parameters: { type: "object", @@ -53,30 +51,45 @@ export const tools = (sdk) => [ minLength: 1, maxLength: 500, }, + buttonText: { + type: "string", + description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.", + minLength: 1, + maxLength: 64, + }, }, }, execute: async (params, context) => { try { - const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; - const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉"; + const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; const startParam = sdk.pluginConfig?.startParam ?? ""; + const url = buildUrl(startParam); - const content = + const text = params.message ?? - "🌉 **TON Bridge** — The #1 Bridge in the TON Catalog\n\nClick the button below to open TON Bridge Mini App."; + "TON Bridge — The #1 Bridge in the TON Catalog\n\nClick the button below to open TON Bridge Mini App."; sdk.log?.info( `ton_bridge_open called by ${context?.senderId ?? "unknown"}` ); + const messageId = await sdk.telegram.sendMessage( + context.chatId, + text, + { + inlineKeyboard: [[{ text: buttonText, url }]], + } + ); + return { success: true, - data: { - content, - reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam), - }, + data: { message_id: messageId, chat_id: context.chatId }, }; } catch (err) { + if (err.name === "PluginSDKError") { + sdk.log?.error(`ton_bridge_open failed: ${err.code}: ${err.message}`); + return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` }; + } sdk.log?.error("ton_bridge_open failed:", err.message); return { success: false, error: String(err.message || err).slice(0, 500) }; } @@ -87,31 +100,46 @@ export const tools = (sdk) => [ { name: "ton_bridge_about", description: - "Send an info message about TON Bridge with a link to the Mini App. Use when the user asks about TON Bridge or wants more information.", + "Send an info message about TON Bridge with a Mini App button. Use when the user asks about TON Bridge or wants more information.", category: "data-bearing", parameters: { type: "object", - properties: {}, + properties: { + buttonText: { + type: "string", + description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.", + minLength: 1, + maxLength: 64, + }, + }, }, execute: async (params, context) => { try { - const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; - const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉"; + const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; const startParam = sdk.pluginConfig?.startParam ?? ""; + const url = buildUrl(startParam); sdk.log?.info( `ton_bridge_about called by ${context?.senderId ?? "unknown"}` ); + const messageId = await sdk.telegram.sendMessage( + context.chatId, + "About TON Bridge\n\nTON Bridge is the #1 bridge in the TON Catalog. Transfer assets across chains seamlessly via the official Mini App.", + { + inlineKeyboard: [[{ text: buttonText, url }]], + } + ); + return { success: true, - data: { - content: - "â„šī¸ **About TON Bridge**\n\nTON Bridge is the #1 bridge in the TON Catalog. Transfer assets across chains seamlessly via the official Mini App.", - reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam), - }, + data: { message_id: messageId, chat_id: context.chatId }, }; } catch (err) { + if (err.name === "PluginSDKError") { + sdk.log?.error(`ton_bridge_about failed: ${err.code}: ${err.message}`); + return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` }; + } sdk.log?.error("ton_bridge_about failed:", err.message); return { success: false, error: String(err.message || err).slice(0, 500) }; } @@ -133,27 +161,42 @@ export const tools = (sdk) => [ minLength: 1, maxLength: 500, }, + buttonText: { + type: "string", + description: "Button label text. Omit to use the configured default. Do NOT include emoji here unless the user explicitly requested one.", + minLength: 1, + maxLength: 64, + }, }, required: ["customMessage"], }, execute: async (params, context) => { try { - const buttonText = sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; - const buttonEmoji = sdk.pluginConfig?.buttonEmoji ?? "🌉"; + const buttonText = params.buttonText ?? sdk.pluginConfig?.buttonText ?? "TON Bridge No1"; const startParam = sdk.pluginConfig?.startParam ?? ""; + const url = buildUrl(startParam); sdk.log?.info( `ton_bridge_custom_message called by ${context?.senderId ?? "unknown"}` ); + const messageId = await sdk.telegram.sendMessage( + context.chatId, + params.customMessage, + { + inlineKeyboard: [[{ text: buttonText, url }]], + } + ); + return { success: true, - data: { - content: params.customMessage, - reply_markup: buildReplyMarkup(buttonText, buttonEmoji, startParam), - }, + data: { message_id: messageId, chat_id: context.chatId }, }; } catch (err) { + if (err.name === "PluginSDKError") { + sdk.log?.error(`ton_bridge_custom_message failed: ${err.code}: ${err.message}`); + return { success: false, error: `${err.code}: ${String(err.message).slice(0, 500)}` }; + } sdk.log?.error("ton_bridge_custom_message failed:", err.message); return { success: false, error: String(err.message || err).slice(0, 500) }; } diff --git a/plugins/ton-bridge/manifest.json b/plugins/ton-bridge/manifest.json index d402c4d..5631d91 100644 --- a/plugins/ton-bridge/manifest.json +++ b/plugins/ton-bridge/manifest.json @@ -18,7 +18,6 @@ ], "defaultConfig": { "buttonText": "TON Bridge No1", - "buttonEmoji": "🌉", "startParam": "" }, "permissions": [], From 7ba9b0f7239bfe088bd669bb7d6f4407b355f120 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 19 Mar 2026 11:18:34 +0000 Subject: [PATCH 3/3] Revert "Initial commit with task details" This reverts commit 58989b1ec5d7891cfcd53eb67f94773b1049da3a. --- .gitkeep | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitkeep b/.gitkeep index 38fc7dd..c46a5b9 100644 --- a/.gitkeep +++ b/.gitkeep @@ -1,2 +1 @@ -# .gitkeep file auto-generated at 2026-03-19T10:37:13.073Z for PR creation at branch issue-19-f54b585823d1 for issue https://github.com/xlabtg/teleton-plugins/issues/19 -# Updated: 2026-03-19T11:14:05.626Z \ No newline at end of file +# .gitkeep file auto-generated at 2026-03-19T10:37:13.073Z for PR creation at branch issue-19-f54b585823d1 for issue https://github.com/xlabtg/teleton-plugins/issues/19 \ No newline at end of file