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

lyzr-cortex-sdk

v0.1.4

Published

SDK for building tools that integrate with Cortex Platform

Readme

Cortex SDK for TypeScript

Build tools that integrate with the Cortex Platform for bidirectional knowledge flow.

Installation

npm install lyzr-cortex-sdk
# or
yarn add lyzr-cortex-sdk
# or
pnpm add lyzr-cortex-sdk

Quick Start

React Integration

import { CortexProvider, useCortex } from 'lyzr-cortex-sdk';

// 1. Wrap your app with CortexProvider
function App() {
  return (
    <CortexProvider
      apiUrl={process.env.REACT_APP_CORTEX_API_URL}
      apiKey={process.env.REACT_APP_CORTEX_API_KEY}
    >
      <YourApp />
    </CortexProvider>
  );
}

// 2. Use the hook in your components
function MeetingCard({ meeting }) {
  const { isEmbedded, openChat, showNotification, push } = useCortex();

  const handleSave = async () => {
    await push({
      id: meeting.id,
      type: 'meeting_transcript',
      content: meeting.transcript,
      name: meeting.title,
      scope: 'team',
    });
    showNotification('Saved to Cortex', 'success');
  };

  return (
    <div>
      <h3>{meeting.title}</h3>
      <button onClick={handleSave}>Save to Cortex</button>

      {/* Only show when embedded in Cortex */}
      {isEmbedded && (
        <button onClick={() => openChat(`What action items from "${meeting.title}"?`)}>
          Ask Cortex
        </button>
      )}
    </div>
  );
}

Direct API Client (without React)

import { CortexClient } from 'lyzr-cortex-sdk';

const client = new CortexClient({
  apiUrl: 'https://api.cortex.ai',
  apiKey: 'your-api-key',
  toolId: 'your-tool',
});

// Push a document
await client.push({
  id: 'doc_123',
  type: 'meeting_transcript',
  content: 'Full transcript...',
  name: 'Product Sync',
  scope: 'team',
});

// Query
const result = await client.query('What decisions were made about Q1?');
console.log(result.answer);
console.log(result.sources);

PostMessage Bridge (Low-level)

import { CortexBridge, isEmbeddedInCortex } from 'lyzr-cortex-sdk';

// Check if embedded
if (isEmbeddedInCortex()) {
  const bridge = new CortexBridge();

  // Wait for initialization
  const user = await bridge.waitForReady();
  console.log('Cortex user:', user?.email);

  // Send messages
  bridge.openChat('Hello from my tool!');
  bridge.showNotification('Tool loaded', 'success');

  // Listen for messages
  bridge.on('CORTEX_THEME', (payload) => {
    document.body.className = payload.theme;
  });
}

Frontend Integration Guide

Step-by-step guide for integrating Cortex into your React/TypeScript frontend.

1. Create Cortex Provider

File: frontend/lib/cortex.tsx

'use client';

import { createContext, useContext, useEffect, useState, useCallback, useMemo, ReactNode } from 'react';

interface CortexUser {
  id: string;
  email: string;
  name?: string;
  orgId: string;
  teams: Array<{ id: string; name: string }>;
}

interface CortexContextValue {
  user: CortexUser | null;
  isEmbedded: boolean;
  isReady: boolean;
  theme: 'light' | 'dark';
  openChat: (query?: string) => void;
}

const CortexContext = createContext<CortexContextValue | null>(null);

function isInIframe(): boolean {
  if (typeof window === 'undefined') return false;
  try {
    return window.self !== window.top;
  } catch {
    return true;
  }
}

export function CortexProvider({ children }: { children: ReactNode }) {
  const [isEmbedded] = useState(() => isInIframe());
  const [isReady, setIsReady] = useState(!isInIframe());
  const [user, setUser] = useState<CortexUser | null>(null);
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  useEffect(() => {
    if (!isEmbedded) return;

    const handleMessage = (event: MessageEvent) => {
      const message = event.data;
      if (!message?.type) return;

      if (message.type === 'CORTEX_INIT') {
        setUser(message.payload?.user || null);
        setTheme(message.payload?.theme || 'light');
        setIsReady(true);
      }

      if (message.type === 'CORTEX_THEME') {
        setTheme(message.payload?.theme || 'light');
      }
    };

    window.addEventListener('message', handleMessage);
    window.parent.postMessage({ type: 'TOOL_READY' }, '*');

    const timeout = setTimeout(() => setIsReady(true), 5000);

    return () => {
      window.removeEventListener('message', handleMessage);
      clearTimeout(timeout);
    };
  }, [isEmbedded]);

  const openChat = useCallback((query?: string) => {
    if (isEmbedded) {
      window.parent.postMessage({ type: 'OPEN_CHAT', payload: { query } }, '*');
    }
  }, [isEmbedded]);

  const value = useMemo(() => ({
    user, isEmbedded, isReady, theme, openChat
  }), [user, isEmbedded, isReady, theme, openChat]);

  return (
    <CortexContext.Provider value={value}>
      {children}
    </CortexContext.Provider>
  );
}

export function useCortex(): CortexContextValue {
  const context = useContext(CortexContext);
  if (!context) {
    return {
      user: null,
      isEmbedded: false,
      isReady: true,
      theme: 'light',
      openChat: () => {},
    };
  }
  return context;
}

