> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plugged.in/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript/TypeScript SDK

> Official JavaScript/TypeScript SDK for the Plugged.in Library API

# JavaScript/TypeScript SDK

[![npm version](https://badge.fury.io/js/pluggedinkit-js.svg)](https://www.npmjs.com/package/pluggedinkit-js)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

The official JavaScript/TypeScript SDK for interacting with Plugged.in's Library API. Easily manage documents, create AI-generated content, and perform RAG queries with full type safety.

<CardGroup cols={2}>
  <Card title="NPM Package" icon="npm" href="https://www.npmjs.com/package/pluggedinkit-js">
    View on NPM Registry
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/VeriTeknik/pluggedinkit-js">
    Source code and examples
  </Card>
</CardGroup>

## Installation

<Tabs>
  <Tab title="npm">
    ```bash theme={null}
    npm install pluggedinkit-js
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add pluggedinkit-js
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add pluggedinkit-js
    ```
  </Tab>
</Tabs>

## Quick Start

```typescript theme={null}
import { PluggedInClient } from 'pluggedinkit-js';

// Initialize the client
const client = new PluggedInClient({
  apiKey: 'your-api-key',
  // baseUrl defaults to https://plugged.in
});

// List documents
const documents = await client.documents.list({
  limit: 10,
  source: 'all'
});

// Search documents
const results = await client.documents.search('machine learning', {
  tags: ['ai', 'ml']
});

// Query RAG
const ragResponse = await client.rag.query('What are the latest updates?');
console.log(ragResponse.answer);
console.log('Matched documents:', ragResponse.documentIds);
```

## Authentication

Get your API key from your [Plugged.in Profile](https://plugged.in/profile/settings) and configure the client:

```typescript theme={null}
const client = new PluggedInClient({
  apiKey: process.env.PLUGGEDIN_API_KEY,
  baseUrl: process.env.PLUGGEDIN_BASE_URL || 'https://plugged.in',
  timeout: 60000, // 60 seconds
  maxRetries: 5,
  debug: true // Enable debug logging
});

// Update API key at runtime
client.setApiKey('new-api-key');
```

## Core Features

### Document Management

#### List Documents

```typescript theme={null}
import { DocumentFilters, DocumentSource, SortOrder } from 'pluggedinkit-js';

const filters: DocumentFilters = {
  source: 'ai_generated',
  tags: ['report', 'analysis'],
  sort: 'date_desc',
  limit: 20,
  offset: 0,
  category: 'documentation',
  dateFrom: '2024-01-01T00:00:00Z',
  modelProvider: 'anthropic'
};

const response = await client.documents.list(filters);

console.log(`Found ${response.total} documents`);
response.documents.forEach(doc => {
  console.log(`- ${doc.title} (${doc.fileSize} bytes)`);
});
```

#### Get Document

```typescript theme={null}
// Get metadata only
const doc = await client.documents.get('document-id');

// Get document with content and version history
const fullDoc = await client.documents.get('document-id', {
  includeContent: true,
  includeVersions: true
});

console.log(fullDoc.content);
console.log(`Version: ${fullDoc.version}`);
```

#### Search Documents

```typescript theme={null}
const searchResults = await client.documents.search('quarterly report', {
  modelProvider: 'anthropic',
  dateFrom: '2024-01-01T00:00:00Z',
  tags: ['finance', 'q4']
}, 10, 0);

searchResults.results.forEach(result => {
  console.log(`${result.title}`);
  console.log(`  Relevance: ${result.relevanceScore}`);
  console.log(`  Snippet: ${result.snippet}`);
});
```

#### Create AI-Generated Document

```typescript theme={null}
const newDoc = await client.documents.create(
  'API Integration Guide',
  '# API Integration Guide\n\n## Introduction\n\n...',
  {
    format: 'md',
    category: 'documentation',
    tags: ['api', 'integration', 'guide'],
    model: {
      name: 'claude-3-opus',
      provider: 'anthropic',
      version: '20240229'
    },
    prompt: 'Create a comprehensive API integration guide',
    context: 'User requested comprehensive API documentation',
    updateReason: 'Initial creation',
    changesFromPrompt: 'Created new guide as requested',
    changeSummary: 'New comprehensive API integration guide',
    conversationContext: [
      { role: 'user', content: 'Create an API guide' },
      { role: 'assistant', content: "I'll create a comprehensive guide..." }
    ],
    sourceDocuments: ['doc-123', 'doc-456'],
    visibility: 'workspace',
    sessionId: 'session-789',
    generationParams: {
      temperature: 0.7,
      maxTokens: 4000,
      topP: 0.9
    },
    // Dynamic fields - add any custom metadata
    customField: 'Any custom value',
    projectMetadata: {
      team: 'engineering',
      version: '1.0.0'
    }
  }
);

console.log(`Created document: ${newDoc.id}`);
// Access all metadata including custom fields
console.log('All metadata:', newDoc.aiMetadata);
```

#### Update Document

```typescript theme={null}
const updateResult = await client.documents.update('document-id', {
  operation: 'append',
  content: '\n\n## New Section\n\nAdditional content here.',
  metadata: {
    changeSummary: 'Added implementation details section',
    model: {
      name: 'gpt-4',
      provider: 'openai',
      version: '0613'
    },
    updateReason: 'Added new section on authentication',
    changesFromPrompt: 'User requested additional auth details',
    prompt: 'Add a section about OAuth 2.0 authentication',
    lastUpdatedBy: {
      name: 'gpt-4',
      provider: 'openai',
      version: '0613'
    },
    lastUpdateTimestamp: '2024-01-15T10:30:00Z',
    conversationContext: [
      { role: 'user', content: 'Add OAuth 2.0 section' },
      { role: 'assistant', content: 'Adding authentication details...' }
    ],
    // Custom metadata fields
    customUpdateMetadata: {
      reviewedBy: 'security-team',
      complianceCheck: 'passed'
    }
  }
});

console.log(`Document updated to version ${updateResult.version}`);
```

### RAG Operations

#### Simple Query

```typescript theme={null}
const rag = await client.rag.query('What are our deployment procedures?');
console.log(rag.answer);
```

#### Query with Sources

```typescript theme={null}
const { answer, sources } = await client.rag.queryWithSources(
  'Explain the authentication flow'
);

console.log('Answer:', answer);
console.log('Sources:');
sources.forEach(source => {
  console.log(`- ${source.name} (${source.id})`);
});
```

#### Find Relevant Documents

```typescript theme={null}
const matches = await client.rag.findRelevantDocuments(
  'user authentication',
  undefined,
  5 // Top 5 documents
);

matches.forEach(match => {
  console.log(`- ${match.name} (${match.id})`);
});

// Storage statistics (requires your Plugged.in user id)
const stats = await client.rag.getStorageStats('user-id-from-dashboard');
console.log(`Indexed documents: ${stats.documentsCount}`);
```

### File Uploads

> **Important:** Direct file uploads are no longer exposed via the public API.
> The `client.uploads` helpers now throw descriptive errors so existing code
> fails fast. Use the Plugged.in web interface or the forthcoming ingestion
> workflow for binary files. AI-generated content can still be created with
> `client.documents.create` or `client.uploads.uploadDocument`.

## Error Handling

The SDK provides typed error classes for better error handling:

```typescript theme={null}
import {
  PluggedInError,
  AuthenticationError,
  RateLimitError,
  NotFoundError,
  ValidationError
} from 'pluggedinkit-js';

try {
  const doc = await client.documents.get('invalid-id');
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key - please check your credentials');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
    // Implement retry logic
  } else if (error instanceof NotFoundError) {
    console.error('Document not found');
  } else if (error instanceof ValidationError) {
    console.error('Validation error:', error.details);
  } else if (error instanceof PluggedInError) {
    console.error(`API error: ${error.message}`);
  }
}
```

## TypeScript Support

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

```typescript theme={null}
import type {
  Document,
  DocumentFilters,
  DocumentSource,
  DocumentVisibility,
  DocumentCategory,
  RagResponse,
  UploadMetadata,
  ModelInfo,
  UpdateOperation
} from 'pluggedinkit-js';

// All types are fully documented with JSDoc comments
const filters: DocumentFilters = {
  source: 'ai_generated',
  tags: ['important'],
  sort: 'date_desc',
  limit: 10
};

// TypeScript will provide autocompletion and type checking
const doc: Document = await client.documents.get('id');
console.log(doc.title); // Type-safe property access
```

## Advanced Configuration

### Environment Variables

```bash theme={null}
# .env
PLUGGEDIN_API_KEY=your-api-key
PLUGGEDIN_BASE_URL=https://plugged.in
```

```typescript theme={null}
const client = new PluggedInClient({
  apiKey: process.env.PLUGGEDIN_API_KEY!,
  baseUrl: process.env.PLUGGEDIN_BASE_URL
});
```

### Custom HTTP Client

```typescript theme={null}
const client = new PluggedInClient({
  apiKey: 'your-api-key',
  baseUrl: 'https://plugged.in',
  timeout: 120000, // 2 minutes
  maxRetries: 10,
  debug: process.env.NODE_ENV === 'development',
  headers: {
    'X-Custom-Header': 'value'
  }
});
```

## PAP Agents

The SDK provides full support for managing PAP (Plugged.in Agent Protocol) agents:

### Creating Agents

```typescript theme={null}
const result = await client.agents.create({
  name: 'my-agent',
  description: 'My autonomous PAP agent',
  resources: {
    cpu_request: '100m',
    memory_request: '256Mi',
    cpu_limit: '1000m',
    memory_limit: '1Gi'
  }
});

console.log(`Agent created: ${result.agent.uuid}`);
console.log(`DNS: ${result.agent.dns_name}`); // my-agent.is.plugged.in
```

### Listing and Managing Agents

```typescript theme={null}
// List all agents
const agents = await client.agents.list();

// Get agent details
const details = await client.agents.get(agentId);
console.log(details.recentHeartbeats);
console.log(details.recentMetrics);
console.log(details.lifecycleEvents);

// Export agent data
const exportData = await client.agents.export(agentId, {
  include_telemetry: true,
  telemetry_limit: 1000
});

// Delete agent
await client.agents.delete(agentId);
```

### Heartbeats and Metrics

<Warning>
  **CRITICAL**: Heartbeats contain ONLY liveness data. Resource telemetry goes in metrics (separate channel). This separation is PAP's zombie prevention superpower.
</Warning>

```typescript theme={null}
// Send heartbeat (liveness only)
await client.agents.heartbeat(agentId, {
  mode: 'IDLE', // or 'EMERGENCY', 'SLEEP'
  uptime_seconds: process.uptime()
});

// Send metrics (resource telemetry)
await client.agents.metrics(agentId, {
  cpu_percent: 12.5,
  memory_mb: 128,
  requests_handled: 45,
  custom_metrics: {
    queue_depth: 3,
    cache_hit_rate: 0.85
  }
});
```

### Agent States

Agents follow the PAP lifecycle state machine:

```
NEW → PROVISIONED → ACTIVE ↔ DRAINING → TERMINATED
                       ↓ (error)
                     KILLED
```

```typescript theme={null}
// Poll until agent is active
while (true) {
  const details = await client.agents.get(agentId);
  if (details.agent.state === 'ACTIVE') {
    console.log('Agent is ready!');
    break;
  }
  await new Promise(resolve => setTimeout(resolve, 5000));
}
```

See [PAP Agents Documentation](/agents/overview) for complete details on the Plugged.in Agent Protocol.

## Rate Limiting

The SDK automatically handles rate limiting with exponential backoff:

* **API Endpoints**: 60 requests per minute
* **Document Search**: 10 requests per hour for AI document creation
* **RAG Queries**: Subject to plan limits

## Browser Support

The SDK works in both Node.js and browser environments:

```html theme={null}
<!-- Browser usage with CDN -->
<script src="https://unpkg.com/pluggedinkit-js/dist/browser.js"></script>
<script>
  const client = new PluggedInKit.PluggedInClient({
    apiKey: 'your-api-key'
  });
</script>
```

## Examples

Complete working examples are available in the [GitHub repository](https://github.com/VeriTeknik/pluggedinkit-js/tree/main/examples):

* [Basic Usage](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/basic.ts)
* [Document Management](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/documents.ts)
* [RAG Queries](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/rag.ts)
* [File Upload (deprecated)](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/upload.ts)
* [Error Handling](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/errors.ts)
* [Browser Usage](https://github.com/VeriTeknik/pluggedinkit-js/blob/main/examples/browser.html)

## API Reference

### Client Options

| Option       | Type    | Default              | Description                     |
| ------------ | ------- | -------------------- | ------------------------------- |
| `apiKey`     | string  | required             | Your Plugged.in API key         |
| `baseUrl`    | string  | `https://plugged.in` | API base URL                    |
| `timeout`    | number  | `60000`              | Request timeout in milliseconds |
| `maxRetries` | number  | `5`                  | Maximum retry attempts          |
| `debug`      | boolean | `false`              | Enable debug logging            |

### Document Methods

| Method                                  | Description                          |
| --------------------------------------- | ------------------------------------ |
| `list(filters)`                         | List documents with optional filters |
| `get(id, options)`                      | Get a specific document              |
| `search(query, filters, limit, offset)` | Search documents                     |
| `create(title, content, metadata)`      | Create a new document                |
| `update(id, request)`                   | Update an existing document          |
| `delete(id)`                            | Delete a document                    |

### RAG Methods

| Method                                 | Description                                                  |
| -------------------------------------- | ------------------------------------------------------------ |
| `query(question)`                      | Returns `RagResponse` with answer, sources, and document IDs |
| `queryWithSources(question)`           | Returns answer plus structured source metadata               |
| `findRelevantDocuments(query, limit?)` | Returns matched document references                          |
| `getStorageStats(userId)`              | Fetch aggregated storage metrics for the authenticated user  |
| `checkAvailability()`                  | Lightweight availability check                               |

### Upload Methods

All binary upload helpers now throw descriptive errors because the public API no longer exposes direct upload endpoints. Use the web interface or upcoming ingestion pipeline for file uploads.

### Clipboard Methods

| Method            | Description                      |
| ----------------- | -------------------------------- |
| `list()`          | List all clipboard entries       |
| `get(filters)`    | Get entry by name or index       |
| `getByName(name)` | Get entry by name                |
| `getByIndex(idx)` | Get entry by stack index         |
| `set(request)`    | Create or update named entry     |
| `push(request)`   | Push value to indexed stack      |
| `pop()`           | Pop and remove most recent entry |
| `delete(request)` | Delete specific entry            |
| `clearAll()`      | Delete all entries               |

### Agent Methods

| Method                     | Description                                                   |
| -------------------------- | ------------------------------------------------------------- |
| `list()`                   | List all PAP agents for the active profile                    |
| `create(request)`          | Create and deploy a new agent                                 |
| `get(agentId)`             | Get detailed agent information including telemetry            |
| `delete(agentId)`          | Terminate and delete an agent                                 |
| `export(agentId, options)` | Export complete agent data including telemetry history        |
| `heartbeat(agentId, data)` | Submit heartbeat (liveness only - zombie prevention)          |
| `metrics(agentId, data)`   | Submit metrics (resource telemetry - separate from heartbeat) |

See [PAP Agents API Reference](/agents/api-reference) for complete endpoint documentation.

## Clipboard (Memory) Service

The Clipboard service provides persistent key-value storage for MCP tools and AI agents.

### Named Access

```typescript theme={null}
// Set a named entry
await client.clipboard.set({
  name: 'user_preferences',
  value: JSON.stringify({ theme: 'dark', lang: 'en' }),
  contentType: 'application/json',
  encoding: 'utf-8',
  visibility: 'private',
  ttlSeconds: 86400  // 24 hours
});

// Get by name
const entry = await client.clipboard.getByName('user_preferences');
console.log('Preferences:', JSON.parse(entry.value));

// Delete by name
await client.clipboard.delete({ name: 'user_preferences' });
```

### Indexed (Stack) Access

```typescript theme={null}
// Push to stack
await client.clipboard.push({
  value: 'Step 1 result',
  contentType: 'text/plain'
});

await client.clipboard.push({
  value: 'Step 2 result',
  contentType: 'text/plain'
});

// Get by index (0 = most recent)
const latest = await client.clipboard.getByIndex(0);
console.log('Latest:', latest.value); // "Step 2 result"

// Pop removes and returns the most recent
const popped = await client.clipboard.pop();
console.log('Popped:', popped.value); // "Step 2 result"
```

### List All Entries

```typescript theme={null}
const entries = await client.clipboard.list();
for (const entry of entries) {
  console.log(`${entry.name || `idx:${entry.idx}`}: ${entry.value}`);
  console.log(`  Expires: ${entry.expiresAt}`);
}
```

### TypeScript Types

```typescript theme={null}
import type {
  ClipboardEntry,
  ClipboardSetRequest,
  ClipboardPushRequest,
  ClipboardGetFilters,
  ClipboardDeleteRequest,
  ClipboardSource,
  ClipboardEncoding,
  ClipboardVisibility
} from 'pluggedinkit-js';

import { DEFAULT_CLIPBOARD_SOURCE } from 'pluggedinkit-js';

// All types are fully documented
const request: ClipboardSetRequest = {
  name: 'cache_key',
  value: 'cached data',
  contentType: 'text/plain',
  encoding: 'utf-8',      // 'utf-8' | 'base64' | 'hex'
  visibility: 'private',  // 'private' | 'workspace' | 'public'
  ttlSeconds: 3600
};

// ClipboardSource tracks where entries originate
type ClipboardSource = 'ui' | 'sdk' | 'mcp';

// The SDK automatically sets source to 'sdk' for all entries you create.
// DEFAULT_CLIPBOARD_SOURCE is 'ui' for backward compatibility with older entries.
```

## Support

* **NPM Package**: [https://www.npmjs.com/package/pluggedinkit-js](https://www.npmjs.com/package/pluggedinkit-js)
* **GitHub Issues**: [Report bugs and request features](https://github.com/VeriTeknik/pluggedinkit-js/issues)
* **Documentation**: [https://docs.plugged.in](https://docs.plugged.in)
* **Discord**: [Join our community](https://discord.gg/pluggedin)
