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

@ai2aim.ai/hivemind-sdk

v1.0.10

Published

Node.js/TypeScript SDK for the Hivemind API

Readme

@hivemind/sdk

Node.js / TypeScript SDK for the Hivemind API. Covers every endpoint — organizations, RAG queries, generation, scraping, analytics, billing, audio, agents, admin, Jira integration, and more. Includes a CLI (hivemind) for init, config, health, helper utilities, query, org creation, and scraping.

Install

From this repo (local):

cd sdk
npm install
npm run build

# Then in your other project:
npm install ../path-to/VERTEX-AI/sdk

Or publish to a private registry and install normally:

npm install @hivemind/sdk

Quick start

Set HIVEMIND_BASE_URL (or HIVEMIND_API_URL) in your environment once. Then create clients with only the overrides you need (e.g. adminKey, apiKey); baseUrl is read from env when omitted.

import { HivemindClient } from "@hivemind/sdk";

const client = new HivemindClient({
  apiKey: "vtx_myorg_abc123...", // or pass per-request via options
});

const health = await client.health();
const result = await client.query("my-org", { query: "What is the return policy?" });
console.log(result.answer);

Configuration

| Option | Required | Description | |---|---|---| | baseUrl | No* | API base URL; defaults to HIVEMIND_BASE_URL or HIVEMIND_API_URL | | apiPrefix | No | Path prefix (default /v1) | | apiKey | No | Org API key; or pass per-request (see below) | | adminKey | No | Bootstrap admin key for admin endpoints | | webhookSecret | No | Secret for webhook endpoints |

* Required: either pass in config or set the env var. | employeeId | No | Employee ID header for RBAC | | timeoutMs | No | Request timeout in ms (default 30 000) | | insecure | No | Skip TLS verification for self-signed certs |

API key from your database or cache

You do not need to put the org API key in the client config. Store it in your system’s database or cache (e.g. per tenant/org) and pass it per request via the optional options parameter.

Set HIVEMIND_BASE_URL (or HIVEMIND_API_URL) in your environment. Then create one shared client with no API key; pass the key from your store on each org-scoped call:

import { HivemindClient } from "@hivemind/sdk";

// One shared client — no API key in config
const client = new HivemindClient({});

// In your app: load API key from your DB/cache for the current org
const apiKey = await getOrgApiKeyFromDb(orgId); // your function

const result = await client.query(orgId, { query: "What is the return policy?" }, { apiKey });

All org-scoped methods accept an optional last argument options?: RequestOptions with { apiKey?: string }. Use it to pass the key from your store instead of setting it on the client.

CLI config

The CLI reads config from environment variables and optionally .hivemindrc.json in the current directory. Env overrides file.

| Env | Description | |---|---| | HIVEMIND_BASE_URL | API base URL (required) | | HIVEMIND_API_KEY | Org API key (for org-scoped commands) | | HIVEMIND_ADMIN_KEY | Admin key for org:create | | HIVEMIND_API_PREFIX | Path prefix (default /v1) | | HIVEMIND_INSECURE | Set to true to skip TLS verification | | HIVEMIND_TIMEOUT_MS | Request timeout in ms |

You can also set apiKey on the client for single-tenant use.

Admin endpoints

If base URL is already in env, pass only adminKey:

const admin = new HivemindClient({
  adminKey: "your-bootstrap-admin-key",
});

// Create a new organization (returns the org + API key)
const { organization, api_key } = await admin.createOrganization({
  org_id: "acme",
  name: "Acme Corp",
  tier: "premium",
});

console.log("API Key:", api_key);

CLI

After install, the hivemind binary is available (npx hivemind or via npm exec hivemind if installed globally).

Commands

| Command | Description | |---|---| | hivemind init | Create .hivemindrc.json and .env.example in the current directory | | hivemind config | Print resolved config (secrets masked) | | hivemind health | Call the API health endpoint | | hivemind helper validate | Validate config and test connection | | hivemind helper env | Print env var template for copy-paste | | hivemind query <org_id> <question> | Run a RAG query (needs API key) | | hivemind org:create <org_id> <name> | Create an organization (needs admin key) | | hivemind scrape <url...> | Submit URLs to scrape | | hivemind scrape:status <task_id> | Get scrape task status and result |

