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

@hsafa/ui-sdk

v0.6.4

Published

React SDK for integrating AI agents built with HSAFA AI Agent Studio

Readme

@hsafa/ui-sdk

React SDK for building AI agent interfaces with custom actions and interactive components.

Features

  • 🤖 AI Agent Chat: Ready-to-use chat interface for AI agents
  • 🎨 Headless Mode: Build completely custom UIs with powerful hooks
  • Custom Actions: Register functions that AI agents can call
  • 🎨 Dynamic Components: Create UI components that agents can render
  • 🔧 TypeScript: Full TypeScript support with comprehensive type definitions
  • 📦 Lightweight: Tree-shakable with minimal dependencies
  • 🎯 Agent-Focused: Built specifically for AI agent interactions

Installation

npm install @hsafa/ui-sdk
# or
yarn add @hsafa/ui-sdk
# or
pnpm add @hsafa/ui-sdk

Quick Start

Option 1: Pre-built UI Component

Use the ready-made chat interface:

import { HsafaProvider, HsafaChat } from '@hsafa/ui-sdk';

function App() {
  return (
    <HsafaProvider baseUrl="https://your-hsafa-api.com">
      <HsafaChat 
        agentId="your-agent-id"
        width={400}
        height={600}
        placeholder="Ask your AI agent anything..."
      />
    </HsafaProvider>
  );
}

Option 2: Headless Mode (Build Your Own UI)

Use the headless hooks to build a completely custom chat interface:

import { useHsafaAgent } from '@hsafa/ui-sdk';

function MyCustomChat() {
  const agent = useHsafaAgent({
    agentId: 'my-agent',
    baseUrl: 'https://your-hsafa-api.com',
  });

  return (
    <div>
      {/* Messages */}
      <div>
        {agent.messages.map(msg => (
          <div key={msg.id}>
            <strong>{msg.role}:</strong> {msg.content}
          </div>
        ))}
      </div>

      {/* Input */}
      <input 
        value={agent.input} 
        onChange={(e) => agent.setInput(e.target.value)}
        onKeyPress={(e) => e.key === 'Enter' && agent.sendMessage()}
      />
      <button onClick={() => agent.sendMessage()}>Send</button>
    </div>
  );
}

📚 Full Headless Documentation - Complete guide with examples

Adding Custom Actions

import { HsafaProvider, HsafaChat, useHsafaAction } from '@hsafa/ui-sdk';

function MyApp() {
  return (
    <HsafaProvider baseUrl="https://your-hsafa-api.com">
      <ActionProviders />
      <HsafaChat agentId="your-agent-id" />
    </HsafaProvider>
  );
}

function ActionProviders() {
  // Register an action that your AI agent can call
  useHsafaAction('getUserData', async (params) => {
    const { userId } = params;
    // Fetch user data from your database
    return { 
      name: 'John Doe', 
      email: '[email protected]',
      status: 'active'
    };
  });

  useHsafaAction('createTask', async (params) => {
    const { title, description } = params;
    // Create task in your system
    return { taskId: '123', status: 'created' };
  });

  return null;
}

Custom UI Components

import { useHsafaComponent } from '@hsafa/ui-sdk';

function ComponentProviders() {
  // Register UI components that agents can render
  useHsafaComponent('ProductCard', ({ product }) => (
    <div className="border rounded-lg p-4">
      <img src={product.image} alt={product.name} />
      <h3>{product.name}</h3>
      <p>${product.price}</p>
      <button>Add to Cart</button>
    </div>
  ));

  useHsafaComponent('StatusChart', ({ data }) => (
    <div className="chart-container">
      {/* Your chart implementation */}
      <h4>Status Overview</h4>
      {data.map(item => (
        <div key={item.id}>{item.label}: {item.value}</div>
      ))}
    </div>
  ));

  return null;
}

Components

Button

A versatile button component with multiple variants and states.

import { Button } from '@hsafa/ui-sdk';

// Basic usage
<Button>Click me</Button>

// With variants
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>

// With sizes
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>

// With loading state
<Button loading>Loading...</Button>

// Disabled
<Button disabled>Disabled</Button>

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | variant | 'primary' \| 'secondary' \| 'outline' \| 'ghost' | 'primary' | Button style variant | | size | 'sm' \| 'md' \| 'lg' | 'md' | Button size | | loading | boolean | false | Show loading spinner | | disabled | boolean | false | Disable the button | | children | ReactNode | - | Button content |

Core Concepts

AI Agent Integration

The SDK connects to your HSAFA AI Agent Studio, allowing your agents to:

  • Execute Actions: Call functions in your application
  • Render Components: Display custom UI elements in chat
  • Access Data: Interact with your backend systems

How It Works

  1. Agent Calls Action: Your AI agent (built in HSAFA Studio) decides to call a registered action
  2. SDK Executes: The action runs in your React app with the provided parameters
  3. Return Data: Results are sent back to the agent to continue the conversation
  4. Render UI: Agent can display custom components based on the data

API Reference

Components

HsafaChat

Chat interface for your AI agents built in HSAFA Studio.

<HsafaChat
  agentId="your-agent-id"
  width={400}
  height={600}
/>

| Prop | Type | Description | |------|------|-------------| | agentId | string | Required - ID of your agent from HSAFA Studio | | width | number | Chat panel width (default: 400) | | height | number | Chat panel height (default: 600) | | placeholder | string | Input placeholder text | | primaryColor | string | Primary theme color |

