Skip to main content

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"

Text Extraction

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;
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

FormatConverter

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;
}

BaseFormatConverter

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 });

Build docs developers (and LLMs) love