@atlas/ai#
Unified AI provider abstraction with chat, embeddings, streaming, RAG, and agent support. Zero external dependencies -- uses fetch for all API calls.
Exports#
Provider:
createProvider({ provider, key?, baseUrl? })→AiProvider— provider is"openai" | "anthropic" | "ollama"AiProviderexposes.chat(opts),.chatStream(opts),.embed(opts)
Chat:
createConversation(system?)→ConversationaddMessage(conv, msg)→Conversation(immutable)send(provider, conv, content, opts?)→{ conversation, response }userMessage,assistantMessage,systemMessage,toolMessage
Stream:
parseSSE(text)→ eventscollectStream(stream)→ChatResponsestreamToSse(stream)→ReadableStream(for HTTP responses)
Embeddings:
embed(provider, inputs)→number[][]— inputs:string | string[]cosineSimilarity(a, b)→numbercreateVectorStore()→{ add, search, size }
Structured / tools:
generateJson<T>(provider, prompt, opts?)→Ttool(name, description, parameters)→ToolDef
RAG:
index(rag, id, text)→Promise<void>—rag = { ai, store, topK? }query(rag, question)→{ answer, sources }
Agents:
runAgent({ ai, system?, tools, maxIterations? }, prompt)→ result
Server pipe:
withAi(provider)→PipeFn— addsprovidertoconn.assigns.ai
Types#
ProviderConfig,Message,ChatOptions,ChatResponse,StreamChunkEmbedOptions,EmbedResponse,ToolDef,ToolCallConversation,VectorStore,VectorEntry,RagOptionsAgentTool,AgentOptions
Provider setup#
import { createProvider } from "@atlas/ai"
const openai = createProvider({ provider: "openai", key: process.env.OPENAI_API_KEY! })
const anthropic = createProvider({ provider: "anthropic", key: process.env.ANTHROPIC_API_KEY! })
const ollama = createProvider({ provider: "ollama" }) // local, no key needed
Chat#
import { createConversation, send } from "@atlas/ai"
const conv = createConversation("You are a helpful assistant")
const { conversation, response } = await send(openai, conv, "Hello!")
// conversation tracks full message history immutably
Streaming#
import { collectStream, streamToSse } from "@atlas/ai"
const stream = openai.chatStream({ messages: [{ role: "user", content: "Hi" }] })
const full = await collectStream(stream) // collect into ChatResponse
const sse = streamToSse(stream) // convert to ReadableStream for HTTP responses
Embeddings and vector search#
import { embed, cosineSimilarity, createVectorStore } from "@atlas/ai"
const vectors = await embed(openai, ["hello", "world"])
const score = cosineSimilarity(vectors[0]!, vectors[1]!)
const store = createVectorStore()
store.add("id1", vectors[0]!, { text: "hello" })
const results = store.search(vectors[1]!, 5) // top 5 nearest
Structured output#
import { generateJson, tool } from "@atlas/ai"
const user = await generateJson<{ name: string }>(openai, "Generate a user")
const searchTool = tool("search", "Search the web", { type: "object", properties: { query: { type: "string" } } })
RAG#
import { index, query, createVectorStore, createProvider } from "@atlas/ai"
const store = createVectorStore()
const rag = { ai: openai, store, topK: 3 }
await index(rag, "doc1", "Document text here...")
const result = await query(rag, "What does the document say?")
// result.answer, result.sources
Agent loop#
import { runAgent, tool } from "@atlas/ai"
const result = await runAgent({
ai: openai,
system: "You are a calculator assistant",
tools: [{
definition: tool("multiply", "Multiply two numbers", {
type: "object",
properties: { a: { type: "number" }, b: { type: "number" } },
}),
handler: async (args) => String((args.a as number) * (args.b as number)),
}],
maxIterations: 5,
}, "What is 6 times 7?")
Server pipe#
import { withAi } from "@atlas/ai"
// Add AI provider to conn.assigns.ai in a server pipeline
const aiPipe = withAi(openai)
Architecture#
provider/-- Provider interface and adapters (openai, anthropic, ollama)chat/-- Immutable conversation managementstream/-- SSE parsing, stream collection, SSE response generationembeddings/-- Vector embeddings and in-memory vector storestructured/-- JSON mode and tool definitionsrag/-- Retrieval-augmented generation pipelineagents/-- Tool-use agent loop with iteration limitspipes/-- Server middleware integration
Dependencies#
@atlas/server— only for thewithAipipe; the rest of the package stands alone.- External: none. All provider calls go through
fetch.
Testing#
All tests use mock providers. No real API calls.
bun test packages/ai/