Deuz SDK

Introduction

A pure, web-first, multi-provider TypeScript AI SDK with zero runtime dependencies and one canonical streaming wire.

@deuz-sdk/core is a from-scratch TypeScript AI SDK that talks to Anthropic, OpenAI, xAI Grok, Google Gemini, Vertex AI, and Yunwu through one canonical streaming protocol. It depends on no other AI SDK, ships zero runtime dependencies, and runs anywhere fetch runs — Node, Deno, Bun, and Vercel/Cloudflare Edge. Use it when you want full control over the wire, deterministic and replayable behavior, and no vendor lock-in at the streaming or UI layer.

npm install @deuz-sdk/core

Requires Node >= 22. The chat core has nothing in dependencies. Optional peers are pulled in only if you use them: zod (or any Standard Schema library) plus @standard-community/standard-json for schema-typed generateObject; @modelcontextprotocol/sdk for MCP; unpdf / mammoth / xlsx for Node document parsing in RAG.

Start by use case

Why it exists

Many AI integrations become hard to test because runtime state, provider-specific stream shapes, and UI wires leak into app code. @deuz-sdk/core keeps those seams explicit: dependencies are injected, provider streams are normalized, and the UI wire is owned by the SDK.

PrincipleWhat it means in practice
Pure coreNo Date.now(), Math.random(), process.env, or console in src/. Everything stateful — clock, logging, metering, circuit breaker, API keys — is injected through one Dependencies seam, so tests are deterministic and replayable.
Edge-safeOnly Web APIs (fetch, Web Streams, TextDecoder, WebCrypto, atob/btoa). node:* and Buffer are forbidden by lint; Node-only code lives in dedicated …/node subpaths.
Zero depsThe chat core ships nothing in dependencies. Heavy or stateful things are optional peers or injected seams.
No vendor lockOur own canonical delta stream and our own versioned UI wire. The SDK never proxies a provider's raw SSE bytes to your client.
Secrets never leakAPI keys are masked in every log, error, and span path. This is a regression-tested invariant.

The SDK core itself never reads process.env. Read keys at the app layer and pass them into the provider factory:

import { createAnthropic } from '@deuz-sdk/core/anthropic';

const anthropic = createAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });

The canonical line

Every request is normalized to a canonical Message[] / Part[] shape before it hits a wire, and every response is normalized to a canonical delta stream (StreamPart) before any orchestration or consumer sees it. Adapters never hand a provider's raw bytes to a caller.

Request:  canonical Message[]/Part[]  ->  adapter (one of 4 wires)  ->  upstream fetch
Response: upstream SSE  ->  robust parser  ->  CANONICAL DELTA STREAM
          (text-delta | reasoning-delta | tool-call-delta | source | finish)
          ->  inference orchestration (retry / timeout / tool-loop)
          ->  (a) canonical stream to the consumer   (b) versioned Deuz UI wire

Without this normalization, abort, retry-after-first-byte, multi-wire merging, and typed UI events are all impossible. The canonical events are a discriminated union (StreamPart) — keep a default case when you switch over them, because new variants are added additively.

Your first call

streamChat returns synchronously — the network request starts lazily on first access of any output, and it never throws synchronously. Failures surface as an error part on fullStream and as a rejected usage / finishReason promise.

stream.ts
import { streamChat } from '@deuz-sdk/core';
import { createAnthropic } from '@deuz-sdk/core/anthropic';

const anthropic = createAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });

const res = streamChat({
  model: anthropic('claude-opus-4-8'),
  messages: [{ role: 'user', content: 'Hello!' }],
  maxRetries: 2,
  onUsage: (u) => console.log(u.inputTokens, u.outputTokens),
});

for await (const chunk of res.textStream) process.stdout.write(chunk);
const usage = await res.usage; // resolves when the stream finishes

generateText and generateObject are awaited, buffered calls:

object.ts
import { generateObject } from '@deuz-sdk/core';
import { createAnthropic } from '@deuz-sdk/core/anthropic';
import { z } from 'zod'; // any Standard Schema works, or pass a raw JSON Schema

const anthropic = createAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });

const { object } = await generateObject({
  model: anthropic('claude-opus-4-8'),
  messages: [{ role: 'user', content: 'Capital of France as JSON.' }],
  schema: z.object({ city: z.string() }),
});

Feature overview

AreaWhat you getPage
Streaming chatLazy, never-throwing canonical stream with usage and finish-reason promisesstreamChat
Text generationBuffered single-turn or multi-step textgenerateText
Structured outputSchema-typed objects (Standard Schema or JSON Schema) with auto json/tool strategygenerateObject
Embeddingsembed / embedMany with auto-batching and concurrency capsEmbeddings
Agentic toolsParallel, self-healing tool loop with runaway guardsTools and Tool loop
Memorymem0 extract/reconcile pipeline over a vector or Obsidian-markdown storeMemory
RAGMIME sniff, chunkers, dense + lexical (BM25) hybrid retrievalRAG
SkillsSKILL.md parser with progressive disclosureSkills
MCPModel Context Protocol client (HTTP/SSE edge-safe; stdio Node-only)MCP
Image generationSync OpenAI-compatible generation, async Midjourney, Yunwu relayImage generation
UI streamingtoDeuzStreamResponse (server) and readDeuzStream (client)UI streaming
MiddlewarewrapModel with logging, caching, PII redaction, injection guardMiddleware
PricingOptional token-to-USD cost tablePricing

Supported providers

All providers normalize to the same canonical stream, so application code is provider-agnostic.

ProviderSubpathNotes
Anthropic@deuz-sdk/core/anthropicMessages API (/v1/messages)
OpenAI@deuz-sdk/core/openaiChat Completions and Responses API + openaiEmbedding
xAI Grok@deuz-sdk/core/xaiOpenAI-compatible wire
Google Gemini@deuz-sdk/core/googleCompat (createGoogle) and native generateContent (createGoogleNative) + googleEmbedding
Vertex AI@deuz-sdk/core/vertexClaude and Gemini on Vertex with OAuth2 Bearer auth
Voyage AI@deuz-sdk/core/voyageEmbeddings
Yunwu@deuz-sdk/core/yunwuUnified relay — chat, image, embed at /v1, Midjourney at the root

A provider factory returns a tiny LanguageModel descriptor; the model registry is the single source of truth for per-model capabilities (vision, tools, reasoning, structured output, caching, native PDF, audio, context window). Unknown model slugs do not throw — they fall back to conservative defaults, so new model releases work without a code change.

Quality bar

  • 377 tests across 38 files (vitest with golden-replay SSE fixtures and deterministic mock models — no real network)
  • tsc strict (moduleResolution: "Bundler", verbatimModuleSyntax, noUncheckedIndexedAccess)
  • eslint with edge-safety enforced, publint --strict, and attw (Are The Types Wrong) all green
  • Dual ESM + CJS build with .d.ts for every subpath export

Next steps

  • Installation — package, peers, and runtime requirements
  • Quickstart — a complete working example end to end

On this page