From e21152dc9636c6d2db6edc9b4531dfc5b2d1cba3 Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Thu, 13 Aug 2026 06:53:56 +0200 Subject: [PATCH] ui: Constants refactor (#26908) * refactor: Constants * refactor: Constants/Enums cleanup * refactor: Constant objects instead of multiple single value constants * refactor: Cleanup constants --- tools/ui/pwa-assets-dark.config.ts | 2 +- tools/ui/pwa-assets.config.ts | 2 +- tools/ui/scripts/vite-plugin-build-info.ts | 2 +- .../ui/scripts/vite-plugin-relativize-base.ts | 2 +- tools/ui/scripts/vite-plugin-splash-screen.ts | 9 +- .../actions/ActionIconCopyToClipboard.svelte | 2 +- ...hatAttachmentsListItemThumbnailFile.svelte | 2 +- ...hatAttachmentsPreviewCurrentItemPdf.svelte | 2 +- ...hatAttachmentsPreviewThumbnailStrip.svelte | 2 +- .../ChatFormActionAddButton.svelte | 3 +- .../ChatFormActionAddDropdown.svelte | 2 +- .../ChatFormActionAddMcpServersSubmenu.svelte | 3 +- .../ChatFormActionAddReasoningSubmenu.svelte | 2 +- .../ChatFormActionAddSheet.svelte | 8 +- .../ChatFormActionAddToolsSubmenu.svelte | 3 +- .../ChatFormActionRecord.svelte | 2 +- .../ChatFormActions/ChatFormActions.svelte | 3 +- .../ChatForm/ChatFormContenteditable.svelte | 6 +- .../ChatFormMentionPicker.svelte | 10 +- .../ChatForm/ChatFormWorkingDirectory.svelte | 23 +--- .../ChatMessage/ChatMessage.svelte | 4 +- .../ChatMessageToolCallBlockDefault.svelte | 2 +- ...essageToolCallBlockExecShellCommand.svelte | 3 +- .../ChatMessageToolCallBlockReadFile.svelte | 4 +- .../ChatMessageToolCallBlockReadMedia.svelte | 2 +- ...atMessageToolCallBlockSearchResults.svelte | 2 +- .../ChatMessageToolCall/ToolCallBlock.svelte | 5 +- .../ChatMessageToolCall/parsers/read-file.ts | 10 +- .../ChatMessageToolCall/parsers/read-media.ts | 2 +- .../ChatMessageToolCall/parsers/write-file.ts | 9 +- .../ChatMessageActionCard.svelte | 2 +- .../ChatMessageReasoningBlock.svelte | 2 +- .../ChatScreenActionScrollDown.svelte | 2 +- .../ChatScreen/ChatScreenServerError.svelte | 2 +- .../content/CollapsibleContentBlock.svelte | 2 +- .../MarkdownContent/MarkdownContent.svelte | 49 +++---- .../plugins/rehype/code-block-utils.ts | 22 ++-- .../plugins/rehype/enhance-code-blocks.ts | 6 +- .../plugins/rehype/enhance-svg-blocks.ts | 35 ++--- .../plugins/rehype/file-badge.ts | 2 +- .../MarkdownContent/plugins/rehype/svg-pre.ts | 8 +- .../app/content/MermaidPreview.svelte | 4 +- .../app/content/MermaidPreviewControls.svelte | 2 +- .../app/content/SyntaxHighlightedCode.svelte | 2 +- .../dialogs/DialogMcpResourcePreview.svelte | 12 +- .../dialogs/DialogMcpResourcesBrowser.svelte | 2 +- .../app/dialogs/DialogMcpServerAddNew.svelte | 9 +- .../dialogs/DialogModelNotAvailable.svelte | 3 +- .../components/app/forms/SearchInput.svelte | 2 +- .../app/mcp/McpActiveServersAvatars.svelte | 3 +- .../app/mcp/McpResourcePreview.svelte | 2 +- .../McpResourcesBrowserHeader.svelte | 2 +- .../McpResourcesBrowserServerItem.svelte | 2 +- .../mcp/McpServerCard/McpServerCard.svelte | 2 +- .../components/app/mcp/McpServerForm.svelte | 16 +-- .../app/misc/HorizontalScrollCarousel.svelte | 2 +- .../app/models/ModelsSelectorOption.svelte | 2 +- .../SidebarNavigationActions.svelte | 2 +- .../SidebarNavigationConversationItem.svelte | 3 +- .../app/server/ServerErrorSplash.svelte | 8 +- .../components/app/server/ServerStatus.svelte | 2 +- .../SettingsChat/SettingsChatFields.svelte | 3 +- .../SettingsChatImportExportSection.svelte | 2 +- .../SettingsChat/SettingsChatToolsTab.svelte | 4 +- .../SettingsChatDesktopSidebar.svelte | 2 +- .../settings/SettingsChatMobileHeader.svelte | 2 +- .../src/lib/components/pwa/PwaMetaTags.svelte | 3 +- .../{agentic.ts => agentic.constants.ts} | 16 +-- ...ndpoints.ts => api-endpoints.constants.ts} | 0 .../constants/{app.ts => app.constants.ts} | 0 .../ui/src/lib/constants/attachment-labels.ts | 4 - ...t-menu.ts => attachment-menu.constants.ts} | 25 +--- ...uto-scroll.ts => auto-scroll.constants.ts} | 0 ...ction.ts => binary-detection.constants.ts} | 0 ...n-tools.ts => built-in-tools.constants.ts} | 14 +- tools/ui/src/lib/constants/cache.constants.ts | 44 +++++++ tools/ui/src/lib/constants/cache.ts | 54 -------- .../{chat-form.ts => chat-form.constants.ts} | 0 .../{cli-flags.ts => cli-flags.constants.ts} | 0 .../src/lib/constants/code-block.constants.ts | 50 ++++++++ tools/ui/src/lib/constants/code-blocks.ts | 8 -- tools/ui/src/lib/constants/code.ts | 27 ---- .../constants/content-detection.constants.ts | 20 +++ ...up.ts => context-gauge-popup.constants.ts} | 0 ...text-keys.ts => context-keys.constants.ts} | 0 ...ctions.ts => control-actions.constants.ts} | 2 - ...rt.ts => conversation-import.constants.ts} | 0 ...ss-classes.ts => css-classes.constants.ts} | 0 .../{database.ts => database.constants.ts} | 2 +- ...-blocks.ts => diagram-blocks.constants.ts} | 0 .../{error.ts => error.constants.ts} | 0 .../lib/constants/floating-ui-constraints.ts | 2 - ...{formatters.ts => formatters.constants.ts} | 0 .../ui/src/lib/constants/headers.constants.ts | 35 +++++ .../{icons.ts => icons.constants.ts} | 0 tools/ui/src/lib/constants/image-size.ts | 3 - tools/ui/src/lib/constants/image.constants.ts | 32 +++++ tools/ui/src/lib/constants/index.ts | 120 +++++++++--------- tools/ui/src/lib/constants/jpeg-exif.ts | 30 ----- ...-pairs.ts => key-value-pairs.constants.ts} | 0 ...ction.ts => latex-protection.constants.ts} | 0 ...eral-html.ts => literal-html.constants.ts} | 5 - .../src/lib/constants/markdown.constants.ts | 17 +++ tools/ui/src/lib/constants/markdown.ts | 5 - ...e-size.ts => max-bundle-size.constants.ts} | 0 .../{mcp-form.ts => mcp-form.constants.ts} | 0 ...-resource.ts => mcp-resource.constants.ts} | 0 .../constants/{mcp.ts => mcp.constants.ts} | 64 +++------- ...on-badge.ts => mention-badge.constants.ts} | 0 ...-blocks.ts => mermaid-blocks.constants.ts} | 0 .../lib/constants/message-export.constants.ts | 24 ++++ tools/ui/src/lib/constants/message-export.ts | 23 ---- .../src/lib/constants/model-id.constants.ts | 43 +++++++ tools/ui/src/lib/constants/model-id.ts | 46 ------- ...-loading.ts => model-loading.constants.ts} | 0 ...h-display.ts => path-display.constants.ts} | 0 .../{precision.ts => precision.constants.ts} | 0 tools/ui/src/lib/constants/processing-info.ts | 8 -- .../constants/{pwa.ts => pwa.constants.ts} | 2 +- .../lib/constants/reasoning-effort-tokens.ts | 12 -- ...ffort.ts => reasoning-effort.constants.ts} | 11 ++ ...s => recommended-mcp-servers.constants.ts} | 0 .../{routes.ts => routes.constants.ts} | 0 .../ui/src/lib/constants/sandbox.constants.ts | 13 ++ ...ngs-keys.ts => settings-keys.constants.ts} | 0 ...stry.ts => settings-registry.constants.ts} | 24 ++-- .../constants/special-characters.constants.ts | 16 +++ .../{storage.ts => storage.constants.ts} | 0 .../constants/{sse.ts => stream.constants.ts} | 8 ++ tools/ui/src/lib/constants/stream.ts | 3 - ...s.ts => supported-file-types.constants.ts} | 0 .../src/lib/constants/svg-blocks.constants.ts | 57 +++++++++ tools/ui/src/lib/constants/svg-blocks.ts | 49 ------- ...er.ts => table-html-restorer.constants.ts} | 0 ...ation.ts => title-generation.constants.ts} | 0 tools/ui/src/lib/constants/tools.ts | 22 ---- tools/ui/src/lib/constants/tooltip-config.ts | 1 - .../lib/constants/{ui.ts => ui.constants.ts} | 43 +++++-- ...-template.ts => uri-template.constants.ts} | 26 +--- .../constants/{url.ts => url.constants.ts} | 0 tools/ui/src/lib/constants/viewport.ts | 1 - .../constants/working-directory.constants.ts | 50 ++++++++ .../ui/src/lib/constants/working-directory.ts | 49 ------- tools/ui/src/lib/enums/attachment.enums.ts | 10 ++ tools/ui/src/lib/enums/index.ts | 7 +- .../lib/hooks/use-chat-form-pickers.svelte.ts | 3 +- .../hooks/use-keyboard-shortcuts.svelte.ts | 2 +- tools/ui/src/lib/hooks/use-pwa.svelte.ts | 3 +- .../lib/hooks/use-reasoning-menu.svelte.ts | 3 +- .../hooks/use-settings-navigation.svelte.ts | 2 +- tools/ui/src/lib/services/chat.service.ts | 21 +-- tools/ui/src/lib/services/index.ts | 2 +- tools/ui/src/lib/services/mcp.service.ts | 14 +- .../ui/src/lib/services/migration.service.ts | 5 +- tools/ui/src/lib/services/models.service.ts | 50 +++----- tools/ui/src/lib/services/router.service.ts | 2 +- tools/ui/src/lib/services/tools.service.ts | 10 +- tools/ui/src/lib/stores/agentic.svelte.ts | 5 +- tools/ui/src/lib/stores/chat.svelte.ts | 20 +-- .../ui/src/lib/stores/conversations.svelte.ts | 32 ++--- .../ui/src/lib/stores/mcp-resources.svelte.ts | 7 +- tools/ui/src/lib/stores/mcp.svelte.ts | 17 +-- tools/ui/src/lib/stores/models.svelte.ts | 7 +- tools/ui/src/lib/stores/tools.svelte.ts | 2 +- tools/ui/src/lib/stores/viewport.svelte.ts | 2 +- tools/ui/src/lib/types/chat.d.ts | 47 ++++++- tools/ui/src/lib/types/index.ts | 10 +- tools/ui/src/lib/types/navigation.d.ts | 14 ++ tools/ui/src/lib/types/tools.d.ts | 10 ++ tools/ui/src/lib/utils/agentic.ts | 34 ++--- tools/ui/src/lib/utils/api-fetch.ts | 2 +- tools/ui/src/lib/utils/api-headers.ts | 22 ++-- tools/ui/src/lib/utils/api-key-validation.ts | 6 +- tools/ui/src/lib/utils/built-in-tools.ts | 13 ++ tools/ui/src/lib/utils/cache-ttl.ts | 10 +- tools/ui/src/lib/utils/cap-img-size.ts | 5 +- .../lib/{constants => utils}/chat-commands.ts | 17 +-- tools/ui/src/lib/utils/code.ts | 27 ++-- .../lib/utils/contenteditable-tokenizer.ts | 2 +- tools/ui/src/lib/utils/cors-proxy.ts | 10 +- tools/ui/src/lib/utils/glob-search.ts | 13 +- tools/ui/src/lib/utils/heic-to-jpeg.ts | 4 +- tools/ui/src/lib/utils/index.ts | 11 +- tools/ui/src/lib/utils/jpeg-orientation.ts | 32 ++--- tools/ui/src/lib/utils/mcp.ts | 47 +++---- tools/ui/src/lib/utils/mention-badge.ts | 7 +- tools/ui/src/lib/utils/path-display.ts | 6 +- .../sandbox.ts => utils/sandbox-tool.ts} | 19 +-- tools/ui/src/lib/utils/sanitize-svg.ts | 10 +- tools/ui/src/lib/utils/stream-identity.ts | 4 +- tools/ui/src/lib/utils/uri-template.ts | 42 +++--- tools/ui/src/lib/utils/working-directory.ts | 36 +++--- tools/ui/src/routes/+error.svelte | 3 +- tools/ui/src/routes/+layout.svelte | 16 ++- tools/ui/src/routes/search/+page.svelte | 2 +- .../tests/client/apikey-splash.svelte.test.ts | 2 +- .../chat-form-enter-code-block.svelte.test.ts | 2 +- ...ettings-registry-invariants.svelte.test.ts | 3 +- ...tings-render-keys-migration.svelte.test.ts | 2 +- .../client/ui-settings-sync.svelte.test.ts | 2 +- tools/ui/tests/unit/agentic-strip.test.ts | 2 +- .../tests/unit/mcp-override-fallback.test.ts | 3 +- .../ui/tests/unit/mcp-servers-default.test.ts | 4 +- tools/ui/tests/unit/mcp-service.test.ts | 8 +- .../unit/parse-mcp-server-settings.test.ts | 2 +- tools/ui/tests/unit/sanitize-headers.test.ts | 8 +- tools/ui/tests/unit/uri-template.test.ts | 8 +- tools/ui/tests/unit/working-directory.test.ts | 10 +- tools/ui/vite.config.ts | 2 +- 209 files changed, 1101 insertions(+), 1137 deletions(-) rename tools/ui/src/lib/constants/{agentic.ts => agentic.constants.ts} (77%) rename tools/ui/src/lib/constants/{api-endpoints.ts => api-endpoints.constants.ts} (100%) rename tools/ui/src/lib/constants/{app.ts => app.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/attachment-labels.ts rename tools/ui/src/lib/constants/{attachment-menu.ts => attachment-menu.constants.ts} (75%) rename tools/ui/src/lib/constants/{auto-scroll.ts => auto-scroll.constants.ts} (100%) rename tools/ui/src/lib/constants/{binary-detection.ts => binary-detection.constants.ts} (100%) rename tools/ui/src/lib/constants/{built-in-tools.ts => built-in-tools.constants.ts} (82%) create mode 100644 tools/ui/src/lib/constants/cache.constants.ts delete mode 100644 tools/ui/src/lib/constants/cache.ts rename tools/ui/src/lib/constants/{chat-form.ts => chat-form.constants.ts} (100%) rename tools/ui/src/lib/constants/{cli-flags.ts => cli-flags.constants.ts} (100%) create mode 100644 tools/ui/src/lib/constants/code-block.constants.ts delete mode 100644 tools/ui/src/lib/constants/code-blocks.ts delete mode 100644 tools/ui/src/lib/constants/code.ts create mode 100644 tools/ui/src/lib/constants/content-detection.constants.ts rename tools/ui/src/lib/constants/{context-gauge-popup.ts => context-gauge-popup.constants.ts} (100%) rename tools/ui/src/lib/constants/{context-keys.ts => context-keys.constants.ts} (100%) rename tools/ui/src/lib/constants/{control-actions.ts => control-actions.constants.ts} (73%) rename tools/ui/src/lib/constants/{conversation-import.ts => conversation-import.constants.ts} (100%) rename tools/ui/src/lib/constants/{css-classes.ts => css-classes.constants.ts} (100%) rename tools/ui/src/lib/constants/{database.ts => database.constants.ts} (93%) rename tools/ui/src/lib/constants/{diagram-blocks.ts => diagram-blocks.constants.ts} (100%) rename tools/ui/src/lib/constants/{error.ts => error.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/floating-ui-constraints.ts rename tools/ui/src/lib/constants/{formatters.ts => formatters.constants.ts} (100%) create mode 100644 tools/ui/src/lib/constants/headers.constants.ts rename tools/ui/src/lib/constants/{icons.ts => icons.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/image-size.ts create mode 100644 tools/ui/src/lib/constants/image.constants.ts delete mode 100644 tools/ui/src/lib/constants/jpeg-exif.ts rename tools/ui/src/lib/constants/{key-value-pairs.ts => key-value-pairs.constants.ts} (100%) rename tools/ui/src/lib/constants/{latex-protection.ts => latex-protection.constants.ts} (100%) rename tools/ui/src/lib/constants/{literal-html.ts => literal-html.constants.ts} (56%) create mode 100644 tools/ui/src/lib/constants/markdown.constants.ts delete mode 100644 tools/ui/src/lib/constants/markdown.ts rename tools/ui/src/lib/constants/{max-bundle-size.ts => max-bundle-size.constants.ts} (100%) rename tools/ui/src/lib/constants/{mcp-form.ts => mcp-form.constants.ts} (100%) rename tools/ui/src/lib/constants/{mcp-resource.ts => mcp-resource.constants.ts} (100%) rename tools/ui/src/lib/constants/{mcp.ts => mcp.constants.ts} (57%) rename tools/ui/src/lib/constants/{mention-badge.ts => mention-badge.constants.ts} (100%) rename tools/ui/src/lib/constants/{mermaid-blocks.ts => mermaid-blocks.constants.ts} (100%) create mode 100644 tools/ui/src/lib/constants/message-export.constants.ts delete mode 100644 tools/ui/src/lib/constants/message-export.ts create mode 100644 tools/ui/src/lib/constants/model-id.constants.ts delete mode 100644 tools/ui/src/lib/constants/model-id.ts rename tools/ui/src/lib/constants/{model-loading.ts => model-loading.constants.ts} (100%) rename tools/ui/src/lib/constants/{path-display.ts => path-display.constants.ts} (100%) rename tools/ui/src/lib/constants/{precision.ts => precision.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/processing-info.ts rename tools/ui/src/lib/constants/{pwa.ts => pwa.constants.ts} (99%) delete mode 100644 tools/ui/src/lib/constants/reasoning-effort-tokens.ts rename tools/ui/src/lib/constants/{reasoning-effort.ts => reasoning-effort.constants.ts} (71%) rename tools/ui/src/lib/constants/{recommended-mcp-servers.ts => recommended-mcp-servers.constants.ts} (100%) rename tools/ui/src/lib/constants/{routes.ts => routes.constants.ts} (100%) create mode 100644 tools/ui/src/lib/constants/sandbox.constants.ts rename tools/ui/src/lib/constants/{settings-keys.ts => settings-keys.constants.ts} (100%) rename tools/ui/src/lib/constants/{settings-registry.ts => settings-registry.constants.ts} (97%) create mode 100644 tools/ui/src/lib/constants/special-characters.constants.ts rename tools/ui/src/lib/constants/{storage.ts => storage.constants.ts} (100%) rename tools/ui/src/lib/constants/{sse.ts => stream.constants.ts} (53%) delete mode 100644 tools/ui/src/lib/constants/stream.ts rename tools/ui/src/lib/constants/{supported-file-types.ts => supported-file-types.constants.ts} (100%) create mode 100644 tools/ui/src/lib/constants/svg-blocks.constants.ts delete mode 100644 tools/ui/src/lib/constants/svg-blocks.ts rename tools/ui/src/lib/constants/{table-html-restorer.ts => table-html-restorer.constants.ts} (100%) rename tools/ui/src/lib/constants/{title-generation.ts => title-generation.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/tools.ts delete mode 100644 tools/ui/src/lib/constants/tooltip-config.ts rename tools/ui/src/lib/constants/{ui.ts => ui.constants.ts} (57%) rename tools/ui/src/lib/constants/{uri-template.ts => uri-template.constants.ts} (71%) rename tools/ui/src/lib/constants/{url.ts => url.constants.ts} (100%) delete mode 100644 tools/ui/src/lib/constants/viewport.ts create mode 100644 tools/ui/src/lib/constants/working-directory.constants.ts delete mode 100644 tools/ui/src/lib/constants/working-directory.ts create mode 100644 tools/ui/src/lib/types/navigation.d.ts create mode 100644 tools/ui/src/lib/utils/built-in-tools.ts rename tools/ui/src/lib/{constants => utils}/chat-commands.ts (65%) rename tools/ui/src/lib/{constants/sandbox.ts => utils/sandbox-tool.ts} (84%) diff --git a/tools/ui/pwa-assets-dark.config.ts b/tools/ui/pwa-assets-dark.config.ts index 1446b47a8..4d8114ee7 100644 --- a/tools/ui/pwa-assets-dark.config.ts +++ b/tools/ui/pwa-assets-dark.config.ts @@ -1,5 +1,5 @@ import { writeThemeFavicons } from './scripts/favicon-colorize'; -import { FAVICON_COLORS, PWA_ASSET_GENERATOR } from './src/lib/constants/pwa'; +import { FAVICON_COLORS, PWA_ASSET_GENERATOR } from './src/lib/constants/pwa.constants'; import { defineConfig } from '@vite-pwa/assets-generator/config'; writeThemeFavicons(FAVICON_COLORS.LIGHT, FAVICON_COLORS.DARK, { diff --git a/tools/ui/pwa-assets.config.ts b/tools/ui/pwa-assets.config.ts index 5fed0a595..f9f8662a2 100644 --- a/tools/ui/pwa-assets.config.ts +++ b/tools/ui/pwa-assets.config.ts @@ -4,7 +4,7 @@ import { PWA_ASSET_GENERATOR, PWA_GENERATOR_DEVICES, THEME_COLORS -} from './src/lib/constants/pwa'; +} from './src/lib/constants/pwa.constants'; import { SplashOrientation } from './src/lib/enums/splash.enums'; import { combinePresetAndAppleSplashScreens, diff --git a/tools/ui/scripts/vite-plugin-build-info.ts b/tools/ui/scripts/vite-plugin-build-info.ts index 800238630..ec864e8d0 100644 --- a/tools/ui/scripts/vite-plugin-build-info.ts +++ b/tools/ui/scripts/vite-plugin-build-info.ts @@ -1,4 +1,4 @@ -import { BUILD_CONFIG } from '../src/lib/constants/pwa'; +import { BUILD_CONFIG } from '../src/lib/constants/pwa.constants'; import { existsSync, writeFileSync } from 'node:fs'; import { resolve } from 'path'; import type { Plugin } from 'vite'; diff --git a/tools/ui/scripts/vite-plugin-relativize-base.ts b/tools/ui/scripts/vite-plugin-relativize-base.ts index f8eac1d66..0e47741ae 100644 --- a/tools/ui/scripts/vite-plugin-relativize-base.ts +++ b/tools/ui/scripts/vite-plugin-relativize-base.ts @@ -1,4 +1,4 @@ -import { BUILD_CONFIG } from '../src/lib/constants/pwa'; +import { BUILD_CONFIG } from '../src/lib/constants/pwa.constants'; import { existsSync, readFileSync, writeFileSync } from 'node:fs'; import { resolve } from 'path'; import type { Plugin } from 'vite'; diff --git a/tools/ui/scripts/vite-plugin-splash-screen.ts b/tools/ui/scripts/vite-plugin-splash-screen.ts index 45d931bab..62b7a063a 100644 --- a/tools/ui/scripts/vite-plugin-splash-screen.ts +++ b/tools/ui/scripts/vite-plugin-splash-screen.ts @@ -1,5 +1,10 @@ -import { NEWLINE, TAB } from '../src/lib/constants/code'; -import { APPLE_DEVICES, BUILD_CONFIG, REGEX_PATTERNS, SPLASH_LINK } from '../src/lib/constants/pwa'; +import { + APPLE_DEVICES, + BUILD_CONFIG, + REGEX_PATTERNS, + SPLASH_LINK +} from '../src/lib/constants/pwa.constants'; +import { NEWLINE, TAB } from '../src/lib/constants/special-characters.constants'; import { SplashOrientation } from '../src/lib/enums/splash.enums'; import type { SplashDimensions } from '../src/lib/types'; import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs'; diff --git a/tools/ui/src/lib/components/app/actions/ActionIconCopyToClipboard.svelte b/tools/ui/src/lib/components/app/actions/ActionIconCopyToClipboard.svelte index 7655f18e8..2d54df89d 100644 --- a/tools/ui/src/lib/components/app/actions/ActionIconCopyToClipboard.svelte +++ b/tools/ui/src/lib/components/app/actions/ActionIconCopyToClipboard.svelte @@ -1,7 +1,7 @@ diff --git a/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenServerError.svelte b/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenServerError.svelte index ae5d91bee..cae37d6f8 100644 --- a/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenServerError.svelte +++ b/tools/ui/src/lib/components/app/chat/ChatScreen/ChatScreenServerError.svelte @@ -1,7 +1,7 @@ diff --git a/tools/ui/src/lib/constants/agentic.ts b/tools/ui/src/lib/constants/agentic.constants.ts similarity index 77% rename from tools/ui/src/lib/constants/agentic.ts rename to tools/ui/src/lib/constants/agentic.constants.ts index 582572a29..e57104e8a 100644 --- a/tools/ui/src/lib/constants/agentic.ts +++ b/tools/ui/src/lib/constants/agentic.constants.ts @@ -5,22 +5,14 @@ export const ATTACHMENT_SAVED_REGEX = /\[Attachment saved: ([^\]]+)\]/; // JSON detection: trimmed content opens with an object or array literal. export const TOOL_RESULT_JSON_OPEN_REGEX = /^[[{]/; -// Markdown structural markers used by `looksLikeMarkdown`. Inline / line-level. -export const MARKDOWN_CODE_FENCE_REGEX = /^(```|~~~)/m; -export const MARKDOWN_ATX_HEADING_REGEX = /^#{1,6}\s+\S/; -export const MARKDOWN_BLOCKQUOTE_REGEX = /^>\s+\S/; -export const MARKDOWN_LIST_BULLET_REGEX = /^\s*[-*+]\s+\S/; -export const MARKDOWN_LIST_NUMBERED_REGEX = /^\s*\d+[.)]\s+\S/; -export const MARKDOWN_LINK_REGEX = /\[[^\]\n]+\]\([^)\s]+\)/; -export const MARKDOWN_BOLD_REGEX = /\*\*[^*\n]+\*\*|__[^_\n]+__/; -export const MARKDOWN_TABLE_SEPARATOR_REGEX = /^\s*\|?[\s:|-]+\|?\s*$/; - // Search-summary wire format used by file-glob and grep tools: // // --- // Total matches: N -export const SEARCH_SUMMARY_SEPARATOR = '---\n'; -export const SEARCH_SUMMARY_TOTAL_REGEX = /Total matches:\s*(\d+)/; +export const SEARCH_SUMMARY = { + SEPARATOR: '---\n', + TOTAL_REGEX: /Total matches:\s*(\d+)/ +} as const; // Separator rendered between stats in the tool-result footer (e.g. between a // result message and the byte/edit count). Plain ASCII spaces bracket a hyphen diff --git a/tools/ui/src/lib/constants/api-endpoints.ts b/tools/ui/src/lib/constants/api-endpoints.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/api-endpoints.ts rename to tools/ui/src/lib/constants/api-endpoints.constants.ts diff --git a/tools/ui/src/lib/constants/app.ts b/tools/ui/src/lib/constants/app.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/app.ts rename to tools/ui/src/lib/constants/app.constants.ts diff --git a/tools/ui/src/lib/constants/attachment-labels.ts b/tools/ui/src/lib/constants/attachment-labels.ts deleted file mode 100644 index be9999c0f..000000000 --- a/tools/ui/src/lib/constants/attachment-labels.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const ATTACHMENT_LABEL_FILE = 'File'; -export const ATTACHMENT_LABEL_PDF_FILE = 'PDF File'; -export const ATTACHMENT_LABEL_MCP_PROMPT = 'MCP Prompt'; -export const ATTACHMENT_LABEL_MCP_RESOURCE = 'MCP Resource'; diff --git a/tools/ui/src/lib/constants/attachment-menu.ts b/tools/ui/src/lib/constants/attachment-menu.constants.ts similarity index 75% rename from tools/ui/src/lib/constants/attachment-menu.ts rename to tools/ui/src/lib/constants/attachment-menu.constants.ts index 1cd7f9ba5..62e03bea6 100644 --- a/tools/ui/src/lib/constants/attachment-menu.ts +++ b/tools/ui/src/lib/constants/attachment-menu.constants.ts @@ -1,33 +1,12 @@ import { FolderOpen, MessageSquare, Zap } from '@lucide/svelte'; -import { FILE_TYPE_ICONS } from '$lib/constants/icons'; +import { FILE_TYPE_ICONS } from '$lib/constants'; import { AttachmentAction, AttachmentItemEnabledWhen, AttachmentItemVisibleWhen, AttachmentMenuItemId } from '$lib/enums'; -import type { Component } from 'svelte'; - -export interface AttachmentMenuItem { - /** Unique identifier for the item */ - id: AttachmentMenuItemId; - /** Display label */ - label: string; - /** Lucide icon component */ - icon: Component; - /** Extra CSS class applied to the item (e.g. for test selectors) */ - class?: string; - /** Whether the item requires a specific modality to be enabled */ - enabledWhen?: AttachmentItemEnabledWhen; - /** Tooltip shown when the item is disabled */ - disabledTooltip?: string; - /** Callback key on the Props interface to invoke when clicked */ - action: AttachmentAction; - /** Whether the item is only shown when a specific capability is present */ - visibleWhen?: AttachmentItemVisibleWhen; - /** Whether this item has a tooltip even when enabled (uses dynamic text) */ - hasEnabledTooltip?: boolean; -} +import type { AttachmentMenuItem } from '$lib/types'; /** * File attachment menu items shown in both the desktop dropdown and mobile sheet. diff --git a/tools/ui/src/lib/constants/auto-scroll.ts b/tools/ui/src/lib/constants/auto-scroll.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/auto-scroll.ts rename to tools/ui/src/lib/constants/auto-scroll.constants.ts diff --git a/tools/ui/src/lib/constants/binary-detection.ts b/tools/ui/src/lib/constants/binary-detection.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/binary-detection.ts rename to tools/ui/src/lib/constants/binary-detection.constants.ts diff --git a/tools/ui/src/lib/constants/built-in-tools.ts b/tools/ui/src/lib/constants/built-in-tools.constants.ts similarity index 82% rename from tools/ui/src/lib/constants/built-in-tools.ts rename to tools/ui/src/lib/constants/built-in-tools.constants.ts index 5bd24ffe8..679c61459 100644 --- a/tools/ui/src/lib/constants/built-in-tools.ts +++ b/tools/ui/src/lib/constants/built-in-tools.constants.ts @@ -20,13 +20,7 @@ import { Terminal } from '@lucide/svelte'; import { BuiltInTool, ToolSource } from '$lib/enums'; -import type { Component } from 'svelte'; - -export interface BuiltinToolUiEntry { - icon: Component; - label: string; - source: ToolSource.BUILTIN | ToolSource.FRONTEND; -} +import type { BuiltinToolUiEntry } from '$lib/types'; export const BUILTIN_TOOL_UI: Readonly> = { [BuiltInTool.EDIT_FILE]: { icon: FilePen, label: 'Edit file', source: ToolSource.BUILTIN }, @@ -56,9 +50,3 @@ export const BUILTIN_TOOL_UI: Readonly> }, [BuiltInTool.WRITE_FILE]: { icon: FilePlus, label: 'Write file', source: ToolSource.BUILTIN } } as const; - -export function getBuiltinToolUi(toolName: string | undefined): BuiltinToolUiEntry | null { - if (!toolName) return null; - - return (BUILTIN_TOOL_UI as Record)[toolName] ?? null; -} diff --git a/tools/ui/src/lib/constants/cache.constants.ts b/tools/ui/src/lib/constants/cache.constants.ts new file mode 100644 index 000000000..b60792d99 --- /dev/null +++ b/tools/ui/src/lib/constants/cache.constants.ts @@ -0,0 +1,44 @@ +/** + * Cache configuration constants + */ + +/** + * Default cache limits when no per-cache overrides are given. + */ +export const CACHE = { + /** Default maximum number of entries in a cache */ + DEFAULT_MAX_ENTRIES: 100, + /** Default TTL (Time-To-Live) for cache entries in milliseconds (5 minutes) */ + DEFAULT_TTL_MS: 5 * 60 * 1000 +} as const; + +/** + * TTL and size for the model props cache. + * Props don't change frequently, so we can cache them longer. + */ +export const MODEL_PROPS_CACHE = { + /** Maximum number of model props to cache */ + MAX_ENTRIES: 50, + /** TTL for model props cache entries in milliseconds (10 minutes) */ + TTL_MS: 10 * 60 * 1000 +} as const; + +/** + * TTL and size for the MCP resource cache. + */ +export const MCP_RESOURCE_CACHE = { + /** Maximum number of MCP resources to cache */ + MAX_ENTRIES: 50, + /** TTL for MCP resource cache entries in milliseconds (5 minutes) */ + TTL_MS: 5 * 60 * 1000 +} as const; + +/** + * Limits for pruning inactive conversation states held in memory. + */ +export const INACTIVE_CONVERSATION = { + /** Maximum age (in ms) for inactive conversation states before cleanup (30 minutes) */ + MAX_AGE_MS: 30 * 60 * 1000, + /** Maximum number of inactive conversation states to keep in memory */ + MAX_STATES: 10 +} as const; diff --git a/tools/ui/src/lib/constants/cache.ts b/tools/ui/src/lib/constants/cache.ts deleted file mode 100644 index 07fe86834..000000000 --- a/tools/ui/src/lib/constants/cache.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Cache configuration constants - */ - -/** - * Default TTL (Time-To-Live) for cache entries in milliseconds - * @default 5 minutes - */ -export const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1000; - -/** - * Default maximum number of entries in a cache - * @default 100 - */ -export const DEFAULT_CACHE_MAX_ENTRIES = 100; - -/** - * TTL for model props cache in milliseconds - * Props don't change frequently, so we can cache them longer - * @default 10 minutes - */ -export const MODEL_PROPS_CACHE_TTL_MS = 10 * 60 * 1000; - -/** - * Maximum number of model props to cache - * @default 50 - */ -export const MODEL_PROPS_CACHE_MAX_ENTRIES = 50; - -/** - * Maximum number of MCP resources to cache - * @default 50 - */ -export const MCP_RESOURCE_CACHE_MAX_ENTRIES = 50; - -/** - * TTL for MCP resource cache entries in milliseconds - * @default 5 minutes - */ -export const MCP_RESOURCE_CACHE_TTL_MS = 5 * 60 * 1000; - -/** - * Maximum number of inactive conversation states to keep in memory - * States for conversations beyond this limit will be cleaned up - * @default 10 - */ -export const MAX_INACTIVE_CONVERSATION_STATES = 10; - -/** - * Maximum age (in ms) for inactive conversation states before cleanup - * States older than this will be removed during cleanup - * @default 30 minutes - */ -export const INACTIVE_CONVERSATION_STATE_MAX_AGE_MS = 30 * 60 * 1000; diff --git a/tools/ui/src/lib/constants/chat-form.ts b/tools/ui/src/lib/constants/chat-form.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/chat-form.ts rename to tools/ui/src/lib/constants/chat-form.constants.ts diff --git a/tools/ui/src/lib/constants/cli-flags.ts b/tools/ui/src/lib/constants/cli-flags.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/cli-flags.ts rename to tools/ui/src/lib/constants/cli-flags.constants.ts diff --git a/tools/ui/src/lib/constants/code-block.constants.ts b/tools/ui/src/lib/constants/code-block.constants.ts new file mode 100644 index 000000000..05db575f9 --- /dev/null +++ b/tools/ui/src/lib/constants/code-block.constants.ts @@ -0,0 +1,50 @@ +// Constants for the markdown code-block renderer: language/fence handling and CSS classes. + +/** Parsing and escaping helpers for the markdown code-block renderer. */ +export const CODE_BLOCK = { + AMPERSAND_REGEX: /&/g, + /** Language fallback used when no language is specified. */ + DEFAULT_LANGUAGE: 'text', + /** Matches opening/closing markdown code fences. */ + FENCE_PATTERN: /^```|\n```/g, + GT_REGEX: />/g, + /** Matches the language specifier at the start of a code fence. */ + LANG_PATTERN: /^(\w*)\n?/, + LT_REGEX: //g; -export const FENCE_PATTERN = /^```|\n```/g; - -// Whitespace-only empty lines (between start of string and first non-empty line). -// Used by trimCodePadding to drop leading/trailing phantom blank rows from LLM -// payload wrappers without touching internal blank lines. -export const TRIM_LEADING_PADDING_REGEX = /^(?:[ \t]*\n)+/; -export const TRIM_TRAILING_PADDING_REGEX = /(?:\n[ \t]*)+$/; - -// Matches either Unix or Windows path separators so `String.split(REGEX)` can -// recover the trailing file-name segment from either `/foo/bar.txt` or -// `C:\foo\bar.txt`. Used wherever a parameter accepts a user-supplied path. -export const FILE_PATH_SEPARATOR_REGEX = /[\\/]/; - -// Separates a file name from its extension, e.g. the '.' in `cover.png`. -export const FILE_EXTENSION_SEPARATOR = '.'; - -// Matches the `text:` prefix that file-type identifiers use to denote a -// plain-text language (e.g. `text:typescript`). Used by tool-call renderers -// to recover the underlying highlight.js language. -export const TEXT_LANGUAGE_PREFIX_REGEX = /^text:/; diff --git a/tools/ui/src/lib/constants/content-detection.constants.ts b/tools/ui/src/lib/constants/content-detection.constants.ts new file mode 100644 index 000000000..c5c05819a --- /dev/null +++ b/tools/ui/src/lib/constants/content-detection.constants.ts @@ -0,0 +1,20 @@ +/** + * String patterns for detecting content kind from MIME types and URIs. + * Used with startsWith/includes checks, not as discriminated values. + */ + +export const MIME_TYPE_PREFIXES = { + IMAGE: 'image/', + TEXT: 'text' +} as const; + +export const MIME_TYPE_SUBSTRINGS = { + JAVASCRIPT: 'javascript', + JSON: 'json', + TYPESCRIPT: 'typescript' +} as const; + +export const URI_PATTERNS = { + DATABASE_KEYWORD: 'database', + DATABASE_SCHEME: 'db://' +} as const; diff --git a/tools/ui/src/lib/constants/context-gauge-popup.ts b/tools/ui/src/lib/constants/context-gauge-popup.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/context-gauge-popup.ts rename to tools/ui/src/lib/constants/context-gauge-popup.constants.ts diff --git a/tools/ui/src/lib/constants/context-keys.ts b/tools/ui/src/lib/constants/context-keys.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/context-keys.ts rename to tools/ui/src/lib/constants/context-keys.constants.ts diff --git a/tools/ui/src/lib/constants/control-actions.ts b/tools/ui/src/lib/constants/control-actions.constants.ts similarity index 73% rename from tools/ui/src/lib/constants/control-actions.ts rename to tools/ui/src/lib/constants/control-actions.constants.ts index 935ae9542..c8ebf701b 100644 --- a/tools/ui/src/lib/constants/control-actions.ts +++ b/tools/ui/src/lib/constants/control-actions.constants.ts @@ -3,5 +3,3 @@ export const CONTROL_ACTION = { END_REASONING: 'reasoning_end' } as const; - -export type ControlAction = (typeof CONTROL_ACTION)[keyof typeof CONTROL_ACTION]; diff --git a/tools/ui/src/lib/constants/conversation-import.ts b/tools/ui/src/lib/constants/conversation-import.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/conversation-import.ts rename to tools/ui/src/lib/constants/conversation-import.constants.ts diff --git a/tools/ui/src/lib/constants/css-classes.ts b/tools/ui/src/lib/constants/css-classes.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/css-classes.ts rename to tools/ui/src/lib/constants/css-classes.constants.ts diff --git a/tools/ui/src/lib/constants/database.ts b/tools/ui/src/lib/constants/database.constants.ts similarity index 93% rename from tools/ui/src/lib/constants/database.ts rename to tools/ui/src/lib/constants/database.constants.ts index 95e698f40..f2c961039 100644 --- a/tools/ui/src/lib/constants/database.ts +++ b/tools/ui/src/lib/constants/database.constants.ts @@ -5,7 +5,7 @@ * naming changes. */ -import { STORAGE_APP_NAME } from './storage'; +import { STORAGE_APP_NAME } from './storage.constants'; /** IndexedDB database name */ export const DB_NAME = STORAGE_APP_NAME; diff --git a/tools/ui/src/lib/constants/diagram-blocks.ts b/tools/ui/src/lib/constants/diagram-blocks.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/diagram-blocks.ts rename to tools/ui/src/lib/constants/diagram-blocks.constants.ts diff --git a/tools/ui/src/lib/constants/error.ts b/tools/ui/src/lib/constants/error.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/error.ts rename to tools/ui/src/lib/constants/error.constants.ts diff --git a/tools/ui/src/lib/constants/floating-ui-constraints.ts b/tools/ui/src/lib/constants/floating-ui-constraints.ts deleted file mode 100644 index 003fc77ac..000000000 --- a/tools/ui/src/lib/constants/floating-ui-constraints.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const VIEWPORT_GUTTER = 8; -export const MENU_OFFSET = 6; diff --git a/tools/ui/src/lib/constants/formatters.ts b/tools/ui/src/lib/constants/formatters.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/formatters.ts rename to tools/ui/src/lib/constants/formatters.constants.ts diff --git a/tools/ui/src/lib/constants/headers.constants.ts b/tools/ui/src/lib/constants/headers.constants.ts new file mode 100644 index 000000000..f40df0571 --- /dev/null +++ b/tools/ui/src/lib/constants/headers.constants.ts @@ -0,0 +1,35 @@ +/** HTTP header handling for API and MCP requests. */ +export const HEADERS = { + /** Canonical casing for the Authorization header (RFC 7235) */ + AUTHORIZATION: 'Authorization', + /** Bearer scheme prefix used for Authorization headers (RFC 6750) */ + BEARER: 'Bearer ', + /** Content-Type HTTP header name */ + CONTENT_TYPE: 'Content-Type', + /** Partial-redaction rules for MCP headers: header name -> visible trailing chars */ + PARTIAL_REDACT: new Map([['mcp-session-id', 5]]), + + /** Header names whose values should be redacted in diagnostic logs */ + REDACTED: new Set([ + 'authorization', + 'api-key', + 'cookie', + 'mcp-session-id', + 'proxy-authorization', + 'set-cookie', + 'x-auth-token', + 'x-api-key' + ]), + + /** Header carrying the stream-session identity (conversation id, optionally with a model suffix) */ + X_CONVERSATION_ID_HEADER: 'X-Conversation-Id', + + /** Header asking the server to encode a tool's output differently, e.g. read_file returning base64. */ + X_RESP_TYPE_HEADER: 'x-resp-type', + + /** Header carrying the working directory a tool call runs in; the model cannot override it */ + X_TOOL_CWD_HEADER: 'x-tool-cwd' +}; + +/** `X_RESP_TYPE_HEADER` value that makes read_file return raw bytes as base64 instead of text. */ +export const RESP_TYPE_BASE64 = 'base64'; diff --git a/tools/ui/src/lib/constants/icons.ts b/tools/ui/src/lib/constants/icons.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/icons.ts rename to tools/ui/src/lib/constants/icons.constants.ts diff --git a/tools/ui/src/lib/constants/image-size.ts b/tools/ui/src/lib/constants/image-size.ts deleted file mode 100644 index 8a7f921fa..000000000 --- a/tools/ui/src/lib/constants/image-size.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const MEGAPIXELS_TO_PIXELS = 1_000_000; - -export const HEIC_JPEG_QUALITY = 0.85; diff --git a/tools/ui/src/lib/constants/image.constants.ts b/tools/ui/src/lib/constants/image.constants.ts new file mode 100644 index 000000000..53a90eaa4 --- /dev/null +++ b/tools/ui/src/lib/constants/image.constants.ts @@ -0,0 +1,32 @@ +/** Image handling constants */ + +export const IMAGE = { + /** JPEG quality used when transcoding HEIC images. */ + HEIC_JPEG_QUALITY: 0.85, + /** Unit conversion: pixels per megapixel. */ + MEGAPIXELS_TO_PIXELS: 1_000_000 +} as const; + +/** + * JPEG and EXIF binary format constants for orientation parsing. + */ +export const EXIF = { + /** APP1 segment marker byte, carries the EXIF payload */ + APP1_MARKER: 0xe1, + /** "Exif" signature opening the APP1 payload, big endian uint32 */ + EXIF_SIGNATURE: 0x45786966, + /** Size in bytes of one IFD directory entry */ + IFD_ENTRY_SIZE: 12, + /** JPEG start of image marker */ + JPEG_SOI_MARKER: 0xffd8, + /** EXIF tag id holding the orientation value */ + ORIENTATION_TAG: 0x0112, + /** Bytes of file prefix to scan, the APP1 EXIF segment sits near the start */ + SCAN_BYTE_LIMIT: 128 * 1024, + /** Start of scan marker byte, compressed data begins and no EXIF follows */ + SOS_MARKER: 0xda, + /** TIFF byte order mark for little endian ("II") */ + TIFF_LITTLE_ENDIAN: 0x4949, + /** TIFF magic number following the byte order mark */ + TIFF_MAGIC: 42 +} as const; diff --git a/tools/ui/src/lib/constants/index.ts b/tools/ui/src/lib/constants/index.ts index 357a33a62..17e5f4d00 100644 --- a/tools/ui/src/lib/constants/index.ts +++ b/tools/ui/src/lib/constants/index.ts @@ -1,67 +1,61 @@ // Central constants export file // All constants should be imported from '$lib/constants' -export * from './agentic'; -export * from './api-endpoints'; -export * from './app'; -export * from './attachment-labels'; -export * from './database'; -export * from './reasoning-effort'; -export * from './reasoning-effort-tokens'; -export * from './recommended-mcp-servers'; -export * from './storage'; -export * from './attachment-menu'; -export * from './auto-scroll'; -export * from './context-gauge-popup'; -export * from './conversation-import'; -export * from './binary-detection'; -export * from './built-in-tools'; -export * from './cache'; -export * from './chat-form'; -export * from './chat-commands'; -export * from './cli-flags'; -export * from './code-blocks'; -export * from './icons'; -export * from './code'; -export * from './context-keys'; -export * from './control-actions'; -export * from './css-classes'; -export * from './floating-ui-constraints'; -export * from './formatters'; -export * from './key-value-pairs'; -export * from './icons'; -export * from './latex-protection'; -export * from './literal-html'; -export * from './markdown'; -export * from './mermaid-blocks'; -export * from './svg-blocks'; -export * from './diagram-blocks'; -export * from './max-bundle-size'; -export * from './mcp'; -export * from './mcp-form'; -export * from './mcp-resource'; -export * from './mention-badge'; -export * from './message-export'; -export * from './path-display'; -export * from './model-id'; -export * from './model-loading'; -export * from './sse'; -export * from './precision'; -export * from './processing-info'; -export * from './pwa'; +export * from './agentic.constants'; +export * from './api-endpoints.constants'; +export * from './app.constants'; +export * from './database.constants'; +export * from './reasoning-effort.constants'; +export * from './recommended-mcp-servers.constants'; +export * from './storage.constants'; +export * from './icons.constants'; +export * from './attachment-menu.constants'; +export * from './auto-scroll.constants'; +export * from './context-gauge-popup.constants'; +export * from './conversation-import.constants'; +export * from './binary-detection.constants'; +export * from './content-detection.constants'; +export * from './built-in-tools.constants'; +export * from './cache.constants'; +export * from './chat-form.constants'; +export * from './cli-flags.constants'; +export * from './code-block.constants'; +export * from './context-keys.constants'; +export * from './control-actions.constants'; +export * from './css-classes.constants'; +export * from './formatters.constants'; +export * from './headers.constants'; +export * from './key-value-pairs.constants'; +export * from './latex-protection.constants'; +export * from './literal-html.constants'; +export * from './markdown.constants'; +export * from './mermaid-blocks.constants'; +export * from './svg-blocks.constants'; +export * from './diagram-blocks.constants'; +export * from './max-bundle-size.constants'; +export * from './error.constants'; +export * from './image.constants'; +export * from './mcp.constants'; +export * from './mcp-form.constants'; +export * from './mcp-resource.constants'; +export * from './mention-badge.constants'; +export * from './message-export.constants'; +export * from './path-display.constants'; +export * from './model-id.constants'; +export * from './model-loading.constants'; +export * from './precision.constants'; +export * from './pwa.constants'; +export * from './routes.constants'; +export * from './sandbox.constants'; +export * from './settings-keys.constants'; +export * from './settings-registry.constants'; +export * from './special-characters.constants'; +export * from './stream.constants'; +export * from './supported-file-types.constants'; +export * from './table-html-restorer.constants'; +export * from './title-generation.constants'; +export * from './ui.constants'; +export * from './uri-template.constants'; +export * from './url.constants'; +export * from './working-directory.constants'; export * from './read-media'; -export * from './routes'; -export * from './sandbox'; -export * from './settings-keys'; -export * from './settings-registry'; -export * from './stream'; -export * from './supported-file-types'; -export * from './table-html-restorer'; -export * from './title-generation'; -export * from './tools'; -export * from './tooltip-config'; -export * from './ui'; -export * from './uri-template'; -export * from './url'; -export * from './viewport'; -export * from './working-directory'; diff --git a/tools/ui/src/lib/constants/jpeg-exif.ts b/tools/ui/src/lib/constants/jpeg-exif.ts deleted file mode 100644 index 5b2591b04..000000000 --- a/tools/ui/src/lib/constants/jpeg-exif.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * JPEG and EXIF binary format constants for orientation parsing. - */ - -/** Bytes of file prefix to scan, the APP1 EXIF segment sits near the start */ -export const EXIF_SCAN_BYTE_LIMIT = 128 * 1024; - -/** JPEG start of image marker */ -export const JPEG_SOI_MARKER = 0xffd8; - -/** APP1 segment marker byte, carries the EXIF payload */ -export const APP1_MARKER = 0xe1; - -/** Start of scan marker byte, compressed data begins and no EXIF follows */ -export const SOS_MARKER = 0xda; - -/** "Exif" signature opening the APP1 payload, big endian uint32 */ -export const EXIF_SIGNATURE = 0x45786966; - -/** TIFF byte order mark for little endian ("II") */ -export const TIFF_LITTLE_ENDIAN = 0x4949; - -/** TIFF magic number following the byte order mark */ -export const TIFF_MAGIC = 42; - -/** EXIF tag id holding the orientation value */ -export const EXIF_ORIENTATION_TAG = 0x0112; - -/** Size in bytes of one IFD directory entry */ -export const IFD_ENTRY_SIZE = 12; diff --git a/tools/ui/src/lib/constants/key-value-pairs.ts b/tools/ui/src/lib/constants/key-value-pairs.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/key-value-pairs.ts rename to tools/ui/src/lib/constants/key-value-pairs.constants.ts diff --git a/tools/ui/src/lib/constants/latex-protection.ts b/tools/ui/src/lib/constants/latex-protection.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/latex-protection.ts rename to tools/ui/src/lib/constants/latex-protection.constants.ts diff --git a/tools/ui/src/lib/constants/literal-html.ts b/tools/ui/src/lib/constants/literal-html.constants.ts similarity index 56% rename from tools/ui/src/lib/constants/literal-html.ts rename to tools/ui/src/lib/constants/literal-html.constants.ts index ed1b0cf0d..8efa6b574 100644 --- a/tools/ui/src/lib/constants/literal-html.ts +++ b/tools/ui/src/lib/constants/literal-html.constants.ts @@ -1,5 +1,3 @@ -export const LINE_BREAK = /\r?\n/; - export const PHRASE_PARENTS = new Set([ 'paragraph', 'heading', @@ -10,6 +8,3 @@ export const PHRASE_PARENTS = new Set([ 'linkReference', 'tableCell' ]); - -export const NBSP = '\u00a0'; -export const TAB_AS_SPACES = NBSP.repeat(4); diff --git a/tools/ui/src/lib/constants/markdown.constants.ts b/tools/ui/src/lib/constants/markdown.constants.ts new file mode 100644 index 000000000..c8289c39a --- /dev/null +++ b/tools/ui/src/lib/constants/markdown.constants.ts @@ -0,0 +1,17 @@ +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'; +export const BOOL_FALSE_STRING = 'false'; + +/** Markdown structural markers used by `looksLikeMarkdown`. Inline / line-level. */ +export const MARKDOWN = { + ATX_HEADING_REGEX: /^#{1,6}\s+\S/, + BLOCKQUOTE_REGEX: /^>\s+\S/, + BOLD_REGEX: /\*\*[^*\n]+\*\*|__[^_\n]+__/, + CODE_FENCE_REGEX: /^(```|~~~)/m, + LINK_REGEX: /\[[^\]\n]+\]\([^)\s]+\)/, + LIST_BULLET_REGEX: /^\s*[-*+]\s+\S/, + LIST_NUMBERED_REGEX: /^\s*\d+[.)]\s+\S/, + TABLE_SEPARATOR_REGEX: /^\s*\|?[\s:|-]+\|?\s*$/ +} as const; diff --git a/tools/ui/src/lib/constants/markdown.ts b/tools/ui/src/lib/constants/markdown.ts deleted file mode 100644 index 1cace78a3..000000000 --- a/tools/ui/src/lib/constants/markdown.ts +++ /dev/null @@ -1,5 +0,0 @@ -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'; -export const BOOL_FALSE_STRING = 'false'; diff --git a/tools/ui/src/lib/constants/max-bundle-size.ts b/tools/ui/src/lib/constants/max-bundle-size.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/max-bundle-size.ts rename to tools/ui/src/lib/constants/max-bundle-size.constants.ts diff --git a/tools/ui/src/lib/constants/mcp-form.ts b/tools/ui/src/lib/constants/mcp-form.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/mcp-form.ts rename to tools/ui/src/lib/constants/mcp-form.constants.ts diff --git a/tools/ui/src/lib/constants/mcp-resource.ts b/tools/ui/src/lib/constants/mcp-resource.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/mcp-resource.ts rename to tools/ui/src/lib/constants/mcp-resource.constants.ts diff --git a/tools/ui/src/lib/constants/mcp.ts b/tools/ui/src/lib/constants/mcp.constants.ts similarity index 57% rename from tools/ui/src/lib/constants/mcp.ts rename to tools/ui/src/lib/constants/mcp.constants.ts index 854cbf9f7..11013d2cb 100644 --- a/tools/ui/src/lib/constants/mcp.ts +++ b/tools/ui/src/lib/constants/mcp.constants.ts @@ -36,11 +36,14 @@ export const DEFAULT_MCP_CONFIG = { export const MCP_SERVER_ID_PREFIX = 'LlamaUI-MCP-Server'; -export const MCP_RECONNECT_INITIAL_DELAY = 1000; -export const MCP_RECONNECT_BACKOFF_MULTIPLIER = 2; -export const MCP_RECONNECT_MAX_DELAY = 30000; -/** Per-attempt timeout for a single reconnection attempt before giving up and backing off. */ -export const MCP_RECONNECT_ATTEMPT_TIMEOUT_MS = 15_000; +/** Backoff policy for reconnecting to a dropped MCP server. */ +export const MCP_RECONNECT = { + /** Per-attempt timeout for a single reconnection attempt before giving up and backing off. */ + ATTEMPT_TIMEOUT_MS: 15_000, + BACKOFF_MULTIPLIER: 2, + INITIAL_DELAY: 1000, + MAX_DELAY: 30000 +}; /** Maximum number of MCP server avatars to display in the chat form */ export const MAX_DISPLAYED_MCP_AVATARS = 4; @@ -48,40 +51,20 @@ export const MAX_DISPLAYED_MCP_AVATARS = 4; /** Expected count when two theme-less icons represent a light/dark pair */ export const EXPECTED_THEMED_ICON_PAIR_COUNT = 2; -/** CORS proxy URL query parameter name */ -export const CORS_PROXY_URL_PARAM = 'url'; +/** CORS proxy connection settings */ +export const CORS_PROXY = { + /** Header prefix for headers that should be forwarded by the CORS proxy */ + HEADER_PREFIX: 'x-llama-server-proxy-header-', + /** CORS proxy URL query parameter name */ + URL_PARAM: 'url' +} as const; -/** Header prefix for headers that should be forwarded by the CORS proxy */ -export const CORS_PROXY_HEADER_PREFIX = 'x-llama-server-proxy-header-'; - -/** Number of trailing characters to keep visible when partially redacting mcp-session-id */ -export const MCP_SESSION_ID_VISIBLE_CHARS = 5; - -/** Partial-redaction rules for MCP headers: header name -> visible trailing chars */ -export const MCP_PARTIAL_REDACT_HEADERS = new Map([ - ['mcp-session-id', MCP_SESSION_ID_VISIBLE_CHARS] -]); - -/** Bearer scheme prefix used for Authorization headers (RFC 6750) */ -export const BEARER_PREFIX = 'Bearer '; - -/** Canonical casing for the Authorization header (RFC 7235) */ -export const AUTHORIZATION_HEADER = 'Authorization'; - -/** Content-Type HTTP header name */ -export const CONTENT_TYPE_HEADER = 'Content-Type'; - -/** Header names whose values should be redacted in diagnostic logs */ -export const REDACTED_HEADERS = new Set([ - 'authorization', - 'api-key', - 'cookie', - 'mcp-session-id', - 'proxy-authorization', - 'set-cookie', - 'x-auth-token', - 'x-api-key' -]); +/** Standard SSE endpoint path indicators */ +export const MCP_SSE = { + ENDPOINT: '/sse', + ENDPOINT_QUERY: '/sse?', + ENDPOINT_SLASH: '/sse/' +} as const; /** Human-readable labels for MCP transport types */ export const MCP_TRANSPORT_LABELS: Record = { @@ -96,8 +79,3 @@ export const MCP_TRANSPORT_ICONS: Record = { [MCPTransportType.STREAMABLE_HTTP]: Globe, [MCPTransportType.WEBSOCKET]: Zap }; - -/** Standard SSE endpoint path indicators */ -export const MCP_SSE_ENDPOINT = '/sse'; -export const MCP_SSE_ENDPOINT_SLASH = '/sse/'; -export const MCP_SSE_ENDPOINT_QUERY = '/sse?'; diff --git a/tools/ui/src/lib/constants/mention-badge.ts b/tools/ui/src/lib/constants/mention-badge.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/mention-badge.ts rename to tools/ui/src/lib/constants/mention-badge.constants.ts diff --git a/tools/ui/src/lib/constants/mermaid-blocks.ts b/tools/ui/src/lib/constants/mermaid-blocks.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/mermaid-blocks.ts rename to tools/ui/src/lib/constants/mermaid-blocks.constants.ts diff --git a/tools/ui/src/lib/constants/message-export.constants.ts b/tools/ui/src/lib/constants/message-export.constants.ts new file mode 100644 index 000000000..f6c576d79 --- /dev/null +++ b/tools/ui/src/lib/constants/message-export.constants.ts @@ -0,0 +1,24 @@ +// Conversation exporter / filename constants + +export const EXPORT_CONV = { + // Producer marker carried by the session record of a JSONL export + HARNESS: 'llama.app', + // Length of the trimmed conversation ID in the filename + ID_TRIM_LENGTH: 8, + // Replacements to the ISO date for use in the export filename + ISO_DATE_TIME_SEPARATOR: 'T', + + ISO_DATE_TIME_SEPARATOR_REPLACEMENT: '_', + + ISO_TIME_SEPARATOR: ':', + ISO_TIME_SEPARATOR_REPLACEMENT: '-', + // Characters to keep in the ISO timestamp. 19 keeps 2026-01-01T00:00:00 + ISO_TIMESTAMP_SLICE: 19, + + MULTIPLE_UNDERSCORE_REGEX: /_+/g, + // Maximum length of the sanitized conversation name snippet + NAME_SUFFIX_MAX_LENGTH: 20, + // Replacements for making the conversation title filename-friendly + NON_ALPHANUMERIC_REGEX: /[^a-z0-9]/gi, + NONALNUM_REPLACEMENT: '_' +} as const; diff --git a/tools/ui/src/lib/constants/message-export.ts b/tools/ui/src/lib/constants/message-export.ts deleted file mode 100644 index fc4dbe259..000000000 --- a/tools/ui/src/lib/constants/message-export.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Conversation filename constants - -// Length of the trimmed conversation ID in the filename -export const EXPORT_CONV_ID_TRIM_LENGTH = 8; -// Maximum length of the sanitized conversation name snippet -export const EXPORT_CONV_NAME_SUFFIX_MAX_LENGTH = 20; -// Characters to keep in the ISO timestamp. 19 keeps 2026-01-01T00:00:00 -export const ISO_TIMESTAMP_SLICE_LENGTH = 19; - -// Producer marker carried by the session record of a JSONL export -export const SESSION_HARNESS = 'llama.app'; - -// Replacements for making the conversation title filename-friendly -export const NON_ALPHANUMERIC_REGEX = /[^a-z0-9]/gi; -export const EXPORT_CONV_NONALNUM_REPLACEMENT = '_'; -export const MULTIPLE_UNDERSCORE_REGEX = /_+/g; - -// Replacements to the ISO date for use in the export filename -export const ISO_DATE_TIME_SEPARATOR = 'T'; -export const ISO_DATE_TIME_SEPARATOR_REPLACEMENT = '_'; - -export const ISO_TIME_SEPARATOR = ':'; -export const ISO_TIME_SEPARATOR_REPLACEMENT = '-'; diff --git a/tools/ui/src/lib/constants/model-id.constants.ts b/tools/ui/src/lib/constants/model-id.constants.ts new file mode 100644 index 000000000..081a13e0e --- /dev/null +++ b/tools/ui/src/lib/constants/model-id.constants.ts @@ -0,0 +1,43 @@ +/** + * Parsing of `org/ModelName[-tag][:quant]` style model IDs. + */ + +export const MODEL_ID = { + /** + * Matches an activated-parameter-count segment, e.g. `A10B`, `a2.4b`. + * The leading `A`/`a` distinguishes it from a regular params segment. + */ + ACTIVATED_PARAMS_RE: /^[Aa]\d+(\.\d+)?[BbMmKkTt]$/, + + /** Matches prefix for custom quantization types, e.g. `UD-Q8_K_XL`. */ + CUSTOM_QUANTIZATION_PREFIX_RE: /^UD$/i, + /** Container format segments to exclude from tags (every model uses these). */ + IGNORED_SEGMENTS: new Set(['GGUF', 'GGML']), + /** Sentinel value returned by `indexOf` when a substring is not found. */ + NOT_FOUND: -1, + + /** Separates `` from `` in a model ID, e.g. `org/ModelName`. */ + ORG_SEPARATOR: '/', + + /** + * Matches a parameter-count segment, e.g. `7B`, `1.5b`, `120M`. + * The optional leading `E` covers effective-parameter sizes, e.g. Gemma's + * `E2B`/`E4B` (MatFormer models sized by resident params). + */ + PARAMS_RE: /^[Ee]?\d+(\.\d+)?[BbMmKkTt]$/, + + /** + * Matches a quantization/precision segment, e.g. `Q4_K_M`, `IQ4_XS`, `F16`, `BF16`, `MXFP4`. + * Case-insensitive to handle both uppercase and lowercase inputs. + */ + QUANTIZATION_SEGMENT_RE: /^(I?Q\d+(_[A-Z0-9]+)*|F\d+|BF\d+|MXFP\d+(_[A-Z0-9]+)*)$/i, + + /** Separates the model path from the quantization tag, e.g. `model:Q4_K_M`. */ + QUANTIZATION_SEPARATOR: ':', + + /** Separates named segments within the model path, e.g. `ModelName-7B-GGUF`. */ + SEGMENT_SEPARATOR: '-', + + /** Matches a trailing weight file extension, e.g. `model.gguf` -> `model`. */ + WEIGHT_EXTENSION_RE: /\.(gguf|ggml)$/i +}; diff --git a/tools/ui/src/lib/constants/model-id.ts b/tools/ui/src/lib/constants/model-id.ts deleted file mode 100644 index 4108a2132..000000000 --- a/tools/ui/src/lib/constants/model-id.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** Sentinel value returned by `indexOf` when a substring is not found. */ -export const MODEL_ID_NOT_FOUND = -1; - -/** Separates `` from `` in a model ID, e.g. `org/ModelName`. */ -export const MODEL_ID_ORG_SEPARATOR = '/'; - -/** Separates named segments within the model path, e.g. `ModelName-7B-GGUF`. */ -export const MODEL_ID_SEGMENT_SEPARATOR = '-'; - -/** Separates the model path from the quantization tag, e.g. `model:Q4_K_M`. */ -export const MODEL_ID_QUANTIZATION_SEPARATOR = ':'; - -/** - * Matches a quantization/precision segment, e.g. `Q4_K_M`, `IQ4_XS`, `F16`, `BF16`, `MXFP4`. - * Case-insensitive to handle both uppercase and lowercase inputs. - */ -export const MODEL_QUANTIZATION_SEGMENT_RE = - /^(I?Q\d+(_[A-Z0-9]+)*|F\d+|BF\d+|MXFP\d+(_[A-Z0-9]+)*)$/i; - -/** - * Matches prefix for custom quantization types, e.g. `UD-Q8_K_XL`. - */ -export const MODEL_CUSTOM_QUANTIZATION_PREFIX_RE = /^UD$/i; - -/** - * Matches a parameter-count segment, e.g. `7B`, `1.5b`, `120M`. - * The optional leading `E` covers effective-parameter sizes, e.g. Gemma's - * `E2B`/`E4B` (MatFormer models sized by resident params). - */ -export const MODEL_PARAMS_RE = /^[Ee]?\d+(\.\d+)?[BbMmKkTt]$/; - -/** - * Matches an activated-parameter-count segment, e.g. `A10B`, `a2.4b`. - * The leading `A`/`a` distinguishes it from a regular params segment. - */ -export const MODEL_ACTIVATED_PARAMS_RE = /^[Aa]\d+(\.\d+)?[BbMmKkTt]$/; - -/** - * Container format segments to exclude from tags (every model uses these). - */ -export const MODEL_IGNORED_SEGMENTS = new Set(['GGUF', 'GGML']); - -/** - * Matches a trailing weight file extension, e.g. `model.gguf` -> `model`. - */ -export const MODEL_WEIGHT_EXTENSION_RE = /\.(gguf|ggml)$/i; diff --git a/tools/ui/src/lib/constants/model-loading.ts b/tools/ui/src/lib/constants/model-loading.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/model-loading.ts rename to tools/ui/src/lib/constants/model-loading.constants.ts diff --git a/tools/ui/src/lib/constants/path-display.ts b/tools/ui/src/lib/constants/path-display.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/path-display.ts rename to tools/ui/src/lib/constants/path-display.constants.ts diff --git a/tools/ui/src/lib/constants/precision.ts b/tools/ui/src/lib/constants/precision.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/precision.ts rename to tools/ui/src/lib/constants/precision.constants.ts diff --git a/tools/ui/src/lib/constants/processing-info.ts b/tools/ui/src/lib/constants/processing-info.ts deleted file mode 100644 index 2c3f7dc53..000000000 --- a/tools/ui/src/lib/constants/processing-info.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const PROCESSING_INFO_TIMEOUT = 2000; - -/** - * Statistics units labels - */ -export const STATS_UNITS = { - TOKENS_PER_SECOND: 't/s' -} as const; diff --git a/tools/ui/src/lib/constants/pwa.ts b/tools/ui/src/lib/constants/pwa.constants.ts similarity index 99% rename from tools/ui/src/lib/constants/pwa.ts rename to tools/ui/src/lib/constants/pwa.constants.ts index 4da37c06b..e807f4a97 100644 --- a/tools/ui/src/lib/constants/pwa.ts +++ b/tools/ui/src/lib/constants/pwa.constants.ts @@ -3,7 +3,7 @@ * definitions across the codebase. */ -import { APP_NAME } from './app'; +import { APP_NAME } from './app.constants'; export const MEDIA_QUERIES = { DISPLAY_MODE_STANDALONE: '(display-mode: standalone)', diff --git a/tools/ui/src/lib/constants/reasoning-effort-tokens.ts b/tools/ui/src/lib/constants/reasoning-effort-tokens.ts deleted file mode 100644 index a0c244e5e..000000000 --- a/tools/ui/src/lib/constants/reasoning-effort-tokens.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ReasoningEffort } from '$lib/enums'; - -/** - * Reasoning effort to token budget mapping. - * Maps the ReasoningEffort enum values to concrete token counts for the server. - */ -export const REASONING_EFFORT_TOKENS: Record = { - [ReasoningEffort.HIGH]: 8192, - [ReasoningEffort.LOW]: 512, - [ReasoningEffort.MAX]: -1, // unlimited - [ReasoningEffort.MEDIUM]: 2048 -}; diff --git a/tools/ui/src/lib/constants/reasoning-effort.ts b/tools/ui/src/lib/constants/reasoning-effort.constants.ts similarity index 71% rename from tools/ui/src/lib/constants/reasoning-effort.ts rename to tools/ui/src/lib/constants/reasoning-effort.constants.ts index 4cbb7388b..e8ec5f0e8 100644 --- a/tools/ui/src/lib/constants/reasoning-effort.ts +++ b/tools/ui/src/lib/constants/reasoning-effort.constants.ts @@ -22,3 +22,14 @@ export const REASONING_EFFORT_LEVELS: ReasoningEffortLevel[] = [ { label: 'High', value: ReasoningEffort.HIGH }, { hasInfo: true, label: 'Max', value: ReasoningEffort.MAX } ]; + +/** + * Reasoning effort to token budget mapping. + * Maps the ReasoningEffort enum values to concrete token counts for the server. + */ +export const REASONING_EFFORT_TOKENS: Record = { + [ReasoningEffort.HIGH]: 8192, + [ReasoningEffort.LOW]: 512, + [ReasoningEffort.MAX]: -1, // unlimited + [ReasoningEffort.MEDIUM]: 2048 +}; diff --git a/tools/ui/src/lib/constants/recommended-mcp-servers.ts b/tools/ui/src/lib/constants/recommended-mcp-servers.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/recommended-mcp-servers.ts rename to tools/ui/src/lib/constants/recommended-mcp-servers.constants.ts diff --git a/tools/ui/src/lib/constants/routes.ts b/tools/ui/src/lib/constants/routes.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/routes.ts rename to tools/ui/src/lib/constants/routes.constants.ts diff --git a/tools/ui/src/lib/constants/sandbox.constants.ts b/tools/ui/src/lib/constants/sandbox.constants.ts new file mode 100644 index 000000000..9846e471a --- /dev/null +++ b/tools/ui/src/lib/constants/sandbox.constants.ts @@ -0,0 +1,13 @@ +import { BuiltInTool } from '$lib/enums'; + +export const SANDBOX_TOOL_NAME = BuiltInTool.RUN_JAVASCRIPT; + +export const SANDBOX_TIMEOUT_MS_DEFAULT = 10000; + +export const SANDBOX_TIMEOUT_MS_MAX = 30000; + +export const SANDBOX_OUTPUT_MAX_CHARS = 8192; + +export const SANDBOX_EMPTY_OUTPUT = '(no output)'; + +export const SANDBOX_TRUNCATION_NOTICE = '[output truncated]'; diff --git a/tools/ui/src/lib/constants/settings-keys.ts b/tools/ui/src/lib/constants/settings-keys.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/settings-keys.ts rename to tools/ui/src/lib/constants/settings-keys.constants.ts diff --git a/tools/ui/src/lib/constants/settings-registry.ts b/tools/ui/src/lib/constants/settings-registry.constants.ts similarity index 97% rename from tools/ui/src/lib/constants/settings-registry.ts rename to tools/ui/src/lib/constants/settings-registry.constants.ts index ada029a33..e44459957 100644 --- a/tools/ui/src/lib/constants/settings-registry.ts +++ b/tools/ui/src/lib/constants/settings-registry.constants.ts @@ -1,12 +1,9 @@ -import { CLI_FLAGS } from './cli-flags'; -import { DEFAULT_MCP_CONFIG } from './mcp'; -import { ROUTES, SETTINGS_SECTION_SLUGS } from './routes'; -import { SETTINGS_KEYS } from './settings-keys'; -import { TITLE_GENERATION } from './title-generation'; -import { - FILE_GLOB_SEARCH_PICKERS_DEFAULT_SEARCH_DEPTH, - FILE_GLOB_SEARCH_PICKERS_MAX_SEARCH_DEPTH -} from './working-directory'; +import { CLI_FLAGS } from './cli-flags.constants'; +import { DEFAULT_MCP_CONFIG } from './mcp.constants'; +import { ROUTES, SETTINGS_SECTION_SLUGS } from './routes.constants'; +import { SETTINGS_KEYS } from './settings-keys.constants'; +import { TITLE_GENERATION } from './title-generation.constants'; +import { FILE_GLOB_SEARCH_PICKERS } from './working-directory.constants'; import { AlertTriangle, Code, @@ -14,7 +11,6 @@ import { Funnel, ListRestart, Monitor, - Monitor as MonitorIcon, Moon, PencilRuler, Sliders, @@ -53,7 +49,7 @@ const STANDALONE_SECTIONS: { title: SettingsSectionTitle; slug: string; icon: Co } ]; const COLOR_MODE_OPTIONS: Array<{ value: string; label: string; icon: Component }> = [ - { icon: MonitorIcon, label: 'System', value: ColorMode.SYSTEM }, + { icon: Monitor, label: 'System', value: ColorMode.SYSTEM }, { icon: Sun, label: 'Light', value: ColorMode.LIGHT }, { icon: Moon, label: 'Dark', value: ColorMode.DARK } ]; @@ -106,14 +102,14 @@ const SETTINGS_REGISTRY: Record = { type: SettingsFieldType.INPUT }, { - defaultValue: FILE_GLOB_SEARCH_PICKERS_DEFAULT_SEARCH_DEPTH, + defaultValue: FILE_GLOB_SEARCH_PICKERS.DEFAULT_SEARCH_DEPTH, help: 'How many directory levels below the working directory the @-mention file search descends. Larger values surface deeply nested files but take longer on large trees.', isPositiveInteger: true, key: SETTINGS_KEYS.MENTION_SEARCH_MAX_DEPTH, label: 'Mention search depth', - max: FILE_GLOB_SEARCH_PICKERS_MAX_SEARCH_DEPTH, + max: FILE_GLOB_SEARCH_PICKERS.MAX_SEARCH_DEPTH, min: 1, - placeholder: `${FILE_GLOB_SEARCH_PICKERS_DEFAULT_SEARCH_DEPTH}`, + placeholder: `${FILE_GLOB_SEARCH_PICKERS.DEFAULT_SEARCH_DEPTH}`, section: SETTINGS_SECTION_SLUGS.AGENTIC, type: SettingsFieldType.INPUT } diff --git a/tools/ui/src/lib/constants/special-characters.constants.ts b/tools/ui/src/lib/constants/special-characters.constants.ts new file mode 100644 index 000000000..aaeebca33 --- /dev/null +++ b/tools/ui/src/lib/constants/special-characters.constants.ts @@ -0,0 +1,16 @@ +// Control / whitespace / formatting characters that appear literally inside rendered text. + +/** Line feed. */ +export const NEWLINE = '\n'; + +/** Horizontal tab. */ +export const TAB = '\t'; + +/** Non-breaking space. */ +export const NBSP = '\u00a0'; + +/** Non-breaking spaces used to render a tab stop that whitespace collapsing would otherwise squash. */ +export const TAB_AS_SPACES = NBSP.repeat(4); + +/** Matches a CR-terminated or bare LF line break. */ +export const LINE_BREAK = /\r?\n/; diff --git a/tools/ui/src/lib/constants/storage.ts b/tools/ui/src/lib/constants/storage.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/storage.ts rename to tools/ui/src/lib/constants/storage.constants.ts diff --git a/tools/ui/src/lib/constants/sse.ts b/tools/ui/src/lib/constants/stream.constants.ts similarity index 53% rename from tools/ui/src/lib/constants/sse.ts rename to tools/ui/src/lib/constants/stream.constants.ts index 0eb4b6ede..64f67243c 100644 --- a/tools/ui/src/lib/constants/sse.ts +++ b/tools/ui/src/lib/constants/stream.constants.ts @@ -1,3 +1,11 @@ +// grace window after a visibilitychange before we kick a reader whose socket likely died +// while the tab was hidden. covers brief background pauses without thrashing live streams +export const STREAM_VISIBILITY_KICK_MS = 3000; + +// separator joining a conversation id and its per-model stream identity +// suffix (conv::model) used by the server side replay buffer +export const CONVERSATION_ID_SEPARATOR = '::'; + /** * Server-sent events wire format, shared by the chat stream and the * /models/sse status feed (text/event-stream). diff --git a/tools/ui/src/lib/constants/stream.ts b/tools/ui/src/lib/constants/stream.ts deleted file mode 100644 index 67951ee95..000000000 --- a/tools/ui/src/lib/constants/stream.ts +++ /dev/null @@ -1,3 +0,0 @@ -// grace window after a visibilitychange before we kick a reader whose socket likely died -// while the tab was hidden. covers brief background pauses without thrashing live streams -export const STREAM_VISIBILITY_KICK_MS = 3000; diff --git a/tools/ui/src/lib/constants/supported-file-types.ts b/tools/ui/src/lib/constants/supported-file-types.constants.ts similarity index 100% rename from tools/ui/src/lib/constants/supported-file-types.ts rename to tools/ui/src/lib/constants/supported-file-types.constants.ts diff --git a/tools/ui/src/lib/constants/svg-blocks.constants.ts b/tools/ui/src/lib/constants/svg-blocks.constants.ts new file mode 100644 index 000000000..705800c26 --- /dev/null +++ b/tools/ui/src/lib/constants/svg-blocks.constants.ts @@ -0,0 +1,57 @@ +/** + * Constants for rendering svg code blocks inline. + */ +export const SVG = { + // CSS classes applied to the inline svg block and its chrome. + BLOCK_CLASS: 'svg-block', + /** + * Shadow root style for the zoom dialog svg. Lets the svg grow past its + * intrinsic size so pan and zoom have room to work. + */ + DIALOG_SHADOW_STYLE: + ':host{display:inline-block}svg{min-height:min(50vh,12rem);min-width:min(80vw,20rem);max-width:none;max-height:none;height:auto;width:auto;display:block}', + ID_ATTR: 'data-svg-id', + + /** + * Shadow root style for an inline svg block. Mirrors the centered, padded + * sizing the light dom used before the svg moved behind a shadow boundary. + */ + INLINE_SHADOW_STYLE: + ':host{display:block;width:100%;text-align:center}svg{display:block;margin:0 auto;width:auto;height:auto;max-width:100%;max-height:70vh;min-height:8rem;padding:3rem 1rem}', + // Languages that mark a code block as svg content. + LANGUAGE: 'svg', + /** + * Hard size ceiling for a single inline svg block. + * Above this the source is left as raw text instead of being rendered. + */ + MAX_BYTES: 256 * 1024, + + RENDERED_ATTR: 'data-svg-rendered', + /** + * DOMPurify config for untrusted svg coming from model output. + * + * foreignObject and script stay forbidden unconditionally, they are the only + * inline svg vectors that execute arbitrary html or js. Everything else is + * allowed for maximum rendering compatibility: href and xlink:href stay so + * use, image, a and animateMotion work, and DOMPurify still neutralizes + * javascript: and data: uri schemes natively. External resource refs are + * allowed by design on a local first tool, the user browser fetches them. + * + * The sanitized svg is always mounted inside a shadow root (see svg-shadow), + * so an author