@zclaudia/agent-transcript-kit
v0.1.1
Published
Shared agent-transcript view model, headless reducer, and text utilities
Readme
@zclaudia/agent-transcript-kit
Shared agent-transcript view model, headless reducer, and transcript utilities for ZClaudia agent clients.
The kit unifies the rendering view model, not the wire protocol: each host application keeps its
own transport and writes a thin adapter that translates wire events into normalized
TranscriptEvents. The shared reducer folds those into a block-structured transcript (text →
tool → text interleaving preserved), and pure selectors derive the strings hosts persist or copy.
Session routing, sequence dedup, and reconnect reconciliation stay host-side; the package has no
runtime dependencies and imports no host types.
Install
pnpm add @zclaudia/agent-transcript-kitUsage
Feed adapter-translated events through the reducer and read the result with selectors:
import {
applyTranscriptEvent,
initialTranscriptState,
orderedToolCalls,
turnText,
type TranscriptEvent,
} from '@zclaudia/agent-transcript-kit';
const events: TranscriptEvent[] = [
{ type: 'turn_started', turnId: 'run-1' },
{ type: 'text_delta', turnId: 'run-1', delta: 'Running the tests.' },
{
type: 'tool_started',
turnId: 'run-1',
toolCallId: 't1',
name: 'Bash',
input: { command: 'npm test' },
},
{
type: 'tool_finished',
turnId: 'run-1',
toolCallId: 't1',
presentation: { kind: 'terminal', command: 'npm test', output: '1 passing' },
},
{ type: 'turn_finished', turnId: 'run-1' },
];
const state = events.reduce(
(current, event) => applyTranscriptEvent(current, event, { assertEvents: true }),
initialTranscriptState
);
const turn = state.items.find(item => item.kind === 'assistant_turn');
// turnText(turn) → 'Running the tests.'
// orderedToolCalls(turn)[0].presentation?.kind → 'terminal'The reducer is immutable and framework-free; wrap it in useReducer, Zustand, or anything else.
Replays are idempotent (duplicate turn_started/tool_started/marker events are no-ops, text
snapshots merge without duplicating), and stream events for an unknown turn create it, so
reconnecting mid-stream still renders.
Modules
transcript— view model:TranscriptItem,AssistantTurnItem,ToolCallView,ToolPresentation(render by presentation, never by tool name), openextslots.interaction— blocking interaction requests (approval/question/form/plan/secret) with capability-declared decision spaces.events— the adapter contract: normalized streamingTranscriptEvents withdelta | snapshottext semantics.state/selectors— the reducer plusturnText,turnThinking,orderedToolCalls,activeTurn,pendingInteraction.delta-batch—createTranscriptBatcher: coalesce streaming deltas into one commit per animation frame (16 ms fallback off-browser); lifecycle events flush synchronously.tool-classify—classifyTool/toolSummary: best-effortname + input + result → ToolPresentationfor hosts without wire-level knowledge.diff— LCS line diff with a 400-line cap, unified-diff parsing, ANSI stripping.text-utils—mergeStreamText,splitThinkTags,stabilizeStreamingMarkdown,stripAnsi.guards— dev-onlyassertTranscriptEvent(enable viaapplyTranscriptEvent'sassertEvents; skip in production builds).
Package boundaries
- The kit owns the transcript view model and the headless logic over it.
- Host applications own their wire protocols and the adapters that translate them; adapters never live in this package.
- The kit depends on nothing at runtime and must not import host ecosystem types.
Internal design notes live in docs/design.md, the cross-host mapping validation in docs/mapping.md, and per-host adapter worklists in docs/roadmap.md.
Compatibility
The package follows semantic versioning. Additive fields and events are minor changes. Removing or changing a public field, event, or reducer behavior hosts can observe is a major change.
Releasing
Publishing uses npm Trusted Publishing from .github/workflows/publish.yml; the repository does
not need an NPM_TOKEN. To release a version:
- Update
package.jsonto the new version and merge the change tomain. - Create a
v<version>tag, such asv0.1.1, on that commit. - Publish a GitHub Release for the tag.
The release workflow verifies that the tag matches package.json, runs all checks, and publishes
the public package through GitHub OIDC. Re-running a release for an already-published npm version
will fail because npm package versions are immutable.
License
MIT
