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

@acpjs/core

v0.8.0

Published

acpjs AcpHost: agent process lifecycle, ACP connection, event normalization/numbering, fs/terminal defaults, permission routing, restart and StorageAdapter scheduling.

Readme

@acpjs/core

Node AcpHost runtime. Spawns ACP agent subprocesses over the official SDK, normalizes protocol notifications into numbered @acpjs/protocol events, replays the log for late subscribers, routes permissions, provides default fs, opt-in terminal handling, crash recovery, and StorageAdapter scheduling.

Install

pnpm add @acpjs/core

ESM-only, node >= 24. Runtime deps: @acpjs/protocol, @agentclientprotocol/sdk, zod.

Usage

import { createAcpHost } from '@acpjs/core'

const host = createAcpHost({ restart: 'on-crash' })

const agent = await host.spawnAgent({
  id: 'my-agent',
  command: 'npx',
  args: ['some-acp-agent'],
})
const { sessionId } = await host.createSession(agent.agentId, {
  cwd: process.cwd(),
  mcpServers: [],
  additionalDirectories: [],
})

const unsubscribe = host.subscribe(sessionId, 0, (event) =>
  console.log(event.seq, event.type),
)
const result = await host.prompt(sessionId, [{ type: 'text', text: 'hello' }])

unsubscribe()
await host.closeSession(sessionId)
await host.dispose()

Exports

  • createAcpHost(options?): AcpHost (the AcpHost class is also exported)
  • createHostEndpoint(host): EnvelopeEndpoint — wraps a host as the HostClientTransport endpoint for @acpjs/client.
  • AcpError — carries a host-boundary code from ACPJS_ERROR_CODES (acpjs/*).
  • resolveHostOptions(options), resolveAgentDefinition(definition) — config pipeline; validation failures throw AcpError (acpjs/config-invalid); resolved products are frozen.
  • deriveClientCapabilities(fs, terminal) — reports only the methods a handler implements.
  • normalizeSessionUpdate(update): NormalizedUpdate — maps the 13 SessionUpdate variants to event type/payload/extensions; unmodeled → unrecognized-update.
  • createMemoryStorage(), createJsonlStorage(file) — built-in StorageAdapters.
  • createDefaultFsHandler(), createDefaultTerminalHandler().
  • Types: HostOptions, ResolvedHostOptions, AgentDefinition, ResolvedAgentDefinition, FsHandler, TerminalHandler, RestartBackoff, AgentSnapshot, SessionSnapshot, CreateOrLoadSessionParams, ResumeSessionParams, CreateSessionResult, SessionConfigValue, PromptResult, EventSubscriber, StorageAdapter, SessionMeta, NormalizedUpdate.

AcpHost methods

  • Agents: spawnAgent(definition), getAgent(agentId), getAgents(), disposeAgent(agentId)
  • Auth: authenticate(agentId, methodId) sends the authenticate RPC; logout(agentId) gated on auth.logout capability (else acpjs/capability-unsupported). Sends RPC only — does not pick method, store credentials, or track login state.
  • Sessions: createSession(agentId, { cwd, mcpServers, additionalDirectories }), loadSession(...), resumeSession(...), listSessions(agentId, { cursor?, cwd? }), deleteSession(agentId, sessionId), prompt(sessionId, ContentBlock[]), cancel(sessionId), closeSession(sessionId), setMode(sessionId, modeId), setConfigOption(sessionId, configId, value), getSession(sessionId), getSessions()
  • Events: subscribe(sessionId | undefined, fromSeq, callback) — pass undefined for the host stream (agent/session/permission projections + diagnostics).
  • Permissions: respondPermission(requestId, outcome)
  • Recovery: restoreSessions() — rebuilds disconnected sessions from storage.
  • dispose(), disposeAgent(agentId) (idempotent; sessions → disconnected, agent removed from registry, emits agent-removed).

HostOptions

| Field | Default | Notes | | ---------------- | ---------------------------------------------- | -------------------------------------------------------------------------- | | restart | 'never' | 'on-crash' restarts only on a crashed exit. | | restartLimit | 3 | Max consecutive restarts; ready resets the counter. | | restartBackoff | { initialMs: 1000, factor: 2, maxMs: 30000 } | Exponential backoff. | | storage | in-memory | StorageAdapter. | | fs | built-in Node fs | Replaced wholesale when injected; drives the initialize capability report. | | terminal | disabled | Requires a complete handler with cleanupSession. | | killTimeoutMs | 5000 | dispose graceful-shutdown timeout; SIGKILL after. |

Frozen once constructed; rebuild the host to change it.

Snapshots

  • AgentSnapshot: { agentId, status, restartCount, reason?, exit?, capabilities?, authMethods? }. authMethods = advertised methods from initialize (read this to pick a methodId for authenticate). capabilities.auth.logout gates logout.
  • SessionSnapshot: { sessionId, status, agentId?, cwd, mcpServers?, additionalDirectories, agentDefinitionId?, title?, updatedAt? }.

Host stream diagnostics (code values)

agent/spawn, agent/spawn-failed, agent/initialized, agent/initialize-failed, agent/exit, agent/process-error, agent/stderr, agent/restart-scheduled, agent/restart-suppressed, agent/restart-exhausted, agent/kill, session/recovery-skipped, session/load-failed, storage/write-failed, event/unserializable, subscriber/error. Diagnostics never participate in SessionState reduction. agent/spawn records env key names only, never values.

Key semantics

  • agentId / requestId: agent-<n> / perm-<n>, monotonic per host lifetime, never reused.
  • cwd: AgentDefinition.cwd defaults to host process cwd; absolutized via path.resolve.
  • prompt protocol errors: prompt rejects on agent JSON-RPC errors (does not fabricate a StopReason); envelope callers receive acpjs/agent-error with the original error in data.
  • normalization key-omission: null optional fields are omitted, except session_info_update title/updatedAt (clear) and tool_call(_update) rawInput/rawOutput (passthrough). Top-level _metaextensions._meta; other unknown fields → extensions.<key>.
  • capability gating: session/list|resume check sessionCapabilities.<x> != null; loadSession checks the top-level boolean; set_mode/set_config_option check whether modes/configOptions were ever seen. Local close/delete always available; remote close/delete is best-effort and resolves on the local tombstone (does not wait for ACP ACK).
  • load/resume staging: unknown load/resume is invisible until the RPC succeeds. load buffers replayed updates, then emits session-reset + replay + config + active; resume rejects replayed history.
  • restart pre-ready failures: during a restart cycle, spawn/initialize failures keep consuming restart budget; the first (non-cyclic) failure is not retried.
  • storage: event writes are queued; failures emit storage/write-failed (not retried). Close/delete tombstones are strict commits — if unwritable, the API rejects. restoreSessions skips closed/deleted and non-clone-safe events; restored sessions are disconnected.
  • terminal ownership: the host records the owning sessionId per terminalId and rejects cross-session terminal ops with acpjs/invalid-params.
  • protocol version: initialize response protocolVersion !== PROTOCOL_VERSION → process killed, judged initialize-failed (no downgrade).
  • unserializable payloads: events failing structured clone are rejected → event/unserializable diagnostic.