Documentation Index
Fetch the complete documentation index at: https://mintlify.com/vercel/chat/llms.txt
Use this file to discover all available pages before exploring further.
The Chat SDK uses mdast (Markdown Abstract Syntax Tree) as the canonical format for message formatting. This enables consistent cross-platform formatting and programmatic content manipulation.
Parsing and Stringifying
parseMarkdown
Parse markdown string into an mdast AST.
function parseMarkdown(markdown: string): Root;
Example:
import { parseMarkdown } from "chat";
const ast = parseMarkdown("**Bold** and _italic_");
console.log(ast);
// {
// type: "root",
// children: [
// {
// type: "paragraph",
// children: [
// { type: "strong", children: [{ type: "text", value: "Bold" }] },
// { type: "text", value: " and " },
// { type: "emphasis", children: [{ type: "text", value: "italic" }] }
// ]
// }
// ]
// }
stringifyMarkdown
Stringify an mdast AST back to markdown.
function stringifyMarkdown(ast: Root): string;
Example:
import { stringifyMarkdown, root, paragraph, strong, text } from "chat";
const ast = root([
paragraph([
strong([text("Bold")]),
text(" text")
])
]);
const markdown = stringifyMarkdown(ast);
console.log(markdown); // "**Bold** text\n"
toPlainText
Extract plain text from an AST (strips all formatting).
function toPlainText(ast: Root): string;
Example:
import { parseMarkdown, toPlainText } from "chat";
const ast = parseMarkdown("**Bold** and _italic_");
const plain = toPlainText(ast);
console.log(plain); // "Bold and italic"
markdownToPlainText
Extract plain text from a markdown string.
function markdownToPlainText(markdown: string): string;
Example:
import { markdownToPlainText } from "chat";
const plain = markdownToPlainText("**Bold** [link](url)");
console.log(plain); // "Bold link"
AST Node Builders
Helper functions for creating mdast nodes programmatically.
root
Create a root node (top-level AST container).
function root(children: Content[]): Root;
paragraph
Create a paragraph node.
function paragraph(children: Content[]): Paragraph;
text
Create a text node.
function text(value: string): Text;
strong
Create a strong (bold) node.
function strong(children: Content[]): Strong;
emphasis
Create an emphasis (italic) node.
function emphasis(children: Content[]): Emphasis;
strikethrough
Create a delete (strikethrough) node.
function strikethrough(children: Content[]): Delete;
inlineCode
Create an inline code node.
function inlineCode(value: string): InlineCode;
codeBlock
Create a code block node.
function codeBlock(value: string, lang?: string): Code;
link
Create a link node.
function link(url: string, children: Content[], title?: string): Link;
blockquote
Create a blockquote node.
function blockquote(children: Content[]): Blockquote;
Example:
import {
root,
paragraph,
text,
strong,
emphasis,
link,
codeBlock
} from "chat";
const ast = root([
paragraph([
text("This is "),
strong([text("bold")]),
text(" and "),
emphasis([text("italic")]),
text(". "),
link("https://example.com", [text("Click here")])
]),
codeBlock("console.log('hello');", "javascript")
]);
await thread.post({ ast });
AST Manipulation
walkAst
Walk the AST and transform nodes.
function walkAst<T extends Content | Root>(
node: T,
visitor: (node: Content) => Content | null
): T;
The visitor function receives each node and can:
- Return the node unchanged
- Return a modified node
- Return
null to remove the node
Example - Remove all links:
import { parseMarkdown, walkAst, isLinkNode } from "chat";
const ast = parseMarkdown("Check out [this link](https://example.com)!");
const withoutLinks = walkAst(ast, (node) => {
if (isLinkNode(node)) {
// Replace link with its text content
return node.children[0];
}
return node;
});
Example - Transform code blocks:
import { parseMarkdown, walkAst, isCodeNode, codeBlock } from "chat";
const ast = parseMarkdown("```\ncode\n```");
const highlighted = walkAst(ast, (node) => {
if (isCodeNode(node)) {
return codeBlock(
highlightSyntax(node.value, node.lang),
node.lang
);
}
return node;
});
Type Guards
Type guards for identifying node types.
function isTextNode(node: Content): node is Text;
function isParagraphNode(node: Content): node is Paragraph;
function isStrongNode(node: Content): node is Strong;
function isEmphasisNode(node: Content): node is Emphasis;
function isDeleteNode(node: Content): node is Delete;
function isInlineCodeNode(node: Content): node is InlineCode;
function isCodeNode(node: Content): node is Code;
function isLinkNode(node: Content): node is Link;
function isBlockquoteNode(node: Content): node is Blockquote;
function isListNode(node: Content): node is List;
function isListItemNode(node: Content): node is ListItem;
function isTableNode(node: Content): node is Table;
function isTableRowNode(node: Content): node is TableRow;
function isTableCellNode(node: Content): node is TableCell;
Example:
import { parseMarkdown, walkAst, isLinkNode, isCodeNode } from "chat";
const ast = parseMarkdown("[link](url) and `code`");
walkAst(ast, (node) => {
if (isLinkNode(node)) {
console.log("Found link:", node.url);
}
if (isCodeNode(node)) {
console.log("Found code:", node.value);
}
return node;
});
Node Property Helpers
getNodeChildren
Get children from a content node that has children. Returns empty array for nodes without children.
function getNodeChildren(node: Content): Content[];
getNodeValue
Get value from a content node that has a value property. Returns empty string for nodes without value.
function getNodeValue(node: Content): string;
Example:
import { parseMarkdown, walkAst, getNodeChildren, getNodeValue } from "chat";
const ast = parseMarkdown("**bold** text");
walkAst(ast, (node) => {
const children = getNodeChildren(node);
const value = getNodeValue(node);
if (children.length > 0) {
console.log("Has", children.length, "children");
}
if (value) {
console.log("Has value:", value);
}
return node;
});
Table Utilities
tableToAscii
Render an mdast table node as a padded ASCII table string.
function tableToAscii(node: Table): string;
Output format:
Name | Age | Role
------|-----|--------
Alice | 30 | Engineer
Bob | 25 | Designer
tableElementToAscii
Render a table from headers and string rows as a padded ASCII table.
function tableElementToAscii(
headers: string[],
rows: string[][]
): string;
Example:
import { tableElementToAscii } from "chat";
const ascii = tableElementToAscii(
["Name", "Score"],
[
["Alice", "95"],
["Bob", "87"]
]
);
console.log(ascii);
// Name | Score
// ------|------
// Alice | 95
// Bob | 87
Interface for platform-specific format converters. Each adapter implements this to convert between platform format and mdast AST.
interface FormatConverter {
/**
* Parse platform's native format into an AST.
* This is the primary method used when receiving messages.
*/
toAst(platformText: string): Root;
/**
* Render an AST to the platform's native format.
* This is the primary method used when sending messages.
*/
fromAst(ast: Root): string;
/**
* Extract plain text from platform format.
* Convenience method - default implementation uses toAst + toPlainText.
*/
extractPlainText(platformText: string): string;
}
Base class for format converters with default implementations.
abstract class BaseFormatConverter implements FormatConverter {
abstract toAst(platformText: string): Root;
abstract fromAst(ast: Root): string;
extractPlainText(platformText: string): string;
// Convenience methods
fromMarkdown(markdown: string): string;
toMarkdown(platformText: string): string;
renderPostable(message: PostableMessage): string;
}
Example - Custom Converter:
import { BaseFormatConverter, Root, Content, text, paragraph } from "chat";
class MyConverter extends BaseFormatConverter {
toAst(platformText: string): Root {
// Parse platform format to AST
return {
type: "root",
children: [paragraph([text(platformText)])]
};
}
fromAst(ast: Root): string {
// Convert AST to platform format
return ast.children
.map(node => this.nodeToString(node))
.join("\n\n");
}
private nodeToString(node: Content): string {
// Convert individual nodes
// ...
}
}
Complete Example
import {
parseMarkdown,
stringifyMarkdown,
walkAst,
isLinkNode,
isCodeNode,
root,
paragraph,
text,
strong,
link,
codeBlock
} from "chat";
// Parse markdown
const ast = parseMarkdown(`
# Hello
This is **bold** and [a link](https://example.com).
\`\`\`js
console.log('code');
\`\`\`
`);
// Transform: remove links, highlight code
const transformed = walkAst(ast, (node) => {
// Remove all links, keep text
if (isLinkNode(node)) {
return text(node.children[0].value);
}
// Add line numbers to code blocks
if (isCodeNode(node)) {
const lines = node.value.split("\n");
const numbered = lines
.map((line, i) => `${i + 1}: ${line}`)
.join("\n");
return codeBlock(numbered, node.lang);
}
return node;
});
// Convert back to markdown
const markdown = stringifyMarkdown(transformed);
// Or post directly
await thread.post({ ast: transformed });