@biroai/agent-events-claude-code
v2026.513.0
Published
**P1.2** from `ROADMAP-NEXT.md` — the first runtime adapter for the Biro universal agent event bus.
Readme
@biroai/agent-events-claude-code
P1.2 from ROADMAP-NEXT.md — the first runtime adapter for the Biro universal agent event bus.
Parses Claude Code --output-format stream-json NDJSON events and emits
normalized BiroAgentEvent objects from @biroai/agent-events. Pure: no I/O,
no subprocess management, no Anthropic SDK dependency — input is an event
object or async line stream, output is validated schema events.
Usage
Per-line (sync)
import { parseClaudeStreamLine, translateClaudeEvent } from "@biroai/agent-events-claude-code";
import { randomUUID } from "node:crypto";
const ctx = {
companyId: "co-abc",
agentId: "agent-xyz",
issueId: null,
generateEventId: () => randomUUID(),
inFlightTools: new Map(), // reuse across lines for durationMs tracking
};
for (const line of rawLines) {
const raw = parseClaudeStreamLine(line);
if (!raw) continue;
const events = translateClaudeEvent(raw, ctx);
for (const ev of events) {
// ev is a validated BiroAgentEvent — safe to persist or broadcast
console.log(ev.type, ev.eventId);
}
}Async streaming
import { translateClaudeStream } from "@biroai/agent-events-claude-code";
import { createInterface } from "node:readline";
import { randomUUID } from "node:crypto";
async function processStream(readable: NodeJS.ReadableStream) {
const rl = createInterface({ input: readable, crlfDelay: Infinity });
const ctx = { companyId: "co-abc", agentId: "agent-xyz", issueId: null, generateEventId: randomUUID };
for await (const ev of translateClaudeStream(rl, ctx)) {
await persistEvent(ev); // your downstream
}
}Event type coverage
| Raw event | Emitted BiroAgentEvent(s) |
|-----------|--------------------------|
| system/init | agent.session.started |
| assistant (tool_use blocks) | agent.tool.requested × N |
| assistant (Task tool) | agent.tool.requested + agent.subagent.spawned |
| assistant (any content) | agent.turn.completed |
| user (tool_result blocks) | agent.tool.completed × N |
| result | agent.session.ended |
| system/compact_summary or compact_boundary | agent.compacted |
| Unknown types | (empty — dropped silently) |
Pointer
Schema types and Zod validators: @biroai/agent-events
Limitations
agent.subagent.completedis not emitted. Correlating aTasktool result back to the sub-agent's session would require cross-stream state that belongs upstream of this package.durationMsonagent.tool.completedis wall-clock from translation time (not tool execution start), because stream-json tool_use blocks carry no timestamp. Pass a sharedinFlightToolsmap across lines to get a reasonable approximation; without it,durationMsis 0.toolNameonagent.tool.completedis populated with thetool_use_idbecausetool_resultblocks do not repeat the tool name. Downstream consumers can join ontoolUseId.
Schema TODOs
- Compaction event shape is not fully documented as of 2026-05. Fields
tokens_before,tokens_after, andsummaryare inferred from community observation forcompact_summary;compact_boundaryappears to carry no token data. Both default to 0 when absent. See comment insrc/translate.ts. agent.subagent.completedexists in@biroai/agent-eventsbut is not emitted here. The wire format would require the parent to tracktool_use_id → sub-sessionmapping across event boundaries.
