@hsafa/ui-sdk
v0.6.4
Published
React SDK for integrating AI agents built with HSAFA AI Agent Studio
Maintainers
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-sdkQuick 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
- Agent Calls Action: Your AI agent (built in HSAFA Studio) decides to call a registered action
- SDK Executes: The action runs in your React app with the provided parameters
- Return Data: Results are sent back to the agent to continue the conversation
- 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 chatuseChatStorage
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 chatuseMessageEditor
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 editinguseFileUpload
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 allLegacy 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 storybookScripts
pnpm build- Build the library for productionpnpm dev- Build in watch modepnpm test- Run testspnpm test:ui- Run tests with UIpnpm storybook- Start Storybook development serverpnpm build:storybook- Build Storybook for productionpnpm lint- Run ESLintpnpm type-check- Run TypeScript type checking
Publishing
# Build the library
pnpm build
# Publish to npm
npm publish --access publicLicense
MIT © Husam Abu Safa
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
