npm package: @fluxsoft/fluxvector
Description: Official TypeScript SDK for FluxVector — 7-signal HyperSearch with TopK fusion, ColBERT, and anti-hallucination confidence
Author: FluxSoft Technologies, LLC
Latest version: 0.5.0

# @fluxsoft/fluxvector

**Semantic search in 4 lines. No OpenAI key. No embedding pipelines. Just text in, results out.**

```bash
npm install @fluxsoft/fluxvector
```

```typescript
import { FluxVector } from '@fluxsoft/fluxvector';

const fv = new FluxVector({ apiKey: 'fv_live_...' });
await fv.collections.create({ name: 'docs' });
await fv.vectors.upsert('docs', [{ id: '1', text: 'Your text here' }]);
const results = await fv.search('docs', 'find similar content');
```

That's it. FluxVector embeds your text server-side with multilingual models (e5-large, BGE-M3). No OpenAI API key, no embedding code, no vector math.

**vs Pinecone:** Pinecone requires you to generate embeddings yourself (usually via OpenAI at $0.13/1M tokens), then send raw vectors. FluxVector does it all in one call.

## Why FluxVector

- **Built-in embeddings** — send text, get search results. No external embedding API needed.
- **Hybrid search** — vector + BM25 keyword scoring combined, zero config.
- **Self-hostable** — one Docker image, your server, your data never leaves.
- **Zero runtime dependencies** — native `fetch`, works in Node 18+, Deno, Bun, edge runtimes.
- **TypeScript-first** — full types for every request and response.

## Install

```bash
npm install @fluxsoft/fluxvector  # or pnpm add / yarn add
```

## Quick Start

```typescript
import { FluxVector } from '@fluxsoft/fluxvector';

const fv = new FluxVector({ apiKey: 'fv_live_abc123' });

// Create a collection (embeddings handled automatically)
await fv.collections.create({ name: 'products' });

// Just send text — FluxVector embeds it for you
await fv.vectors.upsert('products', [
  { id: 'p1', text: 'Red shoes', metadata: { price: 89 } },
  { id: 'p2', text: 'Blue sneakers', metadata: { price: 120 } },
]);

// Semantic search — returns results ranked by meaning, not keywords
const results = await fv.search('products', 'comfortable shoes', {
  topK: 5,
  filter: { price: { $lt: 100 } },
});

for (const r of results) {
  console.log(`${r.id}: ${r.score.toFixed(2)} — ${r.text}`);
}
```

## Configuration

```typescript
const fv = new FluxVector({
  apiKey: 'fv_live_abc123',     // Required
  baseUrl: 'https://fluxvector.dev', // Default, configurable for self-hosted
  maxRetries: 3,                // Default: 3 (retries on 429 and 5xx)
  timeout: 30000,               // Default: 30s
});
```

## API Reference

### Collections

```typescript
// Create
const col = await fv.collections.create({
  name: 'products',
  dimension: 1024,        // Optional, default: auto
  metric: 'cosine',       // 'cosine' | 'euclidean' | 'dotproduct'
  description: 'Product catalog',
});

// List (cursor pagination)
const { data, has_more, next_cursor } = await fv.collections.list({ limit: 10 });

// Get
const col = await fv.collections.get('products');

// Delete
await fv.collections.delete('products');
```

### Vectors

```typescript
// Upsert (auto-chunks at 1000 vectors)
await fv.vectors.upsert('products', [
  { id: 'p1', text: 'Red shoes', metadata: { price: 89, category: 'footwear' } },
  { id: 'p2', values: [0.1, 0.2, ...], metadata: { price: 120 } },
]);

// Query
const { results, usage, took_ms } = await fv.vectors.query({
  collection: 'products',
  text: 'comfortable shoes',
  top_k: 10,
  filter: { category: { $eq: 'footwear' } },
  include_metadata: true,
  include_text: true,
});

// Fetch by IDs
const { vectors } = await fv.vectors.fetch('products', ['p1', 'p2']);

// Delete by IDs
await fv.vectors.delete('products', { ids: ['p1', 'p2'] });

// Delete by filter
await fv.vectors.delete('products', { filter: { category: { $eq: 'old' } } });
```

### Search

The top-level `fv.search()` is the simplest way to do semantic search:

```typescript
// Returns QueryResult[] directly
const results = await fv.search('products', 'comfortable shoes', {
  topK: 5,
  filter: { price: { $lt: 100 } },
  mode: 'hybrid',
});

// Each result: { id, score, text?, metadata? }
```

### Embeddings

```typescript
// Single text
const { embedding, dimension, model } = await fv.embeddings.create('hello world');

// Batch
const { embeddings, dimension, model } = await fv.embeddings.createBatch([
  'hello world',
  'goodbye world',
]);
```

### API Keys

```typescript
// Create
const key = await fv.apiKeys.create({ name: 'Production', env: 'live' });
console.log(key.key); // fv_live_xxx — shown only once

// List
const { data } = await fv.apiKeys.list();

// Update
await fv.apiKeys.update('key_123', { name: 'Renamed' });

// Delete
await fv.apiKeys.delete('key_123');
```

### Usage

```typescript
// Current period
const usage = await fv.usage.get();
// { plan, period_start, requests, embeddings, vectors_stored, collections }

// History
const { data } = await fv.usage.history({ days: 30 });
// [{ date, requests, embeddings, vectors }]
```

## Filter Operators

Filters use MongoDB-style operators on metadata fields:

| Operator | Description |
|----------|-------------|
| `$eq`    | Equal to |
| `$ne`    | Not equal to |
| `$gt`    | Greater than |
| `$gte`   | Greater than or equal |
| `$lt`    | Less than |
| `$lte`   | Less than or equal |
| `$in`    | In array |
| `$nin`   | Not in array |

```typescript
// Examples
{ price: { $lt: 100 } }
{ category: { $in: ['shoes', 'boots'] } }
{ status: { $ne: 'archived' } }
```

## Error Handling

All errors extend `FluxVectorError` with `status`, `code`, and optional `requestId`:

```typescript
import { FluxVector, AuthenticationError, NotFoundError, RateLimitError } from '@fluxsoft/fluxvector';

try {
  await fv.collections.get('missing');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Collection does not exist');
  } else if (err instanceof AuthenticationError) {
    console.log('Check your API key');
  } else if (err instanceof RateLimitError) {
    console.log(`Retry after ${err.retryAfter}s`);
  }
}
```

| Error Class | Status | When |
|-------------|--------|------|
| `AuthenticationError` | 401 | Invalid or missing API key |
| `NotFoundError` | 404 | Resource not found |
| `ValidationError` | 422 | Invalid request body |
| `RateLimitError` | 429 | Too many requests |
| `ServerError` | 5xx | Server-side error |
| `FluxVectorError` | any | Base class for all errors |

## Retry Behavior

The SDK automatically retries on 429 (rate limit) and 5xx (server errors):

- Default: 3 retries with exponential backoff (500ms, 1s, 2s + jitter)
- Respects `Retry-After` headers on 429 responses
- Non-retryable errors (400, 401, 404, 422) fail immediately
- Set `maxRetries: 0` to disable retries

## License

MIT