Skip to main content

JavaScript/TypeScript SDK

npm version License: 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.

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

OptionTypeDefaultDescription
apiKeystringrequiredYour Plugged.in API key
baseUrlstringhttps://plugged.inAPI base URL
timeoutnumber60000Request timeout in milliseconds
maxRetriesnumber5Maximum retry attempts
debugbooleanfalseEnable debug logging

Document Methods

MethodDescription
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

MethodDescription
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

MethodDescription
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

MethodDescription
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