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

@use-crux/ai

v0.5.0

Published

Vercel AI SDK adapter for Crux — run Crux prompts, agents, and flows against any AI SDK model (generate & stream).

Readme

@use-crux/ai

Vercel AI SDK adapter for Crux. Runs Crux prompts against any AI SDK LanguageModel via generate() and stream().

Orchestration — prompt composition, context engineering, memory, tools, routing, safety — lives in @use-crux/core. This package exports aiSdkProviderRuntime, a normal Crux adapter with ownership: 'loop-owned' for SDKs that own their own tool loop, and delegates mechanics to AI SDK natives: stopWhen for loop budgets, prepareStep for mid-loop steering, experimental_repairText for cheap JSON repair, SDK-owned tool approval hooks, abortSignal for timeouts. It owns no policy of its own.

Internally, AI SDK request planning and result projection live in a private call-plan codec. The codec prepares generateText, generateObject, streamText, streamObject, and cached replay plans; the executor only invokes the selected SdkGateway method and decodes or attaches the raw SDK result. SdkGateway remains the only runtime seam that calls the ai package.

The package exports aiSdkProviderRuntime for advanced adapter composition. createCruxAi({ gateway }) binds aiSdkProviderRuntime.create(gateway), including its embedding and reranking extensions; public integrations should depend on the provider runtime rather than the package's internal executor.

Install

pnpm add @use-crux/ai @use-crux/core ai@^6

ai is a peer dependency (^6.0.0). Add a provider package (e.g. @ai-sdk/openai) for the models you call. react is an optional peer, required only for the @use-crux/ai/stream transport.

Usage

import { prompt } from "@use-crux/core";
import { generate } from "@use-crux/ai";
import { openai } from "@ai-sdk/openai";

const fixTypos = prompt({
  id: "fix-typos",
  template: ({ instruction }: { instruction: string }) => instruction,
});

const result = await generate(fixTypos, {
  model: openai("gpt-4o"),
  input: { instruction: "Fix typos" },
});

result.text; // string

A prompt with an output schema routes through generateObject and returns a typed result.object, with tiered repair/retry when validationRetry is set. Models may be plain or wrapped in core's fallback() / router() / cascade(). Tool loops run up to maxSteps: 10 by default — identical to every Crux adapter (and unlike the raw AI SDK's single-step default), so prompts behave the same when moved between adapters. Use Crux's portable maxTokens, topK, stopSequences, seed, toolChoice, stopWhen, maxSteps(), hasToolCall(), reasoning, and toolApproval settings for adapter-neutral control; AI SDK-native stop conditions, tool-choice variants, providerOptions, headers, retries, and fine-grained provider reasoning controls belong under the typed extra option. Tools that declare contextSchema require toolsContext.<toolName> at the call site, and runtimeContext is threaded through tool execution, middleware, and function-form approval policies. timeout accepts structured budgets (totalMs, stepMs, chunkMs, toolMs, and tools[name]) and expired budgets reject with TimeoutError. generate() returns the canonical Crux envelope: accumulated text, optional complete usage, optional cost, steps, finalStep, provider-neutral messages, retained _meta, and typed .raw for the AI SDK result. stream() returns { textStream, raw, completion }; raw is the AI SDK stream result, and completion resolves to the canonical completion envelope. Use createUIMessageStreamResponse(result) or pipeUIMessageStreamToResponse(result, options) for AI SDK useChat integration. embedding() binds AI SDK embedding models as Crux primitives, and generateObjectFn / generateTextFn satisfy @use-crux/core APIs that expect a generate function (e.g. llmJudge, summarizeMessages, and retrieval recipe model steps). generateObjectFn uses the same AI SDK structured-attempt mechanics as prompt structured generation: provider schema sanitation, core-backed experimental_repairText, and router/cascade model resolution before returning { object }. If a GenerateObjectFn call needs to go through full adapter prompt execution, use createGenerateObjectFnFromGenerate(generate) from @use-crux/core/compaction.

For useChat route handlers, keep the AI SDK message edge native:

import { convertToModelMessages } from "ai";
import { createUIMessageStreamResponse, stream } from "@use-crux/ai";

export async function POST(req: Request) {
  const { messages } = await req.json();
  const result = await stream(chatPrompt, {
    model,
    input: { tenantId: "acme" },
    messages: await convertToModelMessages(messages),
  });

  return createUIMessageStreamResponse(result);
}

toParams(resolved, { model }) exposes the AI SDK request-planning codec for headless power users, and fromResponse(response) normalizes an AI SDK generate result into Crux response facts. These helpers translate only; use managed generate()/stream() for Crux-owned tools, approvals, memory, validation retry, safety, and observability.

prepare(prompt, opts) returns a sans-I/O handle over the package's SdkGateway seam: inspect params, call the AI SDK yourself, then pass the raw SDK result to finish(response). Use generate(prompt, { ...opts, transport }) when Crux should keep owning the loop and your callback should make each SdkGateway call. Streaming with transport is not supported and rejects with CruxTransportStreamUnsupportedError.

Streaming structured output uses AI SDK streamObject(). In AI SDK v6 that API does not expose the text-loop tool event surface, so Crux omits tools for structured streams and emits a one-time warning when a structured stream declares tools. Use generate() for structured tool loops, or stream without an output schema when live tool observability is required.

Media

AI SDK ModelMessage and useChat content stay model-owned. Crux preserves normal image/audio/video/file parts and ordered mixed assistant output without adding a second message or tool loop. The package exports native AI SDK generateImage(), transcribe(), and generateSpeech() wrappers with the shared Crux result tail, cancellation, timeout, and descriptor-only reporting. Provider-native controls remain in typed extra; persistence is a separate application assetStore.put() call.

For Anthropic AI SDK models, Crux converts the stable provider-cache prefix into system messages and places providerOptions.anthropic.cacheControl on the single cacheBoundary block.

Agent frameworks

Use @use-crux/ai/agent when an AI SDK-compatible framework, such as Convex Agent or Mastra, owns the model loop but you still want Crux prompt resolution and tracing:

import { resolve } from "@use-crux/ai/agent";

const { instructions, model } = await resolve(chatPrompt, {
  model: languageModel,
  input: { mode: "support" },
  tools: Object.keys(tools),
});

@use-crux/ai/agent composes instructions through the normal core prompt pipeline and adds the AI SDK runtime binding: when Crux execution hooks are installed, the returned model is wrapped with wrapLanguageModel() middleware for generate/stream traces, tool timing estimates, stream progress, and provider metadata cost extraction.

Testing without module mocks

The only module that calls AI SDK functions is the SdkGateway. Bind your own with createCruxAi({ gateway }) to script results in tests — no vi.mock('ai'):

import { createCruxAi } from "@use-crux/ai";

const ai = createCruxAi({ gateway: myScriptedGateway });
const result = await ai.generate(myPrompt, { model, input });

For loop-mechanics coverage, pass MockLanguageModelV3 (from ai/test) models through the default live gateway.

AI SDK helpers such as tool() are not re-exported — import them from 'ai' or this package's helper exports as documented. Crux's portable loop helpers (maxSteps, hasToolCall) come from @use-crux/core. Agent compositions come from @use-crux/core/agent.

See the @use-crux/core reference and the Crux docs for the full API.