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

@generative-a11y/ai-sdk

v0.1.2

Published

Vercel AI SDK accessibility adapter for streaming responses, tools, and paced screen-reader announcements.

Readme

@generative-a11y/ai-sdk

Thin accessibility lifecycle translation for [email protected] and @ai-sdk/[email protected]. It observes host-owned public state and dispatches to a borrowed @generative-a11y/core runtime; it does not render UI, read the DOM, own a chat, invoke regenerate(), or inspect private chat state.

The root entry is SSR-safe. The React integration is available only from @generative-a11y/ai-sdk/react.

Install

For the framework-independent observer:

npm install @generative-a11y/core @generative-a11y/ai-sdk ai

For the React integration, also install the optional React peers:

npm install @ai-sdk/react react

React quick start

Create the accessibility integration before useChat() so its composed callbacks are present when AI SDK creates the chat. Then observe the documented public snapshot returned from useChat().

import { useChat } from "@ai-sdk/react";
import type { GenerativeA11yRuntime } from "@generative-a11y/core";
import {
  useChatAccessibility,
  useObserveChatAccessibility,
} from "@generative-a11y/ai-sdk/react";

function Chat({
  runtime,
}: {
  runtime: Pick<GenerativeA11yRuntime, "dispatch">;
}) {
  const accessibility = useChatAccessibility({
    runtime,
    scopeId: "support-thread",
    onFinish: hostOnFinish,
    onError: hostOnError,
  });
  const chat = useChat({
    id: "support-thread",
    ...accessibility.chatCallbacks,
  });
  useObserveChatAccessibility({ integration: accessibility, snapshot: chat });

  // Render the existing host interface unchanged.
}

useChatAccessibility() owns an observer and its delayed, cancellation-safe unmount cleanup; that avoids disposing it during React Strict Mode’s effect probe. useObserveChatAccessibility() only observes snapshots and never disposes the borrowed integration. Keep only observer-owning runtime, scopeId, and maxTrackedEntities stable for one mounted chat. onFinish, onError, and the optional label mapper may change identity across renders; the integration always uses their latest values.

For a non-React integration, use createObserver() and composeChatCallbacks() from the root entry before initializing the public AI SDK chat. runtime is a borrowed Pick<GenerativeA11yRuntime, "dispatch">; disposing an observer never disposes it.

Event mapping and limits

| Public AI SDK evidence | Core event | | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | | New assistant UIMessage.id | response.started | | Append-only text part content, by message ID and part index | response.text.delta suffix only | | input-streaming or input-available tool part | tool.started | | output-available tool part | tool.completed | | output-error tool part | tool.failed without backend error copy | | approval-requested / approval-responded / output-denied, by approval.id | approval.requested / approval.resolved | | New source-url or source-document, by sourceId | citation.available with tracked source count | | Composed onFinish | exact completion, abort, or error; disconnect is connection.lost only | | Composed onError | failure for the observed active response, without backend error copy |

The first valid snapshot silently baselines assistant text, tool, approval, and source identities. A repeated historical snapshot produces no events. Later text is emitted only when it is an append-only suffix. A non-prefix rewrite or reorder permanently suppresses that message-part until its message ID changes. Historical approvals are not resolved because this package did not observe a prior request event.

status: "ready", status: "error", and a call to regenerate() are not terminal or retry evidence. Retry fidelity is therefore unavailable in frozen CHAT_ADAPTER_METADATA; this package exports no retry wrapper. Disconnect recovery is reported only after a later successful onFinish, so connection fidelity is inferred.

The public chat snapshot does not expose stable run, step, or hierarchy lifecycles, so those fidelity fields remain unavailable rather than inferred.

maxTrackedEntities is a positive safe integer (default: 1000) that caps each response, that response's text-part indices, tool, approval, and source identity collection. Active response, pending approval, active tool, terminal, and historical records are never evicted. When any collection cannot admit another identity, the observer enters the saturation mode below instead of treating a stale event as new.

If initial history or a later live snapshot exceeds any identity cap, the observer enters metadata-declared suppress-after-baseline-capacity mode. It emits no later snapshot or callback lifecycle events for that observer instance. This bounded fail-closed behavior avoids replaying untracked historical IDs as new output; create a new observer with a suitable cap when the host switches chat history.

Automated tests validate normalized event translation, package import safety, and a real public useChat() hook harness. They do not demonstrate real assistive-technology speech.

Documentation

Related packages