ruflo 3.5.2 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/dist/rvf.manifest.json +295 -0
  2. package/package.json +16 -2
  3. package/src/chat-ui/Dockerfile +25 -0
  4. package/src/chat-ui/patch-mcp-url-safety.sh +28 -0
  5. package/src/chat-ui/static/chatui/icon-144x144.png +0 -0
  6. package/src/chat-ui/static/chatui/omni-welcome.gif +0 -0
  7. package/src/config/config.example.json +76 -0
  8. package/src/mcp-bridge/Dockerfile +45 -0
  9. package/src/mcp-bridge/index.js +1668 -0
  10. package/src/mcp-bridge/mcp-stdio-kernel.js +159 -0
  11. package/src/mcp-bridge/package.json +17 -0
  12. package/src/mcp-bridge/test-harness.js +470 -0
  13. package/src/nginx/Dockerfile +10 -0
  14. package/src/nginx/nginx.conf +67 -0
  15. package/src/nginx/static/favicon-dark.svg +4 -0
  16. package/src/nginx/static/favicon.svg +4 -0
  17. package/src/nginx/static/icon.svg +5 -0
  18. package/src/nginx/static/logo.svg +9 -0
  19. package/src/nginx/static/manifest.json +22 -0
  20. package/src/nginx/static/welcome.js +184 -0
  21. package/src/ruvocal/.claude/skills/add-model-descriptions/SKILL.md +73 -0
  22. package/src/ruvocal/.devcontainer/Dockerfile +9 -0
  23. package/src/ruvocal/.devcontainer/devcontainer.json +36 -0
  24. package/src/ruvocal/.dockerignore +13 -0
  25. package/src/ruvocal/.env +194 -0
  26. package/src/ruvocal/.env.ci +1 -0
  27. package/src/ruvocal/.eslintignore +13 -0
  28. package/src/ruvocal/.eslintrc.cjs +45 -0
  29. package/src/ruvocal/.github/ISSUE_TEMPLATE/bug-report--chat-ui-.md +43 -0
  30. package/src/ruvocal/.github/ISSUE_TEMPLATE/config-support.md +9 -0
  31. package/src/ruvocal/.github/ISSUE_TEMPLATE/feature-request--chat-ui-.md +17 -0
  32. package/src/ruvocal/.github/ISSUE_TEMPLATE/huggingchat.md +11 -0
  33. package/src/ruvocal/.github/release.yml +16 -0
  34. package/src/ruvocal/.github/workflows/build-docs.yml +18 -0
  35. package/src/ruvocal/.github/workflows/build-image.yml +142 -0
  36. package/src/ruvocal/.github/workflows/build-pr-docs.yml +20 -0
  37. package/src/ruvocal/.github/workflows/deploy-dev.yml +63 -0
  38. package/src/ruvocal/.github/workflows/deploy-prod.yml +78 -0
  39. package/src/ruvocal/.github/workflows/lint-and-test.yml +84 -0
  40. package/src/ruvocal/.github/workflows/slugify.yaml +72 -0
  41. package/src/ruvocal/.github/workflows/trufflehog.yml +17 -0
  42. package/src/ruvocal/.github/workflows/upload-pr-documentation.yml +16 -0
  43. package/src/ruvocal/.husky/lint-stage-config.js +4 -0
  44. package/src/ruvocal/.husky/pre-commit +2 -0
  45. package/src/ruvocal/.prettierignore +14 -0
  46. package/src/ruvocal/.prettierrc +7 -0
  47. package/src/ruvocal/.vscode/launch.json +11 -0
  48. package/src/ruvocal/.vscode/settings.json +14 -0
  49. package/src/ruvocal/CLAUDE.md +126 -0
  50. package/src/ruvocal/Dockerfile +93 -0
  51. package/src/ruvocal/LICENSE +203 -0
  52. package/src/ruvocal/PRIVACY.md +41 -0
  53. package/src/ruvocal/README.md +190 -0
  54. package/src/ruvocal/chart/Chart.yaml +5 -0
  55. package/src/ruvocal/chart/env/dev.yaml +260 -0
  56. package/src/ruvocal/chart/env/prod.yaml +273 -0
  57. package/src/ruvocal/chart/templates/_helpers.tpl +22 -0
  58. package/src/ruvocal/chart/templates/config.yaml +10 -0
  59. package/src/ruvocal/chart/templates/deployment.yaml +81 -0
  60. package/src/ruvocal/chart/templates/hpa.yaml +45 -0
  61. package/src/ruvocal/chart/templates/infisical.yaml +24 -0
  62. package/src/ruvocal/chart/templates/ingress-internal.yaml +32 -0
  63. package/src/ruvocal/chart/templates/ingress.yaml +32 -0
  64. package/src/ruvocal/chart/templates/network-policy.yaml +36 -0
  65. package/src/ruvocal/chart/templates/service-account.yaml +13 -0
  66. package/src/ruvocal/chart/templates/service-monitor.yaml +17 -0
  67. package/src/ruvocal/chart/templates/service.yaml +21 -0
  68. package/src/ruvocal/chart/values.yaml +73 -0
  69. package/src/ruvocal/docker-compose.yml +21 -0
  70. package/src/ruvocal/docs/adr/ADR-029-HUGGINGFACE-CHAT-UI-CLOUD-RUN.md +1236 -0
  71. package/src/ruvocal/docs/adr/ADR-033-RUVECTOR-RUFLO-MCP-INTEGRATION.md +111 -0
  72. package/src/ruvocal/docs/adr/ADR-034-OPTIONAL-MCP-BACKENDS.md +117 -0
  73. package/src/ruvocal/docs/adr/ADR-035-MCP-TOOL-GROUPS.md +186 -0
  74. package/src/ruvocal/docs/adr/ADR-037-AUTOPILOT-CHAT-MODE.md +1500 -0
  75. package/src/ruvocal/docs/adr/ADR-038-RUVOCAL-FORK.md +286 -0
  76. package/src/ruvocal/docs/source/_toctree.yml +30 -0
  77. package/src/ruvocal/docs/source/configuration/common-issues.md +38 -0
  78. package/src/ruvocal/docs/source/configuration/llm-router.md +105 -0
  79. package/src/ruvocal/docs/source/configuration/mcp-tools.md +84 -0
  80. package/src/ruvocal/docs/source/configuration/metrics.md +9 -0
  81. package/src/ruvocal/docs/source/configuration/open-id.md +57 -0
  82. package/src/ruvocal/docs/source/configuration/overview.md +89 -0
  83. package/src/ruvocal/docs/source/configuration/theming.md +20 -0
  84. package/src/ruvocal/docs/source/developing/architecture.md +48 -0
  85. package/src/ruvocal/docs/source/index.md +53 -0
  86. package/src/ruvocal/docs/source/installation/docker.md +43 -0
  87. package/src/ruvocal/docs/source/installation/helm.md +43 -0
  88. package/src/ruvocal/docs/source/installation/local.md +62 -0
  89. package/src/ruvocal/entrypoint.sh +19 -0
  90. package/src/ruvocal/mcp-bridge/.claude-flow/agents/store.json +27 -0
  91. package/src/ruvocal/mcp-bridge/.claude-flow/daemon-state.json +130 -0
  92. package/src/ruvocal/mcp-bridge/.claude-flow/daemon.log +0 -0
  93. package/src/ruvocal/mcp-bridge/.claude-flow/daemon.pid +1 -0
  94. package/src/ruvocal/mcp-bridge/.claude-flow/tasks/store.json +21 -0
  95. package/src/ruvocal/mcp-bridge/.swarm/hnsw.index +0 -0
  96. package/src/ruvocal/mcp-bridge/.swarm/hnsw.metadata.json +1 -0
  97. package/src/ruvocal/mcp-bridge/.swarm/memory.db +0 -0
  98. package/src/ruvocal/mcp-bridge/.swarm/model-router-state.json +14 -0
  99. package/src/ruvocal/mcp-bridge/.swarm/schema.sql +305 -0
  100. package/src/ruvocal/mcp-bridge/Dockerfile +45 -0
  101. package/src/ruvocal/mcp-bridge/cloudbuild.yaml +49 -0
  102. package/src/ruvocal/mcp-bridge/index.js +1864 -0
  103. package/src/ruvocal/mcp-bridge/mcp-stdio-kernel.js +159 -0
  104. package/src/ruvocal/mcp-bridge/package-lock.json +762 -0
  105. package/src/ruvocal/mcp-bridge/package.json +17 -0
  106. package/src/ruvocal/mcp-bridge/test-harness.js +470 -0
  107. package/src/ruvocal/models/add-your-models-here.txt +1 -0
  108. package/src/ruvocal/package-lock.json +11741 -0
  109. package/src/ruvocal/package.json +121 -0
  110. package/src/ruvocal/postcss.config.js +6 -0
  111. package/src/ruvocal/rvf.manifest.json +204 -0
  112. package/src/ruvocal/scripts/config.ts +64 -0
  113. package/src/ruvocal/scripts/generate-welcome.mjs +181 -0
  114. package/src/ruvocal/scripts/populate.ts +288 -0
  115. package/src/ruvocal/scripts/samples.txt +194 -0
  116. package/src/ruvocal/scripts/setups/vitest-setup-client.ts +0 -0
  117. package/src/ruvocal/scripts/setups/vitest-setup-server.ts +44 -0
  118. package/src/ruvocal/scripts/updateLocalEnv.ts +48 -0
  119. package/src/ruvocal/src/ambient.d.ts +7 -0
  120. package/src/ruvocal/src/app.d.ts +29 -0
  121. package/src/ruvocal/src/app.html +53 -0
  122. package/src/ruvocal/src/hooks.server.ts +32 -0
  123. package/src/ruvocal/src/hooks.ts +6 -0
  124. package/src/ruvocal/src/lib/APIClient.ts +148 -0
  125. package/src/ruvocal/src/lib/actions/clickOutside.ts +18 -0
  126. package/src/ruvocal/src/lib/actions/snapScrollToBottom.ts +346 -0
  127. package/src/ruvocal/src/lib/buildPrompt.ts +33 -0
  128. package/src/ruvocal/src/lib/components/AnnouncementBanner.svelte +20 -0
  129. package/src/ruvocal/src/lib/components/BackgroundGenerationPoller.svelte +168 -0
  130. package/src/ruvocal/src/lib/components/CodeBlock.svelte +73 -0
  131. package/src/ruvocal/src/lib/components/CopyToClipBoardBtn.svelte +92 -0
  132. package/src/ruvocal/src/lib/components/DeleteConversationModal.svelte +75 -0
  133. package/src/ruvocal/src/lib/components/EditConversationModal.svelte +100 -0
  134. package/src/ruvocal/src/lib/components/ExpandNavigation.svelte +22 -0
  135. package/src/ruvocal/src/lib/components/HoverTooltip.svelte +44 -0
  136. package/src/ruvocal/src/lib/components/HtmlPreviewModal.svelte +143 -0
  137. package/src/ruvocal/src/lib/components/InfiniteScroll.svelte +50 -0
  138. package/src/ruvocal/src/lib/components/MobileNav.svelte +300 -0
  139. package/src/ruvocal/src/lib/components/Modal.svelte +115 -0
  140. package/src/ruvocal/src/lib/components/ModelCardMetadata.svelte +71 -0
  141. package/src/ruvocal/src/lib/components/NavConversationItem.svelte +151 -0
  142. package/src/ruvocal/src/lib/components/NavMenu.svelte +295 -0
  143. package/src/ruvocal/src/lib/components/Pagination.svelte +97 -0
  144. package/src/ruvocal/src/lib/components/PaginationArrow.svelte +27 -0
  145. package/src/ruvocal/src/lib/components/Portal.svelte +24 -0
  146. package/src/ruvocal/src/lib/components/RetryBtn.svelte +18 -0
  147. package/src/ruvocal/src/lib/components/RuFloUniverse.svelte +185 -0
  148. package/src/ruvocal/src/lib/components/ScrollToBottomBtn.svelte +47 -0
  149. package/src/ruvocal/src/lib/components/ScrollToPreviousBtn.svelte +77 -0
  150. package/src/ruvocal/src/lib/components/ShareConversationModal.svelte +182 -0
  151. package/src/ruvocal/src/lib/components/StopGeneratingBtn.svelte +69 -0
  152. package/src/ruvocal/src/lib/components/SubscribeModal.svelte +87 -0
  153. package/src/ruvocal/src/lib/components/Switch.svelte +36 -0
  154. package/src/ruvocal/src/lib/components/SystemPromptModal.svelte +44 -0
  155. package/src/ruvocal/src/lib/components/Toast.svelte +27 -0
  156. package/src/ruvocal/src/lib/components/Tooltip.svelte +30 -0
  157. package/src/ruvocal/src/lib/components/WelcomeModal.svelte +46 -0
  158. package/src/ruvocal/src/lib/components/chat/Alternatives.svelte +77 -0
  159. package/src/ruvocal/src/lib/components/chat/BlockWrapper.svelte +72 -0
  160. package/src/ruvocal/src/lib/components/chat/ChatInput.svelte +490 -0
  161. package/src/ruvocal/src/lib/components/chat/ChatIntroduction.svelte +123 -0
  162. package/src/ruvocal/src/lib/components/chat/ChatMessage.svelte +548 -0
  163. package/src/ruvocal/src/lib/components/chat/ChatWindow.svelte +939 -0
  164. package/src/ruvocal/src/lib/components/chat/FileDropzone.svelte +92 -0
  165. package/src/ruvocal/src/lib/components/chat/ImageLightbox.svelte +66 -0
  166. package/src/ruvocal/src/lib/components/chat/MarkdownBlock.svelte +23 -0
  167. package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte +69 -0
  168. package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte.test.ts +58 -0
  169. package/src/ruvocal/src/lib/components/chat/MessageAvatar.svelte +103 -0
  170. package/src/ruvocal/src/lib/components/chat/ModelSwitch.svelte +64 -0
  171. package/src/ruvocal/src/lib/components/chat/OpenReasoningResults.svelte +81 -0
  172. package/src/ruvocal/src/lib/components/chat/TaskGroup.svelte +88 -0
  173. package/src/ruvocal/src/lib/components/chat/ToolUpdate.svelte +273 -0
  174. package/src/ruvocal/src/lib/components/chat/UploadedFile.svelte +253 -0
  175. package/src/ruvocal/src/lib/components/chat/UrlFetchModal.svelte +203 -0
  176. package/src/ruvocal/src/lib/components/chat/VoiceRecorder.svelte +214 -0
  177. package/src/ruvocal/src/lib/components/icons/IconBurger.svelte +20 -0
  178. package/src/ruvocal/src/lib/components/icons/IconCheap.svelte +20 -0
  179. package/src/ruvocal/src/lib/components/icons/IconChevron.svelte +24 -0
  180. package/src/ruvocal/src/lib/components/icons/IconDazzled.svelte +40 -0
  181. package/src/ruvocal/src/lib/components/icons/IconFast.svelte +20 -0
  182. package/src/ruvocal/src/lib/components/icons/IconLoading.svelte +22 -0
  183. package/src/ruvocal/src/lib/components/icons/IconMCP.svelte +28 -0
  184. package/src/ruvocal/src/lib/components/icons/IconMoon.svelte +21 -0
  185. package/src/ruvocal/src/lib/components/icons/IconNew.svelte +20 -0
  186. package/src/ruvocal/src/lib/components/icons/IconOmni.svelte +90 -0
  187. package/src/ruvocal/src/lib/components/icons/IconPaperclip.svelte +24 -0
  188. package/src/ruvocal/src/lib/components/icons/IconPro.svelte +37 -0
  189. package/src/ruvocal/src/lib/components/icons/IconShare.svelte +21 -0
  190. package/src/ruvocal/src/lib/components/icons/IconSun.svelte +93 -0
  191. package/src/ruvocal/src/lib/components/icons/Logo.svelte +68 -0
  192. package/src/ruvocal/src/lib/components/icons/LogoHuggingFaceBorderless.svelte +54 -0
  193. package/src/ruvocal/src/lib/components/mcp/AddServerForm.svelte +250 -0
  194. package/src/ruvocal/src/lib/components/mcp/MCPServerManager.svelte +185 -0
  195. package/src/ruvocal/src/lib/components/mcp/ServerCard.svelte +203 -0
  196. package/src/ruvocal/src/lib/components/players/AudioPlayer.svelte +82 -0
  197. package/src/ruvocal/src/lib/components/voice/AudioWaveform.svelte +96 -0
  198. package/src/ruvocal/src/lib/constants/mcpExamples.ts +135 -0
  199. package/src/ruvocal/src/lib/constants/mime.ts +11 -0
  200. package/src/ruvocal/src/lib/constants/pagination.ts +1 -0
  201. package/src/ruvocal/src/lib/constants/publicSepToken.ts +1 -0
  202. package/src/ruvocal/src/lib/constants/routerExamples.ts +209 -0
  203. package/src/ruvocal/src/lib/createShareLink.ts +27 -0
  204. package/src/ruvocal/src/lib/jobs/refresh-conversation-stats.ts +297 -0
  205. package/src/ruvocal/src/lib/migrations/lock.ts +56 -0
  206. package/src/ruvocal/src/lib/migrations/migrations.spec.ts +74 -0
  207. package/src/ruvocal/src/lib/migrations/migrations.ts +109 -0
  208. package/src/ruvocal/src/lib/migrations/routines/01-update-search-assistants.ts +50 -0
  209. package/src/ruvocal/src/lib/migrations/routines/02-update-assistants-models.ts +48 -0
  210. package/src/ruvocal/src/lib/migrations/routines/04-update-message-updates.ts +151 -0
  211. package/src/ruvocal/src/lib/migrations/routines/05-update-message-files.ts +56 -0
  212. package/src/ruvocal/src/lib/migrations/routines/06-trim-message-updates.ts +56 -0
  213. package/src/ruvocal/src/lib/migrations/routines/08-update-featured-to-review.ts +32 -0
  214. package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts +214 -0
  215. package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.ts +88 -0
  216. package/src/ruvocal/src/lib/migrations/routines/10-update-reports-assistantid.ts +29 -0
  217. package/src/ruvocal/src/lib/migrations/routines/index.ts +15 -0
  218. package/src/ruvocal/src/lib/server/__tests__/conversation-stop-generating.spec.ts +103 -0
  219. package/src/ruvocal/src/lib/server/abortRegistry.ts +57 -0
  220. package/src/ruvocal/src/lib/server/abortedGenerations.ts +43 -0
  221. package/src/ruvocal/src/lib/server/adminToken.ts +62 -0
  222. package/src/ruvocal/src/lib/server/api/__tests__/conversations-id.spec.ts +296 -0
  223. package/src/ruvocal/src/lib/server/api/__tests__/conversations-message.spec.ts +216 -0
  224. package/src/ruvocal/src/lib/server/api/__tests__/conversations.spec.ts +235 -0
  225. package/src/ruvocal/src/lib/server/api/__tests__/misc.spec.ts +72 -0
  226. package/src/ruvocal/src/lib/server/api/__tests__/testHelpers.ts +86 -0
  227. package/src/ruvocal/src/lib/server/api/__tests__/user-reports.spec.ts +78 -0
  228. package/src/ruvocal/src/lib/server/api/__tests__/user.spec.ts +239 -0
  229. package/src/ruvocal/src/lib/server/api/types.ts +37 -0
  230. package/src/ruvocal/src/lib/server/api/utils/requireAuth.ts +22 -0
  231. package/src/ruvocal/src/lib/server/api/utils/resolveConversation.ts +69 -0
  232. package/src/ruvocal/src/lib/server/api/utils/resolveModel.ts +27 -0
  233. package/src/ruvocal/src/lib/server/api/utils/superjsonResponse.ts +15 -0
  234. package/src/ruvocal/src/lib/server/apiToken.ts +11 -0
  235. package/src/ruvocal/src/lib/server/auth.ts +554 -0
  236. package/src/ruvocal/src/lib/server/config.ts +187 -0
  237. package/src/ruvocal/src/lib/server/conversation.ts +83 -0
  238. package/src/ruvocal/src/lib/server/database/__tests__/rvf.spec.ts +709 -0
  239. package/src/ruvocal/src/lib/server/database/postgres.ts +700 -0
  240. package/src/ruvocal/src/lib/server/database/rvf.ts +1078 -0
  241. package/src/ruvocal/src/lib/server/database.ts +145 -0
  242. package/src/ruvocal/src/lib/server/endpoints/document.ts +68 -0
  243. package/src/ruvocal/src/lib/server/endpoints/endpoints.ts +43 -0
  244. package/src/ruvocal/src/lib/server/endpoints/images.ts +211 -0
  245. package/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts +266 -0
  246. package/src/ruvocal/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts +212 -0
  247. package/src/ruvocal/src/lib/server/endpoints/openai/openAICompletionToTextGenerationStream.ts +32 -0
  248. package/src/ruvocal/src/lib/server/endpoints/preprocessMessages.ts +61 -0
  249. package/src/ruvocal/src/lib/server/exitHandler.ts +59 -0
  250. package/src/ruvocal/src/lib/server/files/downloadFile.ts +34 -0
  251. package/src/ruvocal/src/lib/server/files/uploadFile.ts +29 -0
  252. package/src/ruvocal/src/lib/server/findRepoRoot.ts +13 -0
  253. package/src/ruvocal/src/lib/server/fonts/Inter-Black.ttf +0 -0
  254. package/src/ruvocal/src/lib/server/fonts/Inter-Bold.ttf +0 -0
  255. package/src/ruvocal/src/lib/server/fonts/Inter-ExtraBold.ttf +0 -0
  256. package/src/ruvocal/src/lib/server/fonts/Inter-ExtraLight.ttf +0 -0
  257. package/src/ruvocal/src/lib/server/fonts/Inter-Light.ttf +0 -0
  258. package/src/ruvocal/src/lib/server/fonts/Inter-Medium.ttf +0 -0
  259. package/src/ruvocal/src/lib/server/fonts/Inter-Regular.ttf +0 -0
  260. package/src/ruvocal/src/lib/server/fonts/Inter-SemiBold.ttf +0 -0
  261. package/src/ruvocal/src/lib/server/fonts/Inter-Thin.ttf +0 -0
  262. package/src/ruvocal/src/lib/server/generateFromDefaultEndpoint.ts +46 -0
  263. package/src/ruvocal/src/lib/server/hooks/error.ts +37 -0
  264. package/src/ruvocal/src/lib/server/hooks/fetch.ts +22 -0
  265. package/src/ruvocal/src/lib/server/hooks/handle.ts +250 -0
  266. package/src/ruvocal/src/lib/server/hooks/init.ts +51 -0
  267. package/src/ruvocal/src/lib/server/isURLLocal.spec.ts +31 -0
  268. package/src/ruvocal/src/lib/server/isURLLocal.ts +74 -0
  269. package/src/ruvocal/src/lib/server/logger.ts +42 -0
  270. package/src/ruvocal/src/lib/server/mcp/clientPool.ts +70 -0
  271. package/src/ruvocal/src/lib/server/mcp/hf.ts +32 -0
  272. package/src/ruvocal/src/lib/server/mcp/httpClient.ts +122 -0
  273. package/src/ruvocal/src/lib/server/mcp/registry.ts +76 -0
  274. package/src/ruvocal/src/lib/server/mcp/tools.ts +196 -0
  275. package/src/ruvocal/src/lib/server/metrics.ts +255 -0
  276. package/src/ruvocal/src/lib/server/models.ts +518 -0
  277. package/src/ruvocal/src/lib/server/requestContext.ts +55 -0
  278. package/src/ruvocal/src/lib/server/router/arch.ts +230 -0
  279. package/src/ruvocal/src/lib/server/router/endpoint.ts +316 -0
  280. package/src/ruvocal/src/lib/server/router/multimodal.ts +28 -0
  281. package/src/ruvocal/src/lib/server/router/policy.ts +49 -0
  282. package/src/ruvocal/src/lib/server/router/toolsRoute.ts +51 -0
  283. package/src/ruvocal/src/lib/server/router/types.ts +21 -0
  284. package/src/ruvocal/src/lib/server/sendSlack.ts +23 -0
  285. package/src/ruvocal/src/lib/server/textGeneration/generate.ts +258 -0
  286. package/src/ruvocal/src/lib/server/textGeneration/index.ts +95 -0
  287. package/src/ruvocal/src/lib/server/textGeneration/mcp/fileRefs.ts +155 -0
  288. package/src/ruvocal/src/lib/server/textGeneration/mcp/routerResolution.ts +108 -0
  289. package/src/ruvocal/src/lib/server/textGeneration/mcp/runMcpFlow.ts +822 -0
  290. package/src/ruvocal/src/lib/server/textGeneration/mcp/toolInvocation.ts +349 -0
  291. package/src/ruvocal/src/lib/server/textGeneration/reasoning.ts +23 -0
  292. package/src/ruvocal/src/lib/server/textGeneration/title.ts +83 -0
  293. package/src/ruvocal/src/lib/server/textGeneration/types.ts +26 -0
  294. package/src/ruvocal/src/lib/server/textGeneration/utils/prepareFiles.ts +88 -0
  295. package/src/ruvocal/src/lib/server/textGeneration/utils/routing.ts +21 -0
  296. package/src/ruvocal/src/lib/server/textGeneration/utils/toolPrompt.ts +49 -0
  297. package/src/ruvocal/src/lib/server/urlSafety.ts +72 -0
  298. package/src/ruvocal/src/lib/server/usageLimits.ts +30 -0
  299. package/src/ruvocal/src/lib/stores/autopilotStore.svelte.ts +175 -0
  300. package/src/ruvocal/src/lib/stores/backgroundGenerations.svelte.ts +32 -0
  301. package/src/ruvocal/src/lib/stores/backgroundGenerations.ts +1 -0
  302. package/src/ruvocal/src/lib/stores/errors.ts +9 -0
  303. package/src/ruvocal/src/lib/stores/isAborted.ts +3 -0
  304. package/src/ruvocal/src/lib/stores/isPro.ts +4 -0
  305. package/src/ruvocal/src/lib/stores/loading.ts +3 -0
  306. package/src/ruvocal/src/lib/stores/mcpServers.ts +345 -0
  307. package/src/ruvocal/src/lib/stores/pendingChatInput.ts +3 -0
  308. package/src/ruvocal/src/lib/stores/pendingMessage.ts +9 -0
  309. package/src/ruvocal/src/lib/stores/settings.ts +182 -0
  310. package/src/ruvocal/src/lib/stores/shareModal.ts +13 -0
  311. package/src/ruvocal/src/lib/stores/titleUpdate.ts +8 -0
  312. package/src/ruvocal/src/lib/switchTheme.ts +124 -0
  313. package/src/ruvocal/src/lib/types/AbortedGeneration.ts +8 -0
  314. package/src/ruvocal/src/lib/types/Assistant.ts +31 -0
  315. package/src/ruvocal/src/lib/types/AssistantStats.ts +11 -0
  316. package/src/ruvocal/src/lib/types/ConfigKey.ts +4 -0
  317. package/src/ruvocal/src/lib/types/ConvSidebar.ts +9 -0
  318. package/src/ruvocal/src/lib/types/Conversation.ts +27 -0
  319. package/src/ruvocal/src/lib/types/ConversationStats.ts +13 -0
  320. package/src/ruvocal/src/lib/types/Message.ts +41 -0
  321. package/src/ruvocal/src/lib/types/MessageEvent.ts +10 -0
  322. package/src/ruvocal/src/lib/types/MessageUpdate.ts +139 -0
  323. package/src/ruvocal/src/lib/types/MigrationResult.ts +7 -0
  324. package/src/ruvocal/src/lib/types/Model.ts +23 -0
  325. package/src/ruvocal/src/lib/types/Report.ts +12 -0
  326. package/src/ruvocal/src/lib/types/Review.ts +6 -0
  327. package/src/ruvocal/src/lib/types/Semaphore.ts +19 -0
  328. package/src/ruvocal/src/lib/types/Session.ts +22 -0
  329. package/src/ruvocal/src/lib/types/Settings.ts +86 -0
  330. package/src/ruvocal/src/lib/types/SharedConversation.ts +9 -0
  331. package/src/ruvocal/src/lib/types/Template.ts +6 -0
  332. package/src/ruvocal/src/lib/types/Timestamps.ts +4 -0
  333. package/src/ruvocal/src/lib/types/TokenCache.ts +6 -0
  334. package/src/ruvocal/src/lib/types/Tool.ts +74 -0
  335. package/src/ruvocal/src/lib/types/UrlDependency.ts +5 -0
  336. package/src/ruvocal/src/lib/types/User.ts +14 -0
  337. package/src/ruvocal/src/lib/utils/PublicConfig.svelte.ts +75 -0
  338. package/src/ruvocal/src/lib/utils/auth.ts +17 -0
  339. package/src/ruvocal/src/lib/utils/chunk.ts +33 -0
  340. package/src/ruvocal/src/lib/utils/cookiesAreEnabled.ts +13 -0
  341. package/src/ruvocal/src/lib/utils/debounce.ts +17 -0
  342. package/src/ruvocal/src/lib/utils/deepestChild.ts +6 -0
  343. package/src/ruvocal/src/lib/utils/favicon.ts +21 -0
  344. package/src/ruvocal/src/lib/utils/fetchJSON.ts +23 -0
  345. package/src/ruvocal/src/lib/utils/file2base64.ts +14 -0
  346. package/src/ruvocal/src/lib/utils/formatUserCount.ts +37 -0
  347. package/src/ruvocal/src/lib/utils/generationState.spec.ts +75 -0
  348. package/src/ruvocal/src/lib/utils/generationState.ts +26 -0
  349. package/src/ruvocal/src/lib/utils/getHref.ts +41 -0
  350. package/src/ruvocal/src/lib/utils/getReturnFromGenerator.ts +7 -0
  351. package/src/ruvocal/src/lib/utils/haptics.ts +64 -0
  352. package/src/ruvocal/src/lib/utils/hashConv.ts +12 -0
  353. package/src/ruvocal/src/lib/utils/hf.ts +17 -0
  354. package/src/ruvocal/src/lib/utils/isDesktop.ts +7 -0
  355. package/src/ruvocal/src/lib/utils/isUrl.ts +8 -0
  356. package/src/ruvocal/src/lib/utils/isVirtualKeyboard.ts +16 -0
  357. package/src/ruvocal/src/lib/utils/loadAttachmentsFromUrls.ts +115 -0
  358. package/src/ruvocal/src/lib/utils/marked.spec.ts +96 -0
  359. package/src/ruvocal/src/lib/utils/marked.ts +531 -0
  360. package/src/ruvocal/src/lib/utils/mcpValidation.ts +147 -0
  361. package/src/ruvocal/src/lib/utils/mergeAsyncGenerators.ts +38 -0
  362. package/src/ruvocal/src/lib/utils/messageUpdates.spec.ts +262 -0
  363. package/src/ruvocal/src/lib/utils/messageUpdates.ts +324 -0
  364. package/src/ruvocal/src/lib/utils/mime.ts +56 -0
  365. package/src/ruvocal/src/lib/utils/models.ts +14 -0
  366. package/src/ruvocal/src/lib/utils/parseBlocks.ts +120 -0
  367. package/src/ruvocal/src/lib/utils/parseIncompleteMarkdown.ts +644 -0
  368. package/src/ruvocal/src/lib/utils/parseStringToList.ts +10 -0
  369. package/src/ruvocal/src/lib/utils/randomUuid.ts +14 -0
  370. package/src/ruvocal/src/lib/utils/searchTokens.ts +33 -0
  371. package/src/ruvocal/src/lib/utils/sha256.ts +7 -0
  372. package/src/ruvocal/src/lib/utils/stringifyError.ts +12 -0
  373. package/src/ruvocal/src/lib/utils/sum.ts +3 -0
  374. package/src/ruvocal/src/lib/utils/template.spec.ts +59 -0
  375. package/src/ruvocal/src/lib/utils/template.ts +53 -0
  376. package/src/ruvocal/src/lib/utils/timeout.ts +9 -0
  377. package/src/ruvocal/src/lib/utils/toolProgress.spec.ts +46 -0
  378. package/src/ruvocal/src/lib/utils/toolProgress.ts +11 -0
  379. package/src/ruvocal/src/lib/utils/tree/addChildren.spec.ts +102 -0
  380. package/src/ruvocal/src/lib/utils/tree/addChildren.ts +48 -0
  381. package/src/ruvocal/src/lib/utils/tree/addSibling.spec.ts +81 -0
  382. package/src/ruvocal/src/lib/utils/tree/addSibling.ts +41 -0
  383. package/src/ruvocal/src/lib/utils/tree/buildSubtree.spec.ts +110 -0
  384. package/src/ruvocal/src/lib/utils/tree/buildSubtree.ts +24 -0
  385. package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.spec.ts +31 -0
  386. package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.ts +36 -0
  387. package/src/ruvocal/src/lib/utils/tree/isMessageId.spec.ts +15 -0
  388. package/src/ruvocal/src/lib/utils/tree/isMessageId.ts +5 -0
  389. package/src/ruvocal/src/lib/utils/tree/tree.d.ts +14 -0
  390. package/src/ruvocal/src/lib/utils/tree/treeHelpers.spec.ts +167 -0
  391. package/src/ruvocal/src/lib/utils/updates.ts +39 -0
  392. package/src/ruvocal/src/lib/utils/urlParams.ts +13 -0
  393. package/src/ruvocal/src/lib/workers/autopilotWorker.ts +221 -0
  394. package/src/ruvocal/src/lib/workers/detailFetchWorker.ts +100 -0
  395. package/src/ruvocal/src/lib/workers/markdownWorker.ts +61 -0
  396. package/src/ruvocal/src/routes/+error.svelte +20 -0
  397. package/src/ruvocal/src/routes/+layout.svelte +324 -0
  398. package/src/ruvocal/src/routes/+layout.ts +91 -0
  399. package/src/ruvocal/src/routes/+page.svelte +168 -0
  400. package/src/ruvocal/src/routes/.well-known/oauth-cimd/+server.ts +37 -0
  401. package/src/ruvocal/src/routes/__debug/openai/+server.ts +21 -0
  402. package/src/ruvocal/src/routes/admin/export/+server.ts +159 -0
  403. package/src/ruvocal/src/routes/admin/stats/compute/+server.ts +16 -0
  404. package/src/ruvocal/src/routes/api/conversation/[id]/+server.ts +40 -0
  405. package/src/ruvocal/src/routes/api/conversation/[id]/message/[messageId]/+server.ts +42 -0
  406. package/src/ruvocal/src/routes/api/conversations/+server.ts +48 -0
  407. package/src/ruvocal/src/routes/api/fetch-url/+server.ts +147 -0
  408. package/src/ruvocal/src/routes/api/mcp/health/+server.ts +292 -0
  409. package/src/ruvocal/src/routes/api/mcp/servers/+server.ts +32 -0
  410. package/src/ruvocal/src/routes/api/models/+server.ts +25 -0
  411. package/src/ruvocal/src/routes/api/transcribe/+server.ts +104 -0
  412. package/src/ruvocal/src/routes/api/user/+server.ts +15 -0
  413. package/src/ruvocal/src/routes/api/user/validate-token/+server.ts +20 -0
  414. package/src/ruvocal/src/routes/api/v2/conversations/+server.ts +48 -0
  415. package/src/ruvocal/src/routes/api/v2/conversations/[id]/+server.ts +94 -0
  416. package/src/ruvocal/src/routes/api/v2/conversations/[id]/message/[messageId]/+server.ts +43 -0
  417. package/src/ruvocal/src/routes/api/v2/conversations/import-share/+server.ts +23 -0
  418. package/src/ruvocal/src/routes/api/v2/debug/config/+server.ts +16 -0
  419. package/src/ruvocal/src/routes/api/v2/debug/refresh/+server.ts +30 -0
  420. package/src/ruvocal/src/routes/api/v2/export/+server.ts +196 -0
  421. package/src/ruvocal/src/routes/api/v2/feature-flags/+server.ts +14 -0
  422. package/src/ruvocal/src/routes/api/v2/models/+server.ts +38 -0
  423. package/src/ruvocal/src/routes/api/v2/models/[namespace]/+server.ts +8 -0
  424. package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/+server.ts +8 -0
  425. package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/subscribe/+server.ts +28 -0
  426. package/src/ruvocal/src/routes/api/v2/models/[namespace]/subscribe/+server.ts +28 -0
  427. package/src/ruvocal/src/routes/api/v2/models/old/+server.ts +7 -0
  428. package/src/ruvocal/src/routes/api/v2/models/refresh/+server.ts +33 -0
  429. package/src/ruvocal/src/routes/api/v2/public-config/+server.ts +7 -0
  430. package/src/ruvocal/src/routes/api/v2/user/+server.ts +17 -0
  431. package/src/ruvocal/src/routes/api/v2/user/billing-orgs/+server.ts +73 -0
  432. package/src/ruvocal/src/routes/api/v2/user/reports/+server.ts +17 -0
  433. package/src/ruvocal/src/routes/api/v2/user/settings/+server.ts +103 -0
  434. package/src/ruvocal/src/routes/conversation/+server.ts +115 -0
  435. package/src/ruvocal/src/routes/conversation/[id]/+page.svelte +582 -0
  436. package/src/ruvocal/src/routes/conversation/[id]/+page.ts +60 -0
  437. package/src/ruvocal/src/routes/conversation/[id]/+server.ts +736 -0
  438. package/src/ruvocal/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts +66 -0
  439. package/src/ruvocal/src/routes/conversation/[id]/output/[sha256]/+server.ts +58 -0
  440. package/src/ruvocal/src/routes/conversation/[id]/share/+server.ts +69 -0
  441. package/src/ruvocal/src/routes/conversation/[id]/stop-generating/+server.ts +35 -0
  442. package/src/ruvocal/src/routes/healthcheck/+server.ts +3 -0
  443. package/src/ruvocal/src/routes/login/+server.ts +5 -0
  444. package/src/ruvocal/src/routes/login/callback/+server.ts +103 -0
  445. package/src/ruvocal/src/routes/login/callback/updateUser.spec.ts +157 -0
  446. package/src/ruvocal/src/routes/login/callback/updateUser.ts +215 -0
  447. package/src/ruvocal/src/routes/logout/+server.ts +18 -0
  448. package/src/ruvocal/src/routes/metrics/+server.ts +18 -0
  449. package/src/ruvocal/src/routes/models/+page.svelte +233 -0
  450. package/src/ruvocal/src/routes/models/[...model]/+page.svelte +161 -0
  451. package/src/ruvocal/src/routes/models/[...model]/+page.ts +14 -0
  452. package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/+server.ts +64 -0
  453. package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/ModelThumbnail.svelte +28 -0
  454. package/src/ruvocal/src/routes/privacy/+page.svelte +11 -0
  455. package/src/ruvocal/src/routes/r/[id]/+page.ts +34 -0
  456. package/src/ruvocal/src/routes/settings/(nav)/+layout.svelte +282 -0
  457. package/src/ruvocal/src/routes/settings/(nav)/+layout.ts +1 -0
  458. package/src/ruvocal/src/routes/settings/(nav)/+page.svelte +0 -0
  459. package/src/ruvocal/src/routes/settings/(nav)/+server.ts +53 -0
  460. package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.svelte +464 -0
  461. package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.ts +14 -0
  462. package/src/ruvocal/src/routes/settings/(nav)/application/+page.svelte +362 -0
  463. package/src/ruvocal/src/routes/settings/+layout.svelte +40 -0
  464. package/src/ruvocal/src/styles/highlight-js.css +195 -0
  465. package/src/ruvocal/src/styles/main.css +144 -0
  466. package/src/ruvocal/static/chatui/apple-touch-icon.png +0 -0
  467. package/src/ruvocal/static/chatui/favicon-dark.svg +3 -0
  468. package/src/ruvocal/static/chatui/favicon-dev.svg +3 -0
  469. package/src/ruvocal/static/chatui/favicon.ico +0 -0
  470. package/src/ruvocal/static/chatui/favicon.svg +3 -0
  471. package/src/ruvocal/static/chatui/icon-128x128.png +0 -0
  472. package/src/ruvocal/static/chatui/icon-144x144.png +0 -0
  473. package/src/ruvocal/static/chatui/icon-192x192.png +0 -0
  474. package/src/ruvocal/static/chatui/icon-256x256.png +0 -0
  475. package/src/ruvocal/static/chatui/icon-36x36.png +0 -0
  476. package/src/ruvocal/static/chatui/icon-48x48.png +0 -0
  477. package/src/ruvocal/static/chatui/icon-512x512.png +0 -0
  478. package/src/ruvocal/static/chatui/icon-72x72.png +0 -0
  479. package/src/ruvocal/static/chatui/icon-96x96.png +0 -0
  480. package/src/ruvocal/static/chatui/icon.svg +3 -0
  481. package/src/ruvocal/static/chatui/logo.svg +7 -0
  482. package/src/ruvocal/static/chatui/manifest.json +54 -0
  483. package/src/ruvocal/static/chatui/omni-welcome.gif +0 -0
  484. package/src/ruvocal/static/chatui/omni-welcome.png +0 -0
  485. package/src/ruvocal/static/chatui/welcome.js +184 -0
  486. package/src/ruvocal/static/chatui/welcome.svg +1 -0
  487. package/src/ruvocal/static/huggingchat/apple-touch-icon.png +0 -0
  488. package/src/ruvocal/static/huggingchat/assistants-thumbnail.png +0 -0
  489. package/src/ruvocal/static/huggingchat/castle-example.jpg +0 -0
  490. package/src/ruvocal/static/huggingchat/favicon-dark.svg +4 -0
  491. package/src/ruvocal/static/huggingchat/favicon-dev.svg +4 -0
  492. package/src/ruvocal/static/huggingchat/favicon.ico +0 -0
  493. package/src/ruvocal/static/huggingchat/favicon.svg +4 -0
  494. package/src/ruvocal/static/huggingchat/fulltext-logo.svg +2 -0
  495. package/src/ruvocal/static/huggingchat/icon-128x128.png +0 -0
  496. package/src/ruvocal/static/huggingchat/icon-144x144.png +0 -0
  497. package/src/ruvocal/static/huggingchat/icon-192x192.png +0 -0
  498. package/src/ruvocal/static/huggingchat/icon-256x256.png +0 -0
  499. package/src/ruvocal/static/huggingchat/icon-36x36.png +0 -0
  500. package/src/ruvocal/static/huggingchat/icon-48x48.png +0 -0
  501. package/src/ruvocal/static/huggingchat/icon-512x512.png +0 -0
  502. package/src/ruvocal/static/huggingchat/icon-72x72.png +0 -0
  503. package/src/ruvocal/static/huggingchat/icon-96x96.png +0 -0
  504. package/src/ruvocal/static/huggingchat/icon.svg +4 -0
  505. package/src/ruvocal/static/huggingchat/logo.svg +4 -0
  506. package/src/ruvocal/static/huggingchat/manifest.json +54 -0
  507. package/src/ruvocal/static/huggingchat/omni-welcome.gif +0 -0
  508. package/src/ruvocal/static/huggingchat/routes.chat.json +226 -0
  509. package/src/ruvocal/static/huggingchat/thumbnail.png +0 -0
  510. package/src/ruvocal/static/huggingchat/tools-thumbnail.png +0 -0
  511. package/src/ruvocal/static/robots.txt +10 -0
  512. package/src/ruvocal/stub/@reflink/reflink/index.js +0 -0
  513. package/src/ruvocal/stub/@reflink/reflink/package.json +5 -0
  514. package/src/ruvocal/svelte.config.js +53 -0
  515. package/src/ruvocal/tailwind.config.cjs +30 -0
  516. package/src/ruvocal/tsconfig.json +19 -0
  517. package/src/ruvocal/vite.config.ts +87 -0
  518. package/src/scripts/deploy.sh +116 -0
  519. package/src/scripts/generate-config.js +245 -0
  520. package/src/scripts/generate-welcome.js +187 -0
  521. package/src/scripts/package-rvf.sh +116 -0
