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.
- package/dist/rvf.manifest.json +295 -0
- package/package.json +16 -2
- package/src/chat-ui/Dockerfile +25 -0
- package/src/chat-ui/patch-mcp-url-safety.sh +28 -0
- package/src/chat-ui/static/chatui/icon-144x144.png +0 -0
- package/src/chat-ui/static/chatui/omni-welcome.gif +0 -0
- package/src/config/config.example.json +76 -0
- package/src/mcp-bridge/Dockerfile +45 -0
- package/src/mcp-bridge/index.js +1668 -0
- package/src/mcp-bridge/mcp-stdio-kernel.js +159 -0
- package/src/mcp-bridge/package.json +17 -0
- package/src/mcp-bridge/test-harness.js +470 -0
- package/src/nginx/Dockerfile +10 -0
- package/src/nginx/nginx.conf +67 -0
- package/src/nginx/static/favicon-dark.svg +4 -0
- package/src/nginx/static/favicon.svg +4 -0
- package/src/nginx/static/icon.svg +5 -0
- package/src/nginx/static/logo.svg +9 -0
- package/src/nginx/static/manifest.json +22 -0
- package/src/nginx/static/welcome.js +184 -0
- package/src/ruvocal/.claude/skills/add-model-descriptions/SKILL.md +73 -0
- package/src/ruvocal/.devcontainer/Dockerfile +9 -0
- package/src/ruvocal/.devcontainer/devcontainer.json +36 -0
- package/src/ruvocal/.dockerignore +13 -0
- package/src/ruvocal/.env +194 -0
- package/src/ruvocal/.env.ci +1 -0
- package/src/ruvocal/.eslintignore +13 -0
- package/src/ruvocal/.eslintrc.cjs +45 -0
- package/src/ruvocal/.github/ISSUE_TEMPLATE/bug-report--chat-ui-.md +43 -0
- package/src/ruvocal/.github/ISSUE_TEMPLATE/config-support.md +9 -0
- package/src/ruvocal/.github/ISSUE_TEMPLATE/feature-request--chat-ui-.md +17 -0
- package/src/ruvocal/.github/ISSUE_TEMPLATE/huggingchat.md +11 -0
- package/src/ruvocal/.github/release.yml +16 -0
- package/src/ruvocal/.github/workflows/build-docs.yml +18 -0
- package/src/ruvocal/.github/workflows/build-image.yml +142 -0
- package/src/ruvocal/.github/workflows/build-pr-docs.yml +20 -0
- package/src/ruvocal/.github/workflows/deploy-dev.yml +63 -0
- package/src/ruvocal/.github/workflows/deploy-prod.yml +78 -0
- package/src/ruvocal/.github/workflows/lint-and-test.yml +84 -0
- package/src/ruvocal/.github/workflows/slugify.yaml +72 -0
- package/src/ruvocal/.github/workflows/trufflehog.yml +17 -0
- package/src/ruvocal/.github/workflows/upload-pr-documentation.yml +16 -0
- package/src/ruvocal/.husky/lint-stage-config.js +4 -0
- package/src/ruvocal/.husky/pre-commit +2 -0
- package/src/ruvocal/.prettierignore +14 -0
- package/src/ruvocal/.prettierrc +7 -0
- package/src/ruvocal/.vscode/launch.json +11 -0
- package/src/ruvocal/.vscode/settings.json +14 -0
- package/src/ruvocal/CLAUDE.md +126 -0
- package/src/ruvocal/Dockerfile +93 -0
- package/src/ruvocal/LICENSE +203 -0
- package/src/ruvocal/PRIVACY.md +41 -0
- package/src/ruvocal/README.md +190 -0
- package/src/ruvocal/chart/Chart.yaml +5 -0
- package/src/ruvocal/chart/env/dev.yaml +260 -0
- package/src/ruvocal/chart/env/prod.yaml +273 -0
- package/src/ruvocal/chart/templates/_helpers.tpl +22 -0
- package/src/ruvocal/chart/templates/config.yaml +10 -0
- package/src/ruvocal/chart/templates/deployment.yaml +81 -0
- package/src/ruvocal/chart/templates/hpa.yaml +45 -0
- package/src/ruvocal/chart/templates/infisical.yaml +24 -0
- package/src/ruvocal/chart/templates/ingress-internal.yaml +32 -0
- package/src/ruvocal/chart/templates/ingress.yaml +32 -0
- package/src/ruvocal/chart/templates/network-policy.yaml +36 -0
- package/src/ruvocal/chart/templates/service-account.yaml +13 -0
- package/src/ruvocal/chart/templates/service-monitor.yaml +17 -0
- package/src/ruvocal/chart/templates/service.yaml +21 -0
- package/src/ruvocal/chart/values.yaml +73 -0
- package/src/ruvocal/docker-compose.yml +21 -0
- package/src/ruvocal/docs/adr/ADR-029-HUGGINGFACE-CHAT-UI-CLOUD-RUN.md +1236 -0
- package/src/ruvocal/docs/adr/ADR-033-RUVECTOR-RUFLO-MCP-INTEGRATION.md +111 -0
- package/src/ruvocal/docs/adr/ADR-034-OPTIONAL-MCP-BACKENDS.md +117 -0
- package/src/ruvocal/docs/adr/ADR-035-MCP-TOOL-GROUPS.md +186 -0
- package/src/ruvocal/docs/adr/ADR-037-AUTOPILOT-CHAT-MODE.md +1500 -0
- package/src/ruvocal/docs/adr/ADR-038-RUVOCAL-FORK.md +286 -0
- package/src/ruvocal/docs/source/_toctree.yml +30 -0
- package/src/ruvocal/docs/source/configuration/common-issues.md +38 -0
- package/src/ruvocal/docs/source/configuration/llm-router.md +105 -0
- package/src/ruvocal/docs/source/configuration/mcp-tools.md +84 -0
- package/src/ruvocal/docs/source/configuration/metrics.md +9 -0
- package/src/ruvocal/docs/source/configuration/open-id.md +57 -0
- package/src/ruvocal/docs/source/configuration/overview.md +89 -0
- package/src/ruvocal/docs/source/configuration/theming.md +20 -0
- package/src/ruvocal/docs/source/developing/architecture.md +48 -0
- package/src/ruvocal/docs/source/index.md +53 -0
- package/src/ruvocal/docs/source/installation/docker.md +43 -0
- package/src/ruvocal/docs/source/installation/helm.md +43 -0
- package/src/ruvocal/docs/source/installation/local.md +62 -0
- package/src/ruvocal/entrypoint.sh +19 -0
- package/src/ruvocal/mcp-bridge/.claude-flow/agents/store.json +27 -0
- package/src/ruvocal/mcp-bridge/.claude-flow/daemon-state.json +130 -0
- package/src/ruvocal/mcp-bridge/.claude-flow/daemon.log +0 -0
- package/src/ruvocal/mcp-bridge/.claude-flow/daemon.pid +1 -0
- package/src/ruvocal/mcp-bridge/.claude-flow/tasks/store.json +21 -0
- package/src/ruvocal/mcp-bridge/.swarm/hnsw.index +0 -0
- package/src/ruvocal/mcp-bridge/.swarm/hnsw.metadata.json +1 -0
- package/src/ruvocal/mcp-bridge/.swarm/memory.db +0 -0
- package/src/ruvocal/mcp-bridge/.swarm/model-router-state.json +14 -0
- package/src/ruvocal/mcp-bridge/.swarm/schema.sql +305 -0
- package/src/ruvocal/mcp-bridge/Dockerfile +45 -0
- package/src/ruvocal/mcp-bridge/cloudbuild.yaml +49 -0
- package/src/ruvocal/mcp-bridge/index.js +1864 -0
- package/src/ruvocal/mcp-bridge/mcp-stdio-kernel.js +159 -0
- package/src/ruvocal/mcp-bridge/package-lock.json +762 -0
- package/src/ruvocal/mcp-bridge/package.json +17 -0
- package/src/ruvocal/mcp-bridge/test-harness.js +470 -0
- package/src/ruvocal/models/add-your-models-here.txt +1 -0
- package/src/ruvocal/package-lock.json +11741 -0
- package/src/ruvocal/package.json +121 -0
- package/src/ruvocal/postcss.config.js +6 -0
- package/src/ruvocal/rvf.manifest.json +204 -0
- package/src/ruvocal/scripts/config.ts +64 -0
- package/src/ruvocal/scripts/generate-welcome.mjs +181 -0
- package/src/ruvocal/scripts/populate.ts +288 -0
- package/src/ruvocal/scripts/samples.txt +194 -0
- package/src/ruvocal/scripts/setups/vitest-setup-client.ts +0 -0
- package/src/ruvocal/scripts/setups/vitest-setup-server.ts +44 -0
- package/src/ruvocal/scripts/updateLocalEnv.ts +48 -0
- package/src/ruvocal/src/ambient.d.ts +7 -0
- package/src/ruvocal/src/app.d.ts +29 -0
- package/src/ruvocal/src/app.html +53 -0
- package/src/ruvocal/src/hooks.server.ts +32 -0
- package/src/ruvocal/src/hooks.ts +6 -0
- package/src/ruvocal/src/lib/APIClient.ts +148 -0
- package/src/ruvocal/src/lib/actions/clickOutside.ts +18 -0
- package/src/ruvocal/src/lib/actions/snapScrollToBottom.ts +346 -0
- package/src/ruvocal/src/lib/buildPrompt.ts +33 -0
- package/src/ruvocal/src/lib/components/AnnouncementBanner.svelte +20 -0
- package/src/ruvocal/src/lib/components/BackgroundGenerationPoller.svelte +168 -0
- package/src/ruvocal/src/lib/components/CodeBlock.svelte +73 -0
- package/src/ruvocal/src/lib/components/CopyToClipBoardBtn.svelte +92 -0
- package/src/ruvocal/src/lib/components/DeleteConversationModal.svelte +75 -0
- package/src/ruvocal/src/lib/components/EditConversationModal.svelte +100 -0
- package/src/ruvocal/src/lib/components/ExpandNavigation.svelte +22 -0
- package/src/ruvocal/src/lib/components/HoverTooltip.svelte +44 -0
- package/src/ruvocal/src/lib/components/HtmlPreviewModal.svelte +143 -0
- package/src/ruvocal/src/lib/components/InfiniteScroll.svelte +50 -0
- package/src/ruvocal/src/lib/components/MobileNav.svelte +300 -0
- package/src/ruvocal/src/lib/components/Modal.svelte +115 -0
- package/src/ruvocal/src/lib/components/ModelCardMetadata.svelte +71 -0
- package/src/ruvocal/src/lib/components/NavConversationItem.svelte +151 -0
- package/src/ruvocal/src/lib/components/NavMenu.svelte +295 -0
- package/src/ruvocal/src/lib/components/Pagination.svelte +97 -0
- package/src/ruvocal/src/lib/components/PaginationArrow.svelte +27 -0
- package/src/ruvocal/src/lib/components/Portal.svelte +24 -0
- package/src/ruvocal/src/lib/components/RetryBtn.svelte +18 -0
- package/src/ruvocal/src/lib/components/RuFloUniverse.svelte +185 -0
- package/src/ruvocal/src/lib/components/ScrollToBottomBtn.svelte +47 -0
- package/src/ruvocal/src/lib/components/ScrollToPreviousBtn.svelte +77 -0
- package/src/ruvocal/src/lib/components/ShareConversationModal.svelte +182 -0
- package/src/ruvocal/src/lib/components/StopGeneratingBtn.svelte +69 -0
- package/src/ruvocal/src/lib/components/SubscribeModal.svelte +87 -0
- package/src/ruvocal/src/lib/components/Switch.svelte +36 -0
- package/src/ruvocal/src/lib/components/SystemPromptModal.svelte +44 -0
- package/src/ruvocal/src/lib/components/Toast.svelte +27 -0
- package/src/ruvocal/src/lib/components/Tooltip.svelte +30 -0
- package/src/ruvocal/src/lib/components/WelcomeModal.svelte +46 -0
- package/src/ruvocal/src/lib/components/chat/Alternatives.svelte +77 -0
- package/src/ruvocal/src/lib/components/chat/BlockWrapper.svelte +72 -0
- package/src/ruvocal/src/lib/components/chat/ChatInput.svelte +490 -0
- package/src/ruvocal/src/lib/components/chat/ChatIntroduction.svelte +123 -0
- package/src/ruvocal/src/lib/components/chat/ChatMessage.svelte +548 -0
- package/src/ruvocal/src/lib/components/chat/ChatWindow.svelte +939 -0
- package/src/ruvocal/src/lib/components/chat/FileDropzone.svelte +92 -0
- package/src/ruvocal/src/lib/components/chat/ImageLightbox.svelte +66 -0
- package/src/ruvocal/src/lib/components/chat/MarkdownBlock.svelte +23 -0
- package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte +69 -0
- package/src/ruvocal/src/lib/components/chat/MarkdownRenderer.svelte.test.ts +58 -0
- package/src/ruvocal/src/lib/components/chat/MessageAvatar.svelte +103 -0
- package/src/ruvocal/src/lib/components/chat/ModelSwitch.svelte +64 -0
- package/src/ruvocal/src/lib/components/chat/OpenReasoningResults.svelte +81 -0
- package/src/ruvocal/src/lib/components/chat/TaskGroup.svelte +88 -0
- package/src/ruvocal/src/lib/components/chat/ToolUpdate.svelte +273 -0
- package/src/ruvocal/src/lib/components/chat/UploadedFile.svelte +253 -0
- package/src/ruvocal/src/lib/components/chat/UrlFetchModal.svelte +203 -0
- package/src/ruvocal/src/lib/components/chat/VoiceRecorder.svelte +214 -0
- package/src/ruvocal/src/lib/components/icons/IconBurger.svelte +20 -0
- package/src/ruvocal/src/lib/components/icons/IconCheap.svelte +20 -0
- package/src/ruvocal/src/lib/components/icons/IconChevron.svelte +24 -0
- package/src/ruvocal/src/lib/components/icons/IconDazzled.svelte +40 -0
- package/src/ruvocal/src/lib/components/icons/IconFast.svelte +20 -0
- package/src/ruvocal/src/lib/components/icons/IconLoading.svelte +22 -0
- package/src/ruvocal/src/lib/components/icons/IconMCP.svelte +28 -0
- package/src/ruvocal/src/lib/components/icons/IconMoon.svelte +21 -0
- package/src/ruvocal/src/lib/components/icons/IconNew.svelte +20 -0
- package/src/ruvocal/src/lib/components/icons/IconOmni.svelte +90 -0
- package/src/ruvocal/src/lib/components/icons/IconPaperclip.svelte +24 -0
- package/src/ruvocal/src/lib/components/icons/IconPro.svelte +37 -0
- package/src/ruvocal/src/lib/components/icons/IconShare.svelte +21 -0
- package/src/ruvocal/src/lib/components/icons/IconSun.svelte +93 -0
- package/src/ruvocal/src/lib/components/icons/Logo.svelte +68 -0
- package/src/ruvocal/src/lib/components/icons/LogoHuggingFaceBorderless.svelte +54 -0
- package/src/ruvocal/src/lib/components/mcp/AddServerForm.svelte +250 -0
- package/src/ruvocal/src/lib/components/mcp/MCPServerManager.svelte +185 -0
- package/src/ruvocal/src/lib/components/mcp/ServerCard.svelte +203 -0
- package/src/ruvocal/src/lib/components/players/AudioPlayer.svelte +82 -0
- package/src/ruvocal/src/lib/components/voice/AudioWaveform.svelte +96 -0
- package/src/ruvocal/src/lib/constants/mcpExamples.ts +135 -0
- package/src/ruvocal/src/lib/constants/mime.ts +11 -0
- package/src/ruvocal/src/lib/constants/pagination.ts +1 -0
- package/src/ruvocal/src/lib/constants/publicSepToken.ts +1 -0
- package/src/ruvocal/src/lib/constants/routerExamples.ts +209 -0
- package/src/ruvocal/src/lib/createShareLink.ts +27 -0
- package/src/ruvocal/src/lib/jobs/refresh-conversation-stats.ts +297 -0
- package/src/ruvocal/src/lib/migrations/lock.ts +56 -0
- package/src/ruvocal/src/lib/migrations/migrations.spec.ts +74 -0
- package/src/ruvocal/src/lib/migrations/migrations.ts +109 -0
- package/src/ruvocal/src/lib/migrations/routines/01-update-search-assistants.ts +50 -0
- package/src/ruvocal/src/lib/migrations/routines/02-update-assistants-models.ts +48 -0
- package/src/ruvocal/src/lib/migrations/routines/04-update-message-updates.ts +151 -0
- package/src/ruvocal/src/lib/migrations/routines/05-update-message-files.ts +56 -0
- package/src/ruvocal/src/lib/migrations/routines/06-trim-message-updates.ts +56 -0
- package/src/ruvocal/src/lib/migrations/routines/08-update-featured-to-review.ts +32 -0
- package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.spec.ts +214 -0
- package/src/ruvocal/src/lib/migrations/routines/09-delete-empty-conversations.ts +88 -0
- package/src/ruvocal/src/lib/migrations/routines/10-update-reports-assistantid.ts +29 -0
- package/src/ruvocal/src/lib/migrations/routines/index.ts +15 -0
- package/src/ruvocal/src/lib/server/__tests__/conversation-stop-generating.spec.ts +103 -0
- package/src/ruvocal/src/lib/server/abortRegistry.ts +57 -0
- package/src/ruvocal/src/lib/server/abortedGenerations.ts +43 -0
- package/src/ruvocal/src/lib/server/adminToken.ts +62 -0
- package/src/ruvocal/src/lib/server/api/__tests__/conversations-id.spec.ts +296 -0
- package/src/ruvocal/src/lib/server/api/__tests__/conversations-message.spec.ts +216 -0
- package/src/ruvocal/src/lib/server/api/__tests__/conversations.spec.ts +235 -0
- package/src/ruvocal/src/lib/server/api/__tests__/misc.spec.ts +72 -0
- package/src/ruvocal/src/lib/server/api/__tests__/testHelpers.ts +86 -0
- package/src/ruvocal/src/lib/server/api/__tests__/user-reports.spec.ts +78 -0
- package/src/ruvocal/src/lib/server/api/__tests__/user.spec.ts +239 -0
- package/src/ruvocal/src/lib/server/api/types.ts +37 -0
- package/src/ruvocal/src/lib/server/api/utils/requireAuth.ts +22 -0
- package/src/ruvocal/src/lib/server/api/utils/resolveConversation.ts +69 -0
- package/src/ruvocal/src/lib/server/api/utils/resolveModel.ts +27 -0
- package/src/ruvocal/src/lib/server/api/utils/superjsonResponse.ts +15 -0
- package/src/ruvocal/src/lib/server/apiToken.ts +11 -0
- package/src/ruvocal/src/lib/server/auth.ts +554 -0
- package/src/ruvocal/src/lib/server/config.ts +187 -0
- package/src/ruvocal/src/lib/server/conversation.ts +83 -0
- package/src/ruvocal/src/lib/server/database/__tests__/rvf.spec.ts +709 -0
- package/src/ruvocal/src/lib/server/database/postgres.ts +700 -0
- package/src/ruvocal/src/lib/server/database/rvf.ts +1078 -0
- package/src/ruvocal/src/lib/server/database.ts +145 -0
- package/src/ruvocal/src/lib/server/endpoints/document.ts +68 -0
- package/src/ruvocal/src/lib/server/endpoints/endpoints.ts +43 -0
- package/src/ruvocal/src/lib/server/endpoints/images.ts +211 -0
- package/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts +266 -0
- package/src/ruvocal/src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts +212 -0
- package/src/ruvocal/src/lib/server/endpoints/openai/openAICompletionToTextGenerationStream.ts +32 -0
- package/src/ruvocal/src/lib/server/endpoints/preprocessMessages.ts +61 -0
- package/src/ruvocal/src/lib/server/exitHandler.ts +59 -0
- package/src/ruvocal/src/lib/server/files/downloadFile.ts +34 -0
- package/src/ruvocal/src/lib/server/files/uploadFile.ts +29 -0
- package/src/ruvocal/src/lib/server/findRepoRoot.ts +13 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Black.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Bold.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-ExtraBold.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-ExtraLight.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Light.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Medium.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Regular.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-SemiBold.ttf +0 -0
- package/src/ruvocal/src/lib/server/fonts/Inter-Thin.ttf +0 -0
- package/src/ruvocal/src/lib/server/generateFromDefaultEndpoint.ts +46 -0
- package/src/ruvocal/src/lib/server/hooks/error.ts +37 -0
- package/src/ruvocal/src/lib/server/hooks/fetch.ts +22 -0
- package/src/ruvocal/src/lib/server/hooks/handle.ts +250 -0
- package/src/ruvocal/src/lib/server/hooks/init.ts +51 -0
- package/src/ruvocal/src/lib/server/isURLLocal.spec.ts +31 -0
- package/src/ruvocal/src/lib/server/isURLLocal.ts +74 -0
- package/src/ruvocal/src/lib/server/logger.ts +42 -0
- package/src/ruvocal/src/lib/server/mcp/clientPool.ts +70 -0
- package/src/ruvocal/src/lib/server/mcp/hf.ts +32 -0
- package/src/ruvocal/src/lib/server/mcp/httpClient.ts +122 -0
- package/src/ruvocal/src/lib/server/mcp/registry.ts +76 -0
- package/src/ruvocal/src/lib/server/mcp/tools.ts +196 -0
- package/src/ruvocal/src/lib/server/metrics.ts +255 -0
- package/src/ruvocal/src/lib/server/models.ts +518 -0
- package/src/ruvocal/src/lib/server/requestContext.ts +55 -0
- package/src/ruvocal/src/lib/server/router/arch.ts +230 -0
- package/src/ruvocal/src/lib/server/router/endpoint.ts +316 -0
- package/src/ruvocal/src/lib/server/router/multimodal.ts +28 -0
- package/src/ruvocal/src/lib/server/router/policy.ts +49 -0
- package/src/ruvocal/src/lib/server/router/toolsRoute.ts +51 -0
- package/src/ruvocal/src/lib/server/router/types.ts +21 -0
- package/src/ruvocal/src/lib/server/sendSlack.ts +23 -0
- package/src/ruvocal/src/lib/server/textGeneration/generate.ts +258 -0
- package/src/ruvocal/src/lib/server/textGeneration/index.ts +95 -0
- package/src/ruvocal/src/lib/server/textGeneration/mcp/fileRefs.ts +155 -0
- package/src/ruvocal/src/lib/server/textGeneration/mcp/routerResolution.ts +108 -0
- package/src/ruvocal/src/lib/server/textGeneration/mcp/runMcpFlow.ts +822 -0
- package/src/ruvocal/src/lib/server/textGeneration/mcp/toolInvocation.ts +349 -0
- package/src/ruvocal/src/lib/server/textGeneration/reasoning.ts +23 -0
- package/src/ruvocal/src/lib/server/textGeneration/title.ts +83 -0
- package/src/ruvocal/src/lib/server/textGeneration/types.ts +26 -0
- package/src/ruvocal/src/lib/server/textGeneration/utils/prepareFiles.ts +88 -0
- package/src/ruvocal/src/lib/server/textGeneration/utils/routing.ts +21 -0
- package/src/ruvocal/src/lib/server/textGeneration/utils/toolPrompt.ts +49 -0
- package/src/ruvocal/src/lib/server/urlSafety.ts +72 -0
- package/src/ruvocal/src/lib/server/usageLimits.ts +30 -0
- package/src/ruvocal/src/lib/stores/autopilotStore.svelte.ts +175 -0
- package/src/ruvocal/src/lib/stores/backgroundGenerations.svelte.ts +32 -0
- package/src/ruvocal/src/lib/stores/backgroundGenerations.ts +1 -0
- package/src/ruvocal/src/lib/stores/errors.ts +9 -0
- package/src/ruvocal/src/lib/stores/isAborted.ts +3 -0
- package/src/ruvocal/src/lib/stores/isPro.ts +4 -0
- package/src/ruvocal/src/lib/stores/loading.ts +3 -0
- package/src/ruvocal/src/lib/stores/mcpServers.ts +345 -0
- package/src/ruvocal/src/lib/stores/pendingChatInput.ts +3 -0
- package/src/ruvocal/src/lib/stores/pendingMessage.ts +9 -0
- package/src/ruvocal/src/lib/stores/settings.ts +182 -0
- package/src/ruvocal/src/lib/stores/shareModal.ts +13 -0
- package/src/ruvocal/src/lib/stores/titleUpdate.ts +8 -0
- package/src/ruvocal/src/lib/switchTheme.ts +124 -0
- package/src/ruvocal/src/lib/types/AbortedGeneration.ts +8 -0
- package/src/ruvocal/src/lib/types/Assistant.ts +31 -0
- package/src/ruvocal/src/lib/types/AssistantStats.ts +11 -0
- package/src/ruvocal/src/lib/types/ConfigKey.ts +4 -0
- package/src/ruvocal/src/lib/types/ConvSidebar.ts +9 -0
- package/src/ruvocal/src/lib/types/Conversation.ts +27 -0
- package/src/ruvocal/src/lib/types/ConversationStats.ts +13 -0
- package/src/ruvocal/src/lib/types/Message.ts +41 -0
- package/src/ruvocal/src/lib/types/MessageEvent.ts +10 -0
- package/src/ruvocal/src/lib/types/MessageUpdate.ts +139 -0
- package/src/ruvocal/src/lib/types/MigrationResult.ts +7 -0
- package/src/ruvocal/src/lib/types/Model.ts +23 -0
- package/src/ruvocal/src/lib/types/Report.ts +12 -0
- package/src/ruvocal/src/lib/types/Review.ts +6 -0
- package/src/ruvocal/src/lib/types/Semaphore.ts +19 -0
- package/src/ruvocal/src/lib/types/Session.ts +22 -0
- package/src/ruvocal/src/lib/types/Settings.ts +86 -0
- package/src/ruvocal/src/lib/types/SharedConversation.ts +9 -0
- package/src/ruvocal/src/lib/types/Template.ts +6 -0
- package/src/ruvocal/src/lib/types/Timestamps.ts +4 -0
- package/src/ruvocal/src/lib/types/TokenCache.ts +6 -0
- package/src/ruvocal/src/lib/types/Tool.ts +74 -0
- package/src/ruvocal/src/lib/types/UrlDependency.ts +5 -0
- package/src/ruvocal/src/lib/types/User.ts +14 -0
- package/src/ruvocal/src/lib/utils/PublicConfig.svelte.ts +75 -0
- package/src/ruvocal/src/lib/utils/auth.ts +17 -0
- package/src/ruvocal/src/lib/utils/chunk.ts +33 -0
- package/src/ruvocal/src/lib/utils/cookiesAreEnabled.ts +13 -0
- package/src/ruvocal/src/lib/utils/debounce.ts +17 -0
- package/src/ruvocal/src/lib/utils/deepestChild.ts +6 -0
- package/src/ruvocal/src/lib/utils/favicon.ts +21 -0
- package/src/ruvocal/src/lib/utils/fetchJSON.ts +23 -0
- package/src/ruvocal/src/lib/utils/file2base64.ts +14 -0
- package/src/ruvocal/src/lib/utils/formatUserCount.ts +37 -0
- package/src/ruvocal/src/lib/utils/generationState.spec.ts +75 -0
- package/src/ruvocal/src/lib/utils/generationState.ts +26 -0
- package/src/ruvocal/src/lib/utils/getHref.ts +41 -0
- package/src/ruvocal/src/lib/utils/getReturnFromGenerator.ts +7 -0
- package/src/ruvocal/src/lib/utils/haptics.ts +64 -0
- package/src/ruvocal/src/lib/utils/hashConv.ts +12 -0
- package/src/ruvocal/src/lib/utils/hf.ts +17 -0
- package/src/ruvocal/src/lib/utils/isDesktop.ts +7 -0
- package/src/ruvocal/src/lib/utils/isUrl.ts +8 -0
- package/src/ruvocal/src/lib/utils/isVirtualKeyboard.ts +16 -0
- package/src/ruvocal/src/lib/utils/loadAttachmentsFromUrls.ts +115 -0
- package/src/ruvocal/src/lib/utils/marked.spec.ts +96 -0
- package/src/ruvocal/src/lib/utils/marked.ts +531 -0
- package/src/ruvocal/src/lib/utils/mcpValidation.ts +147 -0
- package/src/ruvocal/src/lib/utils/mergeAsyncGenerators.ts +38 -0
- package/src/ruvocal/src/lib/utils/messageUpdates.spec.ts +262 -0
- package/src/ruvocal/src/lib/utils/messageUpdates.ts +324 -0
- package/src/ruvocal/src/lib/utils/mime.ts +56 -0
- package/src/ruvocal/src/lib/utils/models.ts +14 -0
- package/src/ruvocal/src/lib/utils/parseBlocks.ts +120 -0
- package/src/ruvocal/src/lib/utils/parseIncompleteMarkdown.ts +644 -0
- package/src/ruvocal/src/lib/utils/parseStringToList.ts +10 -0
- package/src/ruvocal/src/lib/utils/randomUuid.ts +14 -0
- package/src/ruvocal/src/lib/utils/searchTokens.ts +33 -0
- package/src/ruvocal/src/lib/utils/sha256.ts +7 -0
- package/src/ruvocal/src/lib/utils/stringifyError.ts +12 -0
- package/src/ruvocal/src/lib/utils/sum.ts +3 -0
- package/src/ruvocal/src/lib/utils/template.spec.ts +59 -0
- package/src/ruvocal/src/lib/utils/template.ts +53 -0
- package/src/ruvocal/src/lib/utils/timeout.ts +9 -0
- package/src/ruvocal/src/lib/utils/toolProgress.spec.ts +46 -0
- package/src/ruvocal/src/lib/utils/toolProgress.ts +11 -0
- package/src/ruvocal/src/lib/utils/tree/addChildren.spec.ts +102 -0
- package/src/ruvocal/src/lib/utils/tree/addChildren.ts +48 -0
- package/src/ruvocal/src/lib/utils/tree/addSibling.spec.ts +81 -0
- package/src/ruvocal/src/lib/utils/tree/addSibling.ts +41 -0
- package/src/ruvocal/src/lib/utils/tree/buildSubtree.spec.ts +110 -0
- package/src/ruvocal/src/lib/utils/tree/buildSubtree.ts +24 -0
- package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.spec.ts +31 -0
- package/src/ruvocal/src/lib/utils/tree/convertLegacyConversation.ts +36 -0
- package/src/ruvocal/src/lib/utils/tree/isMessageId.spec.ts +15 -0
- package/src/ruvocal/src/lib/utils/tree/isMessageId.ts +5 -0
- package/src/ruvocal/src/lib/utils/tree/tree.d.ts +14 -0
- package/src/ruvocal/src/lib/utils/tree/treeHelpers.spec.ts +167 -0
- package/src/ruvocal/src/lib/utils/updates.ts +39 -0
- package/src/ruvocal/src/lib/utils/urlParams.ts +13 -0
- package/src/ruvocal/src/lib/workers/autopilotWorker.ts +221 -0
- package/src/ruvocal/src/lib/workers/detailFetchWorker.ts +100 -0
- package/src/ruvocal/src/lib/workers/markdownWorker.ts +61 -0
- package/src/ruvocal/src/routes/+error.svelte +20 -0
- package/src/ruvocal/src/routes/+layout.svelte +324 -0
- package/src/ruvocal/src/routes/+layout.ts +91 -0
- package/src/ruvocal/src/routes/+page.svelte +168 -0
- package/src/ruvocal/src/routes/.well-known/oauth-cimd/+server.ts +37 -0
- package/src/ruvocal/src/routes/__debug/openai/+server.ts +21 -0
- package/src/ruvocal/src/routes/admin/export/+server.ts +159 -0
- package/src/ruvocal/src/routes/admin/stats/compute/+server.ts +16 -0
- package/src/ruvocal/src/routes/api/conversation/[id]/+server.ts +40 -0
- package/src/ruvocal/src/routes/api/conversation/[id]/message/[messageId]/+server.ts +42 -0
- package/src/ruvocal/src/routes/api/conversations/+server.ts +48 -0
- package/src/ruvocal/src/routes/api/fetch-url/+server.ts +147 -0
- package/src/ruvocal/src/routes/api/mcp/health/+server.ts +292 -0
- package/src/ruvocal/src/routes/api/mcp/servers/+server.ts +32 -0
- package/src/ruvocal/src/routes/api/models/+server.ts +25 -0
- package/src/ruvocal/src/routes/api/transcribe/+server.ts +104 -0
- package/src/ruvocal/src/routes/api/user/+server.ts +15 -0
- package/src/ruvocal/src/routes/api/user/validate-token/+server.ts +20 -0
- package/src/ruvocal/src/routes/api/v2/conversations/+server.ts +48 -0
- package/src/ruvocal/src/routes/api/v2/conversations/[id]/+server.ts +94 -0
- package/src/ruvocal/src/routes/api/v2/conversations/[id]/message/[messageId]/+server.ts +43 -0
- package/src/ruvocal/src/routes/api/v2/conversations/import-share/+server.ts +23 -0
- package/src/ruvocal/src/routes/api/v2/debug/config/+server.ts +16 -0
- package/src/ruvocal/src/routes/api/v2/debug/refresh/+server.ts +30 -0
- package/src/ruvocal/src/routes/api/v2/export/+server.ts +196 -0
- package/src/ruvocal/src/routes/api/v2/feature-flags/+server.ts +14 -0
- package/src/ruvocal/src/routes/api/v2/models/+server.ts +38 -0
- package/src/ruvocal/src/routes/api/v2/models/[namespace]/+server.ts +8 -0
- package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/+server.ts +8 -0
- package/src/ruvocal/src/routes/api/v2/models/[namespace]/[model]/subscribe/+server.ts +28 -0
- package/src/ruvocal/src/routes/api/v2/models/[namespace]/subscribe/+server.ts +28 -0
- package/src/ruvocal/src/routes/api/v2/models/old/+server.ts +7 -0
- package/src/ruvocal/src/routes/api/v2/models/refresh/+server.ts +33 -0
- package/src/ruvocal/src/routes/api/v2/public-config/+server.ts +7 -0
- package/src/ruvocal/src/routes/api/v2/user/+server.ts +17 -0
- package/src/ruvocal/src/routes/api/v2/user/billing-orgs/+server.ts +73 -0
- package/src/ruvocal/src/routes/api/v2/user/reports/+server.ts +17 -0
- package/src/ruvocal/src/routes/api/v2/user/settings/+server.ts +103 -0
- package/src/ruvocal/src/routes/conversation/+server.ts +115 -0
- package/src/ruvocal/src/routes/conversation/[id]/+page.svelte +582 -0
- package/src/ruvocal/src/routes/conversation/[id]/+page.ts +60 -0
- package/src/ruvocal/src/routes/conversation/[id]/+server.ts +736 -0
- package/src/ruvocal/src/routes/conversation/[id]/message/[messageId]/prompt/+server.ts +66 -0
- package/src/ruvocal/src/routes/conversation/[id]/output/[sha256]/+server.ts +58 -0
- package/src/ruvocal/src/routes/conversation/[id]/share/+server.ts +69 -0
- package/src/ruvocal/src/routes/conversation/[id]/stop-generating/+server.ts +35 -0
- package/src/ruvocal/src/routes/healthcheck/+server.ts +3 -0
- package/src/ruvocal/src/routes/login/+server.ts +5 -0
- package/src/ruvocal/src/routes/login/callback/+server.ts +103 -0
- package/src/ruvocal/src/routes/login/callback/updateUser.spec.ts +157 -0
- package/src/ruvocal/src/routes/login/callback/updateUser.ts +215 -0
- package/src/ruvocal/src/routes/logout/+server.ts +18 -0
- package/src/ruvocal/src/routes/metrics/+server.ts +18 -0
- package/src/ruvocal/src/routes/models/+page.svelte +233 -0
- package/src/ruvocal/src/routes/models/[...model]/+page.svelte +161 -0
- package/src/ruvocal/src/routes/models/[...model]/+page.ts +14 -0
- package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/+server.ts +64 -0
- package/src/ruvocal/src/routes/models/[...model]/thumbnail.png/ModelThumbnail.svelte +28 -0
- package/src/ruvocal/src/routes/privacy/+page.svelte +11 -0
- package/src/ruvocal/src/routes/r/[id]/+page.ts +34 -0
- package/src/ruvocal/src/routes/settings/(nav)/+layout.svelte +282 -0
- package/src/ruvocal/src/routes/settings/(nav)/+layout.ts +1 -0
- package/src/ruvocal/src/routes/settings/(nav)/+page.svelte +0 -0
- package/src/ruvocal/src/routes/settings/(nav)/+server.ts +53 -0
- package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.svelte +464 -0
- package/src/ruvocal/src/routes/settings/(nav)/[...model]/+page.ts +14 -0
- package/src/ruvocal/src/routes/settings/(nav)/application/+page.svelte +362 -0
- package/src/ruvocal/src/routes/settings/+layout.svelte +40 -0
- package/src/ruvocal/src/styles/highlight-js.css +195 -0
- package/src/ruvocal/src/styles/main.css +144 -0
- package/src/ruvocal/static/chatui/apple-touch-icon.png +0 -0
- package/src/ruvocal/static/chatui/favicon-dark.svg +3 -0
- package/src/ruvocal/static/chatui/favicon-dev.svg +3 -0
- package/src/ruvocal/static/chatui/favicon.ico +0 -0
- package/src/ruvocal/static/chatui/favicon.svg +3 -0
- package/src/ruvocal/static/chatui/icon-128x128.png +0 -0
- package/src/ruvocal/static/chatui/icon-144x144.png +0 -0
- package/src/ruvocal/static/chatui/icon-192x192.png +0 -0
- package/src/ruvocal/static/chatui/icon-256x256.png +0 -0
- package/src/ruvocal/static/chatui/icon-36x36.png +0 -0
- package/src/ruvocal/static/chatui/icon-48x48.png +0 -0
- package/src/ruvocal/static/chatui/icon-512x512.png +0 -0
- package/src/ruvocal/static/chatui/icon-72x72.png +0 -0
- package/src/ruvocal/static/chatui/icon-96x96.png +0 -0
- package/src/ruvocal/static/chatui/icon.svg +3 -0
- package/src/ruvocal/static/chatui/logo.svg +7 -0
- package/src/ruvocal/static/chatui/manifest.json +54 -0
- package/src/ruvocal/static/chatui/omni-welcome.gif +0 -0
- package/src/ruvocal/static/chatui/omni-welcome.png +0 -0
- package/src/ruvocal/static/chatui/welcome.js +184 -0
- package/src/ruvocal/static/chatui/welcome.svg +1 -0
- package/src/ruvocal/static/huggingchat/apple-touch-icon.png +0 -0
- package/src/ruvocal/static/huggingchat/assistants-thumbnail.png +0 -0
- package/src/ruvocal/static/huggingchat/castle-example.jpg +0 -0
- package/src/ruvocal/static/huggingchat/favicon-dark.svg +4 -0
- package/src/ruvocal/static/huggingchat/favicon-dev.svg +4 -0
- package/src/ruvocal/static/huggingchat/favicon.ico +0 -0
- package/src/ruvocal/static/huggingchat/favicon.svg +4 -0
- package/src/ruvocal/static/huggingchat/fulltext-logo.svg +2 -0
- package/src/ruvocal/static/huggingchat/icon-128x128.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-144x144.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-192x192.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-256x256.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-36x36.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-48x48.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-512x512.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-72x72.png +0 -0
- package/src/ruvocal/static/huggingchat/icon-96x96.png +0 -0
- package/src/ruvocal/static/huggingchat/icon.svg +4 -0
- package/src/ruvocal/static/huggingchat/logo.svg +4 -0
- package/src/ruvocal/static/huggingchat/manifest.json +54 -0
- package/src/ruvocal/static/huggingchat/omni-welcome.gif +0 -0
- package/src/ruvocal/static/huggingchat/routes.chat.json +226 -0
- package/src/ruvocal/static/huggingchat/thumbnail.png +0 -0
- package/src/ruvocal/static/huggingchat/tools-thumbnail.png +0 -0
- package/src/ruvocal/static/robots.txt +10 -0
- package/src/ruvocal/stub/@reflink/reflink/index.js +0 -0
- package/src/ruvocal/stub/@reflink/reflink/package.json +5 -0
- package/src/ruvocal/svelte.config.js +53 -0
- package/src/ruvocal/tailwind.config.cjs +30 -0
- package/src/ruvocal/tsconfig.json +19 -0
- package/src/ruvocal/vite.config.ts +87 -0
- package/src/scripts/deploy.sh +116 -0
- package/src/scripts/generate-config.js +245 -0
- package/src/scripts/generate-welcome.js +187 -0
- package/src/scripts/package-rvf.sh +116 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Centralized MIME allowlists used across client and server
|
|
2
|
+
// Keep these lists minimal and consistent with server processing.
|
|
3
|
+
|
|
4
|
+
export const TEXT_MIME_ALLOWLIST = [
|
|
5
|
+
"text/*",
|
|
6
|
+
"application/json",
|
|
7
|
+
"application/xml",
|
|
8
|
+
"application/csv",
|
|
9
|
+
] as const;
|
|
10
|
+
|
|
11
|
+
export const IMAGE_MIME_ALLOWLIST_DEFAULT = ["image/jpeg", "image/png"] as const;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CONV_NUM_PER_PAGE = 30;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PUBLIC_SEP_TOKEN = "</s>";
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
export type RouterFollowUp = {
|
|
2
|
+
title: string;
|
|
3
|
+
prompt: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type RouterExampleAttachment = {
|
|
7
|
+
src: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type RouterExample = {
|
|
11
|
+
title: string;
|
|
12
|
+
prompt: string;
|
|
13
|
+
followUps?: RouterFollowUp[];
|
|
14
|
+
attachments?: RouterExampleAttachment[];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const routerExamples: RouterExample[] = [
|
|
18
|
+
{
|
|
19
|
+
title: "HTML game",
|
|
20
|
+
prompt: "Code a minimal Flappy Bird game using HTML and Canvas",
|
|
21
|
+
followUps: [
|
|
22
|
+
{
|
|
23
|
+
title: "README.md file",
|
|
24
|
+
prompt: "Create a comprehensive README.md for the Flappy Bird game project.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: "CRT Screen",
|
|
28
|
+
prompt: "Add a CRT screen effect to the game",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: "Add power-ups",
|
|
32
|
+
prompt:
|
|
33
|
+
"Add collectible coins between pipes that award bonus points and a shield power-up that allows one collision.",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: "Explain collision detection",
|
|
37
|
+
prompt:
|
|
38
|
+
"Explain the collision detection algorithm for the bird and pipes in simple terms with examples.",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: "Weird painting",
|
|
44
|
+
prompt: "is this a real painting?",
|
|
45
|
+
attachments: [
|
|
46
|
+
{
|
|
47
|
+
src: "huggingchat/castle-example.jpg",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
title: "Landing page",
|
|
53
|
+
prompt:
|
|
54
|
+
"Build a responsive SaaS landing page for my AI coding assitant using Tailwind CSS. With a hero, features, testimonials, and pricing sections.",
|
|
55
|
+
followUps: [
|
|
56
|
+
{
|
|
57
|
+
title: "Dark mode",
|
|
58
|
+
prompt: "Add dark mode and make it the default",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
title: "Write blog post",
|
|
62
|
+
prompt: "Write a blog post introducing my service.",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: "Translate to Italian",
|
|
66
|
+
prompt: "Translate only the text content displayed to users into Italian.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
title: "Architecture review",
|
|
70
|
+
prompt:
|
|
71
|
+
"Review the architecture and suggest improvements for scalability, SEO optimization, and performance.",
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
title: "Eminem song",
|
|
77
|
+
prompt:
|
|
78
|
+
"Write an Eminem-style rap battling AI taking over hip-hop, with two energetic verses and a catchy hook.",
|
|
79
|
+
followUps: [
|
|
80
|
+
{
|
|
81
|
+
title: "Psychological analysis",
|
|
82
|
+
prompt: "Provide a psychological analysis of Eminem's emotions in this song.",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
title: "Wired Article",
|
|
86
|
+
prompt: "Write an article in the style of Wired explaining this Eminem release.",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
title: "Roleplay",
|
|
90
|
+
prompt: "Roleplay as Eminem so I can discuss the song with him.",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
title: "Translate to Spanish",
|
|
94
|
+
prompt: "Translate the rap lyrics to Spanish while maintaining the rhyme scheme and flow.",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
title: "Act as Yoda",
|
|
100
|
+
prompt: "Act as Yoda",
|
|
101
|
+
followUps: [
|
|
102
|
+
{
|
|
103
|
+
title: "Give advice",
|
|
104
|
+
prompt:
|
|
105
|
+
"Continue acting as Yoda and offer three pieces of life advice for staying focused under pressure.",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
title: "Explain the Force",
|
|
109
|
+
prompt:
|
|
110
|
+
"In Yoda's voice, explain the concept of the Force to a young padawan using modern language.",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
title: "Plain English",
|
|
114
|
+
prompt:
|
|
115
|
+
"Rewrite the previous response from Yoda into plain English while keeping the same meaning.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
title: "Compare philosophies",
|
|
119
|
+
prompt:
|
|
120
|
+
"Compare Yoda's Jedi philosophy to Stoic philosophy from ancient Greece and explain the similarities and differences.",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
title: "Generate prompts",
|
|
126
|
+
prompt: `Generate 5 creative prompts Text-to-image prompts like: "Cyberpunk cityscape at night, neon lights, flying cars, rain-slicked streets, blade runner aesthetic, highly detailed`,
|
|
127
|
+
followUps: [
|
|
128
|
+
{
|
|
129
|
+
title: "Turn into JSON",
|
|
130
|
+
prompt: `Generate a detailed JSON object for each prompt. Include fields for subjects (list of objects), scene (setting, environment, background details), actions (what's happening), style (artistic style or medium)`,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
title: "Sci-fi portraits",
|
|
134
|
+
prompt:
|
|
135
|
+
"Produce five futuristic character portrait prompts with unique professions and settings.",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
title: "Explain image generation",
|
|
139
|
+
prompt:
|
|
140
|
+
"Explain how text-to-image diffusion models work, covering the denoising process and how text prompts guide generation.",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
title: "Explain LLMs",
|
|
146
|
+
prompt:
|
|
147
|
+
"Explain how large language models based on transformers work, covering attention, embeddings, and training objectives.",
|
|
148
|
+
followUps: [
|
|
149
|
+
{
|
|
150
|
+
title: "Generate a Quiz",
|
|
151
|
+
prompt: "Craft a 5-question multiple-choice quiz to validate what I learned.",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
title: "Compare to RNNs",
|
|
155
|
+
prompt:
|
|
156
|
+
"Compare transformer-based large language models to recurrent neural networks, focusing on training efficiency and capabilities.",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
title: "Student summary",
|
|
160
|
+
prompt:
|
|
161
|
+
"Summarize the explanation of large language models for a high school student using relatable analogies.",
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
title: "Write a blog post",
|
|
165
|
+
prompt:
|
|
166
|
+
"Write a blog post about how transformers revolutionized NLP, targeting software engineers who are new to AI.",
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
title: "Translate in Italian",
|
|
172
|
+
prompt: `Translate in Italian: Some are born great, some achieve greatness, and some have greatness thrust upon 'em`,
|
|
173
|
+
followUps: [
|
|
174
|
+
{
|
|
175
|
+
title: "Back to English",
|
|
176
|
+
prompt:
|
|
177
|
+
"Translate the Italian version back into English while keeping Shakespeare's tone intact.",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
title: "Explain choices",
|
|
181
|
+
prompt: "Explain your translation choices for each key phrase from the Italian version.",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
title: "Modernize",
|
|
185
|
+
prompt:
|
|
186
|
+
"Modernize the Italian translation into contemporary informal Italian suitable for social media.",
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
title: "Teach me Italian",
|
|
190
|
+
prompt:
|
|
191
|
+
"Help me practice Italian by conversing about this Shakespeare quote, correcting my grammar when needed.",
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
title: "Pelican on a bicycle",
|
|
197
|
+
prompt: "Draw an SVG of a pelican riding a bicycle",
|
|
198
|
+
followUps: [
|
|
199
|
+
{
|
|
200
|
+
title: "Add a top hat",
|
|
201
|
+
prompt: "Add a fancy top hat to the pelican and make it look distinguished",
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: "Make it animated",
|
|
205
|
+
prompt: "Add CSS animations to make the bicycle wheels spin and the pelican's wings flap",
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { base } from "$app/paths";
|
|
2
|
+
import { page } from "$app/state";
|
|
3
|
+
|
|
4
|
+
// Returns a public share URL for a conversation id.
|
|
5
|
+
// If `id` is already a 7-char share id, no network call is made.
|
|
6
|
+
export async function createShareLink(id: string): Promise<string> {
|
|
7
|
+
const prefix =
|
|
8
|
+
page.data.publicConfig.PUBLIC_SHARE_PREFIX ||
|
|
9
|
+
`${page.data.publicConfig.PUBLIC_ORIGIN || page.url.origin}${base}`;
|
|
10
|
+
|
|
11
|
+
if (id.length === 7) {
|
|
12
|
+
return `${prefix}/r/${id}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const res = await fetch(`${base}/conversation/${id}/share`, {
|
|
16
|
+
method: "POST",
|
|
17
|
+
headers: { "Content-Type": "application/json" },
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!res.ok) {
|
|
21
|
+
const text = await res.text().catch(() => "");
|
|
22
|
+
throw new Error(text || "Failed to create share link");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { shareId } = await res.json();
|
|
26
|
+
return `${prefix}/r/${shareId}`;
|
|
27
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import type { ConversationStats } from "$lib/types/ConversationStats";
|
|
2
|
+
import { CONVERSATION_STATS_COLLECTION, collections } from "$lib/server/database";
|
|
3
|
+
import { logger } from "$lib/server/logger";
|
|
4
|
+
import type { ObjectId } from "mongodb";
|
|
5
|
+
import { acquireLock, refreshLock } from "$lib/migrations/lock";
|
|
6
|
+
import { Semaphores } from "$lib/types/Semaphore";
|
|
7
|
+
|
|
8
|
+
async function getLastComputationTime(): Promise<Date> {
|
|
9
|
+
const lastStats = await collections.conversationStats.findOne({}, { sort: { "date.at": -1 } });
|
|
10
|
+
return lastStats?.date?.at || new Date(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function shouldComputeStats(): Promise<boolean> {
|
|
14
|
+
const lastComputationTime = await getLastComputationTime();
|
|
15
|
+
const oneDayAgo = new Date(Date.now() - 24 * 3_600_000);
|
|
16
|
+
return lastComputationTime < oneDayAgo;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function computeAllStats() {
|
|
20
|
+
for (const span of ["day", "week", "month"] as const) {
|
|
21
|
+
computeStats({ dateField: "updatedAt", type: "conversation", span }).catch((e) =>
|
|
22
|
+
logger.error(e, "Error computing conversation stats for updatedAt")
|
|
23
|
+
);
|
|
24
|
+
computeStats({ dateField: "createdAt", type: "conversation", span }).catch((e) =>
|
|
25
|
+
logger.error(e, "Error computing conversation stats for createdAt")
|
|
26
|
+
);
|
|
27
|
+
computeStats({ dateField: "createdAt", type: "message", span }).catch((e) =>
|
|
28
|
+
logger.error(e, "Error computing message stats for createdAt")
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function computeStats(params: {
|
|
34
|
+
dateField: ConversationStats["date"]["field"];
|
|
35
|
+
span: ConversationStats["date"]["span"];
|
|
36
|
+
type: ConversationStats["type"];
|
|
37
|
+
}) {
|
|
38
|
+
const indexes = await collections.semaphores.listIndexes().toArray();
|
|
39
|
+
if (indexes.length <= 2) {
|
|
40
|
+
logger.info("Indexes not created, skipping stats computation");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const lastComputed = await collections.conversationStats.findOne(
|
|
45
|
+
{ "date.field": params.dateField, "date.span": params.span, type: params.type },
|
|
46
|
+
{ sort: { "date.at": -1 } }
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// If the last computed week is at the beginning of the last computed month, we need to include some days from the previous month
|
|
50
|
+
// In those cases we need to compute the stats from before the last month as everything is one aggregation
|
|
51
|
+
const minDate = lastComputed ? lastComputed.date.at : new Date(0);
|
|
52
|
+
|
|
53
|
+
logger.debug(
|
|
54
|
+
{ minDate, dateField: params.dateField, span: params.span, type: params.type },
|
|
55
|
+
"Computing conversation stats"
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const dateField = params.type === "message" ? "messages." + params.dateField : params.dateField;
|
|
59
|
+
|
|
60
|
+
const pipeline = [
|
|
61
|
+
{
|
|
62
|
+
$match: {
|
|
63
|
+
[dateField]: { $gte: minDate },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
// For message stats: use $filter to reduce data before $unwind (optimization)
|
|
67
|
+
// For conversation stats: simple projection
|
|
68
|
+
...(params.type === "message"
|
|
69
|
+
? [
|
|
70
|
+
{
|
|
71
|
+
$project: {
|
|
72
|
+
// Filter messages by date, then map to only keep the date field
|
|
73
|
+
// This avoids carrying large message payloads (content, files, etc.) through the pipeline
|
|
74
|
+
messages: {
|
|
75
|
+
$map: {
|
|
76
|
+
input: {
|
|
77
|
+
$filter: {
|
|
78
|
+
input: "$messages",
|
|
79
|
+
as: "msg",
|
|
80
|
+
cond: { $gte: [`$$msg.${params.dateField}`, minDate] },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
as: "msg",
|
|
84
|
+
in: { [params.dateField]: `$$msg.${params.dateField}` },
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
sessionId: 1,
|
|
88
|
+
userId: 1,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
$unwind: "$messages",
|
|
93
|
+
},
|
|
94
|
+
]
|
|
95
|
+
: [
|
|
96
|
+
{
|
|
97
|
+
$project: {
|
|
98
|
+
[dateField]: 1,
|
|
99
|
+
sessionId: 1,
|
|
100
|
+
userId: 1,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
]),
|
|
104
|
+
{
|
|
105
|
+
$sort: {
|
|
106
|
+
[dateField]: 1,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
$facet: {
|
|
111
|
+
userId: [
|
|
112
|
+
{
|
|
113
|
+
$match: {
|
|
114
|
+
userId: { $exists: true },
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
$group: {
|
|
119
|
+
_id: {
|
|
120
|
+
at: { $dateTrunc: { date: `$${dateField}`, unit: params.span } },
|
|
121
|
+
userId: "$userId",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
$group: {
|
|
127
|
+
_id: "$_id.at",
|
|
128
|
+
count: { $sum: 1 },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
$project: {
|
|
133
|
+
_id: 0,
|
|
134
|
+
date: {
|
|
135
|
+
at: "$_id",
|
|
136
|
+
field: params.dateField,
|
|
137
|
+
span: params.span,
|
|
138
|
+
},
|
|
139
|
+
distinct: "userId",
|
|
140
|
+
count: 1,
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
sessionId: [
|
|
145
|
+
{
|
|
146
|
+
$match: {
|
|
147
|
+
sessionId: { $exists: true },
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
$group: {
|
|
152
|
+
_id: {
|
|
153
|
+
at: { $dateTrunc: { date: `$${dateField}`, unit: params.span } },
|
|
154
|
+
sessionId: "$sessionId",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
$group: {
|
|
160
|
+
_id: "$_id.at",
|
|
161
|
+
count: { $sum: 1 },
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
$project: {
|
|
166
|
+
_id: 0,
|
|
167
|
+
date: {
|
|
168
|
+
at: "$_id",
|
|
169
|
+
field: params.dateField,
|
|
170
|
+
span: params.span,
|
|
171
|
+
},
|
|
172
|
+
distinct: "sessionId",
|
|
173
|
+
count: 1,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
userOrSessionId: [
|
|
178
|
+
{
|
|
179
|
+
$group: {
|
|
180
|
+
_id: {
|
|
181
|
+
at: { $dateTrunc: { date: `$${dateField}`, unit: params.span } },
|
|
182
|
+
userOrSessionId: { $ifNull: ["$userId", "$sessionId"] },
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
$group: {
|
|
188
|
+
_id: "$_id.at",
|
|
189
|
+
count: { $sum: 1 },
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
$project: {
|
|
194
|
+
_id: 0,
|
|
195
|
+
date: {
|
|
196
|
+
at: "$_id",
|
|
197
|
+
field: params.dateField,
|
|
198
|
+
span: params.span,
|
|
199
|
+
},
|
|
200
|
+
distinct: "userOrSessionId",
|
|
201
|
+
count: 1,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
],
|
|
205
|
+
_id: [
|
|
206
|
+
{
|
|
207
|
+
$group: {
|
|
208
|
+
_id: { $dateTrunc: { date: `$${dateField}`, unit: params.span } },
|
|
209
|
+
count: { $sum: 1 },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
$project: {
|
|
214
|
+
_id: 0,
|
|
215
|
+
date: {
|
|
216
|
+
at: "$_id",
|
|
217
|
+
field: params.dateField,
|
|
218
|
+
span: params.span,
|
|
219
|
+
},
|
|
220
|
+
distinct: "_id",
|
|
221
|
+
count: 1,
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
$project: {
|
|
229
|
+
stats: {
|
|
230
|
+
$concatArrays: ["$userId", "$sessionId", "$userOrSessionId", "$_id"],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
$unwind: "$stats",
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
$replaceRoot: {
|
|
239
|
+
newRoot: "$stats",
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
$set: {
|
|
244
|
+
type: params.type,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
$merge: {
|
|
249
|
+
into: CONVERSATION_STATS_COLLECTION,
|
|
250
|
+
on: ["date.at", "type", "date.span", "date.field", "distinct"],
|
|
251
|
+
whenMatched: "replace",
|
|
252
|
+
whenNotMatched: "insert",
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
];
|
|
256
|
+
|
|
257
|
+
await collections.conversations.aggregate(pipeline, { allowDiskUse: true }).next();
|
|
258
|
+
|
|
259
|
+
logger.debug(
|
|
260
|
+
{ minDate, dateField: params.dateField, span: params.span, type: params.type },
|
|
261
|
+
"Computed conversation stats"
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let hasLock = false;
|
|
266
|
+
let lockId: ObjectId | null = null;
|
|
267
|
+
|
|
268
|
+
async function maintainLock() {
|
|
269
|
+
if (hasLock && lockId) {
|
|
270
|
+
hasLock = await refreshLock(Semaphores.CONVERSATION_STATS, lockId);
|
|
271
|
+
|
|
272
|
+
if (!hasLock) {
|
|
273
|
+
lockId = null;
|
|
274
|
+
}
|
|
275
|
+
} else if (!hasLock) {
|
|
276
|
+
lockId = (await acquireLock(Semaphores.CONVERSATION_STATS)) || null;
|
|
277
|
+
hasLock = !!lockId;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
setTimeout(maintainLock, 10_000);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function refreshConversationStats() {
|
|
284
|
+
const ONE_HOUR_MS = 3_600_000;
|
|
285
|
+
|
|
286
|
+
maintainLock().then(async () => {
|
|
287
|
+
if (await shouldComputeStats()) {
|
|
288
|
+
computeAllStats();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
setInterval(async () => {
|
|
292
|
+
if (await shouldComputeStats()) {
|
|
293
|
+
computeAllStats();
|
|
294
|
+
}
|
|
295
|
+
}, 24 * ONE_HOUR_MS);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { collections } from "$lib/server/database";
|
|
2
|
+
import { ObjectId } from "mongodb";
|
|
3
|
+
import type { Semaphores } from "$lib/types/Semaphore";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the lock id if the lock was acquired, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
export async function acquireLock(key: Semaphores | string): Promise<ObjectId | false> {
|
|
9
|
+
try {
|
|
10
|
+
const id = new ObjectId();
|
|
11
|
+
|
|
12
|
+
const insert = await collections.semaphores.insertOne({
|
|
13
|
+
_id: id,
|
|
14
|
+
key,
|
|
15
|
+
createdAt: new Date(),
|
|
16
|
+
updatedAt: new Date(),
|
|
17
|
+
deleteAt: new Date(Date.now() + 1000 * 60 * 3), // 3 minutes
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return insert.acknowledged ? id : false; // true if the document was inserted
|
|
21
|
+
} catch (e) {
|
|
22
|
+
// unique index violation, so there must already be a lock
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function releaseLock(key: Semaphores | string, lockId: ObjectId) {
|
|
28
|
+
await collections.semaphores.deleteOne({
|
|
29
|
+
_id: lockId,
|
|
30
|
+
key,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function isDBLocked(key: Semaphores | string): Promise<boolean> {
|
|
35
|
+
const res = await collections.semaphores.countDocuments({
|
|
36
|
+
key,
|
|
37
|
+
});
|
|
38
|
+
return res > 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function refreshLock(key: Semaphores | string, lockId: ObjectId): Promise<boolean> {
|
|
42
|
+
const result = await collections.semaphores.updateOne(
|
|
43
|
+
{
|
|
44
|
+
_id: lockId,
|
|
45
|
+
key,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
$set: {
|
|
49
|
+
updatedAt: new Date(),
|
|
50
|
+
deleteAt: new Date(Date.now() + 1000 * 60 * 3), // 3 minutes
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return result.matchedCount > 0;
|
|
56
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { afterEach, assert, beforeAll, describe, expect, it } from "vitest";
|
|
2
|
+
import { migrations } from "./routines";
|
|
3
|
+
import { acquireLock, isDBLocked, refreshLock, releaseLock } from "./lock";
|
|
4
|
+
import { Semaphores } from "$lib/types/Semaphore";
|
|
5
|
+
import { collections, ready } from "$lib/server/database";
|
|
6
|
+
|
|
7
|
+
describe(
|
|
8
|
+
"migrations",
|
|
9
|
+
{
|
|
10
|
+
retry: 3,
|
|
11
|
+
},
|
|
12
|
+
() => {
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
await ready;
|
|
15
|
+
try {
|
|
16
|
+
await collections.semaphores.createIndex({ key: 1 }, { unique: true });
|
|
17
|
+
} catch (e) {
|
|
18
|
+
// Index might already exist, ignore error
|
|
19
|
+
}
|
|
20
|
+
}, 20000);
|
|
21
|
+
|
|
22
|
+
it("should not have duplicates guid", async () => {
|
|
23
|
+
const guids = migrations.map((m) => m._id.toString());
|
|
24
|
+
const uniqueGuids = [...new Set(guids)];
|
|
25
|
+
expect(uniqueGuids.length).toBe(guids.length);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should acquire only one lock on DB", async () => {
|
|
29
|
+
const results = await Promise.all(
|
|
30
|
+
new Array(1000).fill(0).map(() => acquireLock(Semaphores.TEST_MIGRATION))
|
|
31
|
+
);
|
|
32
|
+
const locks = results.filter((r) => r);
|
|
33
|
+
|
|
34
|
+
const semaphores = await collections.semaphores.find({}).toArray();
|
|
35
|
+
|
|
36
|
+
expect(locks.length).toBe(1);
|
|
37
|
+
expect(semaphores).toBeDefined();
|
|
38
|
+
expect(semaphores.length).toBe(1);
|
|
39
|
+
expect(semaphores?.[0].key).toBe(Semaphores.TEST_MIGRATION);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should read the lock correctly", async () => {
|
|
43
|
+
const lockId = await acquireLock(Semaphores.TEST_MIGRATION);
|
|
44
|
+
assert(lockId);
|
|
45
|
+
expect(await isDBLocked(Semaphores.TEST_MIGRATION)).toBe(true);
|
|
46
|
+
expect(!!(await acquireLock(Semaphores.TEST_MIGRATION))).toBe(false);
|
|
47
|
+
await releaseLock(Semaphores.TEST_MIGRATION, lockId);
|
|
48
|
+
expect(await isDBLocked(Semaphores.TEST_MIGRATION)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should refresh the lock", async () => {
|
|
52
|
+
const lockId = await acquireLock(Semaphores.TEST_MIGRATION);
|
|
53
|
+
|
|
54
|
+
assert(lockId);
|
|
55
|
+
|
|
56
|
+
// get the updatedAt time
|
|
57
|
+
|
|
58
|
+
const updatedAtInitially = (await collections.semaphores.findOne({}))?.updatedAt;
|
|
59
|
+
|
|
60
|
+
await refreshLock(Semaphores.TEST_MIGRATION, lockId);
|
|
61
|
+
|
|
62
|
+
const updatedAtAfterRefresh = (await collections.semaphores.findOne({}))?.updatedAt;
|
|
63
|
+
|
|
64
|
+
expect(updatedAtInitially).toBeDefined();
|
|
65
|
+
expect(updatedAtAfterRefresh).toBeDefined();
|
|
66
|
+
expect(updatedAtInitially).not.toBe(updatedAtAfterRefresh);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
afterEach(async () => {
|
|
70
|
+
await collections.semaphores.deleteMany({});
|
|
71
|
+
await collections.migrationResults.deleteMany({});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
);
|