Examples

# Initialize config in current directory
hivemind init

# Only create .env.example
hivemind init --env-only

# Check connection
export HIVEMIND_BASE_URL=https://your-api.com
hivemind health

# Validate config and ping API
hivemind helper validate

# Print env template
hivemind helper env

# Run a RAG query (requires HIVEMIND_API_KEY)
hivemind query my-org "What is the return policy?"

# Create org (requires HIVEMIND_ADMIN_KEY)
hivemind org:create acme "Acme Corp" --tier premium

# Scrape URLs and wait for results
hivemind scrape https://example.com https://example.org --wait

Options

  • -d, --dir <path> (for init, config, health, helper, query, org:create, scrape): Directory to use for .hivemindrc.json (default: current directory).
  • -u, --url <url> (health): Override base URL for a one-off health check.
  • --skip-ping (helper validate): Validate config only, do not call the API.

All methods

All org-scoped methods accept an optional last argument options?: RequestOptions where you can pass { apiKey: string } from your database or cache.

Authentication types:

  • Admin — Set adminKey in client config. Sends X-Admin-Key header.
  • API Key — Set apiKey in config or pass per-request via options.apiKey. Sent as Authorization: Bearer <key>.
  • Webhook — Set webhookSecret in client config. Sends X-Webhook-Secret header.
  • None — No authentication required.

All responses are wrapped in the standard envelope:

{ "success": true, "statusCode": 200, "data": { ... }, "message": "Request successful" }

The SDK returns the data payload directly (unwrapped).

Health

| Method | Auth | Description | |---|---|---| | health() | None | Service health check |

Returns HealthResponse:

| Field | Type | Description | |-----------|--------|-------------------------------------------------------| | service | string | Service name | | version | string | Service version | | status | string | Health status ("ok") | | stats | object | { organizations, documents, total_chunks } |

Admin auth

| Method | Auth | Description | |---|---|---| | adminLogin({ admin_key }) | None | Exchange admin key for a signed session token |

Parameters (AdminLoginParams):

| Field | Type | Required | Description | |-------------|--------|----------|----------------------------| | admin_key | string | Yes | The bootstrap admin key |

Returns AdminLoginResponse:

| Field | Type | Description | |----------------------|--------|------------------------------------------| | access_token | string | Signed JWT session token | | token_type | string | Always "bearer" | | expires_in_seconds | number | Token validity (default 28800 = 8 hours) |

const { access_token } = await client.adminLogin({ admin_key: "your-admin-key" });

Organizations

| Method | Auth | Description | |---|---|---| | createOrganization(params) | Admin | Create org, returns org + API key | | getOrganization(orgId, options?) | API Key | Get org details | | rotateApiKey(orgId, options?) | Admin | Rotate org API key (24h grace period for old key) | | suspendOrganization(orgId, options?) | Admin | Suspend an org (blocks API access) | | reactivateOrganization(orgId, options?) | Admin | Reactivate a suspended org | | deleteOrganization(orgId, options?) | Admin | Permanently delete an org (irreversible) |

createOrganization parameters (OrgCreateParams):

| Field | Type | Required | Default | Description | |------------|--------|----------|--------------|------------------------------------------------| | org_id | string | Yes | — | Unique org identifier (2–64 chars) | | name | string | Yes | — | Display name (2–128 chars) | | tier | string | No | "standard" | "free", "standard", "premium", "enterprise" | | settings | object | No | {} | Custom org settings |

Returns OrgBootstrapResponse:

| Field | Type | Description | |----------------|--------------|------------------------------------| | organization | Organization | Full organization entity | | api_key | string | Generated API key (shown only once)|

const { organization, api_key } = await admin.createOrganization({
  org_id: "acme-corp",
  name: "Acme Corporation",
  tier: "premium",
});

Documents

| Method | Auth | Description | |---|---|---| | uploadDocument(orgId, file, filename, options?) | API Key | Upload a document (Buffer or Blob) |

Parameters:

