{#each servers as server (server.id)}
{#if !initialLoadComplete}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
{:else}
= 0 && highlightedIndex < filteredOptions.length) {
const option = filteredOptions[highlightedIndex];
diff --git a/tools/server/webui/src/lib/components/app/server/ServerErrorSplash.svelte b/tools/server/webui/src/lib/components/app/server/ServerErrorSplash.svelte
index fa4c2842cc..c7f52a7c58 100644
--- a/tools/server/webui/src/lib/components/app/server/ServerErrorSplash.svelte
+++ b/tools/server/webui/src/lib/components/app/server/ServerErrorSplash.svelte
@@ -8,6 +8,7 @@
import { serverStore, serverLoading } from '$lib/stores/server.svelte';
import { config, settingsStore } from '$lib/stores/settings.svelte';
import { fade, fly, scale } from 'svelte/transition';
+ import { KeyboardKey } from '$lib/enums';
interface Props {
class?: string;
@@ -117,7 +118,7 @@
}
function handleApiKeyKeydown(event: KeyboardEvent) {
- if (event.key === 'Enter') {
+ if (event.key === KeyboardKey.ENTER) {
handleSaveApiKey();
}
}
diff --git a/tools/server/webui/src/lib/constants/agentic-ui.ts b/tools/server/webui/src/lib/constants/agentic-ui.ts
new file mode 100644
index 0000000000..a4b9baa272
--- /dev/null
+++ b/tools/server/webui/src/lib/constants/agentic-ui.ts
@@ -0,0 +1 @@
+export const ATTACHMENT_SAVED_REGEX = /\[Attachment saved: ([^\]]+)\]/;
diff --git a/tools/server/webui/src/lib/constants/chat-form.ts b/tools/server/webui/src/lib/constants/chat-form.ts
new file mode 100644
index 0000000000..c4aa6b7ef9
--- /dev/null
+++ b/tools/server/webui/src/lib/constants/chat-form.ts
@@ -0,0 +1,2 @@
+export const INITIAL_FILE_SIZE = 0;
+export const PROMPT_CONTENT_SEPARATOR = '\n\n';
diff --git a/tools/server/webui/src/lib/constants/markdown.ts b/tools/server/webui/src/lib/constants/markdown.ts
new file mode 100644
index 0000000000..783d31a22c
--- /dev/null
+++ b/tools/server/webui/src/lib/constants/markdown.ts
@@ -0,0 +1,4 @@
+export const IMAGE_NOT_ERROR_BOUND_SELECTOR = 'img:not([data-error-bound])';
+export const DATA_ERROR_BOUND_ATTR = 'errorBound';
+export const DATA_ERROR_HANDLED_ATTR = 'errorHandled';
+export const BOOL_TRUE_STRING = 'true';
diff --git a/tools/server/webui/src/lib/constants/mcp-form.ts b/tools/server/webui/src/lib/constants/mcp-form.ts
new file mode 100644
index 0000000000..5a3e8f1dca
--- /dev/null
+++ b/tools/server/webui/src/lib/constants/mcp-form.ts
@@ -0,0 +1 @@
+export const MCP_SERVER_URL_PLACEHOLDER = 'https://mcp.example.com/sse';
diff --git a/tools/server/webui/src/lib/enums/index.ts b/tools/server/webui/src/lib/enums/index.ts
index 0e8504cc1d..051fa58a54 100644
--- a/tools/server/webui/src/lib/enums/index.ts
+++ b/tools/server/webui/src/lib/enums/index.ts
@@ -44,3 +44,5 @@ export { ServerRole, ServerModelStatus } from './server';
export { ParameterSource, SyncableParameterType } from './settings';
export { ColorMode, McpPromptVariant, UrlPrefix } from './ui';
+
+export { KeyboardKey } from './keyboard';
diff --git a/tools/server/webui/src/lib/enums/keyboard.ts b/tools/server/webui/src/lib/enums/keyboard.ts
new file mode 100644
index 0000000000..b8f6d5f7a2
--- /dev/null
+++ b/tools/server/webui/src/lib/enums/keyboard.ts
@@ -0,0 +1,15 @@
+/**
+ * Keyboard key names for event handling
+ */
+export enum KeyboardKey {
+ ENTER = 'Enter',
+ ESCAPE = 'Escape',
+ ARROW_UP = 'ArrowUp',
+ ARROW_DOWN = 'ArrowDown',
+ TAB = 'Tab',
+ D_LOWER = 'd',
+ D_UPPER = 'D',
+ E_UPPER = 'E',
+ K_LOWER = 'k',
+ O_UPPER = 'O'
+}
diff --git a/tools/server/webui/src/routes/+layout.svelte b/tools/server/webui/src/routes/+layout.svelte
index 095827b9ca..705066119d 100644
--- a/tools/server/webui/src/routes/+layout.svelte
+++ b/tools/server/webui/src/routes/+layout.svelte
@@ -15,6 +15,7 @@
import { goto } from '$app/navigation';
import { modelsStore } from '$lib/stores/models.svelte';
import { TOOLTIP_DELAY_DURATION } from '$lib/constants/tooltip-config';
+ import { KeyboardKey } from '$lib/enums';
import { IsMobile } from '$lib/hooks/is-mobile.svelte';
let { children } = $props();
@@ -43,7 +44,7 @@
function handleKeydown(event: KeyboardEvent) {
const isCtrlOrCmd = event.ctrlKey || event.metaKey;
- if (isCtrlOrCmd && event.key === 'k') {
+ if (isCtrlOrCmd && event.key === KeyboardKey.K_LOWER) {
event.preventDefault();
if (chatSidebar?.activateSearchMode) {
chatSidebar.activateSearchMode();
@@ -51,12 +52,12 @@
}
}
- if (isCtrlOrCmd && event.shiftKey && event.key === 'O') {
+ if (isCtrlOrCmd && event.shiftKey && event.key === KeyboardKey.O_UPPER) {
event.preventDefault();
goto('?new_chat=true#/');
}
- if (event.shiftKey && isCtrlOrCmd && event.key === 'E') {
+ if (event.shiftKey && isCtrlOrCmd && event.key === KeyboardKey.E_UPPER) {
event.preventDefault();
if (chatSidebar?.editActiveConversation) {