npm package: @piyapi/sdk
Description: Official TypeScript SDK for the PiyAPI Memory API
Author: PiyAPI Team
Latest version: 1.0.0

# @piyapi/sdk

Official TypeScript SDK for the PiyAPI Memory API. Store, retrieve, and semantically search text-based memories using vector embeddings.

## Installation

```bash
npm install @piyapi/sdk
# or
yarn add @piyapi/sdk
# or
pnpm add @piyapi/sdk
```

## Quick Start

```typescript
import { PiyAPIClient } from '@piyapi/sdk';

// Initialize the client
const client = new PiyAPIClient({
  apiKey: 'sk_live_your_api_key',
});

// Create a memory
const memory = await client.memories.create({
  content: 'Important meeting notes about Project X',
  namespace: 'meetings',
  metadata: { date: '2024-01-15', attendees: ['Alice', 'Bob'] },
});

// Search memories semantically
const results = await client.search.semantic('project X meeting notes', {
  limit: 10,
  minSimilarity: 0.7,
});

console.log(`Found ${results.count} relevant memories`);
```

## Configuration

```typescript
const client = new PiyAPIClient({
  // Required: Your API key
  apiKey: 'sk_live_your_api_key',
  
  // Optional: Custom base URL (defaults to https://api.piyapi.cloud)
  baseUrl: 'https://api.piyapi.cloud',
  
  // Optional: Request timeout in milliseconds (defaults to 30000)
  timeout: 30000,
  
  // Optional: Maximum retry attempts (defaults to 3)
  maxRetries: 3,
  
  // Optional: Initial retry delay in milliseconds (defaults to 1000)
  retryDelay: 1000,
  
  // Optional: Custom headers for all requests
  headers: {
    'X-Custom-Header': 'value',
  },
});
```

## Memory Operations

### Create a Memory

```typescript
const memory = await client.memories.create({
  content: 'The quick brown fox jumps over the lazy dog',
  namespace: 'examples',  // Optional, defaults to 'default'
  metadata: {             // Optional custom metadata
    source: 'documentation',
    tags: ['example', 'test'],
  },
  parentMemoryId: 'mem_abc123',  // Optional, for linked memories
});

console.log(`Created memory: ${memory.id}`);
```

### Get a Memory

```typescript
const memory = await client.memories.get('mem_abc123');
console.log(memory.content);
```

### List Memories

```typescript
// Get first page
const page1 = await client.memories.list({
  limit: 50,
  namespace: 'meetings',
});

console.log(`Total memories: ${page1.pagination.total}`);

// Get next page using cursor
if (page1.pagination.nextCursor) {
  const page2 = await client.memories.list({
    limit: 50,
    cursor: page1.pagination.nextCursor,
  });
}
```

### Iterate Over All Memories

```typescript
// Async iteration handles pagination automatically
for await (const memory of client.memories.iterate({ namespace: 'notes' })) {
  console.log(memory.content);
}
```

### Update a Memory

```typescript
const updated = await client.memories.update('mem_abc123', {
  content: 'Updated content',
  metadata: { revised: true },
});
```

### Delete a Memory

```typescript
await client.memories.delete('mem_abc123');
```

### Batch Operations

```typescript
// Create multiple memories
const createResult = await client.memories.batchCreate([
  { content: 'First memory', namespace: 'batch' },
  { content: 'Second memory', namespace: 'batch' },
  { content: 'Third memory', namespace: 'batch' },
]);

console.log(`Created: ${createResult.summary.successful}`);
console.log(`Failed: ${createResult.summary.failed}`);

// Delete multiple memories
const deleteResult = await client.memories.batchDelete([
  'mem_abc123',
  'mem_def456',
]);
```

### Memory Versioning

Track changes and rollback to previous versions:

```typescript
// Get version history
const history = await client.memories.getVersions('mem_abc123', { limit: 10 });
console.log(`Total versions: ${history.totalVersions}`);
for (const version of history.versions) {
  console.log(`Version ${version.version}: ${version.content.substring(0, 50)}...`);
}

// Get specific version
const version2 = await client.memories.getVersion('mem_abc123', 2);
console.log('Version 2 content:', version2.version.content);

// Rollback to previous version
const result = await client.memories.rollback('mem_abc123', 2);
console.log(`Rolled back to version ${result.rollback.restoredVersion}`);
```

### Related Memories

Get parent-child memory relationships:

```typescript
// Get related memories
const related = await client.memories.getRelated('mem_abc123', {
  direction: 'both',  // 'parent', 'children', or 'both'
  depth: 2,           // Traversal depth (1-5)
});

if (related.parent) {
  console.log('Parent:', related.parent.content);
}
console.log(`Children: ${related.children.length}`);
```

## Search Operations

### Semantic Search

Find memories by meaning, not just keywords:

