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

@cuylabs/agent-server

v6.2.2

Published

Transport-neutral local server for @cuylabs/agent-core sessions, turns, and streamed events

Readme

@cuylabs/agent-server

Local session-and-turn host for @cuylabs/agent-core, with in-process, stdio, and websocket clients.

See docs/README.md for the modular package docs.

This package adds an interactive host layer above the existing framework packages:

  • @cuylabs/agent-core still owns agent execution, tools, sessions, and plugins
  • @cuylabs/agent-runtime still owns background scheduling/orchestration
  • @cuylabs/agent-runtime-dapr still owns Dapr durability and workflow hosting
  • @cuylabs/agent-server owns local multi-session turn execution, live event fanout, and client-facing session APIs

Boundary

Use @cuylabs/agent-server when you want a long-lived local process to:

  • manage multiple persisted sessions
  • start and interrupt turns independently of a single UI client
  • stream AgentEvents to multiple subscribers
  • let clients disconnect and reconnect without losing server-owned turn state

This package is intentionally not:

  • a replacement for agent-runtime or agent-runtime-dapr
  • a new plugin system
  • a renderer/UI extension layer

The current implementation ships three access patterns:

  • in-process client/server for the CLI and tests
  • stdio transport for one external client process
  • websocket transport for reconnectable multi-client use

Capability contract

@cuylabs/agent-server now exposes an explicit capability snapshot through getCapabilities().

That contract is split into:

  • protocol
    • transport kind, reconnect semantics, multi-client support
  • sessions
    • persistence and session management features such as branching
  • turns
    • streaming, waiting, interruption, steering, follow-up queuing, follow-up management, and concurrency rules
  • interactive
    • approval request and human input request routing
  • runtime
    • whether execution is local, remote, or hybrid
    • whether orchestration is direct, agent-runtime, or agent-runtime-dapr
    • whether Dapr-backed workflow delegation is available
  • agent
    • workspace summary snapshots for startup and welcome surfaces
    • model inspection and model switching
    • tool, skill, and sub-agent profile inspection
    • session runtime status snapshots for model/session/context state
    • context compaction plus turn undo / diff helpers
  • plugins
    • the server-side plugin contract: headless behavior, command metadata, no client extension execution

This keeps the server/client boundary inspectable without coupling clients to implementation details.

What this enables

@cuylabs/agent-server is useful when one agent session should outlive one UI process.

It gives us a place to:

  • keep a turn running even if one TUI client disconnects
  • let multiple clients observe the same live session
  • expose session read/list/branch APIs without booting a fresh UI-owned loop
  • share one backend between TUI, automation, and future web or chat clients
  • keep plugin and tool execution on the server side while clients focus on rendering and input
  • expose steering and approval-request flows through a stable protocol instead of tying them to one UI

Core model

This package uses the framework's own vocabulary instead of copying another tool's protocol:

  • session — the persisted tree-backed conversation in agent-core storage
  • turn — one user input plus the streamed agent work that follows
  • event — the raw AgentEvent emitted during a turn

That matches the current framework better than introducing a second conversation model.

Quick start

import { createAgent } from "@cuylabs/agent-core";
import {
  InProcessAgentServer,
  InProcessAgentServerClient,
  createAgentServerAdapter,
} from "@cuylabs/agent-server";

const agent = createAgent({
  model,
  cwd: process.cwd(),
  systemPrompt: "You are a helpful coding agent.",
});

const server = new InProcessAgentServer(createAgentServerAdapter(agent));
const client = new InProcessAgentServerClient(server);

const session = await client.createSession({ title: "Refactor auth flow" });
const turn = await client.startTurn(session.id, "Find the auth bug and fix it.");

const off = client.subscribe((notification) => {
  if (notification.type === "turn/event") {
    console.log(notification.event.type);
  }
}, { turnId: turn.id });

const completed = await client.waitForTurn(turn.id);
off();

console.log(client.getCapabilities().runtime);
console.log(completed.status, completed.output);

Transport examples

WebSocket server

import {
  InProcessAgentServer,
  createAgentServerAdapter,
  startAgentServerWebSocketServer,
} from "@cuylabs/agent-server";

const server = new InProcessAgentServer(createAgentServerAdapter(agent));
const transport = startAgentServerWebSocketServer(server, {
  host: "127.0.0.1",
  port: 4647,
});

await transport.ready;
console.error(`listening on ${transport.address()}`);

Remote stdio client

import { connectStdioAgentServerClient } from "@cuylabs/agent-server";

const client = await connectStdioAgentServerClient({
  command: process.execPath,
  args: ["./bin/cuylabs.js", "server", "--transport", "stdio"],
});

Human Input

Direct agent-core human input now plugs into agent-server automatically when the agent is configured with both:

  • humanInput on createAgent(...)
  • at least one human-input tool such as createHumanInputTool()

Example:

import {
  createAgent,
  createHumanInputTool,
} from "@cuylabs/agent-core";

const agent = createAgent({
  model,
  humanInput: {},
  tools: [createHumanInputTool()],
});

const adapter = createAgentServerAdapter(agent);

In that setup:

  • getCapabilities().interactive.humanRequests becomes true
  • human-input-request and human-input-resolved flow through turn events
  • respondToInputRequest(..., { kind: "human", response }) resolves the pending controller request

This keeps direct server mode aligned with the durable Dapr semantics:

  • request state is authoritative
  • events are live notifications
  • explicit response APIs resume execution

Why this exists

Without an app server, the CLI process usually owns the live turn:

  • UI starts the turn
  • UI consumes agent.chat(...)
  • UI dies, the live interaction dies

With an app server:

  • server starts the turn
  • server owns session and turn state
  • server fans out updates to subscribers
  • clients can reconnect or multiple clients can observe the same session

That is the key shift: the live agent loop stops belonging to one terminal window.

Plugins

This package does not require a plugin API rewrite.

agent-core plugins already contribute headless behavior:

  • tools
  • middleware
  • host commands
  • prompt sections
  • lifecycle hooks

That logic stays on the server side. The app server executes the same agent, so plugin business logic continues to run where it already belongs.

Server-backed hosts can now also discover and execute plugin commands through the same agent-server contract:

  • listPluginCommands()
  • executePluginCommand(name, args)

That keeps plugin command routing attached to the hosted agent instead of duplicating command execution logic in every client.

If you later add client-specific UI extensions, that should be a separate client-layer extension surface. Do not mix TUI/web UI contributions into the server plugin contract.

Relationship to Dapr

agent-runtime-dapr and agent-server solve different problems:

  • Dapr gives durable workflows, checkpoints, state stores, and jobs
  • agent-server gives session/turn APIs, subscriptions, and live client semantics

They compose well:

  • agent-server can start turns locally
  • some turns can be delegated to a durable runtime later while still presenting the same client-facing capability contract
  • the client-facing protocol stays the same

Current status

The current package provides:

  • in-process session listing, reading, creation, deletion, and branching
  • background turn execution with startTurn(...)
  • per-turn interruption, steering, and follow-up queuing
  • follow-up management: list, get, resolve/discard queued follow-ups
  • approval request routing over server notifications
  • human input request routing over server notifications
  • multi-subscriber event fanout
  • waitForTurn(...) and turn inspection
  • capability-gated agent affordances such as runtime status, model switching, tool inventory, skill inspection, sub-agent profiles, compact, undo, and diff
  • workspace summary snapshots that let clients render startup state from the server instead of stitching local counters together
  • stdio and websocket transports for external clients

The next layer is not “add a server.” The server already exists. The next layer is broader client adoption and richer request/response flows on top of the same ownership model.