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

lowdeep

v1.1.11

Published

The fluent, resilient, and 100% Type-Safe AI SDK with Self-Healing logic.

Readme

Lowdeep

Fluent, resilient, type-safe AI SDK for OpenAI-compatible chat models.

Lowdeep helps you move from free-form model output to validated TypeScript objects. It uses Zod for runtime validation and retries automatically when responses do not match your schema.

Sponsor Lowdeep

Table of Contents

Why Lowdeep

  • Fluent builder API: lowdeep().key(...).model(...).chat(...)
  • Type-gated usage: chat() is only available after required setup
  • Zod output validation with inferred TypeScript return types
  • Optional Zod input validation before making provider requests
  • Retry-on-validation-error loop with feedback sent back to the model
  • Built-in conversation memory, plus custom history injection

Installation

bun add lowdeep zod
# or
npm install lowdeep zod

Requirements

  • Node.js or Bun
  • TypeScript >=5
  • API key for one of the supported providers

Quick Start

import lowdeep from "lowdeep";

const ai = lowdeep()
  .key(process.env.OPENAI_API_KEY!)
  .model("gpt-4o-mini")
  .system("Be practical and concise.")
  .temperature(0.4);

const answer = await ai.chat("Explain what an API is in one paragraph.");
console.log(answer);

Detailed Examples

Example 1: Simple text chat

Use this when you only need plain text and do not need schema validation.

import lowdeep from "lowdeep";

const ai = lowdeep()
  .key(process.env.GROQ_API_KEY!)
  .model("llama-3.3-70b-versatile")
  .retry(2);

const tips = await ai.chat("Give me 5 ways to learn TypeScript faster.");
console.log(tips);

Example 2: Structured output (output schema only)

Use output schema when you need deterministic object shapes.

import { z } from "zod";
import lowdeep from "lowdeep";

const PlanSchema = z.object({
  topic: z.string(),
  difficulty: z.enum(["beginner", "intermediate", "advanced"]),
  steps: z.array(
    z.object({
      title: z.string(),
      estimateMinutes: z.number().int().min(1),
    }),
  ),
});

const ai = lowdeep()
  .key(process.env.OPENAI_API_KEY!)
  .model("gpt-4o-mini")
  .schema(PlanSchema)
  .retry(3);

const plan = await ai.chat("Create a React hooks study plan for beginners.");

// typed values from z.infer<typeof PlanSchema>
console.log(plan.topic);
console.log(plan.steps[0]?.title);

Example 3: Input + output schemas

Use this when your input is also structured and must be validated before request.

import { z } from "zod";
import lowdeep from "lowdeep";

const InputSchema = z.object({
  productName: z.string().min(2),
  audience: z.enum(["developer", "manager", "founder"]),
  tone: z.enum(["serious", "friendly"]),
});

const OutputSchema = z.object({
  headline: z.string(),
  bullets: z.array(z.string()).length(3),
  cta: z.string(),
});

const ai = lowdeep()
  .key(process.env.OPENAI_API_KEY!)
  .model("gpt-4o-mini")
  .schema(OutputSchema, InputSchema)
  .system("Return concise marketing copy.");

const ad = await ai.chat({
  productName: "Lowdeep",
  audience: "developer",
  tone: "friendly",
});

console.log(ad.headline);
console.log(ad.bullets);
console.log(ad.cta);

If input does not match InputSchema, chat(...) throws immediately and no request is sent.

Example 4: Multi-turn memory

Lowdeep keeps conversation history in memory for the builder instance.

import lowdeep from "lowdeep";

const ai = lowdeep()
  .key(process.env.OPENAI_API_KEY!)
  .model("gpt-4o-mini");

await ai.chat("Remember this code: PX-19.");
const reply = await ai.chat("What code did I ask you to remember?");
console.log(reply);

Example 5: Injecting your own history

Use .use(...) to preload context from your application state.

import lowdeep from "lowdeep";
import type { ChatCompletionMessageParam } from "openai/resources";

const history: ChatCompletionMessageParam[] = [
  { role: "system", content: "You are a strict project assistant." },
  { role: "user", content: "Project codename is Atlas." },
];

const ai = lowdeep()
  .use(history)
  .key(process.env.OPENAI_API_KEY!)
  .model("gpt-4o-mini");

console.log(await ai.chat("What is the project codename?"));

How the Builder Works

Typical order:

  1. lowdeep()
  2. .key(...)
  3. .model(...)
  4. Optional config (.system(), .temperature(), .retry(), .schema(), .use())
  5. .chat(...)

Type behavior:

  • You cannot call chat() until key and model are configured.
  • Without output schema, return type is text.
  • With output schema, return type is inferred from Zod.

API Reference

lowdeep()

Creates a new builder instance.

.key(value: string)

Sets API key and infers provider from key prefix:

  • gsk_ -> groq
  • sk_ -> openai
  • any other prefix -> deepinfra

.model(value: string)

Sets model id passed to the provider.

.system(prompt: string)

Sets system instruction. Default: "Be a helpful assistant".

.temperature(value: number)

Sets temperature from 0 to 2. Throws for values outside this range. Default: 0.7.

.retry(value: number)

Sets max retry attempts for the self-healing loop. Default: 3.

.schema(outputSchema: ZodType, inputSchema?: ZodType)

  • outputSchema: validates model response and returns typed object
  • inputSchema: validates chat(data) payload before provider request

.use(history: ChatCompletionMessageParam[])

Replaces current internal history with your own message array.

.chat(data)

  • If inputSchema exists, input is validated first.
  • If outputSchema is absent, returns model text.
  • If outputSchema exists, returns validated typed data.

Legacy .provider(...)

A runtime provider("groq" | "openai" | "deepinfra") method exists for compatibility, but key-based provider inference is the intended approach.

Self-Healing JSON Flow

When output schema is configured, Lowdeep:

  1. Injects JSON schema guidance in the system message.
  2. Requests strict JSON output.
  3. Cleans model output (including fenced JSON or reasoning tags).
  4. Parses and validates with Zod.
  5. On failure, appends validation errors and retries.

If all retries fail, Lowdeep prints a warning and returns undefined.

Provider Behavior

Supported providers:

  • OpenAI
  • Groq
  • DeepInfra

All requests are sent through OpenAI-compatible chat completions.

Error Handling

Common failures:

  • Provider rejects key/model
  • Temperature out of range (< 0 or > 2)
  • Input schema validation failure
  • Output schema still invalid after all retries

Recommended pattern:

try {
  const result = await ai.chat("Return JSON with title and score");
  console.log(result);
} catch (error) {
  console.error("Lowdeep request failed:", error);
}

Development

Build the package:

bun run build

Build output is generated in dist/.

Security Notes

  • Do not hardcode API keys in committed files.
  • Prefer process.env.* for secrets.
  • Rotate keys immediately if exposed.

License

MIT