HsafaProvider

Provides context for agent communication.

<HsafaProvider baseUrl="https://your-hsafa-api.com">
  {/* Your app */}
</HsafaProvider>

| Prop | Type | Description | |------|------|-------------| | baseUrl | string | Required - Your HSAFA API endpoint | | children | ReactNode | Required - App components |

Headless Hooks

Build custom chat UIs with complete control over styling and layout.

useHsafaAgent

The main hook for headless agent integration. Provides all chat functionality without UI.

import { useHsafaAgent } from '@hsafa/ui-sdk';

const agent = useHsafaAgent({
  agentId: 'my-agent',
  baseUrl: 'https://your-hsafa-api.com',
  tools: { /* custom tools */ },
  uiComponents: { /* custom UI components */ },
  onFinish: (message) => console.log('Done:', message),
  onError: (error) => console.error('Error:', error),
});

// Available properties:
agent.input          // Current input text
agent.setInput()     // Update input
agent.messages       // All messages
agent.isLoading      // Loading state
agent.sendMessage()  // Send message
agent.stop()         // Stop generation
agent.newChat()      // Start new chat

useChatStorage

Persist and manage chat history in localStorage.

import { useHsafaAgent, useChatStorage } from '@hsafa/ui-sdk';

const agent = useHsafaAgent({ /* ... */ });
const storage = useChatStorage({
  agentId: 'my-agent',
  chatId: agent.chatId,
  messages: agent.messages,
  isLoading: agent.isLoading,
  autoSave: true,
  autoRestore: true,
});

// Available properties:
storage.chatList              // All saved chats
storage.loadChat(chatId)      // Load specific chat
storage.deleteChat(chatId)    // Delete chat
storage.switchToChat(chatId)  // Switch to chat

useMessageEditor

Edit messages and regenerate responses.

import { useMessageEditor } from '@hsafa/ui-sdk';

const editor = useMessageEditor({
  messages: agent.messages,
  isLoading: agent.isLoading,
  sendMessage: agent.sendMessage,
  setMessages: agent.setMessages,
});

// Available properties:
editor.startEdit(msgId, text)  // Start editing
editor.saveEdit(msgId)         // Save and regenerate
editor.cancelEdit()            // Cancel editing
editor.isEditing(msgId)        // Check if editing

useFileUpload

Handle file attachments for messages.

import { useFileUpload } from '@hsafa/ui-sdk';

const fileUpload = useFileUpload('https://your-api.com');

// Available properties:
fileUpload.attachments            // Current attachments
fileUpload.handleFileSelection()  // Handle file input
fileUpload.clearAttachments()     // Clear all

Legacy Hooks

useHsafaAction

Register functions that your AI agent can call. Perfect for connecting agents to your business logic.

import { useHsafaAction } from '@hsafa/ui-sdk';

function MyApp() {
  // Register actions your agent can use
  useHsafaAction('getUserProfile', async ({ userId }) => {
    const user = await fetchUserFromDatabase(userId);
    return { name: user.name, email: user.email };
  });

  useHsafaAction('placeOrder', async ({ productId, quantity }) => {
    const order = await createOrder(productId, quantity);
    return { orderId: order.id, total: order.total };
  });

  return <YourApp />;
}

useHsafaComponent

Register UI components that agents can render in chat. Great for displaying data visually.

import { useHsafaComponent } from '@hsafa/ui-sdk';

function MyApp() {
  // Register components your agent can display
  useHsafaComponent('OrderSummary', ({ order }) => (
    <div className="order-card">
      <h3>Order #{order.id}</h3>
      <p>Total: ${order.total}</p>
      <p>Status: {order.status}</p>
    </div>
  ));

  useHsafaComponent('ProductList', ({ products }) => (
    <div className="grid">
      {products.map(product => (
        <div key={product.id} className="product-card">
          <img src={product.image} alt={product.name} />
          <h4>{product.name}</h4>
          <p>${product.price}</p>
        </div>
      ))}
    </div>
  ));

  return <YourApp />;
}

useHsafa

Advanced hook for manual registration and context access.

import { useHsafa } from '@hsafa/ui-sdk';

function MyComponent() {
  const { registerAction, registerComponent } = useHsafa();
  
  // Manual registration with cleanup
  useEffect(() => {
    const cleanup1 = registerAction('customAction', handler);
    const cleanup2 = registerComponent('CustomComponent', Component);
    
    return () => {
      cleanup1();
      cleanup2();
    };
  }, []);
}

Development

Prerequisites

  • Node.js 18+
  • pnpm (recommended)

Setup

# Clone the repository
git clone https://github.com/husamabusafa/hsafa.git
cd hsafa/sdk

# Install dependencies
pnpm install

# Start development
pnpm dev

# Run tests
pnpm test

# Start Storybook
pnpm storybook

Scripts

  • pnpm build - Build the library for production
  • pnpm dev - Build in watch mode
  • pnpm test - Run tests
  • pnpm test:ui - Run tests with UI
  • pnpm storybook - Start Storybook development server
  • pnpm build:storybook - Build Storybook for production
  • pnpm lint - Run ESLint
  • pnpm type-check - Run TypeScript type checking

Publishing

# Build the library
pnpm build

# Publish to npm
npm publish --access public

License

MIT © Husam Abu Safa

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request