Monitor Server
@monitor/server is the core package of Agent Tracer. It ingests events emitted by runtime adapters, structures them into tasks / sessions / timeline events, persists them to SQLite, and exposes HTTP + WebSocket surfaces for the dashboard and MCP layer.
Responsibilities
- task, session, and runtime-session lifecycle
- timeline event ingestion and classification result storage
- bookmark CRUD
- workflow evaluation storage and similarity search
- read models for overview, task detail, and observability
- WebSocket broadcast of every change
Key files
packages/server/src/index.ts— process entrypointpackages/server/src/bootstrap/create-nestjs-monitor-runtime.ts— composition rootpackages/server/src/presentation/app.module.tspackages/server/src/presentation/controllers/*.tspackages/server/src/application/monitor-service.tspackages/server/src/application/services/*— policy + metadata helperspackages/server/src/application/ports/*— repository + broadcaster interfacespackages/server/src/infrastructure/sqlite/*— SQLite repositorypackages/server/src/presentation/ws/event-broadcaster.tspackages/server/src/presentation/schemas.ts— Zod request schemas
Layering
bootstrap/
create-nestjs-monitor-runtime.ts # server composition root
runtime.types.ts # public runtime types
application/
monitor-service.ts # use case entrypoint
services/ # policy + metadata helpers
ports/ # repository + broadcaster interfaces
presentation/
controllers/ # HTTP surface (Nest controllers)
app.module.ts
schemas.ts # Zod DTOs
ws/event-broadcaster.ts # WebSocket notifications
infrastructure/
sqlite/ # SQLite-backed repositoryApplication
MonitorService is the single entrypoint for use cases. It handles task start / complete, runtime session ensure / end, event logging, bookmark CRUD, evaluation, and search. Supporting policy and metadata logic lives in application/services/* (e.g. session-lifecycle-policy.ts, trace-metadata-factory.ts).
Presentation
NestJS controllers handle the HTTP surface. presentation/schemas.ts validates request bodies with Zod before delegating to MonitorService. EventBroadcaster in presentation/ws/ handles real-time notifications.
Controllers currently registered:
admin.controller.ts— overview / read modellifecycle.controller.ts— task / session lifecycleevent.controller.ts— generic event loggingbookmark.controller.ts— bookmark CRUDsearch.controller.ts— search read modelevaluation.controller.ts— workflow library evaluation + search
Infrastructure
SQLite is the only storage backend that currently runs. Repositories live in infrastructure/sqlite/*.repository.ts and are composed in infrastructure/sqlite/index.ts. Because the application layer only depends on the port interfaces, swapping storage is a matter of providing a new adapter.
Bootstrap flow
EventBroadcasteris constructed.NestFactory.create(AppModule.forRoot(...))wires SQLite ports,MonitorServiceProvider, and the controllers.- HTTP server and
WebSocketServerare attached to the same Nest instance. /wsupgrade requests are accepted; overview + task list snapshots are sent to new WebSocket clients immediately.
Points worth knowing
- The default runtime is NestJS — there is no alternative composition root in the current code.
- Canonical
runtimeSourceisclaude-plugin(withclaude-hookkept as a legacy alias). - The workflow library read path and the observability read model are first-class API surfaces, not ad-hoc debugging endpoints.
- Runtime session and explicit session-end coexist so auto-plugins and manual clients can both bind to the same task.
Maintenance notes
MonitorService responsibility spread
Lifecycle, runtime-session binding, generic event logging, bookmark CRUD, search, and evaluation all live under one service. It works today but the next structural improvement is to split it into use-case-level services (lifecycle / event logging / bookmark / evaluation).
Schema / DTO drift risk
presentation/schemas.ts (Zod) and application/types.ts (TS interfaces) must stay in sync. Every new field is two edits, so consider descriptor-level sharing if this becomes a bottleneck.
Read-path cost
The task list read path rebuilds display titles from event history, which scales linearly with event count per task. At higher volume a cached write-model / read-model split will become worthwhile.
Async dedupe map
The monitor service uses an in-memory dedupe map for async events. There is no cleanup policy yet; for long-running servers a TTL or LRU eviction should be added before the map grows unbounded.
Reading order
src/index.tssrc/bootstrap/create-nestjs-monitor-runtime.tssrc/presentation/controllers/*.tssrc/application/monitor-service.tssrc/infrastructure/sqlite/index.ts