ruflo 3.10.46 → 3.12.0

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 (498) hide show
  1. package/README.md +412 -412
  2. package/bin/ruflo.js +77 -77
  3. package/package.json +118 -113
  4. package/src/chat-ui/Dockerfile +25 -25
  5. package/src/chat-ui/patch-mcp-url-safety.sh +28 -28
  6. package/src/config/config.example.json +76 -76
  7. package/src/mcp-bridge/Dockerfile +45 -45
  8. package/src/mcp-bridge/index.js +1692 -1692
  9. package/src/mcp-bridge/mcp-stdio-kernel.js +159 -159
  10. package/src/mcp-bridge/package.json +17 -17
  11. package/src/mcp-bridge/test-harness.js +470 -470
  12. package/src/nginx/Dockerfile +10 -10
  13. package/src/nginx/nginx.conf +67 -67
  14. package/src/nginx/static/favicon-dark.svg +4 -4
  15. package/src/nginx/static/favicon.svg +4 -4
  16. package/src/nginx/static/icon.svg +5 -5
  17. package/src/nginx/static/logo.svg +9 -9
  18. package/src/nginx/static/manifest.json +22 -22
  19. package/src/nginx/static/welcome.js +184 -184
  20. package/src/ruvocal/.claude/skills/add-model-descriptions/SKILL.md +73 -73
  21. package/src/ruvocal/.claude-flow/daemon-state.json +135 -0
  22. package/src/ruvocal/.claude-flow/data/pending-insights.jsonl +0 -0
  23. package/src/ruvocal/.claude-flow/data/ranked-context.json +5 -0
  24. package/src/ruvocal/.claude-flow/logs/daemon.log +31 -0
  25. package/src/ruvocal/.claude-flow/logs/headless/audit_1777949411822_juxau0_prompt.log +989 -0
  26. package/src/ruvocal/.claude-flow/logs/headless/audit_1777949411822_juxau0_result.log +67 -0
  27. package/src/ruvocal/.claude-flow/logs/headless/audit_1777950042278_jvj5xq_prompt.log +989 -0
  28. package/src/ruvocal/.claude-flow/logs/headless/audit_1777950042278_jvj5xq_result.log +93 -0
  29. package/src/ruvocal/.claude-flow/logs/headless/optimize_1777949531823_yt5yc2_prompt.log +1498 -0
  30. package/src/ruvocal/.claude-flow/logs/headless/optimize_1777949531823_yt5yc2_result.log +93 -0
  31. package/src/ruvocal/.claude-flow/logs/headless/testgaps_1777949771821_elw1j4_prompt.log +1498 -0
  32. package/src/ruvocal/.claude-flow/logs/headless/testgaps_1777949771821_elw1j4_result.log +100 -0
  33. package/src/ruvocal/.claude-flow/metrics/codebase-map.json +11 -0
  34. package/src/ruvocal/.claude-flow/metrics/consolidation.json +6 -0
  35. package/src/ruvocal/.claude-flow/neural/stats.json +6 -0
  36. package/src/ruvocal/.claude-flow/sessions/current.json +13 -0
  37. package/src/ruvocal/.devcontainer/Dockerfile +9 -9
  38. package/src/ruvocal/.devcontainer/devcontainer.json +36 -36
  39. package/src/ruvocal/.dockerignore +16 -16
  40. package/src/ruvocal/.eslintignore +13 -13
  41. package/src/ruvocal/.eslintrc.cjs +45 -45
  42. package/src/ruvocal/.gcloudignore +18 -18
  43. package/src/ruvocal/.github/ISSUE_TEMPLATE/bug-report--chat-ui-.md +43 -43
  44. package/src/ruvocal/.github/ISSUE_TEMPLATE/config-support.md +9 -9
  45. package/src/ruvocal/.github/ISSUE_TEMPLATE/feature-request--chat-ui-.md +17 -17
  46. package/src/ruvocal/.github/ISSUE_TEMPLATE/huggingchat.md +11 -11
  47. package/src/ruvocal/.github/release.yml +16 -16
  48. package/src/ruvocal/.github/workflows/build-docs.yml +18 -18
  49. package/src/ruvocal/.github/workflows/build-image.yml +142 -142
  50. package/src/ruvocal/.github/workflows/build-pr-docs.yml +20 -20
  51. package/src/ruvocal/.github/workflows/deploy-dev.yml +63 -63
  52. package/src/ruvocal/.github/workflows/deploy-prod.yml +78 -78
  53. package/src/ruvocal/.github/workflows/lint-and-test.yml +84 -84
  54. package/src/ruvocal/.github/workflows/slugify.yaml +72 -72
  55. package/src/ruvocal/.github/workflows/trufflehog.yml +17 -17
  56. package/src/ruvocal/.github/workflows/upload-pr-documentation.yml +16 -16
  57. package/src/ruvocal/.husky/lint-stage-config.js +4 -4
  58. package/src/ruvocal/.husky/pre-commit +2 -2
  59. package/src/ruvocal/.prettierignore +14 -14
  60. package/src/ruvocal/.prettierrc +7 -7
  61. package/src/ruvocal/.swarm/attestation.db +0 -0
  62. package/src/ruvocal/.swarm/hnsw.index +0 -0
  63. package/src/ruvocal/.swarm/hnsw.metadata.json +1 -0
  64. package/src/ruvocal/.swarm/memory.db +0 -0
  65. package/src/ruvocal/.swarm/schema.sql +305 -0
  66. package/src/ruvocal/CLAUDE.md +126 -126
  67. package/src/ruvocal/Dockerfile +96 -96
  68. package/src/ruvocal/LICENSE +202 -202
  69. package/src/ruvocal/PRIVACY.md +41 -41
  70. package/src/ruvocal/README.md +164 -164
  71. package/src/ruvocal/chart/Chart.yaml +5 -5
  72. package/src/ruvocal/chart/env/dev.yaml +260 -260
  73. package/src/ruvocal/chart/env/prod.yaml +273 -273
  74. package/src/ruvocal/chart/templates/_helpers.tpl +22 -22
  75. package/src/ruvocal/chart/templates/config.yaml +10 -10
  76. package/src/ruvocal/chart/templates/deployment.yaml +81 -81
  77. package/src/ruvocal/chart/templates/hpa.yaml +45 -45
  78. package/src/ruvocal/chart/templates/infisical.yaml +24 -24
  79. package/src/ruvocal/chart/templates/ingress-internal.yaml +32 -32
  80. package/src/ruvocal/chart/templates/ingress.yaml +32 -32
  81. package/src/ruvocal/chart/templates/network-policy.yaml +36 -36
  82. package/src/ruvocal/chart/templates/service-account.yaml +13 -13
  83. package/src/ruvocal/chart/templates/service-monitor.yaml +17 -17
  84. package/src/ruvocal/chart/templates/service.yaml +21 -21
  85. package/src/ruvocal/chart/values.yaml +73 -73
  86. package/src/ruvocal/cloudbuild.yaml +68 -68
  87. package/src/ruvocal/config/branding.env.example +19 -19
  88. package/src/ruvocal/docker-compose.yml +21 -21
  89. package/src/ruvocal/docs/adr/ADR-029-HUGGINGFACE-CHAT-UI-CLOUD-RUN.md +1236 -1236
  90. package/src/ruvocal/docs/adr/ADR-033-RUVECTOR-RUFLO-MCP-INTEGRATION.md +111 -111
  91. package/src/ruvocal/docs/adr/ADR-034-OPTIONAL-MCP-BACKENDS.md +117 -117
  92. package/src/ruvocal/docs/adr/ADR-035-MCP-TOOL-GROUPS.md +186 -186
  93. package/src/ruvocal/docs/adr/ADR-037-AUTOPILOT-CHAT-MODE.md +1500 -1500
  94. package/src/ruvocal/docs/adr/ADR-038-RUVOCAL-FORK.md +286 -286
  95. package/src/ruvocal/docs/source/_toctree.yml +30 -30
  96. package/src/ruvocal/docs/source/configuration/common-issues.md +38 -38
  97. package/src/ruvocal/docs/source/configuration/llm-router.md +105 -105
  98. package/src/ruvocal/docs/source/configuration/mcp-tools.md +84 -84
  99. package/src/ruvocal/docs/source/configuration/metrics.md +9 -9
  100. package/src/ruvocal/docs/source/configuration/open-id.md +57 -57
  101. package/src/ruvocal/docs/source/configuration/overview.md +89 -89
  102. package/src/ruvocal/docs/source/configuration/theming.md +20 -20
  103. package/src/ruvocal/docs/source/developing/architecture.md +48 -48
  104. package/src/ruvocal/docs/source/index.md +53 -53
  105. package/src/ruvocal/docs/source/installation/docker.md +43 -43
  106. package/src/ruvocal/docs/source/installation/helm.md +43 -43
  107. package/src/ruvocal/docs/source/installation/local.md +62 -62
  108. package/src/ruvocal/entrypoint.sh +18 -18
  109. package/src/ruvocal/mcp-bridge/Dockerfile +45 -45
  110. package/src/ruvocal/mcp-bridge/cloudbuild.yaml +49 -49
  111. package/src/ruvocal/mcp-bridge/index.js +1902 -1902
  112. package/src/ruvocal/mcp-bridge/mcp-stdio-kernel.js +159 -159
  113. package/src/ruvocal/mcp-bridge/package-lock.json +762 -762
  114. package/src/ruvocal/mcp-bridge/package.json +17 -17
  115. package/src/ruvocal/mcp-bridge/test-harness.js +470 -470
  116. package/src/ruvocal/package-lock.json +11741 -11741
  117. package/src/ruvocal/package.json +121 -121
  118. package/src/ruvocal/postcss.config.js +6 -6
  119. package/src/ruvocal/rvf.manifest.json +204 -204
  120. package/src/ruvocal/scripts/config.ts +64 -64
  121. package/src/ruvocal/scripts/generate-welcome.mjs +181 -181
  122. package/src/ruvocal/scripts/populate.ts +288 -288
  123. package/src/ruvocal/scripts/samples.txt +194 -194
  124. package/src/ruvocal/scripts/setups/vitest-setup-server.ts +44 -44
  125. package/src/ruvocal/scripts/updateLocalEnv.ts +48 -48
  126. package/src/ruvocal/src/ambient.d.ts +7 -7
  127. package/src/ruvocal/src/app.d.ts +29 -29
  128. package/src/ruvocal/src/app.html +53 -53
  129. package/src/ruvocal/src/hooks.server.ts +32 -32
  130. package/src/ruvocal/src/hooks.ts +6 -6
  131. package/src/ruvocal/src/lib/APIClient.ts +148 -148
  132. package/src/ruvocal/src/lib/actions/clickOutside.ts +18 -18
  133. package/src/ruvocal/src/lib/actions/snapScrollToBottom.ts +346 -346
  134. package/src/ruvocal/src/lib/buildPrompt.ts +33 -33
  135. package/src/ruvocal/src/lib/components/AnnouncementBanner.svelte +20 -20
  136. package/src/ruvocal/src/lib/components/BackgroundGenerationPoller.svelte +168 -168
  137. package/src/ruvocal/src/lib/components/CodeBlock.svelte +73 -73
  138. package/src/ruvocal/src/lib/components/CopyToClipBoardBtn.svelte +92 -92
  139. package/src/ruvocal/src/lib/components/DeleteConversationModal.svelte +75 -75
  140. package/src/ruvocal/src/lib/components/EditConversationModal.svelte +100 -100
  141. package/src/ruvocal/src/lib/components/ExpandNavigation.svelte +22 -22
  142. package/src/ruvocal/src/lib/components/FoundationBackground.svelte +242 -242
  143. package/src/ruvocal/src/lib/components/HoverTooltip.svelte +44 -44
  144. package/src/ruvocal/src/lib/components/HtmlPreviewModal.svelte +143 -143
  145. package/src/ruvocal/src/lib/components/InfiniteScroll.svelte +50 -50
  146. package/src/ruvocal/src/lib/components/MobileNav.svelte +300 -300
  147. package/src/ruvocal/src/lib/components/Modal.svelte +115 -115
  148. package/src/ruvocal/src/lib/components/ModelCardMetadata.svelte +71 -71
  149. package/src/ruvocal/src/lib/components/NavConversationItem.svelte +151 -151
  150. package/src/ruvocal/src/lib/components/NavMenu.svelte +313 -313
  151. package/src/ruvocal/src/lib/components/Pagination.svelte +97 -97
  152. package/src/ruvocal/src/lib/components/PaginationArrow.svelte +27 -27
  153. package/src/ruvocal/src/lib/components/Portal.svelte +24 -24
  154. package/src/ruvocal/src/lib/components/RetryBtn.svelte +18 -18
  155. package/src/ruvocal/src/lib/components/RuFloUniverse.svelte +185 -185
  156. package/src/ruvocal/src/lib/components/RufloHelpModal.svelte +411 -411
  157. package/src/ruvocal/src/lib/components/ScrollToBottomBtn.svelte +47 -47
  158. package/src/ruvocal/src/lib/components/ScrollToPreviousBtn.svelte +77 -77
  159. package/src/ruvocal/src/lib/components/ShareConversationModal.svelte +182 -182
  160. package/src/ruvocal/src/lib/components/StopGeneratingBtn.svelte +69 -69
  161. package/src/ruvocal/src/lib/components/SubscribeModal.svelte +87 -87
  162. package/src/ruvocal/src/lib/components/Switch.svelte +36 -36
  163. package/src/ruvocal/src/lib/components/SystemPromptModal.svelte +44 -44
  164. package/src/ruvocal/src/lib/components/Toast.svelte +27 -27
  165. package/src/ruvocal/src/lib/components/Tooltip.svelte +30 -30
  166. package/src/ruvocal/src/lib/components/WelcomeModal.svelte +46 -46
  167. package/src/ruvocal/src/lib/components/chat/Alternatives.svelte +77 -77
  168. package/src/ruvocal/src/lib/components/chat/BlockWrapper.svelte +72 -72
  169. package/src/ruvocal/src/lib/components/chat/ChatInput.svelte +490 -490
  170. package/src/ruvocal/src/lib/components/chat/ChatIntroduction.svelte +123 -123
  171. package/src/ruvocal/src/lib/components/chat/ChatMessage.svelte +548 -548
  172. package/src/ruvocal/src/lib/components/chat/ChatWindow.svelte +1057 -1057
  173. package/src/ruvocal/src/lib/components/chat/FileDropzone.svelte +92 -92
  174. package/src/ruvocal/src/lib/components/chat/ImageLightbox.svelte +66 -66
  175. package/src/ruvocal/src/lib/components/chat/MarkdownBlock.svelte +23 -23
  176. package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte +69 -69
  177. package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte.test.ts +58 -58
  178. package/src/ruvocal/src/lib/components/chat/MessageAvatar.svelte +103 -103
  179. package/src/ruvocal/src/lib/components/chat/ModelSwitch.svelte +64 -64
  180. package/src/ruvocal/src/lib/components/chat/OpenReasoningResults.svelte +81 -81
  181. package/src/ruvocal/src/lib/components/chat/TaskGroup.svelte +88 -88
  182. package/src/ruvocal/src/lib/components/chat/ToolUpdate.svelte +273 -273
  183. package/src/ruvocal/src/lib/components/chat/UploadedFile.svelte +253 -253
  184. package/src/ruvocal/src/lib/components/chat/UrlFetchModal.svelte +203 -203
  185. package/src/ruvocal/src/lib/components/chat/VoiceRecorder.svelte +214 -214
  186. package/src/ruvocal/src/lib/components/icons/IconBurger.svelte +20 -20
  187. package/src/ruvocal/src/lib/components/icons/IconCheap.svelte +20 -20
  188. package/src/ruvocal/src/lib/components/icons/IconChevron.svelte +24 -24
  189. package/src/ruvocal/src/lib/components/icons/IconDazzled.svelte +40 -40
  190. package/src/ruvocal/src/lib/components/icons/IconFast.svelte +20 -20
  191. package/src/ruvocal/src/lib/components/icons/IconLoading.svelte +22 -22
  192. package/src/ruvocal/src/lib/components/icons/IconMCP.svelte +28 -28
  193. package/src/ruvocal/src/lib/components/icons/IconMoon.svelte +21 -21
  194. package/src/ruvocal/src/lib/components/icons/IconNew.svelte +20 -20
  195. package/src/ruvocal/src/lib/components/icons/IconOmni.svelte +90 -90
  196. package/src/ruvocal/src/lib/components/icons/IconPaperclip.svelte +24 -24
  197. package/src/ruvocal/src/lib/components/icons/IconPro.svelte +37 -37
  198. package/src/ruvocal/src/lib/components/icons/IconShare.svelte +21 -21
  199. package/src/ruvocal/src/lib/components/icons/IconSun.svelte +93 -93
  200. package/src/ruvocal/src/lib/components/icons/Logo.svelte +68 -68
  201. package/src/ruvocal/src/lib/components/icons/LogoHuggingFaceBorderless.svelte +54 -54
  202. package/src/ruvocal/src/lib/components/mcp/AddServerForm.svelte +250 -250
  203. package/src/ruvocal/src/lib/components/mcp/MCPServerManager.svelte +185 -185
  204. package/src/ruvocal/src/lib/components/mcp/ServerCard.svelte +203 -203
  205. package/src/ruvocal/src/lib/components/players/AudioPlayer.svelte +82 -82
  206. package/src/ruvocal/src/lib/components/voice/AudioWaveform.svelte +96 -96
  207. package/src/ruvocal/src/lib/components/wasm/GalleryPanel.svelte +357 -357
  208. package/src/ruvocal/src/lib/constants/mcpExamples.ts +114 -114
  209. package/src/ruvocal/src/lib/constants/mime.ts +11 -11
  210. package/src/ruvocal/src/lib/constants/pagination.ts +1 -1
  211. package/src/ruvocal/src/lib/constants/publicSepToken.ts +1 -1
  212. package/src/ruvocal/src/lib/constants/routerExamples.ts +133 -133
  213. package/src/ruvocal/src/lib/constants/rvagentPresets.ts +206 -206
  214. package/src/ruvocal/src/lib/createShareLink.ts +27 -27
  215. package/src/ruvocal/src/lib/jobs/refresh-conversation-stats.ts +297 -297
  216. package/src/ruvocal/src/lib/migrations/lock.ts +56 -56
  217. package/src/ruvocal/src/lib/migrations/migrations.spec.ts +74 -74
  218. package/src/ruvocal/src/lib/migrations/migrations.ts +109 -109
  219. package/src/ruvocal/src/lib/migrations/routines/01-update-search-assistants.ts +50 -50
  220. package/src/ruvocal/src/lib/migrations/routines/02-update-assistants-models.ts +48 -48
  221. package/src/ruvocal/src/lib/migrations/routines/04-update-message-updates.ts +151 -151
  222. package/src/ruvocal/src/lib/migrations/routines/05-update-message-files.ts +56 -56
  223. package/src/ruvocal/src/lib/migrations/routines/06-trim-message-updates.ts +56 -56
  224. package/src/ruvocal/src/lib/migrations/routines/08-update-featured-to-review.ts +32 -32
  225. package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts +214 -214
  226. package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.ts +88 -88
  227. package/src/ruvocal/src/lib/migrations/routines/10-update-reports-assistantid.ts +29 -29
  228. package/src/ruvocal/src/lib/migrations/routines/index.ts +15 -15
  229. package/src/ruvocal/src/lib/server/__tests__/conversation-stop-generating.spec.ts +103 -103
  230. package/src/ruvocal/src/lib/server/abortRegistry.ts +57 -57
  231. package/src/ruvocal/src/lib/server/abortedGenerations.ts +43 -43
  232. package/src/ruvocal/src/lib/server/adminToken.ts +62 -62
  233. package/src/ruvocal/src/lib/server/api/__tests__/conversations-id.spec.ts +296 -296
  234. package/src/ruvocal/src/lib/server/api/__tests__/conversations-message.spec.ts +216 -216
  235. package/src/ruvocal/src/lib/server/api/__tests__/conversations.spec.ts +235 -235
  236. package/src/ruvocal/src/lib/server/api/__tests__/misc.spec.ts +72 -72
  237. package/src/ruvocal/src/lib/server/api/__tests__/testHelpers.ts +86 -86
  238. package/src/ruvocal/src/lib/server/api/__tests__/user-reports.spec.ts +78 -78
  239. package/src/ruvocal/src/lib/server/api/__tests__/user.spec.ts +239 -239
  240. package/src/ruvocal/src/lib/server/api/types.ts +37 -37
  241. package/src/ruvocal/src/lib/server/api/utils/requireAuth.ts +22 -22
  242. package/src/ruvocal/src/lib/server/api/utils/resolveConversation.ts +69 -69
  243. package/src/ruvocal/src/lib/server/api/utils/resolveModel.ts +27 -27
  244. package/src/ruvocal/src/lib/server/api/utils/superjsonResponse.ts +15 -15
  245. package/src/ruvocal/src/lib/server/apiToken.ts +11 -11
  246. package/src/ruvocal/src/lib/server/auth.ts +554 -554
  247. package/src/ruvocal/src/lib/server/config.ts +187 -187
  248. package/src/ruvocal/src/lib/server/conversation.ts +83 -83
  249. package/src/ruvocal/src/lib/server/database/__tests__/rvf.spec.ts +709 -709
  250. package/src/ruvocal/src/lib/server/database/postgres.ts +700 -700
  251. package/src/ruvocal/src/lib/server/database/rvf.ts +1078 -1078
  252. package/src/ruvocal/src/lib/server/database.ts +145 -145
  253. package/src/ruvocal/src/lib/server/endpoints/document.ts +68 -68
  254. package/src/ruvocal/src/lib/server/endpoints/endpoints.ts +43 -43
  255. package/src/ruvocal/src/lib/server/endpoints/images.ts +211 -211
  256. package/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts +266 -266
  257. package/src/ruvocal/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts +212 -212
  258. package/src/ruvocal/src/lib/server/endpoints/openai/openAICompletionToTextGenerationStream.ts +32 -32
  259. package/src/ruvocal/src/lib/server/endpoints/preprocessMessages.ts +61 -61
  260. package/src/ruvocal/src/lib/server/exitHandler.ts +59 -59
  261. package/src/ruvocal/src/lib/server/files/downloadFile.ts +34 -34
  262. package/src/ruvocal/src/lib/server/files/uploadFile.ts +29 -29
  263. package/src/ruvocal/src/lib/server/findRepoRoot.ts +13 -13
  264. package/src/ruvocal/src/lib/server/generateFromDefaultEndpoint.ts +46 -46
  265. package/src/ruvocal/src/lib/server/hooks/error.ts +37 -37
  266. package/src/ruvocal/src/lib/server/hooks/fetch.ts +22 -22
  267. package/src/ruvocal/src/lib/server/hooks/handle.ts +250 -250
  268. package/src/ruvocal/src/lib/server/hooks/init.ts +51 -51
  269. package/src/ruvocal/src/lib/server/isURLLocal.spec.ts +31 -31
  270. package/src/ruvocal/src/lib/server/isURLLocal.ts +74 -74
  271. package/src/ruvocal/src/lib/server/logger.ts +42 -42
  272. package/src/ruvocal/src/lib/server/mcp/clientPool.spec.ts +175 -175
  273. package/src/ruvocal/src/lib/server/mcp/hf.ts +32 -32
  274. package/src/ruvocal/src/lib/server/mcp/httpClient.ts +122 -122
  275. package/src/ruvocal/src/lib/server/mcp/registry.ts +76 -76
  276. package/src/ruvocal/src/lib/server/mcp/tools.ts +196 -196
  277. package/src/ruvocal/src/lib/server/metrics.ts +255 -255
  278. package/src/ruvocal/src/lib/server/models.ts +518 -518
  279. package/src/ruvocal/src/lib/server/requestContext.ts +55 -55
  280. package/src/ruvocal/src/lib/server/router/arch.ts +230 -230
  281. package/src/ruvocal/src/lib/server/router/endpoint.ts +316 -316
  282. package/src/ruvocal/src/lib/server/router/multimodal.ts +28 -28
  283. package/src/ruvocal/src/lib/server/router/policy.ts +49 -49
  284. package/src/ruvocal/src/lib/server/router/toolsRoute.ts +51 -51
  285. package/src/ruvocal/src/lib/server/router/types.ts +21 -21
  286. package/src/ruvocal/src/lib/server/sendSlack.ts +23 -23
  287. package/src/ruvocal/src/lib/server/textGeneration/generate.ts +258 -258
  288. package/src/ruvocal/src/lib/server/textGeneration/index.ts +96 -96
  289. package/src/ruvocal/src/lib/server/textGeneration/mcp/fileRefs.ts +155 -155
  290. package/src/ruvocal/src/lib/server/textGeneration/mcp/routerResolution.ts +108 -108
  291. package/src/ruvocal/src/lib/server/textGeneration/mcp/runMcpFlow.ts +831 -831
  292. package/src/ruvocal/src/lib/server/textGeneration/mcp/toolInvocation.ts +349 -349
  293. package/src/ruvocal/src/lib/server/textGeneration/mcp/wasmTools.test.ts +633 -633
  294. package/src/ruvocal/src/lib/server/textGeneration/reasoning.ts +23 -23
  295. package/src/ruvocal/src/lib/server/textGeneration/title.ts +83 -83
  296. package/src/ruvocal/src/lib/server/textGeneration/types.ts +28 -28
  297. package/src/ruvocal/src/lib/server/textGeneration/utils/prepareFiles.ts +88 -88
  298. package/src/ruvocal/src/lib/server/textGeneration/utils/routing.ts +21 -21
  299. package/src/ruvocal/src/lib/server/textGeneration/utils/toolPrompt.ts +49 -49
  300. package/src/ruvocal/src/lib/server/urlSafety.ts +77 -77
  301. package/src/ruvocal/src/lib/server/usageLimits.ts +30 -30
  302. package/src/ruvocal/src/lib/stores/autopilotStore.svelte.ts +175 -175
  303. package/src/ruvocal/src/lib/stores/backgroundGenerations.svelte.ts +32 -32
  304. package/src/ruvocal/src/lib/stores/backgroundGenerations.ts +1 -1
  305. package/src/ruvocal/src/lib/stores/errors.ts +9 -9
  306. package/src/ruvocal/src/lib/stores/isAborted.ts +3 -3
  307. package/src/ruvocal/src/lib/stores/isPro.ts +4 -4
  308. package/src/ruvocal/src/lib/stores/loading.ts +3 -3
  309. package/src/ruvocal/src/lib/stores/mcpServers.ts +534 -534
  310. package/src/ruvocal/src/lib/stores/pendingChatInput.ts +3 -3
  311. package/src/ruvocal/src/lib/stores/pendingMessage.ts +9 -9
  312. package/src/ruvocal/src/lib/stores/settings.ts +182 -182
  313. package/src/ruvocal/src/lib/stores/shareModal.ts +13 -13
  314. package/src/ruvocal/src/lib/stores/titleUpdate.ts +8 -8
  315. package/src/ruvocal/src/lib/stores/wasmMcp.ts +472 -472
  316. package/src/ruvocal/src/lib/switchTheme.ts +124 -124
  317. package/src/ruvocal/src/lib/types/AbortedGeneration.ts +8 -8
  318. package/src/ruvocal/src/lib/types/Assistant.ts +31 -31
  319. package/src/ruvocal/src/lib/types/AssistantStats.ts +11 -11
  320. package/src/ruvocal/src/lib/types/ConfigKey.ts +4 -4
  321. package/src/ruvocal/src/lib/types/ConvSidebar.ts +9 -9
  322. package/src/ruvocal/src/lib/types/Conversation.ts +27 -27
  323. package/src/ruvocal/src/lib/types/ConversationStats.ts +13 -13
  324. package/src/ruvocal/src/lib/types/Message.ts +41 -41
  325. package/src/ruvocal/src/lib/types/MessageEvent.ts +10 -10
  326. package/src/ruvocal/src/lib/types/MessageUpdate.ts +139 -139
  327. package/src/ruvocal/src/lib/types/MigrationResult.ts +7 -7
  328. package/src/ruvocal/src/lib/types/Model.ts +23 -23
  329. package/src/ruvocal/src/lib/types/Report.ts +12 -12
  330. package/src/ruvocal/src/lib/types/Review.ts +6 -6
  331. package/src/ruvocal/src/lib/types/Semaphore.ts +19 -19
  332. package/src/ruvocal/src/lib/types/Session.ts +22 -22
  333. package/src/ruvocal/src/lib/types/Settings.ts +93 -93
  334. package/src/ruvocal/src/lib/types/SharedConversation.ts +9 -9
  335. package/src/ruvocal/src/lib/types/Template.ts +6 -6
  336. package/src/ruvocal/src/lib/types/Timestamps.ts +4 -4
  337. package/src/ruvocal/src/lib/types/TokenCache.ts +6 -6
  338. package/src/ruvocal/src/lib/types/Tool.ts +77 -77
  339. package/src/ruvocal/src/lib/types/UrlDependency.ts +5 -5
  340. package/src/ruvocal/src/lib/types/User.ts +14 -14
  341. package/src/ruvocal/src/lib/utils/PublicConfig.svelte.ts +75 -75
  342. package/src/ruvocal/src/lib/utils/auth.ts +17 -17
  343. package/src/ruvocal/src/lib/utils/chunk.ts +33 -33
  344. package/src/ruvocal/src/lib/utils/cookiesAreEnabled.ts +13 -13
  345. package/src/ruvocal/src/lib/utils/debounce.ts +17 -17
  346. package/src/ruvocal/src/lib/utils/deepestChild.ts +6 -6
  347. package/src/ruvocal/src/lib/utils/favicon.ts +21 -21
  348. package/src/ruvocal/src/lib/utils/fetchJSON.ts +23 -23
  349. package/src/ruvocal/src/lib/utils/file2base64.ts +14 -14
  350. package/src/ruvocal/src/lib/utils/formatUserCount.ts +37 -37
  351. package/src/ruvocal/src/lib/utils/generationState.spec.ts +75 -75
  352. package/src/ruvocal/src/lib/utils/generationState.ts +26 -26
  353. package/src/ruvocal/src/lib/utils/getHref.ts +41 -41
  354. package/src/ruvocal/src/lib/utils/getReturnFromGenerator.ts +7 -7
  355. package/src/ruvocal/src/lib/utils/haptics.ts +64 -64
  356. package/src/ruvocal/src/lib/utils/hashConv.ts +12 -12
  357. package/src/ruvocal/src/lib/utils/hf.ts +17 -17
  358. package/src/ruvocal/src/lib/utils/isDesktop.ts +7 -7
  359. package/src/ruvocal/src/lib/utils/isUrl.ts +8 -8
  360. package/src/ruvocal/src/lib/utils/isVirtualKeyboard.ts +16 -16
  361. package/src/ruvocal/src/lib/utils/loadAttachmentsFromUrls.ts +115 -115
  362. package/src/ruvocal/src/lib/utils/marked.spec.ts +96 -96
  363. package/src/ruvocal/src/lib/utils/marked.ts +531 -531
  364. package/src/ruvocal/src/lib/utils/mcpValidation.ts +147 -147
  365. package/src/ruvocal/src/lib/utils/mergeAsyncGenerators.ts +38 -38
  366. package/src/ruvocal/src/lib/utils/messageUpdates.spec.ts +262 -262
  367. package/src/ruvocal/src/lib/utils/messageUpdates.ts +324 -324
  368. package/src/ruvocal/src/lib/utils/mime.ts +56 -56
  369. package/src/ruvocal/src/lib/utils/models.ts +14 -14
  370. package/src/ruvocal/src/lib/utils/parseBlocks.ts +120 -120
  371. package/src/ruvocal/src/lib/utils/parseIncompleteMarkdown.ts +644 -644
  372. package/src/ruvocal/src/lib/utils/parseStringToList.ts +10 -10
  373. package/src/ruvocal/src/lib/utils/randomUuid.ts +14 -14
  374. package/src/ruvocal/src/lib/utils/searchTokens.ts +33 -33
  375. package/src/ruvocal/src/lib/utils/sha256.ts +7 -7
  376. package/src/ruvocal/src/lib/utils/stringifyError.ts +12 -12
  377. package/src/ruvocal/src/lib/utils/sum.ts +3 -3
  378. package/src/ruvocal/src/lib/utils/template.spec.ts +59 -59
  379. package/src/ruvocal/src/lib/utils/template.ts +53 -53
  380. package/src/ruvocal/src/lib/utils/timeout.ts +9 -9
  381. package/src/ruvocal/src/lib/utils/toolProgress.spec.ts +46 -46
  382. package/src/ruvocal/src/lib/utils/toolProgress.ts +11 -11
  383. package/src/ruvocal/src/lib/utils/tree/addChildren.spec.ts +102 -102
  384. package/src/ruvocal/src/lib/utils/tree/addChildren.ts +48 -48
  385. package/src/ruvocal/src/lib/utils/tree/addSibling.spec.ts +81 -81
  386. package/src/ruvocal/src/lib/utils/tree/addSibling.ts +41 -41
  387. package/src/ruvocal/src/lib/utils/tree/buildSubtree.spec.ts +110 -110
  388. package/src/ruvocal/src/lib/utils/tree/buildSubtree.ts +24 -24
  389. package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.spec.ts +31 -31
  390. package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.ts +36 -36
  391. package/src/ruvocal/src/lib/utils/tree/isMessageId.spec.ts +15 -15
  392. package/src/ruvocal/src/lib/utils/tree/isMessageId.ts +5 -5
  393. package/src/ruvocal/src/lib/utils/tree/tree.d.ts +14 -14
  394. package/src/ruvocal/src/lib/utils/tree/treeHelpers.spec.ts +167 -167
  395. package/src/ruvocal/src/lib/utils/updates.ts +39 -39
  396. package/src/ruvocal/src/lib/utils/urlParams.ts +13 -13
  397. package/src/ruvocal/src/lib/wasm/idb.ts +438 -438
  398. package/src/ruvocal/src/lib/wasm/index.ts +1213 -1213
  399. package/src/ruvocal/src/lib/wasm/tests/wasm-capabilities.test.ts +565 -565
  400. package/src/ruvocal/src/lib/wasm/wasm.worker.ts +332 -332
  401. package/src/ruvocal/src/lib/wasm/workerClient.ts +166 -166
  402. package/src/ruvocal/src/lib/workers/autopilotWorker.ts +221 -221
  403. package/src/ruvocal/src/lib/workers/detailFetchWorker.ts +100 -100
  404. package/src/ruvocal/src/lib/workers/markdownWorker.ts +61 -61
  405. package/src/ruvocal/src/routes/+error.svelte +20 -20
  406. package/src/ruvocal/src/routes/+layout.svelte +324 -324
  407. package/src/ruvocal/src/routes/+layout.ts +91 -91
  408. package/src/ruvocal/src/routes/+page.svelte +168 -168
  409. package/src/ruvocal/src/routes/.well-known/oauth-cimd/+server.ts +37 -37
  410. package/src/ruvocal/src/routes/__debug/openai/+server.ts +21 -21
  411. package/src/ruvocal/src/routes/admin/export/+server.ts +159 -159
  412. package/src/ruvocal/src/routes/admin/stats/compute/+server.ts +16 -16
  413. package/src/ruvocal/src/routes/api/conversation/[id]/+server.ts +40 -40
  414. package/src/ruvocal/src/routes/api/conversation/[id]/message/[messageId]/+server.ts +42 -42
  415. package/src/ruvocal/src/routes/api/conversations/+server.ts +48 -48
  416. package/src/ruvocal/src/routes/api/fetch-url/+server.ts +147 -147
  417. package/src/ruvocal/src/routes/api/mcp/health/+server.ts +292 -292
  418. package/src/ruvocal/src/routes/api/mcp/servers/+server.ts +32 -32
  419. package/src/ruvocal/src/routes/api/models/+server.ts +25 -25
  420. package/src/ruvocal/src/routes/api/transcribe/+server.ts +104 -104
  421. package/src/ruvocal/src/routes/api/user/+server.ts +15 -15
  422. package/src/ruvocal/src/routes/api/user/validate-token/+server.ts +20 -20
  423. package/src/ruvocal/src/routes/api/v2/conversations/+server.ts +48 -48
  424. package/src/ruvocal/src/routes/api/v2/conversations/[id]/+server.ts +94 -94
  425. package/src/ruvocal/src/routes/api/v2/conversations/[id]/message/[messageId]/+server.ts +43 -43
  426. package/src/ruvocal/src/routes/api/v2/conversations/import-share/+server.ts +23 -23
  427. package/src/ruvocal/src/routes/api/v2/debug/config/+server.ts +16 -16
  428. package/src/ruvocal/src/routes/api/v2/debug/refresh/+server.ts +30 -30
  429. package/src/ruvocal/src/routes/api/v2/export/+server.ts +196 -196
  430. package/src/ruvocal/src/routes/api/v2/feature-flags/+server.ts +14 -14
  431. package/src/ruvocal/src/routes/api/v2/models/+server.ts +38 -38
  432. package/src/ruvocal/src/routes/api/v2/models/[namespace]/+server.ts +8 -8
  433. package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/+server.ts +8 -8
  434. package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/subscribe/+server.ts +28 -28
  435. package/src/ruvocal/src/routes/api/v2/models/[namespace]/subscribe/+server.ts +28 -28
  436. package/src/ruvocal/src/routes/api/v2/models/old/+server.ts +7 -7
  437. package/src/ruvocal/src/routes/api/v2/models/refresh/+server.ts +33 -33
  438. package/src/ruvocal/src/routes/api/v2/public-config/+server.ts +7 -7
  439. package/src/ruvocal/src/routes/api/v2/user/+server.ts +17 -17
  440. package/src/ruvocal/src/routes/api/v2/user/billing-orgs/+server.ts +73 -73
  441. package/src/ruvocal/src/routes/api/v2/user/reports/+server.ts +17 -17
  442. package/src/ruvocal/src/routes/api/v2/user/settings/+server.ts +110 -110
  443. package/src/ruvocal/src/routes/conversation/+server.ts +115 -115
  444. package/src/ruvocal/src/routes/conversation/[id]/+page.svelte +586 -586
  445. package/src/ruvocal/src/routes/conversation/[id]/+page.ts +60 -60
  446. package/src/ruvocal/src/routes/conversation/[id]/+server.ts +740 -740
  447. package/src/ruvocal/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts +66 -66
  448. package/src/ruvocal/src/routes/conversation/[id]/share/+server.ts +69 -69
  449. package/src/ruvocal/src/routes/conversation/[id]/stop-generating/+server.ts +35 -35
  450. package/src/ruvocal/src/routes/healthcheck/+server.ts +3 -3
  451. package/src/ruvocal/src/routes/login/+server.ts +5 -5
  452. package/src/ruvocal/src/routes/login/callback/+server.ts +103 -103
  453. package/src/ruvocal/src/routes/login/callback/updateUser.spec.ts +157 -157
  454. package/src/ruvocal/src/routes/login/callback/updateUser.ts +215 -215
  455. package/src/ruvocal/src/routes/logout/+server.ts +18 -18
  456. package/src/ruvocal/src/routes/metrics/+server.ts +18 -18
  457. package/src/ruvocal/src/routes/models/+page.svelte +233 -233
  458. package/src/ruvocal/src/routes/models/[...model]/+page.svelte +161 -161
  459. package/src/ruvocal/src/routes/models/[...model]/+page.ts +14 -14
  460. package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/+server.ts +64 -64
  461. package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/ModelThumbnail.svelte +28 -28
  462. package/src/ruvocal/src/routes/privacy/+page.svelte +11 -11
  463. package/src/ruvocal/src/routes/r/[id]/+page.ts +34 -34
  464. package/src/ruvocal/src/routes/settings/(nav)/+layout.svelte +282 -282
  465. package/src/ruvocal/src/routes/settings/(nav)/+layout.ts +1 -1
  466. package/src/ruvocal/src/routes/settings/(nav)/+server.ts +59 -59
  467. package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.svelte +464 -464
  468. package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.ts +14 -14
  469. package/src/ruvocal/src/routes/settings/(nav)/application/+page.svelte +362 -362
  470. package/src/ruvocal/src/routes/settings/+layout.svelte +40 -40
  471. package/src/ruvocal/src/styles/highlight-js.css +195 -195
  472. package/src/ruvocal/src/styles/main.css +144 -144
  473. package/src/ruvocal/static/chatui/favicon-dark.svg +3 -3
  474. package/src/ruvocal/static/chatui/favicon-dev.svg +3 -3
  475. package/src/ruvocal/static/chatui/favicon.svg +3 -3
  476. package/src/ruvocal/static/chatui/icon.svg +3 -3
  477. package/src/ruvocal/static/chatui/logo.svg +7 -7
  478. package/src/ruvocal/static/chatui/manifest.json +54 -54
  479. package/src/ruvocal/static/chatui/welcome.js +184 -184
  480. package/src/ruvocal/static/huggingchat/favicon-dark.svg +4 -4
  481. package/src/ruvocal/static/huggingchat/favicon-dev.svg +4 -4
  482. package/src/ruvocal/static/huggingchat/favicon.svg +4 -4
  483. package/src/ruvocal/static/huggingchat/fulltext-logo.svg +1 -1
  484. package/src/ruvocal/static/huggingchat/icon.svg +4 -4
  485. package/src/ruvocal/static/huggingchat/logo.svg +4 -4
  486. package/src/ruvocal/static/huggingchat/manifest.json +54 -54
  487. package/src/ruvocal/static/huggingchat/routes.chat.json +226 -226
  488. package/src/ruvocal/static/robots.txt +10 -10
  489. package/src/ruvocal/static/wasm/rvagent_wasm.js +1539 -1539
  490. package/src/ruvocal/stub/@reflink/reflink/package.json +5 -5
  491. package/src/ruvocal/svelte.config.js +53 -53
  492. package/src/ruvocal/tailwind.config.cjs +30 -30
  493. package/src/ruvocal/tsconfig.json +19 -19
  494. package/src/ruvocal/vite.config.ts +87 -87
  495. package/src/scripts/deploy.sh +116 -116
  496. package/src/scripts/generate-config.js +245 -245
  497. package/src/scripts/generate-welcome.js +187 -187
  498. package/src/scripts/package-rvf.sh +116 -116
@@ -1,212 +1,212 @@
1
- import type { TextGenerationStreamOutput } from "@huggingface/inference";
2
- import type OpenAI from "openai";
3
- import type { Stream } from "openai/streaming";
4
-
5
- /**
6
- * Transform a stream of OpenAI.Chat.ChatCompletion into a stream of TextGenerationStreamOutput
7
- */
8
- export async function* openAIChatToTextGenerationStream(
9
- completionStream: Stream<OpenAI.Chat.Completions.ChatCompletionChunk>,
10
- getRouterMetadata?: () => { route?: string; model?: string; provider?: string }
11
- ) {
12
- let generatedText = "";
13
- let tokenId = 0;
14
- let toolBuffer = ""; // legacy hack kept harmless
15
- let metadataYielded = false;
16
- let thinkOpen = false;
17
-
18
- for await (const completion of completionStream) {
19
- const retyped = completion as {
20
- "x-router-metadata"?: { route: string; model: string; provider?: string };
21
- };
22
- // Check if this chunk contains router metadata (first chunk from llm-router)
23
- if (!metadataYielded && retyped["x-router-metadata"]) {
24
- const metadata = retyped["x-router-metadata"];
25
- yield {
26
- token: {
27
- id: tokenId++,
28
- text: "",
29
- logprob: 0,
30
- special: true,
31
- },
32
- generated_text: null,
33
- details: null,
34
- routerMetadata: {
35
- route: metadata.route,
36
- model: metadata.model,
37
- provider: metadata.provider,
38
- },
39
- } as TextGenerationStreamOutput & {
40
- routerMetadata: { route: string; model: string; provider?: string };
41
- };
42
- metadataYielded = true;
43
- // Skip processing this chunk as content since it's just metadata
44
- if (
45
- !completion.choices ||
46
- completion.choices.length === 0 ||
47
- !completion.choices[0].delta?.content
48
- ) {
49
- continue;
50
- }
51
- }
52
- const { choices } = completion;
53
- const delta: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta & {
54
- reasoning?: string;
55
- reasoning_content?: string;
56
- } = choices?.[0]?.delta ?? {};
57
- const content: string = delta.content ?? "";
58
- const reasoning: string =
59
- typeof delta?.reasoning === "string"
60
- ? (delta.reasoning as string)
61
- : typeof delta?.reasoning_content === "string"
62
- ? (delta.reasoning_content as string)
63
- : "";
64
- const last = choices?.[0]?.finish_reason === "stop" || choices?.[0]?.finish_reason === "length";
65
-
66
- // if the last token is a stop and the tool buffer is not empty, yield it as a generated_text
67
- if (choices?.[0]?.finish_reason === "stop" && toolBuffer.length > 0) {
68
- yield {
69
- token: {
70
- id: tokenId++,
71
- special: true,
72
- logprob: 0,
73
- text: "",
74
- },
75
- generated_text: toolBuffer,
76
- details: null,
77
- } as TextGenerationStreamOutput;
78
- break;
79
- }
80
-
81
- // weird bug where the parameters are streamed in like this
82
- if (choices?.[0]?.delta?.tool_calls) {
83
- const calls = Array.isArray(choices[0].delta.tool_calls)
84
- ? choices[0].delta.tool_calls
85
- : [choices[0].delta.tool_calls];
86
-
87
- if (
88
- calls.length === 1 &&
89
- calls[0].index === 0 &&
90
- calls[0].id === "" &&
91
- calls[0].type === "function" &&
92
- !!calls[0].function &&
93
- calls[0].function.name === null
94
- ) {
95
- toolBuffer += calls[0].function.arguments;
96
- continue;
97
- }
98
- }
99
-
100
- let combined = "";
101
- if (reasoning && reasoning.length > 0) {
102
- if (!thinkOpen) {
103
- combined += "<think>" + reasoning;
104
- thinkOpen = true;
105
- } else {
106
- combined += reasoning;
107
- }
108
- }
109
-
110
- if (content && content.length > 0) {
111
- const trimmed = content.trim();
112
- // Allow <think> tags in content to pass through (for models like DeepSeek R1)
113
- if (thinkOpen && trimmed === "</think>") {
114
- // close once without duplicating the tag
115
- combined += "</think>";
116
- thinkOpen = false;
117
- } else if (thinkOpen) {
118
- combined += "</think>" + content;
119
- thinkOpen = false;
120
- } else {
121
- combined += content;
122
- }
123
- }
124
-
125
- // Accumulate the combined token into the full text
126
- generatedText += combined;
127
- const output: TextGenerationStreamOutput = {
128
- token: {
129
- id: tokenId++,
130
- text: combined,
131
- logprob: 0,
132
- special: last,
133
- },
134
- generated_text: last ? generatedText : null,
135
- details: null,
136
- };
137
- yield output;
138
-
139
- // Tools removed: ignore tool_calls deltas
140
- }
141
-
142
- // If metadata wasn't yielded from chunks (e.g., from headers), yield it at the end
143
- if (!metadataYielded && getRouterMetadata) {
144
- const routerMetadata = getRouterMetadata();
145
- // Yield if we have either complete router metadata OR just provider info
146
- if (
147
- (routerMetadata && routerMetadata.route && routerMetadata.model) ||
148
- routerMetadata?.provider
149
- ) {
150
- yield {
151
- token: {
152
- id: tokenId++,
153
- text: "",
154
- logprob: 0,
155
- special: true,
156
- },
157
- generated_text: null,
158
- details: null,
159
- routerMetadata,
160
- } as TextGenerationStreamOutput & {
161
- routerMetadata: { route?: string; model?: string; provider?: string };
162
- };
163
- }
164
- }
165
- }
166
-
167
- /**
168
- * Transform a non-streaming OpenAI chat completion into a stream of TextGenerationStreamOutput
169
- */
170
- export async function* openAIChatToTextGenerationSingle(
171
- completion: OpenAI.Chat.Completions.ChatCompletion,
172
- getRouterMetadata?: () => { route?: string; model?: string; provider?: string }
173
- ) {
174
- const message: NonNullable<OpenAI.Chat.Completions.ChatCompletion.Choice>["message"] & {
175
- reasoning?: string;
176
- reasoning_content?: string;
177
- } = completion.choices?.[0]?.message ?? {};
178
- let content: string = message?.content || "";
179
- // Provider-dependent reasoning shapes (non-streaming)
180
- const r: string =
181
- typeof message?.reasoning === "string"
182
- ? (message.reasoning as string)
183
- : typeof message?.reasoning_content === "string"
184
- ? (message.reasoning_content as string)
185
- : "";
186
- if (r && r.length > 0) {
187
- content = `<think>${r}</think>` + content;
188
- }
189
- const tokenId = 0;
190
-
191
- // Yield the content as a single token
192
- yield {
193
- token: {
194
- id: tokenId,
195
- text: content,
196
- logprob: 0,
197
- special: false,
198
- },
199
- generated_text: content,
200
- details: null,
201
- ...(getRouterMetadata
202
- ? (() => {
203
- const metadata = getRouterMetadata();
204
- return (metadata && metadata.route && metadata.model) || metadata?.provider
205
- ? { routerMetadata: metadata }
206
- : {};
207
- })()
208
- : {}),
209
- } as TextGenerationStreamOutput & {
210
- routerMetadata?: { route?: string; model?: string; provider?: string };
211
- };
212
- }
1
+ import type { TextGenerationStreamOutput } from "@huggingface/inference";
2
+ import type OpenAI from "openai";
3
+ import type { Stream } from "openai/streaming";
4
+
5
+ /**
6
+ * Transform a stream of OpenAI.Chat.ChatCompletion into a stream of TextGenerationStreamOutput
7
+ */
8
+ export async function* openAIChatToTextGenerationStream(
9
+ completionStream: Stream<OpenAI.Chat.Completions.ChatCompletionChunk>,
10
+ getRouterMetadata?: () => { route?: string; model?: string; provider?: string }
11
+ ) {
12
+ let generatedText = "";
13
+ let tokenId = 0;
14
+ let toolBuffer = ""; // legacy hack kept harmless
15
+ let metadataYielded = false;
16
+ let thinkOpen = false;
17
+
18
+ for await (const completion of completionStream) {
19
+ const retyped = completion as {
20
+ "x-router-metadata"?: { route: string; model: string; provider?: string };
21
+ };
22
+ // Check if this chunk contains router metadata (first chunk from llm-router)
23
+ if (!metadataYielded && retyped["x-router-metadata"]) {
24
+ const metadata = retyped["x-router-metadata"];
25
+ yield {
26
+ token: {
27
+ id: tokenId++,
28
+ text: "",
29
+ logprob: 0,
30
+ special: true,
31
+ },
32
+ generated_text: null,
33
+ details: null,
34
+ routerMetadata: {
35
+ route: metadata.route,
36
+ model: metadata.model,
37
+ provider: metadata.provider,
38
+ },
39
+ } as TextGenerationStreamOutput & {
40
+ routerMetadata: { route: string; model: string; provider?: string };
41
+ };
42
+ metadataYielded = true;
43
+ // Skip processing this chunk as content since it's just metadata
44
+ if (
45
+ !completion.choices ||
46
+ completion.choices.length === 0 ||
47
+ !completion.choices[0].delta?.content
48
+ ) {
49
+ continue;
50
+ }
51
+ }
52
+ const { choices } = completion;
53
+ const delta: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta & {
54
+ reasoning?: string;
55
+ reasoning_content?: string;
56
+ } = choices?.[0]?.delta ?? {};
57
+ const content: string = delta.content ?? "";
58
+ const reasoning: string =
59
+ typeof delta?.reasoning === "string"
60
+ ? (delta.reasoning as string)
61
+ : typeof delta?.reasoning_content === "string"
62
+ ? (delta.reasoning_content as string)
63
+ : "";
64
+ const last = choices?.[0]?.finish_reason === "stop" || choices?.[0]?.finish_reason === "length";
65
+
66
+ // if the last token is a stop and the tool buffer is not empty, yield it as a generated_text
67
+ if (choices?.[0]?.finish_reason === "stop" && toolBuffer.length > 0) {
68
+ yield {
69
+ token: {
70
+ id: tokenId++,
71
+ special: true,
72
+ logprob: 0,
73
+ text: "",
74
+ },
75
+ generated_text: toolBuffer,
76
+ details: null,
77
+ } as TextGenerationStreamOutput;
78
+ break;
79
+ }
80
+
81
+ // weird bug where the parameters are streamed in like this
82
+ if (choices?.[0]?.delta?.tool_calls) {
83
+ const calls = Array.isArray(choices[0].delta.tool_calls)
84
+ ? choices[0].delta.tool_calls
85
+ : [choices[0].delta.tool_calls];
86
+
87
+ if (
88
+ calls.length === 1 &&
89
+ calls[0].index === 0 &&
90
+ calls[0].id === "" &&
91
+ calls[0].type === "function" &&
92
+ !!calls[0].function &&
93
+ calls[0].function.name === null
94
+ ) {
95
+ toolBuffer += calls[0].function.arguments;
96
+ continue;
97
+ }
98
+ }
99
+
100
+ let combined = "";
101
+ if (reasoning && reasoning.length > 0) {
102
+ if (!thinkOpen) {
103
+ combined += "<think>" + reasoning;
104
+ thinkOpen = true;
105
+ } else {
106
+ combined += reasoning;
107
+ }
108
+ }
109
+
110
+ if (content && content.length > 0) {
111
+ const trimmed = content.trim();
112
+ // Allow <think> tags in content to pass through (for models like DeepSeek R1)
113
+ if (thinkOpen && trimmed === "</think>") {
114
+ // close once without duplicating the tag
115
+ combined += "</think>";
116
+ thinkOpen = false;
117
+ } else if (thinkOpen) {
118
+ combined += "</think>" + content;
119
+ thinkOpen = false;
120
+ } else {
121
+ combined += content;
122
+ }
123
+ }
124
+
125
+ // Accumulate the combined token into the full text
126
+ generatedText += combined;
127
+ const output: TextGenerationStreamOutput = {
128
+ token: {
129
+ id: tokenId++,
130
+ text: combined,
131
+ logprob: 0,
132
+ special: last,
133
+ },
134
+ generated_text: last ? generatedText : null,
135
+ details: null,
136
+ };
137
+ yield output;
138
+
139
+ // Tools removed: ignore tool_calls deltas
140
+ }
141
+
142
+ // If metadata wasn't yielded from chunks (e.g., from headers), yield it at the end
143
+ if (!metadataYielded && getRouterMetadata) {
144
+ const routerMetadata = getRouterMetadata();
145
+ // Yield if we have either complete router metadata OR just provider info
146
+ if (
147
+ (routerMetadata && routerMetadata.route && routerMetadata.model) ||
148
+ routerMetadata?.provider
149
+ ) {
150
+ yield {
151
+ token: {
152
+ id: tokenId++,
153
+ text: "",
154
+ logprob: 0,
155
+ special: true,
156
+ },
157
+ generated_text: null,
158
+ details: null,
159
+ routerMetadata,
160
+ } as TextGenerationStreamOutput & {
161
+ routerMetadata: { route?: string; model?: string; provider?: string };
162
+ };
163
+ }
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Transform a non-streaming OpenAI chat completion into a stream of TextGenerationStreamOutput
169
+ */
170
+ export async function* openAIChatToTextGenerationSingle(
171
+ completion: OpenAI.Chat.Completions.ChatCompletion,
172
+ getRouterMetadata?: () => { route?: string; model?: string; provider?: string }
173
+ ) {
174
+ const message: NonNullable<OpenAI.Chat.Completions.ChatCompletion.Choice>["message"] & {
175
+ reasoning?: string;
176
+ reasoning_content?: string;
177
+ } = completion.choices?.[0]?.message ?? {};
178
+ let content: string = message?.content || "";
179
+ // Provider-dependent reasoning shapes (non-streaming)
180
+ const r: string =
181
+ typeof message?.reasoning === "string"
182
+ ? (message.reasoning as string)
183
+ : typeof message?.reasoning_content === "string"
184
+ ? (message.reasoning_content as string)
185
+ : "";
186
+ if (r && r.length > 0) {
187
+ content = `<think>${r}</think>` + content;
188
+ }
189
+ const tokenId = 0;
190
+
191
+ // Yield the content as a single token
192
+ yield {
193
+ token: {
194
+ id: tokenId,
195
+ text: content,
196
+ logprob: 0,
197
+ special: false,
198
+ },
199
+ generated_text: content,
200
+ details: null,
201
+ ...(getRouterMetadata
202
+ ? (() => {
203
+ const metadata = getRouterMetadata();
204
+ return (metadata && metadata.route && metadata.model) || metadata?.provider
205
+ ? { routerMetadata: metadata }
206
+ : {};
207
+ })()
208
+ : {}),
209
+ } as TextGenerationStreamOutput & {
210
+ routerMetadata?: { route?: string; model?: string; provider?: string };
211
+ };
212
+ }
@@ -1,32 +1,32 @@
1
- import type { TextGenerationStreamOutput } from "@huggingface/inference";
2
- import type OpenAI from "openai";
3
- import type { Stream } from "openai/streaming";
4
-
5
- /**
6
- * Transform a stream of OpenAI.Completions.Completion into a stream of TextGenerationStreamOutput
7
- */
8
- export async function* openAICompletionToTextGenerationStream(
9
- completionStream: Stream<OpenAI.Completions.Completion>
10
- ) {
11
- let generatedText = "";
12
- let tokenId = 0;
13
- for await (const completion of completionStream) {
14
- const { choices } = completion;
15
- const text = choices?.[0]?.text ?? "";
16
- const last = choices?.[0]?.finish_reason === "stop" || choices?.[0]?.finish_reason === "length";
17
- if (text) {
18
- generatedText = generatedText + text;
19
- }
20
- const output: TextGenerationStreamOutput = {
21
- token: {
22
- id: tokenId++,
23
- text,
24
- logprob: 0,
25
- special: last,
26
- },
27
- generated_text: last ? generatedText : null,
28
- details: null,
29
- };
30
- yield output;
31
- }
32
- }
1
+ import type { TextGenerationStreamOutput } from "@huggingface/inference";
2
+ import type OpenAI from "openai";
3
+ import type { Stream } from "openai/streaming";
4
+
5
+ /**
6
+ * Transform a stream of OpenAI.Completions.Completion into a stream of TextGenerationStreamOutput
7
+ */
8
+ export async function* openAICompletionToTextGenerationStream(
9
+ completionStream: Stream<OpenAI.Completions.Completion>
10
+ ) {
11
+ let generatedText = "";
12
+ let tokenId = 0;
13
+ for await (const completion of completionStream) {
14
+ const { choices } = completion;
15
+ const text = choices?.[0]?.text ?? "";
16
+ const last = choices?.[0]?.finish_reason === "stop" || choices?.[0]?.finish_reason === "length";
17
+ if (text) {
18
+ generatedText = generatedText + text;
19
+ }
20
+ const output: TextGenerationStreamOutput = {
21
+ token: {
22
+ id: tokenId++,
23
+ text,
24
+ logprob: 0,
25
+ special: last,
26
+ },
27
+ generated_text: last ? generatedText : null,
28
+ details: null,
29
+ };
30
+ yield output;
31
+ }
32
+ }
@@ -1,61 +1,61 @@
1
- import type { Message } from "$lib/types/Message";
2
- import type { EndpointMessage } from "./endpoints";
3
- import { downloadFile } from "../files/downloadFile";
4
- import type { ObjectId } from "mongodb";
5
-
6
- export async function preprocessMessages(
7
- messages: Message[],
8
- convId: ObjectId
9
- ): Promise<EndpointMessage[]> {
10
- return Promise.resolve(messages)
11
- .then((msgs) => downloadFiles(msgs, convId))
12
- .then((msgs) => injectClipboardFiles(msgs))
13
- .then(stripEmptyInitialSystemMessage);
14
- }
15
-
16
- async function downloadFiles(messages: Message[], convId: ObjectId): Promise<EndpointMessage[]> {
17
- return Promise.all(
18
- messages.map<Promise<EndpointMessage>>((message) =>
19
- Promise.all((message.files ?? []).map((file) => downloadFile(file.value, convId))).then(
20
- (files) => ({ ...message, files })
21
- )
22
- )
23
- );
24
- }
25
-
26
- async function injectClipboardFiles(messages: EndpointMessage[]) {
27
- return Promise.all(
28
- messages.map((message) => {
29
- const plaintextFiles = message.files
30
- ?.filter((file) => file.mime === "application/vnd.chatui.clipboard")
31
- .map((file) => Buffer.from(file.value, "base64").toString("utf-8"));
32
-
33
- if (!plaintextFiles || plaintextFiles.length === 0) return message;
34
-
35
- return {
36
- ...message,
37
- content: `${plaintextFiles.join("\n\n")}\n\n${message.content}`,
38
- files: message.files?.filter((file) => file.mime !== "application/vnd.chatui.clipboard"),
39
- };
40
- })
41
- );
42
- }
43
-
44
- /**
45
- * Remove an initial system message if its content is empty/whitespace only.
46
- * This prevents sending an empty system prompt to any provider.
47
- */
48
- function stripEmptyInitialSystemMessage(messages: EndpointMessage[]): EndpointMessage[] {
49
- if (!messages?.length) return messages;
50
- const first = messages[0];
51
- if (first?.from !== "system") return messages;
52
-
53
- const content = first?.content as unknown;
54
- const isEmpty = typeof content === "string" ? content.trim().length === 0 : false;
55
-
56
- if (isEmpty) {
57
- return messages.slice(1);
58
- }
59
-
60
- return messages;
61
- }
1
+ import type { Message } from "$lib/types/Message";
2
+ import type { EndpointMessage } from "./endpoints";
3
+ import { downloadFile } from "../files/downloadFile";
4
+ import type { ObjectId } from "mongodb";
5
+
6
+ export async function preprocessMessages(
7
+ messages: Message[],
8
+ convId: ObjectId
9
+ ): Promise<EndpointMessage[]> {
10
+ return Promise.resolve(messages)
11
+ .then((msgs) => downloadFiles(msgs, convId))
12
+ .then((msgs) => injectClipboardFiles(msgs))
13
+ .then(stripEmptyInitialSystemMessage);
14
+ }
15
+
16
+ async function downloadFiles(messages: Message[], convId: ObjectId): Promise<EndpointMessage[]> {
17
+ return Promise.all(
18
+ messages.map<Promise<EndpointMessage>>((message) =>
19
+ Promise.all((message.files ?? []).map((file) => downloadFile(file.value, convId))).then(
20
+ (files) => ({ ...message, files })
21
+ )
22
+ )
23
+ );
24
+ }
25
+
26
+ async function injectClipboardFiles(messages: EndpointMessage[]) {
27
+ return Promise.all(
28
+ messages.map((message) => {
29
+ const plaintextFiles = message.files
30
+ ?.filter((file) => file.mime === "application/vnd.chatui.clipboard")
31
+ .map((file) => Buffer.from(file.value, "base64").toString("utf-8"));
32
+
33
+ if (!plaintextFiles || plaintextFiles.length === 0) return message;
34
+
35
+ return {
36
+ ...message,
37
+ content: `${plaintextFiles.join("\n\n")}\n\n${message.content}`,
38
+ files: message.files?.filter((file) => file.mime !== "application/vnd.chatui.clipboard"),
39
+ };
40
+ })
41
+ );
42
+ }
43
+
44
+ /**
45
+ * Remove an initial system message if its content is empty/whitespace only.
46
+ * This prevents sending an empty system prompt to any provider.
47
+ */
48
+ function stripEmptyInitialSystemMessage(messages: EndpointMessage[]): EndpointMessage[] {
49
+ if (!messages?.length) return messages;
50
+ const first = messages[0];
51
+ if (first?.from !== "system") return messages;
52
+
53
+ const content = first?.content as unknown;
54
+ const isEmpty = typeof content === "string" ? content.trim().length === 0 : false;
55
+
56
+ if (isEmpty) {
57
+ return messages.slice(1);
58
+ }
59
+
60
+ return messages;
61
+ }