openrag/sdks/typescript
2025-12-16 02:04:31 -05:00
..
src v0 sdks wip 2025-12-16 02:04:31 -05:00
tests v0 sdks wip 2025-12-16 02:04:31 -05:00
README.md v0 sdks wip 2025-12-16 02:04:31 -05:00
tsup.config.ts v0 sdks wip 2025-12-16 02:04:31 -05:00
vitest.config.ts v0 sdks wip 2025-12-16 02:04:31 -05:00

OpenRAG TypeScript SDK

Official TypeScript/JavaScript SDK for the OpenRAG API.

Installation

npm install openrag-sdk
# or
yarn add openrag-sdk
# or
pnpm add openrag-sdk

Quick Start

import { OpenRAGClient } from "openrag-sdk";

// Client auto-discovers OPENRAG_API_KEY and OPENRAG_URL from environment
const client = new OpenRAGClient();

// Simple chat
const response = await client.chat.create({ message: "What is RAG?" });
console.log(response.response);
console.log(`Chat ID: ${response.chatId}`);

Configuration

The SDK can be configured via environment variables or constructor arguments:

Environment Variable Constructor Option Description
OPENRAG_API_KEY apiKey API key for authentication (required)
OPENRAG_URL baseUrl Base URL for the API (default: http://localhost:8080)
// Using environment variables
const client = new OpenRAGClient();

// Using explicit arguments
const client = new OpenRAGClient({
  apiKey: "orag_...",
  baseUrl: "https://api.example.com",
});

Chat

Non-streaming

const response = await client.chat.create({ message: "What is RAG?" });
console.log(response.response);
console.log(`Chat ID: ${response.chatId}`);

// Continue conversation
const followup = await client.chat.create({
  message: "Tell me more",
  chatId: response.chatId,
});

Streaming with create({ stream: true })

Returns an async iterator directly:

let chatId: string | null = null;
for await (const event of await client.chat.create({
  message: "Explain RAG",
  stream: true,
})) {
  if (event.type === "content") {
    process.stdout.write(event.delta);
  } else if (event.type === "sources") {
    for (const source of event.sources) {
      console.log(`\nSource: ${source.filename}`);
    }
  } else if (event.type === "done") {
    chatId = event.chatId;
  }
}

Streaming with stream() (Disposable pattern)

Provides additional helpers for convenience:

// Full event iteration with Disposable pattern
{
  using stream = await client.chat.stream({ message: "Explain RAG" });
  for await (const event of stream) {
    if (event.type === "content") {
      process.stdout.write(event.delta);
    }
  }

  // Access aggregated data after iteration
  console.log(`\nChat ID: ${stream.chatId}`);
  console.log(`Full text: ${stream.text}`);
  console.log(`Sources: ${stream.sources}`);
}

// Just text deltas
{
  using stream = await client.chat.stream({ message: "Explain RAG" });
  for await (const text of stream.textStream) {
    process.stdout.write(text);
  }
}

// Get final text directly
{
  using stream = await client.chat.stream({ message: "Explain RAG" });
  const text = await stream.finalText();
  console.log(text);
}

Conversation History

// List all conversations
const conversations = await client.chat.list();
for (const conv of conversations.conversations) {
  console.log(`${conv.chatId}: ${conv.title}`);
}

// Get specific conversation with messages
const conversation = await client.chat.get(chatId);
for (const msg of conversation.messages) {
  console.log(`${msg.role}: ${msg.content}`);
}

// Delete conversation
await client.chat.delete(chatId);
// Basic search
const results = await client.search.query("document processing");
for (const result of results.results) {
  console.log(`${result.filename} (score: ${result.score})`);
  console.log(`  ${result.text.slice(0, 100)}...`);
}

// Search with filters
const results = await client.search.query("API documentation", {
  filters: {
    data_sources: ["api-docs.pdf"],
    document_types: ["application/pdf"],
  },
  limit: 5,
  scoreThreshold: 0.5,
});

Documents

// Ingest a file (Node.js)
const result = await client.documents.ingest({
  filePath: "./report.pdf",
});
console.log(`Document ID: ${result.document_id}`);
console.log(`Chunks: ${result.chunks}`);

// Ingest from File object (browser)
const file = new File([...], "report.pdf");
const result = await client.documents.ingest({
  file,
  filename: "report.pdf",
});

// Delete a document
const result = await client.documents.delete("report.pdf");
console.log(`Deleted ${result.deleted_chunks} chunks`);

Settings

const settings = await client.settings.get();
console.log(`LLM Provider: ${settings.agent.llm_provider}`);
console.log(`LLM Model: ${settings.agent.llm_model}`);
console.log(`Embedding Model: ${settings.knowledge.embedding_model}`);

Error Handling

import {
  OpenRAGError,
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  ServerError,
} from "openrag-sdk";

try {
  const response = await client.chat.create({ message: "Hello" });
} catch (e) {
  if (e instanceof AuthenticationError) {
    console.log(`Invalid API key: ${e.message}`);
  } else if (e instanceof NotFoundError) {
    console.log(`Resource not found: ${e.message}`);
  } else if (e instanceof ValidationError) {
    console.log(`Invalid request: ${e.message}`);
  } else if (e instanceof RateLimitError) {
    console.log(`Rate limited: ${e.message}`);
  } else if (e instanceof ServerError) {
    console.log(`Server error: ${e.message}`);
  } else if (e instanceof OpenRAGError) {
    console.log(`API error: ${e.message} (status: ${e.statusCode})`);
  }
}

Browser Support

This SDK works in both Node.js and browser environments. The main difference is file ingestion:

  • Node.js: Use filePath option
  • Browser: Use file option with a File or Blob object

TypeScript

This SDK is written in TypeScript and provides full type definitions. All types are exported from the main module:

import type {
  ChatResponse,
  StreamEvent,
  SearchResponse,
  IngestResponse,
  SettingsResponse,
} from "openrag-sdk";

License

MIT