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

@kestrel-agents/ai-sdk

v0.6.0

Published

Typed Vercel AI SDK presentation adapter for Kestrel runner streams

Downloads

56

Readme

@kestrel-agents/ai-sdk

Typed presentation adapter between Kestrel runner events and Vercel AI SDK 6 UI messages.

The package turns one Kestrel run stream into a durable assistant message with human-facing text, typed activity parts, terminal metadata, and visible contract failures. The same accumulator drives the live UI stream and the message you persist, preventing them from developing different interpretations of a run.

When to Use It

Use this package in a server-side Vercel AI SDK application when you want to render Kestrel:

  • runtime and committed agent progress
  • live provider reasoning when the provider exposes it
  • tool activity
  • citations and artifacts
  • approval or elicitation interactions
  • completed, waiting, failed, cancelled, or contract-failure state
  • terminal assistantText

It is a presentation adapter, not a runtime, transport, React component library, or browser client. Start and control the run through @kestrel-agents/sdk.

Install

pnpm add @kestrel-agents/[email protected] \
  @kestrel-agents/[email protected] \
  ai@^6

The runtime, protocol, SDK, and presentation adapter must use a compatible release line. Check 0.6 Beta release status before pinning a production dependency.

Stream a Kestrel Run

Inside a Vercel AI SDK createUIMessageStream execute callback, pass the writer and the Kestrel SDK stream to the adapter:

import type { UIMessageStreamWriter } from "ai";
import type {
  RunnerRunStreamEvent,
  RunnerRunTerminalEvent,
  RunnerStream,
} from "@kestrel-agents/sdk";
import {
  type KestrelUIMessage,
  writeKestrelFailureToUIMessage,
  writeKestrelRunnerStreamToUIMessage,
} from "@kestrel-agents/ai-sdk";

async function writeRun(
  writer: UIMessageStreamWriter<KestrelUIMessage>,
  runStream: RunnerStream<RunnerRunStreamEvent, RunnerRunTerminalEvent>,
  turnId: string,
) {
  try {
    return await writeKestrelRunnerStreamToUIMessage({
      writer,
      events: runStream,
      terminalEvent: runStream.result,
      assistantMessageId: crypto.randomUUID(),
      textPartId: crypto.randomUUID(),
      turnId,
    });
  } catch (error) {
    return writeKestrelFailureToUIMessage({
      writer,
      error,
      assistantMessageId: crypto.randomUUID(),
      textPartId: crypto.randomUUID(),
      turnId,
    });
  }
}

The returned KestrelPresentationSnapshot contains:

  • message: the complete assistant UIMessage to persist
  • message.metadata.kestrelTurnId: the host product's durable turn identity, when supplied
  • assistantText: canonical human-facing terminal text or null
  • terminalStatus: working, completed, waiting, failed, cancelled, or contract_failure
  • errorMessage: visible normalized failure detail when present
  • failureVisible: whether the terminal failure must remain visible in the UI
  • interaction: the durable pending interaction when the run is waiting

Use one pair of message/text part IDs for one assistant message. If the caller reconnects to the same durable run, preserve the Kestrel event cursor and your application's message identity rules.

assistantText is producer-owned. Completed runs require a non-empty response; user-facing waits require assistantText to equal the interaction prompt. A data-kestrel-status part describes that run segment, while the host product's durable turn ledger remains authoritative for the current multi-segment turn state.

Typed Message Parts

KestrelPresentationDataParts adds these AI SDK data parts:

| Part | Meaning | Persisted | | --- | --- | --- | | data-kestrel-progress | Runtime, environment, or worker progress | Yes | | data-kestrel-agent-progress | Committed agent progress | Yes | | data-kestrel-provider-reasoning | Provider-exposed live reasoning | No; emitted as transient | | data-kestrel-tool | Tool start, completion, or failure | Yes | | data-kestrel-citation | Citation metadata | Yes | | data-kestrel-artifact | Produced artifact metadata | Yes | | data-kestrel-interaction | Pending approval, input, MCP sampling, or elicitation | Yes | | data-kestrel-status | Terminal or contract-failure state | Yes |

Provider reasoning is deliberately live-only. Committed agent progress is a durable product event and remains in the persisted message.

Use the Accumulator Directly

Use createKestrelPresentationAccumulator() when your server framework owns its own stream transport but still needs the canonical presentation contract:

import { createKestrelPresentationAccumulator } from "@kestrel-agents/ai-sdk";

const presentation = createKestrelPresentationAccumulator({
  assistantMessageId: "assistant-123",
  turnId: "turn-123",
});

for await (const event of runStream) {
  const newParts = presentation.append(event);
  // Send newParts through your transport.
}

const snapshot = presentation.finish(await runStream.result);
// Persist snapshot.message.

The accumulator deduplicates identified parts and validates terminal waiting interactions. Invalid or contradictory presentation data becomes a visible KestrelPresentationContractError state instead of disappearing from the UI.

Terminal Interactions

readKestrelTerminalInteraction() extracts a durable pending interaction from a waiting terminal event. It verifies that the canonical assistantText matches the interaction prompt so the user is not shown two contradictory requests.

Exports

  • writeKestrelRunnerStreamToUIMessage
  • writeKestrelFailureToUIMessage
  • createKestrelPresentationAccumulator
  • readKestrelTerminalInteraction
  • KestrelPresentationContractError
  • typed message, metadata, part, snapshot, status, tool, citation, artifact, progress, reasoning, and interaction contracts

Requirements

  • Node.js 20 or newer
  • Vercel AI SDK >=6 <7
  • compatible @kestrel-agents/sdk and protocol contracts
  • server-side execution; do not expose runner credentials to the browser

Development

pnpm run ai-sdk:test
pnpm run ai-sdk:build
pnpm run ai-sdk:release-check

Related Docs