```typescript
const results = await client.search.semantic('project deadline discussion', {
  namespace: 'meetings',           // Filter by namespace
  limit: 10,                       // Max results (1-100)
  minSimilarity: 0.7,              // Minimum similarity (0-1)
  startDate: new Date('2024-01-01'), // Filter by date range
  endDate: new Date('2024-12-31'),
  metadataFilters: {               // Filter by metadata
    category: 'work',
  },
});

for (const result of results.results) {
  console.log(`Score: ${result.similarity.toFixed(2)}`);
  console.log(`Content: ${result.memory.content}`);
}
```

### Hybrid Search

Combine semantic and keyword search:

```typescript
const results = await client.search.hybrid('project deadline', {
  semanticWeight: 0.7,  // Weight for semantic component
  keywordWeight: 0.3,   // Weight for keyword component (must sum to 1.0)
  namespace: 'projects',
  limit: 10,
});

for (const result of results.results) {
  console.log(`Hybrid Score: ${result.hybridScore.toFixed(2)}`);
  console.log(`  Semantic: ${result.semanticScore.toFixed(2)}`);
  console.log(`  Keyword: ${result.keywordScore.toFixed(2)}`);
}
```

## Usage Analytics

### Get Usage Dashboard

```typescript
const dashboard = await client.usage.getDashboard();

console.log(`Plan: ${dashboard.user.plan}`);
console.log(`Status: ${dashboard.user.status}`);

// Current usage
const { memories, searches, storage } = dashboard.currentUsage;
console.log(`Memories: ${memories.count}/${memories.limit} (${memories.percentage}%)`);
console.log(`Searches: ${searches.count}/${searches.limit} (${searches.percentage}%)`);
console.log(`Storage: ${storage.usedMB}/${storage.limitMB} MB`);

// Cost breakdown
console.log(`Total cost: $${dashboard.costBreakdown.total.toFixed(2)}`);

// Overage risk
if (dashboard.overageRisk.hasRisk) {
  console.log(`Warning: ${dashboard.overageRisk.resource} may exceed limit`);
}
```

### Get Cost Breakdown

```typescript
const costs = await client.usage.getCostBreakdown();

console.log(`Embedding: $${costs.embedding.cost.toFixed(2)} (${costs.embedding.percentage}%)`);
console.log(`Storage: $${costs.storage.cost.toFixed(2)} (${costs.storage.percentage}%)`);
console.log(`Search: $${costs.search.cost.toFixed(2)} (${costs.search.percentage}%)`);
console.log(`Total: $${costs.total.toFixed(2)}`);

// With date range
const monthCosts = await client.usage.getCostBreakdown(
  new Date('2024-01-01'),
  new Date('2024-01-31')
);
```

### Get Usage Trends

```typescript
const trends = await client.usage.getTrends(30); // Last 30 days

for (const day of trends) {
  console.log(`${day.date}: ${day.memories} memories, ${day.searches} searches, $${day.cost.toFixed(2)}`);
}
```

## Error Handling

The SDK provides typed errors for different scenarios:

```typescript
import {
  PiyAPIClient,
  PiyAPIError,
  AuthenticationError,
  ValidationError,
  NotFoundError,
  DuplicateContentError,
  StorageLimitError,
  RateLimitError,
  ServiceUnavailableError,
  TimeoutError,
  NetworkError,
} from '@piyapi/sdk';

try {
  await client.memories.create({ content: 'test' });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof ValidationError) {
    console.error('Invalid input:', error.details);
  } else if (error instanceof DuplicateContentError) {
    console.error('Content already exists:', error.existingMemoryId);
  } else if (error instanceof StorageLimitError) {
    console.error('Storage limit exceeded - upgrade your plan');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited - retry after ${error.retryAfter} seconds`);
  } else if (error instanceof NotFoundError) {
    console.error('Memory not found');
  } else if (error instanceof ServiceUnavailableError) {
    console.error('Service temporarily unavailable');
  } else if (error instanceof TimeoutError) {
    console.error('Request timed out');
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof PiyAPIError) {
    console.error(`API error: ${error.code} - ${error.message}`);
  }
}
```

## Automatic Retry

The SDK automatically retries failed requests with exponential backoff:

- **Rate limiting (429)**: Waits for the `Retry-After` duration
- **Network errors**: Retries with exponential backoff
- **Timeouts**: Retries with exponential backoff
- **Server errors (5xx)**: Retries with exponential backoff

Authentication errors (401) are never retried.

Configure retry behavior:

```typescript
const client = new AIMemoryClient({
  apiKey: 'sk_live_your_api_key',
  maxRetries: 5,      // Maximum retry attempts
  retryDelay: 2000,   // Initial delay (doubles each retry)
});
```

## TypeScript Support

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

```typescript
import type {
  Memory,
  CreateMemoryInput,
  SearchResult,
  HybridSearchResult,
  UsageDashboard,
  CostBreakdown,
} from '@piyapi/sdk';

// All types are available for use
const input: CreateMemoryInput = {
  content: 'Typed content',
  namespace: 'typed',
};
```

## Requirements

- Node.js 18.0.0 or higher
- TypeScript 4.7.0 or higher (optional, for type definitions)

## License

MIT