| Param | Type | Required | Description | |------------|----------------|----------|---------------------------------------| | orgId | string | Yes | Organization identifier | | file | Blob | Buffer | Yes | Document content | | filename | string | Yes | Original filename (e.g. "report.pdf") |

Returns DocumentUploadResponse:

| Field | Type | Description | |---------------|--------|-------------------------------------------| | document_id | string | Unique document identifier | | org_id | string | Organization ID | | filename | string | Original filename | | chunks | number | Number of text chunks created | | status | string | Processing status (e.g. "processed") |

import { readFileSync } from "fs";
const file = readFileSync("./report.pdf");
const result = await client.uploadDocument("acme-corp", file, "report.pdf");
console.log(`${result.chunks} chunks created`);

Query (RAG)

| Method | Auth | Description | |---|---|---| | query(orgId, params, options?) | API Key | RAG query with retrieval and generation |

Parameters (QueryParams):

| Field | Type | Required | Default | Description | |----------------------|--------|----------|--------------|-------------------------------------------| | query | string | Yes | — | Query text | | user_id | string | No | null | User identifier for tracking | | model_type | string | No | "gemini-pro" | Gemini model for generation | | temperature | number | No | 0.2 | Sampling temperature (0.0–1.0) | | retrieval_strategy | string | No | "hybrid" | "hybrid", "dense", or "sparse" |

Returns QueryResponse:

| Field | Type | Description | |--------------|----------|-------------------------------------------------| | answer | string | Generated answer text | | sources | object[] | Source citations (doc_id, chunk_id, score, snippet) | | model_type | string | Model used |

const result = await client.query("acme-corp", {
  query: "What are the key findings in Q4?",
  temperature: 0.2,
});
console.log(result.answer);
result.sources.forEach(s => console.log(s.doc_id, s.score));

Generation

| Method | Auth | Description | |---|---|---| | generateVideo(orgId, params, options?) | API Key | Start async video generation (Vertex AI Veo) | | generateImage(orgId, params, options?) | API Key | Start async image generation (Vertex AI Imagen) |

generateVideo parameters (GenerateVideoParams):

| Field | Type | Required | Default | Description | |----------------|--------|----------|----------|------------------------------------| | prompt | string | Yes | — | Video generation prompt | | duration | number | No | 8 | Duration: 4, 6, or 8 seconds | | aspect_ratio | string | No | "16:9" | Aspect ratio | | style | string | No | null | Visual style hint | | user_id | string | No | null | User identifier |

generateImage parameters (GenerateImageParams):

| Field | Type | Required | Default | Description | |----------------|--------|----------|---------|-------------------------------| | prompt | string | Yes | — | Image generation prompt | | aspect_ratio | string | No | "1:1" | Aspect ratio | | style | string | No | null | Visual style hint | | num_images | number | No | 1 | Number of images (1–8) | | user_id | string | No | null | User identifier |

Both return JobAcceptedResponse (HTTP 202):

| Field | Type | Description | |------------------|--------|-----------------------------------------------| | job_id | string | Job ID — use with getJob() / waitForJob() | | status | string | Always "processing" | | estimated_time | number | Estimated processing time in seconds |

const job = await client.generateVideo("acme-corp", {
  prompt: "A drone flyover of a mountain lake at sunset",
  duration: 8,
  style: "cinematic",
});
const result = await client.waitForJob("acme-corp", job.job_id);
console.log(result.result); // { output_url, signed_url }

Jobs

| Method | Auth | Description | |---|---|---| | getJob(orgId, jobId, options?) | API Key | Get job status | | waitForJob(orgId, jobId, intervalMs?, maxWaitMs?, options?) | API Key | Poll until job reaches terminal status |

Returns JobStatusResponse:

| Field | Type | Description | |----------|----------------|------------------------------------------------------| | job_id | string | Job identifier | | status | string | "processing", "completed", "failed", "cancelled" | | result | object | null | Result payload when completed (e.g. { output_url, signed_url }) | | error | string | null | Error message if failed |

waitForJob parameters:

