Block Parsing
Updated
Chaos AI responses contain structured blocks: tables, charts, transaction actions, markdown, interactive elements, info alerts, code snippets, and forms. This recipe shows how to extract and handle each block type using the SDK's type guards and extraction functions.
Block Types Overview
The SDK defines 10 block types:
| Type | Discriminant | Type Guard | Extraction Function |
|---|---|---|---|
| Table | table | isTableBlock | extractTableBlocks |
| Pie Chart | pie_chart | isPieChartBlock | extractChartBlocks |
| Bar Chart | bar_chart | isBarChartBlock | extractChartBlocks |
| Timeseries | timeseries_chart | isTimeseriesChartBlock | extractChartBlocks |
| Action | action | isTransactionActionBlock | extractTransactionBlocks |
| Markdown | markdown | isMarkdownBlock | extractMarkdownBlocks |
| Interactive | interactive | isInteractiveBlock | extractInteractiveBlocks |
| Alert | alert | isInfoBlock | extractInfoBlocks |
| Code | code | isCodeBlock | extractCodeBlocks |
| Form | form | isFormBlock | extractFormBlocks |
Extracting All Blocks
Use extractBlocks to get every block from a response, regardless of type.
import { extractBlocks, countBlocksByType, hasBlocks, hasBlockType } from '@chaoslabs/ai-sdk';
import type { ChatCreateResponse } from '@chaoslabs/ai-sdk';
function summarizeResponse(response: ChatCreateResponse) {
if (!hasBlocks(response)) {
console.log('Response contains no blocks');
return;
}
const blocks = extractBlocks(response);
console.log(`Total blocks: ${blocks.length}`);
// Get counts per type
const counts = countBlocksByType(response);
for (const [type, count] of Object.entries(counts)) {
if (count > 0) {
console.log(` ${type}: ${count}`);
}
}
// Check for specific block types
if (hasBlockType(response, 'action')) {
console.log('Response contains transactions');
}
if (hasBlockType(response, 'table')) {
console.log('Response contains tables');
}
}Copy code
Open in Cursor
Open in VS Code
Open in v0
Open in Claude
Open in ChatGPT
Type Guard Pattern
Iterate over all blocks and use type guards to handle each type with full type narrowing.
import {
extractBlocks,
isTableBlock,
isChartBlock,
isTransactionActionBlock,
isMarkdownBlock,
isInteractiveBlock,
isInfoBlock,
isCodeBlock,
isFormBlock,
isPieChartBlock,
isBarChartBlock,
isTimeseriesChartBlock,
} from '@chaoslabs/ai-sdk';
import type { ChatCreateResponse } from '@chaoslabs/ai-sdk';
function processBlocks(response: ChatCreateResponse) {
for (const block of extractBlocks(response)) {
if (isTableBlock(block)) {
// block is TableBlock
console.log('Table:', block.title);
console.log(' Headers:', block.tableHeaders);
console.log(' Rows:', block.tableRows.length);
} else if (isTransactionActionBlock(block)) {
// block is ActionBlock
console.log('Action primitives:', block.primitives.map((p) => p.type));
console.log(' Risk level:', block.risks.level);
} else if (isChartBlock(block)) {
// block is PieChartBlock | BarChartBlock | TimeseriesChartBlock
console.log('Chart:', block.title, `(${block.type})`);
if (isPieChartBlock(block)) {
console.log(' Pie series:', block.series.length);
} else if (isBarChartBlock(block)) {
console.log(' Bar series:', block.series.length);
} else if (isTimeseriesChartBlock(block)) {
console.log(' Timeseries data points:', block.series.length);
}
} else if (isMarkdownBlock(block)) {
// block is MarkdownBlock
console.log('Markdown:', block.content.slice(0, 100) + '...');
} else if (isInteractiveBlock(block)) {
// block is InteractiveBlock
console.log('Interactive:', block.title);
} else if (isInfoBlock(block)) {
// block is AlertBlock
console.log('Alert:', block.severity, block.content);
} else if (isCodeBlock(block)) {
// block is CodeBlock
console.log('Code:', block.language, block.content.slice(0, 50) + '...');
} else if (isFormBlock(block)) {
// block is FormBlock
console.log('Form:', block.title);
}
}
}Copy code
Open in Cursor
Open in VS Code
Open in v0
Open in Claude
Open in ChatGPT
Typed Extraction Functions
Each extraction function returns an array of the specific block type, already narrowed.
import {
extractTableBlocks,
extractChartBlocks,
extractTransactionBlocks,
extractMarkdownBlocks,
extractInteractiveBlocks,
extractInfoBlocks,
extractCodeBlocks,
extractFormBlocks,
} from '@chaoslabs/ai-sdk';
import type { ChatCreateResponse } from '@chaoslabs/ai-sdk';
function extractAll(response: ChatCreateResponse) {
const tables = extractTableBlocks(response); // TableBlock[]
const charts = extractChartBlocks(response); // ChartBlock[]
const transactions = extractTransactionBlocks(response); // ActionBlock[]
const markdown = extractMarkdownBlocks(response); // MarkdownBlock[]
const interactive = extractInteractiveBlocks(response); // InteractiveBlock[]
const alerts = extractInfoBlocks(response); // AlertBlock[]
const code = extractCodeBlocks(response); // CodeBlock[]
const forms = extractFormBlocks(response); // FormBlock[]
return { tables, charts, transactions, markdown, interactive, alerts, code, forms };
}Copy code
Open in Cursor
Open in VS Code
Open in v0
Open in Claude
Open in ChatGPT
Searching Blocks by Title
Use findTableByTitle and findChartByTitle to locate specific blocks by their title (case-insensitive substring match).
import {
findTableByTitle,
findChartByTitle,
tableToObjects,
} from '@chaoslabs/ai-sdk';
// Find a table containing 'positions' in its title
const positionsTable = findTableByTitle(response, 'positions');
if (positionsTable) {
const rows = tableToObjects(positionsTable);
console.log('Positions:', rows);
}
// Find a chart containing 'allocation' in its title
const chart = findChartByTitle(response, 'allocation');
if (chart) {
console.log('Chart type:', chart.type);
}Copy code
Open in Cursor
Open in VS Code
Open in v0
Open in Claude
Open in ChatGPT
Streaming Block Detection
Use isBlockMessage during streaming to detect block messages as they arrive.
import {
Chaos,
WALLET_MODEL,
isBlockMessage,
isTableBlock,
isChartBlock,
} from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const response = await chaos.chat.responses.create({
model: WALLET_MODEL,
input: [
{ type: 'message', role: 'user', content: 'Show me top DeFi protocols by TVL' },
],
metadata: { user_id: 'user-123', session_id: 'session-blocks' },
onStreamEvent: (message) => {
if (isBlockMessage(message)) {
const block = message.data.block;
if (isTableBlock(block)) {
console.log('[stream] Table received:', block.title);
} else if (isChartBlock(block)) {
console.log('[stream] Chart received:', block.title);
}
}
},
});Copy code
Open in Cursor
Open in VS Code
Open in v0
Open in Claude
Open in ChatGPT
Was this helpful?