From ec604a03e1e6ec85d9d50535a8cd7f1864837709 Mon Sep 17 00:00:00 2001 From: Pascal Date: Mon, 2 Feb 2026 16:38:24 +0100 Subject: [PATCH] Update tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActionAttachmentsDropdown.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPickerArgumentForm.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageStatistics.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/index.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/index.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/chat/index.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServerCard/McpServerCardDeleteDialog.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpCapabilitiesBadges.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpConnectionLogs.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServerForm.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServerSelector.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/misc/index.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/misc/TruncatedText.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/misc/TruncatedText.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/components/app/misc/TruncatedText.svelte Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Update tools/server/webui/src/lib/services/mcp.service.ts Co-authored-by: Aleksander Grygier Load more... --- .../ChatAttachments/ChatAttachmentsList.svelte | 1 + .../ChatFormActionAttachmentsDropdown.svelte | 12 ++++++++++++ .../ChatFormActions/ChatFormActions.svelte | 2 ++ .../ChatFormPromptPicker.svelte | 2 ++ .../ChatFormPromptPickerArgumentForm.svelte | 1 + .../ChatMessages/ChatMessageStatistics.svelte | 5 +++++ .../app/chat/ChatMessages/ChatMessages.svelte | 2 ++ .../webui/src/lib/components/app/chat/index.ts | 5 +++-- .../app/content/CollapsibleContentBlock.svelte | 3 +++ .../app/content/MarkdownContent.svelte | 4 ++++ .../app/dialogs/DialogMcpResources.svelte | 14 ++++++++++++++ .../app/mcp/McpCapabilitiesBadges.svelte | 6 ++++++ .../app/mcp/McpConnectionLogs.svelte | 1 + .../app/mcp/McpResourcePreview.svelte | 12 +++++++++--- .../McpServerCardDeleteDialog.svelte | 3 +++ .../components/app/mcp/McpServerForm.svelte | 1 + .../app/mcp/McpServerSelector.svelte | 7 ++++++- .../app/mcp/McpServersSettings.svelte | 5 +++++ .../components/app/misc/TruncatedText.svelte | 7 +++---- .../webui/src/lib/components/app/misc/index.ts | 16 ++++++++-------- .../webui/src/lib/services/mcp.service.ts | 18 +++++++++++++++++- 21 files changed, 108 insertions(+), 19 deletions(-) diff --git a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte index deb8cb9eef..ea9ac97099 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatAttachments/ChatAttachmentsList.svelte @@ -171,6 +171,7 @@ arguments: item.uploadedFile.mcpPrompt.arguments } : null} + {#if mcpPrompt} onFileUpload?.()} > + Images {:else} @@ -104,9 +105,11 @@ disabled > + Images +

Images require vision models to be processed

@@ -119,6 +122,7 @@ onclick={() => onFileUpload?.()} > + Audio Files {:else} @@ -126,9 +130,11 @@ + Audio Files +

Audio files require audio models to be processed

@@ -140,6 +146,7 @@ onclick={() => onFileUpload?.()} > + Text Files @@ -149,6 +156,7 @@ onclick={() => onFileUpload?.()} > + PDF Files {:else} @@ -159,9 +167,11 @@ onclick={() => onFileUpload?.()} > + PDF Files +

PDFs will be converted to text. Image-based PDFs may not work properly.

@@ -175,9 +185,11 @@ onclick={() => onSystemPromptClick?.()} > + System Message +

{systemMessageTooltip}

diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte index ad85355ff4..458cd2f622 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormActions/ChatFormActions.svelte @@ -165,11 +165,13 @@ let hasMcpPromptsSupport = $derived.by(() => { const perChatOverrides = conversationsStore.getAllMcpServerOverrides(); + return mcpStore.hasPromptsCapability(perChatOverrides); }); let hasMcpResourcesSupport = $derived.by(() => { const perChatOverrides = conversationsStore.getAllMcpServerOverrides(); + return mcpStore.hasResourcesCapability(perChatOverrides); }); diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte index 135008c251..4737c5b422 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPicker.svelte @@ -84,6 +84,7 @@ if (!initialized) { prompts = []; + return; } @@ -142,6 +143,7 @@ const fetchCompletions = debounce(async (argName: string, value: string) => { if (!selectedPrompt || value.length < 1) { suggestions[argName] = []; + return; } diff --git a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPickerArgumentForm.svelte b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPickerArgumentForm.svelte index cb5c8c79ea..ec68c7a28f 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPickerArgumentForm.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatForm/ChatFormPromptPicker/ChatFormPromptPickerArgumentForm.svelte @@ -60,6 +60,7 @@ role="alert" > + {promptError} {/if} diff --git a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageStatistics.svelte b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageStatistics.svelte index b31a5ed641..e8b364fa18 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageStatistics.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessageStatistics.svelte @@ -162,13 +162,16 @@ onclick={() => (activeView = ChatMessageStatsView.TOOLS)} > + Tools +

Tool calls

+ +

Agentic summary

diff --git a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte index 07e526e555..8e20c218fa 100644 --- a/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte +++ b/tools/server/webui/src/lib/components/app/chat/ChatMessages/ChatMessages.svelte @@ -105,9 +105,11 @@ : messages.filter((msg) => msg.type !== MessageRole.SYSTEM); let lastAssistantIndex = -1; + for (let i = filteredMessages.length - 1; i >= 0; i--) { if (filteredMessages[i].role === MessageRole.ASSISTANT) { lastAssistantIndex = i; + break; } } diff --git a/tools/server/webui/src/lib/components/app/chat/index.ts b/tools/server/webui/src/lib/components/app/chat/index.ts index c5f1b74420..2673f0b6b6 100644 --- a/tools/server/webui/src/lib/components/app/chat/index.ts +++ b/tools/server/webui/src/lib/components/app/chat/index.ts @@ -2,7 +2,7 @@ * * ATTACHMENTS * - * Components for displaying and managing file attachments in chat messages. + * Components for displaying and managing different attachment types in chat messages. * Supports two operational modes: * - **Readonly mode**: For displaying stored attachments in sent messages (DatabaseMessageExtra[]) * - **Editable mode**: For managing pending uploads in the input form (ChatUploadedFile[]) @@ -96,7 +96,7 @@ export { default as ChatAttachmentsViewAll } from './ChatAttachments/ChatAttachm * FORM * * Components for the chat input area. The form handles user input, file attachments, - * audio recording, and MCP prompt selection. It integrates with multiple stores: + * audio recording, and MCP prompts & resources selection. It integrates with multiple stores: * - `chatStore` for message submission and generation control * - `modelsStore` for model selection and validation * - `mcpStore` for MCP prompt browsing and loading @@ -130,6 +130,7 @@ export { default as ChatAttachmentsViewAll } from './ChatAttachments/ChatAttachm * - File upload via button dropdown (images/text/PDF), drag-drop, or paste * - Audio recording with WAV conversion (when model supports audio) * - MCP prompt picker with search and argument forms + * - MCP reource picker with component to list attached resources at the bottom of Chat Form * - Model selector integration (router mode) * - Loading state with stop button, disabled state for errors * diff --git a/tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte b/tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte index 07f2a1463e..6f4529389f 100644 --- a/tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte +++ b/tools/server/webui/src/lib/components/app/content/CollapsibleContentBlock.svelte @@ -62,7 +62,9 @@ {#if Icon} {/if} + {title} + {#if subtitle} {subtitle} {/if} @@ -76,6 +78,7 @@ })} > + Toggle content diff --git a/tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte b/tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte index 7eabe43fcb..a87fd87e27 100644 --- a/tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte +++ b/tools/server/webui/src/lib/components/app/content/MarkdownContent.svelte @@ -197,9 +197,11 @@ type?: string; position?: { start?: { offset?: number }; end?: { offset?: number } }; }; + if (n.position?.start?.offset != null && n.position?.end?.offset != null) { return `${n.type}-${n.position.start.offset}-${n.position.end.offset}`; } + return `${n.type}-idx${index}`; } @@ -414,6 +416,7 @@ { position: (child as { position?: unknown }).position } as HastRootContent, index ); + nextBlocks.push({ id, html, contentHash: hash }); } @@ -425,6 +428,7 @@ const transformedRoot = (await processorInstance.run( singleNodeRoot as MdastRoot )) as HastRoot; + unstableHtml = processorInstance.stringify(transformedRoot); } diff --git a/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte b/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte index c643e06119..c7b372e0b3 100644 --- a/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte +++ b/tools/server/webui/src/lib/components/app/dialogs/DialogMcpResources.svelte @@ -40,6 +40,7 @@ async function loadResources() { const perChatOverrides = conversationsStore.getAllMcpServerOverrides(); const initialized = await mcpStore.ensureInitialized(perChatOverrides); + if (initialized) { await mcpStore.fetchAllResources(); } @@ -48,6 +49,7 @@ function handleOpenChange(newOpen: boolean) { open = newOpen; onOpenChange?.(newOpen); + if (!newOpen) { selectedResources.clear(); lastSelectedUri = null; @@ -81,6 +83,7 @@ } else { selectedResources.delete(resource.uri); } + lastSelectedUri = resource.uri; } @@ -101,6 +104,7 @@ if (selectedResources.size === 0) return; isAttaching = true; + try { const allResources = getAllResourcesFlat(); const resourcesToAttach = allResources.filter((r) => selectedResources.has(r.uri)); @@ -111,6 +115,7 @@ } const count = resourcesToAttach.length; + toast.success( count === 1 ? `Resource attached: ${resourcesToAttach[0].name}` @@ -127,9 +132,12 @@ async function handleQuickAttach(resource: MCPResourceInfo) { isAttaching = true; + try { await mcpStore.attachResource(resource.uri); + onAttach?.(resource); + toast.success(`Resource attached: ${resource.name}`); } catch (error) { console.error('Failed to attach resource:', error); @@ -144,11 +152,14 @@ + MCP Resources + {#if totalCount > 0} ({totalCount}) {/if} + Browse and attach resources from connected MCP servers to your chat context. @@ -169,6 +180,7 @@ {#if selectedResources.size === 1} {@const allResources = getAllResourcesFlat()} {@const selectedResource = allResources.find((r) => selectedResources.has(r.uri))} + {:else if selectedResources.size > 1}
@@ -184,12 +196,14 @@ + diff --git a/tools/server/webui/src/lib/components/app/mcp/McpCapabilitiesBadges.svelte b/tools/server/webui/src/lib/components/app/mcp/McpCapabilitiesBadges.svelte index 141e97e2de..d17b24ebb0 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpCapabilitiesBadges.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpCapabilitiesBadges.svelte @@ -14,6 +14,7 @@ {#if capabilities.server.tools} + Tools {/if} @@ -21,6 +22,7 @@ {#if capabilities.server.resources} + Resources {/if} @@ -28,6 +30,7 @@ {#if capabilities.server.prompts} + Prompts {/if} @@ -35,6 +38,7 @@ {#if capabilities.server.logging} + Logging {/if} @@ -42,6 +46,7 @@ {#if capabilities.server.completions} + Completions {/if} @@ -49,6 +54,7 @@ {#if capabilities.server.tasks} + Tasks {/if} diff --git a/tools/server/webui/src/lib/components/app/mcp/McpConnectionLogs.svelte b/tools/server/webui/src/lib/components/app/mcp/McpConnectionLogs.svelte index 0240e62380..3ea446de4c 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpConnectionLogs.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpConnectionLogs.svelte @@ -28,6 +28,7 @@ {:else} {/if} + Connection Log ({logs.length}) {#if connectionTimeMs !== undefined} diff --git a/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte b/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte index 03eecf0b7b..ec90cbedf2 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpResourcePreview.svelte @@ -94,18 +94,21 @@ {#if !resource}
+ Select a resource to preview
{:else} -

{resource.title || resource.name}

+

{resource.uri}

+ {#if resource.description}

{resource.description}

{/if}
+
+
-
{#if isLoading}
@@ -143,6 +146,7 @@ {:else if error}
+ {error}
{:else if content} @@ -163,6 +167,7 @@ {:else}
+ Binary content ({blob.mimeType || 'unknown type'})
{/if} @@ -174,17 +179,18 @@ {/if}
- {#if resource.mimeType || resource.annotations}
{#if resource.mimeType} {resource.mimeType} {/if} + {#if resource.annotations?.priority !== undefined} Priority: {resource.annotations.priority} {/if} + Server: {resource.serverName} diff --git a/tools/server/webui/src/lib/components/app/mcp/McpServerCard/McpServerCardDeleteDialog.svelte b/tools/server/webui/src/lib/components/app/mcp/McpServerCard/McpServerCardDeleteDialog.svelte index 22786c72b7..8f650148a2 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpServerCard/McpServerCardDeleteDialog.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpServerCard/McpServerCardDeleteDialog.svelte @@ -15,13 +15,16 @@ Delete Server + Are you sure you want to delete {displayName}? This action cannot be undone. + Cancel + onUseProxyChange?.(checked)} /> + Use llama-server proxy {/if} diff --git a/tools/server/webui/src/lib/components/app/mcp/McpServerSelector.svelte b/tools/server/webui/src/lib/components/app/mcp/McpServerSelector.svelte index 252404369f..488d3fce7c 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpServerSelector.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpServerSelector.svelte @@ -110,14 +110,18 @@ }} /> {/if} + {getServerLabel(server)} + {#if hasError} Error + Error + {/if}
+ + Manage MCP Servers {/snippet} diff --git a/tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte b/tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte index 6d706b5693..c8c582b81b 100644 --- a/tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte +++ b/tools/server/webui/src/lib/components/app/mcp/McpServersSettings.svelte @@ -19,6 +19,7 @@ servers.length > 0 && servers.every((server) => { const state = mcpStore.getHealthCheckState(server.id); + return state.status === 'success' || state.status === 'error'; }); @@ -55,11 +56,13 @@ function saveNewServer() { if (newServerUrlError) return; + mcpStore.addServer({ enabled: true, url: newServerUrl.trim(), headers: newServerHeaders.trim() || undefined }); + isAddingServer = false; newServerUrl = ''; newServerHeaders = ''; @@ -75,6 +78,7 @@ {#if !isAddingServer} {/if} @@ -85,6 +89,7 @@

Add New Server

+