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

@cogability/sdk

v0.2.0

Published

Framework-agnostic JavaScript SDK for CogAbility CAM and CMG APIs

Readme

@cogability/sdk

Framework-agnostic JavaScript SDK for the CogAbility platform.

Works in browser (React, Vue, vanilla JS, Lovable) and Node.js (agents, servers, CI scripts).

Installation

npm install @cogability/sdk

For browser OIDC flows (login/logout), also install the peer dependency:

npm install oidc-client-ts

Three clients

| Client | Purpose | Works in | |---|---|---| | CamClient | Chat sessions, streaming messages | Browser + Node.js | | CmgClient | Membership validation, geofencing | Browser + Node.js | | AuthClient | OIDC login / callback via App ID | Browser only |


CamClient — anonymous chat (browser SPA)

import { CamClient, BrowserSessionStore } from '@cogability/sdk';

const cam = new CamClient({
  host: 'https://cam.example.com',  // omit in Vite dev (uses proxy)
  cogbotId: 'mc_0091:full',
  sessionStore: new BrowserSessionStore(),
});

// 1. Establish session + fetch config
await cam.initAnonymous();
const config = await cam.initCogbot();
const greeting = await cam.fetchGreeting();

// 2. Send a message (non-streaming)
const response = await cam.sendMessage('Hello');
const items = CamClient.parseResponseGeneric(response);
console.log(items[0].text);

// 3. Send a message (streaming)
for await (const { eventName, data } of cam.streamMessage('Tell me more')) {
  if (eventName === 'partial_object') {
    process.stdout.write(CamClient.parseResponseGeneric(data)[0]?.text ?? '');
  } else if (eventName === 'final_response') {
    console.log('\n[done]');
  }
}

CamClient — authenticated chat (browser SPA)

After the user logs in and you have their idToken:

await cam.initAuthenticated(idToken);
for await (const event of cam.streamMessage('Save my profile', { anonymous: false })) {
  // handle event
}

CmgClient — membership validation (any framework)

import { CmgClient } from '@cogability/sdk';

const cmg = new CmgClient({
  host: 'https://cmg.example.com',
  namespace: 'my-namespace',
});

// Validate a logged-in user's membership
const { isMember, roles, geofenced } = await cmg.validateMembership(idToken);

// Check geofence for an anonymous visitor (fails open)
const { geofenced, message } = await cmg.checkGeofence();

AuthClient — OIDC login flow (browser only)

import { AuthClient } from '@cogability/sdk';

const auth = new AuthClient({
  authorityUrl: 'https://us-south.appid.cloud.ibm.com/oauth/v4/YOUR_TENANT',
  clientId: 'YOUR_CLIENT_ID',
  redirectUri: `${window.location.origin}/callback`,
  // Routes token exchange through CMG to avoid App ID CORS restrictions:
  tokenEndpointProxy: 'https://cmg.example.com/auth/token',
});

// Trigger login redirect
await auth.login('/members');

// On the /callback page:
const { user, idToken } = await auth.handleCallback();
console.log('Logged in as', user.email);

// Later:
await auth.logout();

Node.js agent — programmatic CogBot access

Agents skip OIDC entirely and pass tokens directly.

import { CamClient, CmgClient, MemorySessionStore } from '@cogability/sdk';

const cam = new CamClient({
  host: 'https://cam.example.com',
  cogbotId: 'mc_0091:full',
  sessionStore: new MemorySessionStore(),
  getHostUrl: () => 'https://agent.example.com',
});

const cmg = new CmgClient({
  host: 'https://cmg.example.com',
  namespace: 'my-namespace',
});

// Anonymous session — no login required
await cam.initAnonymous();
await cam.initCogbot();

// Check membership status for a known user token
const membership = await cmg.validateMembership(agentIdToken);
if (membership.isMember) {
  await cam.initAuthenticated(agentIdToken);
}

// Stream a conversation
for await (const { eventName, data } of cam.streamMessage('What are my membership benefits?')) {
  if (eventName === 'final_response') {
    const text = CamClient.parseResponseGeneric(data)
      .filter(g => g.response_type === 'text')
      .map(g => g.text)
      .join('\n');
    console.log(text);
  }
}

Vue / vanilla JS — drop-in chat widget

import { CamClient, BrowserSessionStore } from '@cogability/sdk';

const cam = new CamClient({
  host: import.meta.env.VITE_COGBOT_HOST,
  cogbotId: import.meta.env.VITE_COGBOT_ID,
  sessionStore: new BrowserSessionStore(),
});

await cam.initAnonymous();
await cam.initCogbot();

document.getElementById('send').addEventListener('click', async () => {
  const text = document.getElementById('input').value;
  const output = document.getElementById('output');
  output.textContent = '';

  for await (const { eventName, data } of cam.streamMessage(text)) {
    if (eventName === 'partial_object') {
      const parts = CamClient.parseResponseGeneric(data)
        .filter(g => g.response_type === 'text');
      if (parts[0]) output.textContent = parts[0].text;
    }
  }
});

Session storage

| Class | When to use | |---|---| | BrowserSessionStore | Browser SPAs — wraps window.sessionStorage | | MemorySessionStore | Node.js, SSR, tests — in-process Map |

Custom stores implement three methods: get(key), set(key, value), remove(key).

Advanced: raw SSE parsing

import { parseSseBlock, parseSseStream } from '@cogability/sdk';

// Parse a single SSE block string
const event = parseSseBlock('event: partial_object\ndata: {"output":{"generic":[]}}');

// Parse a fetch Response body as a stream
const res = await fetch('https://cam.example.com/api/cogbots/my-bot/id/uid/message/stream', {
  method: 'POST', body: JSON.stringify(payload), credentials: 'include',
});
for await (const event of parseSseStream(res)) {
  console.log(event.eventName, event.data);
}

Environment variables (Vite)

When using inside the membership-kit or template, the SDK reads these via import.meta.env:

| Variable | Used by | |---|---| | VITE_COGBOT_HOST | CamClient host (production) | | VITE_COGBOT_ID | CamClient cogbotId | | VITE_CMG_URL | CmgClient host | | VITE_SITE_NAMESPACE | CmgClient namespace | | VITE_APPID_OAUTH_SERVER_URL | AuthClient authorityUrl | | VITE_APPID_CLIENT_ID | AuthClient clientId |