PI-MONO
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef, useEffect, type KeyboardEvent } from 'react';
|
||||
import { useState, useMemo, useRef, useEffect, type KeyboardEvent } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
Send,
|
||||
@@ -23,18 +23,32 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useSettings } from '@/state/useSettings';
|
||||
import { useVisibleClaudeModels, useVisibleOpenCodeModels, useVisiblePiMonoModels } from '@/state/useModels';
|
||||
import { useVisiblePiMonoModels } from '@/state/useModels';
|
||||
import type { Attachment } from '@/Screens/Dashboard/Chat/EmbeddableChat';
|
||||
|
||||
const PROVIDER_DISPLAY: Record<string, string> = {
|
||||
anthropic: 'Anthropic',
|
||||
openai: 'OpenAI',
|
||||
opencode: 'OpenCode Zen',
|
||||
google: 'Google',
|
||||
groq: 'Groq',
|
||||
mistral: 'Mistral',
|
||||
xai: 'xAI',
|
||||
openrouter: 'OpenRouter',
|
||||
huggingface: 'Hugging Face',
|
||||
'github-copilot': 'GitHub Copilot',
|
||||
minimax: 'MiniMax',
|
||||
bedrock: 'Amazon Bedrock',
|
||||
'google-vertex': 'Google Vertex AI',
|
||||
'azure-openai': 'Azure OpenAI',
|
||||
};
|
||||
|
||||
export const ChatLauncher = () => {
|
||||
const navigate = useNavigate();
|
||||
const { settings } = useSettings();
|
||||
const claudeModels = useVisibleClaudeModels();
|
||||
const openCodeModels = useVisibleOpenCodeModels();
|
||||
const piMonoModels = useVisiblePiMonoModels();
|
||||
|
||||
const client = useClient();
|
||||
const [provider, setProvider] = useState<'claude' | 'opencode' | 'pi-mono'>(settings.chat.defaultProvider);
|
||||
const [model, setModel] = useState<string | null>(settings.chat.defaultModel);
|
||||
const [input, setInput] = useState('');
|
||||
const [attachments, setAttachments] = useState<Attachment[]>([]);
|
||||
@@ -44,11 +58,23 @@ export const ChatLauncher = () => {
|
||||
const imageInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setProvider(settings.chat.defaultProvider);
|
||||
setModel(settings.chat.defaultModel);
|
||||
}, [settings.chat.defaultProvider, settings.chat.defaultModel]);
|
||||
}, [settings.chat.defaultModel]);
|
||||
|
||||
const models = provider === 'claude' ? claudeModels : provider === 'opencode' ? openCodeModels : piMonoModels;
|
||||
const providers = useMemo(
|
||||
() => [...new Set(piMonoModels.map((m) => m.provider).filter(Boolean))] as string[],
|
||||
[piMonoModels],
|
||||
);
|
||||
|
||||
const activeProvider = piMonoModels.find((m) => m.id === model)?.provider ?? providers[0];
|
||||
const providerModels = piMonoModels.filter((m) => m.provider === activeProvider);
|
||||
|
||||
const displayName = (provider: string) => PROVIDER_DISPLAY[provider] ?? provider;
|
||||
|
||||
const handleProviderClick = (provider: string) => {
|
||||
const firstModel = piMonoModels.find((m) => m.provider === provider);
|
||||
if (firstModel) setModel(firstModel.id);
|
||||
};
|
||||
|
||||
const handleAttachWebpage = async (url: string) => {
|
||||
const idx = attachments.length;
|
||||
@@ -60,7 +86,7 @@ export const ChatLauncher = () => {
|
||||
try {
|
||||
const res = await client.post<{ url: string; title: string; content: string; attachmentId: string }>('/scrape', {
|
||||
url,
|
||||
provider,
|
||||
provider: 'pi-mono',
|
||||
});
|
||||
setAttachments((prev) =>
|
||||
prev.map((a, i) =>
|
||||
@@ -85,7 +111,7 @@ export const ChatLauncher = () => {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('provider', provider);
|
||||
formData.append('provider', 'pi-mono');
|
||||
|
||||
const res = await client.post<{ filename: string; dataUrl: string; attachmentId: string }>('/upload', formData);
|
||||
setAttachments((prev) =>
|
||||
@@ -125,9 +151,7 @@ export const ChatLauncher = () => {
|
||||
attachmentIds.push(a.attachmentId);
|
||||
}
|
||||
|
||||
const route =
|
||||
provider === 'claude' ? '/chat/new' : provider === 'opencode' ? '/chat/opencode/new' : '/chat/pi-mono/new';
|
||||
navigate(route, {
|
||||
navigate('/chat/new', {
|
||||
state: {
|
||||
initialMessage: prompt,
|
||||
model,
|
||||
@@ -259,40 +283,36 @@ export const ChatLauncher = () => {
|
||||
|
||||
<div className="flex items-center justify-between px-4 pb-3">
|
||||
<div className="flex items-center gap-1 rounded-lg bg-duck-dark/5 p-1">
|
||||
{(['claude', 'opencode', 'pi-mono'] as const).map((value) => (
|
||||
{providers.map((provider) => (
|
||||
<button
|
||||
key={value}
|
||||
onClick={() => {
|
||||
setProvider(value);
|
||||
setModel(null);
|
||||
}}
|
||||
key={provider}
|
||||
onClick={() => handleProviderClick(provider)}
|
||||
className={`rounded-md px-3 py-1 text-xs font-medium transition-colors cursor-pointer ${
|
||||
provider === value
|
||||
activeProvider === provider
|
||||
? 'bg-background text-duck-dark shadow-sm'
|
||||
: 'text-duck-dark/50 hover:text-duck-dark/70'
|
||||
}`}
|
||||
>
|
||||
{value === 'claude' ? 'Claude' : value === 'opencode' ? 'OpenCode' : 'Pi'}
|
||||
{displayName(provider)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{models.length > 0 && (
|
||||
{providerModels.length > 0 && (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button className="flex items-center gap-1 text-xs text-duck-dark/50 hover:text-duck-dark/70 cursor-pointer transition-colors">
|
||||
{models.find((m) => m.id === (model ?? models[0]?.id))?.name ?? models[0]?.name}
|
||||
{providerModels.find((m) => m.id === (model ?? providerModels[0]?.id))?.name ?? providerModels[0]?.name}
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="z-[600] max-h-64 overflow-y-auto">
|
||||
{models.map((m) => (
|
||||
{providerModels.map((m) => (
|
||||
<DropdownMenuItem key={m.id} onClick={() => setModel(m.id)} className="cursor-pointer">
|
||||
<Check
|
||||
className={`mr-2 h-3 w-3 ${(model ?? models[0]?.id) === m.id ? 'opacity-100' : 'opacity-0'}`}
|
||||
className={`mr-2 h-3 w-3 ${(model ?? providerModels[0]?.id) === m.id ? 'opacity-100' : 'opacity-0'}`}
|
||||
/>
|
||||
<span className="font-bold">{m.name}</span>
|
||||
{m.provider && <span className="text-duck-dark/50 ml-1">({m.provider})</span>}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
|
||||
Reference in New Issue
Block a user