| Param | Type | Default | Description | |--------------|--------|-----------|-----------------------------| | intervalMs | number | 2000 | Polling interval (ms) | | maxWaitMs | number | 300000 | Maximum wait time (ms) |

Data chat

| Method | Auth | Description | |---|---|---| | dataChat(orgId, params, options?) | API Key | Natural-language questions over BigQuery |

Parameters (DataChatParams):

| Field | Type | Required | Description | |------------|--------|----------|--------------------------------| | question | string | Yes | Natural-language question | | user_id | string | No | User identifier for tracking |

Returns DataChatResponse:

| Field | Type | Description | |----------|----------|------------------------------------| | answer | string | Natural-language answer | | sql | string | Generated SQL query | | rows | object[] | Result rows from BigQuery |

const result = await client.dataChat("acme-corp", {
  question: "How many active users this month?",
});
console.log(result.answer); // "There are 1,247 active users."
console.log(result.sql);    // "SELECT COUNT(DISTINCT user_id) FROM ..."

Agents

| Method | Auth | Description | |---|---|---| | createAgent(orgId, params, options?) | API Key | Create a custom AI agent template | | queryAgent(orgId, params, options?) | API Key | Query an AI agent |

createAgent parameters (AgentCreateParams):

| Field | Type | Required | Default | Description | |----------------|----------|----------|---------|---------------------------------| | name | string | Yes | — | Agent name (2–64 chars) | | instructions | string | Yes | — | System instructions (min 4 chars) | | tools | string[] | No | [] | Tool identifiers to enable |

queryAgent parameters (AgentQueryParams):

| Field | Type | Required | Default | Description | |--------------|--------|----------|----------|--------------------------| | query | string | Yes | — | User query | | user_id | string | Yes | — | User identifier | | agent_type | string | No | "auto" | Agent type to route to |

Audio

| Method | Auth | Description | |---|---|---| | transcribeAudio(orgId, params, options?) | API Key | Speech-to-text transcription | | synthesizeAudio(orgId, params, options?) | API Key | Text-to-speech synthesis |

transcribeAudio parameters (AudioTranscribeParams):

| Field | Type | Required | Default | Description | |-----------------|--------|----------|------------|---------------------------| | audio_text | string | Yes | — | Audio content / reference | | language_code | string | No | "en-US" | BCP-47 language code |

synthesizeAudio parameters (AudioSynthesizeParams):

| Field | Type | Required | Default | Description | |--------------|--------|----------|----------------------|---------------------| | text | string | Yes | — | Text to synthesize | | voice_name | string | No | "en-US-Neural2-J" | Voice identifier |

Analytics / ML

| Method | Auth | Description | |---|---|---| | trainModel(orgId, params, options?) | API Key | Train a predictive model on tabular data | | predict(orgId, params, options?) | API Key | Run predictions with a trained model | | forecast(orgId, params, options?) | API Key | Time-series forecast (ARIMA-based) |

trainModel parameters (TrainModelParams):

| Field | Type | Required | Description | |-------------------|----------|----------|-----------------------------| | target_column | string | Yes | Column to predict | | feature_columns | string[] | Yes | Feature column names | | rows | object[] | Yes | Training data rows |

predict parameters (PredictParams):

| Field | Type | Required | Description | |-------------|----------|----------|------------------------------| | model_id | string | Yes | Trained model ID | | instances | object[] | Yes | Data instances to predict on |

forecast parameters (ForecastParams):

| Field | Type | Required | Default | Description | |-----------|----------|----------|---------|--------------------------------| | series | number[] | Yes | — | Historical time-series values | | horizon | number | No | 30 | Forecast horizon (1–365) |

// Train
const model = await client.trainModel("acme-corp", {
  target_column: "churn",
  feature_columns: ["tenure", "monthly_charges"],
  rows: [{ tenure: 12, monthly_charges: 50, churn: 0 }],
});

// Predict
const { predictions } = await client.predict("acme-corp", {
  model_id: model.model_id,
  instances: [{ tenure: 6, monthly_charges: 65 }],
});

Billing

| Method | Auth | Description | |---|---|---| | getUsage(orgId, month?, options?) | API Key | Monthly usage summary with tier limits | | getInvoice(orgId, month?, options?) | API Key | Monthly invoice with cost breakdown |

