fix(ai): support config read/write when semantic index vector service is unavailable

When sqlite-vec fails to load, use SemanticIndexConfigStore directly to
back the GET/PUT /_web/ai/semantic-index/config routes so users can still
configure the vector model from settings. Session management routes (enable,
build, search, etc.) remain unavailable since they require the vector store.

Export SemanticIndexConfigStore, SEMANTIC_INDEX_CONFIG_FILE, and
isSemanticIndexConfigured from node-runtime and semantic-index packages.
This commit is contained in:
digua committed 2026-06-21 21:52:14 +08:00
1 parent 8f01a8d3b9
commit 386c0bd315
3 files changed
+29 -9

No files matched your search

@@ -5,22 +5,34 @@
* AI pipeline 直接调用 SemanticIndexService,不经过这些 HTTP 路由。
*/
import path from 'node:path'
import type { FastifyInstance } from 'fastify'
import type { HttpRouteContext } from '../../context'
import type { SemanticIndexConfig } from '@openchatlab/node-runtime'
import { defaultSemanticIndexConfig } from '@openchatlab/node-runtime'
import {
SemanticIndexConfigStore,
SEMANTIC_INDEX_CONFIG_FILE,
isSemanticIndexConfigured,
} from '@openchatlab/node-runtime'
export function registerSemanticIndexRoutes(server: FastifyInstance, ctx: HttpRouteContext): void {
const service = ctx.semanticIndexService
// When the service is unavailable (e.g. sqlite-vec failed to load), register read-only stubs
// so the settings UI can still open without 404 errors.
// When the vector service is unavailable (e.g. sqlite-vec failed to load), register config
// routes backed by the config-only store so the settings UI can still read/write configuration.
if (!service) {
server.get('/_web/ai/semantic-index/config', async () => ({
config: defaultSemanticIndexConfig(),
apiKeySet: false,
configured: false,
}))
if (ctx.aiDataDir) {
const configStore = new SemanticIndexConfigStore(path.join(ctx.aiDataDir, SEMANTIC_INDEX_CONFIG_FILE))
server.get('/_web/ai/semantic-index/config', async () => ({
config: configStore.get(),
apiKeySet: false,
configured: isSemanticIndexConfigured(configStore.get()),
}))
server.put<{ Body: { config: SemanticIndexConfig } }>('/_web/ai/semantic-index/config', async (request) => {
const config = configStore.set(request.body.config)
return { config, apiKeySet: false, configured: isSemanticIndexConfigured(config) }
})
}
server.get('/_web/ai/semantic-index/enabled', async () => ({ sessions: [] }))
return
}
+8 -1
View File
@@ -348,7 +348,14 @@ export * as exportService from './services/export-service'
export * as ownerProfileService from './services/owner-profile-service'
// Semantic index (Phase 1 vector search) — independent of legacy ai/rag
export * as semanticIndex from './semantic-index'
export { SemanticIndexService, createSemanticIndexService, defaultSemanticIndexConfig } from './semantic-index'
export {
SemanticIndexService,
createSemanticIndexService,
defaultSemanticIndexConfig,
SemanticIndexConfigStore,
SEMANTIC_INDEX_CONFIG_FILE,
isSemanticIndexConfigured,
} from './semantic-index'
export type {
SemanticIndexServiceOptions,
SemanticIndexSessionStatus,
@@ -46,6 +46,7 @@ export { estimateTokens } from './tokens'
export {
SemanticIndexConfigStore,
defaultSemanticIndexConfig,
isSemanticIndexConfigured,
resolveModelId,
clampSearchMaxResults,
SEMANTIC_INDEX_CONFIG_VERSION,