libre-webui 0.25.0 → 0.26.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 +32 -22
- package/backend/dist/index.d.ts.map +1 -1
- package/backend/dist/index.js +26 -4
- package/backend/dist/index.js.map +1 -1
- package/backend/dist/middleware/auth.d.ts +7 -0
- package/backend/dist/middleware/auth.d.ts.map +1 -1
- package/backend/dist/middleware/auth.js +26 -0
- package/backend/dist/middleware/auth.js.map +1 -1
- package/backend/dist/middleware/index.d.ts +20 -0
- package/backend/dist/middleware/index.d.ts.map +1 -1
- package/backend/dist/middleware/index.js +105 -2
- package/backend/dist/middleware/index.js.map +1 -1
- package/backend/dist/models/personaModel.d.ts.map +1 -1
- package/backend/dist/models/personaModel.js +2 -0
- package/backend/dist/models/personaModel.js.map +1 -1
- package/backend/dist/observability/otel.d.ts +40 -0
- package/backend/dist/observability/otel.d.ts.map +1 -0
- package/backend/dist/observability/otel.js +337 -0
- package/backend/dist/observability/otel.js.map +1 -0
- package/backend/dist/observability/requestContext.d.ts +14 -0
- package/backend/dist/observability/requestContext.d.ts.map +1 -0
- package/backend/dist/observability/requestContext.js +21 -0
- package/backend/dist/observability/requestContext.js.map +1 -0
- package/backend/dist/persistence/chatGenerationTypes.d.ts +9 -0
- package/backend/dist/persistence/chatGenerationTypes.d.ts.map +1 -1
- package/backend/dist/persistence/extensionTypes.d.ts +13 -0
- package/backend/dist/persistence/extensionTypes.d.ts.map +1 -1
- package/backend/dist/persistence/extensionTypes.js.map +1 -1
- package/backend/dist/persistence/index.d.ts +1 -1
- package/backend/dist/persistence/index.d.ts.map +1 -1
- package/backend/dist/persistence/index.js.map +1 -1
- package/backend/dist/persistence/postgresAgentFoundationMigration.d.ts +9 -0
- package/backend/dist/persistence/postgresAgentFoundationMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresAgentFoundationMigration.js +164 -0
- package/backend/dist/persistence/postgresAgentFoundationMigration.js.map +1 -0
- package/backend/dist/persistence/postgresExtensionRepositories.d.ts.map +1 -1
- package/backend/dist/persistence/postgresExtensionRepositories.js +46 -2
- package/backend/dist/persistence/postgresExtensionRepositories.js.map +1 -1
- package/backend/dist/persistence/postgresMediaEnterpriseOpsMigration.d.ts +10 -0
- package/backend/dist/persistence/postgresMediaEnterpriseOpsMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMediaEnterpriseOpsMigration.js +148 -0
- package/backend/dist/persistence/postgresMediaEnterpriseOpsMigration.js.map +1 -0
- package/backend/dist/persistence/postgresMigrationRegistry.d.ts.map +1 -1
- package/backend/dist/persistence/postgresMigrationRegistry.js +10 -0
- package/backend/dist/persistence/postgresMigrationRegistry.js.map +1 -1
- package/backend/dist/persistence/postgresNotesV2Migration.d.ts +4 -0
- package/backend/dist/persistence/postgresNotesV2Migration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresNotesV2Migration.js +57 -0
- package/backend/dist/persistence/postgresNotesV2Migration.js.map +1 -0
- package/backend/dist/persistence/postgresResourceRepositories.d.ts.map +1 -1
- package/backend/dist/persistence/postgresResourceRepositories.js +1646 -11
- package/backend/dist/persistence/postgresResourceRepositories.js.map +1 -1
- package/backend/dist/persistence/postgresSkillFilesMigration.d.ts +9 -0
- package/backend/dist/persistence/postgresSkillFilesMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresSkillFilesMigration.js +50 -0
- package/backend/dist/persistence/postgresSkillFilesMigration.js.map +1 -0
- package/backend/dist/persistence/postgresTeamCollaborationMigration.d.ts +10 -0
- package/backend/dist/persistence/postgresTeamCollaborationMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresTeamCollaborationMigration.js +161 -0
- package/backend/dist/persistence/postgresTeamCollaborationMigration.js.map +1 -0
- package/backend/dist/persistence/resourceTypes.d.ts +541 -3
- package/backend/dist/persistence/resourceTypes.d.ts.map +1 -1
- package/backend/dist/persistence/resourceTypes.js.map +1 -1
- package/backend/dist/persistence/sqliteExtensionRepositories.d.ts.map +1 -1
- package/backend/dist/persistence/sqliteExtensionRepositories.js +26 -4
- package/backend/dist/persistence/sqliteExtensionRepositories.js.map +1 -1
- package/backend/dist/persistence/sqliteMigrations.d.ts +9 -0
- package/backend/dist/persistence/sqliteMigrations.d.ts.map +1 -1
- package/backend/dist/persistence/sqliteMigrations.js +1196 -29
- package/backend/dist/persistence/sqliteMigrations.js.map +1 -1
- package/backend/dist/persistence/sqliteResourceRepositories.d.ts.map +1 -1
- package/backend/dist/persistence/sqliteResourceRepositories.js +1523 -134
- package/backend/dist/persistence/sqliteResourceRepositories.js.map +1 -1
- package/backend/dist/persistence/sqliteToPostgresMigration.d.ts.map +1 -1
- package/backend/dist/persistence/sqliteToPostgresMigration.js +257 -3
- package/backend/dist/persistence/sqliteToPostgresMigration.js.map +1 -1
- package/backend/dist/platform/jobs/domainJobContracts.d.ts +8 -0
- package/backend/dist/platform/jobs/domainJobContracts.d.ts.map +1 -1
- package/backend/dist/platform/jobs/domainJobContracts.js +8 -0
- package/backend/dist/platform/jobs/domainJobContracts.js.map +1 -1
- package/backend/dist/platform/jobs/domainJobHandlers.d.ts.map +1 -1
- package/backend/dist/platform/jobs/domainJobHandlers.js +310 -3
- package/backend/dist/platform/jobs/domainJobHandlers.js.map +1 -1
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.d.ts.map +1 -1
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js +4 -2
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js.map +1 -1
- package/backend/dist/platform/jobs/postgresDurableJobWorker.d.ts.map +1 -1
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js +4 -2
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js.map +1 -1
- package/backend/dist/platform/storage/pgVectorStore.d.ts +2 -1
- package/backend/dist/platform/storage/pgVectorStore.d.ts.map +1 -1
- package/backend/dist/platform/storage/pgVectorStore.js +51 -0
- package/backend/dist/platform/storage/pgVectorStore.js.map +1 -1
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts +8 -2
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts.map +1 -1
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.d.ts.map +1 -1
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js +25 -4
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js.map +1 -1
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts +2 -1
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts.map +1 -1
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js +35 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js.map +1 -1
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.d.ts.map +1 -1
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js +26 -3
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js.map +1 -1
- package/backend/dist/platform/storage/vectorStore.d.ts +14 -0
- package/backend/dist/platform/storage/vectorStore.d.ts.map +1 -1
- package/backend/dist/platform/storage/vectorStore.js.map +1 -1
- package/backend/dist/routes/access.d.ts.map +1 -1
- package/backend/dist/routes/access.js +84 -3
- package/backend/dist/routes/access.js.map +1 -1
- package/backend/dist/routes/calendar.d.ts.map +1 -1
- package/backend/dist/routes/calendar.js +125 -22
- package/backend/dist/routes/calendar.js.map +1 -1
- package/backend/dist/routes/channels.d.ts +3 -0
- package/backend/dist/routes/channels.d.ts.map +1 -0
- package/backend/dist/routes/channels.js +447 -0
- package/backend/dist/routes/channels.js.map +1 -0
- package/backend/dist/routes/chat.d.ts.map +1 -1
- package/backend/dist/routes/chat.js +195 -7
- package/backend/dist/routes/chat.js.map +1 -1
- package/backend/dist/routes/costs.d.ts +3 -0
- package/backend/dist/routes/costs.d.ts.map +1 -0
- package/backend/dist/routes/costs.js +191 -0
- package/backend/dist/routes/costs.js.map +1 -0
- package/backend/dist/routes/documents.d.ts.map +1 -1
- package/backend/dist/routes/documents.js +64 -21
- package/backend/dist/routes/documents.js.map +1 -1
- package/backend/dist/routes/evaluations.d.ts +3 -0
- package/backend/dist/routes/evaluations.d.ts.map +1 -0
- package/backend/dist/routes/evaluations.js +352 -0
- package/backend/dist/routes/evaluations.js.map +1 -0
- package/backend/dist/routes/imageGen.d.ts.map +1 -1
- package/backend/dist/routes/imageGen.js +2 -1
- package/backend/dist/routes/imageGen.js.map +1 -1
- package/backend/dist/routes/media.d.ts.map +1 -1
- package/backend/dist/routes/media.js +228 -7
- package/backend/dist/routes/media.js.map +1 -1
- package/backend/dist/routes/notes.d.ts.map +1 -1
- package/backend/dist/routes/notes.js +149 -36
- package/backend/dist/routes/notes.js.map +1 -1
- package/backend/dist/routes/notifications.d.ts +3 -0
- package/backend/dist/routes/notifications.d.ts.map +1 -0
- package/backend/dist/routes/notifications.js +213 -0
- package/backend/dist/routes/notifications.js.map +1 -0
- package/backend/dist/routes/openaiCompat.d.ts +3 -0
- package/backend/dist/routes/openaiCompat.d.ts.map +1 -0
- package/backend/dist/routes/openaiCompat.js +314 -0
- package/backend/dist/routes/openaiCompat.js.map +1 -0
- package/backend/dist/routes/personas.js +1 -1
- package/backend/dist/routes/personas.js.map +1 -1
- package/backend/dist/routes/prompts.d.ts +3 -0
- package/backend/dist/routes/prompts.d.ts.map +1 -0
- package/backend/dist/routes/prompts.js +173 -0
- package/backend/dist/routes/prompts.js.map +1 -0
- package/backend/dist/routes/search.d.ts.map +1 -1
- package/backend/dist/routes/search.js +29 -1
- package/backend/dist/routes/search.js.map +1 -1
- package/backend/dist/routes/skills.d.ts +3 -0
- package/backend/dist/routes/skills.d.ts.map +1 -0
- package/backend/dist/routes/skills.js +246 -0
- package/backend/dist/routes/skills.js.map +1 -0
- package/backend/dist/routes/stt.d.ts.map +1 -1
- package/backend/dist/routes/stt.js +2 -1
- package/backend/dist/routes/stt.js.map +1 -1
- package/backend/dist/routes/tools.d.ts +3 -0
- package/backend/dist/routes/tools.d.ts.map +1 -0
- package/backend/dist/routes/tools.js +359 -0
- package/backend/dist/routes/tools.js.map +1 -0
- package/backend/dist/routes/tts.d.ts.map +1 -1
- package/backend/dist/routes/tts.js +63 -8
- package/backend/dist/routes/tts.js.map +1 -1
- package/backend/dist/routes/voiceAccess.d.ts +3 -0
- package/backend/dist/routes/voiceAccess.d.ts.map +1 -0
- package/backend/dist/routes/voiceAccess.js +102 -0
- package/backend/dist/routes/voiceAccess.js.map +1 -0
- package/backend/dist/services/apiTokenService.d.ts +2 -2
- package/backend/dist/services/apiTokenService.d.ts.map +1 -1
- package/backend/dist/services/apiTokenService.js +7 -0
- package/backend/dist/services/apiTokenService.js.map +1 -1
- package/backend/dist/services/authorizationService.d.ts +8 -4
- package/backend/dist/services/authorizationService.d.ts.map +1 -1
- package/backend/dist/services/authorizationService.js +31 -1
- package/backend/dist/services/authorizationService.js.map +1 -1
- package/backend/dist/services/automationSchedulerService.d.ts.map +1 -1
- package/backend/dist/services/automationSchedulerService.js +33 -3
- package/backend/dist/services/automationSchedulerService.js.map +1 -1
- package/backend/dist/services/automationService.d.ts +4 -1
- package/backend/dist/services/automationService.d.ts.map +1 -1
- package/backend/dist/services/automationService.js +25 -2
- package/backend/dist/services/automationService.js.map +1 -1
- package/backend/dist/services/builtinToolsService.d.ts +20 -0
- package/backend/dist/services/builtinToolsService.d.ts.map +1 -0
- package/backend/dist/services/builtinToolsService.js +661 -0
- package/backend/dist/services/builtinToolsService.js.map +1 -0
- package/backend/dist/services/calendarService.d.ts +74 -0
- package/backend/dist/services/calendarService.d.ts.map +1 -0
- package/backend/dist/services/calendarService.js +339 -0
- package/backend/dist/services/calendarService.js.map +1 -0
- package/backend/dist/services/channelService.d.ts +195 -0
- package/backend/dist/services/channelService.d.ts.map +1 -0
- package/backend/dist/services/channelService.js +1057 -0
- package/backend/dist/services/channelService.js.map +1 -0
- package/backend/dist/services/chatRequestService.d.ts.map +1 -1
- package/backend/dist/services/chatRequestService.js +29 -1
- package/backend/dist/services/chatRequestService.js.map +1 -1
- package/backend/dist/services/chatService.d.ts +61 -1
- package/backend/dist/services/chatService.d.ts.map +1 -1
- package/backend/dist/services/chatService.js +218 -1
- package/backend/dist/services/chatService.js.map +1 -1
- package/backend/dist/services/chatToolRuntimeService.d.ts +55 -0
- package/backend/dist/services/chatToolRuntimeService.d.ts.map +1 -0
- package/backend/dist/services/chatToolRuntimeService.js +389 -0
- package/backend/dist/services/chatToolRuntimeService.js.map +1 -0
- package/backend/dist/services/costGovernanceService.d.ts +102 -0
- package/backend/dist/services/costGovernanceService.d.ts.map +1 -0
- package/backend/dist/services/costGovernanceService.js +463 -0
- package/backend/dist/services/costGovernanceService.js.map +1 -0
- package/backend/dist/services/dataArchiveService.d.ts +6 -0
- package/backend/dist/services/dataArchiveService.d.ts.map +1 -1
- package/backend/dist/services/dataArchiveService.js +23 -4
- package/backend/dist/services/dataArchiveService.js.map +1 -1
- package/backend/dist/services/documentService.d.ts +58 -1
- package/backend/dist/services/documentService.d.ts.map +1 -1
- package/backend/dist/services/documentService.js +289 -84
- package/backend/dist/services/documentService.js.map +1 -1
- package/backend/dist/services/durableChatGenerationService.d.ts +9 -0
- package/backend/dist/services/durableChatGenerationService.d.ts.map +1 -1
- package/backend/dist/services/durableChatGenerationService.js +152 -11
- package/backend/dist/services/durableChatGenerationService.js.map +1 -1
- package/backend/dist/services/evaluationService.d.ts +111 -0
- package/backend/dist/services/evaluationService.d.ts.map +1 -0
- package/backend/dist/services/evaluationService.js +403 -0
- package/backend/dist/services/evaluationService.js.map +1 -0
- package/backend/dist/services/galleryService.d.ts +6 -0
- package/backend/dist/services/galleryService.d.ts.map +1 -1
- package/backend/dist/services/galleryService.js +26 -0
- package/backend/dist/services/galleryService.js.map +1 -1
- package/backend/dist/services/mcpClientService.d.ts +29 -0
- package/backend/dist/services/mcpClientService.d.ts.map +1 -0
- package/backend/dist/services/mcpClientService.js +189 -0
- package/backend/dist/services/mcpClientService.js.map +1 -0
- package/backend/dist/services/noteService.d.ts +71 -0
- package/backend/dist/services/noteService.d.ts.map +1 -0
- package/backend/dist/services/noteService.js +397 -0
- package/backend/dist/services/noteService.js.map +1 -0
- package/backend/dist/services/notificationService.d.ts +55 -0
- package/backend/dist/services/notificationService.d.ts.map +1 -0
- package/backend/dist/services/notificationService.js +308 -0
- package/backend/dist/services/notificationService.js.map +1 -0
- package/backend/dist/services/openApiToolService.d.ts +38 -0
- package/backend/dist/services/openApiToolService.d.ts.map +1 -0
- package/backend/dist/services/openApiToolService.js +254 -0
- package/backend/dist/services/openApiToolService.js.map +1 -0
- package/backend/dist/services/personaService.d.ts +18 -2
- package/backend/dist/services/personaService.d.ts.map +1 -1
- package/backend/dist/services/personaService.js +113 -4
- package/backend/dist/services/personaService.js.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.d.ts +19 -0
- package/backend/dist/services/pluginImageGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.js +121 -0
- package/backend/dist/services/pluginImageGenerationService.js.map +1 -1
- package/backend/dist/services/pluginService.d.ts +7 -0
- package/backend/dist/services/pluginService.d.ts.map +1 -1
- package/backend/dist/services/pluginService.js +8 -2
- package/backend/dist/services/pluginService.js.map +1 -1
- package/backend/dist/services/promptService.d.ts +74 -0
- package/backend/dist/services/promptService.d.ts.map +1 -0
- package/backend/dist/services/promptService.js +513 -0
- package/backend/dist/services/promptService.js.map +1 -0
- package/backend/dist/services/resourceGrantService.d.ts.map +1 -1
- package/backend/dist/services/resourceGrantService.js +62 -17
- package/backend/dist/services/resourceGrantService.js.map +1 -1
- package/backend/dist/services/searchService.d.ts +29 -0
- package/backend/dist/services/searchService.d.ts.map +1 -0
- package/backend/dist/services/searchService.js +0 -0
- package/backend/dist/services/searchService.js.map +1 -0
- package/backend/dist/services/securityAuditService.d.ts.map +1 -1
- package/backend/dist/services/securityAuditService.js +2 -1
- package/backend/dist/services/securityAuditService.js.map +1 -1
- package/backend/dist/services/sharedResourceAccess.d.ts +25 -0
- package/backend/dist/services/sharedResourceAccess.d.ts.map +1 -0
- package/backend/dist/services/sharedResourceAccess.js +59 -0
- package/backend/dist/services/sharedResourceAccess.js.map +1 -0
- package/backend/dist/services/skillService.d.ts +137 -0
- package/backend/dist/services/skillService.d.ts.map +1 -0
- package/backend/dist/services/skillService.js +852 -0
- package/backend/dist/services/skillService.js.map +1 -0
- package/backend/dist/services/toolAccessService.d.ts +9 -0
- package/backend/dist/services/toolAccessService.d.ts.map +1 -0
- package/backend/dist/services/toolAccessService.js +60 -0
- package/backend/dist/services/toolAccessService.js.map +1 -0
- package/backend/dist/services/toolApprovalService.d.ts +34 -0
- package/backend/dist/services/toolApprovalService.d.ts.map +1 -0
- package/backend/dist/services/toolApprovalService.js +188 -0
- package/backend/dist/services/toolApprovalService.js.map +1 -0
- package/backend/dist/services/toolGatewayService.d.ts +53 -0
- package/backend/dist/services/toolGatewayService.d.ts.map +1 -0
- package/backend/dist/services/toolGatewayService.js +249 -0
- package/backend/dist/services/toolGatewayService.js.map +1 -0
- package/backend/dist/services/toolServerService.d.ts +57 -0
- package/backend/dist/services/toolServerService.d.ts.map +1 -0
- package/backend/dist/services/toolServerService.js +521 -0
- package/backend/dist/services/toolServerService.js.map +1 -0
- package/backend/dist/services/voiceAccessService.d.ts +10 -0
- package/backend/dist/services/voiceAccessService.d.ts.map +1 -0
- package/backend/dist/services/voiceAccessService.js +74 -0
- package/backend/dist/services/voiceAccessService.js.map +1 -0
- package/backend/dist/services/voiceProfileService.d.ts +20 -0
- package/backend/dist/services/voiceProfileService.d.ts.map +1 -1
- package/backend/dist/services/voiceProfileService.js +60 -0
- package/backend/dist/services/voiceProfileService.js.map +1 -1
- package/backend/dist/storage.d.ts +28 -1
- package/backend/dist/storage.d.ts.map +1 -1
- package/backend/dist/storage.js +100 -1
- package/backend/dist/storage.js.map +1 -1
- package/backend/dist/storageMappers.d.ts +2 -2
- package/backend/dist/storageMappers.d.ts.map +1 -1
- package/backend/dist/storageMappers.js.map +1 -1
- package/backend/dist/types/index.d.ts +197 -2
- package/backend/dist/types/index.d.ts.map +1 -1
- package/backend/dist/types/index.js.map +1 -1
- package/backend/dist/types/tools.d.ts +137 -0
- package/backend/dist/types/tools.d.ts.map +1 -0
- package/backend/dist/types/tools.js +25 -0
- package/backend/dist/types/tools.js.map +1 -0
- package/backend/dist/utils/chatDocumentContext.d.ts +26 -1
- package/backend/dist/utils/chatDocumentContext.d.ts.map +1 -1
- package/backend/dist/utils/chatDocumentContext.js +87 -18
- package/backend/dist/utils/chatDocumentContext.js.map +1 -1
- package/backend/dist/utils/documentExtraction.d.ts +69 -0
- package/backend/dist/utils/documentExtraction.d.ts.map +1 -0
- package/backend/dist/utils/documentExtraction.js +545 -0
- package/backend/dist/utils/documentExtraction.js.map +1 -0
- package/backend/dist/utils/hybridRetrieval.d.ts +34 -0
- package/backend/dist/utils/hybridRetrieval.d.ts.map +1 -0
- package/backend/dist/utils/hybridRetrieval.js +119 -0
- package/backend/dist/utils/hybridRetrieval.js.map +1 -0
- package/backend/dist/utils/icsCalendar.d.ts +27 -0
- package/backend/dist/utils/icsCalendar.d.ts.map +1 -0
- package/backend/dist/utils/icsCalendar.js +313 -0
- package/backend/dist/utils/icsCalendar.js.map +1 -0
- package/backend/dist/utils/imageEditUpload.d.ts +29 -0
- package/backend/dist/utils/imageEditUpload.d.ts.map +1 -0
- package/backend/dist/utils/imageEditUpload.js +82 -0
- package/backend/dist/utils/imageEditUpload.js.map +1 -0
- package/backend/dist/utils/logRedaction.d.ts +2 -0
- package/backend/dist/utils/logRedaction.d.ts.map +1 -0
- package/backend/dist/utils/logRedaction.js +66 -0
- package/backend/dist/utils/logRedaction.js.map +1 -0
- package/backend/dist/utils/logger.d.ts +3 -0
- package/backend/dist/utils/logger.d.ts.map +1 -1
- package/backend/dist/utils/logger.js +63 -20
- package/backend/dist/utils/logger.js.map +1 -1
- package/backend/dist/utils/pluginChatAdapter.d.ts +5 -1
- package/backend/dist/utils/pluginChatAdapter.d.ts.map +1 -1
- package/backend/dist/utils/pluginChatAdapter.js +83 -0
- package/backend/dist/utils/pluginChatAdapter.js.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.js +1 -1
- package/backend/dist/utils/resourceLimits.d.ts +61 -2
- package/backend/dist/utils/resourceLimits.d.ts.map +1 -1
- package/backend/dist/utils/resourceLimits.js +59 -0
- package/backend/dist/utils/resourceLimits.js.map +1 -1
- package/backend/dist/utils/toolEgress.d.ts +22 -0
- package/backend/dist/utils/toolEgress.d.ts.map +1 -0
- package/backend/dist/utils/toolEgress.js +157 -0
- package/backend/dist/utils/toolEgress.js.map +1 -0
- package/backend/dist/utils/websocketMessages.d.ts +6 -0
- package/backend/dist/utils/websocketMessages.d.ts.map +1 -1
- package/backend/dist/utils/websocketMessages.js +8 -0
- package/backend/dist/utils/websocketMessages.js.map +1 -1
- package/backend/dist/utils/zipArchive.d.ts +32 -0
- package/backend/dist/utils/zipArchive.d.ts.map +1 -0
- package/backend/dist/utils/zipArchive.js +171 -0
- package/backend/dist/utils/zipArchive.js.map +1 -0
- package/backend/dist/websocketServer.d.ts.map +1 -1
- package/backend/dist/websocketServer.js +142 -35
- package/backend/dist/websocketServer.js.map +1 -1
- package/backend/package.json +1 -1
- package/frontend/dist/artifact-runtime/.build-fingerprint +1 -1
- package/frontend/dist/assets/index-BPsH9FII.js +80 -0
- package/frontend/dist/assets/index-BtXF0Oxa.css +1 -0
- package/frontend/dist/index.html +18 -18
- package/frontend/dist/js/{ArtifactContainer-CpUi6ekF.js → ArtifactContainer-CIoFoMv8.js} +1 -1
- package/frontend/dist/js/{ArtifactDemoPage-BeNs3gHp.js → ArtifactDemoPage-D0JEIAbZ.js} +1 -1
- package/frontend/dist/js/{ArtifactSandboxFrame-qsj_Y3LV.js → ArtifactSandboxFrame-REazyIrx.js} +2 -2
- package/frontend/dist/js/ArtifactSlideOutPanel-A-i94ghF.js +1 -0
- package/frontend/dist/js/AutomationsPage-Dow_lbIf.js +1 -0
- package/frontend/dist/js/{Button-BPf_pOxH.js → Button-C0r3J9G_.js} +1 -1
- package/frontend/dist/js/CalendarPage-DLjasZOd.js +1 -0
- package/frontend/dist/js/ChannelsPage-C8hvTD7J.js +1 -0
- package/frontend/dist/js/ChatPage-BAgBHUES.js +16 -0
- package/frontend/dist/js/EvaluationsPage-Bm8FRoeX.js +2 -0
- package/frontend/dist/js/{FirstTimeSetup-Df0YJni3.js → FirstTimeSetup-BxJapNul.js} +1 -1
- package/frontend/dist/js/GalleryPage-DHz9DkK7.js +1 -0
- package/frontend/dist/js/HomePage-BqNy-FWX.js +1 -0
- package/frontend/dist/js/LibreClawPage-BDzDILjY.js +1 -0
- package/frontend/dist/js/{ModelManagerModals-DcLGYN3l.js → ModelManagerModals-DX9eT5r2.js} +1 -1
- package/frontend/dist/js/ModelSelector-ol8mK2ja.js +1 -0
- package/frontend/dist/js/NotesPage-DzHEx2O4.js +3 -0
- package/frontend/dist/js/{OptimizedSyntaxHighlighter-Dz7D1LPB.js → OptimizedSyntaxHighlighter-CZNPwN0i.js} +1 -1
- package/frontend/dist/js/PersonasPage-M_WKH2a9.js +13 -0
- package/frontend/dist/js/PluginUsagePage-Ctoka6JZ.js +1 -0
- package/frontend/dist/js/RichMessageContent-BqgafH4p.js +3 -0
- package/frontend/dist/js/SettingsModal-R9EDadAV.js +19 -0
- package/frontend/dist/js/{SettingsToggle-woG_WebF.js → SettingsToggle-BIVyfGjl.js} +1 -1
- package/frontend/dist/js/SystemPage-aOkrSuY7.js +1 -0
- package/frontend/dist/js/UserManagementPage-BOuaX3ay.js +1 -0
- package/frontend/dist/js/WorkPage-DxZISerQ.js +6 -0
- package/frontend/dist/js/api-6bSMtSNh.js +14 -0
- package/frontend/dist/js/{appStore-0JnCUlEq.js → appStore-CdObhQBb.js} +2 -2
- package/frontend/dist/js/ar-DT_VLBO3.js +2 -0
- package/frontend/dist/js/{authStore-DbMdvNgJ.js → authStore-DbqqrfZv.js} +3 -3
- package/frontend/dist/js/{babel-BsYoxD-7.js → babel-DSqqk5kt.js} +1 -1
- package/frontend/dist/js/bn-BrvEqhGA.js +2 -0
- package/frontend/dist/js/chatStore-DbZPJNsu.js +3 -0
- package/frontend/dist/js/{config-DSOYQ9a3.js → config-8KdgjtEx.js} +1 -1
- package/frontend/dist/js/cs-BthnM_YI.js +2 -0
- package/frontend/dist/js/da-DCth-6_j.js +2 -0
- package/frontend/dist/js/de-BBWt0gJ_.js +2 -0
- package/frontend/dist/js/es-DuslOPqM.js +2 -0
- package/frontend/dist/js/{estree-BcnBcOAx.js → estree-BU5-LV_1.js} +3 -3
- package/frontend/dist/js/evaluationsApi-CwZJsgeG.js +1 -0
- package/frontend/dist/js/fr-DZAeg46S.js +2 -0
- package/frontend/dist/js/hi-ijDSiY77.js +2 -0
- package/frontend/dist/js/{html-DkY55Jys.js → html-DeoAy2bo.js} +2 -2
- package/frontend/dist/js/id-BS6qS0oq.js +2 -0
- package/frontend/dist/js/is-CO2PMDte.js +2 -0
- package/frontend/dist/js/it-ChhxT4hs.js +2 -0
- package/frontend/dist/js/ja-cyeqUeJN.js +2 -0
- package/frontend/dist/js/ko-CfqHTLXj.js +2 -0
- package/frontend/dist/js/{markdown-IZSI9DXw.js → markdown-DOLsYkBY.js} +3 -3
- package/frontend/dist/js/markdown-core-BK7WVOb7.js +32 -0
- package/frontend/dist/js/{markdown-math-DK846gXU.js → markdown-math-e1ByS3KY.js} +5 -5
- package/frontend/dist/js/{messageCodeStyles-BFNR9Wv6.js → messageCodeStyles-DhVgizF-.js} +2 -2
- package/frontend/dist/js/ms-DZ5pACe1.js +2 -0
- package/frontend/dist/js/nl-BsRsnOVp.js +2 -0
- package/frontend/dist/js/pl-DXSTAW4M.js +2 -0
- package/frontend/dist/js/{postcss-BJ0okz7n.js → postcss-Bg15EcFE.js} +1 -1
- package/frontend/dist/js/pt-DmDx0JxB.js +2 -0
- package/frontend/dist/js/{react-vendor-C5yShNlM.js → react-vendor-BG_HPV6X.js} +1 -1
- package/frontend/dist/js/router-vendor-CbexJIsv.js +1 -0
- package/frontend/dist/js/ru-d2g8EWfY.js +2 -0
- package/frontend/dist/js/{standalone-Csw3jfJ_.js → standalone-BO5pzI8_.js} +3 -3
- package/frontend/dist/js/sv-CIhYUTVQ.js +2 -0
- package/frontend/dist/js/{syntax-highlight-3EEX6CGL.js → syntax-highlight-DcR9Vhb7.js} +3 -3
- package/frontend/dist/js/th-B3wSxanB.js +2 -0
- package/frontend/dist/js/tr-R4UGgPOY.js +2 -0
- package/frontend/dist/js/{typescript-CnF4UVx7.js → typescript-6GJ8APmn.js} +1 -1
- package/frontend/dist/js/ui-CV0LYmkM.js +2 -0
- package/frontend/dist/js/ui-vendor-CWjIBW-z.js +177 -0
- package/frontend/dist/js/uk-BzUF4Vkt.js +2 -0
- package/frontend/dist/js/{useTranslation-Bho4HCyg.js → useTranslation-5b5UhAc9.js} +1 -1
- package/frontend/dist/js/{utils-D9W1Lnkn.js → utils-BGrdX9ie.js} +1 -1
- package/frontend/dist/js/{utils-vendor-DWh39_3x.js → utils-vendor-9bQ62WeD.js} +1 -1
- package/frontend/dist/js/vi-CKc6Fg4h.js +2 -0
- package/frontend/dist/js/{workApi-C3uy9EDT.js → workApi-BruWTlHM.js} +3 -3
- package/frontend/dist/js/{yaml-DzT5hBSH.js → yaml-DUeWcOOH.js} +2 -2
- package/frontend/dist/js/zh-CXL-kDe8.js +2 -0
- package/package.json +2 -2
- package/plugins/openai.json +52 -9
- package/frontend/dist/assets/index-6o-Hc2wS.js +0 -41
- package/frontend/dist/assets/index-D-pM957b.css +0 -1
- package/frontend/dist/js/ArtifactSlideOutPanel-CSFRluWA.js +0 -1
- package/frontend/dist/js/AutomationsPage-KUeWoZNv.js +0 -1
- package/frontend/dist/js/CalendarPage-D9I972w8.js +0 -1
- package/frontend/dist/js/ChatPage-CmBx4oAL.js +0 -16
- package/frontend/dist/js/GalleryPage-bLCrdJN_.js +0 -1
- package/frontend/dist/js/HomePage-Uc6PEg-U.js +0 -1
- package/frontend/dist/js/LibreClawPage-CG63DHg1.js +0 -1
- package/frontend/dist/js/ModelSelector-yxJC64rM.js +0 -1
- package/frontend/dist/js/ModelsPage-1R_TxgmJ.js +0 -2
- package/frontend/dist/js/NotesPage-L65j5HoW.js +0 -1
- package/frontend/dist/js/PersonasPage-CKeBpHIH.js +0 -13
- package/frontend/dist/js/PluginUsagePage-BX1SKMbW.js +0 -1
- package/frontend/dist/js/RichMessageContent-DiySVYGB.js +0 -3
- package/frontend/dist/js/SettingsModal-68SG1uZ2.js +0 -1
- package/frontend/dist/js/SystemPage-CytpZiQV.js +0 -1
- package/frontend/dist/js/UserManagementPage-BzJBvZiS.js +0 -1
- package/frontend/dist/js/WorkPage-C8gr0QJe.js +0 -6
- package/frontend/dist/js/api-BDtqBtqw.js +0 -14
- package/frontend/dist/js/ar-CSpi37Gr.js +0 -2
- package/frontend/dist/js/bn-CyH1BeDD.js +0 -2
- package/frontend/dist/js/chatStore-CHQ2uINS.js +0 -3
- package/frontend/dist/js/cs-Cv2NfRK5.js +0 -2
- package/frontend/dist/js/da-D6D6IvPK.js +0 -2
- package/frontend/dist/js/de-BNoJJTrT.js +0 -2
- package/frontend/dist/js/es-kzo9C7q_.js +0 -2
- package/frontend/dist/js/fr-CjHYvJRp.js +0 -2
- package/frontend/dist/js/hi-BU98AdCQ.js +0 -2
- package/frontend/dist/js/id-CpdedejX.js +0 -2
- package/frontend/dist/js/is-Cp5dDWBH.js +0 -2
- package/frontend/dist/js/it-CuH_cK4U.js +0 -2
- package/frontend/dist/js/ja-BWXXXiHn.js +0 -2
- package/frontend/dist/js/ko-DQgv2M1t.js +0 -2
- package/frontend/dist/js/markdown-core-BmPPZiuD.js +0 -31
- package/frontend/dist/js/ms-DCcRoIcX.js +0 -2
- package/frontend/dist/js/nl-CbKR1_EU.js +0 -2
- package/frontend/dist/js/pl-CRyJZccn.js +0 -2
- package/frontend/dist/js/pt-BXYmHFGH.js +0 -2
- package/frontend/dist/js/router-vendor-DGFGM3EP.js +0 -1
- package/frontend/dist/js/ru-M9SyZG4b.js +0 -2
- package/frontend/dist/js/sv-DJ486LTU.js +0 -2
- package/frontend/dist/js/th-Ch7gKtZv.js +0 -2
- package/frontend/dist/js/tr-ClehWhSC.js +0 -2
- package/frontend/dist/js/ui-CC-K19wO.js +0 -2
- package/frontend/dist/js/ui-vendor-B1UgO3vd.js +0 -177
- package/frontend/dist/js/uk-BqAd5zHF.js +0 -2
- package/frontend/dist/js/vi-D9gjlDVB.js +0 -2
- package/frontend/dist/js/zh-DKTyHkiR.js +0 -2
|
@@ -18,6 +18,10 @@ import crypto from 'node:crypto';
|
|
|
18
18
|
import { Readable } from 'node:stream';
|
|
19
19
|
import { v4 as uuidv4 } from 'uuid';
|
|
20
20
|
import storageService from '../storage.js';
|
|
21
|
+
import { getPersistence } from '../persistence/index.js';
|
|
22
|
+
import { encryptionService } from './encryptionService.js';
|
|
23
|
+
import { listGrantsForActor } from './resourceGrantService.js';
|
|
24
|
+
import { grantedResourceIdsFor, sharedMetaFor, } from './sharedResourceAccess.js';
|
|
21
25
|
import { configurePlatformStorageRuntime, getPlatformStorageRuntime, } from '../platform/storage/index.js';
|
|
22
26
|
import { MAX_VECTOR_RECORDS_PER_UPSERT, MAX_VECTOR_RESOURCE_INDEX_ENTRIES, } from '../platform/storage/vectorStore.js';
|
|
23
27
|
import { aggregateDocumentIndexRevision, createDocumentIndexMetadata, DOCUMENT_CHUNKER_VERSION, DOCUMENT_INDEX_METADATA_KEY, DOCUMENT_VECTOR_NAMESPACE, DOCUMENT_VECTOR_VERSION, documentChunkSourceRevision as sourceRevision, documentEmbeddingDimensions as embeddingDimensions, documentIndexMatchesSpec, embeddedDocumentChunks as embeddedChunks, readDocumentIndexMetadata as readDocumentIndexMetadataValue, } from '../platform/storage/documentVectorIndex.js';
|
|
@@ -29,6 +33,8 @@ import { transactionalResourceDeletionEnqueuer } from '../platform/jobs/resource
|
|
|
29
33
|
import preferencesService from './preferencesService.js';
|
|
30
34
|
import { createLogger } from '../utils/logger.js';
|
|
31
35
|
import { throwIfChatGenerationCancelled } from '../utils/chatCancellation.js';
|
|
36
|
+
import { reciprocalRankFusion, scoreCandidatesBm25, } from '../utils/hybridRetrieval.js';
|
|
37
|
+
import { extractDocumentContentByType, readDocumentSegments, resolveDocumentFileType, resolveSegmentLabel, } from '../utils/documentExtraction.js';
|
|
32
38
|
const logger = createLogger('documents');
|
|
33
39
|
const DOCUMENT_BLOB_PURPOSE = 'document.source';
|
|
34
40
|
const DOCUMENT_POST_VECTOR_FAULT_MARKER = 'LIBRE_DOCUMENT_POST_VECTOR_KILL';
|
|
@@ -248,31 +254,29 @@ const getPdfjsLib = async () => {
|
|
|
248
254
|
}
|
|
249
255
|
return pdfjsLib;
|
|
250
256
|
};
|
|
251
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Segment maps above this length would bloat the encrypted metadata column;
|
|
259
|
+
* a source under the extraction size cap never legitimately reaches it.
|
|
260
|
+
*/
|
|
261
|
+
const MAX_DOCUMENT_SEGMENTS = 5000;
|
|
262
|
+
const extractDocumentContent = async (fileName, fileBuffer, mimeType, signal) => {
|
|
252
263
|
if (signal?.aborted)
|
|
253
264
|
throw signal.reason;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
if (mimeType !== 'application/pdf') {
|
|
265
|
+
const fileType = resolveDocumentFileType(fileName, mimeType);
|
|
266
|
+
if (!fileType) {
|
|
258
267
|
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
259
268
|
}
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const pageText = await page.getTextContent();
|
|
270
|
-
textContent += `${pageText.items
|
|
271
|
-
.map(item => ('str' in item ? item.str : ''))
|
|
272
|
-
.join(' ')}\n\n`;
|
|
273
|
-
}
|
|
274
|
-
return { content: textContent.trim(), fileType: 'pdf' };
|
|
269
|
+
const extracted = await extractDocumentContentByType(fileBuffer, fileType, {
|
|
270
|
+
signal,
|
|
271
|
+
...(fileType === 'pdf' ? { pdfLib: await getPdfjsLib() } : {}),
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
content: extracted.content,
|
|
275
|
+
fileType,
|
|
276
|
+
segments: extracted.segments.slice(0, MAX_DOCUMENT_SEGMENTS),
|
|
277
|
+
};
|
|
275
278
|
};
|
|
279
|
+
const documentContentSha256 = (fileBuffer) => crypto.createHash('sha256').update(fileBuffer).digest('hex');
|
|
276
280
|
export class DocumentService {
|
|
277
281
|
async captureEmbeddingExecutionSpec(userId) {
|
|
278
282
|
const settings = (await preferencesService.getPreferences(userId))
|
|
@@ -333,23 +337,36 @@ export class DocumentService {
|
|
|
333
337
|
* if the SQL transaction cannot commit.
|
|
334
338
|
*/
|
|
335
339
|
async queueDocumentProcessing(fileName, fileBuffer, mimeType, userId, sessionId, signal) {
|
|
336
|
-
|
|
340
|
+
const resolvedType = resolveDocumentFileType(fileName, mimeType);
|
|
341
|
+
if (!resolvedType) {
|
|
337
342
|
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
338
343
|
}
|
|
339
344
|
if (signal?.aborted)
|
|
340
345
|
throw signal.reason;
|
|
346
|
+
const contentSha256 = documentContentSha256(fileBuffer);
|
|
347
|
+
const duplicate = await this.findDuplicateDocument(userId, sessionId, contentSha256);
|
|
348
|
+
if (duplicate) {
|
|
349
|
+
const existingJob = await getDurableJobRuntime().service.getByIdempotency(userId, DOCUMENT_INGEST_IDEMPOTENCY_SCOPE, duplicate.id);
|
|
350
|
+
if (existingJob) {
|
|
351
|
+
return {
|
|
352
|
+
document: duplicate,
|
|
353
|
+
jobId: existingJob.id,
|
|
354
|
+
deduplicated: true,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}
|
|
341
358
|
const documentId = uuidv4();
|
|
342
359
|
const now = Date.now();
|
|
343
360
|
const document = {
|
|
344
361
|
id: documentId,
|
|
345
362
|
filename: fileName,
|
|
346
363
|
content: '',
|
|
347
|
-
fileType:
|
|
364
|
+
fileType: resolvedType,
|
|
348
365
|
size: fileBuffer.length,
|
|
349
366
|
...(sessionId ? { sessionId } : {}),
|
|
350
367
|
uploadedAt: now,
|
|
351
368
|
createdAt: now,
|
|
352
|
-
metadata: { processingStatus: 'queued' },
|
|
369
|
+
metadata: { processingStatus: 'queued', contentSha256 },
|
|
353
370
|
};
|
|
354
371
|
const platform = getPlatformStorageRuntime();
|
|
355
372
|
const sourceBlob = await platform.blobStore.put({
|
|
@@ -417,7 +434,7 @@ export class DocumentService {
|
|
|
417
434
|
async processDocument(fileName, fileBuffer, mimeType, userId, sessionId) {
|
|
418
435
|
const documentId = uuidv4();
|
|
419
436
|
try {
|
|
420
|
-
const { content, fileType } = await extractDocumentContent(fileBuffer, mimeType);
|
|
437
|
+
const { content, fileType, segments } = await extractDocumentContent(fileName, fileBuffer, mimeType);
|
|
421
438
|
let document = {
|
|
422
439
|
id: documentId,
|
|
423
440
|
filename: fileName,
|
|
@@ -426,6 +443,10 @@ export class DocumentService {
|
|
|
426
443
|
size: fileBuffer.length,
|
|
427
444
|
sessionId,
|
|
428
445
|
uploadedAt: Date.now(),
|
|
446
|
+
metadata: {
|
|
447
|
+
contentSha256: documentContentSha256(fileBuffer),
|
|
448
|
+
...(segments.length > 0 ? { segments } : {}),
|
|
449
|
+
},
|
|
429
450
|
};
|
|
430
451
|
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
431
452
|
// Process the document into chunks under one immutable execution spec.
|
|
@@ -791,7 +812,8 @@ export class DocumentService {
|
|
|
791
812
|
}
|
|
792
813
|
buffers.push(buffer);
|
|
793
814
|
}
|
|
794
|
-
const
|
|
815
|
+
const sourceBuffer = Buffer.concat(buffers, size);
|
|
816
|
+
const extracted = await extractDocumentContent(source.descriptor.originalFilename ?? current.filename, sourceBuffer, source.descriptor.contentType, signal);
|
|
795
817
|
let document = {
|
|
796
818
|
...current,
|
|
797
819
|
content: extracted.content,
|
|
@@ -804,6 +826,10 @@ export class DocumentService {
|
|
|
804
826
|
...(document.metadata ?? {}),
|
|
805
827
|
processingStatus: 'completed',
|
|
806
828
|
processedAt: Date.now(),
|
|
829
|
+
contentSha256: documentContentSha256(sourceBuffer),
|
|
830
|
+
...(extracted.segments.length > 0
|
|
831
|
+
? { segments: extracted.segments }
|
|
832
|
+
: {}),
|
|
807
833
|
};
|
|
808
834
|
document = withDocumentIndexMetadata(document, embedded, spec);
|
|
809
835
|
await assertSideEffectAllowed?.();
|
|
@@ -837,6 +863,31 @@ export class DocumentService {
|
|
|
837
863
|
async getDocument(documentId, userId) {
|
|
838
864
|
return storageService.getDocument(documentId, userId);
|
|
839
865
|
}
|
|
866
|
+
/**
|
|
867
|
+
* Finds an existing live document with identical source bytes in the same
|
|
868
|
+
* scope (the same session, or both standing). Upload deduplication only —
|
|
869
|
+
* a match in another scope is not a duplicate because deleting one scope's
|
|
870
|
+
* copy must never remove another's.
|
|
871
|
+
*/
|
|
872
|
+
async findDuplicateDocument(userId, sessionId, contentSha256) {
|
|
873
|
+
const scope = sessionId ?? null;
|
|
874
|
+
const platform = getPlatformStorageRuntime();
|
|
875
|
+
const documents = await storageService.getAllDocuments(userId);
|
|
876
|
+
for (const candidate of documents) {
|
|
877
|
+
if ((candidate.sessionId ?? null) !== scope)
|
|
878
|
+
continue;
|
|
879
|
+
if (candidate.metadata?.contentSha256 !== contentSha256)
|
|
880
|
+
continue;
|
|
881
|
+
const reserved = await platform.domains.resourceDeletions.isReserved('document', candidate.id);
|
|
882
|
+
if (!reserved)
|
|
883
|
+
return candidate;
|
|
884
|
+
}
|
|
885
|
+
return undefined;
|
|
886
|
+
}
|
|
887
|
+
/** Documents in a chat's searchable scope: session uploads, selected collections, and standing uploads. */
|
|
888
|
+
async getDocumentsInScope(userId, sessionId, collectionIds) {
|
|
889
|
+
return (await storageService.getAllDocuments(userId)).filter(document => this.documentInScope(document, sessionId, collectionIds));
|
|
890
|
+
}
|
|
840
891
|
async getDocuments(userId, sessionId) {
|
|
841
892
|
const allDocs = await storageService.getAllDocuments(userId);
|
|
842
893
|
if (sessionId) {
|
|
@@ -892,6 +943,147 @@ export class DocumentService {
|
|
|
892
943
|
document.collectionId &&
|
|
893
944
|
collectionIds.includes(document.collectionId));
|
|
894
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* Principals that may retrieve this document's vectors: everyone granted
|
|
948
|
+
* the document directly plus everyone granted its collection. Grants ride
|
|
949
|
+
* the ACL table, so revocation applies on the very next query without
|
|
950
|
+
* re-embedding anything.
|
|
951
|
+
*/
|
|
952
|
+
async vectorGrantsForDocument(document) {
|
|
953
|
+
const security = getPersistence(encryptionService).repositories.security;
|
|
954
|
+
const rows = [
|
|
955
|
+
...(await security.grants.listForResource('document', document.id)),
|
|
956
|
+
];
|
|
957
|
+
if (document.collectionId) {
|
|
958
|
+
rows.push(...(await security.grants.listForResource('knowledge-collection', document.collectionId)));
|
|
959
|
+
}
|
|
960
|
+
const unique = new Map();
|
|
961
|
+
for (const row of rows) {
|
|
962
|
+
if (row.principal_type !== 'user' && row.principal_type !== 'group') {
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
unique.set(`${row.principal_type}${row.principal_id}`, {
|
|
966
|
+
type: row.principal_type,
|
|
967
|
+
id: row.principal_id,
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
return [...unique.values()];
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Re-publishes the vector ACL for every document a share change affects.
|
|
974
|
+
* Called after a grant on a document or knowledge collection is created
|
|
975
|
+
* or revoked.
|
|
976
|
+
*/
|
|
977
|
+
async syncShareGrants(resourceType, resourceId, ownerUserId) {
|
|
978
|
+
const platform = getPlatformStorageRuntime();
|
|
979
|
+
const documents = resourceType === 'document'
|
|
980
|
+
? await storageService
|
|
981
|
+
.getDocument(resourceId, ownerUserId)
|
|
982
|
+
.then(document => (document ? [document] : []))
|
|
983
|
+
: (await storageService.getAllDocuments(ownerUserId)).filter(document => document.collectionId === resourceId);
|
|
984
|
+
for (const document of documents) {
|
|
985
|
+
const grants = await this.vectorGrantsForDocument(document);
|
|
986
|
+
await platform.vectorStore.replaceResourceGrants({
|
|
987
|
+
actor: { userId: ownerUserId },
|
|
988
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
989
|
+
resourceIds: [document.id],
|
|
990
|
+
grants,
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Documents living in knowledge collections shared with the actor. The
|
|
996
|
+
* grant rows themselves are the authorization: they are resolved fresh
|
|
997
|
+
* (including group membership) on every call.
|
|
998
|
+
*/
|
|
999
|
+
async loadSharedScopeDocuments(userId, collectionIds) {
|
|
1000
|
+
const grants = await listGrantsForActor({ userId });
|
|
1001
|
+
const shared = [];
|
|
1002
|
+
const seenCollections = new Set();
|
|
1003
|
+
const seenDocuments = new Set();
|
|
1004
|
+
for (const grant of grants) {
|
|
1005
|
+
if (grant.resource_type !== 'knowledge-collection')
|
|
1006
|
+
continue;
|
|
1007
|
+
const collectionId = grant.resource_id;
|
|
1008
|
+
if (seenCollections.has(collectionId))
|
|
1009
|
+
continue;
|
|
1010
|
+
seenCollections.add(collectionId);
|
|
1011
|
+
if (grant.owner_user_id === userId)
|
|
1012
|
+
continue;
|
|
1013
|
+
if (collectionIds &&
|
|
1014
|
+
collectionIds.length > 0 &&
|
|
1015
|
+
!collectionIds.includes(collectionId)) {
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
const documents = (await storageService.getAllDocuments(grant.owner_user_id)).filter(document => document.collectionId === collectionId);
|
|
1019
|
+
for (const document of documents) {
|
|
1020
|
+
if (seenDocuments.has(document.id))
|
|
1021
|
+
continue;
|
|
1022
|
+
seenDocuments.add(document.id);
|
|
1023
|
+
shared.push({ document, ownerUserId: grant.owner_user_id });
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return shared;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Loads a document the actor may read: their own, or one reachable
|
|
1030
|
+
* through a document or collection grant. Shared results are read-only.
|
|
1031
|
+
*/
|
|
1032
|
+
async getDocumentShared(documentId, actor) {
|
|
1033
|
+
const own = await storageService.getDocument(documentId, actor.userId);
|
|
1034
|
+
if (own)
|
|
1035
|
+
return { document: own, ownerUserId: actor.userId };
|
|
1036
|
+
const ownerUserId = await getPersistence(encryptionService).repositories.resources.archive.ownerOf('document', documentId);
|
|
1037
|
+
if (!ownerUserId || ownerUserId === actor.userId)
|
|
1038
|
+
return undefined;
|
|
1039
|
+
const document = await storageService.getDocument(documentId, ownerUserId);
|
|
1040
|
+
if (!document)
|
|
1041
|
+
return undefined;
|
|
1042
|
+
let shared = await sharedMetaFor(actor, 'document', documentId, ownerUserId);
|
|
1043
|
+
if (!shared && document.collectionId) {
|
|
1044
|
+
shared = await sharedMetaFor(actor, 'knowledge-collection', document.collectionId, ownerUserId);
|
|
1045
|
+
}
|
|
1046
|
+
if (!shared)
|
|
1047
|
+
return undefined;
|
|
1048
|
+
return { document, ownerUserId, shared };
|
|
1049
|
+
}
|
|
1050
|
+
/** Documents shared with the actor through collection grants. */
|
|
1051
|
+
async listSharedDocuments(actor) {
|
|
1052
|
+
const entries = await this.loadSharedScopeDocuments(actor.userId);
|
|
1053
|
+
const result = [];
|
|
1054
|
+
for (const { document, ownerUserId } of entries) {
|
|
1055
|
+
if (!document.collectionId)
|
|
1056
|
+
continue;
|
|
1057
|
+
const meta = await sharedMetaFor(actor, 'knowledge-collection', document.collectionId, ownerUserId);
|
|
1058
|
+
if (meta)
|
|
1059
|
+
result.push({ document, shared: meta });
|
|
1060
|
+
}
|
|
1061
|
+
return result;
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* The actor's own collections followed by collections shared with them.
|
|
1065
|
+
*/
|
|
1066
|
+
async listCollectionsWithShared(actor) {
|
|
1067
|
+
const own = await storageService.getKnowledgeCollections(actor.userId);
|
|
1068
|
+
const sharedIds = await grantedResourceIdsFor(actor, 'knowledge-collection', new Set(own.map(collection => collection.id)));
|
|
1069
|
+
const shared = [];
|
|
1070
|
+
for (const collectionId of sharedIds) {
|
|
1071
|
+
const collection = await storageService.getKnowledgeCollectionById(collectionId);
|
|
1072
|
+
if (!collection || collection.ownerUserId === actor.userId)
|
|
1073
|
+
continue;
|
|
1074
|
+
const meta = await sharedMetaFor(actor, 'knowledge-collection', collectionId, collection.ownerUserId);
|
|
1075
|
+
if (!meta)
|
|
1076
|
+
continue;
|
|
1077
|
+
shared.push({
|
|
1078
|
+
id: collection.id,
|
|
1079
|
+
name: collection.name,
|
|
1080
|
+
createdAt: collection.createdAt,
|
|
1081
|
+
updatedAt: collection.updatedAt,
|
|
1082
|
+
shared: meta,
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
return [...own, ...shared];
|
|
1086
|
+
}
|
|
895
1087
|
async indexDocumentChunks(document, chunks, userId, spec, attemptCount = 1, signal, assertSideEffectAllowed) {
|
|
896
1088
|
const executionSpec = spec ?? (await this.captureEmbeddingExecutionSpec(userId));
|
|
897
1089
|
const embedded = embeddedChunks(chunks);
|
|
@@ -924,6 +1116,7 @@ export class DocumentService {
|
|
|
924
1116
|
mutated = true;
|
|
925
1117
|
await assertSideEffectAllowed?.();
|
|
926
1118
|
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
1119
|
+
const shareGrants = await this.vectorGrantsForDocument(document);
|
|
927
1120
|
for (let offset = 0; offset < embedded.length; offset += MAX_VECTOR_RECORDS_PER_UPSERT) {
|
|
928
1121
|
await assertSideEffectAllowed?.();
|
|
929
1122
|
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
@@ -947,6 +1140,7 @@ export class DocumentService {
|
|
|
947
1140
|
? { collectionId: document.collectionId }
|
|
948
1141
|
: {}),
|
|
949
1142
|
},
|
|
1143
|
+
...(shareGrants.length > 0 ? { grants: shareGrants } : {}),
|
|
950
1144
|
})),
|
|
951
1145
|
});
|
|
952
1146
|
await assertSideEffectAllowed?.();
|
|
@@ -992,9 +1186,19 @@ export class DocumentService {
|
|
|
992
1186
|
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
993
1187
|
}
|
|
994
1188
|
const documents = (await storageService.getAllDocuments(userId)).filter(document => this.documentInScope(document, sessionId, collectionIds));
|
|
1189
|
+
// Shared-collection documents join the corpus read-only: their chunks
|
|
1190
|
+
// feed the lexical ranking directly, and their vector hits pass the
|
|
1191
|
+
// store's ACL predicate through the grants published at share time.
|
|
1192
|
+
const sharedDocuments = await this.loadSharedScopeDocuments(userId, collectionIds);
|
|
995
1193
|
const platform = getPlatformStorageRuntime();
|
|
996
1194
|
const chunksById = new Map();
|
|
997
|
-
const
|
|
1195
|
+
for (const { document } of sharedDocuments) {
|
|
1196
|
+
throwIfChatGenerationCancelled(signal);
|
|
1197
|
+
const documentChunks = await this.loadDocumentChunks(document.id);
|
|
1198
|
+
for (const chunk of documentChunks) {
|
|
1199
|
+
chunksById.set(chunk.id, { chunk, document });
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
998
1202
|
for (const document of documents) {
|
|
999
1203
|
throwIfChatGenerationCancelled(signal);
|
|
1000
1204
|
let searchableDocument = document;
|
|
@@ -1026,7 +1230,6 @@ export class DocumentService {
|
|
|
1026
1230
|
// and deletion cleanup through the shared document resource lease.
|
|
1027
1231
|
// PostgreSQL/team reads never mutate PGVector.
|
|
1028
1232
|
const publishedIndex = readDocumentIndexMetadata(searchableDocument);
|
|
1029
|
-
const canProveCurrentEmbeddingModel = documentIndexMatchesSpec(publishedIndex, executionSpec);
|
|
1030
1233
|
const localIndexProbe = platform.dialect === 'sqlite'
|
|
1031
1234
|
? exactLocalDocumentIndexProbe(searchableDocument, documentChunks, userId, executionSpec)
|
|
1032
1235
|
: undefined;
|
|
@@ -1069,24 +1272,20 @@ export class DocumentService {
|
|
|
1069
1272
|
for (const chunk of documentChunks) {
|
|
1070
1273
|
// PostgreSQL deliberately keeps embeddings only in PGVector, so a
|
|
1071
1274
|
// relational chunk without an `embedding` property can still be the
|
|
1072
|
-
// authoritative content for a vector hit.
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1075
|
-
//
|
|
1275
|
+
// authoritative content for a vector hit. Every current relational
|
|
1276
|
+
// chunk joins the candidate set: vector hits hydrate from it and
|
|
1277
|
+
// the BM25 side of the hybrid ranking scores it, so chunks without
|
|
1278
|
+
// a current embedding stay reachable.
|
|
1076
1279
|
chunksById.set(chunk.id, {
|
|
1077
1280
|
chunk,
|
|
1078
1281
|
document: searchableDocument,
|
|
1079
1282
|
});
|
|
1080
|
-
const indexedForSemanticQuery = canProveCurrentEmbeddingModel &&
|
|
1081
|
-
publishedIndex !== undefined &&
|
|
1082
|
-
publishedIndex.dimensions !== null &&
|
|
1083
|
-
(platform.dialect === 'postgres' || localIndexReady);
|
|
1084
|
-
if (!indexedForSemanticQuery) {
|
|
1085
|
-
unembedded.push({ chunk, document: searchableDocument });
|
|
1086
|
-
}
|
|
1087
1283
|
}
|
|
1088
1284
|
}
|
|
1089
|
-
const resourceIds =
|
|
1285
|
+
const resourceIds = [
|
|
1286
|
+
...documents.map(document => document.id),
|
|
1287
|
+
...sharedDocuments.map(entry => entry.document.id),
|
|
1288
|
+
];
|
|
1090
1289
|
const hits = [];
|
|
1091
1290
|
for (let offset = 0; offset < resourceIds.length; offset += MAX_VECTOR_RESOURCE_FILTERS) {
|
|
1092
1291
|
throwIfChatGenerationCancelled(signal);
|
|
@@ -1106,37 +1305,39 @@ export class DocumentService {
|
|
|
1106
1305
|
hits.sort((left, right) => right.score - left.score ||
|
|
1107
1306
|
left.ownerUserId.localeCompare(right.ownerUserId) ||
|
|
1108
1307
|
left.id.localeCompare(right.id));
|
|
1109
|
-
|
|
1110
|
-
|
|
1308
|
+
// Hybrid assembly: fuse the vector ranking with an in-process BM25
|
|
1309
|
+
// ranking over every in-scope chunk. The lexical side keeps chunks
|
|
1310
|
+
// without current embeddings reachable and lets an exact term match
|
|
1311
|
+
// outrank a semantically weak neighbor; fusion means neither ranking
|
|
1312
|
+
// silently dominates the other.
|
|
1313
|
+
const semanticRanked = [];
|
|
1314
|
+
const semanticScores = new Map();
|
|
1111
1315
|
for (const hit of hits) {
|
|
1112
|
-
if (top.length >= limit)
|
|
1113
|
-
break;
|
|
1114
1316
|
const match = chunksById.get(hit.id);
|
|
1115
1317
|
if (!match ||
|
|
1116
1318
|
match.document.id !== hit.resourceId ||
|
|
1117
1319
|
sourceRevision(match.chunk) !== hit.sourceRevision ||
|
|
1118
|
-
|
|
1320
|
+
semanticScores.has(match.chunk.id)) {
|
|
1119
1321
|
continue;
|
|
1120
1322
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
filename: match.document.filename,
|
|
1124
|
-
});
|
|
1125
|
-
selectedChunkIds.add(match.chunk.id);
|
|
1323
|
+
semanticRanked.push(match.chunk.id);
|
|
1324
|
+
semanticScores.set(match.chunk.id, hit.score);
|
|
1126
1325
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1326
|
+
const lexicalScored = this.scoreChunksByKeywords(query, [
|
|
1327
|
+
...chunksById.values(),
|
|
1328
|
+
]);
|
|
1329
|
+
const fused = reciprocalRankFusion([
|
|
1330
|
+
semanticRanked,
|
|
1331
|
+
lexicalScored.map(entry => entry.chunk.id),
|
|
1332
|
+
]);
|
|
1333
|
+
const top = [];
|
|
1334
|
+
for (const { id, score } of fused) {
|
|
1335
|
+
if (top.length >= limit)
|
|
1336
|
+
break;
|
|
1337
|
+
const match = chunksById.get(id);
|
|
1338
|
+
if (!match)
|
|
1339
|
+
continue;
|
|
1340
|
+
top.push(this.hydrateRetrievedChunk(match.chunk, match.document, score));
|
|
1140
1341
|
}
|
|
1141
1342
|
if (top.length > 0)
|
|
1142
1343
|
return top;
|
|
@@ -1151,25 +1352,13 @@ export class DocumentService {
|
|
|
1151
1352
|
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
1152
1353
|
}
|
|
1153
1354
|
}
|
|
1154
|
-
/**
|
|
1355
|
+
/** BM25 scores for a set of chunks, best first. */
|
|
1155
1356
|
scoreChunksByKeywords(query, entries) {
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
.
|
|
1159
|
-
.
|
|
1160
|
-
|
|
1161
|
-
for (const { chunk, document } of entries) {
|
|
1162
|
-
const chunkText = chunk.content.toLowerCase();
|
|
1163
|
-
let score = 0;
|
|
1164
|
-
for (const term of searchTerms) {
|
|
1165
|
-
// Escape special regex characters to prevent injection
|
|
1166
|
-
const escapedTerm = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1167
|
-
score += (chunkText.match(new RegExp(escapedTerm, 'gi')) || []).length;
|
|
1168
|
-
}
|
|
1169
|
-
if (score > 0)
|
|
1170
|
-
scored.push({ chunk, score, document });
|
|
1171
|
-
}
|
|
1172
|
-
return scored.sort((a, b) => b.score - a.score);
|
|
1357
|
+
const byId = new Map(entries.map(entry => [entry.chunk.id, entry]));
|
|
1358
|
+
return scoreCandidatesBm25(query, entries.map(entry => ({ id: entry.chunk.id, text: entry.chunk.content })), { requireQueryWordMatch: true }).map(({ id, score }) => {
|
|
1359
|
+
const entry = byId.get(id);
|
|
1360
|
+
return { chunk: entry.chunk, score, document: entry.document };
|
|
1361
|
+
});
|
|
1173
1362
|
}
|
|
1174
1363
|
async keywordSearchDocuments(query, userId, sessionId, limit = 5, collectionIds, signal) {
|
|
1175
1364
|
const candidates = [];
|
|
@@ -1184,12 +1373,28 @@ export class DocumentService {
|
|
|
1184
1373
|
candidates.push({ chunk, document });
|
|
1185
1374
|
}
|
|
1186
1375
|
}
|
|
1376
|
+
for (const { document } of await this.loadSharedScopeDocuments(userId, collectionIds)) {
|
|
1377
|
+
throwIfChatGenerationCancelled(signal);
|
|
1378
|
+
const documentChunks = await this.loadDocumentChunks(document.id);
|
|
1379
|
+
for (const chunk of documentChunks) {
|
|
1380
|
+
candidates.push({ chunk, document });
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1187
1383
|
throwIfChatGenerationCancelled(signal);
|
|
1188
1384
|
const results = this.scoreChunksByKeywords(query, candidates);
|
|
1189
|
-
return results
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1385
|
+
return results
|
|
1386
|
+
.slice(0, limit)
|
|
1387
|
+
.map(result => this.hydrateRetrievedChunk(result.chunk, result.document, result.score));
|
|
1388
|
+
}
|
|
1389
|
+
/** Attaches filename, score, and source location to a retrieval result. */
|
|
1390
|
+
hydrateRetrievedChunk(chunk, document, score) {
|
|
1391
|
+
const location = resolveSegmentLabel(readDocumentSegments(document.metadata), chunk.startChar, chunk.endChar);
|
|
1392
|
+
return {
|
|
1393
|
+
...chunk,
|
|
1394
|
+
filename: document.filename,
|
|
1395
|
+
...(score !== undefined ? { score } : {}),
|
|
1396
|
+
...(location ? { location } : {}),
|
|
1397
|
+
};
|
|
1193
1398
|
}
|
|
1194
1399
|
// Get relevant context for RAG
|
|
1195
1400
|
async getRelevantContext(query, userId, sessionId) {
|