AbsoluteJS

AI Integration

Built-in AI streaming with multi-provider support, tool calling, extended thinking, and framework-specific hooks. Add a real-time AI chat to your app with a single Elysia plugin and a one-line hook.

#Quick Start

Add AI streaming to your server with the aiChat plugin. It creates a WebSocket endpoint and REST routes for conversation management automatically.

BASH
bun add @absolutejs/ai elysia
TS
import { Elysia } from 'elysia';
import { prepare, networking } from '@absolutejs/absolute';
import { aiChat } from '@absolutejs/ai';
import { anthropic } from '@absolutejs/ai/anthropic';

const { absolutejs, manifest } = await prepare();

new Elysia()
  .use(absolutejs)
  .use(
    aiChat({
      provider: () => anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
      systemPrompt: 'You are a helpful assistant.',
    })
  )
  .use(networking);

#Deterministic conversation turns

Per-conversation serialization prevents later turns from overtaking active or failed work while keeping queued state visible to every framework adapter.

  1. Queue
    Assign a stable client message id and enqueue behind the active turn.
  2. Expose
    Emit turn_queued so the UI can render isQueued immediately.
  3. Start
    Emit turn_started only when prior work reaches a safe terminal state.
  4. Fence failures
    Block later turns after failure until the user retries or removes the failed turn.
  5. Branch
    Branch explicitly when the user chooses an alternate history.

#Architecture

The AI integration is organized in three layers that flow from server to client:

1
Server Plugin
The aiChat Elysia plugin creates WebSocket and REST endpoints, manages conversations, and orchestrates streaming with tool execution.
@absolutejs/ai
2
Provider Layer
Adapters for each AI service that normalize different APIs into a unified AsyncIterable<AIChunk> streaming interface.
@absolutejs/ai/anthropic
3
Client Layer
Framework-specific hooks and composables that manage WebSocket connections, auto-reconnect, and message state with a reducer pattern.
@absolutejs/ai/react
TS
import { aiChat } from '@absolutejs/ai';              // Server plugin
import { anthropic } from '@absolutejs/ai/anthropic';  // Provider
import { useAIStream } from '@absolutejs/ai/react';    // Client hook

#Features

Multi-Provider
Anthropic, OpenAI, Gemini, Ollama, and 7 more via OpenAI-compatible adapters
Tool Calling
JSON Schema inputs with async handlers. Multi-turn tool loops execute automatically.
Extended Thinking
Stream reasoning tokens from Claude, o3, and DeepSeek R1 with configurable budgets
Image Generation
Generate images with OpenAI and Gemini, streamed progressively to the client
File Attachments
Send images and PDFs as base64 alongside messages for vision and document analysis
Conversations
Server-side history with branching, listing, and deletion via REST endpoints

#Supported Providers

ProviderImportModels
Anthropicai/anthropicClaude Opus 4.6, Sonnet 4.6, Haiku 4.5
OpenAIai/openaiGPT-4o, GPT-5.x
OpenAI Responsesai/openai-responseso3, o4-mini, gpt-image-1.5
Geminiai/geminiGemini 3 Pro/Flash, 2.5 Pro/Flash
Ollamaai/ollamaAny local model
xAIai/providersGrok 4, Grok 3
DeepSeekai/providersDeepSeek V3, R1
Mistralai/providersLarge, Small, Codestral
Metaai/providersLlama 4 Maverick/Scout
Alibabaai/providersQwen Max/Plus/Turbo
Moonshotai/providersKimi K2

#Client Hooks

Every framework gets an idiomatic binding with the same API surface:

FrameworkImportAPI
Reactreact/aiuseAIStream() hook + AIStreamProvider
Vuevue/aiuseAIStream() composable + provide/inject
Sveltesvelte/aicreateAIStream() with reactive getters
Angularangular/aiAIStreamService injectable with signals
Vanilla / HTMLai/clientcreateAIStream() with subscribe callback

#Client Usage

On the client, a single hook connects to the WebSocket and manages all message state. Here is the React example. Vue, Svelte, and Angular have the same API:

TSX
import { useAIStream } from '@absolutejs/ai/react';

export const Chat = () => {
  const { messages, send, cancel, isStreaming } = useAIStream('/chat');

  return (
    <div>
      {messages.map((msg) => (
        <div key={msg.id}>{msg.content}</div>
      ))}
      <button onClick={() => send('Hello!')}>Send</button>
      {isStreaming && <button onClick={cancel}>Cancel</button>}
    </div>
  );
};

Current package surface

What ships today

@absolutejs/aiv0.0.47 · betaAInpmSource
16entry points195symbols

Import surface · click to copy

80 symbols
aiChatexportPermalinkSource
TS
aiChat
Exported from @absolutejs/ai

Outcomes

What you can build

Portable provider execution

Run provider-neutral chat and model traffic locally or across a trusted control plane while retaining host egress policy, tracing, aborts, and test transports.

Deterministic conversations

Serialize concurrent turns, expose queued state to every framework adapter, and create conversation branches without allowing later messages to overtake failures.

Hardening checklist

Production guidance

Bound every model streamUse structured SSE events, explicit token and duration ceilings, abort propagation, heartbeat-aware proxying, and host-controlled provider credentials.

Follow in order

Troubleshooting path

1
A stream ended unexpectedly
Inspect structured SSE terminal events first: complete, stopped, and error distinguish normal completion from budget limits, aborts, provider failures, and lookup failures.