feat: WIP
This commit is contained in:
parent
c3520f1e2c
commit
5acfc403bd
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -18,7 +18,7 @@
|
|||
<div style="display: contents">
|
||||
<script>
|
||||
{
|
||||
__sveltekit_uoz4e7 = {
|
||||
__sveltekit_1a51eho = {
|
||||
base: new URL('.', location).pathname.slice(0, -1)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -247,6 +247,8 @@
|
|||
</Tooltip.Root>
|
||||
{/if}
|
||||
|
||||
<DropdownMenu.Separator />
|
||||
|
||||
<Tooltip.Root delayDuration={TOOLTIP_DELAY_DURATION}>
|
||||
<Tooltip.Trigger class="w-full">
|
||||
<DropdownMenu.Item
|
||||
|
|
@ -264,8 +266,6 @@
|
|||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
|
||||
<DropdownMenu.Separator />
|
||||
|
||||
<DropdownMenu.Sub onOpenChange={handleToolsSubMenuOpen}>
|
||||
<DropdownMenu.SubTrigger class="flex cursor-pointer items-center gap-2">
|
||||
<PencilRuler class="h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
import type { Component } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
class: string;
|
||||
class?: string;
|
||||
onSave?: () => void;
|
||||
initialSection?: SettingsSectionTitle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,64 +140,66 @@
|
|||
</script>
|
||||
|
||||
<div class="flex h-full flex-col">
|
||||
<ScrollArea class="flex-1">
|
||||
<Sidebar.Header class=" top-0 z-10 gap-4 bg-sidebar/50 p-3 pt-4 pb-2 backdrop-blur-lg md:sticky">
|
||||
<a href="#/" onclick={handleMobileSidebarItemClick}>
|
||||
<h1 class="inline-flex items-center gap-1 px-2 text-xl font-semibold">llama.cpp</h1>
|
||||
</a>
|
||||
<ScrollArea class="flex-1">
|
||||
<Sidebar.Header
|
||||
class=" top-0 z-10 gap-4 bg-sidebar/50 p-3 pt-4 pb-2 backdrop-blur-lg md:sticky"
|
||||
>
|
||||
<a href="#/" onclick={handleMobileSidebarItemClick}>
|
||||
<h1 class="inline-flex items-center gap-1 px-2 text-xl font-semibold">llama.cpp</h1>
|
||||
</a>
|
||||
|
||||
<ChatSidebarActions {handleMobileSidebarItemClick} bind:isSearchModeActive bind:searchQuery />
|
||||
</Sidebar.Header>
|
||||
<ChatSidebarActions {handleMobileSidebarItemClick} bind:isSearchModeActive bind:searchQuery />
|
||||
</Sidebar.Header>
|
||||
|
||||
<Sidebar.Group class="mt-2 space-y-2 p-0 px-3">
|
||||
{#if (filteredConversations.length > 0 && isSearchModeActive) || !isSearchModeActive}
|
||||
<Sidebar.GroupLabel>
|
||||
{isSearchModeActive ? 'Search results' : 'Conversations'}
|
||||
</Sidebar.GroupLabel>
|
||||
{/if}
|
||||
<Sidebar.Group class="mt-2 space-y-2 p-0 px-3">
|
||||
{#if (filteredConversations.length > 0 && isSearchModeActive) || !isSearchModeActive}
|
||||
<Sidebar.GroupLabel>
|
||||
{isSearchModeActive ? 'Search results' : 'Conversations'}
|
||||
</Sidebar.GroupLabel>
|
||||
{/if}
|
||||
|
||||
<Sidebar.GroupContent>
|
||||
<Sidebar.Menu>
|
||||
{#each conversationTree as { conversation, depth } (conversation.id)}
|
||||
<Sidebar.MenuItem class="mb-1 p-0">
|
||||
<ChatSidebarConversationItem
|
||||
conversation={{
|
||||
id: conversation.id,
|
||||
name: conversation.name,
|
||||
lastModified: conversation.lastModified,
|
||||
currNode: conversation.currNode,
|
||||
forkedFromConversationId: conversation.forkedFromConversationId
|
||||
}}
|
||||
{depth}
|
||||
{handleMobileSidebarItemClick}
|
||||
isActive={currentChatId === conversation.id}
|
||||
onSelect={selectConversation}
|
||||
onEdit={handleEditConversation}
|
||||
onDelete={handleDeleteConversation}
|
||||
onStop={handleStopGeneration}
|
||||
/>
|
||||
</Sidebar.MenuItem>
|
||||
{/each}
|
||||
<Sidebar.GroupContent>
|
||||
<Sidebar.Menu>
|
||||
{#each conversationTree as { conversation, depth } (conversation.id)}
|
||||
<Sidebar.MenuItem class="mb-1 p-0">
|
||||
<ChatSidebarConversationItem
|
||||
conversation={{
|
||||
id: conversation.id,
|
||||
name: conversation.name,
|
||||
lastModified: conversation.lastModified,
|
||||
currNode: conversation.currNode,
|
||||
forkedFromConversationId: conversation.forkedFromConversationId
|
||||
}}
|
||||
{depth}
|
||||
{handleMobileSidebarItemClick}
|
||||
isActive={currentChatId === conversation.id}
|
||||
onSelect={selectConversation}
|
||||
onEdit={handleEditConversation}
|
||||
onDelete={handleDeleteConversation}
|
||||
onStop={handleStopGeneration}
|
||||
/>
|
||||
</Sidebar.MenuItem>
|
||||
{/each}
|
||||
|
||||
{#if conversationTree.length === 0}
|
||||
<div class="px-2 py-4 text-center">
|
||||
<p class="mb-4 p-4 text-sm text-muted-foreground">
|
||||
{searchQuery.length > 0
|
||||
? 'No results found'
|
||||
: isSearchModeActive
|
||||
? 'Start typing to see results'
|
||||
: 'No conversations yet'}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</Sidebar.Menu>
|
||||
</Sidebar.GroupContent>
|
||||
</Sidebar.Group>
|
||||
</ScrollArea>
|
||||
{#if conversationTree.length === 0}
|
||||
<div class="px-2 py-4 text-center">
|
||||
<p class="mb-4 p-4 text-sm text-muted-foreground">
|
||||
{searchQuery.length > 0
|
||||
? 'No results found'
|
||||
: isSearchModeActive
|
||||
? 'Start typing to see results'
|
||||
: 'No conversations yet'}
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</Sidebar.Menu>
|
||||
</Sidebar.GroupContent>
|
||||
</Sidebar.Group>
|
||||
</ScrollArea>
|
||||
|
||||
<Sidebar.Footer>
|
||||
<ChatSidebarFooter />
|
||||
</Sidebar.Footer>
|
||||
<Sidebar.Footer>
|
||||
<ChatSidebarFooter />
|
||||
</Sidebar.Footer>
|
||||
</div>
|
||||
|
||||
<DialogConfirmation
|
||||
|
|
|
|||
|
|
@ -96,6 +96,5 @@
|
|||
Import / Export
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@
|
|||
|
||||
<div class="space-y-1 pt-0">
|
||||
<Button
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100 {isMcpActive ? 'bg-accent text-accent-foreground' : ''}"
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100 {isMcpActive
|
||||
? 'bg-accent text-accent-foreground'
|
||||
: ''}"
|
||||
onclick={() => {
|
||||
mcpServersDialog.open();
|
||||
}}
|
||||
|
|
@ -27,7 +29,9 @@
|
|||
</Button>
|
||||
|
||||
<Button
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100 {isSettingsActive ? 'bg-accent text-accent-foreground' : ''}"
|
||||
class="w-full justify-between px-2 backdrop-blur-none! hover:[&>kbd]:opacity-100 {isSettingsActive
|
||||
? 'bg-accent text-accent-foreground'
|
||||
: ''}"
|
||||
onclick={() => {
|
||||
chatSettingsDialog.open();
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@
|
|||
import type { SettingsSectionTitle } from '$lib/constants';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
open?: boolean;
|
||||
initialSection?: SettingsSectionTitle;
|
||||
}
|
||||
|
||||
let { onOpenChange, open = false, initialSection }: Props = $props();
|
||||
let { class: className = '', onOpenChange, open = false, initialSection }: Props = $props();
|
||||
|
||||
let chatSettingsRef: ChatSettings | undefined = $state();
|
||||
|
||||
|
|
@ -31,7 +32,7 @@
|
|||
<Dialog.Root {open} onOpenChange={handleClose}>
|
||||
<Dialog.Content
|
||||
class="z-999999 flex h-[100dvh] max-h-[100dvh] min-h-[100dvh] max-w-4xl! flex-col gap-0 rounded-none
|
||||
p-0 md:h-[64vh] md:max-h-[64vh] md:min-h-0 md:rounded-lg"
|
||||
p-0 md:h-[64vh] md:max-h-[64vh] md:min-h-0 md:rounded-lg {className}"
|
||||
>
|
||||
<ChatSettings bind:this={chatSettingsRef} onSave={handleSave} {initialSection} />
|
||||
</Dialog.Content>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@
|
|||
import { McpServerCard, McpServerCardSkeleton, McpServerForm } from '$lib/components/app/mcp';
|
||||
import { MCP_SERVER_ID_PREFIX } from '$lib/constants';
|
||||
import { HealthCheckStatus } from '$lib/enums';
|
||||
import McpLogo from './McpLogo.svelte';
|
||||
|
||||
interface Props {
|
||||
class?: string;
|
||||
}
|
||||
|
||||
|
||||
let { class: className }: Props = $props();
|
||||
|
||||
let servers = $derived(mcpStore.getServersSorted());
|
||||
|
|
@ -83,10 +84,12 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="gap-5 grid md:space-y-4 {className}">
|
||||
<div class="grid gap-5 md:space-y-4 {className}">
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<h4 class="text-base font-semibold">Manage Servers</h4>
|
||||
<div class="flex items-center gap-2">
|
||||
<McpLogo class="h-6 w-6" />
|
||||
|
||||
<h2 class="text-2xl font-semibold">MCP Servers</h2>
|
||||
</div>
|
||||
|
||||
{#if !isAddingServer}
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@
|
|||
: 'text-muted-foreground',
|
||||
isOpen ? 'text-foreground' : ''
|
||||
)}
|
||||
style="max-width: min(calc(100cqw - 9rem), 20rem)"
|
||||
style="max-width: min(calc(100cqw - 9rem), 24rem)"
|
||||
disabled={disabled || updating}
|
||||
>
|
||||
<Package class="h-3.5 w-3.5" />
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@
|
|||
data-slot="sidebar-trigger"
|
||||
variant="ghost"
|
||||
size="icon-lg"
|
||||
class="rounded-full backdrop-blur-lg {className} {sidebar.open ? 'top-1.5' : 'top-0'} md:left-[14.5rem]"
|
||||
class="rounded-full backdrop-blur-lg {className} {sidebar.open
|
||||
? 'top-1.5'
|
||||
: 'top-0'} md:left-[14.5rem]"
|
||||
type="button"
|
||||
onclick={(e) => {
|
||||
onclick?.(e);
|
||||
|
|
@ -31,9 +33,9 @@
|
|||
{...restProps}
|
||||
>
|
||||
{#if sidebar.open}
|
||||
<PanelLeftClose />
|
||||
<PanelLeftClose />
|
||||
{:else}
|
||||
<PanelLeftIcon />
|
||||
<PanelLeftIcon />
|
||||
{/if}
|
||||
<span class="sr-only">Toggle Sidebar</span>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@
|
|||
ChatSidebar,
|
||||
ChatSettings,
|
||||
McpServersSettings,
|
||||
McpLogo,
|
||||
DialogConversationTitleUpdate,
|
||||
DialogChatSettingsImportExport
|
||||
} from '$lib/components/app';
|
||||
import { Settings } from '@lucide/svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { isLoading } from '$lib/stores/chat.svelte';
|
||||
import { conversationsStore, activeMessages } from '$lib/stores/conversations.svelte';
|
||||
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||
|
|
@ -291,16 +294,37 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
{#if !sidebarOpen}
|
||||
<div class="absolute bottom-0 left-0 z-[900] flex flex-col gap-1 p-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-8 w-8 {activePanel === 'mcp' ? 'bg-accent text-accent-foreground' : ''}"
|
||||
onclick={() => (activePanel = activePanel === 'mcp' ? 'chat' : 'mcp')}
|
||||
>
|
||||
<McpLogo class="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-8 w-8 {activePanel === 'settings' ? 'bg-accent text-accent-foreground' : ''}"
|
||||
onclick={() => (activePanel = activePanel === 'settings' ? 'chat' : 'settings')}
|
||||
>
|
||||
<Settings class="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Sidebar.Inset class="flex flex-1 flex-col overflow-hidden">
|
||||
{#if activePanel === 'settings'}
|
||||
<ChatSettings
|
||||
bind:this={chatSettingsRef}
|
||||
onSave={() => (activePanel = 'chat')}
|
||||
initialSection={chatSettingsInitialSection}
|
||||
class="p-8! mx-auto h-full"
|
||||
class="mx-auto h-full p-8!"
|
||||
/>
|
||||
{:else if activePanel === 'mcp'}
|
||||
<McpServersSettings class="w-full mx-auto p-8! md:translate-x-1.5" />
|
||||
<McpServersSettings class="mx-auto w-full p-8! md:translate-x-1.5" />
|
||||
{:else}
|
||||
{@render children?.()}
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Reference in New Issue