Native Rich DSL ships in GramIO 0.15
September 10, 2026
This focused release makes Telegram's structured Rich Messages practical to author and safe to send. The release train keeps the Markdown lane available while adding a native blocks lane for tables, media, buttons, and nested containers.
Release status
The package train is published to npm and GitHub in dependency order. Documentation examples and the published-package smoke suite use the versions listed below.
Release train
| Order | Package | Version | Status |
|---|---|---|---|
| 1 | @gramio/contexts | 0.12.0 | Published |
| 1 | @gramio/format | 0.12.1 | Published |
| 1 | @gramio/files | 0.8.1 | Published |
| 2 | gramio | 0.15.1 | Published |
@gramio/format 0.12 — two explicit Rich Messages lanes
The old Markdown table serializer is now named markdownTable(). table() creates Telegram's native InputRichBlockTable, and blocks([...]) composes native blocks into an InputRichMessage:
import { blocks, markdownTable, table } from "gramio/rich";
const native = blocks([
table([
["Package", "Version"],
["gramio", "0.15.1"],
]),
]);
const markdown = markdownTable([
["Package", "Version"],
["gramio", "0.15.1"],
]);This is the intentional breaking change from @gramio/format 0.11: replace calls that expected a Markdown string from table() with markdownTable(), or use the native result with blocks(). Native media helpers accept URLs/file IDs, Blob/File, and complete InputMedia* objects. Await MediaUpload helpers before passing a file; put a visible native caption in the helper options. Version 0.12.1 also fixes direct Blob/File values being wrapped as native InputMedia* objects.
@gramio/contexts 0.12 — native values route automatically
ctx.send(), ctx.reply(), and ctx.editText() accept both Markdown rich values and native structured values. Branded values are routed to sendRichMessage/editMessageText with the correct rich_message field, while ordinary strings keep using the ordinary Bot API methods.
streamRichMessage() remains Markdown-only because Telegram drafts are Markdown chunks. Passing a native structured value now fails loudly instead of silently dropping its blocks.
@gramio/files 0.8.1 — nested uploads are detected reliably
Multipart detection now finds Blob, File, and MediaUpload values at every recursive Rich Messages depth, including blockquotes, lists, collages, slideshows, details, thumbnails, and covers. sendRichMessageDraft remains upload-free by Telegram design.
Upgrade checklist
- Replace Markdown
table()calls withmarkdownTable(). - Use
blocks([ ... ])and nativetable()for structured Rich Messages. await MediaUpload.path(...)(or another upload helper) before passing the result to a native media helper.- Keep new uploads on regular chat sends/edits; inline-result rich content and edits addressed by
inline_message_idrequire existing Telegramfile_idvalues.
See the Rich Messages guide and the Russian guide for complete examples.