Optional month parameter: YYYY-MM format. Defaults to current month.

getUsage returns UsageSummaryResponse:

| Field | Type | Description | |-------------------|----------|------------------------------------------------| | org_id | string | Organization ID | | month | string | Month (YYYY-MM) | | usage | object | { tokens_used, images_generated, videos_generated, storage_bytes, compute_hours } | | limits | object | Tier limits | | within_quota | boolean | Whether all metrics are within quota | | exceeded_limits | string[] | List of exceeded metric names |

getInvoice returns InvoiceResponse:

| Field | Type | Description | |--------------|----------|--------------------------------------| | org_id | string | Organization ID | | month | string | Month (YYYY-MM) | | total | number | Total cost in USD | | line_items | object[] | Itemized costs per resource type |

Audit

| Method | Auth | Description | |---|---|---| | getAuditLogs(orgId, options?) | API Key | List audit log records |

Returns AuditLogResponse:

| Field | Type | Description | |-----------|----------------|--------------------| | org_id | string | Organization ID | | records | AuditRecord[] | Audit log entries |

Each AuditRecord:

| Field | Type | Description | |------------|----------------|-----------------------------------------| | timestamp| string | ISO 8601 timestamp | | action | string | Action (e.g. "query.execute") | | resource | string | Resource path | | status | string | "success" or "failure" | | user_id | string | null | User who performed the action | | metadata | object | Additional context |

Scraping

| Method | Auth | Description | |---|---|---| | getScrapingConfig() | None | Runtime scraping configuration | | scrape({ urls }) | None | Submit URLs for scraping | | getScrapeStatus(taskId) | None | Check scrape task status and results | | scrapeAndWait(urls, intervalMs?, maxWaitMs?) | None | Submit + poll until results are ready |

scrape parameters (ScrapeParams):

| Field | Type | Required | Description | |--------|----------|----------|---------------------------------| | urls | string[] | Yes | URLs to scrape |

getScrapeStatus returns ScrapeStatusResponse:

| Field | Type | Description | |-----------|-------------------|----------------------------------------------------| | task_id | string | Task identifier | | status | string | "PENDING", "SUCCESS", "FAILURE", "completed" | | result | ScrapeResultItem[] | Scraped results (each with url, title, full_text) |

const result = await client.scrapeAndWait(["https://example.com"]);
for (const page of result.result) {
  console.log(page.title, page.full_text?.substring(0, 200));
}

Webhooks

| Method | Auth | Description | |---|---|---| | sendVideoCompleteWebhook(payload) | Webhook | Send video completion notification | | sendDocumentProcessedWebhook(payload) | Webhook | Send document processing notification |

VideoCompleteWebhook payload:

| Field | Type | Required | Description | |------------|--------|----------|-------------------------------------| | job_id | string | Yes | Job identifier | | org_id | string | Yes | Organization identifier | | status | string | Yes | Completion status | | metadata | object | No | Additional data (e.g. { output_uri }) |

DocumentProcessedWebhook payload:

| Field | Type | Required | Description | |---------------|--------|----------|-------------------------------------| | document_id | string | Yes | Document identifier | | org_id | string | Yes | Organization identifier | | status | string | Yes | Processing status | | metadata | object | No | Additional data (e.g. { chunks }) |

Error handling

All API errors throw HivemindError:

import { HivemindClient, HivemindError } from "@hivemind/sdk";

try {
  await client.query("my-org", { query: "hello" });
} catch (err) {
  if (err instanceof HivemindError) {
    console.error(err.statusCode, err.detail);
  }
}

Vercel / Next.js example

// app/api/query/route.ts (Next.js App Router)
import { HivemindClient } from "@hivemind/sdk";
import { NextResponse } from "next/server";

// With HIVEMIND_API_URL set in env
const client = new HivemindClient({
  apiKey: process.env.HIVEMIND_API_KEY!,
});

export async function POST(req: Request) {
  const { query } = await req.json();
  const result = await client.query("my-org", { query });
  return NextResponse.json(result);
}