Skip to content

[Bug] markdown.tables config is ignored during Telegram outbound message chunking / streaming #85085

@ShuaiHui

Description

@ShuaiHui

Describe the Bug

When sending messages through the Telegram outbound adapter, if the parse mode is not explicitly HTML (such as during streaming assistant updates or chunked progress text), the message text is split using markdownToTelegramHtmlChunks(text, limit).

However, in the compiled output (specifically format-CqcuR36z.js / src/extensions/telegram/src/format.ts), the markdownToTelegramHtmlChunks function does not accept or propagate an options parameter to markdownToTelegramChunks. Consequently, the configured tableMode (e.g., "markdown.tables": "bullets") is completely ignored, and markdown tables are delivered to Telegram in their raw format (| --- |), which looks unrendered and messy.

Additionally, the delivery orchestrator (deliver.ts) and the reply payload sender (reply-payload.ts) do not supply the configuration context (cfg and accountId) to the chunker function, preventing it from resolving tableMode configuration for the channel.

Steps to Reproduce

  1. Set the following in openclaw.json:
    "channels": {
      "telegram": {
        "markdown": {
          "tables": "bullets"
        }
      }
    }
  2. Initiate a streaming response from an assistant that generates a Markdown table.
  3. Observe that the intermediate or final streaming message chunks delivered to Telegram render the raw markdown tables instead of converting them to lists/bullets.

Proposed Solution

Here is a hotfix that resolves this issue by propagating the configuration context and resolving the table mode in chunkTelegramOutboundText.

1. Accept options in markdownToTelegramHtmlChunks

Modify format-CqcuR36z.js to accept options and forward them:

function markdownToTelegramHtmlChunks(markdown, limit, options = {}) {
	return markdownToTelegramChunks(markdown, limit, options).map((chunk) => chunk.html);
}

2. Resolve tableMode in chunkTelegramOutboundText

Modify channel-RqV6hPGF.js (or the Telegram outbound adapter file) to import resolveMarkdownTableMode and resolve tableMode from the context:

import { t as resolveMarkdownTableMode } from "./markdown-tables-D2-aDWLS.js";

function chunkTelegramOutboundText(text, limit, ctx) {
	const tableMode = resolveMarkdownTableMode({
		cfg: ctx?.cfg,
		channel: "telegram",
		accountId: ctx?.accountId
	});
	return ctx?.formatting?.parseMode === "HTML" ? splitTelegramHtmlChunks(text, limit) : markdownToTelegramHtmlChunks(text, limit, { tableMode });
}

3. Propagate context down to chunkers

  • In deliver-Cp6bjPd4.js (outbound message plan):
    Update chunkTextForPlan and planOutboundTextMessageUnits to accept and pass cfg and accountId to the chunker call:
    function chunkTextForPlan(params) {
        return params.formatting 
            ? params.chunker(params.text, params.limit, { formatting: params.formatting, cfg: params.cfg, accountId: params.accountId }) 
            : params.chunker(params.text, params.limit, { cfg: params.cfg, accountId: params.accountId });
    }
  • In reply-payload-DP0q6t5P.js:
    Forward cfg and accountId when calling the chunker function in sendTextMediaPayload:
    const chunks = limit && params.adapter.chunker ? params.adapter.chunker(text, limit, {
        formatting: params.ctx.formatting,
        cfg: params.ctx.cfg,
        accountId: params.ctx.accountId
    }) : [text];

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions