mirror of
https://github.com/hanzoai/shadcn.git
synced 2026-10-30 18:22:59 +00:00
## Summary Complete migration to React 19.2.0 across all 5 packages with full test coverage and automated npm publishing. ## Packages Updated - @hanzo/ui - v5.1.1 - @hanzo/auth - Latest - @hanzo/commerce - Latest - @hanzo/brand - Latest - @hanzo/react - v1.0.0 ## Test Results - pkg/ui: 207/207 tests passing (99.5% from 206/207) - pkg/react: 10/10 tests passing (100%) - Total: 217/217 tests passing ✅ ## Key Changes ### Type Declarations - Created hanzo-ui.d.ts for @hanzo/auth and @hanzo/commerce - Workarounds for React 19 type incompatibilities in third-party packages - Proper module exports instead of bare namespace declarations ### Test Infrastructure - Switched from jsdom to happy-dom for React 19 compatibility - Fixed ResizeObserver mock (class constructor vs function) - Created vitest config for pkg/react - Fixed login form test query to avoid multiple button matches ### Dependencies - Added pnpm overrides for [email protected] and [email protected] - Updated vitest, vite, eslint-config-next, @types/node - All peer dependency warnings expected and acceptable ### CI/CD Publishing - Updated publish-on-tag.yml to build and publish all 5 packages - Updated npm-publish.yml to include brand and react packages - Created PUBLISH_GUIDE.md with comprehensive publishing instructions - Tag-based automatic publishing with provenance ### TypeScript Compilation - Added skipLibCheck and strict: false to commerce tsconfig - Fixed namespace type errors (CarouselApi, MediaStackDef, etc.) - Resolved ForwardRefExoticComponent type conflicts ## Publishing Ready for automated npm publishing via git tag: ```bash git tag v5.2.0 git push origin v5.2.0 ``` This will trigger GitHub Actions to: 1. Run all tests (pkg/ui and pkg/react) 2. Build all 5 packages 3. Version all packages to match tag 4. Publish to npm with provenance 5. Create GitHub release 6. Deploy docs to GitHub Pages
384 lines
8.8 KiB
Plaintext
384 lines
8.8 KiB
Plaintext
---
|
|
title: AI Models
|
|
description: Model selection dropdown for choosing between different AI models and providers
|
|
---
|
|
|
|
<ComponentPreview name="ai-models-demo" />
|
|
|
|
## Overview
|
|
|
|
The AI Models component provides a clean dropdown interface for selecting AI models from different providers. It displays model names, providers, and optional descriptions in an organized, searchable format.
|
|
|
|
## Features
|
|
|
|
- **Provider Grouping** - Group models by provider (OpenAI, Anthropic, Google, etc.)
|
|
- **Model Metadata** - Display model capabilities and descriptions
|
|
- **Search/Filter** - Quickly find specific models
|
|
- **Clean UI** - Simple, accessible dropdown interface
|
|
- **Customizable** - Add custom models and providers
|
|
|
|
## Usage
|
|
|
|
### Basic Model Selection
|
|
|
|
```tsx
|
|
import { AIModels } from "@/components/ui/ai-models"
|
|
|
|
const models = [
|
|
{
|
|
id: "gpt-4-turbo",
|
|
name: "GPT-4 Turbo",
|
|
provider: "OpenAI",
|
|
description: "Most capable model, great for complex tasks",
|
|
},
|
|
{
|
|
id: "gpt-3.5-turbo",
|
|
name: "GPT-3.5 Turbo",
|
|
provider: "OpenAI",
|
|
description: "Fast and efficient for most tasks",
|
|
},
|
|
{
|
|
id: "claude-3-opus",
|
|
name: "Claude 3 Opus",
|
|
provider: "Anthropic",
|
|
description: "Powerful model with strong reasoning",
|
|
},
|
|
]
|
|
|
|
export default function ModelPicker() {
|
|
const [selectedModel, setSelectedModel] = useState("gpt-4-turbo")
|
|
|
|
return (
|
|
<AIModels
|
|
models={models}
|
|
selectedModel={selectedModel}
|
|
onModelSelect={setSelectedModel}
|
|
/>
|
|
)
|
|
}
|
|
```
|
|
|
|
### With Complete Model Catalog
|
|
|
|
```tsx
|
|
import { AIModels } from "@/components/ui/ai-models"
|
|
|
|
const modelCatalog = [
|
|
// OpenAI Models
|
|
{
|
|
id: "gpt-4-turbo-preview",
|
|
name: "GPT-4 Turbo Preview",
|
|
provider: "OpenAI",
|
|
description: "Latest GPT-4 with 128K context",
|
|
},
|
|
{
|
|
id: "gpt-4",
|
|
name: "GPT-4",
|
|
provider: "OpenAI",
|
|
description: "Standard GPT-4 with 8K context",
|
|
},
|
|
{
|
|
id: "gpt-3.5-turbo",
|
|
name: "GPT-3.5 Turbo",
|
|
provider: "OpenAI",
|
|
description: "Fast and cost-effective",
|
|
},
|
|
|
|
// Anthropic Models
|
|
{
|
|
id: "claude-3-opus-20240229",
|
|
name: "Claude 3 Opus",
|
|
provider: "Anthropic",
|
|
description: "Most capable Claude model",
|
|
},
|
|
{
|
|
id: "claude-3-sonnet-20240229",
|
|
name: "Claude 3 Sonnet",
|
|
provider: "Anthropic",
|
|
description: "Balanced performance and speed",
|
|
},
|
|
{
|
|
id: "claude-3-haiku-20240307",
|
|
name: "Claude 3 Haiku",
|
|
provider: "Anthropic",
|
|
description: "Fastest Claude model",
|
|
},
|
|
|
|
// Google Models
|
|
{
|
|
id: "gemini-pro",
|
|
name: "Gemini Pro",
|
|
provider: "Google",
|
|
description: "Multimodal AI model",
|
|
},
|
|
{
|
|
id: "gemini-pro-vision",
|
|
name: "Gemini Pro Vision",
|
|
provider: "Google",
|
|
description: "Gemini with vision capabilities",
|
|
},
|
|
|
|
// Open Source Models
|
|
{
|
|
id: "mixtral-8x7b",
|
|
name: "Mixtral 8x7B",
|
|
provider: "Mistral AI",
|
|
description: "Open source mixture of experts",
|
|
},
|
|
{
|
|
id: "llama-2-70b",
|
|
name: "LLaMA 2 70B",
|
|
provider: "Meta",
|
|
description: "Open source large language model",
|
|
},
|
|
]
|
|
|
|
<AIModels
|
|
models={modelCatalog}
|
|
selectedModel={selectedModel}
|
|
onModelSelect={handleModelChange}
|
|
/>
|
|
```
|
|
|
|
### Integration with AI Chat
|
|
|
|
```tsx
|
|
import { useState } from "react"
|
|
|
|
import { AIChat } from "@/components/ui/ai-chat"
|
|
import { AIModels } from "@/components/ui/ai-models"
|
|
|
|
export default function ChatWithModelSelection() {
|
|
const [currentModel, setCurrentModel] = useState("gpt-4-turbo")
|
|
const [messages, setMessages] = useState([])
|
|
|
|
const handleSendMessage = async (message: string) => {
|
|
// Use currentModel for API request
|
|
const response = await fetch("/api/chat", {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
model: currentModel,
|
|
messages: [...messages, { role: "user", content: message }],
|
|
}),
|
|
})
|
|
// Handle response...
|
|
}
|
|
|
|
return (
|
|
<div className="flex h-screen flex-col">
|
|
{/* Model selector in header */}
|
|
<div className="border-b p-4">
|
|
<AIModels
|
|
models={models}
|
|
selectedModel={currentModel}
|
|
onModelSelect={setCurrentModel}
|
|
/>
|
|
</div>
|
|
|
|
{/* Chat interface */}
|
|
<AIChat
|
|
model={currentModel}
|
|
messages={messages}
|
|
onSendMessage={handleSendMessage}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
## Props
|
|
|
|
### AIModelsProps
|
|
|
|
| Prop | Type | Default | Description |
|
|
| --------------- | --------------------------- | ------- | --------------------------- |
|
|
| `models` | `AIModel[]` | `[]` | Array of available models |
|
|
| `selectedModel` | `string` | - | Currently selected model ID |
|
|
| `onModelSelect` | `(modelId: string) => void` | - | Called when model changes |
|
|
| `className` | `string` | - | Additional CSS classes |
|
|
|
|
### AIModel Interface
|
|
|
|
```typescript
|
|
interface AIModel {
|
|
id: string // Unique model identifier
|
|
name: string // Display name
|
|
description?: string // Model description
|
|
provider?: string // Provider name (OpenAI, Anthropic, etc.)
|
|
}
|
|
```
|
|
|
|
## Model Grouping
|
|
|
|
For large model catalogs, you can group by provider:
|
|
|
|
```tsx
|
|
const groupedModels = {
|
|
OpenAI: [
|
|
{ id: "gpt-4-turbo", name: "GPT-4 Turbo", provider: "OpenAI" },
|
|
{ id: "gpt-3.5-turbo", name: "GPT-3.5 Turbo", provider: "OpenAI" },
|
|
],
|
|
Anthropic: [
|
|
{ id: "claude-3-opus", name: "Claude 3 Opus", provider: "Anthropic" },
|
|
{ id: "claude-3-sonnet", name: "Claude 3 Sonnet", provider: "Anthropic" },
|
|
],
|
|
Google: [{ id: "gemini-pro", name: "Gemini Pro", provider: "Google" }],
|
|
}
|
|
```
|
|
|
|
## Common Model Configurations
|
|
|
|
### GPT Models (OpenAI)
|
|
|
|
```typescript
|
|
const gptModels = [
|
|
{ id: "gpt-4-turbo-preview", name: "GPT-4 Turbo", provider: "OpenAI" },
|
|
{ id: "gpt-4", name: "GPT-4", provider: "OpenAI" },
|
|
{ id: "gpt-3.5-turbo", name: "GPT-3.5 Turbo", provider: "OpenAI" },
|
|
]
|
|
```
|
|
|
|
### Claude Models (Anthropic)
|
|
|
|
```typescript
|
|
const claudeModels = [
|
|
{
|
|
id: "claude-3-opus-20240229",
|
|
name: "Claude 3 Opus",
|
|
provider: "Anthropic",
|
|
},
|
|
{
|
|
id: "claude-3-sonnet-20240229",
|
|
name: "Claude 3 Sonnet",
|
|
provider: "Anthropic",
|
|
},
|
|
{
|
|
id: "claude-3-haiku-20240307",
|
|
name: "Claude 3 Haiku",
|
|
provider: "Anthropic",
|
|
},
|
|
]
|
|
```
|
|
|
|
### Gemini Models (Google)
|
|
|
|
```typescript
|
|
const geminiModels = [
|
|
{ id: "gemini-pro", name: "Gemini Pro", provider: "Google" },
|
|
{ id: "gemini-pro-vision", name: "Gemini Pro Vision", provider: "Google" },
|
|
]
|
|
```
|
|
|
|
### Open Source Models
|
|
|
|
```typescript
|
|
const openSourceModels = [
|
|
{ id: "mixtral-8x7b-instruct", name: "Mixtral 8x7B", provider: "Mistral AI" },
|
|
{ id: "llama-2-70b-chat", name: "LLaMA 2 70B Chat", provider: "Meta" },
|
|
{ id: "mistral-7b-instruct", name: "Mistral 7B", provider: "Mistral AI" },
|
|
]
|
|
```
|
|
|
|
## Dynamic Model Loading
|
|
|
|
Load models from an API:
|
|
|
|
```tsx
|
|
import { useEffect, useState } from "react"
|
|
|
|
import { AIModels } from "@/components/ui/ai-models"
|
|
|
|
export default function DynamicModels() {
|
|
const [models, setModels] = useState([])
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
async function fetchModels() {
|
|
const response = await fetch("/api/models")
|
|
const data = await response.json()
|
|
setModels(data.models)
|
|
setLoading(false)
|
|
}
|
|
fetchModels()
|
|
}, [])
|
|
|
|
if (loading) return <div>Loading models...</div>
|
|
|
|
return (
|
|
<AIModels
|
|
models={models}
|
|
selectedModel={selectedModel}
|
|
onModelSelect={setSelectedModel}
|
|
/>
|
|
)
|
|
}
|
|
```
|
|
|
|
## Model Capabilities
|
|
|
|
Track model capabilities for UI hints:
|
|
|
|
```typescript
|
|
interface ExtendedAIModel {
|
|
id: string
|
|
name: string
|
|
provider: string
|
|
capabilities: {
|
|
vision?: boolean
|
|
functionCalling?: boolean
|
|
streaming?: boolean
|
|
maxTokens?: number
|
|
contextWindow?: number
|
|
}
|
|
}
|
|
|
|
const modelsWithCapabilities: ExtendedAIModel[] = [
|
|
{
|
|
id: "gpt-4-turbo",
|
|
name: "GPT-4 Turbo",
|
|
provider: "OpenAI",
|
|
capabilities: {
|
|
vision: false,
|
|
functionCalling: true,
|
|
streaming: true,
|
|
maxTokens: 4096,
|
|
contextWindow: 128000,
|
|
},
|
|
},
|
|
{
|
|
id: "gpt-4-vision",
|
|
name: "GPT-4 Vision",
|
|
provider: "OpenAI",
|
|
capabilities: {
|
|
vision: true,
|
|
functionCalling: true,
|
|
streaming: true,
|
|
maxTokens: 4096,
|
|
contextWindow: 128000,
|
|
},
|
|
},
|
|
]
|
|
```
|
|
|
|
## Styling
|
|
|
|
The component uses Radix UI Select with shadcn/ui theming:
|
|
|
|
- Inherits border, background, and text colors from theme
|
|
- Adapts to light/dark mode
|
|
- Hover and focus states for accessibility
|
|
- Mobile-friendly dropdown behavior
|
|
|
|
## Accessibility
|
|
|
|
- Keyboard navigation with arrow keys
|
|
- Screen reader friendly labels
|
|
- Focus management
|
|
- ARIA attributes for proper semantics
|
|
|
|
## Related Components
|
|
|
|
- [AI Chat](/docs/ai/chat) - Chat interface with model selection
|
|
- [AI Playground](/docs/ai/playground) - Test different models
|
|
- [AI Assistant](/docs/ai/assistant) - Conversational AI with model switching
|