libre-webui 0.21.3 → 0.22.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 +308 -328
- package/backend/dist/cli/migrateSqliteToPostgres.d.ts +2 -0
- package/backend/dist/cli/migrateSqliteToPostgres.d.ts.map +1 -0
- package/backend/dist/cli/migrateSqliteToPostgres.js +113 -0
- package/backend/dist/cli/migrateSqliteToPostgres.js.map +1 -0
- package/backend/dist/cli/recoveryBackup.d.ts +3 -0
- package/backend/dist/cli/recoveryBackup.d.ts.map +1 -0
- package/backend/dist/cli/recoveryBackup.js +251 -0
- package/backend/dist/cli/recoveryBackup.js.map +1 -0
- package/backend/dist/cli/recoveryInventory.d.ts +2 -0
- package/backend/dist/cli/recoveryInventory.d.ts.map +1 -0
- package/backend/dist/cli/recoveryInventory.js +109 -0
- package/backend/dist/cli/recoveryInventory.js.map +1 -0
- package/backend/dist/db.d.ts +27 -0
- package/backend/dist/db.d.ts.map +1 -1
- package/backend/dist/db.js +333 -16
- package/backend/dist/db.js.map +1 -1
- package/backend/dist/env.d.ts.map +1 -1
- package/backend/dist/env.js +12 -2
- package/backend/dist/env.js.map +1 -1
- package/backend/dist/index.d.ts.map +1 -1
- package/backend/dist/index.js +235 -47
- package/backend/dist/index.js.map +1 -1
- package/backend/dist/main.d.ts +2 -0
- package/backend/dist/main.d.ts.map +1 -0
- package/backend/dist/main.js +137 -0
- package/backend/dist/main.js.map +1 -0
- package/backend/dist/middleware/auth.d.ts.map +1 -1
- package/backend/dist/middleware/auth.js +7 -3
- package/backend/dist/middleware/auth.js.map +1 -1
- package/backend/dist/middleware/chatCancellationAdmission.d.ts +7 -0
- package/backend/dist/middleware/chatCancellationAdmission.d.ts.map +1 -0
- package/backend/dist/middleware/chatCancellationAdmission.js +17 -0
- package/backend/dist/middleware/chatCancellationAdmission.js.map +1 -0
- package/backend/dist/middleware/coordinatedRateLimit.d.ts +18 -0
- package/backend/dist/middleware/coordinatedRateLimit.d.ts.map +1 -0
- package/backend/dist/middleware/coordinatedRateLimit.js +52 -0
- package/backend/dist/middleware/coordinatedRateLimit.js.map +1 -0
- package/backend/dist/middleware/sharedRateLimit.d.ts +26 -0
- package/backend/dist/middleware/sharedRateLimit.d.ts.map +1 -0
- package/backend/dist/middleware/sharedRateLimit.js +99 -0
- package/backend/dist/middleware/sharedRateLimit.js.map +1 -0
- package/backend/dist/models/personaModel.d.ts +1 -26
- package/backend/dist/models/personaModel.d.ts.map +1 -1
- package/backend/dist/models/personaModel.js +54 -247
- package/backend/dist/models/personaModel.js.map +1 -1
- package/backend/dist/models/userModel.d.ts +23 -66
- package/backend/dist/models/userModel.d.ts.map +1 -1
- package/backend/dist/models/userModel.js +110 -187
- package/backend/dist/models/userModel.js.map +1 -1
- package/backend/dist/persistence/chatGenerationTypes.d.ts +24 -0
- package/backend/dist/persistence/chatGenerationTypes.d.ts.map +1 -0
- package/backend/dist/persistence/chatGenerationTypes.js +7 -0
- package/backend/dist/persistence/chatGenerationTypes.js.map +1 -0
- package/backend/dist/persistence/extensionTypes.d.ts +185 -0
- package/backend/dist/persistence/extensionTypes.d.ts.map +1 -0
- package/backend/dist/persistence/extensionTypes.js +13 -0
- package/backend/dist/persistence/extensionTypes.js.map +1 -0
- package/backend/dist/persistence/identityDeletionTypes.d.ts +16 -0
- package/backend/dist/persistence/identityDeletionTypes.d.ts.map +1 -0
- package/backend/dist/persistence/identityDeletionTypes.js +7 -0
- package/backend/dist/persistence/identityDeletionTypes.js.map +1 -0
- package/backend/dist/persistence/index.d.ts +48 -0
- package/backend/dist/persistence/index.d.ts.map +1 -0
- package/backend/dist/persistence/index.js +159 -0
- package/backend/dist/persistence/index.js.map +1 -0
- package/backend/dist/persistence/postgresConfig.d.ts +32 -0
- package/backend/dist/persistence/postgresConfig.d.ts.map +1 -0
- package/backend/dist/persistence/postgresConfig.js +91 -0
- package/backend/dist/persistence/postgresConfig.js.map +1 -0
- package/backend/dist/persistence/postgresCoreMigration.d.ts +8 -0
- package/backend/dist/persistence/postgresCoreMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresCoreMigration.js +179 -0
- package/backend/dist/persistence/postgresCoreMigration.js.map +1 -0
- package/backend/dist/persistence/postgresDatabase.d.ts +40 -0
- package/backend/dist/persistence/postgresDatabase.d.ts.map +1 -0
- package/backend/dist/persistence/postgresDatabase.js +148 -0
- package/backend/dist/persistence/postgresDatabase.js.map +1 -0
- package/backend/dist/persistence/postgresExtensionMigration.d.ts +4 -0
- package/backend/dist/persistence/postgresExtensionMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresExtensionMigration.js +143 -0
- package/backend/dist/persistence/postgresExtensionMigration.js.map +1 -0
- package/backend/dist/persistence/postgresExtensionRepositories.d.ts +6 -0
- package/backend/dist/persistence/postgresExtensionRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/postgresExtensionRepositories.js +550 -0
- package/backend/dist/persistence/postgresExtensionRepositories.js.map +1 -0
- package/backend/dist/persistence/postgresImportState.d.ts +9 -0
- package/backend/dist/persistence/postgresImportState.d.ts.map +1 -0
- package/backend/dist/persistence/postgresImportState.js +64 -0
- package/backend/dist/persistence/postgresImportState.js.map +1 -0
- package/backend/dist/persistence/postgresMigrationRegistry.d.ts +4 -0
- package/backend/dist/persistence/postgresMigrationRegistry.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrationRegistry.js +33 -0
- package/backend/dist/persistence/postgresMigrationRegistry.js.map +1 -0
- package/backend/dist/persistence/postgresMigrationTypes.d.ts +24 -0
- package/backend/dist/persistence/postgresMigrationTypes.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrationTypes.js +7 -0
- package/backend/dist/persistence/postgresMigrationTypes.js.map +1 -0
- package/backend/dist/persistence/postgresMigrations.d.ts +15 -0
- package/backend/dist/persistence/postgresMigrations.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrations.js +333 -0
- package/backend/dist/persistence/postgresMigrations.js.map +1 -0
- package/backend/dist/persistence/postgresPersistence.d.ts +17 -0
- package/backend/dist/persistence/postgresPersistence.d.ts.map +1 -0
- package/backend/dist/persistence/postgresPersistence.js +332 -0
- package/backend/dist/persistence/postgresPersistence.js.map +1 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.d.ts +4 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.js +40 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.js.map +1 -0
- package/backend/dist/persistence/postgresResourceRepositories.d.ts +7 -0
- package/backend/dist/persistence/postgresResourceRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/postgresResourceRepositories.js +776 -0
- package/backend/dist/persistence/postgresResourceRepositories.js.map +1 -0
- package/backend/dist/persistence/postgresSchemaInspector.d.ts +14 -0
- package/backend/dist/persistence/postgresSchemaInspector.d.ts.map +1 -0
- package/backend/dist/persistence/postgresSchemaInspector.js +817 -0
- package/backend/dist/persistence/postgresSchemaInspector.js.map +1 -0
- package/backend/dist/persistence/resourceTypes.d.ts +207 -0
- package/backend/dist/persistence/resourceTypes.d.ts.map +1 -0
- package/backend/dist/persistence/resourceTypes.js +38 -0
- package/backend/dist/persistence/resourceTypes.js.map +1 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.d.ts +4 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.js +494 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.js.map +1 -0
- package/backend/dist/persistence/sqliteMigrations.d.ts +93 -0
- package/backend/dist/persistence/sqliteMigrations.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteMigrations.js +2232 -0
- package/backend/dist/persistence/sqliteMigrations.js.map +1 -0
- package/backend/dist/persistence/sqlitePersistence.d.ts +23 -0
- package/backend/dist/persistence/sqlitePersistence.d.ts.map +1 -0
- package/backend/dist/persistence/sqlitePersistence.js +596 -0
- package/backend/dist/persistence/sqlitePersistence.js.map +1 -0
- package/backend/dist/persistence/sqliteResourceRepositories.d.ts +4 -0
- package/backend/dist/persistence/sqliteResourceRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteResourceRepositories.js +663 -0
- package/backend/dist/persistence/sqliteResourceRepositories.js.map +1 -0
- package/backend/dist/persistence/sqliteSyncExecutor.d.ts +5 -0
- package/backend/dist/persistence/sqliteSyncExecutor.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteSyncExecutor.js +19 -0
- package/backend/dist/persistence/sqliteSyncExecutor.js.map +1 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.d.ts +80 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.js +1543 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.js.map +1 -0
- package/backend/dist/persistence/types.d.ts +131 -0
- package/backend/dist/persistence/types.d.ts.map +1 -0
- package/backend/dist/persistence/types.js +18 -0
- package/backend/dist/persistence/types.js.map +1 -0
- package/backend/dist/persistence/voiceProfileNameLookup.d.ts +9 -0
- package/backend/dist/persistence/voiceProfileNameLookup.d.ts.map +1 -0
- package/backend/dist/persistence/voiceProfileNameLookup.js +15 -0
- package/backend/dist/persistence/voiceProfileNameLookup.js.map +1 -0
- package/backend/dist/platform/coordination/index.d.ts +7 -0
- package/backend/dist/platform/coordination/index.d.ts.map +1 -0
- package/backend/dist/platform/coordination/index.js +24 -0
- package/backend/dist/platform/coordination/index.js.map +1 -0
- package/backend/dist/platform/coordination/localCoordinator.d.ts +49 -0
- package/backend/dist/platform/coordination/localCoordinator.d.ts.map +1 -0
- package/backend/dist/platform/coordination/localCoordinator.js +380 -0
- package/backend/dist/platform/coordination/localCoordinator.js.map +1 -0
- package/backend/dist/platform/coordination/redisCoordinator.d.ts +83 -0
- package/backend/dist/platform/coordination/redisCoordinator.d.ts.map +1 -0
- package/backend/dist/platform/coordination/redisCoordinator.js +726 -0
- package/backend/dist/platform/coordination/redisCoordinator.js.map +1 -0
- package/backend/dist/platform/coordination/service.d.ts +11 -0
- package/backend/dist/platform/coordination/service.d.ts.map +1 -0
- package/backend/dist/platform/coordination/service.js +55 -0
- package/backend/dist/platform/coordination/service.js.map +1 -0
- package/backend/dist/platform/coordination/sharedAdmission.d.ts +53 -0
- package/backend/dist/platform/coordination/sharedAdmission.d.ts.map +1 -0
- package/backend/dist/platform/coordination/sharedAdmission.js +194 -0
- package/backend/dist/platform/coordination/sharedAdmission.js.map +1 -0
- package/backend/dist/platform/coordination/types.d.ts +76 -0
- package/backend/dist/platform/coordination/types.d.ts.map +1 -0
- package/backend/dist/platform/coordination/types.js +32 -0
- package/backend/dist/platform/coordination/types.js.map +1 -0
- package/backend/dist/platform/events/durableEventGateway.d.ts +54 -0
- package/backend/dist/platform/events/durableEventGateway.d.ts.map +1 -0
- package/backend/dist/platform/events/durableEventGateway.js +262 -0
- package/backend/dist/platform/events/durableEventGateway.js.map +1 -0
- package/backend/dist/platform/events/index.d.ts +3 -0
- package/backend/dist/platform/events/index.d.ts.map +1 -0
- package/backend/dist/platform/events/index.js +8 -0
- package/backend/dist/platform/events/index.js.map +1 -0
- package/backend/dist/platform/events/service.d.ts +8 -0
- package/backend/dist/platform/events/service.d.ts.map +1 -0
- package/backend/dist/platform/events/service.js +25 -0
- package/backend/dist/platform/events/service.js.map +1 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.js +55 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.js +38 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/domainJobContracts.d.ts +30 -0
- package/backend/dist/platform/jobs/domainJobContracts.d.ts.map +1 -0
- package/backend/dist/platform/jobs/domainJobContracts.js +53 -0
- package/backend/dist/platform/jobs/domainJobContracts.js.map +1 -0
- package/backend/dist/platform/jobs/domainJobHandlers.d.ts +11 -0
- package/backend/dist/platform/jobs/domainJobHandlers.d.ts.map +1 -0
- package/backend/dist/platform/jobs/domainJobHandlers.js +612 -0
- package/backend/dist/platform/jobs/domainJobHandlers.js.map +1 -0
- package/backend/dist/platform/jobs/durableEventIdentity.d.ts +8 -0
- package/backend/dist/platform/jobs/durableEventIdentity.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableEventIdentity.js +33 -0
- package/backend/dist/platform/jobs/durableEventIdentity.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntime.d.ts +57 -0
- package/backend/dist/platform/jobs/durableJobRuntime.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntime.js +131 -0
- package/backend/dist/platform/jobs/durableJobRuntime.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.d.ts +28 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.js +62 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobService.d.ts +85 -0
- package/backend/dist/platform/jobs/durableJobService.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobService.js +726 -0
- package/backend/dist/platform/jobs/durableJobService.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobTypes.d.ts +195 -0
- package/backend/dist/platform/jobs/durableJobTypes.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobTypes.js +72 -0
- package/backend/dist/platform/jobs/durableJobTypes.js.map +1 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.d.ts +87 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.d.ts.map +1 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js +429 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js.map +1 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.js +36 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/index.d.ts +18 -0
- package/backend/dist/platform/jobs/index.d.ts.map +1 -0
- package/backend/dist/platform/jobs/index.js +34 -0
- package/backend/dist/platform/jobs/index.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.d.ts +4 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.js +25 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.d.ts +4 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.js +23 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.d.ts +11 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.js +106 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.d.ts +88 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.js +1185 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.d.ts +86 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.js +696 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.d.ts +53 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js +393 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js.map +1 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.js +43 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.d.ts +166 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.d.ts.map +1 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.js +1008 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.js.map +1 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.d.ts +4 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.js +46 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.js +38 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.js.map +1 -0
- package/backend/dist/platform/ollamaRuntimeConfig.d.ts +40 -0
- package/backend/dist/platform/ollamaRuntimeConfig.d.ts.map +1 -0
- package/backend/dist/platform/ollamaRuntimeConfig.js +72 -0
- package/backend/dist/platform/ollamaRuntimeConfig.js.map +1 -0
- package/backend/dist/platform/recovery/backupArchive.d.ts +120 -0
- package/backend/dist/platform/recovery/backupArchive.d.ts.map +1 -0
- package/backend/dist/platform/recovery/backupArchive.js +842 -0
- package/backend/dist/platform/recovery/backupArchive.js.map +1 -0
- package/backend/dist/platform/recovery/index.d.ts +3 -0
- package/backend/dist/platform/recovery/index.d.ts.map +1 -0
- package/backend/dist/platform/recovery/index.js +8 -0
- package/backend/dist/platform/recovery/index.js.map +1 -0
- package/backend/dist/platform/recovery/teamBackupArchive.d.ts +98 -0
- package/backend/dist/platform/recovery/teamBackupArchive.d.ts.map +1 -0
- package/backend/dist/platform/recovery/teamBackupArchive.js +1203 -0
- package/backend/dist/platform/recovery/teamBackupArchive.js.map +1 -0
- package/backend/dist/platform/runtimeConfig.d.ts +70 -0
- package/backend/dist/platform/runtimeConfig.d.ts.map +1 -0
- package/backend/dist/platform/runtimeConfig.js +205 -0
- package/backend/dist/platform/runtimeConfig.js.map +1 -0
- package/backend/dist/platform/storage/aesGcmKeyring.d.ts +26 -0
- package/backend/dist/platform/storage/aesGcmKeyring.d.ts.map +1 -0
- package/backend/dist/platform/storage/aesGcmKeyring.js +135 -0
- package/backend/dist/platform/storage/aesGcmKeyring.js.map +1 -0
- package/backend/dist/platform/storage/blobReferenceRepository.d.ts +36 -0
- package/backend/dist/platform/storage/blobReferenceRepository.d.ts.map +1 -0
- package/backend/dist/platform/storage/blobReferenceRepository.js +117 -0
- package/backend/dist/platform/storage/blobReferenceRepository.js.map +1 -0
- package/backend/dist/platform/storage/blobStore.d.ts +111 -0
- package/backend/dist/platform/storage/blobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/blobStore.js +46 -0
- package/backend/dist/platform/storage/blobStore.js.map +1 -0
- package/backend/dist/platform/storage/documentVectorIndex.d.ts +44 -0
- package/backend/dist/platform/storage/documentVectorIndex.d.ts.map +1 -0
- package/backend/dist/platform/storage/documentVectorIndex.js +110 -0
- package/backend/dist/platform/storage/documentVectorIndex.js.map +1 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.d.ts +82 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.d.ts.map +1 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.js +583 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.js.map +1 -0
- package/backend/dist/platform/storage/index.d.ts +19 -0
- package/backend/dist/platform/storage/index.d.ts.map +1 -0
- package/backend/dist/platform/storage/index.js +35 -0
- package/backend/dist/platform/storage/index.js.map +1 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.d.ts +120 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.js +1205 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.js.map +1 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.d.ts +12 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.d.ts.map +1 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.js +25 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.js.map +1 -0
- package/backend/dist/platform/storage/pgVectorStore.d.ts +37 -0
- package/backend/dist/platform/storage/pgVectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/pgVectorStore.js +493 -0
- package/backend/dist/platform/storage/pgVectorStore.js.map +1 -0
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts +244 -0
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/platformDomainRepositories.js +7 -0
- package/backend/dist/platform/storage/platformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/platformStorageRuntime.d.ts +35 -0
- package/backend/dist/platform/storage/platformStorageRuntime.d.ts.map +1 -0
- package/backend/dist/platform/storage/platformStorageRuntime.js +299 -0
- package/backend/dist/platform/storage/platformStorageRuntime.js.map +1 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.d.ts +4 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js +1017 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.d.ts +4 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.d.ts.map +1 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.js +40 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.js.map +1 -0
- package/backend/dist/platform/storage/resourceContentCleanup.d.ts +29 -0
- package/backend/dist/platform/storage/resourceContentCleanup.d.ts.map +1 -0
- package/backend/dist/platform/storage/resourceContentCleanup.js +100 -0
- package/backend/dist/platform/storage/resourceContentCleanup.js.map +1 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.d.ts +14 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.d.ts.map +1 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.js +31 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.js.map +1 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.d.ts +140 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.js +1309 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.js.map +1 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts +71 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js +766 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js.map +1 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.d.ts +4 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js +1037 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.d.ts +25 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.js +1292 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.js.map +1 -0
- package/backend/dist/platform/storage/storageFactory.d.ts +81 -0
- package/backend/dist/platform/storage/storageFactory.d.ts.map +1 -0
- package/backend/dist/platform/storage/storageFactory.js +518 -0
- package/backend/dist/platform/storage/storageFactory.js.map +1 -0
- package/backend/dist/platform/storage/storageSchemaContracts.d.ts +22 -0
- package/backend/dist/platform/storage/storageSchemaContracts.d.ts.map +1 -0
- package/backend/dist/platform/storage/storageSchemaContracts.js +299 -0
- package/backend/dist/platform/storage/storageSchemaContracts.js.map +1 -0
- package/backend/dist/platform/storage/vectorStore.d.ts +117 -0
- package/backend/dist/platform/storage/vectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/vectorStore.js +40 -0
- package/backend/dist/platform/storage/vectorStore.js.map +1 -0
- package/backend/dist/platform/workPersistence/index.d.ts +9 -0
- package/backend/dist/platform/workPersistence/index.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/index.js +14 -0
- package/backend/dist/platform/workPersistence/index.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.d.ts +9 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.js +47 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.d.ts +3 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.js +28 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.d.ts +3 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.js +101 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.d.ts +79 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.js +521 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.js.map +1 -0
- package/backend/dist/platform/workPersistence/service.d.ts +6 -0
- package/backend/dist/platform/workPersistence/service.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/service.js +27 -0
- package/backend/dist/platform/workPersistence/service.js.map +1 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.d.ts +77 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.js +463 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.js.map +1 -0
- package/backend/dist/platform/workPersistence/types.d.ts +159 -0
- package/backend/dist/platform/workPersistence/types.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/types.js +13 -0
- package/backend/dist/platform/workPersistence/types.js.map +1 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.d.ts +13 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.js +7 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.js.map +1 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.d.ts +8 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.js +25 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.js.map +1 -0
- package/backend/dist/platform/workPersistence/workTextSafety.d.ts +3 -0
- package/backend/dist/platform/workPersistence/workTextSafety.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workTextSafety.js +8 -0
- package/backend/dist/platform/workPersistence/workTextSafety.js.map +1 -0
- package/backend/dist/routes/agentCli.js +1 -1
- package/backend/dist/routes/agentCli.js.map +1 -1
- package/backend/dist/routes/artifacts.d.ts.map +1 -1
- package/backend/dist/routes/artifacts.js +2 -1
- package/backend/dist/routes/artifacts.js.map +1 -1
- package/backend/dist/routes/auth.d.ts.map +1 -1
- package/backend/dist/routes/auth.js +64 -18
- 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 +519 -85
- 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 +134 -28
- 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 -1
- package/backend/dist/routes/embeddings.js.map +1 -1
- package/backend/dist/routes/health.d.ts +3 -0
- package/backend/dist/routes/health.d.ts.map +1 -0
- package/backend/dist/routes/health.js +52 -0
- package/backend/dist/routes/health.js.map +1 -0
- package/backend/dist/routes/huggingfaceHub.d.ts.map +1 -1
- package/backend/dist/routes/huggingfaceHub.js +2 -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 +42 -10
- package/backend/dist/routes/imageGen.js.map +1 -1
- package/backend/dist/routes/jobs.d.ts +3 -0
- package/backend/dist/routes/jobs.d.ts.map +1 -0
- package/backend/dist/routes/jobs.js +117 -0
- package/backend/dist/routes/jobs.js.map +1 -0
- package/backend/dist/routes/libreClaw.d.ts.map +1 -1
- package/backend/dist/routes/libreClaw.js +10 -7
- package/backend/dist/routes/libreClaw.js.map +1 -1
- package/backend/dist/routes/media.d.ts.map +1 -1
- package/backend/dist/routes/media.js +523 -77
- 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 +21 -21
- package/backend/dist/routes/notes.js.map +1 -1
- package/backend/dist/routes/ollama.d.ts.map +1 -1
- package/backend/dist/routes/ollama.js +40 -12
- 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 +4 -2
- 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 +79 -51
- package/backend/dist/routes/plugins.js.map +1 -1
- package/backend/dist/routes/preferences.d.ts.map +1 -1
- package/backend/dist/routes/preferences.js +290 -25
- package/backend/dist/routes/preferences.js.map +1 -1
- package/backend/dist/routes/search.d.ts.map +1 -1
- package/backend/dist/routes/search.js +23 -14
- package/backend/dist/routes/search.js.map +1 -1
- package/backend/dist/routes/stt.d.ts +9 -0
- package/backend/dist/routes/stt.d.ts.map +1 -0
- package/backend/dist/routes/stt.js +217 -0
- package/backend/dist/routes/stt.js.map +1 -0
- package/backend/dist/routes/systemDiagnostics.d.ts.map +1 -1
- package/backend/dist/routes/systemDiagnostics.js +2 -1
- package/backend/dist/routes/systemDiagnostics.js.map +1 -1
- package/backend/dist/routes/tts.d.ts.map +1 -1
- package/backend/dist/routes/tts.js +577 -28
- 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 +16 -25
- 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 +167 -113
- package/backend/dist/routes/work.js.map +1 -1
- package/backend/dist/services/agentAccessService.d.ts +2 -2
- package/backend/dist/services/agentAccessService.d.ts.map +1 -1
- package/backend/dist/services/agentAccessService.js +5 -14
- package/backend/dist/services/agentAccessService.js.map +1 -1
- package/backend/dist/services/agentCliService.d.ts +3 -2
- package/backend/dist/services/agentCliService.d.ts.map +1 -1
- package/backend/dist/services/agentCliService.js +44 -16
- package/backend/dist/services/agentCliService.js.map +1 -1
- package/backend/dist/services/assistantCompletionService.d.ts +2 -1
- package/backend/dist/services/assistantCompletionService.d.ts.map +1 -1
- package/backend/dist/services/assistantCompletionService.js +7 -3
- package/backend/dist/services/assistantCompletionService.js.map +1 -1
- package/backend/dist/services/authService.d.ts +7 -2
- package/backend/dist/services/authService.d.ts.map +1 -1
- package/backend/dist/services/authService.js +23 -10
- package/backend/dist/services/authService.js.map +1 -1
- package/backend/dist/services/chatGenerationService.d.ts +5 -4
- package/backend/dist/services/chatGenerationService.d.ts.map +1 -1
- package/backend/dist/services/chatGenerationService.js +23 -17
- package/backend/dist/services/chatGenerationService.js.map +1 -1
- package/backend/dist/services/chatRequestService.d.ts +4 -3
- package/backend/dist/services/chatRequestService.d.ts.map +1 -1
- package/backend/dist/services/chatRequestService.js +3 -3
- package/backend/dist/services/chatRequestService.js.map +1 -1
- package/backend/dist/services/chatService.d.ts +66 -16
- package/backend/dist/services/chatService.d.ts.map +1 -1
- package/backend/dist/services/chatService.js +402 -111
- package/backend/dist/services/chatService.js.map +1 -1
- package/backend/dist/services/codexOAuthService.d.ts +2 -2
- package/backend/dist/services/codexOAuthService.d.ts.map +1 -1
- package/backend/dist/services/codexOAuthService.js +63 -7
- package/backend/dist/services/codexOAuthService.js.map +1 -1
- package/backend/dist/services/dataArchiveService.d.ts +88 -0
- package/backend/dist/services/dataArchiveService.d.ts.map +1 -0
- package/backend/dist/services/dataArchiveService.js +1027 -0
- package/backend/dist/services/dataArchiveService.js.map +1 -0
- package/backend/dist/services/documentService.d.ts +67 -14
- package/backend/dist/services/documentService.d.ts.map +1 -1
- package/backend/dist/services/documentService.js +938 -193
- package/backend/dist/services/documentService.js.map +1 -1
- package/backend/dist/services/durableChatCompletion.d.ts +16 -0
- package/backend/dist/services/durableChatCompletion.d.ts.map +1 -0
- package/backend/dist/services/durableChatCompletion.js +34 -0
- package/backend/dist/services/durableChatCompletion.js.map +1 -0
- package/backend/dist/services/durableChatGenerationService.d.ts +19 -0
- package/backend/dist/services/durableChatGenerationService.d.ts.map +1 -0
- package/backend/dist/services/durableChatGenerationService.js +341 -0
- package/backend/dist/services/durableChatGenerationService.js.map +1 -0
- package/backend/dist/services/embeddingService.d.ts +1 -1
- package/backend/dist/services/embeddingService.d.ts.map +1 -1
- package/backend/dist/services/embeddingService.js +16 -13
- package/backend/dist/services/embeddingService.js.map +1 -1
- package/backend/dist/services/encryptionService.d.ts +28 -1
- package/backend/dist/services/encryptionService.d.ts.map +1 -1
- package/backend/dist/services/encryptionService.js +131 -51
- package/backend/dist/services/encryptionService.js.map +1 -1
- package/backend/dist/services/followUpService.d.ts +1 -1
- package/backend/dist/services/followUpService.d.ts.map +1 -1
- package/backend/dist/services/followUpService.js +1 -1
- package/backend/dist/services/followUpService.js.map +1 -1
- package/backend/dist/services/galleryService.d.ts +38 -37
- package/backend/dist/services/galleryService.d.ts.map +1 -1
- package/backend/dist/services/galleryService.js +356 -251
- package/backend/dist/services/galleryService.js.map +1 -1
- package/backend/dist/services/healthService.d.ts +65 -0
- package/backend/dist/services/healthService.d.ts.map +1 -0
- package/backend/dist/services/healthService.js +379 -0
- package/backend/dist/services/healthService.js.map +1 -0
- package/backend/dist/services/legacyCiphertextIntegrity.d.ts +40 -0
- package/backend/dist/services/legacyCiphertextIntegrity.d.ts.map +1 -0
- package/backend/dist/services/legacyCiphertextIntegrity.js +406 -0
- package/backend/dist/services/legacyCiphertextIntegrity.js.map +1 -0
- package/backend/dist/services/mediaGenerationJobService.d.ts +27 -5
- package/backend/dist/services/mediaGenerationJobService.d.ts.map +1 -1
- package/backend/dist/services/mediaGenerationJobService.js +185 -55
- package/backend/dist/services/mediaGenerationJobService.js.map +1 -1
- package/backend/dist/services/memoryService.d.ts +7 -83
- package/backend/dist/services/memoryService.d.ts.map +1 -1
- package/backend/dist/services/memoryService.js +428 -573
- package/backend/dist/services/memoryService.js.map +1 -1
- package/backend/dist/services/memoryUtils.d.ts.map +1 -1
- package/backend/dist/services/memoryUtils.js +8 -1
- package/backend/dist/services/memoryUtils.js.map +1 -1
- package/backend/dist/services/modelAccessService.d.ts +3 -3
- package/backend/dist/services/modelAccessService.d.ts.map +1 -1
- package/backend/dist/services/modelAccessService.js +8 -16
- package/backend/dist/services/modelAccessService.js.map +1 -1
- package/backend/dist/services/mutationEngineService.d.ts +0 -7
- package/backend/dist/services/mutationEngineService.d.ts.map +1 -1
- package/backend/dist/services/mutationEngineService.js +7 -78
- package/backend/dist/services/mutationEngineService.js.map +1 -1
- package/backend/dist/services/ollamaService.d.ts +4 -4
- package/backend/dist/services/ollamaService.d.ts.map +1 -1
- package/backend/dist/services/ollamaService.js +62 -31
- 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 +19 -54
- package/backend/dist/services/personaService.js.map +1 -1
- package/backend/dist/services/pluginActivationService.d.ts +6 -5
- package/backend/dist/services/pluginActivationService.d.ts.map +1 -1
- package/backend/dist/services/pluginActivationService.js +36 -76
- package/backend/dist/services/pluginActivationService.js.map +1 -1
- package/backend/dist/services/pluginAudioGenerationService.d.ts +11 -6
- package/backend/dist/services/pluginAudioGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginAudioGenerationService.js +74 -16
- package/backend/dist/services/pluginAudioGenerationService.js.map +1 -1
- package/backend/dist/services/pluginCacheInvalidation.d.ts +38 -0
- package/backend/dist/services/pluginCacheInvalidation.d.ts.map +1 -0
- package/backend/dist/services/pluginCacheInvalidation.js +198 -0
- package/backend/dist/services/pluginCacheInvalidation.js.map +1 -0
- package/backend/dist/services/pluginCapabilityRegistryService.d.ts +3 -3
- package/backend/dist/services/pluginCapabilityRegistryService.d.ts.map +1 -1
- package/backend/dist/services/pluginCapabilityRegistryService.js +11 -7
- package/backend/dist/services/pluginCapabilityRegistryService.js.map +1 -1
- package/backend/dist/services/pluginCredentialsService.d.ts +9 -8
- package/backend/dist/services/pluginCredentialsService.d.ts.map +1 -1
- package/backend/dist/services/pluginCredentialsService.js +48 -89
- package/backend/dist/services/pluginCredentialsService.js.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.d.ts +8 -7
- package/backend/dist/services/pluginEmbeddingService.d.ts.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.js +13 -11
- package/backend/dist/services/pluginEmbeddingService.js.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.d.ts +10 -8
- package/backend/dist/services/pluginImageGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.js +119 -14
- package/backend/dist/services/pluginImageGenerationService.js.map +1 -1
- package/backend/dist/services/pluginSTTService.d.ts +47 -0
- package/backend/dist/services/pluginSTTService.d.ts.map +1 -0
- package/backend/dist/services/pluginSTTService.js +199 -0
- package/backend/dist/services/pluginSTTService.js.map +1 -0
- package/backend/dist/services/pluginService.d.ts +94 -40
- package/backend/dist/services/pluginService.d.ts.map +1 -1
- package/backend/dist/services/pluginService.js +799 -274
- package/backend/dist/services/pluginService.js.map +1 -1
- package/backend/dist/services/pluginTTSService.d.ts +26 -8
- package/backend/dist/services/pluginTTSService.d.ts.map +1 -1
- package/backend/dist/services/pluginTTSService.js +277 -25
- package/backend/dist/services/pluginTTSService.js.map +1 -1
- package/backend/dist/services/pluginUsageService.d.ts +4 -4
- package/backend/dist/services/pluginUsageService.d.ts.map +1 -1
- package/backend/dist/services/pluginUsageService.js +44 -93
- package/backend/dist/services/pluginUsageService.js.map +1 -1
- package/backend/dist/services/pluginVariablesService.d.ts +14 -7
- package/backend/dist/services/pluginVariablesService.d.ts.map +1 -1
- package/backend/dist/services/pluginVariablesService.js +116 -81
- package/backend/dist/services/pluginVariablesService.js.map +1 -1
- package/backend/dist/services/pluginVideoGenerationService.d.ts +19 -8
- package/backend/dist/services/pluginVideoGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginVideoGenerationService.js +116 -20
- package/backend/dist/services/pluginVideoGenerationService.js.map +1 -1
- package/backend/dist/services/preferencesService.d.ts +31 -21
- package/backend/dist/services/preferencesService.d.ts.map +1 -1
- package/backend/dist/services/preferencesService.js +104 -102
- package/backend/dist/services/preferencesService.js.map +1 -1
- package/backend/dist/services/recoveryInventoryService.d.ts +244 -0
- package/backend/dist/services/recoveryInventoryService.d.ts.map +1 -0
- package/backend/dist/services/recoveryInventoryService.js +1436 -0
- package/backend/dist/services/recoveryInventoryService.js.map +1 -0
- package/backend/dist/services/simpleGitHubOAuth.js +3 -3
- package/backend/dist/services/simpleGitHubOAuth.js.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.js +3 -3
- package/backend/dist/services/simpleHuggingFaceOAuth.js.map +1 -1
- package/backend/dist/services/systemDiagnosticsService.d.ts.map +1 -1
- package/backend/dist/services/systemDiagnosticsService.js +2 -2
- package/backend/dist/services/systemDiagnosticsService.js.map +1 -1
- package/backend/dist/services/systemSettingsService.d.ts +5 -0
- package/backend/dist/services/systemSettingsService.d.ts.map +1 -0
- package/backend/dist/services/systemSettingsService.js +24 -0
- package/backend/dist/services/systemSettingsService.js.map +1 -0
- package/backend/dist/services/titleGenerationService.d.ts +1 -1
- package/backend/dist/services/titleGenerationService.d.ts.map +1 -1
- package/backend/dist/services/titleGenerationService.js +1 -1
- package/backend/dist/services/titleGenerationService.js.map +1 -1
- package/backend/dist/services/voiceProfileService.d.ts +44 -0
- package/backend/dist/services/voiceProfileService.d.ts.map +1 -0
- package/backend/dist/services/voiceProfileService.js +195 -0
- package/backend/dist/services/voiceProfileService.js.map +1 -0
- package/backend/dist/services/webSearchService.d.ts +7 -7
- package/backend/dist/services/webSearchService.d.ts.map +1 -1
- package/backend/dist/services/webSearchService.js +40 -35
- package/backend/dist/services/webSearchService.js.map +1 -1
- package/backend/dist/services/websocketTicketService.d.ts +39 -0
- package/backend/dist/services/websocketTicketService.d.ts.map +1 -0
- package/backend/dist/services/websocketTicketService.js +183 -0
- package/backend/dist/services/websocketTicketService.js.map +1 -0
- package/backend/dist/services/workAccessService.d.ts +3 -3
- package/backend/dist/services/workAccessService.d.ts.map +1 -1
- package/backend/dist/services/workAccessService.js +8 -16
- package/backend/dist/services/workAccessService.js.map +1 -1
- package/backend/dist/services/workAdminService.d.ts +3 -3
- package/backend/dist/services/workAdminService.d.ts.map +1 -1
- package/backend/dist/services/workAdminService.js +4 -4
- package/backend/dist/services/workAdminService.js.map +1 -1
- package/backend/dist/services/workAgentService.d.ts +25 -1
- package/backend/dist/services/workAgentService.d.ts.map +1 -1
- package/backend/dist/services/workAgentService.js +294 -126
- package/backend/dist/services/workAgentService.js.map +1 -1
- package/backend/dist/services/workEventService.d.ts +15 -2
- package/backend/dist/services/workEventService.d.ts.map +1 -1
- package/backend/dist/services/workEventService.js +201 -3
- package/backend/dist/services/workEventService.js.map +1 -1
- package/backend/dist/services/workKubernetesDriver.d.ts +8 -7
- package/backend/dist/services/workKubernetesDriver.d.ts.map +1 -1
- package/backend/dist/services/workKubernetesDriver.js +65 -21
- package/backend/dist/services/workKubernetesDriver.js.map +1 -1
- package/backend/dist/services/workModelProviderService.d.ts +2 -2
- package/backend/dist/services/workModelProviderService.d.ts.map +1 -1
- package/backend/dist/services/workModelProviderService.js +38 -34
- package/backend/dist/services/workModelProviderService.js.map +1 -1
- package/backend/dist/services/workPolicyService.d.ts +7 -7
- package/backend/dist/services/workPolicyService.d.ts.map +1 -1
- package/backend/dist/services/workPolicyService.js +50 -51
- package/backend/dist/services/workPolicyService.js.map +1 -1
- package/backend/dist/services/workPreviewProxyService.d.ts +8 -8
- package/backend/dist/services/workPreviewProxyService.d.ts.map +1 -1
- package/backend/dist/services/workPreviewProxyService.js +47 -44
- package/backend/dist/services/workPreviewProxyService.js.map +1 -1
- package/backend/dist/services/workRuntimeDriver.d.ts +21 -18
- package/backend/dist/services/workRuntimeDriver.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeDriver.js +69 -20
- package/backend/dist/services/workRuntimeDriver.js.map +1 -1
- package/backend/dist/services/workRuntimeService.d.ts +18 -13
- package/backend/dist/services/workRuntimeService.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeService.js +438 -194
- package/backend/dist/services/workRuntimeService.js.map +1 -1
- package/backend/dist/services/workRuntimeShared.d.ts +2 -0
- package/backend/dist/services/workRuntimeShared.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeShared.js.map +1 -1
- package/backend/dist/services/workTaskService.d.ts +42 -36
- package/backend/dist/services/workTaskService.d.ts.map +1 -1
- package/backend/dist/services/workTaskService.js +445 -350
- 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 +33 -6
- package/backend/dist/services/workTerminalService.js.map +1 -1
- package/backend/dist/storage.d.ts +72 -40
- package/backend/dist/storage.d.ts.map +1 -1
- package/backend/dist/storage.js +312 -660
- package/backend/dist/storage.js.map +1 -1
- package/backend/dist/types/index.d.ts +28 -0
- 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 +7 -2
- package/backend/dist/types/work.d.ts.map +1 -1
- package/backend/dist/utils/chatCancellation.d.ts +48 -0
- package/backend/dist/utils/chatCancellation.d.ts.map +1 -0
- package/backend/dist/utils/chatCancellation.js +152 -0
- package/backend/dist/utils/chatCancellation.js.map +1 -0
- 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 +11 -5
- package/backend/dist/utils/chatDocumentContext.js.map +1 -1
- package/backend/dist/utils/chatStreamCoalescer.d.ts +15 -0
- package/backend/dist/utils/chatStreamCoalescer.d.ts.map +1 -0
- package/backend/dist/utils/chatStreamCoalescer.js +59 -0
- package/backend/dist/utils/chatStreamCoalescer.js.map +1 -0
- package/backend/dist/utils/dataDirectory.d.ts +49 -0
- package/backend/dist/utils/dataDirectory.d.ts.map +1 -0
- package/backend/dist/utils/dataDirectory.js +291 -0
- package/backend/dist/utils/dataDirectory.js.map +1 -0
- package/backend/dist/utils/generationUtils.d.ts.map +1 -1
- package/backend/dist/utils/generationUtils.js +18 -6
- package/backend/dist/utils/generationUtils.js.map +1 -1
- package/backend/dist/utils/jwt.d.ts.map +1 -1
- package/backend/dist/utils/jwt.js +2 -3
- package/backend/dist/utils/jwt.js.map +1 -1
- package/backend/dist/utils/ollamaModelDefaults.d.ts.map +1 -1
- package/backend/dist/utils/ollamaModelDefaults.js +2 -7
- package/backend/dist/utils/ollamaModelDefaults.js.map +1 -1
- package/backend/dist/utils/ollamaStreaming.d.ts +2 -1
- package/backend/dist/utils/ollamaStreaming.d.ts.map +1 -1
- package/backend/dist/utils/ollamaStreaming.js +49 -11
- package/backend/dist/utils/ollamaStreaming.js.map +1 -1
- package/backend/dist/utils/pluginConnectionVariables.d.ts.map +1 -1
- package/backend/dist/utils/pluginConnectionVariables.js +11 -3
- package/backend/dist/utils/pluginConnectionVariables.js.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.d.ts.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.js +4 -3
- package/backend/dist/utils/pluginDefinitionTrust.js.map +1 -1
- package/backend/dist/utils/pluginStreaming.d.ts +2 -1
- package/backend/dist/utils/pluginStreaming.d.ts.map +1 -1
- package/backend/dist/utils/pluginStreaming.js +5 -1
- package/backend/dist/utils/pluginStreaming.js.map +1 -1
- package/backend/dist/utils/pluginUpload.d.ts +1 -0
- package/backend/dist/utils/pluginUpload.d.ts.map +1 -1
- package/backend/dist/utils/pluginUpload.js +9 -2
- package/backend/dist/utils/pluginUpload.js.map +1 -1
- package/backend/dist/utils/pluginValidation.d.ts.map +1 -1
- package/backend/dist/utils/pluginValidation.js +29 -1
- package/backend/dist/utils/pluginValidation.js.map +1 -1
- package/backend/dist/utils/sttAudioUpload.d.ts +24 -0
- package/backend/dist/utils/sttAudioUpload.d.ts.map +1 -0
- package/backend/dist/utils/sttAudioUpload.js +500 -0
- package/backend/dist/utils/sttAudioUpload.js.map +1 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.d.ts +34 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.d.ts.map +1 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.js +224 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.js.map +1 -0
- package/backend/dist/utils/websocketMessages.d.ts +2 -1
- package/backend/dist/utils/websocketMessages.d.ts.map +1 -1
- package/backend/dist/utils/websocketMessages.js +16 -2
- package/backend/dist/utils/websocketMessages.js.map +1 -1
- package/backend/dist/websocketServer.d.ts +4 -1
- package/backend/dist/websocketServer.d.ts.map +1 -1
- package/backend/dist/websocketServer.js +290 -44
- package/backend/dist/websocketServer.js.map +1 -1
- package/backend/dist/workTerminalServer.d.ts +9 -0
- package/backend/dist/workTerminalServer.d.ts.map +1 -1
- package/backend/dist/workTerminalServer.js +221 -52
- package/backend/dist/workTerminalServer.js.map +1 -1
- package/backend/dist/worker.d.ts +2 -0
- package/backend/dist/worker.d.ts.map +1 -0
- package/backend/dist/worker.js +250 -0
- package/backend/dist/worker.js.map +1 -0
- package/backend/package.json +19 -9
- package/bin/cli.js +126 -99
- package/bin/runtime-paths.js +108 -0
- package/frontend/dist/artifact-runtime/.build-fingerprint +1 -1
- package/frontend/dist/artifact-runtime/framer-motion.js +5 -5
- package/frontend/dist/artifact-runtime/lucide-react.js +1 -1
- package/frontend/dist/assets/index-CUhEG7E2.js +33 -0
- package/frontend/dist/assets/index-kxtZQLV6.css +1 -0
- package/frontend/dist/assets/{markdown-math-ClQbWekD.css → markdown-math-ClTedVi7.css} +1 -1
- package/frontend/dist/index.html +18 -18
- package/frontend/dist/js/{ArtifactContainer-Dy2Q0iIL.js → ArtifactContainer-BTEDhBnv.js} +1 -1
- package/frontend/dist/js/{ArtifactDemoPage-K79dWshB.js → ArtifactDemoPage-B0gN3YTl.js} +1 -1
- package/frontend/dist/js/{ArtifactSandboxFrame-DhqLNUtY.js → ArtifactSandboxFrame-CLBXQkZs.js} +3 -3
- package/frontend/dist/js/{ArtifactSlideOutPanel-Cl8JG7bz.js → ArtifactSlideOutPanel-CfqHPFdE.js} +1 -1
- package/frontend/dist/js/{Button-CTXHujOd.js → Button-BV44cTnj.js} +1 -1
- package/frontend/dist/js/ChatPage-DIkAXZWA.js +23 -0
- package/frontend/dist/js/{FirstTimeSetup-kHhRzGJ8.js → FirstTimeSetup-B8phXGNA.js} +1 -1
- package/frontend/dist/js/GalleryPage-W4uI043I.js +1 -0
- package/frontend/dist/js/{HomePage-C1L8WAXL.js → HomePage-DlxehbyO.js} +1 -1
- package/frontend/dist/js/{LibreClawPage-Dyua8IUu.js → LibreClawPage-CgD0_G_F.js} +1 -1
- package/frontend/dist/js/{ModelManagerModals-CuMRGUd-.js → ModelManagerModals-D7jIT3v1.js} +1 -1
- package/frontend/dist/js/{ModelSelector-CqHc-Ln4.js → ModelSelector-BYxJU1UV.js} +1 -1
- package/frontend/dist/js/ModelsPage-C4XdCKP5.js +2 -0
- package/frontend/dist/js/NotesPage-CDECOl4V.js +1 -0
- package/frontend/dist/js/{OptimizedSyntaxHighlighter-CWYUn9Oe.js → OptimizedSyntaxHighlighter-XwqZEoTf.js} +1 -1
- package/frontend/dist/js/{PersonasPage-D_6WBCH5.js → PersonasPage-CjSLPrgS.js} +2 -2
- package/frontend/dist/js/PluginUsagePage-DJOXJuH4.js +1 -0
- package/frontend/dist/js/RichMessageContent-Debeh6bi.js +3 -0
- package/frontend/dist/js/SettingsModal-cUqAeYUP.js +1 -0
- package/frontend/dist/js/{SettingsToggle-DLHlCDBl.js → SettingsToggle-WTa0rgvY.js} +1 -1
- package/frontend/dist/js/{SystemPage-BMWEet9e.js → SystemPage-DxPw0GS7.js} +1 -1
- package/frontend/dist/js/UserManagementPage-CEdYFe_Z.js +1 -0
- package/frontend/dist/js/WorkPage-DDVeuG_9.js +6 -0
- package/frontend/dist/js/api-IzobHGND.js +14 -0
- package/frontend/dist/js/appStore-DKwC2vgn.js +2 -0
- package/frontend/dist/js/ar-xTSvTq05.js +2 -0
- package/frontend/dist/js/authStore-OaTuapL7.js +4 -0
- package/frontend/dist/js/{babel-CmENXdZw.js → babel-D24oDI9y.js} +1 -1
- package/frontend/dist/js/bn-iYAsohEA.js +2 -0
- package/frontend/dist/js/chatStore-DXGUVLXD.js +3 -0
- package/frontend/dist/js/{config-DkV1ka7I.js → config-DPEEuTAe.js} +1 -1
- package/frontend/dist/js/cs-YBHN88Hb.js +2 -0
- package/frontend/dist/js/da-D7qlLy_k.js +2 -0
- package/frontend/dist/js/de-DV671k2c.js +2 -0
- package/frontend/dist/js/es-kyBgzNq-.js +2 -0
- package/frontend/dist/js/{estree-D5KP-qbw.js → estree-ChwJsD2w.js} +1 -1
- package/frontend/dist/js/fr-Cw1vut7I.js +2 -0
- package/frontend/dist/js/hi-DWEFC024.js +2 -0
- package/frontend/dist/js/{html-Cm9c2akd.js → html-DFrVjciF.js} +1 -1
- package/frontend/dist/js/id-DlMHjjy0.js +2 -0
- package/frontend/dist/js/is-B9E_a7dG.js +2 -0
- package/frontend/dist/js/it-DawmVbLC.js +2 -0
- package/frontend/dist/js/ja-DmVvwY3W.js +2 -0
- package/frontend/dist/js/ko-DzOPpkVs.js +2 -0
- package/frontend/dist/js/{markdown-B2u7CnKN.js → markdown-FLLx7b67.js} +1 -1
- package/frontend/dist/js/markdown-core-BmPPZiuD.js +31 -0
- package/frontend/dist/js/{markdown-math-B7FlYsmr.js → markdown-math-mH7AZ_mb.js} +6 -6
- package/frontend/dist/js/{messageCodeStyles-DalG2j6U.js → messageCodeStyles-CBkkZY4n.js} +1 -1
- package/frontend/dist/js/ms-DpsaOPht.js +2 -0
- package/frontend/dist/js/nl-B1d8W22n.js +2 -0
- package/frontend/dist/js/pl-nCncRVgt.js +2 -0
- package/frontend/dist/js/{postcss-B5WIGhAY.js → postcss-Bx9CTcIc.js} +1 -1
- package/frontend/dist/js/pt-DHw8fGuu.js +2 -0
- package/frontend/dist/js/{react-vendor-DPNXrO-8.js → react-vendor-C5yShNlM.js} +1 -1
- package/frontend/dist/js/{router-vendor-Ca9zqOqT.js → router-vendor-CbPDks39.js} +1 -1
- package/frontend/dist/js/ru-Derl_YP_.js +2 -0
- package/frontend/dist/js/{standalone-Dwm1daef.js → standalone-i8-5bg5p.js} +1 -1
- package/frontend/dist/js/sv-pJAfBVo0.js +2 -0
- package/frontend/dist/js/{syntax-highlight-Ca9bHsaz.js → syntax-highlight-3EEX6CGL.js} +3 -3
- package/frontend/dist/js/th-C_7fIGnk.js +2 -0
- package/frontend/dist/js/tr-CPqsJvaP.js +2 -0
- package/frontend/dist/js/{typescript-CwieSptM.js → typescript-CQ3x-Uni.js} +1 -1
- package/frontend/dist/js/{ui-BnDZpjfc.js → ui-BHhR3Vok.js} +2 -2
- package/frontend/dist/js/ui-vendor-D3Ahl1x5.js +177 -0
- package/frontend/dist/js/uk-3o8P_kFi.js +2 -0
- package/frontend/dist/js/{useTranslation-CXY69qNk.js → useTranslation-C3ei3mJq.js} +1 -1
- package/frontend/dist/js/{utils-BM0_0iFj.js → utils-CuC1beTY.js} +1 -1
- package/frontend/dist/js/{utils-vendor-1zob7nK9.js → utils-vendor-BBa8OxtB.js} +1 -1
- package/frontend/dist/js/vi-Dv6N7OVD.js +2 -0
- package/frontend/dist/js/{workApi-BOS7crs9.js → workApi-Czu69yWS.js} +2 -2
- package/frontend/dist/js/{yaml-QD4znPfZ.js → yaml-DioTxVLA.js} +1 -1
- package/frontend/dist/js/zh-qg5iqtPi.js +2 -0
- package/package.json +16 -5
- package/plugins/huggingface.json +12 -3
- package/plugins/llama-cpp.json +18 -6
- package/plugins/longcat-audiodit.json +114 -0
- package/plugins/openai.json +18 -0
- package/frontend/dist/assets/index-BBpNbfKW.js +0 -16
- package/frontend/dist/assets/index-BLATyFmD.css +0 -1
- package/frontend/dist/js/ChatPage-BBayfMLS.js +0 -16
- package/frontend/dist/js/GalleryPage-By8VI39Q.js +0 -1
- package/frontend/dist/js/ModelsPage-ODeXhDDk.js +0 -2
- package/frontend/dist/js/NotesPage-CApzDjOq.js +0 -1
- package/frontend/dist/js/PluginUsagePage-kutS6SOd.js +0 -1
- package/frontend/dist/js/RichMessageContent-g6WT75Te.js +0 -3
- package/frontend/dist/js/SettingsModal-B7z51BCx.js +0 -1
- package/frontend/dist/js/UserManagementPage-D08lM51c.js +0 -1
- package/frontend/dist/js/WorkPage-DdVLefsK.js +0 -6
- package/frontend/dist/js/api-CLEmGcEh.js +0 -14
- package/frontend/dist/js/appStore-CGdhvp9P.js +0 -2
- package/frontend/dist/js/ar-BTmB2WVm.js +0 -2
- package/frontend/dist/js/authStore-Dh3beEOq.js +0 -4
- package/frontend/dist/js/bn-CQnH7YVT.js +0 -2
- package/frontend/dist/js/chatStore-CDeYWL_q.js +0 -3
- package/frontend/dist/js/cs-oTTZkQXr.js +0 -2
- package/frontend/dist/js/da-Br0gB6J6.js +0 -2
- package/frontend/dist/js/de-DE2iztTF.js +0 -2
- package/frontend/dist/js/es-DgthfVtl.js +0 -2
- package/frontend/dist/js/fr-BjxjFwPh.js +0 -2
- package/frontend/dist/js/hi-D1q7E-9N.js +0 -2
- package/frontend/dist/js/id-CDJZqLTF.js +0 -2
- package/frontend/dist/js/is-BU7Um_Tq.js +0 -2
- package/frontend/dist/js/it-CdAxr8P_.js +0 -2
- package/frontend/dist/js/ja-BLbQwz9u.js +0 -2
- package/frontend/dist/js/ko-CY5lpkAe.js +0 -2
- package/frontend/dist/js/markdown-core-DHnR5Hw8.js +0 -16
- package/frontend/dist/js/ms-tQ8AYXEQ.js +0 -2
- package/frontend/dist/js/nl-CRNi2oWT.js +0 -2
- package/frontend/dist/js/pl-CWtFRS_W.js +0 -2
- package/frontend/dist/js/pt-C7SPoLF8.js +0 -2
- package/frontend/dist/js/ru-Dz4AX8xc.js +0 -2
- package/frontend/dist/js/sv-ETy5-boa.js +0 -2
- package/frontend/dist/js/th-DpuMqvxU.js +0 -2
- package/frontend/dist/js/tr-C-1AYAqg.js +0 -2
- package/frontend/dist/js/ui-vendor-xUzKqAXI.js +0 -177
- package/frontend/dist/js/uk-CyS680gr.js +0 -2
- package/frontend/dist/js/vi-BG8HuiTz.js +0 -2
- package/frontend/dist/js/zh-NCs2mkHj.js +0 -2
|
@@ -14,25 +14,222 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
import crypto from 'node:crypto';
|
|
18
|
+
import { Readable } from 'node:stream';
|
|
17
19
|
import { v4 as uuidv4 } from 'uuid';
|
|
18
20
|
import storageService from '../storage.js';
|
|
19
|
-
import
|
|
21
|
+
import { configurePlatformStorageRuntime, getPlatformStorageRuntime, } from '../platform/storage/index.js';
|
|
22
|
+
import { MAX_VECTOR_RECORDS_PER_UPSERT, MAX_VECTOR_RESOURCE_INDEX_ENTRIES, } from '../platform/storage/vectorStore.js';
|
|
23
|
+
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';
|
|
24
|
+
import { getCoordinator } from '../platform/coordination/service.js';
|
|
25
|
+
import { DOCUMENT_INGEST_IDEMPOTENCY_SCOPE } from '../platform/jobs/domainJobContracts.js';
|
|
26
|
+
import { transactionalDocumentIngestionEnqueuer } from '../platform/jobs/documentIngestionEnqueuer.js';
|
|
27
|
+
import { getDurableJobRuntime } from '../platform/jobs/durableJobRuntime.js';
|
|
28
|
+
import { transactionalResourceDeletionEnqueuer } from '../platform/jobs/resourceDeletionEnqueuer.js';
|
|
20
29
|
import preferencesService from './preferencesService.js';
|
|
21
30
|
import { createLogger } from '../utils/logger.js';
|
|
31
|
+
import { throwIfChatGenerationCancelled } from '../utils/chatCancellation.js';
|
|
22
32
|
const logger = createLogger('documents');
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const DOCUMENT_BLOB_PURPOSE = 'document.source';
|
|
34
|
+
const DOCUMENT_POST_VECTOR_FAULT_MARKER = 'LIBRE_DOCUMENT_POST_VECTOR_KILL';
|
|
35
|
+
const DOCUMENT_RESOURCE_LEASE_WAIT_MS = 15000;
|
|
36
|
+
const MAX_VECTOR_RESOURCE_FILTERS = 100;
|
|
37
|
+
export class DocumentResourceBusyError extends Error {
|
|
38
|
+
constructor() {
|
|
39
|
+
super('Document indexing is already in progress; retry shortly');
|
|
40
|
+
this.name = 'DocumentResourceBusyError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class DocumentChunkLimitError extends Error {
|
|
44
|
+
constructor(chunks) {
|
|
45
|
+
super(`Document produces ${chunks} chunks; the maximum is ${MAX_VECTOR_RESOURCE_INDEX_ENTRIES}. Increase the embedding chunk size or remove excessive paragraph breaks.`);
|
|
46
|
+
this.chunks = chunks;
|
|
47
|
+
this.name = 'DocumentChunkLimitError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
class DocumentIndexSupersededError extends Error {
|
|
51
|
+
constructor() {
|
|
52
|
+
super('Document disappeared while its vector index was being published');
|
|
53
|
+
this.name = 'DocumentIndexSupersededError';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const resourceLeaseTtlMs = () => {
|
|
57
|
+
const value = Number.parseInt(process.env.RESOURCE_LEASE_TTL_MS ?? '30000', 10);
|
|
58
|
+
if (!Number.isSafeInteger(value) || value < 5000 || value > 300000) {
|
|
59
|
+
throw new Error('RESOURCE_LEASE_TTL_MS must be between 5000 and 300000 milliseconds');
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
};
|
|
63
|
+
const waitForLeaseRetry = (milliseconds, signal) => new Promise((resolve, reject) => {
|
|
64
|
+
if (signal?.aborted) {
|
|
65
|
+
reject(signal.reason ?? new Error('Document indexing was cancelled'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
let timer;
|
|
69
|
+
const abort = () => {
|
|
70
|
+
clearTimeout(timer);
|
|
71
|
+
reject(signal?.reason ?? new Error('Document indexing was cancelled'));
|
|
72
|
+
};
|
|
73
|
+
timer = setTimeout(() => {
|
|
74
|
+
signal?.removeEventListener('abort', abort);
|
|
75
|
+
resolve();
|
|
76
|
+
}, milliseconds);
|
|
77
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
78
|
+
});
|
|
79
|
+
const acquireDocumentResourceLease = async (userId, documentId, signal, waitMs = DOCUMENT_RESOURCE_LEASE_WAIT_MS) => {
|
|
80
|
+
const coordinator = getCoordinator();
|
|
81
|
+
const ttlMs = resourceLeaseTtlMs();
|
|
82
|
+
const deadline = Date.now() + waitMs;
|
|
83
|
+
let lease = null;
|
|
84
|
+
do {
|
|
85
|
+
if (signal?.aborted)
|
|
86
|
+
throw signal.reason;
|
|
87
|
+
lease = await coordinator.acquireLease(`resource:${userId}:document:${documentId}`, ttlMs);
|
|
88
|
+
if (lease)
|
|
89
|
+
break;
|
|
90
|
+
if (Date.now() >= deadline)
|
|
91
|
+
throw new DocumentResourceBusyError();
|
|
92
|
+
await waitForLeaseRetry(25, signal);
|
|
93
|
+
} while (!lease);
|
|
94
|
+
let closed = false;
|
|
95
|
+
let lost = false;
|
|
96
|
+
let renewal;
|
|
97
|
+
const scheduleRenewal = () => {
|
|
98
|
+
if (closed || lost)
|
|
99
|
+
return;
|
|
100
|
+
renewal = setTimeout(async () => {
|
|
101
|
+
try {
|
|
102
|
+
if (!(await lease.extend(ttlMs)))
|
|
103
|
+
lost = true;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
lost = true;
|
|
107
|
+
}
|
|
108
|
+
scheduleRenewal();
|
|
109
|
+
}, Math.max(1000, Math.floor(ttlMs / 3)));
|
|
110
|
+
renewal.unref?.();
|
|
111
|
+
};
|
|
112
|
+
scheduleRenewal();
|
|
113
|
+
return {
|
|
114
|
+
async assertHeld() {
|
|
115
|
+
if (signal?.aborted)
|
|
116
|
+
throw signal.reason;
|
|
117
|
+
if (closed || lost)
|
|
118
|
+
throw new DocumentResourceBusyError();
|
|
119
|
+
try {
|
|
120
|
+
if (await lease.extend(ttlMs))
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Report the same safe error for expiry and coordinator outages.
|
|
125
|
+
}
|
|
126
|
+
lost = true;
|
|
127
|
+
throw new DocumentResourceBusyError();
|
|
128
|
+
},
|
|
129
|
+
async release() {
|
|
130
|
+
if (closed)
|
|
131
|
+
return false;
|
|
132
|
+
closed = true;
|
|
133
|
+
if (renewal)
|
|
134
|
+
clearTimeout(renewal);
|
|
135
|
+
return lease.release();
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
const deterministicDocumentChunkId = (documentId, chunkIndex, content) => {
|
|
140
|
+
const digest = crypto
|
|
141
|
+
.createHash('sha256')
|
|
142
|
+
.update('libre-document-chunk-v1\u0000')
|
|
143
|
+
.update(documentId)
|
|
144
|
+
.update('\u0000')
|
|
145
|
+
.update(String(chunkIndex))
|
|
146
|
+
.update('\u0000')
|
|
147
|
+
.update(content, 'utf8')
|
|
148
|
+
.digest();
|
|
149
|
+
// Preserve the familiar UUID shape while deriving the identity from source
|
|
150
|
+
// state. Retries therefore overwrite the same SQL/vector record.
|
|
151
|
+
digest[6] = (digest[6] & 0x0f) | 0x50;
|
|
152
|
+
digest[8] = (digest[8] & 0x3f) | 0x80;
|
|
153
|
+
const hex = digest.subarray(0, 16).toString('hex');
|
|
154
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
155
|
+
};
|
|
156
|
+
const readDocumentIndexMetadata = (document) => readDocumentIndexMetadataValue(document.metadata);
|
|
157
|
+
const hasValidDocumentIndexMetadata = (document) => readDocumentIndexMetadata(document) !== undefined;
|
|
158
|
+
const exactLocalDocumentIndexProbe = (document, chunks, userId, spec) => {
|
|
159
|
+
const metadata = readDocumentIndexMetadata(document);
|
|
160
|
+
if (!documentIndexMatchesSpec(metadata, spec) ||
|
|
161
|
+
metadata.dimensions === null) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const embedded = embeddedChunks(chunks);
|
|
165
|
+
if (embedded.length === 0 || embedded.length !== chunks.length) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
if (embeddingDimensions(embedded) !== metadata.dimensions ||
|
|
169
|
+
aggregateDocumentIndexRevision(embedded, spec) !==
|
|
170
|
+
metadata.aggregateRevision) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
actor: { userId },
|
|
175
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
176
|
+
resourceId: document.id,
|
|
177
|
+
model: spec.model,
|
|
178
|
+
dimensions: metadata.dimensions,
|
|
179
|
+
version: spec.version,
|
|
180
|
+
entries: embedded.map(chunk => ({
|
|
181
|
+
id: chunk.id,
|
|
182
|
+
sourceRevision: sourceRevision(chunk),
|
|
183
|
+
})),
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
const withDocumentIndexMetadata = (document, chunks, spec) => {
|
|
187
|
+
const metadata = createDocumentIndexMetadata(chunks, spec);
|
|
188
|
+
return {
|
|
189
|
+
...document,
|
|
190
|
+
metadata: {
|
|
191
|
+
...(document.metadata ?? {}),
|
|
192
|
+
[DOCUMENT_INDEX_METADATA_KEY]: metadata,
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
const delayAfterVectorUpsertForRecoveryDrill = async (document, attemptCount, signal) => {
|
|
197
|
+
if (process.env.LIBRE_ENABLE_TEST_FAULT_INJECTION !== 'true' ||
|
|
198
|
+
attemptCount !== 1 ||
|
|
199
|
+
!document.content?.includes(DOCUMENT_POST_VECTOR_FAULT_MARKER)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const delayMs = Number.parseInt(process.env.LIBRE_TEST_FAULT_DELAY_MS ?? '60000', 10);
|
|
203
|
+
if (!Number.isSafeInteger(delayMs) || delayMs < 1 || delayMs > 300000) {
|
|
204
|
+
throw new Error('Invalid recovery-drill fault delay');
|
|
205
|
+
}
|
|
206
|
+
await new Promise((resolve, reject) => {
|
|
207
|
+
if (signal?.aborted) {
|
|
208
|
+
reject(signal.reason ?? new Error('Document ingestion was cancelled'));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
let settled = false;
|
|
212
|
+
let timer;
|
|
213
|
+
const finish = (error) => {
|
|
214
|
+
if (settled)
|
|
215
|
+
return;
|
|
216
|
+
settled = true;
|
|
217
|
+
clearTimeout(timer);
|
|
218
|
+
signal?.removeEventListener('abort', abort);
|
|
219
|
+
if (error === undefined)
|
|
220
|
+
resolve();
|
|
221
|
+
else
|
|
222
|
+
reject(error);
|
|
223
|
+
};
|
|
224
|
+
const abort = () => finish(signal?.reason ?? new Error('Document ingestion was cancelled'));
|
|
225
|
+
timer = setTimeout(finish, delayMs);
|
|
226
|
+
timer.unref?.();
|
|
227
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
/** Installed by team-mode bootstrap so all replicas share S3 and PGVector. */
|
|
231
|
+
export const configureDocumentPlatformStorage = (storage) => {
|
|
232
|
+
configurePlatformStorageRuntime(storage);
|
|
36
233
|
};
|
|
37
234
|
// Lazy load pdfjs-dist legacy build for Node.js
|
|
38
235
|
let pdfjsLib = null;
|
|
@@ -51,85 +248,177 @@ const getPdfjsLib = async () => {
|
|
|
51
248
|
}
|
|
52
249
|
return pdfjsLib;
|
|
53
250
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.loadChunks();
|
|
251
|
+
const extractDocumentContent = async (fileBuffer, mimeType, signal) => {
|
|
252
|
+
if (signal?.aborted)
|
|
253
|
+
throw signal.reason;
|
|
254
|
+
if (mimeType === 'text/plain') {
|
|
255
|
+
return { content: fileBuffer.toString('utf8'), fileType: 'txt' };
|
|
60
256
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
257
|
+
if (mimeType !== 'application/pdf') {
|
|
258
|
+
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
259
|
+
}
|
|
260
|
+
const pdfLib = await getPdfjsLib();
|
|
261
|
+
const pdfDocument = await pdfLib.getDocument({
|
|
262
|
+
data: new Uint8Array(fileBuffer),
|
|
263
|
+
}).promise;
|
|
264
|
+
let textContent = '';
|
|
265
|
+
for (let pageNum = 1; pageNum <= pdfDocument.numPages; pageNum += 1) {
|
|
266
|
+
if (signal?.aborted)
|
|
267
|
+
throw signal.reason;
|
|
268
|
+
const page = await pdfDocument.getPage(pageNum);
|
|
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' };
|
|
275
|
+
};
|
|
276
|
+
export class DocumentService {
|
|
277
|
+
async captureEmbeddingExecutionSpec(userId) {
|
|
278
|
+
const settings = (await preferencesService.getPreferences(userId))
|
|
279
|
+
.embeddingSettings;
|
|
280
|
+
const model = settings.model.trim();
|
|
281
|
+
if (!model || Buffer.byteLength(model, 'utf8') > 256) {
|
|
282
|
+
throw new Error('Embedding model must contain 1-256 bytes');
|
|
66
283
|
}
|
|
67
|
-
|
|
68
|
-
|
|
284
|
+
if (!Number.isSafeInteger(settings.chunkSize) ||
|
|
285
|
+
settings.chunkSize < 1 ||
|
|
286
|
+
settings.chunkSize > 1000000) {
|
|
287
|
+
throw new Error('Embedding chunk size must be between 1 and 1000000');
|
|
288
|
+
}
|
|
289
|
+
if (!Number.isSafeInteger(settings.chunkOverlap) ||
|
|
290
|
+
settings.chunkOverlap < 0 ||
|
|
291
|
+
settings.chunkOverlap >= settings.chunkSize) {
|
|
292
|
+
throw new Error('Embedding chunk overlap must be non-negative and smaller than the chunk size');
|
|
69
293
|
}
|
|
294
|
+
if (!Number.isFinite(settings.similarityThreshold) ||
|
|
295
|
+
settings.similarityThreshold < -1 ||
|
|
296
|
+
settings.similarityThreshold > 1) {
|
|
297
|
+
throw new Error('Embedding similarity threshold must be between -1 and 1');
|
|
298
|
+
}
|
|
299
|
+
return Object.freeze({
|
|
300
|
+
enabled: settings.enabled === true,
|
|
301
|
+
model,
|
|
302
|
+
version: DOCUMENT_VECTOR_VERSION,
|
|
303
|
+
chunkerVersion: DOCUMENT_CHUNKER_VERSION,
|
|
304
|
+
chunkSize: settings.chunkSize,
|
|
305
|
+
chunkOverlap: settings.chunkOverlap,
|
|
306
|
+
similarityThreshold: settings.similarityThreshold,
|
|
307
|
+
});
|
|
70
308
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
309
|
+
async assertDocumentIndexAuthoritative(documentId, userId, aggregateRevision, expectedSource) {
|
|
310
|
+
const platform = getPlatformStorageRuntime();
|
|
311
|
+
const [document, reserved] = await Promise.all([
|
|
312
|
+
platform.domains.documents.findByOwner(documentId, userId),
|
|
313
|
+
platform.domains.resourceDeletions.isReserved('document', documentId),
|
|
314
|
+
]);
|
|
315
|
+
if (!document || reserved)
|
|
316
|
+
throw new DocumentIndexSupersededError();
|
|
317
|
+
if (aggregateRevision) {
|
|
318
|
+
const metadata = readDocumentIndexMetadata(document);
|
|
319
|
+
if (metadata?.aggregateRevision !== aggregateRevision) {
|
|
320
|
+
throw new DocumentIndexSupersededError();
|
|
80
321
|
}
|
|
81
|
-
logger.debug(`Loaded chunks for ${this.chunks.size} documents from storage`);
|
|
82
322
|
}
|
|
83
|
-
|
|
84
|
-
|
|
323
|
+
if (expectedSource &&
|
|
324
|
+
((document.content ?? null) !== expectedSource.content ||
|
|
325
|
+
(document.fileType ?? null) !== expectedSource.fileType)) {
|
|
326
|
+
throw new DocumentIndexSupersededError();
|
|
85
327
|
}
|
|
328
|
+
return document;
|
|
86
329
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Persist the private source and publish extraction in the same SQL
|
|
332
|
+
* transaction as the document placeholder. The object write is compensated
|
|
333
|
+
* if the SQL transaction cannot commit.
|
|
334
|
+
*/
|
|
335
|
+
async queueDocumentProcessing(fileName, fileBuffer, mimeType, userId, sessionId, signal) {
|
|
336
|
+
if (mimeType !== 'text/plain' && mimeType !== 'application/pdf') {
|
|
337
|
+
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
338
|
+
}
|
|
339
|
+
if (signal?.aborted)
|
|
340
|
+
throw signal.reason;
|
|
96
341
|
const documentId = uuidv4();
|
|
97
|
-
|
|
98
|
-
|
|
342
|
+
const now = Date.now();
|
|
343
|
+
const document = {
|
|
344
|
+
id: documentId,
|
|
345
|
+
filename: fileName,
|
|
346
|
+
content: '',
|
|
347
|
+
fileType: mimeType === 'application/pdf' ? 'pdf' : 'txt',
|
|
348
|
+
size: fileBuffer.length,
|
|
349
|
+
...(sessionId ? { sessionId } : {}),
|
|
350
|
+
uploadedAt: now,
|
|
351
|
+
createdAt: now,
|
|
352
|
+
metadata: { processingStatus: 'queued' },
|
|
353
|
+
};
|
|
354
|
+
const platform = getPlatformStorageRuntime();
|
|
355
|
+
const sourceBlob = await platform.blobStore.put({
|
|
356
|
+
ownerUserId: userId,
|
|
357
|
+
purpose: DOCUMENT_BLOB_PURPOSE,
|
|
358
|
+
contentType: mimeType,
|
|
359
|
+
originalFilename: fileName,
|
|
360
|
+
expectedSize: fileBuffer.length,
|
|
361
|
+
metadata: { resourceType: 'document', resourceId: documentId },
|
|
362
|
+
source: Readable.from(fileBuffer),
|
|
363
|
+
...(signal ? { signal } : {}),
|
|
364
|
+
});
|
|
99
365
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
366
|
+
await platform.domains.documents.upsertWithBlobAndEnqueue(document, userId, {
|
|
367
|
+
blobId: sourceBlob.id,
|
|
368
|
+
ownerUserId: userId,
|
|
369
|
+
resourceType: 'document',
|
|
370
|
+
resourceId: documentId,
|
|
371
|
+
purpose: DOCUMENT_BLOB_PURPOSE,
|
|
372
|
+
createdAt: Date.parse(sourceBlob.createdAt) || now,
|
|
373
|
+
}, transactionalDocumentIngestionEnqueuer);
|
|
374
|
+
}
|
|
375
|
+
catch (error) {
|
|
376
|
+
// A PostgreSQL COMMIT can succeed even when its acknowledgement is
|
|
377
|
+
// lost. Resolve that unknown outcome from authoritative state before
|
|
378
|
+
// compensating the already-durable blob; deleting first would leave a
|
|
379
|
+
// committed document/reference/job pointing at a missing object.
|
|
380
|
+
try {
|
|
381
|
+
const [publishedDocument, publishedReference, publishedJob] = await Promise.all([
|
|
382
|
+
platform.domains.documents.findByOwner(documentId, userId),
|
|
383
|
+
platform.blobReferences.find('document', documentId, DOCUMENT_BLOB_PURPOSE),
|
|
384
|
+
getDurableJobRuntime().service.getByIdempotency(userId, DOCUMENT_INGEST_IDEMPOTENCY_SCOPE, documentId),
|
|
385
|
+
]);
|
|
386
|
+
const committed = publishedDocument !== undefined &&
|
|
387
|
+
publishedReference?.blobId === sourceBlob.id &&
|
|
388
|
+
publishedReference.ownerUserId === userId &&
|
|
389
|
+
publishedJob != null;
|
|
390
|
+
if (committed && publishedJob) {
|
|
391
|
+
return { document, jobId: publishedJob.id };
|
|
119
392
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
393
|
+
const safelyAbsent = publishedDocument === undefined &&
|
|
394
|
+
publishedReference === undefined &&
|
|
395
|
+
publishedJob == null;
|
|
396
|
+
if (!safelyAbsent) {
|
|
397
|
+
throw new Error('Document ingestion publish outcome is inconsistent; the source blob was retained for recovery');
|
|
123
398
|
}
|
|
124
399
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
400
|
+
catch (resolutionError) {
|
|
401
|
+
logger.error('Document ingestion publish failed and its outcome could not be resolved', error, resolutionError);
|
|
402
|
+
throw new Error('Could not resolve the document ingestion transaction outcome; the source blob was retained for recovery');
|
|
131
403
|
}
|
|
132
|
-
|
|
404
|
+
await platform.blobStore
|
|
405
|
+
.delete({ id: sourceBlob.id, ownerUserId: userId })
|
|
406
|
+
.catch(cleanupError => {
|
|
407
|
+
logger.warn('Document source cleanup failed after a rolled-back publish; lifecycle reconciliation will retry it', cleanupError);
|
|
408
|
+
});
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
const job = await getDurableJobRuntime().service.getByIdempotency(userId, DOCUMENT_INGEST_IDEMPOTENCY_SCOPE, documentId);
|
|
412
|
+
if (!job) {
|
|
413
|
+
throw new Error('Document ingestion transaction did not publish its job');
|
|
414
|
+
}
|
|
415
|
+
return { document, jobId: job.id };
|
|
416
|
+
}
|
|
417
|
+
async processDocument(fileName, fileBuffer, mimeType, userId, sessionId) {
|
|
418
|
+
const documentId = uuidv4();
|
|
419
|
+
try {
|
|
420
|
+
const { content, fileType } = await extractDocumentContent(fileBuffer, mimeType);
|
|
421
|
+
let document = {
|
|
133
422
|
id: documentId,
|
|
134
423
|
filename: fileName,
|
|
135
424
|
content,
|
|
@@ -138,15 +427,53 @@ class DocumentService {
|
|
|
138
427
|
sessionId,
|
|
139
428
|
uploadedAt: Date.now(),
|
|
140
429
|
};
|
|
141
|
-
|
|
142
|
-
|
|
430
|
+
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
431
|
+
// Process the document into chunks under one immutable execution spec.
|
|
432
|
+
const chunks = this.chunkDocument(document, spec);
|
|
143
433
|
// Generate embeddings for chunks if enabled
|
|
144
|
-
const chunksWithEmbeddings = await this.generateEmbeddingsForChunks(chunks, userId);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
434
|
+
const chunksWithEmbeddings = await this.generateEmbeddingsForChunks(chunks, userId, spec);
|
|
435
|
+
document = withDocumentIndexMetadata(document, chunksWithEmbeddings, spec);
|
|
436
|
+
const platform = getPlatformStorageRuntime();
|
|
437
|
+
const sourceBlob = await platform.blobStore.put({
|
|
438
|
+
ownerUserId: userId,
|
|
439
|
+
purpose: DOCUMENT_BLOB_PURPOSE,
|
|
440
|
+
contentType: mimeType,
|
|
441
|
+
originalFilename: fileName,
|
|
442
|
+
expectedSize: fileBuffer.length,
|
|
443
|
+
metadata: { resourceType: 'document', resourceId: documentId },
|
|
444
|
+
source: Readable.from(fileBuffer),
|
|
445
|
+
});
|
|
446
|
+
try {
|
|
447
|
+
await storageService.saveDocument(document, userId);
|
|
448
|
+
await storageService.saveDocumentChunks(documentId, chunksWithEmbeddings);
|
|
449
|
+
await platform.blobReferences.attach({
|
|
450
|
+
blobId: sourceBlob.id,
|
|
451
|
+
ownerUserId: userId,
|
|
452
|
+
resourceType: 'document',
|
|
453
|
+
resourceId: documentId,
|
|
454
|
+
purpose: DOCUMENT_BLOB_PURPOSE,
|
|
455
|
+
createdAt: Date.now(),
|
|
456
|
+
});
|
|
457
|
+
await this.indexDocumentChunks(document, chunksWithEmbeddings, userId, spec);
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
await platform.vectorStore
|
|
461
|
+
.delete({
|
|
462
|
+
actor: { userId },
|
|
463
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
464
|
+
resourceId: documentId,
|
|
465
|
+
})
|
|
466
|
+
.catch(() => undefined);
|
|
467
|
+
await platform.blobReferences
|
|
468
|
+
.detach('document', documentId, DOCUMENT_BLOB_PURPOSE)
|
|
469
|
+
.catch(() => undefined);
|
|
470
|
+
await platform.blobStore
|
|
471
|
+
.delete({ id: sourceBlob.id, ownerUserId: userId })
|
|
472
|
+
.catch(() => undefined);
|
|
473
|
+
await storageService.deleteDocumentChunks(documentId);
|
|
474
|
+
await storageService.deleteDocument(documentId, userId);
|
|
475
|
+
throw error;
|
|
476
|
+
}
|
|
150
477
|
logger.debug(`Processed ${fileType.toUpperCase()} document: ${fileName} (${chunksWithEmbeddings.length} chunks)`);
|
|
151
478
|
return document;
|
|
152
479
|
}
|
|
@@ -155,11 +482,16 @@ class DocumentService {
|
|
|
155
482
|
throw new Error(`Failed to process document: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
156
483
|
}
|
|
157
484
|
}
|
|
158
|
-
chunkDocument(document,
|
|
485
|
+
chunkDocument(document, spec) {
|
|
159
486
|
const chunks = [];
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
487
|
+
const appendChunk = (chunk) => {
|
|
488
|
+
if (chunks.length >= MAX_VECTOR_RESOURCE_INDEX_ENTRIES) {
|
|
489
|
+
throw new DocumentChunkLimitError(chunks.length + 1);
|
|
490
|
+
}
|
|
491
|
+
chunks.push(chunk);
|
|
492
|
+
};
|
|
493
|
+
const chunkSize = spec.chunkSize;
|
|
494
|
+
const overlap = spec.chunkOverlap;
|
|
163
495
|
const text = document.content?.trim();
|
|
164
496
|
if (!text)
|
|
165
497
|
return chunks;
|
|
@@ -180,10 +512,11 @@ class DocumentService {
|
|
|
180
512
|
if (currentChunk.trim()) {
|
|
181
513
|
const chunkStart = currentOffset - currentChunk.length;
|
|
182
514
|
const chunkEnd = currentOffset;
|
|
183
|
-
|
|
184
|
-
|
|
515
|
+
const content = currentChunk.trim();
|
|
516
|
+
appendChunk({
|
|
517
|
+
id: deterministicDocumentChunkId(document.id, chunkIndex, content),
|
|
185
518
|
documentId: document.id,
|
|
186
|
-
content
|
|
519
|
+
content,
|
|
187
520
|
chunkIndex: chunkIndex++,
|
|
188
521
|
startChar: Math.max(0, chunkStart),
|
|
189
522
|
endChar: chunkEnd,
|
|
@@ -191,8 +524,12 @@ class DocumentService {
|
|
|
191
524
|
}
|
|
192
525
|
// Start new chunk with overlap from previous chunk
|
|
193
526
|
const words = currentChunk.split(' ');
|
|
194
|
-
const
|
|
195
|
-
|
|
527
|
+
const overlapWordCount = calculateOverlapWordCount(overlap);
|
|
528
|
+
const overlapWords = overlapWordCount === 0 ? [] : words.slice(-overlapWordCount);
|
|
529
|
+
currentChunk =
|
|
530
|
+
overlapWords.length === 0
|
|
531
|
+
? paragraphText
|
|
532
|
+
: `${overlapWords.join(' ')}\n\n${paragraphText}`;
|
|
196
533
|
currentOffset += paragraphText.length + 2; // +2 for \n\n
|
|
197
534
|
}
|
|
198
535
|
else {
|
|
@@ -211,10 +548,11 @@ class DocumentService {
|
|
|
211
548
|
if (currentChunk.trim()) {
|
|
212
549
|
const chunkStart = currentOffset - currentChunk.length;
|
|
213
550
|
const chunkEnd = currentOffset;
|
|
214
|
-
|
|
215
|
-
|
|
551
|
+
const content = currentChunk.trim();
|
|
552
|
+
appendChunk({
|
|
553
|
+
id: deterministicDocumentChunkId(document.id, chunkIndex, content),
|
|
216
554
|
documentId: document.id,
|
|
217
|
-
content
|
|
555
|
+
content,
|
|
218
556
|
chunkIndex: chunkIndex,
|
|
219
557
|
startChar: Math.max(0, chunkStart),
|
|
220
558
|
endChar: chunkEnd,
|
|
@@ -222,100 +560,317 @@ class DocumentService {
|
|
|
222
560
|
}
|
|
223
561
|
return chunks;
|
|
224
562
|
}
|
|
225
|
-
async generateEmbeddingForText(text, userId) {
|
|
563
|
+
async generateEmbeddingForText(text, userId, spec, signal) {
|
|
226
564
|
try {
|
|
227
|
-
|
|
228
|
-
if (!preferences.embeddingSettings.enabled) {
|
|
565
|
+
if (!spec.enabled)
|
|
229
566
|
return null;
|
|
230
|
-
|
|
567
|
+
// Provider/plugin construction is stateful and must happen only after
|
|
568
|
+
// the selected persistence backend has completed bootstrap.
|
|
569
|
+
const { default: embeddingService } = await import('./embeddingService.js');
|
|
231
570
|
const response = await embeddingService.generateEmbeddings({
|
|
232
|
-
model:
|
|
571
|
+
model: spec.model,
|
|
233
572
|
input: text,
|
|
234
|
-
}, userId);
|
|
573
|
+
}, userId, signal);
|
|
235
574
|
return response.embeddings[0] || null;
|
|
236
575
|
}
|
|
237
576
|
catch (error) {
|
|
577
|
+
if (signal?.aborted)
|
|
578
|
+
throw error;
|
|
238
579
|
logger.error('Failed to generate embedding:', error);
|
|
239
580
|
return null;
|
|
240
581
|
}
|
|
241
582
|
}
|
|
242
|
-
async generateEmbeddingsForChunks(chunks, userId) {
|
|
243
|
-
|
|
244
|
-
if (!preferences.embeddingSettings.enabled) {
|
|
583
|
+
async generateEmbeddingsForChunks(chunks, userId, spec, signal, assertSideEffectAllowed) {
|
|
584
|
+
if (!spec.enabled)
|
|
245
585
|
return chunks;
|
|
246
|
-
}
|
|
247
586
|
logger.debug(`Generating embeddings for ${chunks.length} chunks...`);
|
|
248
587
|
const chunksWithEmbeddings = [];
|
|
249
588
|
for (const chunk of chunks) {
|
|
250
|
-
|
|
589
|
+
await assertSideEffectAllowed?.();
|
|
590
|
+
const embedding = await this.generateEmbeddingForText(chunk.content, userId, spec, signal);
|
|
591
|
+
if (!embedding) {
|
|
592
|
+
throw new Error('Embedding generation returned no vector');
|
|
593
|
+
}
|
|
251
594
|
chunksWithEmbeddings.push({
|
|
252
595
|
...chunk,
|
|
253
|
-
embedding
|
|
596
|
+
embedding,
|
|
254
597
|
});
|
|
255
598
|
}
|
|
599
|
+
embeddingDimensions(embeddedChunks(chunksWithEmbeddings));
|
|
256
600
|
logger.debug(`Generated embeddings for ${chunksWithEmbeddings.filter(c => c.embedding).length} chunks`);
|
|
257
601
|
return chunksWithEmbeddings;
|
|
258
602
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
603
|
+
/**
|
|
604
|
+
* Older solo databases stored inline vectors without recording which model
|
|
605
|
+
* produced them. Presence is therefore only an upgrade signal: rebuild the
|
|
606
|
+
* authoritative document from text under today's immutable execution spec,
|
|
607
|
+
* and never copy or relabel the legacy payload.
|
|
608
|
+
*/
|
|
609
|
+
async upgradeLegacyDocumentIndex(document, userId, spec, signal) {
|
|
610
|
+
const platform = getPlatformStorageRuntime();
|
|
611
|
+
if (platform.dialect !== 'sqlite' ||
|
|
612
|
+
hasValidDocumentIndexMetadata(document) ||
|
|
613
|
+
!document.content?.trim()) {
|
|
614
|
+
return undefined;
|
|
615
|
+
}
|
|
616
|
+
const legacy = await platform.domains.documents.inspectLegacyChunkEmbeddings(document.id, userId);
|
|
617
|
+
if (!legacy.present)
|
|
618
|
+
return undefined;
|
|
619
|
+
let lease;
|
|
620
|
+
try {
|
|
621
|
+
lease = await acquireDocumentResourceLease(userId, document.id, signal, 0);
|
|
622
|
+
await lease.assertHeld();
|
|
623
|
+
const current = await this.assertDocumentIndexAuthoritative(document.id, userId);
|
|
624
|
+
if (hasValidDocumentIndexMetadata(current)) {
|
|
625
|
+
return {
|
|
626
|
+
document: current,
|
|
627
|
+
chunks: await this.loadDocumentChunks(current.id),
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
if (!current.content?.trim())
|
|
631
|
+
return undefined;
|
|
632
|
+
const currentLegacy = await platform.domains.documents.inspectLegacyChunkEmbeddings(current.id, userId);
|
|
633
|
+
if (!currentLegacy.present)
|
|
634
|
+
return undefined;
|
|
635
|
+
if (!currentLegacy.authenticated) {
|
|
636
|
+
logger.warn(`Legacy inline embeddings for document ${current.id} failed authentication; rebuilding from authoritative text`);
|
|
637
|
+
}
|
|
638
|
+
const chunks = this.chunkDocument(current, spec);
|
|
639
|
+
if (chunks.length === 0) {
|
|
640
|
+
logger.debug(`Legacy document ${current.id} has no authoritative text to reindex`);
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
const embedded = await this.generateEmbeddingsForChunks(chunks, userId, spec, signal, () => lease.assertHeld());
|
|
644
|
+
await lease.assertHeld();
|
|
645
|
+
const latest = await this.assertDocumentIndexAuthoritative(current.id, userId, undefined, {
|
|
646
|
+
content: current.content ?? null,
|
|
647
|
+
fileType: current.fileType ?? null,
|
|
648
|
+
});
|
|
649
|
+
if (hasValidDocumentIndexMetadata(latest)) {
|
|
650
|
+
throw new DocumentIndexSupersededError();
|
|
651
|
+
}
|
|
652
|
+
const published = withDocumentIndexMetadata(latest, embedded, spec);
|
|
653
|
+
const embeddingIndex = readDocumentIndexMetadata(published);
|
|
654
|
+
if (!embeddingIndex) {
|
|
655
|
+
throw new Error('Document embedding index metadata is invalid');
|
|
656
|
+
}
|
|
657
|
+
const completed = await platform.domains.documents.publishEmbeddingIndex(current.id, userId, {
|
|
658
|
+
content: current.content ?? null,
|
|
659
|
+
fileType: current.fileType ?? null,
|
|
660
|
+
}, embeddingIndex, embedded);
|
|
661
|
+
if (!completed)
|
|
662
|
+
throw new DocumentIndexSupersededError();
|
|
663
|
+
await lease.assertHeld();
|
|
664
|
+
const authoritative = await this.assertDocumentIndexAuthoritative(current.id, userId, embeddingIndex.aggregateRevision, {
|
|
665
|
+
content: current.content ?? null,
|
|
666
|
+
fileType: current.fileType ?? null,
|
|
667
|
+
});
|
|
668
|
+
await this.indexDocumentChunks(authoritative, embedded, userId, spec, 1, signal, () => lease.assertHeld());
|
|
669
|
+
return { document: authoritative, chunks: embedded };
|
|
670
|
+
}
|
|
671
|
+
catch (error) {
|
|
672
|
+
if (signal?.aborted)
|
|
673
|
+
throw error;
|
|
674
|
+
if (!(error instanceof DocumentResourceBusyError) &&
|
|
675
|
+
!(error instanceof DocumentIndexSupersededError)) {
|
|
676
|
+
logger.warn(`Could not upgrade legacy document embeddings for ${document.id}; keyword fallback remains available`, error);
|
|
677
|
+
}
|
|
678
|
+
return undefined;
|
|
679
|
+
}
|
|
680
|
+
finally {
|
|
681
|
+
await lease?.release().catch(() => false);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Rebuild every document under one immutable preference snapshot. Each
|
|
686
|
+
* resource uses the same renewable coordinator lease as ingestion/deletion,
|
|
687
|
+
* while the relational delete is still allowed to publish its tombstone.
|
|
688
|
+
* The final authoritative check then removes any vector recreated after that
|
|
689
|
+
* tombstone committed.
|
|
690
|
+
*/
|
|
691
|
+
async regenerateAllEmbeddings(userId, signal) {
|
|
692
|
+
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
693
|
+
const documents = await storageService.getAllDocuments(userId);
|
|
694
|
+
const result = {
|
|
695
|
+
documentsTotal: documents.length,
|
|
696
|
+
documentsRegenerated: 0,
|
|
697
|
+
documentsSkipped: 0,
|
|
698
|
+
chunksTotal: 0,
|
|
699
|
+
chunksEmbedded: 0,
|
|
700
|
+
model: spec.model,
|
|
701
|
+
version: spec.version,
|
|
702
|
+
};
|
|
703
|
+
if (!spec.enabled) {
|
|
704
|
+
result.documentsSkipped = documents.length;
|
|
263
705
|
logger.debug('Embeddings are disabled, skipping regeneration');
|
|
264
|
-
return;
|
|
706
|
+
return result;
|
|
265
707
|
}
|
|
266
708
|
logger.debug('Starting to regenerate embeddings for all documents...');
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
709
|
+
for (const listedDocument of documents) {
|
|
710
|
+
if (signal?.aborted)
|
|
711
|
+
throw signal.reason;
|
|
712
|
+
let lease;
|
|
713
|
+
try {
|
|
714
|
+
lease = await acquireDocumentResourceLease(userId, listedDocument.id, signal);
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
if (error instanceof DocumentResourceBusyError) {
|
|
718
|
+
result.documentsSkipped += 1;
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
throw error;
|
|
722
|
+
}
|
|
723
|
+
try {
|
|
724
|
+
await lease.assertHeld();
|
|
725
|
+
const current = await this.assertDocumentIndexAuthoritative(listedDocument.id, userId);
|
|
726
|
+
const chunks = this.chunkDocument(current, spec);
|
|
727
|
+
result.chunksTotal += chunks.length;
|
|
728
|
+
const embedded = await this.generateEmbeddingsForChunks(chunks, userId, spec, signal, () => lease.assertHeld());
|
|
729
|
+
await lease.assertHeld();
|
|
730
|
+
const latest = await this.assertDocumentIndexAuthoritative(current.id, userId);
|
|
731
|
+
if (latest.content !== current.content ||
|
|
732
|
+
latest.fileType !== current.fileType) {
|
|
733
|
+
throw new DocumentIndexSupersededError();
|
|
734
|
+
}
|
|
735
|
+
// Preserve routing/metadata changes published while embedding work was
|
|
736
|
+
// in flight. The repository merges only embeddingIndex and chunks
|
|
737
|
+
// under its row/write lock, so an acknowledged collection/session
|
|
738
|
+
// change can never be replaced by this stale service snapshot.
|
|
739
|
+
const published = withDocumentIndexMetadata(latest, embedded, spec);
|
|
740
|
+
const embeddingIndex = readDocumentIndexMetadata(published);
|
|
741
|
+
if (!embeddingIndex) {
|
|
742
|
+
throw new Error('Document embedding index metadata is invalid');
|
|
743
|
+
}
|
|
744
|
+
const completed = await getPlatformStorageRuntime().domains.documents.publishEmbeddingIndex(current.id, userId, {
|
|
745
|
+
content: current.content ?? null,
|
|
746
|
+
fileType: current.fileType ?? null,
|
|
747
|
+
}, embeddingIndex, embedded);
|
|
748
|
+
if (!completed)
|
|
749
|
+
throw new DocumentIndexSupersededError();
|
|
750
|
+
await lease.assertHeld();
|
|
751
|
+
const authoritativePublished = await this.assertDocumentIndexAuthoritative(current.id, userId, embeddingIndex.aggregateRevision, {
|
|
752
|
+
content: current.content ?? null,
|
|
753
|
+
fileType: current.fileType ?? null,
|
|
754
|
+
});
|
|
755
|
+
await this.indexDocumentChunks(authoritativePublished, embedded, userId, spec, 1, signal, () => lease.assertHeld());
|
|
756
|
+
result.documentsRegenerated += 1;
|
|
757
|
+
result.chunksEmbedded += embedded.length;
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
if (error instanceof DocumentIndexSupersededError) {
|
|
761
|
+
result.documentsSkipped += 1;
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
throw error;
|
|
765
|
+
}
|
|
766
|
+
finally {
|
|
767
|
+
await lease.release().catch(() => false);
|
|
768
|
+
}
|
|
277
769
|
}
|
|
278
|
-
logger.debug(`Regenerated embeddings for ${
|
|
770
|
+
logger.debug(`Regenerated embeddings for ${result.chunksEmbedded}/${result.chunksTotal} chunks`);
|
|
771
|
+
return result;
|
|
772
|
+
}
|
|
773
|
+
/** Durable extraction/embedding handler entrypoint for an existing source. */
|
|
774
|
+
async reprocessDocument(documentId, userId, signal, assertSideEffectAllowed, attemptCount = 1) {
|
|
775
|
+
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
776
|
+
const current = await this.getDocument(documentId, userId);
|
|
777
|
+
if (!current)
|
|
778
|
+
throw new Error('Document not found');
|
|
779
|
+
const source = await this.openDocumentSource(documentId, userId, undefined, signal);
|
|
780
|
+
if (!source)
|
|
781
|
+
throw new Error('Document source is unavailable');
|
|
782
|
+
const buffers = [];
|
|
783
|
+
let size = 0;
|
|
784
|
+
for await (const chunk of source.body) {
|
|
785
|
+
if (signal?.aborted)
|
|
786
|
+
throw signal.reason;
|
|
787
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
788
|
+
size += buffer.length;
|
|
789
|
+
if (size > 10 * 1024 * 1024) {
|
|
790
|
+
throw new Error('Document source exceeds the extraction limit');
|
|
791
|
+
}
|
|
792
|
+
buffers.push(buffer);
|
|
793
|
+
}
|
|
794
|
+
const extracted = await extractDocumentContent(Buffer.concat(buffers, size), source.descriptor.contentType, signal);
|
|
795
|
+
let document = {
|
|
796
|
+
...current,
|
|
797
|
+
content: extracted.content,
|
|
798
|
+
fileType: extracted.fileType,
|
|
799
|
+
size,
|
|
800
|
+
};
|
|
801
|
+
const chunks = this.chunkDocument(document, spec);
|
|
802
|
+
const embedded = await this.generateEmbeddingsForChunks(chunks, userId, spec, signal, assertSideEffectAllowed);
|
|
803
|
+
document.metadata = {
|
|
804
|
+
...(document.metadata ?? {}),
|
|
805
|
+
processingStatus: 'completed',
|
|
806
|
+
processedAt: Date.now(),
|
|
807
|
+
};
|
|
808
|
+
document = withDocumentIndexMetadata(document, embedded, spec);
|
|
809
|
+
await assertSideEffectAllowed?.();
|
|
810
|
+
const completed = await getPlatformStorageRuntime().domains.documents.completeIngestion(document, userId, embedded);
|
|
811
|
+
if (!completed)
|
|
812
|
+
throw new Error('Document was deleted during ingestion');
|
|
813
|
+
await assertSideEffectAllowed?.();
|
|
814
|
+
await this.indexDocumentChunks(document, embedded, userId, spec, attemptCount, signal, assertSideEffectAllowed);
|
|
815
|
+
return {
|
|
816
|
+
chunks: embedded.length,
|
|
817
|
+
embedded: embedded.filter(chunk => chunk.embedding?.length).length,
|
|
818
|
+
};
|
|
279
819
|
}
|
|
280
820
|
// Method to get embedding model information
|
|
281
821
|
async getEmbeddingModelInfo(userId) {
|
|
282
|
-
const
|
|
822
|
+
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
283
823
|
let chunksWithEmbeddings = 0;
|
|
284
824
|
let totalChunks = 0;
|
|
285
|
-
for (const document of storageService.getAllDocuments(userId)) {
|
|
286
|
-
const chunks = this.loadDocumentChunks(document.id);
|
|
825
|
+
for (const document of await storageService.getAllDocuments(userId)) {
|
|
826
|
+
const chunks = await this.loadDocumentChunks(document.id);
|
|
287
827
|
totalChunks += chunks.length;
|
|
288
828
|
chunksWithEmbeddings += chunks.filter(c => c.embedding).length;
|
|
289
829
|
}
|
|
290
830
|
return {
|
|
291
|
-
available:
|
|
292
|
-
model:
|
|
831
|
+
available: spec.enabled,
|
|
832
|
+
model: spec.model,
|
|
293
833
|
chunksWithEmbeddings,
|
|
294
834
|
totalChunks,
|
|
295
835
|
};
|
|
296
836
|
}
|
|
297
|
-
getDocument(documentId, userId) {
|
|
837
|
+
async getDocument(documentId, userId) {
|
|
298
838
|
return storageService.getDocument(documentId, userId);
|
|
299
839
|
}
|
|
300
|
-
getDocuments(userId, sessionId) {
|
|
301
|
-
const allDocs = storageService.getAllDocuments(userId);
|
|
840
|
+
async getDocuments(userId, sessionId) {
|
|
841
|
+
const allDocs = await storageService.getAllDocuments(userId);
|
|
302
842
|
if (sessionId) {
|
|
303
843
|
return allDocs.filter(doc => doc.sessionId === sessionId);
|
|
304
844
|
}
|
|
305
845
|
return allDocs.sort((a, b) => b.uploadedAt - a.uploadedAt);
|
|
306
846
|
}
|
|
307
|
-
getDocumentChunks(documentId, userId) {
|
|
308
|
-
if (!this.getDocument(documentId, userId))
|
|
847
|
+
async getDocumentChunks(documentId, userId) {
|
|
848
|
+
if (!(await this.getDocument(documentId, userId)))
|
|
309
849
|
return [];
|
|
310
850
|
return this.loadDocumentChunks(documentId);
|
|
311
851
|
}
|
|
312
|
-
|
|
313
|
-
if (!this.getDocument(documentId, userId))
|
|
852
|
+
async openDocumentSource(documentId, userId, range, signal) {
|
|
853
|
+
if (!(await this.getDocument(documentId, userId)))
|
|
854
|
+
return undefined;
|
|
855
|
+
const platform = getPlatformStorageRuntime();
|
|
856
|
+
const reference = await platform.blobReferences.find('document', documentId, DOCUMENT_BLOB_PURPOSE);
|
|
857
|
+
if (!reference || reference.ownerUserId !== userId)
|
|
858
|
+
return undefined;
|
|
859
|
+
return platform.blobStore.open({
|
|
860
|
+
id: reference.blobId,
|
|
861
|
+
ownerUserId: userId,
|
|
862
|
+
...(range ? { range } : {}),
|
|
863
|
+
...(signal ? { signal } : {}),
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
async deleteDocument(documentId, userId) {
|
|
867
|
+
if (!(await this.getDocument(documentId, userId)))
|
|
868
|
+
return false;
|
|
869
|
+
const platform = getPlatformStorageRuntime();
|
|
870
|
+
const relationalDeleted = await platform.domains.documents.deleteAndEnqueue(documentId, userId, transactionalResourceDeletionEnqueuer);
|
|
871
|
+
if (!relationalDeleted)
|
|
314
872
|
return false;
|
|
315
|
-
|
|
316
|
-
this.chunks.delete(documentId);
|
|
317
|
-
storageService.deleteDocumentChunks(documentId);
|
|
318
|
-
return storageService.deleteDocument(documentId, userId) || deleted;
|
|
873
|
+
return true;
|
|
319
874
|
}
|
|
320
875
|
/**
|
|
321
876
|
* A document is searchable for a chat when it belongs to that session or
|
|
@@ -337,74 +892,263 @@ class DocumentService {
|
|
|
337
892
|
document.collectionId &&
|
|
338
893
|
collectionIds.includes(document.collectionId));
|
|
339
894
|
}
|
|
895
|
+
async indexDocumentChunks(document, chunks, userId, spec, attemptCount = 1, signal, assertSideEffectAllowed) {
|
|
896
|
+
const executionSpec = spec ?? (await this.captureEmbeddingExecutionSpec(userId));
|
|
897
|
+
const embedded = embeddedChunks(chunks);
|
|
898
|
+
embeddingDimensions(embedded);
|
|
899
|
+
const platform = getPlatformStorageRuntime();
|
|
900
|
+
const revisions = embedded.map(sourceRevision);
|
|
901
|
+
const aggregateRevision = aggregateDocumentIndexRevision(embedded, executionSpec);
|
|
902
|
+
const publishedMetadata = readDocumentIndexMetadata(document);
|
|
903
|
+
if (publishedMetadata &&
|
|
904
|
+
publishedMetadata.aggregateRevision !== aggregateRevision) {
|
|
905
|
+
throw new Error('Document index metadata does not match its embeddings');
|
|
906
|
+
}
|
|
907
|
+
const expectedRevision = publishedMetadata?.aggregateRevision;
|
|
908
|
+
const expectedSource = {
|
|
909
|
+
content: document.content ?? null,
|
|
910
|
+
fileType: document.fileType ?? null,
|
|
911
|
+
};
|
|
912
|
+
await assertSideEffectAllowed?.();
|
|
913
|
+
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
914
|
+
let mutated = false;
|
|
915
|
+
try {
|
|
916
|
+
// Replace the resource index rather than only upserting the latest IDs.
|
|
917
|
+
// Deterministic chunk IDs make a crash after upsert retry-safe, while this
|
|
918
|
+
// deletion removes records from older document revisions.
|
|
919
|
+
await platform.vectorStore.delete({
|
|
920
|
+
actor: { userId },
|
|
921
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
922
|
+
resourceId: document.id,
|
|
923
|
+
});
|
|
924
|
+
mutated = true;
|
|
925
|
+
await assertSideEffectAllowed?.();
|
|
926
|
+
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
927
|
+
for (let offset = 0; offset < embedded.length; offset += MAX_VECTOR_RECORDS_PER_UPSERT) {
|
|
928
|
+
await assertSideEffectAllowed?.();
|
|
929
|
+
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
930
|
+
const batch = embedded.slice(offset, offset + MAX_VECTOR_RECORDS_PER_UPSERT);
|
|
931
|
+
await platform.vectorStore.upsert({
|
|
932
|
+
actor: { userId },
|
|
933
|
+
records: batch.map((chunk, index) => ({
|
|
934
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
935
|
+
id: chunk.id,
|
|
936
|
+
ownerUserId: userId,
|
|
937
|
+
resourceId: document.id,
|
|
938
|
+
model: executionSpec.model,
|
|
939
|
+
dimensions: chunk.embedding.length,
|
|
940
|
+
version: executionSpec.version,
|
|
941
|
+
sourceRevision: revisions[offset + index],
|
|
942
|
+
embedding: chunk.embedding,
|
|
943
|
+
attributes: {
|
|
944
|
+
chunkIndex: String(chunk.chunkIndex),
|
|
945
|
+
...(document.sessionId ? { sessionId: document.sessionId } : {}),
|
|
946
|
+
...(document.collectionId
|
|
947
|
+
? { collectionId: document.collectionId }
|
|
948
|
+
: {}),
|
|
949
|
+
},
|
|
950
|
+
})),
|
|
951
|
+
});
|
|
952
|
+
await assertSideEffectAllowed?.();
|
|
953
|
+
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
954
|
+
}
|
|
955
|
+
await delayAfterVectorUpsertForRecoveryDrill(document, attemptCount, signal);
|
|
956
|
+
await assertSideEffectAllowed?.();
|
|
957
|
+
await this.assertDocumentIndexAuthoritative(document.id, userId, expectedRevision, expectedSource);
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
if (mutated) {
|
|
961
|
+
await platform.vectorStore
|
|
962
|
+
.delete({
|
|
963
|
+
actor: { userId },
|
|
964
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
965
|
+
resourceId: document.id,
|
|
966
|
+
})
|
|
967
|
+
.catch(cleanupError => {
|
|
968
|
+
logger.error('Failed to compensate a superseded document vector publication', cleanupError);
|
|
969
|
+
return 0;
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
throw error;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
340
975
|
// Enhanced search with semantic similarity using embeddings
|
|
341
|
-
async searchDocuments(query, userId, sessionId, limit = 5, collectionIds) {
|
|
342
|
-
const
|
|
976
|
+
async searchDocuments(query, userId, sessionId, limit = 5, collectionIds, signal) {
|
|
977
|
+
const spec = await this.captureEmbeddingExecutionSpec(userId);
|
|
343
978
|
// Use semantic search if embeddings are enabled
|
|
344
|
-
if (
|
|
345
|
-
return this.semanticSearchDocuments(query, userId, sessionId, limit, collectionIds);
|
|
979
|
+
if (spec.enabled) {
|
|
980
|
+
return this.semanticSearchDocuments(query, userId, sessionId, limit, collectionIds, spec, signal);
|
|
346
981
|
}
|
|
347
982
|
// Fall back to keyword search
|
|
348
|
-
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds);
|
|
983
|
+
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
349
984
|
}
|
|
350
|
-
async semanticSearchDocuments(query, userId, sessionId, limit = 5, collectionIds) {
|
|
985
|
+
async semanticSearchDocuments(query, userId, sessionId, limit = 5, collectionIds, spec, signal) {
|
|
351
986
|
try {
|
|
987
|
+
const executionSpec = spec ?? (await this.captureEmbeddingExecutionSpec(userId));
|
|
352
988
|
// Generate embedding for the query
|
|
353
|
-
const queryEmbedding = await this.generateEmbeddingForText(query, userId);
|
|
989
|
+
const queryEmbedding = await this.generateEmbeddingForText(query, userId, executionSpec, signal);
|
|
354
990
|
if (!queryEmbedding) {
|
|
355
991
|
logger.warn('Failed to generate query embedding, falling back to keyword search');
|
|
356
|
-
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds);
|
|
357
|
-
}
|
|
358
|
-
const
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
// whose embedding generation failed) would otherwise be invisible to
|
|
362
|
-
// semantic search forever — exactly the "only my first document is
|
|
363
|
-
// used" failure. They compete through keyword scoring instead.
|
|
992
|
+
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
993
|
+
}
|
|
994
|
+
const documents = (await storageService.getAllDocuments(userId)).filter(document => this.documentInScope(document, sessionId, collectionIds));
|
|
995
|
+
const platform = getPlatformStorageRuntime();
|
|
996
|
+
const chunksById = new Map();
|
|
364
997
|
const unembedded = [];
|
|
365
|
-
for (const document of
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
998
|
+
for (const document of documents) {
|
|
999
|
+
throwIfChatGenerationCancelled(signal);
|
|
1000
|
+
let searchableDocument = document;
|
|
1001
|
+
let documentChunks = await this.loadDocumentChunks(document.id);
|
|
1002
|
+
throwIfChatGenerationCancelled(signal);
|
|
1003
|
+
if (platform.dialect === 'sqlite' &&
|
|
1004
|
+
!hasValidDocumentIndexMetadata(searchableDocument)) {
|
|
1005
|
+
const upgraded = await this.upgradeLegacyDocumentIndex(searchableDocument, userId, executionSpec, signal);
|
|
1006
|
+
if (upgraded) {
|
|
1007
|
+
searchableDocument = upgraded.document;
|
|
1008
|
+
documentChunks = upgraded.chunks;
|
|
373
1009
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
1010
|
+
else {
|
|
1011
|
+
// A failed vector publication may still have durably published
|
|
1012
|
+
// current inline chunks. Reload so the exact-index repair below
|
|
1013
|
+
// can finish it in this same read; provider/busy failures retain
|
|
1014
|
+
// the original legacy chunks for keyword fallback.
|
|
1015
|
+
const latest = await platform.domains.documents.findByOwner(document.id, userId);
|
|
1016
|
+
if (!latest)
|
|
1017
|
+
continue;
|
|
1018
|
+
searchableDocument = latest;
|
|
1019
|
+
documentChunks = await this.loadDocumentChunks(latest.id);
|
|
378
1020
|
}
|
|
379
1021
|
}
|
|
1022
|
+
// SQLite may contain relationally published embeddings from a prior
|
|
1023
|
+
// process while its local vector table still needs publication. Only
|
|
1024
|
+
// publish a revision whose immutable model metadata proves it belongs
|
|
1025
|
+
// to this query spec, and serialize that mutation with regeneration
|
|
1026
|
+
// and deletion cleanup through the shared document resource lease.
|
|
1027
|
+
// PostgreSQL/team reads never mutate PGVector.
|
|
1028
|
+
const publishedIndex = readDocumentIndexMetadata(searchableDocument);
|
|
1029
|
+
const canProveCurrentEmbeddingModel = documentIndexMatchesSpec(publishedIndex, executionSpec);
|
|
1030
|
+
const localIndexProbe = platform.dialect === 'sqlite'
|
|
1031
|
+
? exactLocalDocumentIndexProbe(searchableDocument, documentChunks, userId, executionSpec)
|
|
1032
|
+
: undefined;
|
|
1033
|
+
let localIndexReady = localIndexProbe !== undefined &&
|
|
1034
|
+
(await platform.vectorStore.hasExactResourceIndex(localIndexProbe));
|
|
1035
|
+
const needsLazyPublication = localIndexProbe !== undefined && !localIndexReady;
|
|
1036
|
+
if (platform.dialect === 'sqlite' &&
|
|
1037
|
+
localIndexProbe !== undefined &&
|
|
1038
|
+
needsLazyPublication) {
|
|
1039
|
+
let lease;
|
|
1040
|
+
try {
|
|
1041
|
+
lease = await acquireDocumentResourceLease(userId, document.id, signal, 0);
|
|
1042
|
+
await lease.assertHeld();
|
|
1043
|
+
const latest = await this.assertDocumentIndexAuthoritative(document.id, userId, publishedIndex.aggregateRevision);
|
|
1044
|
+
const latestChunks = await this.loadDocumentChunks(document.id);
|
|
1045
|
+
const latestProbe = exactLocalDocumentIndexProbe(latest, latestChunks, userId, executionSpec);
|
|
1046
|
+
if (!latestProbe)
|
|
1047
|
+
throw new DocumentIndexSupersededError();
|
|
1048
|
+
const latestIndexReady = await platform.vectorStore.hasExactResourceIndex(latestProbe);
|
|
1049
|
+
if (!latestIndexReady) {
|
|
1050
|
+
await this.indexDocumentChunks(latest, latestChunks, userId, executionSpec, 1, signal, () => lease.assertHeld());
|
|
1051
|
+
}
|
|
1052
|
+
localIndexReady = true;
|
|
1053
|
+
searchableDocument = latest;
|
|
1054
|
+
documentChunks = latestChunks;
|
|
1055
|
+
}
|
|
1056
|
+
catch (error) {
|
|
1057
|
+
if (!(error instanceof DocumentResourceBusyError) &&
|
|
1058
|
+
!(error instanceof DocumentIndexSupersededError)) {
|
|
1059
|
+
throw error;
|
|
1060
|
+
}
|
|
1061
|
+
// A writer owns the resource or replaced/deleted this revision.
|
|
1062
|
+
// Skip the optional lazy publication; keyword fallback remains
|
|
1063
|
+
// available and the next query reloads authoritative state.
|
|
1064
|
+
}
|
|
1065
|
+
finally {
|
|
1066
|
+
await lease?.release().catch(() => false);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
for (const chunk of documentChunks) {
|
|
1070
|
+
// PostgreSQL deliberately keeps embeddings only in PGVector, so a
|
|
1071
|
+
// relational chunk without an `embedding` property can still be the
|
|
1072
|
+
// authoritative content for a vector hit. Always make every current
|
|
1073
|
+
// relational chunk available for hit hydration. Metadata tells us
|
|
1074
|
+
// whether an absent inline embedding means "stored externally" or
|
|
1075
|
+
// whether this chunk genuinely needs keyword fallback.
|
|
1076
|
+
chunksById.set(chunk.id, {
|
|
1077
|
+
chunk,
|
|
1078
|
+
document: searchableDocument,
|
|
1079
|
+
});
|
|
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
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
const resourceIds = documents.map(document => document.id);
|
|
1090
|
+
const hits = [];
|
|
1091
|
+
for (let offset = 0; offset < resourceIds.length; offset += MAX_VECTOR_RESOURCE_FILTERS) {
|
|
1092
|
+
throwIfChatGenerationCancelled(signal);
|
|
1093
|
+
hits.push(...(await platform.vectorStore.query({
|
|
1094
|
+
actor: { userId },
|
|
1095
|
+
namespace: DOCUMENT_VECTOR_NAMESPACE,
|
|
1096
|
+
model: executionSpec.model,
|
|
1097
|
+
dimensions: queryEmbedding.length,
|
|
1098
|
+
version: executionSpec.version,
|
|
1099
|
+
embedding: queryEmbedding,
|
|
1100
|
+
limit,
|
|
1101
|
+
minScore: executionSpec.similarityThreshold,
|
|
1102
|
+
resourceIds: resourceIds.slice(offset, offset + MAX_VECTOR_RESOURCE_FILTERS),
|
|
1103
|
+
})));
|
|
1104
|
+
throwIfChatGenerationCancelled(signal);
|
|
1105
|
+
}
|
|
1106
|
+
hits.sort((left, right) => right.score - left.score ||
|
|
1107
|
+
left.ownerUserId.localeCompare(right.ownerUserId) ||
|
|
1108
|
+
left.id.localeCompare(right.id));
|
|
1109
|
+
const top = [];
|
|
1110
|
+
const selectedChunkIds = new Set();
|
|
1111
|
+
for (const hit of hits) {
|
|
1112
|
+
if (top.length >= limit)
|
|
1113
|
+
break;
|
|
1114
|
+
const match = chunksById.get(hit.id);
|
|
1115
|
+
if (!match ||
|
|
1116
|
+
match.document.id !== hit.resourceId ||
|
|
1117
|
+
sourceRevision(match.chunk) !== hit.sourceRevision ||
|
|
1118
|
+
selectedChunkIds.has(match.chunk.id)) {
|
|
1119
|
+
continue;
|
|
1120
|
+
}
|
|
1121
|
+
top.push({
|
|
1122
|
+
...match.chunk,
|
|
1123
|
+
filename: match.document.filename,
|
|
1124
|
+
});
|
|
1125
|
+
selectedChunkIds.add(match.chunk.id);
|
|
380
1126
|
}
|
|
381
|
-
const top = results
|
|
382
|
-
.sort((a, b) => b.similarity - a.similarity)
|
|
383
|
-
.slice(0, limit)
|
|
384
|
-
.map(result => ({
|
|
385
|
-
...result.chunk,
|
|
386
|
-
filename: result.document.filename, // Add filename for context
|
|
387
|
-
}));
|
|
388
1127
|
if (top.length < limit && unembedded.length > 0) {
|
|
389
1128
|
const scored = this.scoreChunksByKeywords(query, unembedded);
|
|
390
1129
|
for (const entry of scored) {
|
|
391
1130
|
if (top.length >= limit)
|
|
392
1131
|
break;
|
|
1132
|
+
if (selectedChunkIds.has(entry.chunk.id))
|
|
1133
|
+
continue;
|
|
393
1134
|
top.push({
|
|
394
1135
|
...entry.chunk,
|
|
395
1136
|
filename: entry.document.filename,
|
|
396
1137
|
});
|
|
1138
|
+
selectedChunkIds.add(entry.chunk.id);
|
|
397
1139
|
}
|
|
398
1140
|
}
|
|
399
1141
|
if (top.length > 0)
|
|
400
1142
|
return top;
|
|
401
1143
|
// Nothing cleared the similarity threshold: keyword search is a
|
|
402
1144
|
// better answer than an empty context.
|
|
403
|
-
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds);
|
|
1145
|
+
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
404
1146
|
}
|
|
405
1147
|
catch (error) {
|
|
1148
|
+
if (signal?.aborted)
|
|
1149
|
+
throw error;
|
|
406
1150
|
logger.error('Semantic search failed, falling back to keyword search:', error);
|
|
407
|
-
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds);
|
|
1151
|
+
return this.keywordSearchDocuments(query, userId, sessionId, limit, collectionIds, signal);
|
|
408
1152
|
}
|
|
409
1153
|
}
|
|
410
1154
|
/** Term-frequency scores for a set of chunks, best first. */
|
|
@@ -427,16 +1171,20 @@ class DocumentService {
|
|
|
427
1171
|
}
|
|
428
1172
|
return scored.sort((a, b) => b.score - a.score);
|
|
429
1173
|
}
|
|
430
|
-
keywordSearchDocuments(query, userId, sessionId, limit = 5, collectionIds) {
|
|
1174
|
+
async keywordSearchDocuments(query, userId, sessionId, limit = 5, collectionIds, signal) {
|
|
431
1175
|
const candidates = [];
|
|
432
|
-
|
|
433
|
-
|
|
1176
|
+
throwIfChatGenerationCancelled(signal);
|
|
1177
|
+
for (const document of await storageService.getAllDocuments(userId)) {
|
|
1178
|
+
throwIfChatGenerationCancelled(signal);
|
|
1179
|
+
const documentChunks = await this.loadDocumentChunks(document.id);
|
|
1180
|
+
throwIfChatGenerationCancelled(signal);
|
|
434
1181
|
if (!this.documentInScope(document, sessionId, collectionIds))
|
|
435
1182
|
continue;
|
|
436
1183
|
for (const chunk of documentChunks) {
|
|
437
1184
|
candidates.push({ chunk, document });
|
|
438
1185
|
}
|
|
439
1186
|
}
|
|
1187
|
+
throwIfChatGenerationCancelled(signal);
|
|
440
1188
|
const results = this.scoreChunksByKeywords(query, candidates);
|
|
441
1189
|
return results.slice(0, limit).map(result => ({
|
|
442
1190
|
...result.chunk,
|
|
@@ -452,12 +1200,10 @@ class DocumentService {
|
|
|
452
1200
|
});
|
|
453
1201
|
}
|
|
454
1202
|
// Restore a document from import (used during data import)
|
|
455
|
-
restoreDocument(document, userId) {
|
|
1203
|
+
async restoreDocument(document, userId) {
|
|
456
1204
|
try {
|
|
457
|
-
// Add to memory
|
|
458
|
-
this.documents.set(document.id, document);
|
|
459
1205
|
// Save to storage
|
|
460
|
-
storageService.saveDocument(document, userId);
|
|
1206
|
+
await storageService.saveDocument(document, userId);
|
|
461
1207
|
// If there are any chunks with this document, they'll be handled separately
|
|
462
1208
|
logger.debug(`Restored document: ${document.filename} (${document.id})`);
|
|
463
1209
|
}
|
|
@@ -466,13 +1212,12 @@ class DocumentService {
|
|
|
466
1212
|
throw new Error(`Failed to restore document: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
467
1213
|
}
|
|
468
1214
|
}
|
|
469
|
-
loadDocumentChunks(documentId) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
return chunks;
|
|
1215
|
+
async loadDocumentChunks(documentId) {
|
|
1216
|
+
// Relational storage is authoritative. In team mode another replica's
|
|
1217
|
+
// durable worker can complete or replace chunks after this process first
|
|
1218
|
+
// observes a queued document; caching [] (or an older revision) forever
|
|
1219
|
+
// makes that completion invisible and can drive a stale vector backfill.
|
|
1220
|
+
return storageService.getDocumentChunks(documentId);
|
|
476
1221
|
}
|
|
477
1222
|
}
|
|
478
1223
|
export default new DocumentService();
|