# Types

The exported types and constants of `nanocode-wasm` that no other page covers.

These types describe runtime metrics, model timing records, logged events, model sockets, remote requests, and timing aggregates. Import them as types from `nanocode-wasm`. `RECENT_MODEL_LIMIT`, `Timings`, and `timingDifference` are values.

```ts title="metrics.ts"
import type { AgentRuntime, RuntimeMetrics } from 'nanocode-wasm'

declare const runtime: AgentRuntime

// Reads a snapshot of the counters and timings
const metrics: Readonly<RuntimeMetrics> = runtime.metrics
console.log(metrics.model_requests, metrics.timing.models.length)
```

## Runtime Metrics

### RuntimeMetrics

```ts
type RuntimeMetrics = {
  // The size of the module's linear memory
  wasm_memory_bytes: number
  timing: {
    runtime_id: string
    started_at: number
    elapsed_ms: number
    spans: TimingSnapshot
    checkpoints: TimingSnapshot
    models: ModelTiming[]
  }
  initializations: number
  runs: number
  completed: number
  failed: number
  cancelled: number
  retries: number
  waits: number
  resumes: number
  rejected_runs: number
  cancellations: number
  host_calls: number
  store_calls: number
  log_calls: number
  model_requests: number
  model_sockets: number
  socket_sends: number
  socket_frames: number
  tool_calls: number
  body_reads: number
  event_batches: number
  events: number
  host_cancellations: number
  dropped_replies: number
  disposals: number
  bridge_request_bytes: number
  bridge_reply_bytes: number
}
```

`runtime.metrics` returns this shape. `runs` counts `drive` calls, and `completed`, `failed`, `cancelled`, `retries`, `rejected_runs` (busy), `waits`, and `resumes` count their results. `timing.spans` aggregates bridge and host call durations, and `timing.checkpoints` aggregates store transactions by operation. `timing.models` holds the last `RECENT_MODEL_LIMIT` dispatches.

```ts
import type { AgentRuntime } from 'nanocode-wasm'

declare const runtime: AgentRuntime

// The mean duration of WASM entries
const enter = runtime.metrics.timing.spans['wasm.enter']
if (enter) console.log(enter.total_ms / enter.count)
```

### RECENT_MODEL_LIMIT

```ts
// The number of model dispatches that metrics keep
const RECENT_MODEL_LIMIT = 64
```

`metrics.timing.models` keeps the most recent 64 model dispatches and drops the oldest first. This constant is the retention policy for diagnostics.

```ts
import { RECENT_MODEL_LIMIT, type AgentRuntime } from 'nanocode-wasm'

declare const runtime: AgentRuntime

// true once 64 dispatches ran
console.log(runtime.metrics.timing.models.length === RECENT_MODEL_LIMIT)
```

## Model Timing

### ModelProvider

```ts
type ModelProvider = 'claude' | 'codex'
```

The model backend of a session, set by `config.provider`.

```ts
import type { ModelProvider } from 'nanocode-wasm'

// The default provider
const provider: ModelProvider = 'claude'
```

### ModelTiming

```ts
type ModelTiming = {
  dispatch_id: number
  transport?: 'websocket'
  started_ms: number
  headers_ms?: number
  first_byte_ms?: number
  last_byte_ms?: number
  body_read_wait_ms: number
  body_reads: number
  bytes: number
  max_chunk_gap_ms: number
  sends?: number
  duration_ms?: number
  status?: number
  outcome?: 'eof' | 'closed' | 'cancelled' | 'failed'
  diagnostic?: unknown
}
```

The timing record of one model HTTPS request or Codex socket. `started_ms` is relative to the runtime's start, and `headers_ms`, `first_byte_ms`, `last_byte_ms`, and `duration_ms` are relative to `started_ms`. Socket records set `transport` and count `sends`. `outcome` is set when the request ends.

```ts
import type { ModelTiming } from 'nanocode-wasm'

declare const timing: ModelTiming

// Time to first byte, in milliseconds
console.log(timing.first_byte_ms)
```

### RuntimeTiming

```ts
type RuntimeTiming = ModelTiming & { runtime_id: string }
```

The record that `dispatch` and `socket.open` receive as `timing`, with the runtime's ID. The runtime fills it as the request runs. A host can set `diagnostic` on it.

