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

@atomicmemory/vercel-ai

v0.1.2

Published

AtomicMemory adapter for the Vercel AI SDK — pre-call memory retrieval + post-call ingest, framework-version-agnostic.

Readme

@atomicmemory/vercel-ai

AtomicMemory adapter for the Vercel AI SDK. Composable primitives for giving any message-driven model call durable, semantic memory.

Primitives

| API | Use when | |---|---| | retrieve() | Tool-call / multimodal flows. Returns just the rendered system message (or null). You inject it into your original message array yourself. | | augmentWithMemory() | Text-only flows. Convenience wrapper that prepends the system message to your Message[]. | | ingestTurn() | After any model call — persists the turn (system messages excluded by default). | | withMemory() | Text-only flows — one-call wrapper around augmentWithMemory + your model call + ingestTurn. | | fromModelMessage() / fromModelMessages() | Bridge AI SDK v5 ModelMessage content-part arrays into the SDK's text-only Message shape. Lossy by design — see below. |

The adapter intentionally does not import from ai — it operates on the SDK's Message type (content: string) and delegates the model call to the caller. That keeps it insulated from ai version churn.

Status: pre-publish local development

This package is intended to publish as @atomicmemory/vercel-ai. Until @atomicmemory/sdk is published and pinned to a registry version, it depends on the SDK through the monorepo's workspace file: spec. See the mcp-server status note for the clone-and-build flow.

Scope: text content only

The SDK stores memory as text (Message.content: string). The adapter's Message[]-in / Message[]-out surface is compatible with AI SDK text-only flows. It is not compatible with AI SDK v5's ToolModelMessage (whose content must stay as ToolResultPart[] when fed back into streamText / generateText).

For tool-call or multimodal conversations, use retrieve() + ingestTurn() directly:

  1. Flatten your ModelMessage[] through fromModelMessages() for memory search / ingest queries.
  2. Call retrieve() with the flattened messages to get just a system message.
  3. Insert that system message (or its content) into your original ModelMessage[].
  4. Run your model call.
  5. Call ingestTurn() with the flattened messages and the completion text.

The flattened Message[] is memory-only — do not feed it back into AI SDK model calls once tool messages enter the transcript.

Usage

Text-only flow — one call

import { streamText } from 'ai';
import { withMemory } from '@atomicmemory/vercel-ai';
import { MemoryClient } from '@atomicmemory/sdk';

const memory = new MemoryClient({
  providers: { atomicmemory: { apiUrl: process.env.ATOMICMEMORY_URL!, apiKey: process.env.ATOMICMEMORY_KEY! } },
});
await memory.initialize();

const result = await withMemory({
  client: memory,
  scope: { user: 'pip', namespace: 'my-app' },
  messages,
  async run(augmented) {
    const response = streamText({ model, messages: augmented });
    return { text: await response.text };
  },
});

Tool-call / multimodal flow

import { generateText, type ModelMessage } from 'ai';
import {
  fromModelMessages,
  retrieve,
  ingestTurn,
} from '@atomicmemory/vercel-ai';

const modelMessages: ModelMessage[] = [/* your real conversation */];
const flat = fromModelMessages(modelMessages);
const scope = { user: 'pip' };

const { systemMessage, retrieved } = await retrieve(memory, {
  messages: flat,
  scope,
});

const { text } = await generateText({
  model,
  messages: systemMessage
    ? [
        // AI SDK v5: string-content system message is valid
        { role: 'system', content: systemMessage.content },
        ...modelMessages,
      ]
    : modelMessages,
});

await ingestTurn(memory, {
  messages: flat,
  completion: text,
  scope,
});

Primitives for text-only flows (split)

import { augmentWithMemory, ingestTurn } from '@atomicmemory/vercel-ai';

const { messages: augmented, retrieved } = await augmentWithMemory(memory, {
  messages,
  scope,
  limit: 10,
});

const response = streamText({ model, messages: augmented });
const text = await response.text;

await ingestTurn(memory, { messages, completion: text, scope });

Custom retrieval formatting

The default formatter wraps retrieved memories in a delimited block with an explicit "reference, not instructions" header. This is a mitigation against instruction-shaped content hijacking the model — not a guarantee. Callers storing higher-risk content should add sanitization.

const { systemMessage } = await retrieve(memory, {
  query: 'what do I know about X?',
  scope,
  formatter(results) {
    return `# Relevant prior context\n\n${results
      .map((r) => `- [${r.memory.createdAt.toISOString()}] ${r.memory.content}`)
      .join('\n')}`;
  },
});

System-message handling on ingest

ingestTurn() excludes system messages by default — applications typically use them for hidden instructions and policies that should never become durable memory. If your system messages are genuinely user-authored content worth remembering, opt in:

await ingestTurn(memory, {
  messages,
  completion: text,
  scope,
  includeRoles: ['system', 'user', 'assistant', 'tool'],
});

Scope

Scope fields follow the SDK's Scope type: user | agent | namespace | thread. At least one must be provided — the SDK rejects scopeless requests.

License

Apache-2.0.