Message Parsing & Streaming
Relevant source files
The following files were used as context for generating this wiki page:
The Message Parsing & Streaming system is a core architectural component designed to process real-time AI assistant responses. It serves as the bridge between raw LLM output and the application's interactive elements, specifically identifying and executing "Artifacts" and "Actions" (such as file creations or shell commands) while the message is still being received.
This system ensures that structural commands embedded within natural language are intercepted and handled by the WorkbenchStore, while the remaining text is rendered as clean Markdown for the user. By processing messages incrementally, the application can trigger side effects—like opening the code editor or running installation scripts—immediately upon detection in the stream.
Sources: app/lib/runtime/message-parser.ts, app/lib/hooks/useMessageParser.ts, app/components/chat/Chat.client.tsx:103-110
Architecture and Data Flow
The parsing logic is decoupled into a stateful parser class, a React hook for component integration, and a centralized store for managing the resulting side effects.
Streaming Lifecycle
The following sequence diagram illustrates how a raw message chunk flows from the AI provider through the parser to the UI and Workbench.
The StreamingMessageParser
The StreamingMessageParser is a stateful class that maintains the context of multiple messages simultaneously using a Map<string, MessageState>. It scans incoming strings for specific XML-like tags: <boltArtifact> and <boltAction>.
Key Parsing Logic
- Artifacts: Represent a container for a set of related actions (e.g., a project scaffold).
- Actions: Represent specific operations, currently supporting
file(writing content to a path) andshell(running terminal commands). - Incremental Parsing: The parser tracks the
positionof the last processed character to avoid re-parsing the entire message history on every new chunk.
| Component | Responsibility |
|---|---|
parse(messageId, input) | The primary entry point. Processes new text and returns "clean" output for the UI. |
insideArtifact | State flag indicating the parser is currently within an artifact block. |
insideAction | State flag indicating the parser is currently within an action block. |
onArtifactOpen | Callback triggered when a <boltArtifact> tag is first detected. |
onActionClose | Callback triggered when a </boltAction> tag is reached, providing the full content of the action. |
Sources: app/lib/runtime/message-parser.ts:40-48, app/lib/runtime/message-parser.ts:180-210
Integration Hooks and Callbacks
The useMessageParser hook wraps the parser for use within React components, specifically the ChatImpl component. It transforms the parser's callbacks into application-level side effects.
const messageParser = new StreamingMessageParser({
callbacks: {
onArtifactOpen: (data) => {
workbenchStore.showWorkbench.set(true);
workbenchStore.addArtifact(data);
},
onActionClose: (data) => {
if (data.action.type === 'shell') {
workbenchStore.addAction(data);
}
workbenchStore.runAction(data);
},
// ... other callbacks
},
});
Sources: app/lib/hooks/useMessageParser.ts:11-36
Callback Execution Table
| Callback | Action Taken |
|---|---|
onArtifactOpen | Sets showWorkbench to true and initializes the artifact in the store. |
onArtifactClose | Updates the artifact state to closed: true. |
onActionOpen | Adds non-shell actions immediately (streaming file content). |
onActionClose | Finalizes the action and triggers runAction via the ActionRunner. |
Sources: app/lib/hooks/useMessageParser.ts:15-35, app/lib/stores/workbench.ts:252-270
Workbench Integration
The WorkbenchStore manages the execution of actions identified by the parser. Each artifact is assigned an ActionRunner which interfaces with the webcontainer to perform file system operations or execute terminal commands.
Data Structures
- ArtifactState: Contains
id,title,closedstatus, and the associatedActionRunner. - ActionCallbackData: Encapsulates the
artifactId,messageId,actionId, and theBoltActionobject itself.
Sources: app/lib/runtime/message-parser.ts:21-26, app/lib/stores/workbench.ts:16-21
Markdown Rendering
While the parser handles functional tags, the remaining text is passed to the Markdown component. This component uses react-markdown with custom plugins to ensure that even if the parser leaves structural placeholders (like artifact divs), the UI renders them correctly.
- Custom Divs: The parser replaces
<boltArtifact>tags with<div class="__boltArtifact__" data-message-id="..."></div>. - Component Mapping: The
Markdowncomponent maps these specific divs to theArtifactReact component.
Sources: app/lib/components/chat/Markdown.tsx:28-40, app/lib/runtime/message-parser.ts:241-252
Summary
The Message Parsing & Streaming module provides a robust mechanism for handling complex, multi-step AI instructions. By utilizing a streaming parser that emits granular callbacks, the system maintains a responsive UI where code is written and commands are prepared in the background while the assistant continues to communicate. This architecture ensures strict separation between the conversational interface and the underlying execution environment.