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

@ank1015/llm-types

v0.0.3

Published

Shared contracts and provider-native types for @ank1015/llm

Readme

@ank1015/llm-types

Shared contracts for a multi-provider LLM SDK that preserve native provider types instead of flattening everything into a lowest-common-denominator abstraction.

This package is mostly compile-time types, with a very small shared runtime surface:

  • KnownApis
  • isValidApi()
  • LLMError and its subclasses

Why This Package Exists

The monorepo has packages that need the shared contracts without needing the full runtime implementation. For example:

  • @ank1015/llm-core implements provider calls and streaming
  • @ank1015/llm-sdk composes higher-level workflows on top
  • @ank1015/llm-sdk-adapters implements storage adapters and mostly needs interfaces, messages, sessions, and errors

Keeping the contracts separate lets those packages share the same shapes without forcing all of them to depend on the provider runtime stack.

Philosophy

Most multi-provider LLM libraries normalize both inputs and outputs so aggressively that provider-specific capabilities disappear.

This package takes a different approach:

  • Provider options stay provider-native. OpenAIProviderOptions stays close to the OpenAI Responses API. AnthropicProviderOptions stays close to Anthropic Messages. GoogleProviderOptions stays close to @google/genai.
  • Native responses are preserved. BaseAssistantMessage<TApi> always keeps the original provider response object in message.
  • Normalized fields are added on top. You still get provider-agnostic content, usage, stopReason, and streaming event shapes for UI and orchestration logic.

Installation

pnpm add @ank1015/llm-types

Supported Providers

type Api =
  | 'openai'
  | 'codex'
  | 'google'
  | 'deepseek'
  | 'anthropic'
  | 'claude-code'
  | 'zai'
  | 'kimi'
  | 'minimax'
  | 'cerebras'
  | 'openrouter';

The union is derived from KnownApis, so adding a provider in src/api.ts automatically updates the type and triggers exhaustiveness errors across consumers.

Core Types

BaseAssistantMessage<TApi>

The central response contract preserves both normalized and native data:

interface BaseAssistantMessage<TApi extends Api> {
  role: 'assistant';
  api: TApi;
  id: string;
  model: Model<TApi>;

  // Normalized fields
  content: AssistantResponse;
  usage: Usage;
  stopReason: StopReason;
  timestamp: number;
  duration: number;
  errorMessage?: string;

  // Provider-native response
  message: NativeResponseForApi<TApi>;
}

NativeResponseForApi<TApi> resolves to the real SDK response type:

  • anthropic, claude-code, minimax -> Anthropic.Message
  • openai, codex -> OpenAI.Response
  • google -> GenerateContentResponse
  • deepseek, kimi, zai, cerebras, openrouter -> ChatCompletion

BaseAssistantEvent<TApi>

Typed streaming events cover the full assistant lifecycle:

  • start
  • text_start / text_delta / text_end
  • thinking_start / thinking_delta / thinking_end
  • image_start / image_frame / image_end
  • toolcall_start / toolcall_delta / toolcall_end
  • done
  • error

Every event includes the in-progress BaseAssistantMessage<TApi>.

Content

Unified multimodal content blocks:

type Content = (TextContent | ImageContent | FileContent)[];

ImageContent also supports normalized generated-image metadata such as:

  • generation stage (partial, thought, final)
  • provider
  • provider item id
  • revised prompt
  • output size / quality / format / background

Model<TApi> and Provider<TApi>

Model<TApi> is the shared model metadata contract:

  • api, id, name, baseUrl
  • reasoning
  • supported inputs
  • token pricing
  • contextWindow, maxTokens
  • headers
  • supported tool capabilities

Provider<TApi> pairs a model with its provider-specific options.

Tool and Context

Tools use TypeBox schemas directly:

interface Tool<TParameters extends TSchema = TSchema> {
  name: string;
  description: string;
  parameters: TParameters;
}

interface Context {
  messages: Message[];
  systemPrompt?: string;
  tools?: Tool[];
}

Provider Option Families

The current provider options fall into a few families:

  • Anthropic Messages-compatible
    • AnthropicProviderOptions
    • ClaudeCodeProviderOptions
    • MiniMaxProviderOptions
  • OpenAI Responses-compatible
    • OpenAIProviderOptions
    • CodexProviderOptions
  • Google GenAI-compatible
    • GoogleProviderOptions
  • OpenAI Chat Completions-compatible
    • DeepSeekProviderOptions
    • KimiProviderOptions
    • ZaiProviderOptions
    • CerebrasProviderOptions
    • OpenRouterProviderOptions

The package preserves provider-specific extensions where needed, for example:

  • CodexProviderOptions requires chatgpt-account-id
  • ClaudeCodeProviderOptions uses oauthToken, betaFlag, and billingHeader
  • KimiProviderOptions and ZaiProviderOptions expose thinking config
  • CerebrasProviderOptions exposes reasoning format / effort controls

Type Maps

Compile-time lookups connect Api to the right native response and options type:

type NativeResponseForApi<TApi extends Api> = ApiNativeResponseMap[TApi];
type OptionsForApi<TApi extends Api> = ApiOptionsMap[TApi];
type WithOptionalKey<T> = Omit<T, 'apiKey'> & { apiKey?: string };

Agent Contracts

This package also defines the shared contracts for tool-using agents:

  • AgentTool
  • AgentToolResult<T>
  • AgentState
  • AgentLoopConfig
  • AgentEvent
  • Attachment
  • QueuedMessage<T>
  • ToolExecutionContext

These are shared here because they are part of the monorepo-wide contract surface, even though the runtime agent loop lives in @ank1015/llm-core.

Storage Contracts

Shared adapter and session types also live here:

  • KeysAdapter
  • UsageAdapter
  • SessionsAdapter
  • SessionNode, Session, SessionSummary, BranchInfo
  • CreateSessionInput, AppendMessageInput, AppendCustomInput, UpdateSessionNameInput

These contracts are consumed directly by packages like @ank1015/llm-sdk-adapters.

Error Classes

Minimal shared runtime errors are exported so every package can throw and catch the same error types:

  • LLMError
  • ApiKeyNotFoundError
  • CostLimitError
  • ContextLimitError
  • ConversationBusyError
  • ModelNotConfiguredError
  • SessionNotFoundError
  • InvalidParentError
  • PathTraversalError

Adding a Provider

  1. Create src/providers/<name>.ts with native response and provider options types
  2. Add the provider string to KnownApis in src/api.ts
  3. Add it to ApiNativeResponseMap and ApiOptionsMap in src/providers/index.ts
  4. Re-export it from src/providers/index.ts
  5. Re-export it from src/index.ts

TypeScript will surface exhaustiveness errors anywhere the new provider is not handled.

What Does and Doesn't Belong Here

Belongs here:

  • Shared public contracts
  • Provider-native response and option types
  • Agent/storage/session interfaces
  • Small shared runtime primitives used across packages

Does not belong here:

  • API clients
  • Provider request execution
  • Streaming implementations
  • Model catalogs
  • Registry/dispatch logic

Those live in @ank1015/llm-core.

License

MIT