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

@neutron-build/ai

v0.1.0

Published

AI SDK for Neutron. Model calls, streaming, structured output, and tool-calling over pluggable provider adapters.

Readme

@neutron-build/ai

AI SDK for Neutron. Model calls, streaming, structured output, and tool-calling over pluggable provider adapters.

Providers are subpath exports — importing one never loads another, and no provider SDKs are pulled in at all (adapters speak the provider HTTP APIs directly over fetch).

import { generateText, streamText } from "@neutron-build/ai";
import { anthropic } from "@neutron-build/ai/anthropic";

const model = anthropic("claude-sonnet-5");

const { text, usage } = await generateText({
  model,
  prompt: "Summarize the Neutron framework in one sentence.",
});

const result = streamText({ model, prompt: "Write a haiku about databases." });
for await (const delta of result.textStream) {
  process.stdout.write(delta);
}

Tools and agents

import { generateText, tool } from "@neutron-build/ai";
import { z } from "zod";

const search = tool({
  name: "search",
  description: "Search the codebase",
  inputSchema: z.object({ query: z.string() }),
  execute: async ({ query }) => runSearch(query),
});

const deploy = tool({
  name: "deploy",
  inputSchema: z.object({ target: z.string() }),
  execute: async ({ target }) => runDeploy(target),
  needsApproval: true, // or a predicate: ({ target }) => target === "prod"
});

const result = await generateText({ model, prompt, tools: [search, deploy], maxSteps: 5 });

if (result.finishReason === "tool-approval") {
  // Serializable suspension: persist result.messages + result.approvalRequests,
  // then resume — hours or days later — with the decisions:
  await generateText({
    model,
    messages: result.messages,
    tools: [search, deploy],
    maxSteps: 5,
    toolApprovals: [{ toolCallId: result.approvalRequests[0].toolCallId, approved: true }],
  });
}

Tool inputs validate through any Standard Schema library (zod, valibot, arktype). Invalid model inputs, unknown tools, and tool exceptions become error results fed back to the model so it can self-correct instead of crashing the loop.

Structured output

import { generateObject } from "@neutron-build/ai";

const { object } = await generateObject({
  model,
  prompt: "Extract the review.",
  schema: z.object({ title: z.string(), stars: z.number().int() }),
});

Implemented as a forced tool call — the one mechanism every provider supports identically — so it behaves the same on Anthropic, OpenAI, and any OpenAI-compatible server.

Streaming structured output

import { streamObject } from "@neutron-build/ai";

const result = streamObject({ model, prompt: "Extract the review.", schema });
for await (const partial of result.partialObjectStream) {
  render(partial); // growing snapshots as the JSON streams in
}
const review = await result.object; // final, schema-validated

Chat over the wire

Server (any Neutron mode:"api" route — it's just a web-standard Response):

import { streamText, toEventStreamResponse } from "@neutron-build/ai";

export async function POST(request: Request) {
  const { messages } = await request.json();
  return toEventStreamResponse(streamText({ model, messages, tools, maxSteps: 5 }));
}

Client — Preact hook, or the framework-free ChatStore it wraps:

import { useChat } from "@neutron-build/ai/preact";

const { messages, status, send, stop } = useChat({ api: "/api/chat" });

Embeddings

import { embedMany, embedAndStore } from "@neutron-build/ai";
import { createOpenAI } from "@neutron-build/ai/openai";

const openai = createOpenAI();
const embedder = openai.embedding("text-embedding-3-small");

const { embeddings } = await embedMany({ model: embedder, values: chunks });

// Or write straight to a Nucleus Vector collection:
await embedAndStore({ model: embedder, values: chunks, vector: nucleus.vector, collection: "docs" });

Agent harnesses

One interface for driving any agent — in-process, Claude Code, or your own — so consumers never couple to a specific one:

import { localAgent, claudeCode } from "@neutron-build/ai/harness";

const agent = localAgent({ model, tools, maxSteps: 8 });   // this SDK's own loop
// const agent = claudeCode({ permissionMode: "acceptEdits" });  // or the Claude Code CLI

const run = agent.run({ prompt: "fix the failing test", cwd: "/repo" });
for await (const event of run.events) {
  // session | text-delta | tool-start | tool-end | approval-request | finish
}
const { status, output, sessionId, usage, costUSD } = await run.result;
// continue the conversation later:
agent.run({ prompt: "now add a regression test", sessionId });

Runs never throw from the event stream — failures arrive as a finish event plus result.error (RFC 7807), so every harness fails identically. localAgent supports the SDK's approval suspension (status: "suspended", resume with toolApprovals); CLI harnesses govern permissions their own way (permissionMode for Claude Code).

Exports

| Subpath | Contents | |---------|----------| | . | generateText, streamText, generateObject, streamObject, embed/embedMany/embedAndStore, tool, jsonSchema, ChatStore, toEventStreamResponse/streamPartsFromResponse, core types, ModelAdapter interface | | ./anthropic | anthropic() / createAnthropic() — Anthropic Messages API adapter | | ./openai | openai() / createOpenAI() — OpenAI Chat Completions + embeddings; via baseURL also Groq, DeepSeek, Gemini's OpenAI-compatible endpoint, vLLM/Ollama | | ./preact | useChat hook (optional preact peer dependency) | | ./harness | AgentHarness interface, localAgent(), claudeCode() (Node-only subpath) |

Configuration

The Anthropic adapter reads ANTHROPIC_API_KEY, or takes an explicit key:

import { createAnthropic } from "@neutron-build/ai/anthropic";

const anthropic = createAnthropic({
  apiKey: process.env.MY_KEY,
  baseURL: "https://gateway.example.com", // optional: AI Gateway / proxy
});

Errors

All errors are AIError carrying an RFC 7807 problem-details object (error.problem), mapped from provider responses per the framework contract (429 becomes rate-limited, provider 5xx becomes internal with the provider message in detail).

Status

All five milestones complete: core types, ModelAdapter interface, Anthropic + OpenAI adapters, the multi-step tool loop with approval suspension, generateObject/streamObject, embeddings with Nucleus Vector write-through, the event-stream chat wire, the /preact hook, and the /harness agent interface with localAgent and claudeCode implementations. Also: extended-thinking passthrough (reasoning parts round-trip with signatures; enable via anthropic(model, { thinking: { budgetTokens } })) and automatic retries (maxRetries, default 2, jittered backoff on 429/5xx; streams retry only before producing output). A Codex CLI harness follows the same interface when wire fixtures are captured.