any-llm-ts
Migration

Migrating from Python any-llm

Translate the original Python library's central patterns into idiomatic TypeScript.

This is an intent-level port, not a line-by-line translation. The provider facade and adapter architecture remain recognizable, but the public API follows TypeScript and JavaScript conventions.

Import and naming changes

from any_llm import completion
import { completion } from "any-llm-ts";

Public identifiers use camelCase: listModels, imageGeneration, apiKey, providerOptions, and toolCalls.

Async operations

Network operations always return promises:

const response = await completion(params);

Streaming uses the standard AsyncIterable protocol:

const stream = await completion({ ...params, stream: true });

for await (const chunk of stream) {
  // ...
}

Client construction

Use a reusable AnyLLM instance when making repeated calls:

const llm = AnyLLM.create("anthropic");
await llm.completion(params);

This replaces Python-specific factory and context patterns with an explicit object that owns the underlying SDK client.

Model syntax

Use provider:model when a stateless helper must infer the provider:

await completion({
  model: "anthropic:claude-sonnet-4-5",
  messages,
});

The slash form is deprecated in the TypeScript port because model names frequently contain slashes.

Data models

Python model classes and dictionaries become TypeScript interfaces and discriminated unions. They do not perform runtime validation by themselves. Validate untrusted inputs with your preferred runtime schema library before passing them to provider operations.

Exceptions

Catch exported error classes with instanceof:

try {
  await llm.completion(params);
} catch (error) {
  if (error instanceof RateLimitError) {
    // ...
  }
}

Parity and deliberate differences

The TypeScript port tracks the same provider names and stateless operations as Python source commit 43b3bbbdd4a1a5fa57cddee7a29041afaaaf271e. That includes Messages compatibility, batches, reranking, structured output, provider tiers, prompt-cache policy, and the native adapters needed by non-OpenAI-compatible services.

The parity contract records three deliberate capability-flag differences. Azure Anthropic and Vertex Anthropic do not advertise batches because their TypeScript SDK clients do not expose the Messages batch API. Voyage does not advertise Messages because its SDK provides embeddings only, even though the Python class inherits a default True flag.

For the architectural rationale and a detailed parity map, see docs/PORTING.md.

On this page