npm package: @orchata-ai/sdk
Description: Official TypeScript SDK for Orchata
Author: Orchata Labs
Latest version: 1.3.0

<div align="center">
    <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://cdn.orchata.ai/img/orchata-logo-dark.svg">
    <img alt="Orchata Logo" src="https://cdn.orchata.ai/img/orchata-logo-light.svg">
    </picture>
</div>

<div align="center">

**Infrastructure for intelligent applications**

[![Website](https://img.shields.io/badge/Website-orchata.ai-blue?style=for-the-badge&logo=internet-explorer)](https://orchata.ai)
[![GitHub](https://img.shields.io/badge/GitHub-Repository-black?style=for-the-badge&logo=github)](https://github.com/orchata-ai)

</div>

## Orchata TypeScript SDK

The official TypeScript/JavaScript SDK for [Orchata](https://orchata.ai).

## Features

- **Type-safe** - Full TypeScript support with auto-completion
- **Universal** - Works with Node.js 18+, Deno, Bun, and browsers
- **Zero runtime dependencies** - Uses native `fetch` for HTTP requests
- **Modern** - ESM-first with CommonJS fallback
- **AI-ready** - Built-in tools for Vercel AI SDK v5+ integration

## Installation

```bash
# npm
npm install @orchata-ai/sdk

# pnpm
pnpm add @orchata-ai/sdk

# yarn
yarn add @orchata-ai/sdk

# bun
bun add @orchata-ai/sdk
```

### Optional: AI SDK Integration

If you want to use the Vercel AI SDK tools (`@orchata-ai/sdk/ai`), also install:

```bash
npm install ai@^5.0.0 zod@^3.22.0
```

## Quick Start

```typescript
import { Orchata } from '@orchata-ai/sdk';

const client = new Orchata({
  apiKey: 'oai_your_api_key' // Get one at https://app.orchata.ai
});

// Query your knowledge base
const { results } = await client.query({
  spaceIds: 'space_123',
  query: 'How do I reset my password?'
});

console.log(results[0].chunk.content);
```

## Usage

### Spaces

Spaces are knowledge bases that contain your documents.

```typescript
// List all spaces
const { spaces, total } = await client.spaces.list();

// Create a new space
const { space } = await client.spaces.create({
  name: 'Documentation',
  description: 'Product documentation and guides',
  icon: 'book'
});

// Get a specific space
const { space } = await client.spaces.get('space_123');

// Update a space
const { space } = await client.spaces.update('space_123', {
  name: 'Updated Name',
  description: 'New description'
});

// Delete a space
await client.spaces.delete('space_123');

// Get space usage limits
const limits = await client.spaces.getLimits('space_123');
console.log(`${limits.documents.current} / ${limits.documents.max} documents`);
```

### Documents

Documents are the content you want to query.

```typescript
// List documents in a space
const { documents } = await client.documents.list({
  spaceId: 'space_123'
});

// Upload a document (raw content)
const { document } = await client.documents.upload({
  spaceId: 'space_123',
  content: '# My Document\n\nSome markdown content...',
  filename: 'my-doc.md',
  metadata: { category: 'guides' }
});

// Upload a file (browser)
const { document } = await client.documents.uploadFile({
  spaceId: 'space_123',
  file: fileInput.files[0]
});

// Batch upload multiple documents
const result = await client.documents.batchUpload({
  spaceId: 'space_123',
  documents: [
    { filename: 'doc1.md', content: '# Doc 1\n\nContent...' },
    { filename: 'doc2.md', content: '# Doc 2\n\nContent...' },
  ]
});
console.log(`Uploaded: ${result.totalSuccessful}, Failed: ${result.totalFailed}`);

// Get processed content
const { content } = await client.documents.getContent('doc_123', 'space_123');

// Upsert a document (create or update by filename)
const { document, created } = await client.documents.upsert({
  spaceId: 'space_123',
  filename: 'readme.md',
  content: '# Updated README\n\nNew content...',
  metadata: { version: '2.0' }
});
console.log(created ? 'Created' : 'Updated', document.id);

// Append content to a document
const { document } = await client.documents.append('doc_123', {
  spaceId: 'space_123',
  content: '## New Section\n\nAdditional content...',
  separator: '\n\n---\n\n'  // Optional
});

// Get a document by filename
const doc = await client.documents.getByFilename({
  spaceId: 'space_123',
  filename: 'readme.md'
});
console.log(doc.content);

// Delete a document
await client.documents.delete('doc_123', 'space_123');
```

### Queries

Query your knowledge base using semantic search.

```typescript
// Simple query
const { results } = await client.query({
  spaceIds: 'space_123',
  query: 'How do I authenticate?'
});

// Query multiple spaces
const { results } = await client.query({
  spaceIds: ['space_123', 'space_456'],
  query: 'authentication',
  topK: 5  // Return top 5 results
});

// Filter by metadata
const { results } = await client.query({
  spaceIds: 'space_123',
  query: 'API reference',
  metadata: { category: 'docs' }
});

// Group results by space
const { groupedBySpace } = await client.query({
  spaceIds: ['space_123', 'space_456'],
  query: 'authentication',
  groupBySpace: true
});

// Process results
for (const result of results) {
  console.log(`Score: ${result.similarity}`);
  console.log(`Content: ${result.chunk.content}`);
  console.log(`Document: ${result.document.filename}`);
  console.log(`Space: ${result.space.name}`);
}
```

### Smart Query

Discover which spaces are most relevant for a query.

```typescript
// Find relevant spaces
const { relevantSpaces } = await client.smartQuery({
  query: 'How do I authenticate users?',
  maxSpaces: 3
});

// Use different relevance methods
const { relevantSpaces } = await client.smartQuery({
  query: 'authentication',
  relevanceMethod: 'hybrid',  // 'keyword', 'embedding', or 'hybrid'
  keywordWeight: 0.5
});

// Full workflow: discover then query
const { relevantSpaces } = await client.smartQuery({
  query: 'user authentication'
});

const { results } = await client.query({
  spaceIds: relevantSpaces.map(s => s.space.id),
  query: 'user authentication'
});
```

## Vercel AI SDK Integration

The SDK includes tools for the [Vercel AI SDK](https://sdk.vercel.ai/) v5+, allowing AI models to query your knowledge base.

### Installation

```bash
# Install the SDK with AI SDK dependencies
npm install @orchata-ai/sdk ai zod

# Or with specific versions
npm install @orchata-ai/sdk ai@^5.0.0 zod@^3.22.0
```

> **Note:** The AI tools require `ai` v5.0.0+ and `zod` v3.22.0+ as peer dependencies. These are optional - if you don't need AI SDK integration, you can use the core SDK without them.

### Basic Usage

```typescript
import { Orchata } from '@orchata-ai/sdk';
import { createOrchataTools } from '@orchata-ai/sdk/ai';
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';

const client = new Orchata({ apiKey: 'oai_xxx' });
const tools = createOrchataTools(client);

const { text } = await generateText({
  model: openai('gpt-4-turbo'),
  tools,
  prompt: 'What does our documentation say about authentication?'
});
```

### Available Tools

The `createOrchataTools` function creates these tools:

| Tool | Description |
|------|-------------|
| `queryKnowledge` | Search the knowledge base for relevant information |
| `findRelevantSpaces` | Discover which spaces are most relevant for a query |
| `listSpaces` | List all available knowledge spaces |
| `getDocumentContent` | Get the full content of a specific document |
| `uploadDocument` | Upload new content (disabled by default) |
| `createSpace` | Create a new space (disabled by default) |

### Simple Query Tool

For simple use cases, use the `createQueryTool` helper:

```typescript
import { Orchata } from '@orchata-ai/sdk';
import { createQueryTool } from '@orchata-ai/sdk/ai';
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';

const client = new Orchata({ apiKey: 'oai_xxx' });

// Create a tool that queries a specific space
const queryTool = createQueryTool(client, 'space_123');

const { text } = await generateText({
  model: openai('gpt-4-turbo'),
  tools: { query: queryTool },
  prompt: 'What is our refund policy?'
});
```

### Configuration Options

```typescript
const tools = createOrchataTools(client, {
  // Restrict which spaces the AI can access
  allowedSpaceIds: ['space_123', 'space_456'],

  // Default number of results (default: 5)
  defaultTopK: 10,

  // Enable document upload (default: false)
  enableUpload: true,

  // Enable space creation (default: false)
  enableSpaceCreation: true,
});
```

### With Streaming

```typescript
import { streamText } from 'ai';

const result = streamText({
  model: openai('gpt-4-turbo'),
  tools,
  prompt: 'Summarize our API documentation'
});

for await (const chunk of result.textStream) {
  process.stdout.write(chunk);
}
```

## Error Handling

The SDK throws typed errors for different scenarios:

```typescript
import {
  Orchata,
  OrchataError,
  AuthenticationError,
  NotFoundError,
  RateLimitError
} from '@orchata-ai/sdk';

try {
  const { results } = await client.query({
    spaceIds: 'space_123',
    query: 'test'
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof NotFoundError) {
    console.error('Space not found');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof OrchataError) {
    console.error(`API error: ${error.message} (${error.status})`);
  } else {
    throw error;
  }
}
```

### Error Types

| Error | Status | Description |
|-------|--------|-------------|
| `BadRequestError` | 400 | Invalid request parameters |
| `AuthenticationError` | 401 | Missing or invalid API key |
| `PermissionDeniedError` | 403 | Insufficient permissions |
| `NotFoundError` | 404 | Resource not found |
| `ConflictError` | 409 | Resource conflict |
| `UnprocessableEntityError` | 422 | Validation error |
| `RateLimitError` | 429 | Too many requests |
| `InternalServerError` | 5xx | Server error |
| `TimeoutError` | - | Request timeout |
| `ConnectionError` | - | Network connectivity issue |

## Configuration

```typescript
const client = new Orchata({
  // Required: Your API key
  apiKey: 'oai_xxx',

  // Optional: Custom base URL (default: https://api.orchata.ai)
  baseUrl: 'https://api.orchata.ai',

  // Optional: Request timeout in ms (default: 30000)
  timeout: 30000,

  // Optional: Custom fetch implementation
  fetch: customFetch
});
```

## Runtime Support

| Runtime | Supported | Notes |
|---------|-----------|-------|
| Node.js 18+ | ✅ | Uses native fetch |
| Node.js 16-17 | ⚠️ | Requires fetch polyfill |
| Deno | ✅ | Full support |
| Bun | ✅ | Full support |
| Browsers | ✅ | Modern browsers |
| Cloudflare Workers | ✅ | Full support |

## TypeScript

The SDK is written in TypeScript and provides full type definitions:

```typescript
import type {
  Space,
  Document,
  QueryParams,
  QueryResponse,
  QueryResultItem
} from '@orchata-ai/sdk';

// Types are automatically inferred
const { spaces } = await client.spaces.list();
//    ^? Space[]

const { results } = await client.query({ spaceIds: 'x', query: 'test' });
//    ^? QueryResultItem[]
```

## Contributing

Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.

## License

MIT License - see [LICENSE](LICENSE) for details.