2. Wrap App with Provider

File: frontend/app/providers.tsx

'use client';

import { CortexProvider } from '@/lib/cortex';

export function Providers({ children }: { children: React.ReactNode }) {
  return <CortexProvider>{children}</CortexProvider>;
}

File: frontend/app/layout.tsx

import { Providers } from './providers';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

3. Use in Components

import { useCortex } from '@/lib/cortex';

function TranscriptCard({ meeting }) {
  const { isEmbedded, openChat } = useCortex();

  return (
    <div>
      <h3>{meeting.title}</h3>
      <p>{meeting.transcript}</p>

      {isEmbedded && (
        <button onClick={() => openChat(`Summarize meeting: ${meeting.title}`)}>
          Ask Cortex
        </button>
      )}
    </div>
  );
}

4. Embedded Mode Authentication

When your tool is embedded in Cortex, the frontend receives the user's OGI JWT via CORTEX_INIT postMessage. Always send both custom headers and the standard Authorization header to survive production reverse proxies:

// In your tool's frontend
const headers = {
  'X-Cortex-Embedded': 'true',
  'X-Cortex-User-Email': user.email,
  'Authorization': `Bearer ${ogiJwtToken}`,  // Standard header — proxy-safe
};

Your tool's backend should accept both modes:

  1. Custom X-Cortex-Embedded + X-Cortex-User-Email headers (fast path, works locally)
  2. Authorization: Bearer {ogiJWT} decoded with CORTEX_JWT_PUBLIC_KEY (works through all proxies)

Production Note: Reverse proxies, CDNs, and load balancers may strip custom X-Cortex-* headers. Always send the OGI JWT as Authorization: Bearer alongside custom headers. The tool backend should accept both auth modes.


API Reference

CortexProvider

React context provider for Cortex integration.

<CortexProvider
  apiUrl="https://api.cortex.ai"  // Cortex gateway URL
  apiKey="your-api-key"           // Tool's API key
  toolId="your-tool"              // Tool identifier (optional)
  debug={false}                   // Enable debug logging (optional)
>
  {children}
</CortexProvider>

useCortex()

React hook returning Cortex context:

interface CortexContextValue {
  user: CortexUser | null;      // Current user (null if standalone)
  isEmbedded: boolean;          // Whether in Cortex iframe
  isReady: boolean;             // Whether SDK is initialized
  theme: 'light' | 'dark';      // Current theme

  push(doc): Promise<void>;     // Push document to Knowledge Graph
  query(question, options?): Promise<CortexQueryResult>;  // Query
  openChat(query?): void;       // Open Cortex chat
  showNotification(message, type?): void;  // Show notification
}

Additional Hooks

// More efficient if you only need specific values
const isEmbedded = useIsEmbedded();
const user = useCortexUser();
const theme = useCortexTheme();

CortexClient

HTTP client for direct API calls:

const client = new CortexClient(config);

// Check if configured
client.isConfigured; // boolean

// Methods
await client.push(document);
await client.query(question, options);
await client.getUserContext(email);

CortexBridge

Low-level postMessage bridge:

const bridge = new CortexBridge();

// Properties
bridge.isEmbedded;  // boolean
bridge.isReady;     // boolean
bridge.user;        // CortexUser | null
bridge.theme;       // 'light' | 'dark'

// Methods
await bridge.waitForReady();
bridge.openChat(query?);
bridge.showNotification(message, type);
bridge.navigate(path);
bridge.on(messageType, handler);
bridge.destroy();

Types

interface CortexUser {
  id: string;
  email: string;
  name?: string;
  orgId: string;
  orgName?: string;
  teams: Array<{ id: string; name: string }>;
  role: string;
  permissions: string[];
}

interface CortexDocument {
  id: string;         // External ID
  type: string;       // Document type
  content: string;    // Text content
  name?: string;      // Display name
  externalUrl?: string;
  scope?: 'global' | 'team' | 'personal';
  teamIds?: string[];
  metadata?: Record<string, unknown>;
}

interface CortexQueryResult {
  answer: string;
  sources: CortexSource[];
  query: string;
}

PostMessage Protocol

When embedded in Cortex, the SDK uses postMessage for communication:

| Direction | Message Type | Payload | |-----------|--------------|---------| | Tool → Cortex | TOOL_READY | - | | Cortex → Tool | CORTEX_INIT | { user, theme } | | Cortex → Tool | CORTEX_THEME | { theme } | | Tool → Cortex | OPEN_CHAT | { query? } | | Tool → Cortex | SHOW_NOTIFICATION | { message, type } | | Tool → Cortex | NAVIGATE | { path } |

Graceful Degradation

The SDK works in both embedded and standalone modes:

function MyComponent() {
  const { isEmbedded, push, openChat } = useCortex();

  // Push always works (no-op if not configured)
  await push({ id: '1', type: 'doc', content: '...' });

  // openChat is a no-op if not embedded
  openChat('Hello');

  // Conditionally render embedded-only features
  return (
    <div>
      {isEmbedded && <CortexOnlyFeature />}
    </div>
  );
}

License

MIT