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

@earendil-works/pi-server

v0.87.1

Published

experimental server package for pi

Readme

@earendil-works/pi-server

Experimental local server for the new durable Session and Agent Harness interfaces.

The current slice supports server- and Session-scoped facet-service routing and multi-presentation attachment. RoutedServerServiceHost.attachClient() creates one connection-scoped server service endpoint with narrow attachment-management capabilities. RoutedSessionHandle.attachClient() returns a presentation-scoped Session capability. Its invokeService() forwards an opaque service/member envelope to the selected Session endpoint; the server validates the attachment route but does not load the facet contract.

  • server service calls and subscriptions route opaquely through the connection's RoutedServerServiceAttachment;
  • the application-owned SessionDirectory projects the private catalog into replicated presentation-safe state;
  • the application-owned SessionManagement creates, removes, attaches, and detaches Sessions without exposing route IDs in business results;
  • attachment changes are published out of band after the router installs or clears the live route;
  • Session service calls route through invokeService without server-side business-payload decoding;
  • service subscription updates remain scoped to the requesting attachment;
  • application observations such as transcripts route as ordinary service state without server-owned business schemas.

A Session may have multiple presentation attachments. Repeating attach from one connection is idempotent; every successful attachment has a server-generated attachmentId delivered only as routing control data. Session requests carry { serverId, sessionId, attachmentId }, and the server rejects stale or mismatched routes. Losing a connection rejects its local responses but releases its attachment only after admitted service calls settle. The host decides when zero presentation demand and worker-local Harness activity permit worker retirement. Server shutdown closes every routed Session handle, releasing its worker and Session writer ownership.

import { randomUUID } from "node:crypto";
import { MemorySessionRepo, type Session } from "@earendil-works/pi-agent-core";
import {
  type RoutedServerServiceHost,
  type RoutedSessionHandle,
  type ServerHost,
  SessionAmbiguousError,
  SessionNotFoundError,
} from "@earendil-works/pi-server";
import { createUnixServer, getUnixSocketPath } from "@earendil-works/pi-server/unix";

async function startServer(
  serverServices: RoutedServerServiceHost,
  openRoutedSession: (session: Session) => Promise<RoutedSessionHandle>,
) {
  const sessions = new MemorySessionRepo();
  const host: ServerHost = {
    serverServices,
    async resolveSession(sessionId, context) {
      const matches = (await sessions.list(undefined, context))
        .filter((metadata) => metadata.id === sessionId);
      if (matches.length === 0) {
        throw new SessionNotFoundError(`Unknown session: ${sessionId}`);
      }
      if (matches.length > 1) throw new SessionAmbiguousError();
      return matches[0];
    },
    async openSession(metadata, context) {
      const session = await sessions.open(metadata, context);
      try {
        return await openRoutedSession(session);
      } catch (error) {
        try {
          await session.close(context);
        } catch (cleanupError) {
          throw new AggregateError(
            [error, cleanupError],
            "Harness creation and Session cleanup failed",
          );
        }
        throw error;
      }
    },
  };

  const serverId = randomUUID();
  const server = createUnixServer(host, {
    serverId,
    path: getUnixSocketPath(serverId, "/run/user/1000/pi"),
  });
  await server.start();
  return server;
}

Applications supply a required server service host, a bounded Session resolver, and a routed Session factory. Session discovery and management are application-owned services; the protocol server only asks the resolver for metadata when routing an attachment. The host owns acquiring the worker-local Session and Harness. Failures are cleaned up in that worker. Neither an open JavaScript Session nor a Harness crosses the process boundary.

serverId is a logical identity supplied by the launcher, not a socket address. The Unix preset requires an explicit physical path; getUnixSocketPath() derives one from a caller-selected directory. Choose a short, private runtime directory rather than deriving the route from an unbounded home-directory path. A long-lived launcher can reuse the same ID and path when replacing a server process.

Server composes transports through ServerListener; peer authentication remains application policy and is not implemented by the experimental Unix transport. The Unix submodule provides createUnixListener() and createUnixServer(). Low-level routed-envelope validation, CBOR, and framing come from @earendil-works/pi-protocol; Chord owns service-control parsing, error codes, snapshots and updates, and each subscription's replicated-state encoder.

Server and worker lifecycle is managed outside the public Pi protocol. The replaceable application server converts connection attachments into private demand updates; the worker combines generation-tagged demand with authoritative Harness activity. The experimental coordinator only supplies stable routing and reports generic server-generation connection changes.