@x-otto/devtools
v0.0.1-alpha.0
Published
Agent debug infrastructure: 21 breakpoints (4 categories), pause/resume control (`PauseController`), step control (`DebugPort` contract), CDP command mapping, and opt-in OpenTelemetry GenAI span export.
Readme
@x-otto/devtools
Agent debug infrastructure: 21 breakpoints (4 categories), pause/resume control (PauseController), step control (DebugPort contract), CDP command mapping, and opt-in OpenTelemetry GenAI span export.
In-process implementation (M17-02 removed the old Worker double-hop — Devtools is a pure in-memory composition).
Install
pnpm add @x-otto/devtoolsQuick Start
import { createDevtools } from '@x-otto/devtools'
const devtools = createDevtools()
// Breakpoints — all disabled by default
devtools.breakpoints.list() // 21 breakpoints
devtools.breakpoints.enable('tool_before')
devtools.breakpoints.enable('model_after')
// Engine integration: pass DebugPort to agent
// Agent calls debugPort.pause(snapshot) at pausable nodesDebug Commands
| Command | Description |
|---------|-------------|
| next() | Advance to next breakpoint |
| step() | Single step |
| over(depth?) | Skip current frame depth |
| continue() | Resume execution |
| stop(reason?) | Stop debugging |
Breakpoints
21 breakpoints, 4 categories (canonical source in @x-otto/agent engine-nodes pausable projection):
| Category | Count | Breakpoints |
|----------|-------|-------------|
| agent_work_loop | 10 | loop_start, model_before, model_after, tool_before, tool_after, loop_end, loop_cleanup, agent_aborted, agent_error, agent_done |
| work_loop_injection | 3 | steering_check, follow_up_check, context_transform |
| tool_executor | 4 | tool_resolve, tool_validate, tool_hook_before, tool_hook_after |
| session_prompt_lifecycle | 4 | prompt_before, prompt_after, context_build, messages_persist |
All disabled by default (CDP convention: explicit enable only).
DebugSnapshot & PauseResumePayload
Both defined in @x-otto/agent (re-exported here). PauseResumePayload supports mutation during pause:
systemPrompt— modify system promptinjectMessages— inject extra messages (user/system)removeMessageIndices— remove by indexllmParams— modify model params (temperature, maxTokens, thinkingLevel)metadata— attach metadata
Protocol (protocol.ts)
Canonical debug contract re-exported from @x-otto/agent (BREAKPOINT_POINTS, DebugSnapshot, DebugPort, DebugCommand, PauseResumePayload, PauseResult). Additional devtools-specific:
CDP_METHOD_TO_COMMAND— CDP method → internal command (e.g.Debugger.resume→continue,Debugger.stepOver→next)CommandRejectCode— rejection codes (STALE_OR_NO_PAUSE,INVALID_PARAMS,DEBUGGER_OFFLINE,BRIDGE_DISCONNECTED)- Platform domain methods (M11-01):
Trace.tail/range,Replay.start/seek/step,Checkpoint.list/restore/fork
OTel GenAI Export (opt-in, src/otel/)
Privacy-first by default: includeContent: false = no prompt/response/tool content in exported attributes.
| Module | Export | Description |
|--------|--------|-------------|
| genai-spans.ts | traceToGenAiSpans | TraceEvent[] → GenAI semantic convention span tree: invoke_agent (root) → chat (per LLM turn) → execute_tool (per tool call) |
| otlp.ts | buildOtlpTracesPayload | GenAiSpan tree → OTLP/HTTP JSON payload |
| exporter.ts | OtlpHttpExporter / exportSessionTrace / otlpExporterFromEnv | POST to collector; env opt-in via OTEL_EXPORTER_OTLP_ENDPOINT |
Compatible with Jaeger, Langfuse, or any standard OTLP collector.
Key Files
src/
devtools.ts # Devtools composition class + createDevtools factory
pause-controller.ts # In-process pause controller (FIFO pending, normalizeCommand, events)
protocol.ts # CDP mapping + platform domain protocol + debug contract re-exports
tools/
breakpoints.ts # 21 breakpoints (4 categories, all disabled by default)
debugger.ts # DebugPort implementation (breakpoint proxy + pause delegation)
otel/
genai-spans.ts # TraceEvent → GenAI semantic span tree
otlp.ts # GenAiSpan → OTLP/HTTP JSON payload
exporter.ts # OTLP HTTP exporter + env opt-in factory
index.ts # otel barrel
types.ts # Placeholder (types in protocol.ts / @x-otto/agent)
index.ts # Barrel exports
tests/ # 8 test filesDependencies
- Internal:
@x-otto/agent(debug contract truth source, TraceEvent),@x-otto/shared(TypedEventEmitter, logger) - External: none (OTLP export uses global fetch)
- Consumers:
@x-otto/service(DebugBridge),@x-otto/coding(app),@x-otto/runtime(session)
Testing
pnpm --filter @x-otto/devtools typecheck
pnpm --filter @x-otto/devtools build
pnpm vitest run packages/devtools/tests/8 test files covering: breakpoints (default disabled + CRUD), Debugger (DebugPort delegation), Devtools lifecycle, PauseController (pause/resume/reject/dispose), platform domain guards, GenAI span mapping, OTLP payload, OTLP export e2e.
