Node.js SDK
The official Node.js SDK for Plasmate, with full TypeScript types and SOM query helpers.
Installation
npm install plasmate
Requires Node.js 18+ and the plasmate binary on your PATH.
Quick Start
import { Plasmate } from 'plasmate';
const client = new Plasmate();
// Fetch a page and get SOM
const som = await client.som('https://example.com');
console.log(som.title); // "Example Domain"
console.log(som.regions); // semantic regions
console.log(som.meta); // compression stats
client.close();
TypeScript Types
`Som`
The top-level SOM document.
interface Som {
som_version: string;
url: string;
title: string;
lang: string;
regions: SomRegion[];
meta: SomMeta;
structured_data?: StructuredData;
}
`SomRegion`
A semantic region of the page (navigation, main content, sidebar, etc.).
interface SomRegion {
id: string;
role: RegionRole; // 'navigation' | 'main' | 'aside' | 'header' | 'footer' | 'form' | 'dialog' | 'content'
label?: string;
action?: string;
method?: string;
elements: SomElement[];
}
`SomElement`
An individual element within a region.
interface SomElement {
id: string;
role: ElementRole; // 'link' | 'button' | 'text_input' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'heading' | 'image' | 'list' | 'table' | 'paragraph' | 'section' | 'separator'
text?: string;
label?: string;
actions?: ElementAction[];
attrs?: SomElementAttrs;
children?: SomElement[];
hints?: SemanticHint[];
}
`SomMeta`
Compression and element statistics.
interface SomMeta {
html_bytes: number;
som_bytes: number;
element_count: number;
interactive_count: number;
}
Query Helpers
All query helpers accept a Som object and return matching elements or regions.
`findByRole(som, role)`
Find all regions matching a given role.
import { findByRole } from 'plasmate';
const navRegions = findByRole(som, 'navigation');
`findById(som, id)`
Find a single element by its stable ID.
import { findById } from 'plasmate';
const el = findById(som, 'login-btn');
if (el) console.log(el.text);
`findByTag(som, tag)`
Find elements matching a tag/role string.
import { findByTag } from 'plasmate';
const links = findByTag(som, 'link');
`findInteractive(som)`
Return all interactive elements (links, buttons, inputs, selects, textareas, checkboxes, radios).
import { findInteractive } from 'plasmate';
const interactive = findInteractive(som);
console.log(`${interactive.length} interactive elements`);
`getActionPlan(som)`
Return compact action targets with stable ids, deterministic cache_key values, labels, action lists, and availability state.
import { getActionPlan } from 'plasmate';
const availableTargets = getActionPlan(som).filter((target) => target.enabled);
`getActionPlanCacheKey(item)`
Return the same deterministic cache key used by getActionPlan() for a compact target.
import { getActionPlanCacheKey } from 'plasmate';
const cacheKey = getActionPlanCacheKey(target);
`getActionPlanIndex(som, options)`
Return compact action targets indexed by replay ids and grouped by role/action. Use this when an agent needs a small action menu instead of the full SOM.
import { getActionPlanIndex } from 'plasmate';
const index = getActionPlanIndex(som, { enabledOnly: true });
const buttons = index.byRole.button ?? [];
const clickTargets = index.byAction.click ?? [];
`findActionTargetsByRole(som, role, options)`
Return compact action targets for one SOM role without scanning the full plan.
import { findActionTargetsByRole } from 'plasmate';
const buttons = findActionTargetsByRole(som, 'button', { enabledOnly: true });
`findActionTargetsByAction(som, action, options)`
Return compact action targets exposing one action.
import { findActionTargetsByAction } from 'plasmate';
const clicks = findActionTargetsByAction(som, 'click', { enabledOnly: true });
`findByText(som, text)`
Find elements whose text content contains the given string (case-insensitive).
import { findByText } from 'plasmate';
const matches = findByText(som, 'Sign in');
`flatElements(som)`
Flatten all elements across all regions into a single array.
import { flatElements } from 'plasmate';
const all = flatElements(som);
`getTokenEstimate(som)`
Estimate the LLM token count for the SOM (heuristic: ~4 bytes per token).
import { getTokenEstimate } from 'plasmate';
const tokens = getTokenEstimate(som);
console.log(`~${tokens} tokens`);
Client API
Constructor
const client = new Plasmate({
binary: 'plasmate', // path to plasmate binary (default: 'plasmate')
timeout: 30000, // timeout in ms (default: 30000)
});
Stateless Methods
// Fetch a page and return SOM
const som = await client.som(url, options?);
// Alias for som()
const som = await client.fetchPage(url, options?);
// Extract plain text from a page
const text = await client.extractText(url, options?);
Stateful Sessions
// Open a persistent page session
const { sessionId, som } = await client.openPage(url);
// Execute JavaScript in the session
const result = await client.evaluate(sessionId, 'document.title');
// Click an element and get updated SOM
const updatedSom = await client.click(sessionId, 'login-btn');
// Close the session
await client.closePage(sessionId);
Cleanup
client.close();
The client communicates with the plasmate mcp subprocess over JSON-RPC 2.0 on stdio. It auto-starts the process on first call.