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

@crow-agent/server

v0.2.0

Published

Server host for Crow sessions: listeners, routing, and transports.

Readme

@crow-agent/server

Local server that hosts durable Sessions and exposes the Agent Harness over a byte transport.

A Server instance accepts connections, runs the hello handshake, and then routes service calls at two levels: calls aimed at the server itself, and calls aimed at one attached Session. Routing stays opaque — the server never decodes application payloads. It only checks that the { serverId, sessionId, attachmentId } route on each request is live, then forwards the envelope.

What the host provides

Everything session-shaped is application code. The server asks a ServerHost for three things:

  • serverServices — the connection-scoped service endpoint. Its attachClient() hands each connection a narrow attachment-management surface (RoutedServerServiceAttachment).
  • resolveSession(sessionId, context) — map an id to metadata, or throw SessionNotFoundError / SessionAmbiguousError.
  • openSession(metadata, context) — acquire the worker-local Session and wrap it in a RoutedSessionHandle. The handle's attachClient() returns a presentation-scoped capability whose invokeService() forwards an opaque service/member envelope at the chosen Session endpoint.

Application-owned services (SessionDirectory, SessionManagement) project the private session catalog into replicated, presentation-safe state and create, remove, attach, and detach Sessions without leaking route ids into business results. Subscription snapshots and updates stay scoped to the attachment that requested them; attachment changes are published out of band once the router installs or clears the live route.

Attachments

One Session can serve several presentation attachments at once. Repeating attach from a single connection is idempotent. Each successful attachment receives a server-generated attachmentId that only travels in routing control data. Stale or mismatched routes are rejected. When a connection drops, its pending responses fail, but its attachment is released only after admitted service calls settle — the host decides when zero presentation demand plus quiet worker-local Harness activity allow worker retirement. server.close() shuts every routed Session handle down, relinquishing worker and Session-writer ownership.

Example

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

const catalog = new MemorySessionRepo();

async function lookupSession(sessionId: string, context: Context) {
  const candidates = await catalog.list(undefined, context);
  const match = candidates.filter((entry) => entry.id === sessionId);
  if (match.length > 1) throw new SessionAmbiguousError();
  const found = match[0];
  if (found === undefined) throw new SessionNotFoundError(`Unknown session: ${sessionId}`);
  return found;
}

async function launch(
  serverServices: RoutedServerServiceHost,
  openRoutedSession: (session: Session) => Promise<RoutedSessionHandle>,
) {
  const host: ServerHost = {
    serverServices,
    resolveSession: lookupSession,
    openSession: async (metadata, context) => {
      const session = await catalog.open(metadata, context);
      return openRoutedSession(session);
    },
  };

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

The launcher picks serverId as a logical identity — it is not a socket address. getUnixSocketPath() derives a filesystem path from a directory you choose; prefer a short private runtime directory. A long-lived launcher may reuse the same id and path when replacing the server process.

Server composes transports through the ServerListener interface; peer authentication is application policy and is not provided by the Unix transport. The Unix submodule offers createUnixListener() and createUnixServer(). Low-level envelope validation, CBOR, and framing come from @crow-agent/protocol; Chord handles service-control parsing, error codes, snapshots and updates, and each subscription's replicated-state encoder.

Server and worker lifecycle live outside the public Crow protocol. The replaceable application server turns connection attachments into private demand updates; the worker merges generation-tagged demand with authoritative Harness activity. The coordinator supplies stable routing and reports generic server-generation connection changes.