openrag/sdks/typescript
2026-01-05 11:04:47 -05:00
..
src v1 endpoints for kf and settings 2025-12-19 03:31:54 -05:00
tests ingest status assertion 2025-12-19 06:35:22 -05:00
package-lock.json package.json 2025-12-18 16:48:00 -05:00
package.json python and ts sdks v0.1.2 2026-01-05 11:04:47 -05:00
README.md backend /v1 frontend /api/v1 routing, sdks port 3000 2025-12-19 01:50:29 -05:00
tsconfig.json package.json 2025-12-18 16:48:00 -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 OpenRAG frontend (default: http://localhost:3000)
// 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()

Provides additional helpers for convenience:

// Full event iteration
const stream = await client.chat.stream({ message: "Explain RAG" });
try {
  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}`);
} finally {
  stream.close();
}

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

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

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 (waits for completion by default)
const result = await client.documents.ingest({
  filePath: "./report.pdf",
});
console.log(`Status: ${result.status}`);
console.log(`Successful files: ${result.successful_files}`);

// Ingest without waiting (returns immediately with task_id)
const result = await client.documents.ingest({
  filePath: "./report.pdf",
  wait: false,
});
console.log(`Task ID: ${result.task_id}`);

// Poll for completion manually
const finalStatus = await client.documents.waitForTask(result.task_id);
console.log(`Status: ${finalStatus.status}`);
console.log(`Successful files: ${finalStatus.successful_files}`);

// 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(`Success: ${result.success}`);

Settings

// Get 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}`);

// Update settings
await client.settings.update({
  chunk_size: 1000,
  chunk_overlap: 200,
});

Knowledge Filters

Knowledge filters are reusable, named filter configurations that can be applied to chat and search operations.

// Create a knowledge filter
const result = await client.knowledgeFilters.create({
  name: "Technical Docs",
  description: "Filter for technical documentation",
  queryData: {
    query: "technical",
    filters: {
      document_types: ["application/pdf"],
    },
    limit: 10,
    scoreThreshold: 0.5,
  },
});
const filterId = result.id;

// Search for filters
const filters = await client.knowledgeFilters.search("Technical");
for (const filter of filters) {
  console.log(`${filter.name}: ${filter.description}`);
}

// Get a specific filter
const filter = await client.knowledgeFilters.get(filterId);

// Update a filter
await client.knowledgeFilters.update(filterId, {
  description: "Updated description",
});

// Delete a filter
await client.knowledgeFilters.delete(filterId);

// Use filter in chat
const response = await client.chat.create({
  message: "Explain the API",
  filterId,
});

// Use filter in search
const results = await client.search.query("API endpoints", { filterId });

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