Skip to main content
  • Version 0.1.0 · Purity pure zero-dep (browser-safe)
  • Purpose Parse runtime/Gateway message frames into typed text/thinking/tool blocks and build/merge ordered transcript entries.
  • Workspace deps none
  • External deps none (devDependency: @clawboo/tsconfig)
A single flat barrel, no subpath exports. All consumers import from @clawboo/protocol.

Public API

Functions

Text extraction

  • extractText(message: unknown): string | null, pull display text from a message; strips the [[reply_to_current]] assistant prefix + thinking tags (assistant role), or the channel envelope + appended exec-approval-wait policy (other roles). src/index.ts:315
  • extractTextCached(message: unknown): string | null, extractText memoized per object via a module-level WeakMap. src/index.ts:342
  • extractThinking(message: unknown): string | null, extract reasoning from block content, direct fields (thinking/analysis/reasoning/…), or tagged streams. src/index.ts:387
  • extractThinkingCached(message: unknown): string | null, extractThinking memoized per object. src/index.ts:451
  • extractThinkingFromTaggedText(text: string): string, extract content between closed <think>/<analysis>/<thought>/<antthinking> tags only. src/index.ts:352
  • extractThinkingFromTaggedStream(text: string): string, like above but also returns the tail after a still-open thinking tag (streaming in progress). src/index.ts:369

Tool extraction

  • extractToolCalls(message: unknown): ToolCallRecord[], read type: 'toolCall' items from array content → { id?, name?, arguments }. src/index.ts:514
  • extractToolResult(message: unknown): ToolResultRecord | null, read a role: 'toolResult' | 'tool' message → { toolCallId?, toolName?, details, isError?, text }. src/index.ts:532
  • extractToolLines(message: unknown): string[], format any tool calls + result as [[tool]]/[[tool-result]] markdown lines. src/index.ts:572

Markdown formatting & parsing

  • formatThinkingMarkdown(text: string): string, wrap each non-empty line in _…_ under a [[trace]] prefix. src/index.ts:460
  • formatToolCallMarkdown(call: ToolCallRecord): string, render a tool call as a [[tool]] line with a fenced JSON args block. src/index.ts:550
  • formatToolResultMarkdown(result: ToolResultRecord): string, render a tool result as a [[tool-result]] line with status meta + fenced text body. src/index.ts:558
  • parseToolMarkdown(line: string): ParsedToolMarkdown, split a [[tool]]/[[tool-result]] line into { kind, label, body }. src/index.ts:596
  • formatMetaMarkdown(meta): string, serialize { role, timestamp, thinkingDurationMs? } to a [[meta]] JSON line. src/index.ts:612
  • parseMetaMarkdown(line): { role, timestamp, thinkingDurationMs? } | null, parse a [[meta]] line back; null on invalid/missing role or non-positive timestamp. src/index.ts:626
  • stripTraceMarkdown(line: string): string, drop the leading [[trace]] prefix. src/index.ts:591

Markdown type guards

  • isTraceMarkdown(line: string): boolean, line starts with [[trace]]. src/index.ts:586
  • isToolMarkdown(line: string): boolean, line starts with [[tool]] or [[tool-result]]. src/index.ts:587
  • isMetaMarkdown(line: string): boolean, line starts with [[meta]]. src/index.ts:589

UI-metadata helpers

  • stripUiMetadata(text: string): string, remove reset/system-event/project-path injections, [message_id:…] tags, and the channel envelope. src/index.ts:652
  • isUiMetadataPrefix(text: string): boolean, text starts with a project/workspace-path or reset-session preamble. src/index.ts:663
  • isHeartbeatPrompt(text: string): boolean, text is a Read HEARTBEAT.md… prompt or carries a heartbeat-file-path line. src/index.ts:664

Main parser

  • parseMessage(raw: unknown): ParsedMessage, full parse → { text, thinking, toolCalls, toolResults, metadata }. src/index.ts:672

Agent helpers

  • buildAgentInstruction(params: { message: string }): string, trim a message into an agent instruction. src/index.ts:608
  • isAgentFileName(value: string): value is AgentFileName, type guard over AGENT_FILE_NAMES. src/index.ts:176
  • createAgentFilesState(): Record<AgentFileName, AgentFileState>, empty { content: '', exists: false } map keyed by every agent file name. src/index.ts:179

