Adapter UI Parser
A UI parser is a JavaScript bundle that an adapter ships to control how its agent's raw stdout lines render as transcript entries in the SLAW UI.
Built-in adapters include their parsers as compiled modules. External adapters can ship an optional ui-parser.js bundle that SLAW loads on demand.
How parsers are loaded
When SLAW's UI encounters an external adapter type for the first time, it fetches the parser from:
GET /api/adapters/{adapterType}/ui-parser.js
The returned JavaScript is executed inside a dedicated Web Worker so it cannot access the operator UI's same-origin state — no cookies, no localStorage, no authenticated fetch, no DOM.
Communication protocol
The main thread and worker communicate via a narrow postMessage protocol:
| Direction | Message |
|---|---|
| Main → Worker | { type: "init", source } |
| Worker → Main | { type: "ready" } or { type: "error", message } |
| Main → Worker | { type: "parse", id, line, ts } |
| Worker → Main | { type: "result", id, entries } |
Each parse request includes a unique id, the raw line string, and the ts timestamp. The worker responds with entries — an array of TranscriptEntry objects that the UI renders.
Sync fast-path
The existing parseStdoutLine contract is synchronous: the UI reads cached results on the next transcript recomputation. After the first parse round-trip, subsequent lines return from the in-memory cache with no additional latency. In practice this adds at most one frame of delay, which is imperceptible.
Built-in adapter fallback
When no UI parser is available for an adapter type — because no ui-parser.js was found, or the adapter has not been loaded yet — SLAW falls back to the process adapter parser, which renders each stdout line as a plain text entry.
Overriding a built-in parser
An external adapter can ship a ui-parser.js for a built-in adapter type (claude_local, codex_local, etc.). While that external override is enabled, SLAW uses it in place of the built-in parser. When the override is disabled or removed, the original built-in parser is restored without a page reload.
A generation counter prevents stale async loads from racing with deactivation: if the parser resolves after its override has been torn down, the stale result is discarded.
Implementing a UI parser
A ui-parser.js module must export either parseStdoutLine (stateless, line-by-line) or createStdoutParser (stateful, for multi-line protocols):
// Stateless line parser
export function parseStdoutLine(line, ts) {
// Return an array of TranscriptEntry objects, or [] to emit nothing
return [{ type: "text", content: line, ts }];
}
// Stateful parser factory (optional)
export function createStdoutParser() {
let buffer = "";
return {
push(line, ts) {
buffer += line;
return []; // accumulate
},
flush(ts) {
return [{ type: "text", content: buffer, ts }];
}
};
}
Build the module as a self-contained IIFE or ESM bundle — no require or Node.js APIs; it executes in a Worker context.