```ts
import type { RuntimeOptions } from 'nanocode-wasm'

// Records which region served the request
const dispatch: RuntimeOptions['dispatch'] = async (
  request,
  signal,
  timing,
) => {
  const response = await fetch(request.endpoint, {
    body: request.body as Uint8Array<ArrayBuffer>,
    headers: request.headers,
    method: 'POST',
    redirect: 'error',
    signal,
  })
  timing.diagnostic = { region: response.headers.get('x-region') }
  return response
}
```

## Events and Sockets

### LoggedEvent

```ts
type LoggedEvent = {
  seq: number
  request_id: string | null
  created_at: number
  event: unknown
}
```

One event of the session log. `seq` orders the log, `request_id` names the event's turn or is `null`, `created_at` is in milliseconds since the epoch, and `event` is the event JSON.

```ts
import type { LoggedEvent } from 'nanocode-wasm'

declare const entry: LoggedEvent

// Reads the event type
console.log((entry.event as { type?: string }).type)
```

### MessageSocket

```ts
interface MessageSocket {
  send(message: string): void
  close(code?: number, reason?: string): void
  addEventListener(
    type: 'message' | 'close' | 'error',
    listener: (event: any) => void,
  ): void
}
```

The socket shape that model sockets and `RemoteExecutor` use. A standard `WebSocket` satisfies it. The runtime reads `event.data` from `message` events and `event.code` and `event.reason` from `close` events.

```ts
import type { MessageSocket } from 'nanocode-wasm'

// A WebSocket is a MessageSocket
const socket: MessageSocket = new WebSocket(
  'wss://executor.example.com',
)
```

### SocketHandshake

```ts
type SocketHandshake = {
  status: number
  headers: Iterable<[string, string]>
  socket?: MessageSocket
  idle_ms?: number
  text(): Promise<string>
}
```

The result of `socket.open`. On status 101, `socket` is the open socket and `idle_ms` sets an optional read deadline. A frame that does not arrive within `idle_ms` fails the socket. For a rejected handshake, `text()` returns the response body.

```ts
import type { SocketHandshake } from 'nanocode-wasm'

declare const socket: WebSocket

// An accepted handshake with a 60-second read deadline
const handshake: SocketHandshake = {
  headers: [],
  idle_ms: 60_000,
  socket,
  status: 101,
  text: async () => '',
}
```

### RemoteRequest

```ts
type RemoteRequest = {
  op: string
  connection?: string | null
  frames?: string[]
  durable?: boolean
  dispatches?: boolean
  reason?: string
}
```

A request that `RuntimeOptions.remote.execute` receives. `op` is `remote_catalog`, `remote_send`, `remote_poll`, or `remote_close`. `connection` is `null` for the configured executor and the attached connection for a hand. `frames` holds a send's frames, and `reason` a close's reason.

```ts
import type { RemoteRequest } from 'nanocode-wasm'

declare const request: RemoteRequest

// Routes the request to a hand or to the executor
const target = request.connection ?? 'executor'
```

## Timing Aggregates

### Timings

```ts
class Timings {
  record(name: string, milliseconds: number): void
  snapshot(): TimingSnapshot
}
```

Aggregates span durations by name. `record` adds one duration, and `snapshot` returns a copy of the totals.

```ts
import { Timings } from 'nanocode-wasm'

// Aggregates two host spans
const timings = new Timings()
timings.record('host.tool_call', 12)
timings.record('host.tool_call', 8)
console.log(timings.snapshot())
```

### TimingSnapshot

```ts
type TimingValue = { count: number; total_ms: number; max_ms: number }
type TimingSnapshot = Record<string, TimingValue>
```

The totals per span name: the number of durations, their sum, and the largest one.

```ts
import type { TimingSnapshot } from 'nanocode-wasm'

declare const snapshot: TimingSnapshot

// The slowest tool call
console.log(snapshot['host.tool_call']?.max_ms)
```

### timingDifference

```ts
timingDifference(
  after: TimingSnapshot,
  before: TimingSnapshot,
): Record<string, { count: number; total_ms: number }>
```

Returns the count and total per span name between two snapshots, and leaves out names without new durations.

```ts
import { timingDifference, type AgentRuntime } from 'nanocode-wasm'

declare const runtime: AgentRuntime

// Measures the spans of one turn
const before = runtime.metrics.timing.spans
await runtime.drive()
console.log(timingDifference(runtime.metrics.timing.spans, before))
```
