npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shinrag/sdk

v0.6.0

Published

Official SDK for ShinRAG - Enterprise RAG Platform

Downloads

16

Readme

@shinrag/sdk

Official TypeScript/JavaScript SDK for the ShinRAG Enterprise RAG Platform. Provides full API coverage for agents, pipelines, indexes, integrations, widgets, usage/billing, cost tracking, and more.

Installation

npm install @shinrag/sdk
# or
pnpm add @shinrag/sdk
# or
yarn add @shinrag/sdk

Requirements: Node.js 18+ (uses native fetch). No runtime dependencies.

Quick Start

import { ShinRAGClient } from '@shinrag/sdk';

const client = new ShinRAGClient({
  apiKey: 'sk_your_api_key_here',
  organizationId: 'org_123', // Optional: for org-scoped resources
});

// Query a pipeline
const result = await client.executePipeline('pipeline-id', {
  input: 'What are the key features mentioned in the documentation?',
});
console.log(result.output);
console.log('Tokens used:', result.totalTokensUsed);

// Query an agent
const agentResult = await client.queryAgent('agent-id', {
  question: 'What are the key features?',
  maxResults: 5,
});
console.log(agentResult.answer);
console.log('Sources:', agentResult.sources);

// Search an index
const indexResult = await client.queryIndex({
  indexId: 'index-id',
  queryText: 'What are the key features?',
  limit: 10,
});
console.log(indexResult.results);

API Reference

ShinRAGClient

The main client class for interacting with the ShinRAG API.

Constructor

new ShinRAGClient(config: ShinRAGClientConfig)

