npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@telorun/debug-ui

v0.3.0

Published

Browser-safe debug event UI for Telo: wire types, filtering, SSE client, and React components for watching a running app's event stream.

Readme

@telorun/debug-ui

Browser-safe building blocks for watching a running Telo app's debug stream: filter logic, an SSE client, a graph model, and React components (a Logs / Events / Graph tab split) — plus a standalone single-page app, built both multi-file (app-dist/) and as one self-contained file (app-single/index.html).

The Graph view has two modes. Its left rail lists every traced invocation; selecting one scopes the canvas to just the resources that took part in that call, wired by the real parent→child call edges (reconstructed from event metadata.invocationId / parentInvocationId), each node showing its inputs → outputs. With nothing selected, the canvas shows the live resource topology: a node is born gray on Created, brightens on Initialized, and pulses on each invocation. The folds from frames to nodes/edges are the pure, testable deriveGraph (topology) and deriveInvocations + traceSubgraph (traces); the component adds @xyflow/react + dagre layout on top.

Traces require the producer to be tracing — the CLI turns it on automatically under telo run --inspect (or --debug).

The wire format itself lives in @telorun/debug-wire; this package re-exports its types. A stream carries two frame kinds: kind: "event" (kernel events) and kind: "log" (stdout/stderr lines).

This package is a consumer: it parses events, it never produces them. It has no Node-only dependency (no fs/http, not @telorun/runner-core) so it runs in any browser and in the editor webview.

Why it's shaped this way

The Telo kernel is polyglot — Node today, Rust/Go later. The thing that produces debug events (taps the kernel, serializes values, serves them) lives inside each runtime and is reimplemented per language. What's shared across runtimes is the wire format, not code. Every consumer (this package, the editor) codes against that contract; the Node producer lives in the CLI.

wire format (@telorun/debug-wire)              ← the cross-runtime contract
  produced by → a kernel runtime's debug server (Node: the telo CLI)
  consumed by → the standalone app (served by the producer) + the editor panel

Wire format

Each frame is one JSON object, delivered one-per-line over SSE and JSONL. Schema and types: @telorun/debug-wire. An event frame:

{ "kind": "event", "timestamp": "2026-06-13T07:00:00.000Z", "event": "Server.Listening",
  "payload": { "port": 5599, "mounts": [{ "path": "/v1", "mount": { "kind": "Http.Api", "name": "Api" } }] } }

A log frame (one stdout/stderr line):

{ "kind": "log", "timestamp": "2026-06-13T07:00:00.000Z", "stream": "stdout", "line": "listening on :5599" }

Producers reduce event payload values to wire-safe forms before sending:

| Value | Encodes as | |---|---| | byte buffer (Uint8Array/Buffer, any file kind) | { "$blob": "blobs/<id>", "mediaType", "byteLength" } — a pointer; bytes are offloaded to the producer's blob store, fetched on demand. The key it sits under is preserved. | | resolved !ref (live resource instance) | { "kind", "name" } | | other live / unrepresentable value (controller, stream, client, function, bigint) | "[Marker]" (e.g. "[Stream]", "[Kernel]") | | reference cycle | "[Circular]" | | anything else | plain JSON |

A non-TS producer (Rust/Go) conforms to the same table.

Blobs (binary payloads)

The bytes never enter the log. A producer offloads each buffer to a content-addressed store (so identical buffers dedupe) and emits a $blob pointer — a path relative to the producer origin. The consumer resolves it against the debug-server URL and fetches GET /blobs/<id> (which sets the real Content-Type). mediaType is sniffed from magic bytes, falling back to application/octet-stream. The UI renders image/* inline and other types as a download link; byteLength + sibling width/height (if present) form the caption. An evicted blob 404s — the log keeps the pointer + metadata, so you still see what it was.

Endpoints (served by a producer's debug server)

  • GET / — the standalone UI (the self-contained app-single/index.html bytes).
  • GET /events — SSE; on connect, the producer flushes its replay buffer, then streams live events.
  • GET /events.jsonl — the full event log, for download.
  • GET /blobs/:id — a binary payload offloaded from an event (see Blobs below).
  • GET /json/version — discovery handshake: { protocol, protocolVersion, url, events, eventsLog, blobs, appEndpoints }, so a consumer can confirm the wire format before connecting. appEndpoints is the running app's exposed addresses ({ host, port, protocol, url? }[]); a blank host means the producer couldn't know which hostname the viewer used — the UI fills it from the page origin.

The Telo CLI exposes this server with telo run <manifest> --inspect[=[host:]port] (loopback 127.0.0.1:9230 by default). It serves the UI same-origin, fetching the app-single bundle on demand and caching it under the .telo cache root — the CLI bundles no UI bytes (see Scripts). --debug is the separate, network-free path: it only writes the .telo.debug.jsonl event log.

Surface

// Logic — framework-agnostic, browser-safe
import { connectDebugStream, matchesFilter, distinctSuffixes, isWireRef, eventSuffix,
         isLogFrame, endpointHref, deriveGraph, type DebugFrame, type EventFilter,
         type GraphState, type AppEndpoint } from "@telorun/debug-ui";

// React components — for the standalone app and the editor panel
import { DebugWatcher, DebugPanel } from "@telorun/debug-ui/components";
// Standalone (owns its SSE + buffer; fetches `appEndpoints` from the handshake);
// theme defaults to "system":
//   <DebugWatcher url="http://localhost:9230/events" theme="system" />
// Controlled (editor feeds frames it sourced itself, injects its own terminal as
// the Logs tab, passes its own resolved theme + the app's run endpoints):
//   <DebugPanel frames={frames} status={…} paused={…} onTogglePause={…} onClear={…}
//               resolveBlobUrl={…} logsSlot={<Terminal/>} endpoints={…} theme="dark" />

Scripts

  • pnpm --filter @telorun/debug-ui build — builds both the multi-file standalone app (app-dist/) and the self-contained single-file app (app-single/index.html). The single file is what the CLI fetches on demand (hosted on npm, delivered via jsDelivr) and serves; in the monorepo the CLI resolves it directly from this package, so a local build is testable without any network.
  • pnpm --filter @telorun/debug-ui test — unit tests (filter + graph logic).