@claxedo/agent-event-runtime
v0.5.1
Published
`@claxedo/agent-event-runtime` owns harness event normalization and projection. It turns harness-native event frames from external agent harnesses into canonical `AgentRuntimeEvent` values, then lets host packages project those events into UI, compatibili
Readme
Agent Event Runtime Architecture
@claxedo/agent-event-runtime owns harness event normalization and projection.
It turns harness-native event frames from external agent harnesses into
canonical AgentRuntimeEvent values, then lets host packages project those
events into UI, compatibility, replay, or diagnostic formats.
The package is intentionally browser-safe. Hosts still own process management, stdio, WebSocket, EventSource, storage, HTTP routes, and persistence.
Agent-First Public Docs
Coding agents and host integrators should start with docs/agent.md. If the model is not obvious yet, read docs/concepts.md next. These docs define the package job, mental model, stability labels, boundaries, recipes, and public API.
Flow
native harness event frame
-> RawHarnessEvent
-> Harness event adapter state
-> AgentRuntimeEvent[]
-> RuntimeProjection state
-> compat events / debug traces / host-specific viewsThe runtime can sit on the server, in the browser, or in tests. The same adapter and projection code should produce the same canonical event stream when given the same raw harness event frames, clock, id factory, and snapshots.
A snapshot is a serializable checkpoint for resuming one state boundary:
RuntimeSnapshot resumes harness-frame-to-canonical-event translation, while
ProjectionSnapshot resumes canonical-event-to-output-view projection.
Layers
Contracts
src/contracts defines the cross-harness data model.
RawHarnessEventis the ingress envelope. It carriessource, optionalmethod, rawpayload, and optionalreceivedAt.AgentRuntimeEventis the canonical event union used between harness event adapters and projections.agentRuntimeEventfactories construct canonical events and keep event-kind drift visible to TypeScript.ToolDisplayandToolIntentcarry harness-neutral tool metadata that projections need for cards, labels, paths, commands, and search details.- diagnostics describe lossy mappings, unknown harness events, and runtime adapter failures without crashing the stream.
Core Runtime
src/core contains the harness-agnostic state machine.
createAgentEventRuntime()owns one adapter state value for one harness/thread pair.translateRawHarnessEvent()is the pure reducer API for replay and tests.HarnessEventAdapteris the TypeScript name for the harness event adapter boundary.RuntimeProjectionis the boundary each output projection implements.createAdapterRegistry()is a small name-to-adapter registry for hosts that select harness event adapters dynamically.
The runtime stamps emitted events with provider, threadId, and raw.
provider is the current API field for the external harness/source id. The
runtime also catches adapter exceptions and turns them into diagnostic events,
so a bad frame does not tear down the host stream.
Harness Event Adapters
src/harnesses contains harness event adapters. In this package, external
harness event sources are called agent providers, so provider adapters
translate harness-native payloads into canonical runtime events.
acpmaps ACPsession/updatenotifications and preserves ACP-specific details in metadata.claude-sdkmaps Claude Agent SDK messages, tool lifecycle updates, todos, rate limits, auth status, and result events.cursor-sdkmaps Cursor SDK local run stream events and SDK messages.codex-app-servermaps Codex app-server protocol notifications and requests.tool-display.tsextracts common harness-neutral display facts from tool names, kinds, and inputs.value.tscontains small shape readers for untrusted harness payloads.
Adapters own only translation state. They do not start processes, perform I/O, persist data, or know about OpenCode compatibility events.
Projections
src/projections turns canonical runtime events into output-specific views.
opencode-compatincrementally emits OpenCode-compatible event envelopes. It tracks assistant text, reasoning text, plan text, tool parts, tool status, tool outputs, and split part ids.debug-traceemits compact trace rows with runtime type, harness, thread, raw payload, and diagnostics.
Projections own their own state and snapshots. They should not mutate adapter state or depend on harness-native payloads except through diagnostic metadata.
Test Utilities
src/test-utils/replay.ts provides fixture replay for deterministic tests. Use
it when checking that a set of raw harness event frames still produces the expected
canonical stream.
Snapshots
There are two explicit restore boundaries:
RuntimeSnapshotstores harness/source id, thread id, snapshot version, and adapter state.ProjectionSnapshotstores projection name, snapshot version, and projection state.
Runtime snapshots do not include host transport state, persisted event stores,
or the default sequential id counter. Hosts that need stable fallback ids after
restore should provide a persisted createId implementation.
Both runtime and projection snapshots use cloneSnapshotValue() to avoid
sharing mutable state with callers. The primary path uses structuredClone;
the fallback constrains values to JSON-safe data.
Determinism
createAgentEventRuntime() accepts injected clock and createId functions.
Adapters should use those context functions whenever they need timestamps or
fallback ids.
createOpencodeCompatProjection() accepts its own clock because compatibility
events have their own timestamp boundary.
Tests should inject deterministic clocks and ids for replay parity. Production callers can omit them and use the defaults.
Adding A Harness Adapter
- Add a folder under
src/harnesses/<harness>. - Export a
create<Harness>Adapter()function from that folder. - Keep harness payload parsing local to the adapter.
- Emit
AgentRuntimeEventvalues through the canonical event contract. - Preserve harness-specific details in
metadata, not in new event variants, unless another harness adapter or projection needs the same concept. - Use
ToolDisplayfor projection-critical tool facts. - Add adapter tests with real harness-shaped frames and diagnostics for unmapped events.
- Add the harness adapter entry point to
src/index.ts,package.jsonexports, andscripts/build.tswhen it should be public.
Adding A Projection
- Add a folder under
src/projections/<projection>. - Implement
RuntimeProjection<Event, State>. - Keep all output-specific ids, accumulated text, and part maps in projection state.
- Return incremental events from
ingest(); do not require a full history. - Add
ProjectionSnapshotsupport for reload and replay. - Add tests that assert observable output, not private helper choreography.
- Add public exports and a build entry when the projection should be consumed directly.
Public Entry Points
The package ships public docs under docs/. Use
docs/recipes.md for import examples and
docs/api.md for the intended stable root API.
Entry point status:
- Stable:
@claxedo/agent-event-runtime,@claxedo/agent-event-runtime/contracts - Integration:
@claxedo/agent-event-runtime/harnesses/acp,@claxedo/agent-event-runtime/harnesses/claude,@claxedo/agent-event-runtime/harnesses/codex,@claxedo/agent-event-runtime/harnesses/cursor,@claxedo/agent-event-runtime/projections/debug-trace - Compatibility:
@claxedo/agent-event-runtime/projections/opencode-compat
The package publishes built ESM and declaration files from dist.
Verification
Run package checks from the package directory:
cd packages/agent-event-runtime
bun test src
bun typecheck
bun run buildDo not run tests from the repository root. This workspace guards against root test execution.