Parameters:

  • config.apiKey (string, required): Your API key (must start with sk_)
  • config.baseUrl (string, optional): Base URL for the API (defaults to https://api.shinrag.com/v1)
  • config.organizationId (string, optional): Organization ID for accessing org-scoped resources

Agents

// List all agents
const agents = await client.listAgents();

// Get a specific agent
const agent = await client.getAgent('agent-id');

// Create an agent
const newAgent = await client.createAgent({
  name: 'My Agent',
  description: 'A helpful assistant',
  provider: 'openai',
  model: 'gpt-4o',
  indexIds: ['index-id'],
});

// Update an agent
const updated = await client.updateAgent('agent-id', { name: 'Updated Name' });

// Delete an agent
await client.deleteAgent('agent-id');

// Query an agent (RAG)
const answer = await client.queryAgent('agent-id', {
  question: 'How do I reset my password?',
  maxResults: 5,       // optional
  temperature: 0.7,    // optional
  maxTokens: 1000,     // optional
});

QueryAgentResponse:

{
  answer: string | null;
  sources: Array<{ dataset?: string; index?: string; score: number; text: string }>;
  tokensUsed: number;
  model: string;
  warning?: string;
  diagnostic?: { totalResultsFound: number; threshold: number | null; topScores: number[] };
}

Pipelines

// List all pipelines
const pipelines = await client.listPipelines();

// Get a specific pipeline
const pipeline = await client.getPipeline('pipeline-id');

// Execute a pipeline
const result = await client.executePipeline('pipeline-id', {
  input: 'What is the return policy?',
});
// Or use the convenience alias:
const result2 = await client.queryPipeline('pipeline-id', {
  input: 'What is the return policy?',
});

// Get execution status
const status = await client.getPipelineExecutionStatus('pipeline-id', 'execution-id');

// Get execution details
const execution = await client.getPipelineExecution('pipeline-id', 'execution-id');

// List executions with pagination
const executions = await client.getPipelineExecutions('pipeline-id', {
  cursor: undefined,
  limit: 20,
});

ExecutePipelineResponse:

{
  executionId: string;
  status: string;
  output?: string;
  outputs?: Array<{ nodeId: string; label?: string; output: string }>;
  error?: string;
  nodeResults: Array<{ nodeId: string; status: string; output?: string; tokensUsed: number; warning?: string }>;
  totalTokensUsed: number;
}

Indexes

// List all indexes
const indexes = await client.listIndexes();

// Get a specific index
const index = await client.getIndex('index-id');

// Create an index
import { PineconeEmbeddingModel } from '@shinrag/sdk';
const newIndex = await client.createIndex({
  name: 'My Index',
  pineconeIndexName: 'my-pinecone-index',
  embeddingModel: PineconeEmbeddingModel.OPENAI_SMALL,
  metric: 'cosine', // optional: 'cosine' | 'euclidean' | 'dotproduct'
});

// Query an index (semantic search)
const results = await client.queryIndex({
  indexId: 'index-id',
  queryText: 'authentication',
  limit: 10,
  filter: { category: 'docs' }, // optional metadata filter
});
// Or use the convenience alias:
const results2 = await client.searchIndex({
  indexId: 'index-id',
  queryText: 'authentication',
});

// Get records with pagination
const records = await client.getIndexRecords('index-id', {
  limit: 50,
  paginationToken: 'token',
  prefix: 'doc_',
});

// Update records
await client.updateIndexRecords('index-id', {
  records: [
    { id: 'rec_1', metadata: { text: 'Updated content' } },
    { id: 'rec_2', metadata: { text: 'New content' }, isNew: true },
    { id: 'rec_3', metadata: {}, isDeleted: true },
  ],
});

// Check ingestion job status
const job = await client.getIngestionStatus('job-id');

Integrations

// List all integrations
const integrations = await client.listIntegrations();

// Get integration types and categories
const types = await client.getIntegrationTypes();
const byCategory = await client.getIntegrationTypesByCategory();

// Create an integration (e.g., PostgreSQL)
const integration = await client.createIntegration({
  type: 'postgres',
  name: 'My Database',
  credentials: { host: 'localhost', port: 5432, database: 'mydb', user: 'user', password: 'pass' },
  validateCredentials: true,
});

// Test an integration
const testResult = await client.testIntegration('integration-id');

// Execute an integration
const execResult = await client.executeIntegration('integration-id', {
  config: { query: 'SELECT * FROM users LIMIT 10' },
  input: 'Fetch user data',
});

// Slack OAuth flow
const { url } = await client.getSlackAuthUrl();
// Redirect user to url, then on callback:
const slackIntegration = await client.completeSlackOAuth(code);
const { channels } = await client.refreshSlackChannels('integration-id');

// GitHub OAuth flow
const { url: ghUrl } = await client.getGitHubAuthUrl();
const ghIntegration = await client.completeGitHubOAuth(code);
const { repositories } = await client.refreshGitHubRepositories('integration-id');
const { issues } = await client.getGitHubIssues('integration-id', 'owner', 'repo', 'open');
const { pullRequests } = await client.getGitHubPullRequests('integration-id', 'owner', 'repo');

Supported integration types: slack, discord, webhook, github, postgres, mysql, mongodb, snowflake, bigquery, perplexity, tavily, http

Widgets

// Manage widgets (authenticated)
const widgets = await client.listWidgets();
const widget = await client.createWidget({ name: 'Support Chat', agentId: 'agent-id' });
await client.updateWidget('widget-id', { isActive: false });
await client.deleteWidget('widget-id');

// Public widget endpoints (can be used without API key auth)
const widgetInfo = await client.getWidgetByKey('widget-key');
const response = await client.queryWidget('widget-key', {
  question: 'How do I get started?',
  sessionId: 'session_123', // optional: for conversation continuity
});
const history = await client.getWidgetSessionHistory('widget-key', 'session_123');

API Keys

const keys = await client.listApiKeys();
const newKey = await client.createApiKey({ name: 'Production Key' });
console.log(newKey.key); // sk_... (only shown once!)
await client.deleteApiKey('key-id');

Usage & Billing

const usage = await client.getUsage();
const pricing = await client.getV2Pricing();
const usageSummary = await client.getV2UsageSummary();
const cacheStatus = await client.getV2CacheStatus();

// Checkout for upgrading tier
const { checkoutUrl } = await client.createV2Checkout({
  tier: 'developer',
  successUrl: 'https://myapp.com/success',
  cancelUrl: 'https://myapp.com/cancel',
});

// Downgrade management
const downgradeStatus = await client.getV2DowngradeStatus();
await client.scheduleV2Downgrade('sandbox');
await client.cancelV2PendingDowngrade();

// Cancel subscription
await client.cancelV2Subscription();

Cost Tracking

const summary = await client.getCostSummary(30);       // last 30 days
const pipelineCosts = await client.getPipelineCosts(7); // last 7 days
const trend = await client.getCostTrend(30);            // daily breakdown
const execCost = await client.getExecutionCost('execution-id');
const rates = await client.getCostRates();

Batch Execution

const batch = await client.createBatch('pipeline-id', {
  inputs: ['Question 1', 'Question 2', 'Question 3'],
  name: 'Test Batch',
});

// Poll for completion
let status = await client.getBatchStatus(batch.batchId);
while (status.status === 'pending' || status.status === 'processing') {
  await new Promise(r => setTimeout(r, 2000));
  status = await client.getBatchStatus(batch.batchId);
}
console.log('Batch complete:', status.results);

Webhooks

const webhooks = await client.listWebhooks('pipeline-id');
const webhook = await client.createWebhook('pipeline-id', {
  name: 'My Webhook',
  description: 'Triggers on incoming data',
  secretToken: 'my-secret',       // optional
  inputMapping: '{{body.query}}',  // optional
});
await client.deleteWebhook('pipeline-id', 'webhook-id');

Schedules

const schedules = await client.listSchedules('pipeline-id');
const schedule = await client.createSchedule('pipeline-id', {
  name: 'Daily Report',
  cronExpression: '0 9 * * *',       // Every day at 9 AM
  inputTemplate: 'Generate daily summary',
  timezone: 'America/New_York',      // optional
});
await client.deleteSchedule('pipeline-id', 'schedule-id');

Templates

const templates = await client.listTemplates('pipeline-id');
const template = await client.createTemplate('pipeline-id', {
  name: 'FAQ Template',
  inputTemplate: 'Answer the following FAQ: {{question}}',
});

Execution History

const history = await client.getExecutionHistory('pipeline-id', {
  limit: 20,
  status: 'completed',                // optional: 'pending' | 'running' | 'completed' | 'failed'
  source: 'api',                       // optional: 'manual' | 'api' | 'schedule' | 'webhook' | 'batch'
  cursor: 'next-page-cursor',         // optional: for pagination
});

const detail = await client.getExecution('execution-id');

Support

const issue = await client.createIssue({
  title: 'Bug: Pipeline fails on large input',
  description: 'When input exceeds 10k chars...',
  issueType: 'bug',
});

Advanced: Custom Authentication

The SDK exports BaseApiClient for use with custom authentication (e.g., JWT in the frontend):

import { BaseApiClient } from '@shinrag/sdk/core';

const client = new BaseApiClient({
  baseUrl: 'http://localhost:1337',
  headers: { 'Authorization': `Bearer ${jwtToken}` },
  organizationId: 'org_123',
});

// All the same API methods are available
const agents = await client.listAgents();

Error Handling

The SDK throws ShinRAGError for API errors:

import { ShinRAGClient, ShinRAGError } from '@shinrag/sdk';

try {
  const result = await client.executePipeline('pipeline-id', {
    input: 'Your query here',
  });
} catch (error) {
  if (error instanceof ShinRAGError) {
    console.error('API Error:', error.message);
    console.error('Status Code:', error.statusCode);
    console.error('Response:', error.response);
  } else {
    console.error('Unknown error:', error);
  }
}

Type Exports

All types are available as named exports:

import type {
  Agent, CreateAgentRequest, QueryAgentRequest, QueryAgentResponse,
  Pipeline, ExecutePipelineRequest, ExecutePipelineResponse,
  IndexMetadata, QueryIndexOptions, QueryIndexResponse,
  Integration, IntegrationType, IntegrationCategory,
  Widget, QueryWidgetRequest, QueryWidgetResponse,
  V2Tier, V2UsageSummary, CostSummary,
  ShinRAGClientConfig, RequestConfig,
  // ... and many more
} from '@shinrag/sdk';

// Enum (value import, not type-only)
import { PineconeEmbeddingModel, ShinRAGError } from '@shinrag/sdk';

Development

For local development, point to your local API:

const client = new ShinRAGClient({
  apiKey: 'sk_your_api_key_here',
  baseUrl: 'http://localhost:1337',
});

Run the example test suite:

cd apps/example
cp .env.example .env  # Set your API key
npx tsx index.ts --all

License

MIT