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

@input/pen-transport

v0.2.11

Published

Transports for Pen: in-process direct and SSE

Downloads

3,257

Readme

@input/pen-transport

@input/pen-transport ships Pen's two reference transports as subpath entries: @input/pen-transport/direct (in-process, for tests and demos) and @input/pen-transport/sse (Server-Sent Events, a development-oriented reference for the streaming protocol). Neither is a production collaboration or sync backend, and this package does not own endpoint routing, auth, persistence, or deployment — those stay host seams.

The root entry re-exports both variants; the subpaths are the documented way to name the one you use.

Install

pnpm add @input/pen @input/pen-transport

./direct

Grade: development-only. Support status: experimental. This is a single-process, in-process only, no-network transport for tests and demos. It never opens a socket and cannot reach a runtime in another process. It is non-resumable: there is no stream history and nothing to reconnect. Do not ship it.

A host can rely on directTransport({ toolRuntime, editor }).stream(request) running toolCalls in-process against the construction-time runtime and editor and yielding PenStreamParts until done. A host cannot rely on a socket, resume, reconnect, or onConnectionChange.

import { createEditor } from "@input/pen";
import { getAIToolRuntime } from "@input/pen-ai/tools";
import { directTransport } from "@input/pen-transport/direct";

const editor = createEditor();
const toolRuntime = getAIToolRuntime(editor);

if (!toolRuntime) {
  throw new Error("AI tools are unavailable.");
}

const transport = directTransport({
  toolRuntime,
  editor,
  onError(error) {
    console.error(error);
  },
});

A live Editor is passed at construction. It is not a field on PenStreamRequest — that type is the wire shape, and direct does not smuggle a handle through it.

Mutating toolCalls are default-deny. Set allowedMutatingTools to grant specific names.

Options — directTransport

| Option | Default | Effect | | ---------------------- | ------- | ------------------------------------------------ | | toolRuntime | none | Required. In-process tool execution | | editor | unset | In-process editor handed to ToolContext.editor | | allowedMutatingTools | [] | Mutating tools the request may run. Default deny | | onError | unset | Called with tool-execution errors |

./sse

Grade: reference. Support status: reference. This transport is single-process, non-resumable, and development-oriented. It illustrates Pen's SSE streaming protocol. Do not use it as a production collaboration or sync backend.

A host can rely on sseTransport({ url }).stream(request) POSTing a PenStreamRequest and yielding PenStreamParts from createSSEHandler's event-stream, including in-process toolCalls when a toolRuntime is wired. A host cannot rely on resume, reconnect, multi-process deployment, persistence, or request authentication — those stay host seams.

Resume is absent, not stubbed. createSSEHandler answers GET — with or without Last-Event-ID — with 405 Method Not Allowed and Allow: POST. It does not return 501. There is no replayable log, no retention bound, and no X-Replay-Supported header. Event id fields on the wire are not a replay contract. The client POSTs a fresh stream and does not send Last-Event-ID. A dropped connection is a full restart, not a continuation. This package does not resync document state. The handler is in-process memory only; it does not survive a process restart or a second instance.

Server example

import { createEditor } from "@input/pen";
import { getAIToolRuntime } from "@input/pen-ai/tools";
import { createSSEHandler } from "@input/pen-transport/sse";

const editor = createEditor();
const toolRuntime = getAIToolRuntime(editor);

if (!toolRuntime) {
  throw new Error("AI tools are unavailable.");
}

const handler = createSSEHandler({
  toolRuntime,
  editor,
  onError(error) {
    console.error(error);
  },
});

A live Editor is passed at construction. PenStreamRequest is the wire body and has no editor field. The handler rejects a body that is not a PenStreamRequest — including a top-level or nested editor, a wrong-shaped field, a prototype key, or an oversized payload — with 400 before any tool runs.

Mutating toolCalls are default-deny. Set allowedMutatingTools to grant specific names; an un-allowlisted mutating call emits tool-error and does not run the handler or apply.

Client example

import { sseTransport } from "@input/pen-transport/sse";

const transport = sseTransport({
  url: "https://example.com/api/stream",
  pingTimeout: 30_000,
});

Integration notes

  • This package handles streaming transport concerns, not editor authority or product UI.
  • The host application still owns endpoint routing, auth, headers, and server deployment. Auth is a host seam; this package does not verify requests.
  • A dropped stream is not retried or resumed by this package. If the host retries, that is a new POST, not a continuation.
  • createSSEHandler() can execute Pen tool-runtime requests and stream PenStreamPart events back to the client.

Options — sseTransport

| Option | Default | Effect | | ------------- | -------- | ---------------------------- | | url | required | POST endpoint | | headers | unset | Extra request headers | | pingTimeout | 30_000 | Idle timeout in milliseconds | | signal | unset | Abort the client stream |

Options — createSSEHandler

| Option | Default | Effect | | ---------------------- | -------- | ------------------------------------------------ | | toolRuntime | unset | In-process tool execution | | editor | unset | In-process editor for ToolContext | | allowedMutatingTools | [] | Mutating tools the request may run. Default deny | | onRequest | unset | Called with each PenStreamRequest | | onError | unset | Called with handler errors | | pingInterval | 15_000 | Server ping interval in milliseconds |

Documentation

The docs site (the @input/pen-docs package) covers this area on the AI features page (#/ai).

The public signatures of record are in api-report.md next to this package's source in the Pen repository. The docs site does not host a generated browsable reference.

License

MIT © Input B.V. See LICENSE.md.