libre-webui 0.17.0 → 0.19.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.
- package/README.md +30 -17
- package/backend/dist/db.d.ts.map +1 -1
- package/backend/dist/db.js +195 -6
- package/backend/dist/db.js.map +1 -1
- package/backend/dist/index.d.ts.map +1 -1
- package/backend/dist/index.js +48 -19
- package/backend/dist/index.js.map +1 -1
- package/backend/dist/middleware/auth.d.ts.map +1 -1
- package/backend/dist/middleware/auth.js +35 -3
- package/backend/dist/middleware/auth.js.map +1 -1
- package/backend/dist/middleware/index.d.ts.map +1 -1
- package/backend/dist/models/personaModel.d.ts.map +1 -1
- package/backend/dist/models/personaModel.js.map +1 -1
- package/backend/dist/models/userModel.d.ts +24 -0
- package/backend/dist/models/userModel.d.ts.map +1 -1
- package/backend/dist/models/userModel.js +92 -24
- package/backend/dist/models/userModel.js.map +1 -1
- package/backend/dist/routes/agentCli.d.ts.map +1 -1
- package/backend/dist/routes/agentCli.js +4 -2
- package/backend/dist/routes/agentCli.js.map +1 -1
- package/backend/dist/routes/auth.d.ts.map +1 -1
- package/backend/dist/routes/auth.js +118 -55
- package/backend/dist/routes/auth.js.map +1 -1
- package/backend/dist/routes/chat.d.ts.map +1 -1
- package/backend/dist/routes/chat.js +106 -3
- package/backend/dist/routes/chat.js.map +1 -1
- package/backend/dist/routes/documents.d.ts.map +1 -1
- package/backend/dist/routes/documents.js +179 -41
- package/backend/dist/routes/documents.js.map +1 -1
- package/backend/dist/routes/embeddings.d.ts.map +1 -1
- package/backend/dist/routes/embeddings.js +2 -2
- package/backend/dist/routes/embeddings.js.map +1 -1
- package/backend/dist/routes/huggingfaceHub.d.ts.map +1 -1
- package/backend/dist/routes/huggingfaceHub.js +3 -1
- package/backend/dist/routes/huggingfaceHub.js.map +1 -1
- package/backend/dist/routes/imageGen.d.ts.map +1 -1
- package/backend/dist/routes/imageGen.js +2 -0
- package/backend/dist/routes/imageGen.js.map +1 -1
- package/backend/dist/routes/libreClaw.d.ts.map +1 -1
- package/backend/dist/routes/media.d.ts +3 -0
- package/backend/dist/routes/media.d.ts.map +1 -0
- package/backend/dist/routes/media.js +429 -0
- package/backend/dist/routes/media.js.map +1 -0
- package/backend/dist/routes/notes.d.ts +3 -0
- package/backend/dist/routes/notes.d.ts.map +1 -0
- package/backend/dist/routes/notes.js +121 -0
- package/backend/dist/routes/notes.js.map +1 -0
- package/backend/dist/routes/ollama.d.ts.map +1 -1
- package/backend/dist/routes/ollama.js +17 -85
- package/backend/dist/routes/ollama.js.map +1 -1
- package/backend/dist/routes/personas.d.ts.map +1 -1
- package/backend/dist/routes/personas.js +2 -0
- package/backend/dist/routes/personas.js.map +1 -1
- package/backend/dist/routes/plugins.d.ts.map +1 -1
- package/backend/dist/routes/plugins.js +28 -0
- package/backend/dist/routes/plugins.js.map +1 -1
- package/backend/dist/routes/preferences.d.ts.map +1 -1
- package/backend/dist/routes/systemDiagnostics.d.ts +3 -0
- package/backend/dist/routes/systemDiagnostics.d.ts.map +1 -0
- package/backend/dist/routes/systemDiagnostics.js +49 -0
- package/backend/dist/routes/systemDiagnostics.js.map +1 -0
- package/backend/dist/routes/tts.d.ts.map +1 -1
- package/backend/dist/routes/tts.js +4 -0
- package/backend/dist/routes/tts.js.map +1 -1
- package/backend/dist/routes/users.d.ts.map +1 -1
- package/backend/dist/routes/users.js +79 -0
- package/backend/dist/routes/users.js.map +1 -1
- package/backend/dist/routes/work.d.ts.map +1 -1
- package/backend/dist/routes/work.js +84 -0
- package/backend/dist/routes/work.js.map +1 -1
- package/backend/dist/services/agentCliService.d.ts +37 -4
- package/backend/dist/services/agentCliService.d.ts.map +1 -1
- package/backend/dist/services/agentCliService.js +229 -10
- package/backend/dist/services/agentCliService.js.map +1 -1
- package/backend/dist/services/assistantCompletionService.d.ts.map +1 -1
- package/backend/dist/services/authService.d.ts +15 -9
- package/backend/dist/services/authService.d.ts.map +1 -1
- package/backend/dist/services/authService.js +39 -29
- package/backend/dist/services/authService.js.map +1 -1
- package/backend/dist/services/chatGenerationService.d.ts.map +1 -1
- package/backend/dist/services/chatGenerationService.js +3 -3
- package/backend/dist/services/chatGenerationService.js.map +1 -1
- package/backend/dist/services/chatRequestService.d.ts +8 -2
- package/backend/dist/services/chatRequestService.d.ts.map +1 -1
- package/backend/dist/services/chatRequestService.js +30 -3
- package/backend/dist/services/chatRequestService.js.map +1 -1
- package/backend/dist/services/chatService.d.ts +6 -1
- package/backend/dist/services/chatService.d.ts.map +1 -1
- package/backend/dist/services/chatService.js +54 -1
- package/backend/dist/services/chatService.js.map +1 -1
- package/backend/dist/services/codexOAuthService.d.ts +22 -0
- package/backend/dist/services/codexOAuthService.d.ts.map +1 -0
- package/backend/dist/services/codexOAuthService.js +176 -0
- package/backend/dist/services/codexOAuthService.js.map +1 -0
- package/backend/dist/services/documentService.d.ts +17 -10
- package/backend/dist/services/documentService.d.ts.map +1 -1
- package/backend/dist/services/documentService.js +79 -58
- package/backend/dist/services/documentService.js.map +1 -1
- package/backend/dist/services/embeddingService.d.ts.map +1 -1
- package/backend/dist/services/encryptionService.d.ts.map +1 -1
- package/backend/dist/services/encryptionService.js +18 -8
- package/backend/dist/services/encryptionService.js.map +1 -1
- package/backend/dist/services/followUpService.d.ts +44 -0
- package/backend/dist/services/followUpService.d.ts.map +1 -0
- package/backend/dist/services/followUpService.js +123 -0
- package/backend/dist/services/followUpService.js.map +1 -0
- package/backend/dist/services/galleryService.d.ts +23 -1
- package/backend/dist/services/galleryService.d.ts.map +1 -1
- package/backend/dist/services/galleryService.js +125 -8
- package/backend/dist/services/galleryService.js.map +1 -1
- package/backend/dist/services/libreClawService.d.ts.map +1 -1
- package/backend/dist/services/mediaGenerationJobService.d.ts +25 -0
- package/backend/dist/services/mediaGenerationJobService.d.ts.map +1 -0
- package/backend/dist/services/mediaGenerationJobService.js +82 -0
- package/backend/dist/services/mediaGenerationJobService.js.map +1 -0
- package/backend/dist/services/memoryService.d.ts.map +1 -1
- package/backend/dist/services/memoryService.js.map +1 -1
- package/backend/dist/services/mutationEngineService.d.ts.map +1 -1
- package/backend/dist/services/oauthSecurity.d.ts +14 -0
- package/backend/dist/services/oauthSecurity.d.ts.map +1 -0
- package/backend/dist/services/oauthSecurity.js +101 -0
- package/backend/dist/services/oauthSecurity.js.map +1 -0
- package/backend/dist/services/ollamaService.d.ts +8 -2
- package/backend/dist/services/ollamaService.d.ts.map +1 -1
- package/backend/dist/services/ollamaService.js +40 -2
- package/backend/dist/services/ollamaService.js.map +1 -1
- package/backend/dist/services/personaService.d.ts.map +1 -1
- package/backend/dist/services/personaService.js.map +1 -1
- package/backend/dist/services/pluginActivationService.d.ts.map +1 -1
- package/backend/dist/services/pluginActivationService.js.map +1 -1
- package/backend/dist/services/pluginAudioGenerationService.d.ts +34 -0
- package/backend/dist/services/pluginAudioGenerationService.d.ts.map +1 -0
- package/backend/dist/services/pluginAudioGenerationService.js +211 -0
- package/backend/dist/services/pluginAudioGenerationService.js.map +1 -0
- package/backend/dist/services/pluginCapabilityRegistryService.d.ts.map +1 -1
- package/backend/dist/services/pluginCapabilityRegistryService.js +6 -0
- package/backend/dist/services/pluginCapabilityRegistryService.js.map +1 -1
- package/backend/dist/services/pluginCredentialsService.d.ts.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.d.ts +2 -0
- package/backend/dist/services/pluginEmbeddingService.d.ts.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.js +66 -35
- package/backend/dist/services/pluginEmbeddingService.js.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.d.ts +2 -0
- package/backend/dist/services/pluginImageGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.js +63 -38
- package/backend/dist/services/pluginImageGenerationService.js.map +1 -1
- package/backend/dist/services/pluginService.d.ts +43 -1
- package/backend/dist/services/pluginService.d.ts.map +1 -1
- package/backend/dist/services/pluginService.js +441 -71
- package/backend/dist/services/pluginService.js.map +1 -1
- package/backend/dist/services/pluginTTSService.d.ts +2 -0
- package/backend/dist/services/pluginTTSService.d.ts.map +1 -1
- package/backend/dist/services/pluginTTSService.js +27 -2
- package/backend/dist/services/pluginTTSService.js.map +1 -1
- package/backend/dist/services/pluginUsageService.d.ts +100 -0
- package/backend/dist/services/pluginUsageService.d.ts.map +1 -0
- package/backend/dist/services/pluginUsageService.js +291 -0
- package/backend/dist/services/pluginUsageService.js.map +1 -0
- package/backend/dist/services/pluginVariablesService.d.ts.map +1 -1
- package/backend/dist/services/pluginVariablesService.js.map +1 -1
- package/backend/dist/services/pluginVideoGenerationService.d.ts +45 -0
- package/backend/dist/services/pluginVideoGenerationService.d.ts.map +1 -0
- package/backend/dist/services/pluginVideoGenerationService.js +198 -0
- package/backend/dist/services/pluginVideoGenerationService.js.map +1 -0
- package/backend/dist/services/preferencesService.d.ts.map +1 -1
- package/backend/dist/services/preferencesService.js +16 -1
- package/backend/dist/services/preferencesService.js.map +1 -1
- package/backend/dist/services/registrationPolicy.d.ts +5 -0
- package/backend/dist/services/registrationPolicy.d.ts.map +1 -0
- package/backend/dist/services/registrationPolicy.js +21 -0
- package/backend/dist/services/registrationPolicy.js.map +1 -0
- package/backend/dist/services/simpleGitHubOAuth.d.ts +1 -1
- package/backend/dist/services/simpleGitHubOAuth.d.ts.map +1 -1
- package/backend/dist/services/simpleGitHubOAuth.js +13 -13
- package/backend/dist/services/simpleGitHubOAuth.js.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.js +12 -17
- package/backend/dist/services/simpleHuggingFaceOAuth.js.map +1 -1
- package/backend/dist/services/systemDiagnosticsService.d.ts +117 -0
- package/backend/dist/services/systemDiagnosticsService.d.ts.map +1 -0
- package/backend/dist/services/systemDiagnosticsService.js +326 -0
- package/backend/dist/services/systemDiagnosticsService.js.map +1 -0
- package/backend/dist/services/titleGenerationService.d.ts.map +1 -1
- package/backend/dist/services/turnstileService.d.ts +2 -1
- package/backend/dist/services/turnstileService.d.ts.map +1 -1
- package/backend/dist/services/turnstileService.js +28 -2
- package/backend/dist/services/turnstileService.js.map +1 -1
- package/backend/dist/services/userService.d.ts +1 -0
- package/backend/dist/services/userService.js +1 -1
- package/backend/dist/services/workAgentService.d.ts.map +1 -1
- package/backend/dist/services/workAgentService.js.map +1 -1
- package/backend/dist/services/workEventService.d.ts.map +1 -1
- package/backend/dist/services/workEventService.js.map +1 -1
- package/backend/dist/services/workHostWorkspaceService.d.ts.map +1 -1
- package/backend/dist/services/workModelProviderService.d.ts +3 -0
- package/backend/dist/services/workModelProviderService.d.ts.map +1 -1
- package/backend/dist/services/workModelProviderService.js +67 -10
- package/backend/dist/services/workModelProviderService.js.map +1 -1
- package/backend/dist/services/workPreviewProxyService.d.ts +27 -0
- package/backend/dist/services/workPreviewProxyService.d.ts.map +1 -0
- package/backend/dist/services/workPreviewProxyService.js +514 -0
- package/backend/dist/services/workPreviewProxyService.js.map +1 -0
- package/backend/dist/services/workRuntimeService.d.ts +28 -7
- package/backend/dist/services/workRuntimeService.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeService.js +287 -8
- package/backend/dist/services/workRuntimeService.js.map +1 -1
- package/backend/dist/services/workTaskService.d.ts.map +1 -1
- package/backend/dist/services/workTaskService.js.map +1 -1
- package/backend/dist/services/workTerminalService.d.ts +1 -1
- package/backend/dist/services/workTerminalService.d.ts.map +1 -1
- package/backend/dist/services/workTerminalService.js.map +1 -1
- package/backend/dist/storage.d.ts +12 -1
- package/backend/dist/storage.d.ts.map +1 -1
- package/backend/dist/storage.js +183 -9
- package/backend/dist/storage.js.map +1 -1
- package/backend/dist/storageMappers.d.ts +13 -0
- package/backend/dist/storageMappers.d.ts.map +1 -1
- package/backend/dist/storageMappers.js +5 -0
- package/backend/dist/storageMappers.js.map +1 -1
- package/backend/dist/types/index.d.ts +106 -1
- package/backend/dist/types/index.d.ts.map +1 -1
- package/backend/dist/types/index.js.map +1 -1
- package/backend/dist/types/work.d.ts +31 -0
- package/backend/dist/types/work.d.ts.map +1 -1
- package/backend/dist/utils/chatContext.js.map +1 -1
- package/backend/dist/utils/chatDocumentContext.d.ts +1 -1
- package/backend/dist/utils/chatDocumentContext.d.ts.map +1 -1
- package/backend/dist/utils/chatDocumentContext.js +9 -4
- package/backend/dist/utils/chatDocumentContext.js.map +1 -1
- package/backend/dist/utils/chatProviderSelection.d.ts.map +1 -1
- package/backend/dist/utils/generationUtils.d.ts.map +1 -1
- package/backend/dist/utils/hash.d.ts.map +1 -1
- package/backend/dist/utils/hash.js +13 -2
- package/backend/dist/utils/hash.js.map +1 -1
- package/backend/dist/utils/logger.d.ts +1 -1
- package/backend/dist/utils/logger.d.ts.map +1 -1
- package/backend/dist/utils/ollamaStreaming.d.ts +6 -2
- package/backend/dist/utils/ollamaStreaming.d.ts.map +1 -1
- package/backend/dist/utils/ollamaStreaming.js +12 -2
- package/backend/dist/utils/ollamaStreaming.js.map +1 -1
- package/backend/dist/utils/openAIResponsesAdapter.js.map +1 -1
- package/backend/dist/utils/packagePaths.js.map +1 -1
- package/backend/dist/utils/pluginChatAdapter.d.ts.map +1 -1
- package/backend/dist/utils/pluginChatAdapter.js +11 -4
- package/backend/dist/utils/pluginChatAdapter.js.map +1 -1
- package/backend/dist/utils/pluginChatContext.js.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.d.ts.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.js +2 -1
- package/backend/dist/utils/pluginDefinitionTrust.js.map +1 -1
- package/backend/dist/utils/pluginStreamAdapter.d.ts +10 -1
- package/backend/dist/utils/pluginStreamAdapter.d.ts.map +1 -1
- package/backend/dist/utils/pluginStreamAdapter.js +30 -23
- package/backend/dist/utils/pluginStreamAdapter.js.map +1 -1
- package/backend/dist/utils/pluginValidation.d.ts +4 -3
- package/backend/dist/utils/pluginValidation.d.ts.map +1 -1
- package/backend/dist/utils/pluginValidation.js +47 -2
- package/backend/dist/utils/pluginValidation.js.map +1 -1
- package/backend/dist/utils/resourceLimits.d.ts +10 -0
- package/backend/dist/utils/resourceLimits.d.ts.map +1 -0
- package/backend/dist/utils/resourceLimits.js +29 -0
- package/backend/dist/utils/resourceLimits.js.map +1 -0
- package/backend/dist/utils/thinkingPhaseTimer.d.ts +21 -0
- package/backend/dist/utils/thinkingPhaseTimer.d.ts.map +1 -0
- package/backend/dist/utils/thinkingPhaseTimer.js +84 -0
- package/backend/dist/utils/thinkingPhaseTimer.js.map +1 -0
- package/backend/dist/utils/webpageFetcher.d.ts +25 -0
- package/backend/dist/utils/webpageFetcher.d.ts.map +1 -0
- package/backend/dist/utils/webpageFetcher.js +231 -0
- package/backend/dist/utils/webpageFetcher.js.map +1 -0
- package/backend/dist/utils/websocketMessages.js.map +1 -1
- package/backend/dist/utils/workGit.d.ts +14 -0
- package/backend/dist/utils/workGit.d.ts.map +1 -0
- package/backend/dist/utils/workGit.js +207 -0
- package/backend/dist/utils/workGit.js.map +1 -0
- package/backend/dist/websocketServer.d.ts +1 -0
- package/backend/dist/websocketServer.d.ts.map +1 -1
- package/backend/dist/websocketServer.js +110 -25
- package/backend/dist/websocketServer.js.map +1 -1
- package/backend/dist/workTerminalServer.d.ts.map +1 -1
- package/backend/dist/workTerminalServer.js +3 -1
- package/backend/dist/workTerminalServer.js.map +1 -1
- package/backend/package.json +8 -7
- package/bin/cli.js +2 -2
- package/frontend/dist/assets/index-CFhy8YLA.css +1 -0
- package/frontend/dist/assets/index-_lG_lwU-.js +164 -0
- package/frontend/dist/assets/markdown-math-ClQbWekD.css +1 -0
- package/frontend/dist/assets/xterm-DHcfr8qj.css +1 -0
- package/frontend/dist/index.html +41 -16
- package/frontend/dist/js/ArtifactContainer-CjpvtR8G.js +1 -0
- package/frontend/dist/js/{ArtifactDemoPage-B4qsvUnF.js → ArtifactDemoPage-yrPXLBQo.js} +1 -1
- package/frontend/dist/js/ArtifactSlideOutPanel-DdsL2AOQ.js +1 -0
- package/frontend/dist/js/{Button-CRwzOaDZ.js → Button-X9TT9gTD.js} +1 -1
- package/frontend/dist/js/ChatPage-D9lWGM8g.js +16 -0
- package/frontend/dist/js/FirstTimeSetup-CwLPbHkI.js +1 -0
- package/frontend/dist/js/GalleryPage-C9DTdo_-.js +1 -0
- package/frontend/dist/js/HomePage-iF44c34e.js +1 -0
- package/frontend/dist/js/LibreClawPage-B9wWZIz6.js +1 -0
- package/frontend/dist/js/{ModelManagerModals-DMoEav1l.js → ModelManagerModals-D9j9RECi.js} +1 -1
- package/frontend/dist/js/ModelSelector-B0RKEJwC.js +1 -0
- package/frontend/dist/js/ModelsPage-DJXoIOs8.js +2 -0
- package/frontend/dist/js/NotesPage-BTNH6JR2.js +1 -0
- package/frontend/dist/js/{OptimizedSyntaxHighlighter-Ci9sRc78.js → OptimizedSyntaxHighlighter-CWYUn9Oe.js} +1 -1
- package/frontend/dist/js/PersonasPage--nqoJ-wA.js +13 -0
- package/frontend/dist/js/PluginUsagePage-BHwm-BBr.js +1 -0
- package/frontend/dist/js/{RichMessageContent-BJ49VN9j.js → RichMessageContent-DYRrXJ75.js} +3 -3
- package/frontend/dist/js/SettingsModal-y1Nzg55O.js +1 -0
- package/frontend/dist/js/SystemPage-CHez8h3p.js +1 -0
- package/frontend/dist/js/UserManagementPage-aJhKXQxG.js +1 -0
- package/frontend/dist/js/WorkPage-Ccla0MDm.js +5 -0
- package/frontend/dist/js/addon-fit-DIOBYJe3.js +1 -0
- package/frontend/dist/js/api-DVP8xiYT.js +19 -0
- package/frontend/dist/js/appStore-Cw7PmG-J.js +2 -0
- package/frontend/dist/js/ar-ONXFvOB1.js +2 -0
- package/frontend/dist/js/artifactHtml-C0Hu9I1u.js +41 -0
- package/frontend/dist/js/authStore-gv_MgDKr.js +3 -0
- package/frontend/dist/js/babel-CmENXdZw.js +16 -0
- package/frontend/dist/js/bn-BLhREPm6.js +2 -0
- package/frontend/dist/js/chatStore-DmDbolTg.js +2 -0
- package/frontend/dist/js/cs-Bg8E9fG5.js +2 -0
- package/frontend/dist/js/da-ODCU8w4x.js +2 -0
- package/frontend/dist/js/de-nuGHRJ5N.js +2 -0
- package/frontend/dist/js/es-DcN_cwum.js +2 -0
- package/frontend/dist/js/estree-DJwQLE88.js +44 -0
- package/frontend/dist/js/fr-C-L_xGr5.js +2 -0
- package/frontend/dist/js/hi-DUEtwA9G.js +2 -0
- package/frontend/dist/js/html-DdAOfeK4.js +25 -0
- package/frontend/dist/js/i18n-xir4Zz7C.js +2 -0
- package/frontend/dist/js/i18next-DgmgtwsV.js +1 -0
- package/frontend/dist/js/id-DNTYhti_.js +2 -0
- package/frontend/dist/js/imageGenModels-Dx_QMLJQ.js +1 -0
- package/frontend/dist/js/is-Bx28ymbQ.js +2 -0
- package/frontend/dist/js/it-BjW-JLlS.js +2 -0
- package/frontend/dist/js/ja-uThj4Q1w.js +2 -0
- package/frontend/dist/js/ko-DqgmMYXK.js +2 -0
- package/frontend/dist/js/logger-DSXjF4ye.js +1 -0
- package/frontend/dist/js/markdown-RaVsONor.js +70 -0
- package/frontend/dist/js/markdown-core-DHnR5Hw8.js +16 -0
- package/frontend/dist/js/markdown-math-B7FlYsmr.js +261 -0
- package/frontend/dist/js/messageCodeStyles-cTX0rQGK.js +2 -0
- package/frontend/dist/js/ms-R9kt_P0T.js +2 -0
- package/frontend/dist/js/nl-BjmtEgpK.js +2 -0
- package/frontend/dist/js/pl-C8_gU9r1.js +2 -0
- package/frontend/dist/js/postcss-B5WIGhAY.js +62 -0
- package/frontend/dist/js/pt-7BJForUD.js +2 -0
- package/frontend/dist/js/react-vendor-DPNXrO-8.js +9 -0
- package/frontend/dist/js/{rolldown-runtime-QTnfLwEv.js → rolldown-runtime-hePW80VL.js} +1 -1
- package/frontend/dist/js/router-vendor-Ca9zqOqT.js +1 -0
- package/frontend/dist/js/ru-D2HmhY6Y.js +2 -0
- package/frontend/dist/js/{standalone-DmLfI4Qj.js → standalone-B_aPlu7o.js} +8 -8
- package/frontend/dist/js/sv-zny3sDBM.js +2 -0
- package/frontend/dist/js/syntax-highlight-Ca9bHsaz.js +8 -0
- package/frontend/dist/js/th-CAzEKRz8.js +2 -0
- package/frontend/dist/js/tr-BmYgtmUo.js +2 -0
- package/frontend/dist/js/{typescript-Bcq62agC.js → typescript-Dz4OUZSl.js} +10 -10
- package/frontend/dist/js/ui-DDlcz2oy.js +2 -0
- package/frontend/dist/js/ui-vendor-D_pYT79f.js +177 -0
- package/frontend/dist/js/uk-eiYZ0uRq.js +2 -0
- package/frontend/dist/js/useTranslation-CdeLZqSW.js +1 -0
- package/frontend/dist/js/utils-BhpNrGnR.js +1 -0
- package/frontend/dist/js/utils-vendor-1zob7nK9.js +9 -0
- package/frontend/dist/js/vi-C7SVAWpO.js +2 -0
- package/frontend/dist/js/welcomePrompts-to5mv_gx.js +1 -0
- package/frontend/dist/js/xterm-Da5ppSVt.js +18 -0
- package/frontend/dist/js/{yaml-mLy9chOK.js → yaml-QD4znPfZ.js} +20 -20
- package/frontend/dist/js/zh-2Q3cQv3s.js +2 -0
- package/package.json +20 -13
- package/plugins/codex-oauth.json +19 -0
- package/plugins/openrouter.json +89 -0
- package/backend/dist/services/systemSettingsService.d.ts +0 -12
- package/backend/dist/services/systemSettingsService.d.ts.map +0 -1
- package/backend/dist/services/systemSettingsService.js +0 -70
- package/backend/dist/services/systemSettingsService.js.map +0 -1
- package/frontend/dist/assets/index-BqI0kezz.css +0 -1
- package/frontend/dist/assets/index-CRC6g6bL.js +0 -3
- package/frontend/dist/assets/markdown-math-CYlHEDRF.css +0 -1
- package/frontend/dist/assets/xterm-CmMoOwwu.css +0 -1
- package/frontend/dist/js/ArtifactContainer-Cdy-973y.js +0 -1
- package/frontend/dist/js/ArtifactSlideOutPanel-CmKgQ4eD.js +0 -1
- package/frontend/dist/js/ChatPage-CYT69oBR.js +0 -16
- package/frontend/dist/js/FirstTimeSetup-C8LdLP5J.js +0 -1
- package/frontend/dist/js/GalleryPage-Bm89pnS8.js +0 -1
- package/frontend/dist/js/HomePage-CeCYnMUG.js +0 -1
- package/frontend/dist/js/LibreClawPage-DGMEV6dm.js +0 -1
- package/frontend/dist/js/ModelSelector-DXPdGdQ_.js +0 -1
- package/frontend/dist/js/ModelsPage-D-FIy2x-.js +0 -2
- package/frontend/dist/js/PersonasPage-CIrEVFo5.js +0 -13
- package/frontend/dist/js/SettingsModal-CxtOXPY7.js +0 -1
- package/frontend/dist/js/UserManagementPage-BfyYGGFQ.js +0 -1
- package/frontend/dist/js/WorkPage-C7bW6Hxx.js +0 -4
- package/frontend/dist/js/addon-fit-Cj0_dfHF.js +0 -1
- package/frontend/dist/js/api-DCD41-l9.js +0 -19
- package/frontend/dist/js/appStore-Bw-8Exsx.js +0 -2
- package/frontend/dist/js/ar-BAHlIvy0.js +0 -2
- package/frontend/dist/js/artifactHtml-B7Oy2e__.js +0 -27
- package/frontend/dist/js/authStore-mOYH_AXI.js +0 -4
- package/frontend/dist/js/babel-BnLuavNv.js +0 -16
- package/frontend/dist/js/bn-BxquDVbd.js +0 -2
- package/frontend/dist/js/cs-C4DoKzRm.js +0 -2
- package/frontend/dist/js/da-CFslpGTw.js +0 -2
- package/frontend/dist/js/de-ChudoRh2.js +0 -2
- package/frontend/dist/js/demoMode-BhEpMVh5.js +0 -1
- package/frontend/dist/js/es-B36fefE-.js +0 -2
- package/frontend/dist/js/estree-0vwU39qX.js +0 -44
- package/frontend/dist/js/fr-BSVeTM5W.js +0 -2
- package/frontend/dist/js/hi-BGoFbl5V.js +0 -2
- package/frontend/dist/js/html-CApr2Bvi.js +0 -25
- package/frontend/dist/js/id-BfYs2p_j.js +0 -2
- package/frontend/dist/js/is-DZ1MS-5A.js +0 -2
- package/frontend/dist/js/it-CXtrPCG1.js +0 -2
- package/frontend/dist/js/ja-FPJ_NK_y.js +0 -2
- package/frontend/dist/js/ko-DVwD4ZZF.js +0 -2
- package/frontend/dist/js/logger-DbNs3-DK.js +0 -1
- package/frontend/dist/js/markdown-C78Qc6xu.js +0 -70
- package/frontend/dist/js/markdown-core-GI9BPwrB.js +0 -16
- package/frontend/dist/js/markdown-math-E4O1gcxj.js +0 -261
- package/frontend/dist/js/ms-PKPP0RX3.js +0 -2
- package/frontend/dist/js/nl-DWM5HJZ8.js +0 -2
- package/frontend/dist/js/pl-B9va8Tuf.js +0 -2
- package/frontend/dist/js/postcss-DSDkwgFE.js +0 -62
- package/frontend/dist/js/pt-P0IQi-Zr.js +0 -2
- package/frontend/dist/js/react-vendor-DyG_ODzn.js +0 -9
- package/frontend/dist/js/router-vendor-BjDI9mRe.js +0 -1
- package/frontend/dist/js/ru-Ca2bxYnc.js +0 -2
- package/frontend/dist/js/sv-DI4RDwyZ.js +0 -2
- package/frontend/dist/js/syntax-highlight-pM1xnNpY.js +0 -8
- package/frontend/dist/js/th-DN0bDS9d.js +0 -2
- package/frontend/dist/js/tr-ChqMv5Q4.js +0 -2
- package/frontend/dist/js/ui-vendor-DohPFHDW.js +0 -177
- package/frontend/dist/js/uk-Cr51h_XQ.js +0 -2
- package/frontend/dist/js/useBaseQuery-BAOlhjar.js +0 -1
- package/frontend/dist/js/useQuery-CcRqxveh.js +0 -1
- package/frontend/dist/js/useTranslation-Cs6iTP4m.js +0 -1
- package/frontend/dist/js/utils-DmZD5uA3.js +0 -1
- package/frontend/dist/js/utils-vendor-Cbaj0BC5.js +0 -9
- package/frontend/dist/js/vi-D4OhoVMH.js +0 -2
- package/frontend/dist/js/xterm-DKl1QLiw.js +0 -7
- package/frontend/dist/js/zh-Bvau7hlR.js +0 -2
|
@@ -19,13 +19,17 @@ import path from 'path';
|
|
|
19
19
|
import { createHash } from 'crypto';
|
|
20
20
|
import sanitize from 'sanitize-filename';
|
|
21
21
|
import axios from 'axios';
|
|
22
|
+
import codexOAuthService, { CODEX_OAUTH_PLUGIN_ID, } from './codexOAuthService.js';
|
|
23
|
+
import { userModel } from '../models/userModel.js';
|
|
22
24
|
import pluginCredentialsService from './pluginCredentialsService.js';
|
|
23
25
|
import pluginVariablesService from './pluginVariablesService.js';
|
|
24
26
|
import pluginActivationService from './pluginActivationService.js';
|
|
27
|
+
import { PluginAudioGenerationService } from './pluginAudioGenerationService.js';
|
|
25
28
|
import { PluginCapabilityRegistryService } from './pluginCapabilityRegistryService.js';
|
|
26
29
|
import { PluginEmbeddingService } from './pluginEmbeddingService.js';
|
|
27
30
|
import { PluginImageGenerationService } from './pluginImageGenerationService.js';
|
|
28
31
|
import { PluginTTSService } from './pluginTTSService.js';
|
|
32
|
+
import { PluginVideoGenerationService } from './pluginVideoGenerationService.js';
|
|
29
33
|
import { applyPluginDefinitionPolicy, buildPluginChatPayload, convertProviderResponse, getOpenAICompatibleSamplingParameters, resolvePluginChatParameters, toOpenAICompatibleMessages, } from '../utils/pluginChatAdapter.js';
|
|
30
34
|
import { streamAnthropicResponse, streamOpenAICompatibleResponse, streamOpenAIResponsesResponse, } from '../utils/pluginStreamAdapter.js';
|
|
31
35
|
import { applyModelEndpointTemplate, assertSafePluginEndpoint, buildPluginAuthHeaders, buildPluginModelDiscoveryHeaders, pluginRequiresApiKey, resolvePluginApiConfig, resolvePluginEndpoint, resolvePluginModelsEndpoint, validatePluginModel, } from '../utils/pluginValidation.js';
|
|
@@ -34,6 +38,7 @@ import { resolveBundledPluginsDir } from '../utils/packagePaths.js';
|
|
|
34
38
|
import { getDatabaseSafe } from '../db.js';
|
|
35
39
|
import { createOpenAIResponsesStateScope, createPluginCredentialFingerprint, OPENAI_RESPONSES_INCOMPLETE_REASON_METADATA_KEY, } from '../utils/openAIResponsesAdapter.js';
|
|
36
40
|
import { getPluginConnectionVariableNames } from '../utils/pluginConnectionVariables.js';
|
|
41
|
+
import pluginUsageService from './pluginUsageService.js';
|
|
37
42
|
import { getPluginDefinitionFingerprint, matchesBundledPluginTrustAnchor, } from '../utils/pluginDefinitionTrust.js';
|
|
38
43
|
const logger = createLogger('plugins');
|
|
39
44
|
const readPositiveIntEnv = (name, fallback) => {
|
|
@@ -77,6 +82,7 @@ function getPluginRoutingAuthProjection(plugin) {
|
|
|
77
82
|
return {
|
|
78
83
|
name,
|
|
79
84
|
endpoint: capability.endpoint ?? null,
|
|
85
|
+
models_endpoint: capability.models_endpoint ?? null,
|
|
80
86
|
endpoint_variable: config.endpoint_variable ?? capability.endpoint_variable ?? null,
|
|
81
87
|
};
|
|
82
88
|
});
|
|
@@ -118,6 +124,10 @@ export class PluginService {
|
|
|
118
124
|
this.discoveredModelsUpdatedAt = new Map();
|
|
119
125
|
this.discoveryAttemptedAt = new Map();
|
|
120
126
|
this.inflightDiscovery = new Map();
|
|
127
|
+
this.discoveredCapabilityModelsCache = new Map();
|
|
128
|
+
this.discoveredCapabilityModelsUpdatedAt = new Map();
|
|
129
|
+
this.capabilityDiscoveryAttemptedAt = new Map();
|
|
130
|
+
this.inflightCapabilityDiscovery = new Map();
|
|
121
131
|
this.bundledRoutingProjectionCache = new Map();
|
|
122
132
|
this.bundledPluginsDir = resolveBundledPluginsDir(import.meta.url);
|
|
123
133
|
this.legacyPluginsDir = path.join(process.cwd(), 'plugins');
|
|
@@ -134,6 +144,7 @@ export class PluginService {
|
|
|
134
144
|
getApiKey: (plugin, userId) => this.getApiKey(plugin, userId),
|
|
135
145
|
getPluginVariables: (plugin, userId) => this.getPluginVariables(plugin, userId),
|
|
136
146
|
validateEndpointUrl: endpoint => this.validateEndpointUrl(endpoint),
|
|
147
|
+
recordUsage: usage => pluginUsageService.record(usage),
|
|
137
148
|
});
|
|
138
149
|
this.ttsService = new PluginTTSService({
|
|
139
150
|
getAllPlugins: userId => this.getActivePlugins(userId),
|
|
@@ -141,6 +152,7 @@ export class PluginService {
|
|
|
141
152
|
getApiKey: (plugin, userId) => this.getApiKey(plugin, userId),
|
|
142
153
|
getPluginVariables: (plugin, userId) => this.getPluginVariables(plugin, userId),
|
|
143
154
|
validateEndpointUrl: endpoint => this.validateEndpointUrl(endpoint),
|
|
155
|
+
recordUsage: usage => pluginUsageService.record(usage),
|
|
144
156
|
});
|
|
145
157
|
this.imageGenerationService = new PluginImageGenerationService({
|
|
146
158
|
getAllPlugins: userId => this.getActivePlugins(userId),
|
|
@@ -148,6 +160,23 @@ export class PluginService {
|
|
|
148
160
|
getApiKey: (plugin, userId) => this.getApiKey(plugin, userId),
|
|
149
161
|
getPluginVariables: (plugin, userId) => this.getPluginVariables(plugin, userId),
|
|
150
162
|
validateEndpointUrl: endpoint => this.validateEndpointUrl(endpoint),
|
|
163
|
+
recordUsage: usage => pluginUsageService.record(usage),
|
|
164
|
+
});
|
|
165
|
+
this.audioGenerationService = new PluginAudioGenerationService({
|
|
166
|
+
getAllPlugins: userId => this.getActivePlugins(userId),
|
|
167
|
+
getPlugin: (id, userId) => this.getPlugin(id, userId),
|
|
168
|
+
getApiKey: (plugin, userId) => this.getApiKey(plugin, userId),
|
|
169
|
+
getPluginVariables: (plugin, userId) => this.getPluginVariables(plugin, userId),
|
|
170
|
+
validateEndpointUrl: endpoint => this.validateEndpointUrl(endpoint),
|
|
171
|
+
recordUsage: usage => pluginUsageService.record(usage),
|
|
172
|
+
});
|
|
173
|
+
this.videoGenerationService = new PluginVideoGenerationService({
|
|
174
|
+
getAllPlugins: userId => this.getActivePlugins(userId),
|
|
175
|
+
getPlugin: (id, userId) => this.getPlugin(id, userId),
|
|
176
|
+
getApiKey: (plugin, userId) => this.getApiKey(plugin, userId),
|
|
177
|
+
getPluginVariables: (plugin, userId) => this.getPluginVariables(plugin, userId),
|
|
178
|
+
validateEndpointUrl: endpoint => this.validateEndpointUrl(endpoint),
|
|
179
|
+
recordUsage: usage => pluginUsageService.record(usage),
|
|
151
180
|
});
|
|
152
181
|
this.capabilityRegistryService = new PluginCapabilityRegistryService({
|
|
153
182
|
getAllPlugins: userId => this.getActivePlugins(userId),
|
|
@@ -157,6 +186,65 @@ export class PluginService {
|
|
|
157
186
|
discoveredModelsCacheKey(pluginId, userId) {
|
|
158
187
|
return `${userId}:${pluginId}`;
|
|
159
188
|
}
|
|
189
|
+
discoveredCapabilityModelsCacheKey(pluginId, capability, userId) {
|
|
190
|
+
return `${userId}:${pluginId}:${capability}`;
|
|
191
|
+
}
|
|
192
|
+
getDiscoveredCapabilityModels(pluginId, capability, userId) {
|
|
193
|
+
const effectiveUserId = userId || 'default';
|
|
194
|
+
const cacheKey = this.discoveredCapabilityModelsCacheKey(pluginId, capability, effectiveUserId);
|
|
195
|
+
if (this.discoveredCapabilityModelsCache.has(cacheKey)) {
|
|
196
|
+
return this.discoveredCapabilityModelsCache.get(cacheKey) || undefined;
|
|
197
|
+
}
|
|
198
|
+
const db = getDatabaseSafe();
|
|
199
|
+
if (!db) {
|
|
200
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, null);
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const row = db
|
|
205
|
+
.prepare(`SELECT models_json, updated_at
|
|
206
|
+
FROM plugin_discovered_capability_models
|
|
207
|
+
WHERE user_id = ? AND plugin_id = ? AND capability = ?`)
|
|
208
|
+
.get(effectiveUserId, pluginId, capability);
|
|
209
|
+
if (!row) {
|
|
210
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, null);
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
const parsed = JSON.parse(row.models_json);
|
|
214
|
+
const models = Array.isArray(parsed)
|
|
215
|
+
? Array.from(new Set(parsed.filter((model) => typeof model === 'string' && model.length > 0)))
|
|
216
|
+
: [];
|
|
217
|
+
if (models.length === 0) {
|
|
218
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, null);
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, models);
|
|
222
|
+
this.discoveredCapabilityModelsUpdatedAt.set(cacheKey, row.updated_at);
|
|
223
|
+
return models;
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
logger.warn('Failed to read discovered %s models for plugin %s:', capability, pluginId, error);
|
|
227
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, null);
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
storeDiscoveredCapabilityModels(pluginId, capability, models, userId) {
|
|
232
|
+
const effectiveUserId = userId || 'default';
|
|
233
|
+
const uniqueModels = Array.from(new Set(models));
|
|
234
|
+
const cacheKey = this.discoveredCapabilityModelsCacheKey(pluginId, capability, effectiveUserId);
|
|
235
|
+
const discoveredAt = Date.now();
|
|
236
|
+
this.discoveredCapabilityModelsCache.set(cacheKey, uniqueModels);
|
|
237
|
+
this.discoveredCapabilityModelsUpdatedAt.set(cacheKey, discoveredAt);
|
|
238
|
+
const db = getDatabaseSafe();
|
|
239
|
+
if (!db)
|
|
240
|
+
return;
|
|
241
|
+
db.prepare(`INSERT INTO plugin_discovered_capability_models
|
|
242
|
+
(user_id, plugin_id, capability, models_json, updated_at)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?)
|
|
244
|
+
ON CONFLICT(user_id, plugin_id, capability) DO UPDATE SET
|
|
245
|
+
models_json = excluded.models_json,
|
|
246
|
+
updated_at = excluded.updated_at`).run(effectiveUserId, pluginId, capability, JSON.stringify(uniqueModels), discoveredAt);
|
|
247
|
+
}
|
|
160
248
|
getDiscoveredModels(pluginId, userId) {
|
|
161
249
|
const effectiveUserId = userId || 'default';
|
|
162
250
|
const cacheKey = this.discoveredModelsCacheKey(pluginId, effectiveUserId);
|
|
@@ -219,6 +307,7 @@ export class PluginService {
|
|
|
219
307
|
}
|
|
220
308
|
}
|
|
221
309
|
clearDiscoveredModels(pluginId, userId) {
|
|
310
|
+
this.clearDiscoveredCapabilityModels(pluginId, userId);
|
|
222
311
|
const db = getDatabaseSafe();
|
|
223
312
|
if (userId) {
|
|
224
313
|
const cacheKey = this.discoveredModelsCacheKey(pluginId, userId);
|
|
@@ -251,13 +340,58 @@ export class PluginService {
|
|
|
251
340
|
logger.warn('Failed to clear discovered models for plugin %s:', pluginId, error);
|
|
252
341
|
}
|
|
253
342
|
}
|
|
343
|
+
clearDiscoveredCapabilityModels(pluginId, userId) {
|
|
344
|
+
const db = getDatabaseSafe();
|
|
345
|
+
if (userId) {
|
|
346
|
+
for (const capability of ['image', 'tts', 'audio', 'video']) {
|
|
347
|
+
const key = this.discoveredCapabilityModelsCacheKey(pluginId, capability, userId);
|
|
348
|
+
this.discoveredCapabilityModelsCache.delete(key);
|
|
349
|
+
this.discoveredCapabilityModelsUpdatedAt.delete(key);
|
|
350
|
+
this.capabilityDiscoveryAttemptedAt.delete(key);
|
|
351
|
+
}
|
|
352
|
+
if (db) {
|
|
353
|
+
db.prepare(`DELETE FROM plugin_discovered_capability_models
|
|
354
|
+
WHERE user_id = ? AND plugin_id = ?`).run(userId, pluginId);
|
|
355
|
+
}
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
for (const key of this.discoveredCapabilityModelsCache.keys()) {
|
|
359
|
+
if (['image', 'tts', 'audio', 'video'].some(capability => key.endsWith(`:${pluginId}:${capability}`))) {
|
|
360
|
+
this.discoveredCapabilityModelsCache.delete(key);
|
|
361
|
+
this.discoveredCapabilityModelsUpdatedAt.delete(key);
|
|
362
|
+
this.capabilityDiscoveryAttemptedAt.delete(key);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (db) {
|
|
366
|
+
db.prepare('DELETE FROM plugin_discovered_capability_models WHERE plugin_id = ?').run(pluginId);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
254
369
|
applyDiscoveredModels(plugin, userId) {
|
|
255
370
|
if (!this.canUseStoredConnectionOverrides(userId) &&
|
|
256
371
|
pluginVariablesService.hasStoredConnectionOverride(plugin.id, userId, plugin.variables, getPluginConnectionVariableNames(plugin))) {
|
|
257
372
|
return plugin;
|
|
258
373
|
}
|
|
259
374
|
const models = this.getDiscoveredModels(plugin.id, userId);
|
|
260
|
-
|
|
375
|
+
const capabilities = plugin.capabilities
|
|
376
|
+
? { ...plugin.capabilities }
|
|
377
|
+
: undefined;
|
|
378
|
+
if (capabilities) {
|
|
379
|
+
for (const capability of ['image', 'tts', 'audio', 'video']) {
|
|
380
|
+
const definition = capabilities[capability];
|
|
381
|
+
const discovered = this.getDiscoveredCapabilityModels(plugin.id, capability, userId);
|
|
382
|
+
if (definition && discovered) {
|
|
383
|
+
capabilities[capability] = {
|
|
384
|
+
...definition,
|
|
385
|
+
model_map: [...discovered],
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return {
|
|
391
|
+
...plugin,
|
|
392
|
+
...(models ? { model_map: [...models] } : {}),
|
|
393
|
+
...(capabilities ? { capabilities } : {}),
|
|
394
|
+
};
|
|
261
395
|
}
|
|
262
396
|
ensurePluginsDirectory() {
|
|
263
397
|
if (!fs.existsSync(this.pluginsDir)) {
|
|
@@ -420,6 +554,15 @@ export class PluginService {
|
|
|
420
554
|
* @returns The API key or null if not found
|
|
421
555
|
*/
|
|
422
556
|
getApiKey(plugin, userId) {
|
|
557
|
+
if (plugin.id === CODEX_OAUTH_PLUGIN_ID) {
|
|
558
|
+
// Resolved from the server's Codex CLI sign-in, never user credentials.
|
|
559
|
+
// A writable same-ID definition must never receive the server user's
|
|
560
|
+
// OAuth bearer token, even when an administrator approved that file.
|
|
561
|
+
return this.usesTrustedBundledRouting(plugin) &&
|
|
562
|
+
matchesBundledPluginTrustAnchor(plugin)
|
|
563
|
+
? codexOAuthService.getCachedAccessToken()
|
|
564
|
+
: null;
|
|
565
|
+
}
|
|
423
566
|
const hasHonoredConnectionOverride = this.canUseStoredConnectionOverrides(userId) &&
|
|
424
567
|
pluginVariablesService.hasStoredConnectionOverride(plugin.id, userId, plugin.variables, getPluginConnectionVariableNames(plugin));
|
|
425
568
|
const usesTrustedBundledRouting = this.usesTrustedBundledRouting(plugin);
|
|
@@ -566,6 +709,98 @@ export class PluginService {
|
|
|
566
709
|
new Promise(resolve => setTimeout(resolve, modelDiscoveryRefreshDeadlineMs()).unref?.()),
|
|
567
710
|
]);
|
|
568
711
|
}
|
|
712
|
+
async discoverCapabilityModels(pluginId, capability, userId) {
|
|
713
|
+
const cacheKey = this.discoveredCapabilityModelsCacheKey(pluginId, capability, userId || 'default');
|
|
714
|
+
const inflight = this.inflightCapabilityDiscovery.get(cacheKey);
|
|
715
|
+
if (inflight)
|
|
716
|
+
return inflight;
|
|
717
|
+
const attempt = this.runCapabilityModelDiscovery(pluginId, capability, userId).finally(() => this.inflightCapabilityDiscovery.delete(cacheKey));
|
|
718
|
+
this.inflightCapabilityDiscovery.set(cacheKey, attempt);
|
|
719
|
+
return attempt;
|
|
720
|
+
}
|
|
721
|
+
isCapabilityModelDiscoveryDue(pluginId, capability, userId) {
|
|
722
|
+
const cacheKey = this.discoveredCapabilityModelsCacheKey(pluginId, capability, userId || 'default');
|
|
723
|
+
const attemptedAt = this.capabilityDiscoveryAttemptedAt.get(cacheKey);
|
|
724
|
+
if (attemptedAt && Date.now() - attemptedAt < modelDiscoveryRetryMs()) {
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
const models = this.getDiscoveredCapabilityModels(pluginId, capability, userId);
|
|
728
|
+
const updatedAt = this.discoveredCapabilityModelsUpdatedAt.get(cacheKey);
|
|
729
|
+
return (!models || !updatedAt || Date.now() - updatedAt >= modelDiscoveryTtlMs());
|
|
730
|
+
}
|
|
731
|
+
async refreshStaleCapabilityModels(capability, userId) {
|
|
732
|
+
const due = this.getActivePlugins(userId).filter(plugin => {
|
|
733
|
+
const definition = plugin.capabilities?.[capability];
|
|
734
|
+
return (Boolean(definition?.models_endpoint) &&
|
|
735
|
+
this.isCapabilityModelDiscoveryDue(plugin.id, capability, userId));
|
|
736
|
+
});
|
|
737
|
+
if (due.length === 0)
|
|
738
|
+
return;
|
|
739
|
+
const refreshes = Promise.all(due.map(plugin => this.discoverCapabilityModels(plugin.id, capability, userId).catch(() => undefined)));
|
|
740
|
+
await Promise.race([
|
|
741
|
+
refreshes,
|
|
742
|
+
new Promise(resolve => setTimeout(resolve, modelDiscoveryRefreshDeadlineMs()).unref?.()),
|
|
743
|
+
]);
|
|
744
|
+
}
|
|
745
|
+
async runCapabilityModelDiscovery(pluginId, capability, userId) {
|
|
746
|
+
const plugin = this.getPlugin(pluginId, userId);
|
|
747
|
+
const definition = plugin?.capabilities?.[capability];
|
|
748
|
+
if (!plugin || !definition) {
|
|
749
|
+
return {
|
|
750
|
+
models: [],
|
|
751
|
+
outcome: 'unavailable',
|
|
752
|
+
reason: `Plugin has no ${capability} capability`,
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
if (!definition.models_endpoint) {
|
|
756
|
+
return { models: definition.model_map, outcome: 'unchanged' };
|
|
757
|
+
}
|
|
758
|
+
const cacheKey = this.discoveredCapabilityModelsCacheKey(pluginId, capability, userId || 'default');
|
|
759
|
+
this.capabilityDiscoveryAttemptedAt.set(cacheKey, Date.now());
|
|
760
|
+
const modelsEndpoint = definition.models_endpoint;
|
|
761
|
+
assertSafePluginEndpoint(modelsEndpoint, `${capability} model discovery endpoint`);
|
|
762
|
+
const apiKey = this.getApiKey(plugin, userId);
|
|
763
|
+
if (pluginRequiresApiKey(plugin) && !apiKey) {
|
|
764
|
+
return {
|
|
765
|
+
models: definition.model_map,
|
|
766
|
+
outcome: 'missing_credentials',
|
|
767
|
+
reason: this.describeMissingCredential(plugin),
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
try {
|
|
771
|
+
const response = await axios.get(modelsEndpoint, {
|
|
772
|
+
headers: buildPluginModelDiscoveryHeaders(plugin, apiKey, modelsEndpoint),
|
|
773
|
+
timeout: MODEL_DISCOVERY_REQUEST_TIMEOUT_MS,
|
|
774
|
+
maxRedirects: 0,
|
|
775
|
+
});
|
|
776
|
+
const data = response.data?.data;
|
|
777
|
+
const models = Array.isArray(data)
|
|
778
|
+
? Array.from(new Set(data
|
|
779
|
+
.map((entry) => entry?.id)
|
|
780
|
+
.filter((id) => typeof id === 'string' && id.length > 0)))
|
|
781
|
+
: [];
|
|
782
|
+
if (models.length === 0) {
|
|
783
|
+
return {
|
|
784
|
+
models: definition.model_map,
|
|
785
|
+
outcome: 'unavailable',
|
|
786
|
+
reason: 'The provider returned no models',
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
const previous = definition.model_map;
|
|
790
|
+
this.storeDiscoveredCapabilityModels(pluginId, capability, models, userId);
|
|
791
|
+
return {
|
|
792
|
+
models,
|
|
793
|
+
outcome: JSON.stringify(previous) === JSON.stringify(models)
|
|
794
|
+
? 'unchanged'
|
|
795
|
+
: 'updated',
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
const reason = describeModelDiscoveryFailure(error);
|
|
800
|
+
logger.debug('[Plugin] %s model discovery unavailable for %s (%s)', capability, pluginId, reason);
|
|
801
|
+
return { models: definition.model_map, outcome: 'unavailable', reason };
|
|
802
|
+
}
|
|
803
|
+
}
|
|
569
804
|
/**
|
|
570
805
|
* Say why no key was usable. An environment key is deliberately ignored for a
|
|
571
806
|
* provider whose definition was installed into the writable plugins directory,
|
|
@@ -602,7 +837,7 @@ export class PluginService {
|
|
|
602
837
|
reason: this.describeMissingCredential(plugin),
|
|
603
838
|
};
|
|
604
839
|
}
|
|
605
|
-
const headers = buildPluginModelDiscoveryHeaders(plugin, apiKey);
|
|
840
|
+
const headers = buildPluginModelDiscoveryHeaders(plugin, apiKey, modelsEndpoint);
|
|
606
841
|
try {
|
|
607
842
|
const response = await axios.get(modelsEndpoint, {
|
|
608
843
|
headers,
|
|
@@ -689,7 +924,20 @@ export class PluginService {
|
|
|
689
924
|
logger.error(`Failed to read plugins directory ${pluginsDir}:`, error);
|
|
690
925
|
}
|
|
691
926
|
}
|
|
692
|
-
return Array.from(plugins.values());
|
|
927
|
+
return Array.from(plugins.values()).filter(plugin => this.isPluginVisibleToUser(plugin, userId));
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* The codex-oauth plugin rides the server user's ChatGPT sign-in, so it is
|
|
931
|
+
* administrator-only and hidden entirely when no sign-in exists.
|
|
932
|
+
*/
|
|
933
|
+
isPluginVisibleToUser(plugin, userId) {
|
|
934
|
+
if (plugin.id !== CODEX_OAUTH_PLUGIN_ID)
|
|
935
|
+
return true;
|
|
936
|
+
if (!codexOAuthService.isAvailable())
|
|
937
|
+
return false;
|
|
938
|
+
if (!userId)
|
|
939
|
+
return false;
|
|
940
|
+
return userModel.getUserById(userId)?.role === 'admin';
|
|
693
941
|
}
|
|
694
942
|
// Get a specific plugin by ID
|
|
695
943
|
getPlugin(id, userId) {
|
|
@@ -707,7 +955,8 @@ export class PluginService {
|
|
|
707
955
|
const parsedPlugin = JSON.parse(content);
|
|
708
956
|
if (this.validatePlugin(parsedPlugin) &&
|
|
709
957
|
parsedPlugin.id === sanitizedId &&
|
|
710
|
-
this.isPluginDefinitionApproved(parsedPlugin, filePath)
|
|
958
|
+
this.isPluginDefinitionApproved(parsedPlugin, filePath) &&
|
|
959
|
+
this.isPluginVisibleToUser(parsedPlugin, userId)) {
|
|
711
960
|
const plugin = applyPluginDefinitionPolicy(parsedPlugin);
|
|
712
961
|
plugin.active = this.isPluginActive(plugin.id, userId);
|
|
713
962
|
return this.applyDiscoveredModels(plugin, userId);
|
|
@@ -723,6 +972,9 @@ export class PluginService {
|
|
|
723
972
|
if (!this.validatePlugin(pluginData)) {
|
|
724
973
|
throw new Error('Invalid plugin structure');
|
|
725
974
|
}
|
|
975
|
+
if (pluginData.id === CODEX_OAUTH_PLUGIN_ID) {
|
|
976
|
+
throw new Error('The bundled Codex OAuth plugin ID is reserved');
|
|
977
|
+
}
|
|
726
978
|
if (!this.canUseStoredConnectionOverrides(approvedByUserId)) {
|
|
727
979
|
throw new Error('Administrator approval is required');
|
|
728
980
|
}
|
|
@@ -810,7 +1062,12 @@ export class PluginService {
|
|
|
810
1062
|
}
|
|
811
1063
|
// Wait for discovery so the activation response and the UI's first reload
|
|
812
1064
|
// observe the same user-scoped model catalog.
|
|
813
|
-
await
|
|
1065
|
+
await Promise.all([
|
|
1066
|
+
this.discoverModels(id, userId).catch(() => []),
|
|
1067
|
+
...['image', 'tts', 'audio', 'video']
|
|
1068
|
+
.filter(capability => plugin.capabilities?.[capability]?.models_endpoint)
|
|
1069
|
+
.map(capability => this.discoverCapabilityModels(id, capability, userId).catch(() => undefined)),
|
|
1070
|
+
]);
|
|
814
1071
|
return true;
|
|
815
1072
|
}
|
|
816
1073
|
// Deactivate a specific plugin
|
|
@@ -886,6 +1143,20 @@ export class PluginService {
|
|
|
886
1143
|
if (!activePlugin.model_map.includes(model)) {
|
|
887
1144
|
throw new Error(`Model ${model} is not supported by plugin ${activePlugin.id}`);
|
|
888
1145
|
}
|
|
1146
|
+
if (activePlugin.id === CODEX_OAUTH_PLUGIN_ID) {
|
|
1147
|
+
await codexOAuthService.ensureFreshToken();
|
|
1148
|
+
// The codex endpoint only answers as an SSE stream; aggregate it here
|
|
1149
|
+
// so non-streaming callers still get a complete response.
|
|
1150
|
+
let aggregated = '';
|
|
1151
|
+
for await (const chunk of this.executePluginStreamRequest(model, messages, options, userId, activePlugin.id)) {
|
|
1152
|
+
if (chunk.type === 'content' && chunk.content) {
|
|
1153
|
+
aggregated += chunk.content;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return {
|
|
1157
|
+
choices: [{ message: { role: 'assistant', content: aggregated } }],
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
889
1160
|
const pluginVars = this.getPluginVariables(activePlugin, userId);
|
|
890
1161
|
const { apiMode, endpoint: effectiveEndpoint } = resolvePluginApiConfig(activePlugin, pluginVars);
|
|
891
1162
|
const processedEndpoint = applyModelEndpointTemplate(effectiveEndpoint, model);
|
|
@@ -897,18 +1168,45 @@ export class PluginService {
|
|
|
897
1168
|
const providerStateScope = apiMode === 'responses'
|
|
898
1169
|
? createOpenAIResponsesStateScope(activePlugin.id, model, processedEndpoint, createPluginCredentialFingerprint(apiKey))
|
|
899
1170
|
: undefined;
|
|
900
|
-
const headers = buildPluginAuthHeaders(activePlugin, apiKey);
|
|
1171
|
+
const headers = buildPluginAuthHeaders(activePlugin, apiKey, processedEndpoint);
|
|
901
1172
|
const { payload, headers: payloadHeaders } = buildPluginChatPayload(activePlugin, model, messages, options, pluginVars, false, apiMode, providerStateScope);
|
|
902
1173
|
Object.assign(headers, payloadHeaders);
|
|
1174
|
+
const startedAt = Date.now();
|
|
903
1175
|
try {
|
|
904
1176
|
const response = await axios.post(processedEndpoint, payload, {
|
|
905
1177
|
headers,
|
|
906
1178
|
timeout: 60000, // 60 second timeout
|
|
907
1179
|
maxRedirects: 0,
|
|
908
1180
|
});
|
|
909
|
-
|
|
1181
|
+
const normalized = convertProviderResponse(activePlugin, response.data, model, apiMode, providerStateScope);
|
|
1182
|
+
pluginUsageService.record({
|
|
1183
|
+
userId,
|
|
1184
|
+
pluginId: activePlugin.id,
|
|
1185
|
+
pluginName: activePlugin.name,
|
|
1186
|
+
capability: 'chat',
|
|
1187
|
+
model,
|
|
1188
|
+
status: 'success',
|
|
1189
|
+
durationMs: Date.now() - startedAt,
|
|
1190
|
+
tokens: normalized.usage
|
|
1191
|
+
? {
|
|
1192
|
+
promptTokens: normalized.usage.prompt_tokens,
|
|
1193
|
+
completionTokens: normalized.usage.completion_tokens,
|
|
1194
|
+
totalTokens: normalized.usage.total_tokens,
|
|
1195
|
+
}
|
|
1196
|
+
: undefined,
|
|
1197
|
+
});
|
|
1198
|
+
return normalized;
|
|
910
1199
|
}
|
|
911
1200
|
catch (error) {
|
|
1201
|
+
pluginUsageService.record({
|
|
1202
|
+
userId,
|
|
1203
|
+
pluginId: activePlugin.id,
|
|
1204
|
+
pluginName: activePlugin.name,
|
|
1205
|
+
capability: 'chat',
|
|
1206
|
+
model,
|
|
1207
|
+
status: 'error',
|
|
1208
|
+
durationMs: Date.now() - startedAt,
|
|
1209
|
+
});
|
|
912
1210
|
logger.error(`Plugin request failed for ${activePlugin.id}:`, error);
|
|
913
1211
|
if (error && typeof error === 'object' && 'response' in error) {
|
|
914
1212
|
const axiosError = error;
|
|
@@ -937,6 +1235,9 @@ export class PluginService {
|
|
|
937
1235
|
if (!activePlugin.model_map.includes(model)) {
|
|
938
1236
|
throw new Error(`Model ${model} is not supported by plugin ${activePlugin.id}`);
|
|
939
1237
|
}
|
|
1238
|
+
if (activePlugin.id === CODEX_OAUTH_PLUGIN_ID) {
|
|
1239
|
+
await codexOAuthService.ensureFreshToken();
|
|
1240
|
+
}
|
|
940
1241
|
const pluginVars = this.getPluginVariables(activePlugin, userId);
|
|
941
1242
|
const { apiMode, endpoint: effectiveEndpoint } = resolvePluginApiConfig(activePlugin, pluginVars);
|
|
942
1243
|
const processedEndpoint = applyModelEndpointTemplate(effectiveEndpoint, model);
|
|
@@ -948,7 +1249,7 @@ export class PluginService {
|
|
|
948
1249
|
const providerStateScope = apiMode === 'responses'
|
|
949
1250
|
? createOpenAIResponsesStateScope(activePlugin.id, model, processedEndpoint, createPluginCredentialFingerprint(apiKey))
|
|
950
1251
|
: undefined;
|
|
951
|
-
const headers = buildPluginAuthHeaders(activePlugin, apiKey);
|
|
1252
|
+
const headers = buildPluginAuthHeaders(activePlugin, apiKey, processedEndpoint);
|
|
952
1253
|
let payload;
|
|
953
1254
|
if (activePlugin.id === 'anthropic' || apiMode === 'responses') {
|
|
954
1255
|
const pluginRequest = buildPluginChatPayload(activePlugin, model, messages, options, pluginVars, true, apiMode, providerStateScope);
|
|
@@ -966,77 +1267,128 @@ export class PluginService {
|
|
|
966
1267
|
stream: true,
|
|
967
1268
|
};
|
|
968
1269
|
}
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1270
|
+
const startedAt = Date.now();
|
|
1271
|
+
let status = 'cancelled';
|
|
1272
|
+
let tokenUsage;
|
|
1273
|
+
const captureUsage = (chunk) => {
|
|
1274
|
+
if (chunk.type !== 'usage' || !chunk.usage)
|
|
1275
|
+
return;
|
|
1276
|
+
const { promptTokens, completionTokens, totalTokens } = chunk.usage;
|
|
1277
|
+
if (promptTokens === undefined &&
|
|
1278
|
+
completionTokens === undefined &&
|
|
1279
|
+
totalTokens === undefined) {
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
const prompt = promptTokens ?? 0;
|
|
1283
|
+
const completion = completionTokens ?? 0;
|
|
1284
|
+
tokenUsage = {
|
|
1285
|
+
promptTokens: prompt,
|
|
1286
|
+
completionTokens: completion,
|
|
1287
|
+
totalTokens: totalTokens ?? prompt + completion,
|
|
1288
|
+
};
|
|
1289
|
+
};
|
|
1290
|
+
const forward = async function* (chunks) {
|
|
1291
|
+
for await (const chunk of chunks) {
|
|
1292
|
+
captureUsage(chunk);
|
|
1293
|
+
yield chunk;
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
try {
|
|
1297
|
+
const response = await fetch(processedEndpoint, {
|
|
1298
|
+
method: 'POST',
|
|
1299
|
+
headers,
|
|
1300
|
+
body: JSON.stringify(payload),
|
|
1301
|
+
redirect: 'error',
|
|
1302
|
+
});
|
|
1303
|
+
if (activePlugin.id === 'anthropic') {
|
|
1304
|
+
yield* forward(streamAnthropicResponse(response));
|
|
1305
|
+
}
|
|
1306
|
+
else if (apiMode === 'responses') {
|
|
1307
|
+
const contentType = response.headers.get('content-type') || '';
|
|
1308
|
+
// The codex endpoint streams SSE without any content-type header.
|
|
1309
|
+
const streamedAnyway = activePlugin.id === CODEX_OAUTH_PLUGIN_ID && response.ok;
|
|
1310
|
+
if (!contentType.includes('text/event-stream') && !streamedAnyway) {
|
|
1311
|
+
if (!response.ok) {
|
|
1312
|
+
const errorText = await response.text();
|
|
1313
|
+
throw new Error(`Plugin API error: ${response.status} - ${errorText.slice(0, 200)}`);
|
|
1314
|
+
}
|
|
1315
|
+
const normalized = convertProviderResponse(activePlugin, (await response.json()), model, apiMode, providerStateScope);
|
|
1316
|
+
const choice = normalized.choices[0];
|
|
1317
|
+
const message = choice?.message;
|
|
1318
|
+
if (typeof message?.content === 'string' && message.content) {
|
|
1319
|
+
yield { type: 'content', content: message.content };
|
|
1320
|
+
}
|
|
1321
|
+
if (typeof message?.reasoning_content === 'string' &&
|
|
1322
|
+
message.reasoning_content) {
|
|
1323
|
+
yield {
|
|
1324
|
+
type: 'reasoning',
|
|
1325
|
+
content: message.reasoning_content,
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
for (const call of message?.tool_calls || []) {
|
|
1329
|
+
yield {
|
|
1330
|
+
type: 'tool_call',
|
|
1331
|
+
toolCall: {
|
|
1332
|
+
id: call.id,
|
|
1333
|
+
name: call.function.name,
|
|
1334
|
+
arguments: call.function.arguments,
|
|
1335
|
+
...(call.providerMetadata
|
|
1336
|
+
? { providerMetadata: call.providerMetadata }
|
|
1337
|
+
: {}),
|
|
1338
|
+
},
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
if (normalized.usage) {
|
|
1342
|
+
const usageChunk = {
|
|
1343
|
+
type: 'usage',
|
|
1344
|
+
usage: {
|
|
1345
|
+
promptTokens: normalized.usage.prompt_tokens,
|
|
1346
|
+
completionTokens: normalized.usage.completion_tokens,
|
|
1347
|
+
totalTokens: normalized.usage.total_tokens,
|
|
1348
|
+
},
|
|
1349
|
+
};
|
|
1350
|
+
captureUsage(usageChunk);
|
|
1351
|
+
yield usageChunk;
|
|
1352
|
+
}
|
|
1353
|
+
const incompleteReason = typeof normalized.providerMetadata?.[OPENAI_RESPONSES_INCOMPLETE_REASON_METADATA_KEY] === 'string'
|
|
1354
|
+
? normalized.providerMetadata[OPENAI_RESPONSES_INCOMPLETE_REASON_METADATA_KEY]
|
|
1355
|
+
: undefined;
|
|
999
1356
|
yield {
|
|
1000
|
-
type: '
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
: {}),
|
|
1008
|
-
},
|
|
1357
|
+
type: 'done',
|
|
1358
|
+
...(incompleteReason
|
|
1359
|
+
? { doneReason: `incomplete:${incompleteReason}` }
|
|
1360
|
+
: {}),
|
|
1361
|
+
...(normalized.providerMetadata
|
|
1362
|
+
? { providerMetadata: normalized.providerMetadata }
|
|
1363
|
+
: {}),
|
|
1009
1364
|
};
|
|
1010
1365
|
}
|
|
1011
|
-
|
|
1012
|
-
yield {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
promptTokens: normalized.usage.prompt_tokens,
|
|
1016
|
-
completionTokens: normalized.usage.completion_tokens,
|
|
1017
|
-
totalTokens: normalized.usage.total_tokens,
|
|
1018
|
-
},
|
|
1019
|
-
};
|
|
1366
|
+
else {
|
|
1367
|
+
yield* forward(streamOpenAIResponsesResponse(response, providerStateScope, {
|
|
1368
|
+
allowEmptyTerminalOutput: activePlugin.id === CODEX_OAUTH_PLUGIN_ID,
|
|
1369
|
+
}));
|
|
1020
1370
|
}
|
|
1021
|
-
const incompleteReason = typeof normalized.providerMetadata?.[OPENAI_RESPONSES_INCOMPLETE_REASON_METADATA_KEY] === 'string'
|
|
1022
|
-
? normalized.providerMetadata[OPENAI_RESPONSES_INCOMPLETE_REASON_METADATA_KEY]
|
|
1023
|
-
: undefined;
|
|
1024
|
-
yield {
|
|
1025
|
-
type: 'done',
|
|
1026
|
-
...(incompleteReason
|
|
1027
|
-
? { doneReason: `incomplete:${incompleteReason}` }
|
|
1028
|
-
: {}),
|
|
1029
|
-
...(normalized.providerMetadata
|
|
1030
|
-
? { providerMetadata: normalized.providerMetadata }
|
|
1031
|
-
: {}),
|
|
1032
|
-
};
|
|
1033
1371
|
}
|
|
1034
1372
|
else {
|
|
1035
|
-
yield*
|
|
1373
|
+
yield* forward(streamOpenAICompatibleResponse(response));
|
|
1036
1374
|
}
|
|
1375
|
+
status = 'success';
|
|
1037
1376
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1377
|
+
catch (error) {
|
|
1378
|
+
status = 'error';
|
|
1379
|
+
throw error;
|
|
1380
|
+
}
|
|
1381
|
+
finally {
|
|
1382
|
+
pluginUsageService.record({
|
|
1383
|
+
userId,
|
|
1384
|
+
pluginId: activePlugin.id,
|
|
1385
|
+
pluginName: activePlugin.name,
|
|
1386
|
+
capability: 'chat',
|
|
1387
|
+
model,
|
|
1388
|
+
status,
|
|
1389
|
+
durationMs: Date.now() - startedAt,
|
|
1390
|
+
tokens: tokenUsage,
|
|
1391
|
+
});
|
|
1040
1392
|
}
|
|
1041
1393
|
}
|
|
1042
1394
|
// Validate plugin structure
|
|
@@ -1152,6 +1504,24 @@ export class PluginService {
|
|
|
1152
1504
|
getPluginsByCapability(capabilityType, userId) {
|
|
1153
1505
|
return this.capabilityRegistryService.getPluginsByCapability(capabilityType, userId);
|
|
1154
1506
|
}
|
|
1507
|
+
getAvailableAudioGenModels(userId) {
|
|
1508
|
+
return this.audioGenerationService.getAvailableModels(userId);
|
|
1509
|
+
}
|
|
1510
|
+
executeAudioGenRequest(model, prompt, options) {
|
|
1511
|
+
return this.audioGenerationService.generate(model, prompt, options);
|
|
1512
|
+
}
|
|
1513
|
+
getAvailableVideoGenModels(userId) {
|
|
1514
|
+
return this.videoGenerationService.getAvailableModels(userId);
|
|
1515
|
+
}
|
|
1516
|
+
submitVideoGenRequest(model, prompt, options) {
|
|
1517
|
+
return this.videoGenerationService.submit(model, prompt, options);
|
|
1518
|
+
}
|
|
1519
|
+
pollVideoGenRequest(model, providerJobId, pluginId, userId) {
|
|
1520
|
+
return this.videoGenerationService.poll(model, providerJobId, pluginId, userId);
|
|
1521
|
+
}
|
|
1522
|
+
downloadVideoGenResult(model, providerJobId, pluginId, userId) {
|
|
1523
|
+
return this.videoGenerationService.download(model, providerJobId, pluginId, userId);
|
|
1524
|
+
}
|
|
1155
1525
|
}
|
|
1156
1526
|
export default new PluginService();
|
|
1157
1527
|
//# sourceMappingURL=pluginService.js.map
|