mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-01-02 14:22:28 +08:00
* feat: add multi-provider model configuration - Add model config dialog for managing multiple AI providers - Support for OpenAI, Anthropic, Google, Azure, Bedrock, OpenRouter, DeepSeek, SiliconFlow, Ollama, and AI Gateway - Add model selector dropdown in chat panel header - Add API key validation endpoint - Add custom model ID input with keyboard navigation - Fix hover highlight in Command component - Add suggested models for each provider including latest Claude 4.5 series - Store configuration locally in browser * feat: improve model config UI and move selector to chat input - Move model selector from header to chat input (left of send button) - Add per-model validation status (queued, running, valid, invalid) - Filter model selector to only show verified models - Add editable model IDs in config dialog - Add custom model input field alongside suggested models dropdown - Fix hover states on provider buttons and select triggers - Update OpenAI suggested models with GPT-5 series - Add alert-dialog component for delete confirmation * refactor: revert shadcn component changes, apply hover fix at usage site * feat: add AWS credentials support for Bedrock provider - Add AWS Access Key ID, Secret Access Key, Region fields for Bedrock - Show different credential fields based on provider type - Update validation API to handle Bedrock with AWS credentials - Add region selector with common AWS regions * fix: reset Test button after validation completes * fix: reset validation button to Test after success * fix: complete bedrock support and UI/UX improvements - Add bedrock to ALLOWED_CLIENT_PROVIDERS for client credentials - Pass AWS credentials through full chain (headers → API → provider) - Replace non-existent GPT-5 models with real ones (o1, o3-mini) - Add accessibility: aria-labels, focus-visible rings, inline errors - Add more AWS regions (Ohio, London, Paris, Mumbai, Seoul, São Paulo) - Fix setTimeout cleanup with useRef on component unmount - Fix TypeScript type consistency in getSelectedAIConfig fallback * chore: remove unused code - Remove unused setAccessCodeRequired state in chat-panel.tsx - Remove unused getSelectedModel export in model-config.ts * fix: UI/UX improvements for model configuration dialog - Add gradient header styling with icon badge - Change Configuration section icon from Key to Settings2 - Add duplicate model detection with warning banner and inline removal - Filter out already-added models from suggestions dropdown - Add type-to-confirm for deleting providers with 3+ models - Enhance delete confirmation dialog with warning icon - Improve model selector discoverability (show model name + chevron) - Add truncation for long model names with title tooltip - Remove AI provider settings from Settings dialog (now in Model Config) - Extract ValidationButton into reusable component * fix: prevent duplicate model IDs within same provider - Block adding model if ID already exists in provider - Block editing model ID to match existing model in provider * fix: improve duplicate model ID notifications - Add toast notification when trying to add duplicate model - Allow free typing when editing model ID, validate on blur - Show warning toast instead of blocking input * fix: improve duplicate model validation UX in config dialog - Add inline error display for duplicate model IDs - Show red border on input when error exists - Validate on blur with shake animation for edit errors - Prevent saving empty model names - Clear errors when user starts typing - Simplify error styling (small red text, no heavy chips)
158 lines
3.8 KiB
TypeScript
158 lines
3.8 KiB
TypeScript
"use client"
|
|
|
|
import * as React from "react"
|
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
|
|
|
import { cn } from "@/lib/utils"
|
|
import { buttonVariants } from "@/components/ui/button"
|
|
|
|
function AlertDialog({
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
|
|
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
|
|
}
|
|
|
|
function AlertDialogTrigger({
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
|
|
return (
|
|
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
)
|
|
}
|
|
|
|
function AlertDialogPortal({
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
|
|
return (
|
|
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
)
|
|
}
|
|
|
|
function AlertDialogOverlay({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
|
|
return (
|
|
<AlertDialogPrimitive.Overlay
|
|
data-slot="alert-dialog-overlay"
|
|
className={cn(
|
|
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogContent({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
|
|
return (
|
|
<AlertDialogPortal>
|
|
<AlertDialogOverlay />
|
|
<AlertDialogPrimitive.Content
|
|
data-slot="alert-dialog-content"
|
|
className={cn(
|
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
</AlertDialogPortal>
|
|
)
|
|
}
|
|
|
|
function AlertDialogHeader({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="alert-dialog-header"
|
|
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogFooter({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<"div">) {
|
|
return (
|
|
<div
|
|
data-slot="alert-dialog-footer"
|
|
className={cn(
|
|
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
className
|
|
)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogTitle({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
return (
|
|
<AlertDialogPrimitive.Title
|
|
data-slot="alert-dialog-title"
|
|
className={cn("text-lg font-semibold", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogDescription({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
return (
|
|
<AlertDialogPrimitive.Description
|
|
data-slot="alert-dialog-description"
|
|
className={cn("text-muted-foreground text-sm", className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogAction({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
|
|
return (
|
|
<AlertDialogPrimitive.Action
|
|
className={cn(buttonVariants(), className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function AlertDialogCancel({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
|
|
return (
|
|
<AlertDialogPrimitive.Cancel
|
|
className={cn(buttonVariants({ variant: "outline" }), className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export {
|
|
AlertDialog,
|
|
AlertDialogPortal,
|
|
AlertDialogOverlay,
|
|
AlertDialogTrigger,
|
|
AlertDialogContent,
|
|
AlertDialogHeader,
|
|
AlertDialogFooter,
|
|
AlertDialogTitle,
|
|
AlertDialogDescription,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
}
|