@@ -0,0 +1,185 @@
1
+ <script lang="ts">
2
+ import { usePublicConfig } from "$lib/utils/PublicConfig.svelte";
3
+ import Modal from "$lib/components/Modal.svelte";
4
+ import ServerCard from "./ServerCard.svelte";
5
+ import AddServerForm from "./AddServerForm.svelte";
6
+ import {
7
+ allMcpServers,
8
+ selectedServerIds,
9
+ enabledServersCount,
10
+ addCustomServer,
11
+ refreshMcpServers,
12
+ healthCheckServer,
13
+ } from "$lib/stores/mcpServers";
14
+ import type { KeyValuePair } from "$lib/types/Tool";
15
+ import IconAddLarge from "~icons/carbon/add-large";
16
+ import IconRefresh from "~icons/carbon/renew";
17
+ import LucideHammer from "~icons/lucide/hammer";
18
+ import IconMCP from "$lib/components/icons/IconMCP.svelte";
19
+
20
+ const publicConfig = usePublicConfig();
21
+
22
+ interface Props {
23
+ onclose: () => void;
24
+ }
25
+
26
+ let { onclose }: Props = $props();
27
+
28
+ type View = "list" | "add";
29
+ let currentView = $state<View>("list");
30
+ let isRefreshing = $state(false);
31
+
32
+ const baseServers = $derived($allMcpServers.filter((s) => s.type === "base"));
33
+ const customServers = $derived($allMcpServers.filter((s) => s.type === "custom"));
34
+ const enabledCount = $derived($enabledServersCount);
35
+
36
+ function handleAddServer(serverData: { name: string; url: string; headers?: KeyValuePair[] }) {
37
+ addCustomServer(serverData);
38
+ currentView = "list";
39
+ }
40
+
41
+ function handleCancel() {
42
+ currentView = "list";
43
+ }
44
+
45
+ async function handleRefresh() {
46
+ if (isRefreshing) return;
47
+ isRefreshing = true;
48
+ try {
49
+ await refreshMcpServers();
50
+ // After refreshing the list, re-run health checks for all known servers
51
+ const servers = $allMcpServers;
52
+ await Promise.allSettled(servers.map((s) => healthCheckServer(s)));
53
+ } finally {
54
+ isRefreshing = false;
55
+ }
56
+ }
57
+ </script>
58
+
59
+ <Modal width={currentView === "list" ? "w-[800px]" : "w-[600px]"} {onclose} closeButton>
60
+ <div class="p-6">
61
+ <!-- Header -->
62
+ <div class="mb-6">
63
+ <h2 class="mb-1 text-xl font-semibold text-gray-900 dark:text-gray-200">
64
+ {#if currentView === "list"}
65
+ MCP Servers
66
+ {:else}
67
+ Add MCP server
68
+ {/if}
69
+ </h2>
70
+ <p class="text-sm text-gray-600 dark:text-gray-400">
71
+ {#if currentView === "list"}
72
+ Manage MCP servers to extend {publicConfig.PUBLIC_APP_NAME} with external tools.
73
+ {:else}
74
+ Add a custom MCP server to {publicConfig.PUBLIC_APP_NAME}.
75
+ {/if}
76
+ </p>
77
+ </div>
78
+
79
+ <!-- Content -->
80
+ {#if currentView === "list"}
81
+ <div
82
+ class="mb-6 flex justify-between rounded-lg p-4 max-sm:flex-col max-sm:gap-4 sm:items-center {!enabledCount
83
+ ? 'bg-gray-100 dark:bg-white/5'
84
+ : 'bg-blue-50 dark:bg-blue-900/10'}"
85
+ >
86
+ <div class="flex items-center gap-3">
87
+ <div
88
+ class="flex size-10 items-center justify-center rounded-xl bg-blue-500/10"
89
+ class:grayscale={!enabledCount}
90
+ >
91
+ <IconMCP classNames="size-8 text-blue-600 dark:text-blue-500" />
92
+ </div>
93
+ <div>
94
+ <p class="text-sm font-semibold text-gray-900 dark:text-gray-100">
95
+ {$allMcpServers.length}
96
+ {$allMcpServers.length === 1 ? "server" : "servers"} configured
97
+ </p>
98
+ <p class="text-xs text-gray-600 dark:text-gray-400">
99
+ {enabledCount} enabled
100
+ </p>
101
+ </div>
102
+ </div>
103
+
104
+ <div class="flex gap-2">
105
+ <button
106
+ onclick={handleRefresh}
107
+ disabled={isRefreshing}
108
+ class="btn gap-1.5 rounded-lg border border-gray-200 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"
109
+ >
110
+ <IconRefresh class="size-4 {isRefreshing ? 'animate-spin' : ''}" />
111
+ {isRefreshing ? "Refreshing…" : "Refresh"}
112
+ </button>
113
+ <button
114
+ onclick={() => (currentView = "add")}
115
+ class="btn flex items-center gap-0.5 rounded-lg bg-blue-600 py-1.5 pl-2 pr-3 text-sm font-medium text-white hover:bg-blue-600"
116
+ >
117
+ <IconAddLarge class="size-4" />
118
+ Add Server
119
+ </button>
120
+ </div>
121
+ </div>
122
+ <div class="space-y-5">
123
+ <!-- Base Servers -->
124
+ {#if baseServers.length > 0}
125
+ <div>
126
+ <h3 class="mb-3 text-sm font-medium text-gray-700 dark:text-gray-300">
127
+ Base Servers ({baseServers.length})
128
+ </h3>
129
+ <div class="grid grid-cols-1 gap-3 md:grid-cols-2">
130
+ {#each baseServers as server (server.id)}
131
+ <ServerCard {server} isSelected={$selectedServerIds.has(server.id)} />
132
+ {/each}
133
+ </div>
134
+ </div>
135
+ {/if}
136
+
137
+ <!-- Custom Servers -->
138
+ <div>
139
+ <h3 class="mb-3 text-sm font-medium text-gray-700 dark:text-gray-300">
140
+ Custom Servers ({customServers.length})
141
+ </h3>
142
+ {#if customServers.length === 0}
143
+ <div
144
+ class="flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 p-8 dark:border-gray-700"
145
+ >
146
+ <LucideHammer class="mb-3 size-12 text-gray-400" />
147
+ <p class="mb-1 text-sm font-medium text-gray-900 dark:text-gray-100">
148
+ No custom servers yet
149
+ </p>
150
+ <p class="mb-4 text-xs text-gray-600 dark:text-gray-400">
151
+ Add your own MCP servers with custom tools
152
+ </p>
153
+ <button
154
+ onclick={() => (currentView = "add")}
155
+ class="flex items-center gap-1.5 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-600"
156
+ >
157
+ <IconAddLarge class="size-4" />
158
+ Add Your First Server
159
+ </button>
160
+ </div>
161
+ {:else}
162
+ <div class="grid grid-cols-1 gap-3 md:grid-cols-2">
163
+ {#each customServers as server (server.id)}
164
+ <ServerCard {server} isSelected={$selectedServerIds.has(server.id)} />
165
+ {/each}
166
+ </div>
167
+ {/if}
168
+ </div>
169
+
170
+ <!-- Help Text -->
171
+ <div class="rounded-lg bg-gray-50 p-4 dark:bg-gray-700">
172
+ <h4 class="mb-2 text-sm font-medium text-gray-900 dark:text-gray-100">💡 Quick Tips</h4>
173
+ <ul class="space-y-1 text-xs text-gray-600 dark:text-gray-400">
174
+ <li>• Only connect to servers you trust</li>
175
+ <li>• Enable servers to make their tools available in chat</li>
176
+ <li>• Use the Health Check button to verify server connectivity</li>
177
+ <li>• You can add HTTP headers for authentication when required</li>
178
+ </ul>
179
+ </div>
180
+ </div>
181
+ {:else if currentView === "add"}
182
+ <AddServerForm onsubmit={handleAddServer} oncancel={handleCancel} />
183
+ {/if}
184
+ </div>
185
+ </Modal>
@@ -0,0 +1,203 @@
1
+ <script lang="ts">
2
+ import type { MCPServer } from "$lib/types/Tool";
3
+ import { toggleServer, healthCheckServer, deleteCustomServer } from "$lib/stores/mcpServers";
4
+ import IconCheckmark from "~icons/carbon/checkmark-filled";
5
+ import IconWarning from "~icons/carbon/warning-filled";
6
+ import IconPending from "~icons/carbon/pending-filled";
7
+ import IconRefresh from "~icons/carbon/renew";
8
+ import IconTrash from "~icons/carbon/trash-can";
9
+ import LucideHammer from "~icons/lucide/hammer";
10
+ import IconSettings from "~icons/carbon/settings";
11
+ import Switch from "$lib/components/Switch.svelte";
12
+ import { getMcpServerFaviconUrl } from "$lib/utils/favicon";
13
+
14
+ interface Props {
15
+ server: MCPServer;
16
+ isSelected: boolean;
17
+ }
18
+
19
+ let { server, isSelected }: Props = $props();
20
+
21
+ let isLoadingHealth = $state(false);
22
+
23
+ // Show a quick-access link ONLY for the exact HF MCP login endpoint
24
+ import { isStrictHfMcpLogin as isStrictHfMcpLoginUrl } from "$lib/utils/hf";
25
+ const isHfMcp = $derived.by(() => isStrictHfMcpLoginUrl(server.url));
26
+
27
+ const statusInfo = $derived.by(() => {
28
+ switch (server.status) {
29
+ case "connected":
30
+ return {
31
+ label: "Connected",
32
+ color: "text-green-600 dark:text-green-400",
33
+ bgColor: "bg-green-100 dark:bg-green-900/20",
34
+ icon: IconCheckmark,
35
+ };
36
+ case "connecting":
37
+ return {
38
+ label: "Connecting...",
39
+ color: "text-blue-600 dark:text-blue-400",
40
+ bgColor: "bg-blue-100 dark:bg-blue-900/20",
41
+ icon: IconPending,
42
+ };
43
+ case "error":
44
+ return {
45
+ label: "Error",
46
+ color: "text-red-600 dark:text-red-400",
47
+ bgColor: "bg-red-100 dark:bg-red-900/20",
48
+ icon: IconWarning,
49
+ };
50
+ case "disconnected":
51
+ default:
52
+ return {
53
+ label: "Unknown",
54
+ color: "text-gray-600 dark:text-gray-400",
55
+ bgColor: "bg-gray-100 dark:bg-gray-700",
56
+ icon: IconPending,
57
+ };
58
+ }
59
+ });
60
+
61
+ // Switch setter handles enable/disable (simple, idiomatic)
62
+ function setEnabled(v: boolean) {
63
+ if (v === isSelected) return;
64
+ toggleServer(server.id);
65
+ if (v && server.status !== "connected") handleHealthCheck();
66
+ }
67
+
68
+ async function handleHealthCheck() {
69
+ isLoadingHealth = true;
70
+ try {
71
+ await healthCheckServer(server);
72
+ } finally {
73
+ isLoadingHealth = false;
74
+ }
75
+ }
76
+
77
+ function handleDelete() {
78
+ deleteCustomServer(server.id);
79
+ }
80
+ </script>
81
+
82
+ <div
83
+ class="rounded-lg border bg-gradient-to-br transition-colors {isSelected
84
+ ? 'border-blue-600/20 bg-blue-50 from-blue-500/5 to-transparent dark:border-blue-700/60 dark:bg-blue-900/10 dark:from-blue-900/20'
85
+ : 'border-gray-200 bg-white from-black/5 dark:border-gray-700 dark:bg-gray-800 dark:from-white/5'}"
86
+ >
87
+ <div class="px-4 py-3.5">
88
+ <!-- Header -->
89
+ <div class="mb-3 flex items-start justify-between gap-3">
90
+ <div class="min-w-0 flex-1">
91
+ <div class="mb-0.5 flex items-center gap-2">
92
+ <img
93
+ src={getMcpServerFaviconUrl(server.url)}
94
+ alt=""
95
+ class="size-4 flex-shrink-0 rounded"
96
+ />
97
+ <h3 class="truncate font-semibold text-gray-900 dark:text-gray-100">
98
+ {server.name}
99
+ </h3>
100
+ </div>
101
+ <p class="truncate text-sm text-gray-600 dark:text-gray-400">
102
+ {server.url}
103
+ </p>
104
+ </div>
105
+
106
+ <!-- Enable Switch (function binding per Svelte 5 docs) -->
107
+ <Switch name={`enable-${server.id}`} bind:checked={() => isSelected, setEnabled} />
108
+ </div>
109
+
110
+ <!-- Status -->
111
+ {#if server.status}
112
+ <div class="mb-2 flex items-center gap-2">
113
+ <span
114
+ class="inline-flex items-center gap-1 rounded-full {statusInfo.bgColor} py-0.5 pl-1.5 pr-2 text-xs font-medium {statusInfo.color}"
115
+ >
116
+ {#if server.status === "connected"}
117
+ <IconCheckmark class="size-3" />
118
+ {:else if server.status === "connecting"}
119
+ <IconPending class="size-3" />
120
+ {:else if server.status === "error"}
121
+ <IconWarning class="size-3" />
122
+ {:else}
123
+ <IconPending class="size-3" />
124
+ {/if}
125
+ {statusInfo.label}
126
+ </span>
127
+
128
+ {#if server.tools && server.tools.length > 0}
129
+ <span class="inline-flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400">
130
+ <LucideHammer class="size-3" />
131
+ {server.tools.length}
132
+ {server.tools.length === 1 ? "tool" : "tools"}
133
+ </span>
134
+ {/if}
135
+ </div>
136
+ {/if}
137
+
138
+ <!-- Error Message -->
139
+ {#if server.errorMessage}
140
+ <div class="mb-2 flex items-center gap-2">
141
+ <div
142
+ class="line-clamp-6 break-words rounded bg-red-50 px-2 py-1 text-xs text-red-800 dark:bg-red-900/20 dark:text-red-200"
143
+ >
144
+ {server.errorMessage}
145
+ </div>
146
+ </div>
147
+ {/if}
148
+
149
+ <!-- Actions -->
150
+ <div class="flex flex-wrap gap-1">
151
+ <button
152
+ onclick={handleHealthCheck}
153
+ disabled={isLoadingHealth}
154
+ class="flex items-center gap-1.5 rounded-lg border border-gray-200 bg-white px-2.5 py-[.29rem] text-xs font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600"
155
+ >
156
+ <IconRefresh class="size-3 {isLoadingHealth ? 'animate-spin' : ''}" />
157
+ Health Check
158
+ </button>
159
+
160
+ {#if isHfMcp}
161
+ <a
162
+ href="https://huggingface.co/settings/mcp"
163
+ target="_blank"
164
+ rel="noopener noreferrer"
165
+ class="flex items-center gap-1.5 rounded-lg border border-gray-200 bg-white px-2.5 py-[.29rem] text-xs font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600"
166
+ aria-label="Open Hugging Face MCP settings"
167
+ >
168
+ <IconSettings class="size-3" />
169
+ Settings
170
+ </a>
171
+ {/if}
172
+
173
+ {#if server.type === "custom"}
174
+ <button
175
+ onclick={handleDelete}
176
+ class="flex items-center gap-1.5 rounded-lg border border-red-500/15 bg-red-50 px-2.5 py-[.29rem] text-xs font-medium text-red-600 hover:bg-red-100 dark:border-red-500/25 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50"
177
+ >
178
+ <IconTrash class="size-3" />
179
+ Delete
180
+ </button>
181
+ {/if}
182
+ </div>
183
+
184
+ <!-- Tools List (Expandable) -->
185
+ {#if server.tools && server.tools.length > 0}
186
+ <details class="mt-3">
187
+ <summary class="cursor-pointer text-xs font-medium text-gray-700 dark:text-gray-300">
188
+ Available Tools ({server.tools.length})
189
+ </summary>
190
+ <ul class="mt-2 space-y-1 text-xs">
191
+ {#each server.tools as tool}
192
+ <li class="text-gray-600 dark:text-gray-400">
193
+ <span class="font-medium text-gray-900 dark:text-gray-100">{tool.name}</span>
194
+ {#if tool.description}
195
+ <span class="text-gray-500 dark:text-gray-500">- {tool.description}</span>
196
+ {/if}
197
+ </li>
198
+ {/each}
199
+ </ul>
200
+ </details>
201
+ {/if}
202
+ </div>
203
+ </div>
@@ -0,0 +1,82 @@
1
+ <script lang="ts">
2
+ import CarbonPause from "~icons/carbon/pause";
3
+ import CarbonPlay from "~icons/carbon/play";
4
+ interface Props {
5
+ src: string;
6
+ name: string;
7
+ }
8
+
9
+ let { src, name }: Props = $props();
10
+
11
+ let time = $state(0);
12
+ let duration = $state(0);
13
+ let paused = $state(true);
14
+
15
+ function format(time: number) {
16
+ if (isNaN(time)) return "...";
17
+
18
+ const minutes = Math.floor(time / 60);
19
+ const seconds = Math.floor(time % 60);
20
+
21
+ return `${minutes}:${seconds < 10 ? `0${seconds}` : seconds}`;
22
+ }
23
+
24
+ function seek(e: PointerEvent) {
25
+ if (!e.currentTarget) return;
26
+ const { left, width } = (e.currentTarget as HTMLElement).getBoundingClientRect();
27
+
28
+ let p = (e.clientX - left) / width;
29
+ if (p < 0) p = 0;
30
+ if (p > 1) p = 1;
31
+
32
+ time = p * duration;
33
+ }
34
+ </script>
35
+
36
+ <div
37
+ class="flex h-14 w-72 items-center gap-4 rounded-2xl border border-gray-200 bg-white p-2.5 text-gray-600 shadow-sm transition-all dark:border-gray-800 dark:bg-gray-900 dark:text-gray-300"
38
+ >
39
+ <audio
40
+ {src}
41
+ bind:currentTime={time}
42
+ bind:duration
43
+ bind:paused
44
+ preload="metadata"
45
+ onended={() => {
46
+ time = 0;
47
+ }}
48
+ ></audio>
49
+
50
+ <button
51
+ class="mx-auto my-auto aspect-square size-8 rounded-full border border-gray-400 bg-gray-100 dark:border-gray-800 dark:bg-gray-700"
52
+ aria-label={paused ? "play" : "pause"}
53
+ onclick={() => (paused = !paused)}
54
+ >
55
+ {#if paused}
56
+ <CarbonPlay class="mx-auto my-auto text-gray-600 dark:text-gray-300" />
57
+ {:else}
58
+ <CarbonPause class="mx-auto my-auto text-gray-600 dark:text-gray-300" />
59
+ {/if}
60
+ </button>
61
+ <div class="overflow-hidden">
62
+ <div class="truncate font-medium">{name}</div>
63
+ {#if duration !== Infinity}
64
+ <div class="flex items-center gap-2">
65
+ <span class="text-xs">{format(time)}</span>
66
+ <div
67
+ class="relative h-2 flex-1 rounded-full bg-gray-200 dark:bg-gray-700"
68
+ onpointerdown={() => {
69
+ paused = true;
70
+ }}
71
+ onpointerup={seek}
72
+ >
73
+ <div
74
+ class="absolute inset-0 h-full bg-gray-400 dark:bg-gray-600"
75
+ style="width: {(time / duration) * 100}%"
76
+ ></div>
77
+ </div>
78
+ <span class="text-xs">{duration ? format(duration) : "--:--"}</span>
79
+ </div>
80
+ {/if}
81
+ </div>
82
+ </div>
@@ -0,0 +1,96 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from "svelte";
3
+
4
+ interface Props {
5
+ frequencyData: Uint8Array;
6
+ minHeight?: number;
7
+ maxHeight?: number;
8
+ }
9
+
10
+ let { frequencyData, minHeight = 4, maxHeight = 40 }: Props = $props();
11
+
12
+ const PILL_WIDTH = 2; // w-0.5 = 2px
13
+ const PILL_GAP = 2;
14
+ const SAMPLE_INTERVAL_MS = 50; // Sample every 50ms (~20 samples/sec)
15
+
16
+ let containerRef: HTMLDivElement | undefined = $state();
17
+ let timeline: number[] = $state([]);
18
+ let pillCount = $state(60); // Default, will be calculated from container width
19
+ let intervalId: ReturnType<typeof setInterval> | undefined;
20
+ let smoothedAmplitude = 0;
21
+
22
+ // Calculate average amplitude from frequency data
23
+ function getAmplitude(): number {
24
+ if (!frequencyData.length) return 0;
25
+ let sum = 0;
26
+ for (let i = 0; i < frequencyData.length; i++) {
27
+ sum += frequencyData[i];
28
+ }
29
+ return sum / frequencyData.length / 255; // Normalize to 0-1
30
+ }
31
+
32
+ function addSample() {
33
+ const rawAmplitude = getAmplitude();
34
+ // Smooth the amplitude for less jittery visualization
35
+ smoothedAmplitude = smoothedAmplitude * 0.3 + rawAmplitude * 0.7;
36
+
37
+ // Boost amplitude by 1.5x and apply slight curve for better visibility
38
+ const boostedAmplitude = Math.min(1, Math.pow(smoothedAmplitude * 1.5, 0.85));
39
+
40
+ const height = minHeight + boostedAmplitude * (maxHeight - minHeight);
41
+
42
+ // Push new sample, keep only pillCount samples (sliding window)
43
+ timeline = [...timeline, height].slice(-pillCount);
44
+ }
45
+
46
+ function calculatePillCount() {
47
+ if (containerRef) {
48
+ const width = containerRef.clientWidth;
49
+ pillCount = Math.max(20, Math.floor(width / (PILL_WIDTH + PILL_GAP)));
50
+ }
51
+ }
52
+
53
+ onMount(() => {
54
+ calculatePillCount();
55
+
56
+ // Initialize timeline with minimum height dots
57
+ timeline = Array(pillCount).fill(minHeight);
58
+
59
+ // Start sampling at fixed intervals
60
+ intervalId = setInterval(addSample, SAMPLE_INTERVAL_MS);
61
+
62
+ // Handle resize
63
+ const resizeObserver = new ResizeObserver(() => {
64
+ const oldCount = pillCount;
65
+ calculatePillCount();
66
+ // Adjust timeline buffer if container size changed
67
+ if (pillCount > oldCount) {
68
+ // Pad with min height on the left
69
+ timeline = [...Array(pillCount - oldCount).fill(minHeight), ...timeline];
70
+ } else if (pillCount < oldCount) {
71
+ timeline = timeline.slice(-pillCount);
72
+ }
73
+ });
74
+
75
+ if (containerRef) {
76
+ resizeObserver.observe(containerRef);
77
+ }
78
+
79
+ return () => {
80
+ resizeObserver.disconnect();
81
+ };
82
+ });
83
+
84
+ onDestroy(() => {
85
+ if (intervalId) clearInterval(intervalId);
86
+ });
87
+ </script>
88
+
89
+ <div bind:this={containerRef} class="flex h-12 w-full items-center justify-start gap-[2px]">
90
+ {#each timeline as height, i (i)}
91
+ <div
92
+ class="w-0.5 shrink-0 rounded-full bg-gray-400 dark:bg-white/60"
93
+ style="height: {Math.max(minHeight, Math.round(height))}px;"
94
+ ></div>
95
+ {/each}
96
+ </div>
@@ -0,0 +1,135 @@
1
+ import type { RouterExample } from "./routerExamples";
2
+
3
+ // Examples that showcase MCP tool capabilities (web search, Hugging Face, etc.)
4
+ export const mcpExamples: RouterExample[] = [
5
+ {
6
+ title: "Generate an image",
7
+ prompt: "Generate an image of a zebra in front of a volcanic eruption",
8
+ },
9
+ {
10
+ title: "Latest world news",
11
+ prompt: "What is the latest world news?",
12
+ followUps: [
13
+ {
14
+ title: "Tech focus",
15
+ prompt: "What about technology news?",
16
+ },
17
+ {
18
+ title: "San Francisco",
19
+ prompt: "What's happening in San Francisco?",
20
+ },
21
+ {
22
+ title: "vs last week",
23
+ prompt: "How does this compare to last week's news?",
24
+ },
25
+ ],
26
+ },
27
+ {
28
+ title: "Trending models",
29
+ prompt: "What are the top trending models on Hugging Face?",
30
+ followUps: [
31
+ {
32
+ title: "Text generation",
33
+ prompt: "What about text generation models?",
34
+ },
35
+ {
36
+ title: "Image generation",
37
+ prompt: "What about text-to-image models?",
38
+ },
39
+ {
40
+ title: "How to use",
41
+ prompt: "Show me how to use the most popular one",
42
+ },
43
+ ],
44
+ },
45
+ {
46
+ title: "Plan a trip",
47
+ prompt: "Things to do in Tokyo next week",
48
+ followUps: [
49
+ {
50
+ title: "Transport & prices",
51
+ prompt: "How do I get around and how much will it cost?",
52
+ },
53
+ {
54
+ title: "Weather",
55
+ prompt: "What's the weather like in Tokyo next week?",
56
+ },
57
+ {
58
+ title: "Meet people",
59
+ prompt: "Where can I meet new people and make friends?",
60
+ },
61
+ ],
62
+ },
63
+ {
64
+ title: "Compare technologies",
65
+ prompt: "Search the web to compare React, Vue, and Svelte for building web apps in 2025",
66
+ followUps: [
67
+ {
68
+ title: "Performance benchmarks",
69
+ prompt: "Search for recent performance benchmarks comparing these frameworks",
70
+ },
71
+ {
72
+ title: "Job market",
73
+ prompt: "Search for job market trends for each of these frameworks",
74
+ },
75
+ {
76
+ title: "Migration guides",
77
+ prompt: "Search for guides on migrating from React to Svelte",
78
+ },
79
+ ],
80
+ },
81
+ {
82
+ title: "Find a dataset",
83
+ prompt: "Find datasets on Hugging Face for training a sentiment analysis model",
84
+ followUps: [
85
+ {
86
+ title: "Dataset details",
87
+ prompt: "Tell me more about the largest dataset - its size, format, and how to load it",
88
+ },
89
+ {
90
+ title: "Find models",
91
+ prompt: "Find pre-trained models that were trained on this dataset",
92
+ },
93
+ {
94
+ title: "Code snippet",
95
+ prompt: "Show me how to load and preprocess this dataset with the datasets library",
96
+ },
97
+ ],
98
+ },
99
+ {
100
+ title: "Gift ideas",
101
+ prompt: "Search for unique gift ideas for someone who loves cooking",
102
+ followUps: [
103
+ {
104
+ title: "Budget options",
105
+ prompt: "Search for gift ideas under $50",
106
+ },
107
+ {
108
+ title: "Top rated",
109
+ prompt: "Search for the top-rated cooking gadgets of this year",
110
+ },
111
+ {
112
+ title: "DIY gifts",
113
+ prompt: "Search for homemade gift ideas for cooking enthusiasts",
114
+ },
115
+ ],
116
+ },
117
+ {
118
+ title: "Learn something new",
119
+ prompt: "Search for the best resources to learn Rust programming in 2025",
120
+ followUps: [
121
+ {
122
+ title: "Project ideas",
123
+ prompt: "Search for beginner Rust project ideas to practice with",
124
+ },
125
+ {
126
+ title: "Find tools",
127
+ prompt: "Search for the most popular Rust tools and libraries I should know about",
128
+ },
129
+ {
130
+ title: "Community",
131
+ prompt: "Search for Rust communities and forums where I can ask questions",
132
+ },
133
+ ],
134
+ },
135
+ ];