Skip to content

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 ​

OrderPackageVersionStatus
1@gramio/contexts0.12.0Published
1@gramio/format0.12.1Published
1@gramio/files0.8.1Published
2gramio0.15.1Published

@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:

ts
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 ​

  1. Replace Markdown table() calls with markdownTable().
  2. Use blocks([ ... ]) and native table() for structured Rich Messages.
  3. await MediaUpload.path(...) (or another upload helper) before passing the result to a native media helper.
  4. Keep new uploads on regular chat sends/edits; inline-result rich content and edits addressed by inline_message_id require existing Telegram file_id values.

See the Rich Messages guide and the Russian guide for complete examples.