API
@ogygia/devtools
The in-page dock.
On this page
- add_sink
- clear
- configure
- emit
- ingest
- ingest_server_events
- install_console_sink
- install_devtools_ui
- install_postmessage_sink
- install_window_sink
- snapshot
- to_trace
- DEVTOOLS
- DEVTOOLS_SCHEMA_VERSION
- DevtoolsEnvelope
- DevtoolsEnvelope.v
- DevtoolsEnvelope.seq
- DevtoolsEnvelope.t
- DevtoolsEnvelope.realm
- DevtoolsTrace
- DevtoolsTrace.kind
- DevtoolsTrace.version
- DevtoolsTrace.events
- DevtoolsWindowHook
- DevtoolsWindowHook.version
- DevtoolsWindowHook.events
- DevtoolsWindowHook.on
- DevtoolsWindowHook.clear
- DevtoolsWindowHook.trace
- CompileEventInput
- DevtoolsDomain
- DevtoolsEvent
- DevtoolsEventInput
- DevtoolsSink
- HubEventInput
- NavEventInput
- RuntimeEventInput
- ServerEventInput
- WireEventInput
This page is generated from the package’s own .d.ts files on every build, so the signatures, descriptions and examples below always match the source.
import { … } from '@ogygia/devtools';Exports add_sink · clear · configure · emit · ingest · ingest_server_events · install_console_sink · install_devtools_ui · install_postmessage_sink · install_window_sink · snapshot · to_trace · DEVTOOLS · DEVTOOLS_SCHEMA_VERSION · DevtoolsEnvelope · DevtoolsTrace · DevtoolsWindowHook · CompileEventInput · DevtoolsDomain · DevtoolsEvent · DevtoolsEventInput · DevtoolsSink · HubEventInput · NavEventInput · RuntimeEventInput · ServerEventInput · WireEventInput
add_sink
function
Register a sink; returns an unregister fn. A sink sees events from registration onward — to also
replay what's buffered, iterate snapshot first.
function add_sink(sink: DevtoolsSink): () => void;clear
function
Drop every buffered event (the sinks are left registered). Used between e2e scenarios + traces.
function clear(): void;configure
function
Runtime configuration — pause/resume, resize the ring, set per-name sampling.
function configure(opts: {
active?: boolean;
cap?: number;
sample?: Record<string, number>;
}): void;emit
function
THE emit entry point. Stamps the envelope (v / seq / t / realm), rings the buffer, fans to sinks.
A no-op when the bus is inactive. Guard the CALL with a module-local if (DEVTOOLS) so the event
literal compiles out entirely when off — this internal guard only protects direct/dynamic callers.
function emit(input: DevtoolsEventInput): void;ingest
function
Push ALREADY-STAMPED events into the buffer + sinks WITHOUT re-stamping — the ingest path for the
server realm's events, which arrive from the application/ogygia-devtools side-channel carrying
their own envelope (v / seq / t / realm:'server'). This is what unifies the server render stream
and the client wake stream into ONE window.__ogygia_devtools timeline, correlated by fingerprint.
function ingest(events: DevtoolsEvent[]): void;ingest_server_events
function
Read the server realm's <script type="application/ogygia-devtools"> side-channel (injected by the
handle on a devtools build) and INGEST its events into the unified stream, so a region's server
render sits in the same window.__ogygia_devtools timeline as its client wake — correlated by
fingerprint. Idempotent per document via a marker attribute; no-op off the browser or when the
script is absent. Returns how many server events were ingested.
function ingest_server_events(): number;install_console_sink
function
Log every event to the console (debugging). filter limits by domain/name substring.
function install_console_sink(filter?: (event: DevtoolsEvent) => boolean): () => void;install_devtools_ui
function
function install_devtools_ui(opts?: {
csr_true?: boolean;
}): void;install_postmessage_sink
function
Forward every event to a postMessage target (the REPL's tab ↔ worker ↔ iframe channel). Pass a Worker / MessagePort / Window; each event is posted as { __ogygia_devtools: event }.
Returns the unregister fn.
function install_postmessage_sink(target: {
postMessage: (message: unknown) => void;
}): () => void;install_window_sink
function
Publish window.__ogygia_devtools so an out-of-page reader (Playwright, a devtools panel, a REPL
host) can pull buffered events, subscribe to new ones, and drain a trace — WITHOUT importing any
framework module. Idempotent. No-op off the browser. Returns the hook (or undefined on the server).
This is what lets our e2e assert on the ISLAND LIFECYCLE directly ("interaction island fired its
wake, replayed exactly one click") instead of polling the DOM behind a waitForTimeout — the
bus pays for itself in our own tests first (the note's proof-of-value).
function install_window_sink(): DevtoolsWindowHook | undefined;snapshot
function
Buffered events in emission order (oldest → newest). Copies out — safe to hold/serialize.
function snapshot(): DevtoolsEvent[];to_trace
function
Serialize the current buffer into a DevtoolsTrace.
function to_trace(): DevtoolsTrace;DEVTOOLS
const
Compile-time gate (Vite define). Exported for the public surface + tests; seam modules declare
their OWN local const DEVTOOLS from the same token so DCE never depends on cross-module folding.
const DEVTOOLS: booleanDEVTOOLS_SCHEMA_VERSION
const
Bump only on a breaking shape change; a trace stamps this so a reader can gate on it.
const DEVTOOLS_SCHEMA_VERSION = 1DevtoolsEnvelope
interface
Fields the bus stamps on EVERY event — the caller never sets these.
interface DevtoolsEnvelope {/*…*/}DevtoolsEnvelope.v
Schema version (DEVTOOLS_SCHEMA_VERSION) — copied onto every event for trace gating.
v: number;DevtoolsEnvelope.seq
Monotonic per-session sequence number (ordering that survives equal timestamps).
seq: number;DevtoolsEnvelope.t
Timestamp: performance.now() (ms, sub-ms precision) when available, else Date.now().
t: number;DevtoolsEnvelope.realm
Which realm emitted it — a trace merges client + server streams, so it must be labelled.
realm: "client" | "server";DevtoolsTrace
interface
A portable trace — a versioned bag of events, attachable to a bug report and replayable in the REPL later (the note's "CPU-profile energy, but for the islands lifecycle").
interface DevtoolsTrace {/*…*/}DevtoolsTrace.kind
Marker so a consumer knows what it's holding.
kind: "ogygia-devtools-trace";DevtoolsTrace.version
{@link DEVTOOLS_SCHEMA_VERSION }.
version: number;DevtoolsTrace.events
Events in emission order.
events: DevtoolsEvent[];DevtoolsWindowHook
interface
Shape of window.__ogygia_devtools (the e2e / instrument entry point).
interface DevtoolsWindowHook {/*…*/}DevtoolsWindowHook.version
Schema version, so a reader can gate.
version: number;DevtoolsWindowHook.events
Every buffered event, oldest → newest (a fresh copy each call).
events(): DevtoolsEvent[];DevtoolsWindowHook.on
Subscribe to events from now on; returns an unsubscribe fn.
on(cb: (event: DevtoolsEvent) => void): () => void;DevtoolsWindowHook.clear
Drop the buffer (between e2e scenarios).
clear(): void;DevtoolsWindowHook.trace
Serialize the buffer to a portable trace.
trace(): DevtoolsTrace;CompileEventInput
type
type CompileEventInput = {
domain: "compile";
name: "compile.island.discovered";
iid: string;
entry?: string;
strategy: string;
csr: boolean;
} | {
domain: "compile";
name: "compile.chunk.emitted";
entry: string;
bytes: number;
};DevtoolsDomain
type
The six event domains (note's Schema-v1 table).
type DevtoolsDomain = "compile" | "server" | "wire" | "runtime" | "hub" | "nav";DevtoolsEvent
type
A fully-stamped event as it sits in the ring buffer / trace / on a sink.
type DevtoolsEvent = DevtoolsEventInput & DevtoolsEnvelope;DevtoolsEventInput
type
What a call site passes to emit — the envelope is added by the bus.
type DevtoolsEventInput = CompileEventInput | ServerEventInput | WireEventInput | RuntimeEventInput | HubEventInput | NavEventInput;DevtoolsSink
type
A sink is any consumer of stamped events. Throwing is contained — one bad sink never starves the others, and never breaks the framework path that emitted the event.
type DevtoolsSink = (event: DevtoolsEvent) => void;HubEventInput
type
type HubEventInput = {
domain: "hub";
name: "hub.mint";
kind: string;
id: string;
tag?: string;
} | {
domain: "hub";
name: "hub.resolve";
kind: string;
id: string;
scope: string;
tag?: string;
hit: boolean;
} | {
domain: "hub";
name: "hub.dispose";
scope: string;
count: number;
};NavEventInput
type
type NavEventInput = {
domain: "nav";
name: "nav.start";
from: string;
to: string;
type: string;
} | {
domain: "nav";
name: "nav.finish";
to: string;
ms: number;
reconciled: boolean;
vt: boolean;
} | {
domain: "nav";
name: "nav.reconcile";
key: string;
decision: "keep" | "patch" | "mount" | "remove";
entry?: string;
wake?: string;
} | {
domain: "nav";
name: "nav.batch";
count: number;
} | {
domain: "nav";
name: "nav.fallback";
reason: string;
};RuntimeEventInput
type
type RuntimeEventInput = {
domain: "runtime";
name: "runtime.boot";
features: string[];
} | {
domain: "runtime";
name: "region.connected";
entry?: string;
fp?: string;
wake?: string;
deferred: boolean;
nested: boolean;
} | {
domain: "runtime";
name: "wake.scheduled";
entry?: string;
fp?: string;
when: string;
} | {
domain: "runtime";
name: "wake.fired";
entry?: string;
fp?: string;
when: string;
} | {
domain: "runtime";
name: "region.prefetch";
entry?: string;
fp?: string;
} | {
domain: "runtime";
name: "region.hydrate.start";
entry?: string;
fp?: string;
} | {
domain: "runtime";
name: "region.hydrate.done";
entry?: string;
fp?: string;
ms: number;
} | {
domain: "runtime";
name: "region.hydrate.failed";
entry?: string;
fp?: string;
message: string;
} | {
domain: "runtime";
name: "region.hydrate.recovered";
entry?: string;
fp?: string;
reason?: string;
} | {
domain: "runtime";
name: "region.hydrate.healed";
entry?: string;
fp?: string;
reason?: string;
} | {
domain: "runtime";
name: "load.started";
class: "user" | "visible" | "ahead" | "speculative";
kind: "code" | "content";
label?: string;
waited_ms: number;
} | {
domain: "runtime";
name: "load.critical";
outcome: "arrived" | "input" | "cap" | "none";
resources: number;
waited_ms: number;
} | {
domain: "runtime";
name: "region.hydrate.conflict";
entry?: string;
fp?: string;
reason?: string;
} | {
domain: "runtime";
name: "svelte.hydration.warning";
code: string;
message: string;
file?: string;
fp?: string;
} | {
domain: "runtime";
name: "region.server.applied";
entry?: string;
endpoint?: string;
bytes: number;
revalidate: boolean;
wait_ms?: number;
} | {
domain: "runtime";
name: "region.batch.sent";
batch: number;
kind: "page" | "nav";
endpoints: string[];
} | {
domain: "runtime";
name: "region.batch.part";
batch: number;
endpoint: string;
} | {
domain: "runtime";
name: "region.batch.done";
batch: number;
sent: number;
delivered: number;
status: number;
refused?: "redirected" | "document";
final_url?: string;
} | {
domain: "runtime";
name: "region.server.failed";
entry?: string;
endpoint?: string;
reason: "redirected" | "document" | "forbidden" | "error";
final_url?: string;
message?: string;
attempt: number;
final: boolean;
} | {
domain: "runtime";
name: "entry.fallback";
entry: string;
src: string;
recovered: boolean;
} | {
domain: "runtime";
name: "interaction.replay";
entry?: string;
fp?: string;
clicks: number;
fields: number;
};ServerEventInput
type
type ServerEventInput = {
domain: "server";
name: "server.region.rendered";
fp: string;
mode: string;
entry?: string;
htmlBytes?: number;
propsBytes?: number;
ms?: number;
} | {
domain: "server";
name: "server.capability.minted";
id: string;
ttl?: number;
} | {
domain: "server";
name: "server.delta.skip";
fp: string;
} | {
domain: "server";
name: "server.seed.injected";
kind: "page" | "remote";
bytes: number;
} | {
domain: "server";
name: "server.postrender";
op: string;
url?: string;
reason?: string;
bytes?: number;
};WireEventInput
type
type WireEventInput = {
domain: "wire";
name: "wire.props";
entry?: string;
bytes: number;
} | {
domain: "wire";
name: "wire.context";
bytes: number;
} | {
domain: "wire";
name: "wire.frame.batch";
count: number;
bytes?: number;
} | {
domain: "wire";
name: "wire.known.sent";
count: number;
bytes: number;
};