Transcript v2 utilities

  • fnv1a(value: string): string, FNV-1a 32-bit hash → 8-char hex. src/index.ts:729
  • createTranscriptEntryFromLine(params): TranscriptEntry | null, build one entry from a line; derives kind/role from markdown prefixes, resolves timestamp, computes the dedup fingerprint + entryId. src/index.ts:860
  • buildTranscriptEntriesFromLines(params: BuildTranscriptEntriesFromLinesParams): TranscriptEntry[], map lines → entries, threading sequence + the active [[meta]] timestamp. src/index.ts:910
  • sortTranscriptEntries(entries: TranscriptEntry[]): TranscriptEntry[], dedup by entryId, then sort by timestampMs with sequenceKey as tiebreak. src/index.ts:835
  • mergeTranscriptEntriesWithHistory(params): MergeTranscriptEntriesResult, fold persisted history into live entries (entryId then text/kind/role match), returning merge/confirmed/conflict counts. src/index.ts:994
  • buildOutputLinesFromTranscriptEntries(entries: TranscriptEntry[]): string[], extract the .text of each entry. src/index.ts:840
  • areTranscriptEntriesEqual(left: TranscriptEntry[], right: TranscriptEntry[]): boolean, shallow positional equality on entryId/text/timestamp/confirmed. src/index.ts:843

Types & interfaces

  • ToolCall: { id?, name, arguments: Record<string, unknown> }. src/index.ts:34
  • ToolResult: { toolCallId?, name, output, isError?, details? }. src/index.ts:40
  • MessageMeta: { role?, timestamp?, thinkingDurationMs? }. src/index.ts:48
  • ParsedMessage: { text, thinking, toolCalls, toolResults, metadata }, the parseMessage return. src/index.ts:54
  • ParsedToolMarkdown: { kind: 'call' | 'result', label, body }. src/index.ts:62
  • ToolResultRecord: { toolCallId?, toolName?, details, isError?, text? }, the extractToolResult shape. src/index.ts:476
  • TranscriptEntryKind: 'meta' | 'user' | 'assistant' | 'thinking' | 'tool'. src/index.ts:70
  • TranscriptEntryRole: 'user' | 'assistant' | 'tool' | 'system' | 'other'. src/index.ts:72
  • TranscriptEntrySource: 'local-send' | 'runtime-chat' | 'runtime-agent' | 'history' | 'legacy'. src/index.ts:74
  • TranscriptEntry: the canonical transcript row: { entryId, role, kind, text, sessionKey, runId, source, timestampMs, sequenceKey, confirmed, fingerprint }. src/index.ts:81
  • TranscriptAppendMeta: optional append-time overrides for an entry. src/index.ts:95
  • BuildTranscriptEntriesFromLinesParams: input shape for buildTranscriptEntriesFromLines. src/index.ts:106
  • MergeTranscriptEntriesResult: { entries, mergedCount, confirmedCount, conflictCount }. src/index.ts:117
  • AgentFileName: union of the 7 AGENT_FILE_NAMES literals. src/index.ts:136
  • AgentFileMeta: { title, hint }. src/index.ts:138
  • AgentFileState: { content, exists }. src/index.ts:143
  • AgentFileDef: backward-compat { filename, label, description, editable }. src/index.ts:149
ToolCallRecord is referenced in several function signatures above (formatToolCallMarkdown, extractToolCalls) but is a module-local type, not exported from the barrel.

Constants

  • AGENT_FILE_NAMES: readonly ['AGENTS.md', 'SOUL.md', 'IDENTITY.md', 'USER.md', 'TOOLS.md', 'HEARTBEAT.md', 'MEMORY.md']. src/index.ts:126
  • AGENT_FILE_META: Record<AgentFileName, AgentFileMeta>: { title, hint } per file. src/index.ts:156
  • AGENT_FILE_PLACEHOLDERS: Record<AgentFileName, string>: editor placeholder text per file. src/index.ts:166
  • AGENT_FILES: AgentFileDef[]: backward-compat 7-entry list ({ filename, label, description, editable }); MEMORY.md is editable: false. src/index.ts:185

Used by

  • @clawboo/events, Bridge parsers reuse extractText / parseMessage / isReasoningStream shapes for the policy pipeline.
  • @clawboo/adapter-openclaw, maps Gateway frames → RuntimeEvent via the pure parseChatPayload/parseMessage/extractText helpers.
  • apps/web chat + group-chat surfaces, parseToolMarkdown, the [[tool]]/[[trace]]/[[meta]] guards, TranscriptEntry ordering (sortTranscriptEntries, mergeTranscriptEntriesWithHistory), and AGENT_FILE_NAMES / AGENT_FILE_META for the agent file editor.
  • @clawboo/agent-registry, mirrors AGENT_FILE_NAMES locally to stay dependency-free (does not import this package).

Source

Barrel: packages/protocol/src/index.ts (single flat module; no subpath exports in package.json).

See also