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

@ziro-agent/checkpoint-redis

v0.5.0

Published

Redis Checkpointer adapter for ZiroAgent SDK — durable agent state with sorted-set indexed snapshots (RFC 0006).

Readme

@ziro-agent/checkpoint-redis

Redis adapter for the ZiroAgent SDK Checkpointer interface (RFC 0006).

pnpm add @ziro-agent/checkpoint-redis ioredis
# or
pnpm add @ziro-agent/checkpoint-redis redis

Quick start

with ioredis

import { createAgent } from '@ziro-agent/agent';
import { fromIoRedis, RedisCheckpointer } from '@ziro-agent/checkpoint-redis';
import IORedis from 'ioredis';

const redis = new IORedis(process.env.REDIS_URL!);

const checkpointer = new RedisCheckpointer({
  client: fromIoRedis(redis),
  ttlSeconds: 7 * 24 * 3600,        // GC abandoned threads after 7 days
  maxCheckpointsPerThread: 50,      // keep last 50 snapshots per thread
});

const agent = createAgent({
  model,
  checkpointer,
  defaultThreadId: 'user:42',
});

with redis (node-redis v4+)

import { createClient } from 'redis';
import { fromNodeRedis, RedisCheckpointer } from '@ziro-agent/checkpoint-redis';

const client = createClient({ url: process.env.REDIS_URL });
await client.connect();

const checkpointer = new RedisCheckpointer({
  client: fromNodeRedis(client),
});

bring-your-own client

The adapter only needs a single method. If you're using a sandboxed client (Cloudflare Workers, Edge, etc), implement the RedisLike surface yourself:

const checkpointer = new RedisCheckpointer({
  client: {
    async command(args) {
      return myCustomTransport(args);
    },
  },
});

Resumable streamText event log

Use RedisResumableStreamEventStore with streamText({ resumable: true, streamEventStore }) from @ziro-agent/core so cached ModelStreamPart events can be replayed after a disconnect (same semantics as the in-memory store, backed by Redis with optional TTL). See the resumable streamText cookbook.

import { streamText } from '@ziro-agent/core';
import IORedis from 'ioredis';
import { fromIoRedis, RedisResumableStreamEventStore } from '@ziro-agent/checkpoint-redis';

const redis = new IORedis(process.env.REDIS_URL!);
const streamEventStore = new RedisResumableStreamEventStore({
  client: fromIoRedis(redis),
  ttlSeconds: 3600,
  maxEventsPerStream: 10_000,
  maxBytesPerStream: 8 * 1024 * 1024, // 8 MiB
});

const result = await streamText({
  model,
  prompt: 'Hello',
  resumable: true,
  streamEventStore,
});

Default stream key prefix is ziro:st (separate from the checkpointer’s ziro:cp). TTL is still recommended as the primary long-session guardrail; event/byte caps add deterministic per-stream limits aligned with the in-memory store.

RedisResumableStreamEventStore also exposes optional continue lock hooks used by streamText({ continueUpstream: true }) to reduce multi-writer races across processes. Configure lock TTL with continueLockSeconds (default: 30).

RedisResumableStreamEventStore key layout (default ziro:st)

| Key | Type | Purpose | | --- | ---- | -------- | | ziro:st:reg:<resumeKey> | STRING | stream registered ("1") | | ziro:st:log:<resumeKey> | LIST | one JSON line per ModelStreamPart | | ziro:st:bytes:<resumeKey> | STRING | running byte total (accounting) | | ziro:st:ts:<resumeKey> | STRING | last append time (ms), for getSessionMeta | | ziro:st:comp:<resumeKey> | STRING | set to "1" when a terminal part (finish / error) is stored | | ziro:st:lock:<resumeKey> | STRING | best-effort continue-upstream writer lock token (SET NX EX) |

Key layout

With the default keyPrefix = "ziro:cp":

| Key | Type | Purpose | | -------------------------------- | ------ | ----------------------------------------- | | ziro:cp:idx:<threadId> | ZSET | id → ms timestamp (newest = highest rank) | | ziro:cp:snap:<threadId>:<id> | STRING | JSON-encoded AgentSnapshot |

Pick a different keyPrefix to isolate environments or share a Redis between SDK installations.

Concurrency model

  • IDs are UUID v7 generated client-side, so two concurrent put() calls to the same threadId never collide on the snapshot key.
  • The trim pass that enforces maxCheckpointsPerThread runs as separate Redis commands AFTER the new snapshot is committed. A crash mid-trim leaves at most cap+1 checkpoints — never fewer than cap. Postgres adapter does this atomically via a CTE; we accept the trade-off for Redis.
  • TTL is set per-key on put, both for the snapshot payload and for the index ZSET. Long-abandoned threads GC themselves without a cleanup job.

When to pick this vs @ziro-agent/checkpoint-postgres

| Need | Choose Redis | Choose Postgres | | ------------------------------------------ | ------------------------------------- | ---------------------------------------- | | Sub-millisecond reads | ✅ | ❌ (network + parse overhead dominates) | | You already run Redis | ✅ | — | | You already run Postgres | — | ✅ | | Snapshot size > 1 MiB regularly | ⚠️ (Redis values can be large but eviction policies bite) | ✅ (JSONB scales) | | Auto-eviction of abandoned threads | ✅ (TTL native) | ⚠️ (run a periodic DELETE job) | | Atomic trim-on-cap | ❌ (best effort) | ✅ (CTE in put) | | Hot-cold tiering, point-in-time queries | ❌ | ✅ |

If both are options and you want a single source of truth, run Postgres in production and Redis as a hot cache only after measuring the latency gap matters.