Bug Description
When the Discord adapter converts a message containing a bare URL or an autolink (https://…) from mdast to Discord markdown, it wraps it as a masked link https://example.com. Discord only renders masked-link syntax inside embeds — in a normal message, text is shown as literal text. So a plain URL that should be a clean, clickable link instead appears to the user as the raw string https://example.com.
The root cause is in DiscordFormatConverter's link handling (packages/adapter-discord/src/markdown.ts, the isLinkNode branch of nodeToDiscordMarkdown): it unconditionally emits ${linkText} with no special case for when the link's label equals its URL (the bare-URL / autolink case).
Steps to Reproduce
- Create a
Chat instance with the Discord adapter.
- From a handler, post a message containing a bare URL as markdown, e.g.
await thread.post({ markdown: "https://example.com" }) (or have any flow that produces an mdast link node whose text equals its URL — bare URLs and both do).
- Observe the message in Discord.
Expected Behavior
The bare URL is sent through as-is (https://example.com) and renders as a clickable link in Discord.
Actual Behavior
The adapter sends https://example.com, which Discord displays as literal text (masked links only render inside embeds), so the link is neither clean nor clickable.
Code Sample
import { DiscordFormatConverter } from "@chat-adapter/discord";
const converter = new DiscordFormatConverter();
// Bare URL
converter.fromAst(converter.toAst("https://example.com"));
// → "[https://example.com](https://example.com)" ❌ expected: "https://example.com"
// Autolink
converter.fromAst(converter.toAst("<https://example.com>"));
// → "[https://example.com](https://example.com)" ❌ expected: "https://example.com"
// Labeled links are fine (text !== url):
converter.fromAst(converter.toAst("[click here](https://example.com)"));
// → "[click here](https://example.com)" ✅
Chat SDK Version
4.29.0
Node.js Version
22.22.2
Platform Adapter
Discord
Operating System
Linux
Additional Context
Existing unit tests in markdown.test.ts only cover labeled links ([link text](url) where text ≠ url), so the bare-URL/autolink case slips through with no coverage. A targeted fix is to short-circuit the isLinkNode branch when linkText === node.url and return the bare URL. I have a fix + failing-then-passing tests ready and am happy to open a PR.
Bug Description
When the Discord adapter converts a message containing a bare URL or an autolink (https://…) from mdast to Discord markdown, it wraps it as a masked link https://example.com. Discord only renders masked-link syntax inside embeds — in a normal message, text is shown as literal text. So a plain URL that should be a clean, clickable link instead appears to the user as the raw string https://example.com.
The root cause is in DiscordFormatConverter's link handling (packages/adapter-discord/src/markdown.ts, the isLinkNode branch of nodeToDiscordMarkdown): it unconditionally emits ${linkText} with no special case for when the link's label equals its URL (the bare-URL / autolink case).
Steps to Reproduce
Chatinstance with theDiscordadapter.await thread.post({ markdown: "https://example.com" })(or have any flow that produces an mdastlinknode whose text equals its URL — bare URLs and both do).Expected Behavior
The bare URL is sent through as-is (https://example.com) and renders as a clickable link in Discord.
Actual Behavior
The adapter sends https://example.com, which Discord displays as literal text (masked links only render inside embeds), so the link is neither clean nor clickable.
Code Sample
Chat SDK Version
4.29.0
Node.js Version
22.22.2
Platform Adapter
Discord
Operating System
Linux
Additional Context
Existing unit tests in
markdown.test.tsonly cover labeled links ([link text](url)where text ≠ url), so the bare-URL/autolink case slips through with no coverage. A targeted fix is to short-circuit theisLinkNodebranch whenlinkText === node.urland return the bare URL. I have a fix + failing-then-passing tests ready and am happy to open a PR.