JavaScript/TypeScript SDK
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.
Installation
npm install pluggedinkit-js
Quick Start
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 and configure the client:
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
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
// 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
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
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
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
const rag = await client.rag.query('What are our deployment procedures?');
console.log(rag.answer);
Query with Sources
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
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:
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:
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
# .env
PLUGGEDIN_API_KEY=your-api-key
PLUGGEDIN_BASE_URL=https://plugged.in
const client = new PluggedInClient({
apiKey: process.env.PLUGGEDIN_API_KEY!,
baseUrl: process.env.PLUGGEDIN_BASE_URL
});
Custom HTTP Client
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
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
// 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
CRITICAL: Heartbeats contain ONLY liveness data. Resource telemetry goes in metrics (separate channel). This separation is PAP’s zombie prevention superpower.
// 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
// 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 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:
<!-- 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:
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 for complete endpoint documentation.
Clipboard (Memory) Service
The Clipboard service provides persistent key-value storage for MCP tools and AI agents.
Named Access
// 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
// 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
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
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