@open-mercato/search 0.6.7-develop.6842.1.8cd8a8883c → 0.6.7-develop.6859.1.e4727b568a
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/AGENTS.md +2 -0
- package/dist/modules/search/api/openapi.js +2 -0
- package/dist/modules/search/api/openapi.js.map +2 -2
- package/dist/modules/search/api/settings/vector-store/route.js +34 -0
- package/dist/modules/search/api/settings/vector-store/route.js.map +2 -2
- package/dist/modules/search/frontend/components/SearchSettingsPageClient.js.map +2 -2
- package/dist/modules/search/frontend/components/sections/VectorSearchSection.js +14 -2
- package/dist/modules/search/frontend/components/sections/VectorSearchSection.js.map +2 -2
- package/dist/modules/search/i18n/de.json +2 -0
- package/dist/modules/search/i18n/en.json +2 -0
- package/dist/modules/search/i18n/es.json +2 -0
- package/dist/modules/search/i18n/ko.json +2 -0
- package/dist/modules/search/i18n/pl.json +2 -0
- package/dist/strategies/vector.strategy.js +3 -1
- package/dist/strategies/vector.strategy.js.map +2 -2
- package/dist/vector/drivers/pgvector/index.js +55 -1
- package/dist/vector/drivers/pgvector/index.js.map +2 -2
- package/dist/vector/types.js.map +2 -2
- package/package.json +4 -4
- package/src/__tests__/pgvector-extension-availability.test.ts +158 -0
- package/src/modules/search/api/openapi.ts +2 -0
- package/src/modules/search/api/settings/vector-store/route.ts +43 -0
- package/src/modules/search/frontend/components/SearchSettingsPageClient.tsx +2 -0
- package/src/modules/search/frontend/components/sections/VectorSearchSection.tsx +31 -1
- package/src/modules/search/frontend/components/sections/__tests__/VectorSearchSection.test.tsx +36 -1
- package/src/modules/search/i18n/de.json +2 -0
- package/src/modules/search/i18n/en.json +2 -0
- package/src/modules/search/i18n/es.json +2 -0
- package/src/modules/search/i18n/ko.json +2 -0
- package/src/modules/search/i18n/pl.json +2 -0
- package/src/strategies/vector.strategy.ts +7 -1
- package/src/vector/drivers/pgvector/index.ts +77 -1
- package/src/vector/types.ts +14 -0
package/AGENTS.md
CHANGED
|
@@ -42,6 +42,8 @@ Choose strategies based on what users need:
|
|
|
42
42
|
|
|
43
43
|
Strategies automatically become unavailable if their backend is not configured (e.g., no `MEILISEARCH_HOST` means fulltext is unavailable).
|
|
44
44
|
|
|
45
|
+
Availability covers the **store**, not just its credentials. `VectorDriver` exposes optional `isHealthy()` / `getStatus()`; the pgvector driver reports `false` when the `vector` extension is neither installed nor installable, and `VectorSearchStrategy.isAvailable()` consumes it. Writes (`index`/`delete`/`purge`) stay fail-loud for available strategies — a driver that cannot serve its backend MUST report itself unhealthy rather than throwing per record. Settings > Search shows the reason when the store is unavailable.
|
|
46
|
+
|
|
45
47
|
## Configure Global Search (Cmd+K)
|
|
46
48
|
|
|
47
49
|
Search settings (Cmd+K strategies, embedding provider/model, auto-index flag) are
|
|
@@ -178,6 +178,8 @@ const vectorDriverStatusSchema = z.object({
|
|
|
178
178
|
name: z.string(),
|
|
179
179
|
configured: z.boolean(),
|
|
180
180
|
implemented: z.boolean(),
|
|
181
|
+
available: z.boolean().nullable(),
|
|
182
|
+
unavailableReason: z.string().nullable(),
|
|
181
183
|
envVars: z.array(vectorDriverEnvVarSchema)
|
|
182
184
|
});
|
|
183
185
|
const vectorStoreSettingsResponseSchema = z.object({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/search/api/openapi.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\n// ============================================================================\n// Common Schemas\n// ============================================================================\n\nexport const searchStrategyIdSchema = z.enum(['fulltext', 'vector', 'tokens'])\n\nexport const searchResultPresenterSchema = z.object({\n title: z.string(),\n subtitle: z.string().optional(),\n icon: z.string().optional(),\n badge: z.string().optional(),\n})\n\nexport const searchResultLinkSchema = z.object({\n href: z.string(),\n label: z.string(),\n kind: z.enum(['primary', 'secondary']),\n})\n\nexport const searchResultSchema = z.object({\n entityId: z.string().describe('Entity identifier (e.g., \"customers:customer_person_profile\")'),\n recordId: z.string().describe('Primary key of the record'),\n score: z.number().describe('Relevance score (0-1)'),\n source: searchStrategyIdSchema.describe('Which strategy returned this result'),\n presenter: searchResultPresenterSchema.optional(),\n url: z.string().optional(),\n links: z.array(searchResultLinkSchema).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const errorResponseSchema = z.object({\n error: z.string(),\n})\n\n// ============================================================================\n// Search Endpoint Schemas (/api/search)\n// ============================================================================\n\nexport const searchQueryParamsSchema = z.object({\n q: z.string().describe('Search query (required)'),\n limit: z.coerce.number().min(1).max(100).optional().describe('Maximum results to return (default: 50, max: 100)'),\n strategies: z.string().optional().describe('Comma-separated strategies to use: fulltext, vector, tokens (e.g., \"fulltext,vector\")'),\n entityTypes: z.string().optional().describe('Comma-separated entity types to filter results (e.g., \"customers:customer_person_profile,catalog:catalog_product,sales:sales_order\")'),\n})\n\nexport const searchResponseSchema = z.object({\n results: z.array(searchResultSchema),\n strategiesUsed: z.array(searchStrategyIdSchema),\n timing: z.number().describe('Search duration in milliseconds'),\n query: z.string(),\n limit: z.number(),\n})\n\n// ============================================================================\n// Global Search Endpoint Schemas (/api/search/global)\n// ============================================================================\n\nexport const globalSearchQueryParamsSchema = z.object({\n q: z.string().describe('Search query (required)'),\n limit: z.coerce.number().min(1).max(100).optional().describe('Maximum results to return (default: 50, max: 100)'),\n entityTypes: z.string().optional().describe('Comma-separated entity types to filter results (e.g., \"customers:customer_person_profile,catalog:catalog_product,sales:sales_order\")'),\n})\n\nexport const globalSearchResponseSchema = z.object({\n results: z.array(searchResultSchema),\n strategiesUsed: z.array(searchStrategyIdSchema),\n strategiesEnabled: z.array(searchStrategyIdSchema),\n timing: z.number().describe('Search duration in milliseconds'),\n query: z.string(),\n limit: z.number(),\n})\n\n// ============================================================================\n// Settings Endpoint Schemas (/api/search/settings)\n// ============================================================================\n\nexport const strategyStatusSchema = z.object({\n id: z.string(),\n name: z.string(),\n priority: z.number(),\n available: z.boolean(),\n})\n\nexport const fulltextStatsSchema = z.object({\n numberOfDocuments: z.number(),\n isIndexing: z.boolean(),\n fieldDistribution: z.record(z.string(), z.number()),\n})\n\nexport const reindexLockSchema = z.object({\n type: z.enum(['fulltext', 'vector']),\n action: z.string(),\n startedAt: z.string(),\n elapsedMinutes: z.number(),\n processedCount: z.number().nullable().optional(),\n totalCount: z.number().nullable().optional(),\n})\n\nexport const searchSettingsSchema = z.object({\n strategies: z.array(strategyStatusSchema),\n fulltextConfigured: z.boolean(),\n fulltextStats: fulltextStatsSchema.nullable(),\n vectorConfigured: z.boolean(),\n tokensEnabled: z.boolean(),\n defaultStrategies: z.array(z.string()),\n reindexLock: reindexLockSchema.nullable().describe('Deprecated: Use fulltextReindexLock or vectorReindexLock'),\n fulltextReindexLock: reindexLockSchema.nullable(),\n vectorReindexLock: reindexLockSchema.nullable(),\n})\n\nexport const settingsResponseSchema = z.object({\n settings: searchSettingsSchema,\n})\n\n// ============================================================================\n// Global Search Settings Schemas (/api/search/settings/global-search)\n// ============================================================================\n\nexport const globalSearchSettingsResponseSchema = z.object({\n enabledStrategies: z.array(searchStrategyIdSchema),\n})\n\nexport const globalSearchSettingsUpdateSchema = z.object({\n enabledStrategies: z.array(searchStrategyIdSchema).min(1),\n})\n\nexport const globalSearchSettingsUpdateResponseSchema = z.object({\n ok: z.boolean(),\n enabledStrategies: z.array(searchStrategyIdSchema),\n})\n\n// ============================================================================\n// Reindex Endpoint Schemas (/api/search/reindex)\n// ============================================================================\n\nexport const reindexRequestSchema = z.object({\n action: z.enum(['clear', 'recreate', 'reindex']).optional().describe('Action to perform (default: reindex)'),\n entityId: z.string().optional().describe('Specific entity ID to reindex (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n useQueue: z.boolean().optional().describe('Whether to use queue (default: true)'),\n})\n\nexport const reindexResultSchema = z.object({\n entitiesProcessed: z.number().optional(),\n recordsIndexed: z.number().optional(),\n jobsEnqueued: z.number().optional(),\n errors: z.array(z.object({\n entityId: z.string(),\n error: z.string(),\n })).optional(),\n})\n\nexport const reindexResponseSchema = z.object({\n ok: z.boolean(),\n action: z.enum(['clear', 'recreate', 'reindex']),\n entityId: z.string().nullable(),\n useQueue: z.boolean().optional(),\n result: reindexResultSchema.optional(),\n stats: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional(),\n})\n\nexport const reindexConflictResponseSchema = z.object({\n error: z.string(),\n lock: reindexLockSchema,\n})\n\n// ============================================================================\n// Index Endpoint Schemas (/api/search/index)\n// ============================================================================\n\nexport const indexEntrySchema = z.object({\n id: z.string(),\n entityId: z.string(),\n recordId: z.string(),\n tenantId: z.string(),\n organizationId: z.string().nullable().optional(),\n title: z.string().optional(),\n subtitle: z.string().optional(),\n createdAt: z.string().optional(),\n})\n\nexport const indexListQueryParamsSchema = z.object({\n entityId: z.string().optional().describe('Filter by entity ID (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n limit: z.coerce.number().min(1).max(200).optional().describe('Maximum entries to return (default: 50, max: 200)'),\n offset: z.coerce.number().min(0).optional().describe('Offset for pagination (default: 0)'),\n})\n\nexport const indexListResponseSchema = z.object({\n entries: z.array(indexEntrySchema),\n limit: z.number(),\n offset: z.number(),\n})\n\nexport const indexPurgeQueryParamsSchema = z.object({\n entityId: z.string().optional().describe('Specific entity ID to purge (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n confirmAll: z.enum(['true']).optional().describe('Required when purging all entities'),\n})\n\nexport const indexPurgeResponseSchema = z.object({\n ok: z.boolean(),\n})\n\n// ============================================================================\n// Fulltext Settings Schemas (/api/search/settings/fulltext)\n// ============================================================================\n\nexport const fulltextEnvVarStatusSchema = z.object({\n set: z.boolean(),\n hint: z.string(),\n})\n\nexport const fulltextOptionalEnvVarStatusSchema = z.object({\n set: z.boolean(),\n value: z.union([z.string(), z.boolean()]).optional(),\n default: z.union([z.string(), z.boolean()]).optional(),\n hint: z.string(),\n})\n\nexport const fulltextSettingsResponseSchema = z.object({\n driver: z.enum(['meilisearch']).nullable(),\n configured: z.boolean(),\n envVars: z.object({\n MEILISEARCH_HOST: fulltextEnvVarStatusSchema,\n MEILISEARCH_API_KEY: fulltextEnvVarStatusSchema,\n }),\n optionalEnvVars: z.object({\n MEILISEARCH_INDEX_PREFIX: fulltextOptionalEnvVarStatusSchema,\n SEARCH_EXCLUDE_ENCRYPTED_FIELDS: fulltextOptionalEnvVarStatusSchema,\n }),\n})\n\n// ============================================================================\n// Vector Store Settings Schemas (/api/search/settings/vector-store)\n// ============================================================================\n\nexport const vectorDriverEnvVarSchema = z.object({\n name: z.string(),\n set: z.boolean(),\n hint: z.string(),\n})\n\nexport const vectorDriverStatusSchema = z.object({\n id: z.enum(['pgvector', 'qdrant', 'chromadb']),\n name: z.string(),\n configured: z.boolean(),\n implemented: z.boolean(),\n envVars: z.array(vectorDriverEnvVarSchema),\n})\n\nexport const vectorStoreSettingsResponseSchema = z.object({\n currentDriver: z.enum(['pgvector', 'qdrant', 'chromadb']),\n configured: z.boolean(),\n drivers: z.array(vectorDriverStatusSchema),\n})\n\n// ============================================================================\n// Embeddings Endpoint Schemas (/api/search/embeddings)\n// ============================================================================\n\nexport const embeddingProviderIdSchema = z.enum(['openai', 'google', 'mistral', 'cohere', 'bedrock', 'ollama'])\n\nexport const embeddingConfigSchema = z.object({\n providerId: embeddingProviderIdSchema,\n model: z.string(),\n dimension: z.number(),\n outputDimensionality: z.number().optional(),\n baseUrl: z.string().optional(),\n updatedAt: z.string().optional(),\n})\n\nexport const embeddingsSettingsSchema = z.object({\n openaiConfigured: z.boolean(),\n autoIndexingEnabled: z.boolean(),\n autoIndexingLocked: z.boolean(),\n lockReason: z.string().nullable(),\n embeddingConfig: embeddingConfigSchema.nullable(),\n configuredProviders: z.array(embeddingProviderIdSchema),\n indexedDimension: z.number().nullable(),\n reindexRequired: z.boolean(),\n documentCount: z.number().nullable(),\n})\n\nexport const embeddingsSettingsResponseSchema = z.object({\n settings: embeddingsSettingsSchema,\n})\n\nexport const embeddingsSettingsUpdateSchema = z.object({\n autoIndexingEnabled: z.boolean().optional(),\n embeddingConfig: z.object({\n providerId: embeddingProviderIdSchema,\n model: z.string(),\n dimension: z.number(),\n outputDimensionality: z.number().optional(),\n baseUrl: z.string().optional(),\n }).optional(),\n})\n\n// ============================================================================\n// Reindex Cancel Schemas (/api/search/reindex/cancel)\n// ============================================================================\n\nexport const reindexCancelResponseSchema = z.object({\n ok: z.boolean(),\n jobsRemoved: z.number(),\n})\n\n// ============================================================================\n// Vector Reindex Schemas (/api/search/embeddings/reindex)\n// ============================================================================\n\nexport const vectorReindexRequestSchema = z.object({\n entityId: z.string().optional().describe('Specific entity ID to reindex (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n purgeFirst: z.boolean().optional().describe('Purge existing entries before reindexing'),\n})\n\nexport const vectorReindexResponseSchema = z.object({\n ok: z.boolean(),\n recordsIndexed: z.number().optional(),\n jobsEnqueued: z.number().optional(),\n entitiesProcessed: z.number().optional(),\n errors: z.array(z.object({\n entityId: z.string(),\n error: z.string(),\n })).optional(),\n})\n\n// ============================================================================\n// OpenAPI Route Docs\n// ============================================================================\n\nexport const searchOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Search across all indexed entities',\n description: 'Performs a search using configured strategies (fulltext, vector, tokens). Use for search playground.',\n methods: {\n GET: {\n summary: 'Search across all indexed entities',\n description: 'Performs a search using configured strategies (fulltext, vector, tokens). Use for search playground.',\n tags: ['Search'],\n query: searchQueryParamsSchema,\n responses: [\n { status: 200, description: 'Search results', schema: searchResponseSchema },\n { status: 400, description: 'Missing query parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Search failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const globalSearchOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Global search (Cmd+K)',\n description: 'Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.',\n methods: {\n GET: {\n summary: 'Global search (Cmd+K)',\n description: 'Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.',\n tags: ['Search'],\n query: globalSearchQueryParamsSchema,\n responses: [\n { status: 200, description: 'Search results', schema: globalSearchResponseSchema },\n { status: 400, description: 'Missing query parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Search failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const settingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get search settings and status',\n description: 'Returns search module configuration, available strategies, and reindex lock status.',\n methods: {\n GET: {\n summary: 'Get search settings and status',\n description: 'Returns search module configuration, available strategies, and reindex lock status.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Search settings', schema: settingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const globalSearchSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Global search strategy settings',\n description: 'Manage enabled strategies for Cmd+K global search.',\n methods: {\n GET: {\n summary: 'Get global search strategies',\n description: 'Returns the enabled strategies for Cmd+K global search.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Global search settings', schema: globalSearchSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Update global search strategies',\n description: 'Sets which strategies are enabled for Cmd+K global search.',\n tags: ['Search'],\n requestBody: { schema: globalSearchSettingsUpdateSchema },\n responses: [\n { status: 200, description: 'Updated settings', schema: globalSearchSettingsUpdateResponseSchema },\n { status: 400, description: 'Invalid request', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Internal error', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const reindexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Trigger fulltext reindex',\n description: 'Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.',\n methods: {\n POST: {\n summary: 'Trigger fulltext reindex',\n description: 'Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.',\n tags: ['Search'],\n requestBody: { schema: reindexRequestSchema },\n responses: [\n { status: 200, description: 'Reindex result', schema: reindexResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Reindex already in progress', schema: reindexConflictResponseSchema },\n { status: 500, description: 'Reindex failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const reindexCancelOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Cancel fulltext reindex',\n description: 'Cancels an in-progress fulltext reindex operation.',\n methods: {\n POST: {\n summary: 'Cancel fulltext reindex',\n description: 'Cancels an in-progress fulltext reindex operation.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Cancel result', schema: reindexCancelResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const indexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Vector index management',\n description: 'List and purge vector search index entries.',\n methods: {\n GET: {\n summary: 'List vector index entries',\n description: 'Returns paginated list of entries in the vector search index.',\n tags: ['Search'],\n query: indexListQueryParamsSchema,\n responses: [\n { status: 200, description: 'Index entries', schema: indexListResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Failed to fetch index', schema: errorResponseSchema },\n { status: 503, description: 'Vector strategy unavailable', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Purge vector index',\n description: 'Purges entries from the vector search index. Requires confirmAll=true when purging all entities.',\n tags: ['Search'],\n query: indexPurgeQueryParamsSchema,\n responses: [\n { status: 200, description: 'Purge result', schema: indexPurgeResponseSchema },\n { status: 400, description: 'Missing confirmAll parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Purge failed', schema: errorResponseSchema },\n { status: 503, description: 'Search indexer unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const fulltextSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get fulltext search configuration',\n description: 'Returns Meilisearch configuration status and index statistics.',\n methods: {\n GET: {\n summary: 'Get fulltext search configuration',\n description: 'Returns Meilisearch configuration status and index statistics.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Fulltext settings', schema: fulltextSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const vectorStoreSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get vector store configuration',\n description: 'Returns vector store configuration status.',\n methods: {\n GET: {\n summary: 'Get vector store configuration',\n description: 'Returns vector store configuration status.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Vector store settings', schema: vectorStoreSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Embeddings configuration',\n description: 'Manage embedding provider and model configuration.',\n methods: {\n GET: {\n summary: 'Get embeddings configuration',\n description: 'Returns current embedding provider and model configuration.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Embeddings settings', schema: embeddingsSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Update embeddings configuration',\n description: 'Updates the embedding provider and model settings.',\n tags: ['Search'],\n requestBody: { schema: embeddingsSettingsUpdateSchema },\n responses: [\n { status: 200, description: 'Updated settings', schema: embeddingsSettingsResponseSchema },\n { status: 400, description: 'Invalid request', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Auto-indexing disabled via environment', schema: errorResponseSchema },\n { status: 500, description: 'Update failed', schema: errorResponseSchema },\n { status: 503, description: 'Configuration service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsReindexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Trigger vector reindex',\n description: 'Starts a vector embedding reindex operation.',\n methods: {\n POST: {\n summary: 'Trigger vector reindex',\n description: 'Starts a vector embedding reindex operation.',\n tags: ['Search'],\n requestBody: { schema: vectorReindexRequestSchema },\n responses: [\n { status: 200, description: 'Reindex result', schema: vectorReindexResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Reindex already in progress', schema: reindexConflictResponseSchema },\n { status: 500, description: 'Reindex failed', schema: errorResponseSchema },\n { status: 503, description: 'Search indexer unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsReindexCancelOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Cancel vector reindex',\n description: 'Cancels an in-progress vector reindex operation.',\n methods: {\n POST: {\n summary: 'Cancel vector reindex',\n description: 'Cancels an in-progress vector reindex operation.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Cancel result', schema: reindexCancelResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\n// ============================================================================\n// Common Schemas\n// ============================================================================\n\nexport const searchStrategyIdSchema = z.enum(['fulltext', 'vector', 'tokens'])\n\nexport const searchResultPresenterSchema = z.object({\n title: z.string(),\n subtitle: z.string().optional(),\n icon: z.string().optional(),\n badge: z.string().optional(),\n})\n\nexport const searchResultLinkSchema = z.object({\n href: z.string(),\n label: z.string(),\n kind: z.enum(['primary', 'secondary']),\n})\n\nexport const searchResultSchema = z.object({\n entityId: z.string().describe('Entity identifier (e.g., \"customers:customer_person_profile\")'),\n recordId: z.string().describe('Primary key of the record'),\n score: z.number().describe('Relevance score (0-1)'),\n source: searchStrategyIdSchema.describe('Which strategy returned this result'),\n presenter: searchResultPresenterSchema.optional(),\n url: z.string().optional(),\n links: z.array(searchResultLinkSchema).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const errorResponseSchema = z.object({\n error: z.string(),\n})\n\n// ============================================================================\n// Search Endpoint Schemas (/api/search)\n// ============================================================================\n\nexport const searchQueryParamsSchema = z.object({\n q: z.string().describe('Search query (required)'),\n limit: z.coerce.number().min(1).max(100).optional().describe('Maximum results to return (default: 50, max: 100)'),\n strategies: z.string().optional().describe('Comma-separated strategies to use: fulltext, vector, tokens (e.g., \"fulltext,vector\")'),\n entityTypes: z.string().optional().describe('Comma-separated entity types to filter results (e.g., \"customers:customer_person_profile,catalog:catalog_product,sales:sales_order\")'),\n})\n\nexport const searchResponseSchema = z.object({\n results: z.array(searchResultSchema),\n strategiesUsed: z.array(searchStrategyIdSchema),\n timing: z.number().describe('Search duration in milliseconds'),\n query: z.string(),\n limit: z.number(),\n})\n\n// ============================================================================\n// Global Search Endpoint Schemas (/api/search/global)\n// ============================================================================\n\nexport const globalSearchQueryParamsSchema = z.object({\n q: z.string().describe('Search query (required)'),\n limit: z.coerce.number().min(1).max(100).optional().describe('Maximum results to return (default: 50, max: 100)'),\n entityTypes: z.string().optional().describe('Comma-separated entity types to filter results (e.g., \"customers:customer_person_profile,catalog:catalog_product,sales:sales_order\")'),\n})\n\nexport const globalSearchResponseSchema = z.object({\n results: z.array(searchResultSchema),\n strategiesUsed: z.array(searchStrategyIdSchema),\n strategiesEnabled: z.array(searchStrategyIdSchema),\n timing: z.number().describe('Search duration in milliseconds'),\n query: z.string(),\n limit: z.number(),\n})\n\n// ============================================================================\n// Settings Endpoint Schemas (/api/search/settings)\n// ============================================================================\n\nexport const strategyStatusSchema = z.object({\n id: z.string(),\n name: z.string(),\n priority: z.number(),\n available: z.boolean(),\n})\n\nexport const fulltextStatsSchema = z.object({\n numberOfDocuments: z.number(),\n isIndexing: z.boolean(),\n fieldDistribution: z.record(z.string(), z.number()),\n})\n\nexport const reindexLockSchema = z.object({\n type: z.enum(['fulltext', 'vector']),\n action: z.string(),\n startedAt: z.string(),\n elapsedMinutes: z.number(),\n processedCount: z.number().nullable().optional(),\n totalCount: z.number().nullable().optional(),\n})\n\nexport const searchSettingsSchema = z.object({\n strategies: z.array(strategyStatusSchema),\n fulltextConfigured: z.boolean(),\n fulltextStats: fulltextStatsSchema.nullable(),\n vectorConfigured: z.boolean(),\n tokensEnabled: z.boolean(),\n defaultStrategies: z.array(z.string()),\n reindexLock: reindexLockSchema.nullable().describe('Deprecated: Use fulltextReindexLock or vectorReindexLock'),\n fulltextReindexLock: reindexLockSchema.nullable(),\n vectorReindexLock: reindexLockSchema.nullable(),\n})\n\nexport const settingsResponseSchema = z.object({\n settings: searchSettingsSchema,\n})\n\n// ============================================================================\n// Global Search Settings Schemas (/api/search/settings/global-search)\n// ============================================================================\n\nexport const globalSearchSettingsResponseSchema = z.object({\n enabledStrategies: z.array(searchStrategyIdSchema),\n})\n\nexport const globalSearchSettingsUpdateSchema = z.object({\n enabledStrategies: z.array(searchStrategyIdSchema).min(1),\n})\n\nexport const globalSearchSettingsUpdateResponseSchema = z.object({\n ok: z.boolean(),\n enabledStrategies: z.array(searchStrategyIdSchema),\n})\n\n// ============================================================================\n// Reindex Endpoint Schemas (/api/search/reindex)\n// ============================================================================\n\nexport const reindexRequestSchema = z.object({\n action: z.enum(['clear', 'recreate', 'reindex']).optional().describe('Action to perform (default: reindex)'),\n entityId: z.string().optional().describe('Specific entity ID to reindex (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n useQueue: z.boolean().optional().describe('Whether to use queue (default: true)'),\n})\n\nexport const reindexResultSchema = z.object({\n entitiesProcessed: z.number().optional(),\n recordsIndexed: z.number().optional(),\n jobsEnqueued: z.number().optional(),\n errors: z.array(z.object({\n entityId: z.string(),\n error: z.string(),\n })).optional(),\n})\n\nexport const reindexResponseSchema = z.object({\n ok: z.boolean(),\n action: z.enum(['clear', 'recreate', 'reindex']),\n entityId: z.string().nullable(),\n useQueue: z.boolean().optional(),\n result: reindexResultSchema.optional(),\n stats: z.record(z.string(), z.record(z.string(), z.unknown()).nullable()).optional(),\n})\n\nexport const reindexConflictResponseSchema = z.object({\n error: z.string(),\n lock: reindexLockSchema,\n})\n\n// ============================================================================\n// Index Endpoint Schemas (/api/search/index)\n// ============================================================================\n\nexport const indexEntrySchema = z.object({\n id: z.string(),\n entityId: z.string(),\n recordId: z.string(),\n tenantId: z.string(),\n organizationId: z.string().nullable().optional(),\n title: z.string().optional(),\n subtitle: z.string().optional(),\n createdAt: z.string().optional(),\n})\n\nexport const indexListQueryParamsSchema = z.object({\n entityId: z.string().optional().describe('Filter by entity ID (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n limit: z.coerce.number().min(1).max(200).optional().describe('Maximum entries to return (default: 50, max: 200)'),\n offset: z.coerce.number().min(0).optional().describe('Offset for pagination (default: 0)'),\n})\n\nexport const indexListResponseSchema = z.object({\n entries: z.array(indexEntrySchema),\n limit: z.number(),\n offset: z.number(),\n})\n\nexport const indexPurgeQueryParamsSchema = z.object({\n entityId: z.string().optional().describe('Specific entity ID to purge (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n confirmAll: z.enum(['true']).optional().describe('Required when purging all entities'),\n})\n\nexport const indexPurgeResponseSchema = z.object({\n ok: z.boolean(),\n})\n\n// ============================================================================\n// Fulltext Settings Schemas (/api/search/settings/fulltext)\n// ============================================================================\n\nexport const fulltextEnvVarStatusSchema = z.object({\n set: z.boolean(),\n hint: z.string(),\n})\n\nexport const fulltextOptionalEnvVarStatusSchema = z.object({\n set: z.boolean(),\n value: z.union([z.string(), z.boolean()]).optional(),\n default: z.union([z.string(), z.boolean()]).optional(),\n hint: z.string(),\n})\n\nexport const fulltextSettingsResponseSchema = z.object({\n driver: z.enum(['meilisearch']).nullable(),\n configured: z.boolean(),\n envVars: z.object({\n MEILISEARCH_HOST: fulltextEnvVarStatusSchema,\n MEILISEARCH_API_KEY: fulltextEnvVarStatusSchema,\n }),\n optionalEnvVars: z.object({\n MEILISEARCH_INDEX_PREFIX: fulltextOptionalEnvVarStatusSchema,\n SEARCH_EXCLUDE_ENCRYPTED_FIELDS: fulltextOptionalEnvVarStatusSchema,\n }),\n})\n\n// ============================================================================\n// Vector Store Settings Schemas (/api/search/settings/vector-store)\n// ============================================================================\n\nexport const vectorDriverEnvVarSchema = z.object({\n name: z.string(),\n set: z.boolean(),\n hint: z.string(),\n})\n\nexport const vectorDriverStatusSchema = z.object({\n id: z.enum(['pgvector', 'qdrant', 'chromadb']),\n name: z.string(),\n configured: z.boolean(),\n implemented: z.boolean(),\n available: z.boolean().nullable(),\n unavailableReason: z.string().nullable(),\n envVars: z.array(vectorDriverEnvVarSchema),\n})\n\nexport const vectorStoreSettingsResponseSchema = z.object({\n currentDriver: z.enum(['pgvector', 'qdrant', 'chromadb']),\n configured: z.boolean(),\n drivers: z.array(vectorDriverStatusSchema),\n})\n\n// ============================================================================\n// Embeddings Endpoint Schemas (/api/search/embeddings)\n// ============================================================================\n\nexport const embeddingProviderIdSchema = z.enum(['openai', 'google', 'mistral', 'cohere', 'bedrock', 'ollama'])\n\nexport const embeddingConfigSchema = z.object({\n providerId: embeddingProviderIdSchema,\n model: z.string(),\n dimension: z.number(),\n outputDimensionality: z.number().optional(),\n baseUrl: z.string().optional(),\n updatedAt: z.string().optional(),\n})\n\nexport const embeddingsSettingsSchema = z.object({\n openaiConfigured: z.boolean(),\n autoIndexingEnabled: z.boolean(),\n autoIndexingLocked: z.boolean(),\n lockReason: z.string().nullable(),\n embeddingConfig: embeddingConfigSchema.nullable(),\n configuredProviders: z.array(embeddingProviderIdSchema),\n indexedDimension: z.number().nullable(),\n reindexRequired: z.boolean(),\n documentCount: z.number().nullable(),\n})\n\nexport const embeddingsSettingsResponseSchema = z.object({\n settings: embeddingsSettingsSchema,\n})\n\nexport const embeddingsSettingsUpdateSchema = z.object({\n autoIndexingEnabled: z.boolean().optional(),\n embeddingConfig: z.object({\n providerId: embeddingProviderIdSchema,\n model: z.string(),\n dimension: z.number(),\n outputDimensionality: z.number().optional(),\n baseUrl: z.string().optional(),\n }).optional(),\n})\n\n// ============================================================================\n// Reindex Cancel Schemas (/api/search/reindex/cancel)\n// ============================================================================\n\nexport const reindexCancelResponseSchema = z.object({\n ok: z.boolean(),\n jobsRemoved: z.number(),\n})\n\n// ============================================================================\n// Vector Reindex Schemas (/api/search/embeddings/reindex)\n// ============================================================================\n\nexport const vectorReindexRequestSchema = z.object({\n entityId: z.string().optional().describe('Specific entity ID to reindex (e.g., \"customers:customer_person_profile\", \"catalog:catalog_product\")'),\n purgeFirst: z.boolean().optional().describe('Purge existing entries before reindexing'),\n})\n\nexport const vectorReindexResponseSchema = z.object({\n ok: z.boolean(),\n recordsIndexed: z.number().optional(),\n jobsEnqueued: z.number().optional(),\n entitiesProcessed: z.number().optional(),\n errors: z.array(z.object({\n entityId: z.string(),\n error: z.string(),\n })).optional(),\n})\n\n// ============================================================================\n// OpenAPI Route Docs\n// ============================================================================\n\nexport const searchOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Search across all indexed entities',\n description: 'Performs a search using configured strategies (fulltext, vector, tokens). Use for search playground.',\n methods: {\n GET: {\n summary: 'Search across all indexed entities',\n description: 'Performs a search using configured strategies (fulltext, vector, tokens). Use for search playground.',\n tags: ['Search'],\n query: searchQueryParamsSchema,\n responses: [\n { status: 200, description: 'Search results', schema: searchResponseSchema },\n { status: 400, description: 'Missing query parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Search failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const globalSearchOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Global search (Cmd+K)',\n description: 'Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.',\n methods: {\n GET: {\n summary: 'Global search (Cmd+K)',\n description: 'Performs a global search using saved tenant strategies. Does NOT accept strategies from URL.',\n tags: ['Search'],\n query: globalSearchQueryParamsSchema,\n responses: [\n { status: 200, description: 'Search results', schema: globalSearchResponseSchema },\n { status: 400, description: 'Missing query parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Search failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const settingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get search settings and status',\n description: 'Returns search module configuration, available strategies, and reindex lock status.',\n methods: {\n GET: {\n summary: 'Get search settings and status',\n description: 'Returns search module configuration, available strategies, and reindex lock status.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Search settings', schema: settingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const globalSearchSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Global search strategy settings',\n description: 'Manage enabled strategies for Cmd+K global search.',\n methods: {\n GET: {\n summary: 'Get global search strategies',\n description: 'Returns the enabled strategies for Cmd+K global search.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Global search settings', schema: globalSearchSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Update global search strategies',\n description: 'Sets which strategies are enabled for Cmd+K global search.',\n tags: ['Search'],\n requestBody: { schema: globalSearchSettingsUpdateSchema },\n responses: [\n { status: 200, description: 'Updated settings', schema: globalSearchSettingsUpdateResponseSchema },\n { status: 400, description: 'Invalid request', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Internal error', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const reindexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Trigger fulltext reindex',\n description: 'Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.',\n methods: {\n POST: {\n summary: 'Trigger fulltext reindex',\n description: 'Starts a fulltext (Meilisearch) reindex operation. Can clear, recreate, or fully reindex.',\n tags: ['Search'],\n requestBody: { schema: reindexRequestSchema },\n responses: [\n { status: 200, description: 'Reindex result', schema: reindexResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Reindex already in progress', schema: reindexConflictResponseSchema },\n { status: 500, description: 'Reindex failed', schema: errorResponseSchema },\n { status: 503, description: 'Search service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const reindexCancelOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Cancel fulltext reindex',\n description: 'Cancels an in-progress fulltext reindex operation.',\n methods: {\n POST: {\n summary: 'Cancel fulltext reindex',\n description: 'Cancels an in-progress fulltext reindex operation.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Cancel result', schema: reindexCancelResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const indexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Vector index management',\n description: 'List and purge vector search index entries.',\n methods: {\n GET: {\n summary: 'List vector index entries',\n description: 'Returns paginated list of entries in the vector search index.',\n tags: ['Search'],\n query: indexListQueryParamsSchema,\n responses: [\n { status: 200, description: 'Index entries', schema: indexListResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Failed to fetch index', schema: errorResponseSchema },\n { status: 503, description: 'Vector strategy unavailable', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Purge vector index',\n description: 'Purges entries from the vector search index. Requires confirmAll=true when purging all entities.',\n tags: ['Search'],\n query: indexPurgeQueryParamsSchema,\n responses: [\n { status: 200, description: 'Purge result', schema: indexPurgeResponseSchema },\n { status: 400, description: 'Missing confirmAll parameter', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 500, description: 'Purge failed', schema: errorResponseSchema },\n { status: 503, description: 'Search indexer unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const fulltextSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get fulltext search configuration',\n description: 'Returns Meilisearch configuration status and index statistics.',\n methods: {\n GET: {\n summary: 'Get fulltext search configuration',\n description: 'Returns Meilisearch configuration status and index statistics.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Fulltext settings', schema: fulltextSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const vectorStoreSettingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Get vector store configuration',\n description: 'Returns vector store configuration status.',\n methods: {\n GET: {\n summary: 'Get vector store configuration',\n description: 'Returns vector store configuration status.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Vector store settings', schema: vectorStoreSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Embeddings configuration',\n description: 'Manage embedding provider and model configuration.',\n methods: {\n GET: {\n summary: 'Get embeddings configuration',\n description: 'Returns current embedding provider and model configuration.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Embeddings settings', schema: embeddingsSettingsResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Update embeddings configuration',\n description: 'Updates the embedding provider and model settings.',\n tags: ['Search'],\n requestBody: { schema: embeddingsSettingsUpdateSchema },\n responses: [\n { status: 200, description: 'Updated settings', schema: embeddingsSettingsResponseSchema },\n { status: 400, description: 'Invalid request', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Auto-indexing disabled via environment', schema: errorResponseSchema },\n { status: 500, description: 'Update failed', schema: errorResponseSchema },\n { status: 503, description: 'Configuration service unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsReindexOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Trigger vector reindex',\n description: 'Starts a vector embedding reindex operation.',\n methods: {\n POST: {\n summary: 'Trigger vector reindex',\n description: 'Starts a vector embedding reindex operation.',\n tags: ['Search'],\n requestBody: { schema: vectorReindexRequestSchema },\n responses: [\n { status: 200, description: 'Reindex result', schema: vectorReindexResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 409, description: 'Reindex already in progress', schema: reindexConflictResponseSchema },\n { status: 500, description: 'Reindex failed', schema: errorResponseSchema },\n { status: 503, description: 'Search indexer unavailable', schema: errorResponseSchema },\n ],\n },\n },\n}\n\nexport const embeddingsReindexCancelOpenApi: OpenApiRouteDoc = {\n tag: 'Search',\n summary: 'Cancel vector reindex',\n description: 'Cancels an in-progress vector reindex operation.',\n methods: {\n POST: {\n summary: 'Cancel vector reindex',\n description: 'Cancels an in-progress vector reindex operation.',\n tags: ['Search'],\n responses: [\n { status: 200, description: 'Cancel result', schema: reindexCancelResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
2
3
|
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
3
4
|
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
4
5
|
import { vectorStoreSettingsOpenApi } from "../../openapi.js";
|
|
5
6
|
const metadata = {
|
|
6
7
|
GET: { requireAuth: true, requireFeatures: ["search.view"] }
|
|
7
8
|
};
|
|
9
|
+
async function probeDriverStatus(container, driverId) {
|
|
10
|
+
try {
|
|
11
|
+
const drivers = container.resolve("vectorDrivers");
|
|
12
|
+
const driver = drivers.find((entry) => entry.id === driverId);
|
|
13
|
+
if (!driver?.getStatus) return { available: null, unavailableReason: null };
|
|
14
|
+
const status = await driver.getStatus();
|
|
15
|
+
return {
|
|
16
|
+
available: status.available,
|
|
17
|
+
unavailableReason: status.available ? null : status.reason ?? null
|
|
18
|
+
};
|
|
19
|
+
} catch {
|
|
20
|
+
return { available: null, unavailableReason: null };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
8
23
|
const unauthorized = async () => {
|
|
9
24
|
const { t } = await resolveTranslations();
|
|
10
25
|
return NextResponse.json({ error: t("api.errors.unauthorized", "Unauthorized") }, { status: 401 });
|
|
@@ -16,12 +31,27 @@ async function GET(req) {
|
|
|
16
31
|
const qdrantUrlSet = Boolean(process.env.QDRANT_URL?.trim());
|
|
17
32
|
const qdrantApiKeySet = Boolean(process.env.QDRANT_API_KEY?.trim());
|
|
18
33
|
const chromaUrlSet = Boolean(process.env.CHROMA_URL?.trim());
|
|
34
|
+
let pgvectorStatus = {
|
|
35
|
+
available: null,
|
|
36
|
+
unavailableReason: null
|
|
37
|
+
};
|
|
38
|
+
if (databaseUrlSet) {
|
|
39
|
+
const container = await createRequestContainer();
|
|
40
|
+
try {
|
|
41
|
+
pgvectorStatus = await probeDriverStatus(container, "pgvector");
|
|
42
|
+
} finally {
|
|
43
|
+
const disposable = container;
|
|
44
|
+
if (typeof disposable.dispose === "function") await disposable.dispose();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
19
47
|
const drivers = [
|
|
20
48
|
{
|
|
21
49
|
id: "pgvector",
|
|
22
50
|
name: "PostgreSQL (pgvector)",
|
|
23
51
|
configured: databaseUrlSet,
|
|
24
52
|
implemented: true,
|
|
53
|
+
available: pgvectorStatus.available,
|
|
54
|
+
unavailableReason: pgvectorStatus.unavailableReason,
|
|
25
55
|
envVars: [
|
|
26
56
|
{
|
|
27
57
|
name: "DATABASE_URL",
|
|
@@ -35,6 +65,8 @@ async function GET(req) {
|
|
|
35
65
|
name: "Qdrant",
|
|
36
66
|
configured: qdrantUrlSet,
|
|
37
67
|
implemented: false,
|
|
68
|
+
available: null,
|
|
69
|
+
unavailableReason: null,
|
|
38
70
|
envVars: [
|
|
39
71
|
{
|
|
40
72
|
name: "QDRANT_URL",
|
|
@@ -53,6 +85,8 @@ async function GET(req) {
|
|
|
53
85
|
name: "ChromaDB",
|
|
54
86
|
configured: chromaUrlSet,
|
|
55
87
|
implemented: false,
|
|
88
|
+
available: null,
|
|
89
|
+
unavailableReason: null,
|
|
56
90
|
envVars: [
|
|
57
91
|
{
|
|
58
92
|
name: "CHROMA_URL",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/search/api/settings/vector-store/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { VectorDriverId } from '@open-mercato/shared/modules/vector'\nimport { vectorStoreSettingsOpenApi } from '../../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['search.view'] },\n}\n\ntype DriverStatus = {\n id: VectorDriverId\n name: string\n configured: boolean\n implemented: boolean\n envVars: {\n name: string\n set: boolean\n hint: string\n }[]\n}\n\ntype VectorStoreConfigResponse = {\n currentDriver: VectorDriverId\n configured: boolean\n drivers: DriverStatus[]\n}\n\nconst unauthorized = async () => {\n const { t } = await resolveTranslations()\n return NextResponse.json({ error: t('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.sub) return await unauthorized()\n\n // Check pgvector - uses existing DATABASE_URL\n const databaseUrlSet = Boolean(process.env.DATABASE_URL?.trim())\n\n // Check qdrant - would need QDRANT_URL\n const qdrantUrlSet = Boolean(process.env.QDRANT_URL?.trim())\n const qdrantApiKeySet = Boolean(process.env.QDRANT_API_KEY?.trim())\n\n // Check chromadb - would need CHROMA_URL\n const chromaUrlSet = Boolean(process.env.CHROMA_URL?.trim())\n\n const drivers: DriverStatus[] = [\n {\n id: 'pgvector',\n name: 'PostgreSQL (pgvector)',\n configured: databaseUrlSet,\n implemented: true,\n envVars: [\n {\n name: 'DATABASE_URL',\n set: databaseUrlSet,\n hint: 'PostgreSQL connection string with pgvector extension',\n },\n ],\n },\n {\n id: 'qdrant',\n name: 'Qdrant',\n configured: qdrantUrlSet,\n implemented: false,\n envVars: [\n {\n name: 'QDRANT_URL',\n set: qdrantUrlSet,\n hint: 'URL of your Qdrant server (e.g., http://localhost:6333)',\n },\n {\n name: 'QDRANT_API_KEY',\n set: qdrantApiKeySet,\n hint: 'API key for Qdrant authentication (optional for local)',\n },\n ],\n },\n {\n id: 'chromadb',\n name: 'ChromaDB',\n configured: chromaUrlSet,\n implemented: false,\n envVars: [\n {\n name: 'CHROMA_URL',\n set: chromaUrlSet,\n hint: 'URL of your ChromaDB server (e.g., http://localhost:8000)',\n },\n ],\n },\n ]\n\n // Currently only pgvector is supported\n const currentDriver: VectorDriverId = 'pgvector'\n const configured = databaseUrlSet\n\n const response: VectorStoreConfigResponse = {\n currentDriver,\n configured,\n drivers,\n }\n\n return NextResponse.json(response)\n}\n\nexport const openApi = vectorStoreSettingsOpenApi\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { VectorDriverId } from '@open-mercato/shared/modules/vector'\nimport type { VectorDriver } from '../../../../../vector'\nimport { vectorStoreSettingsOpenApi } from '../../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['search.view'] },\n}\n\ntype DriverStatus = {\n id: VectorDriverId\n name: string\n configured: boolean\n implemented: boolean\n /** Runtime reachability of the store itself; `null` when the driver exposes no probe. */\n available: boolean | null\n unavailableReason: string | null\n envVars: {\n name: string\n set: boolean\n hint: string\n }[]\n}\n\ntype VectorStoreConfigResponse = {\n currentDriver: VectorDriverId\n configured: boolean\n drivers: DriverStatus[]\n}\n\nasync function probeDriverStatus(\n container: { resolve: <T = unknown>(name: string) => T },\n driverId: VectorDriverId,\n): Promise<{ available: boolean | null; unavailableReason: string | null }> {\n try {\n const drivers = container.resolve<VectorDriver[]>('vectorDrivers')\n const driver = drivers.find((entry) => entry.id === driverId)\n if (!driver?.getStatus) return { available: null, unavailableReason: null }\n const status = await driver.getStatus()\n return {\n available: status.available,\n unavailableReason: status.available ? null : status.reason ?? null,\n }\n } catch {\n return { available: null, unavailableReason: null }\n }\n}\n\nconst unauthorized = async () => {\n const { t } = await resolveTranslations()\n return NextResponse.json({ error: t('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.sub) return await unauthorized()\n\n // Check pgvector - uses existing DATABASE_URL\n const databaseUrlSet = Boolean(process.env.DATABASE_URL?.trim())\n\n // Check qdrant - would need QDRANT_URL\n const qdrantUrlSet = Boolean(process.env.QDRANT_URL?.trim())\n const qdrantApiKeySet = Boolean(process.env.QDRANT_API_KEY?.trim())\n\n // Check chromadb - would need CHROMA_URL\n const chromaUrlSet = Boolean(process.env.CHROMA_URL?.trim())\n\n let pgvectorStatus: { available: boolean | null; unavailableReason: string | null } = {\n available: null,\n unavailableReason: null,\n }\n if (databaseUrlSet) {\n const container = await createRequestContainer()\n try {\n pgvectorStatus = await probeDriverStatus(container, 'pgvector')\n } finally {\n const disposable = container as { dispose?: () => Promise<unknown> }\n if (typeof disposable.dispose === 'function') await disposable.dispose()\n }\n }\n\n const drivers: DriverStatus[] = [\n {\n id: 'pgvector',\n name: 'PostgreSQL (pgvector)',\n configured: databaseUrlSet,\n implemented: true,\n available: pgvectorStatus.available,\n unavailableReason: pgvectorStatus.unavailableReason,\n envVars: [\n {\n name: 'DATABASE_URL',\n set: databaseUrlSet,\n hint: 'PostgreSQL connection string with pgvector extension',\n },\n ],\n },\n {\n id: 'qdrant',\n name: 'Qdrant',\n configured: qdrantUrlSet,\n implemented: false,\n available: null,\n unavailableReason: null,\n envVars: [\n {\n name: 'QDRANT_URL',\n set: qdrantUrlSet,\n hint: 'URL of your Qdrant server (e.g., http://localhost:6333)',\n },\n {\n name: 'QDRANT_API_KEY',\n set: qdrantApiKeySet,\n hint: 'API key for Qdrant authentication (optional for local)',\n },\n ],\n },\n {\n id: 'chromadb',\n name: 'ChromaDB',\n configured: chromaUrlSet,\n implemented: false,\n available: null,\n unavailableReason: null,\n envVars: [\n {\n name: 'CHROMA_URL',\n set: chromaUrlSet,\n hint: 'URL of your ChromaDB server (e.g., http://localhost:8000)',\n },\n ],\n },\n ]\n\n // Currently only pgvector is supported\n const currentDriver: VectorDriverId = 'pgvector'\n const configured = databaseUrlSet\n\n const response: VectorStoreConfigResponse = {\n currentDriver,\n configured,\n drivers,\n }\n\n return NextResponse.json(response)\n}\n\nexport const openApi = vectorStoreSettingsOpenApi\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/search/frontend/components/SearchSettingsPageClient.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { GlobalSearchSection } from './sections/GlobalSearchSection'\nimport { FulltextSearchSection } from './sections/FulltextSearchSection'\nimport { VectorSearchSection } from './sections/VectorSearchSection'\n\n// Types\ntype StrategyStatus = {\n id: string\n name: string\n priority: number\n available: boolean\n}\n\ntype FulltextStats = {\n numberOfDocuments: number\n isIndexing: boolean\n fieldDistribution: Record<string, number>\n}\n\ntype ReindexLock = {\n type: 'fulltext' | 'vector'\n action: string\n startedAt: string\n elapsedMinutes: number\n}\n\ntype SearchSettings = {\n strategies: StrategyStatus[]\n fulltextConfigured: boolean\n fulltextStats: FulltextStats | null\n vectorConfigured: boolean\n tokensEnabled: boolean\n defaultStrategies: string[]\n reindexLock: ReindexLock | null\n fulltextReindexLock: ReindexLock | null\n vectorReindexLock: ReindexLock | null\n}\n\ntype SettingsResponse = {\n settings?: SearchSettings\n error?: string\n}\n\n// Embedding types\ntype EmbeddingProviderId = 'openai' | 'google' | 'mistral' | 'cohere' | 'bedrock' | 'ollama'\n\ntype EmbeddingProviderConfig = {\n providerId: EmbeddingProviderId\n model: string\n dimension: number\n outputDimensionality?: number\n baseUrl?: string\n updatedAt: string\n}\n\ntype EmbeddingSettings = {\n openaiConfigured: boolean\n autoIndexingEnabled: boolean\n autoIndexingLocked: boolean\n lockReason: string | null\n embeddingConfig: EmbeddingProviderConfig | null\n configuredProviders: EmbeddingProviderId[]\n indexedDimension: number | null\n reindexRequired: boolean\n documentCount: number | null\n}\n\ntype EmbeddingSettingsResponse = {\n settings?: EmbeddingSettings\n error?: string\n}\n\n// Full-text search config types\ntype FulltextEnvVarStatus = {\n set: boolean\n hint: string\n}\n\ntype FulltextOptionalEnvVarStatus = {\n set: boolean\n value?: string | boolean\n default?: string | boolean\n hint: string\n}\n\ntype FulltextConfigResponse = {\n driver: 'meilisearch' | null\n configured: boolean\n envVars: {\n MEILISEARCH_HOST: FulltextEnvVarStatus\n MEILISEARCH_API_KEY: FulltextEnvVarStatus\n }\n optionalEnvVars: {\n MEILISEARCH_INDEX_PREFIX: FulltextOptionalEnvVarStatus\n SEARCH_EXCLUDE_ENCRYPTED_FIELDS: FulltextOptionalEnvVarStatus\n }\n}\n\n// Vector store driver types\ntype VectorDriverId = 'pgvector' | 'qdrant' | 'chromadb'\n\ntype VectorDriverEnvVar = {\n name: string\n set: boolean\n hint: string\n}\n\ntype VectorDriverStatus = {\n id: VectorDriverId\n name: string\n configured: boolean\n implemented: boolean\n envVars: VectorDriverEnvVar[]\n}\n\ntype VectorStoreConfigResponse = {\n currentDriver: VectorDriverId\n configured: boolean\n drivers: VectorDriverStatus[]\n}\n\nconst normalizeErrorMessage = (error: unknown, fallback: string): string => {\n if (typeof error === 'string' && error.trim().length) return error.trim()\n if (error instanceof Error && error.message.trim().length) return error.message.trim()\n return fallback\n}\n\nexport function SearchSettingsPageClient() {\n const t = useT()\n\n // Main settings state\n const [settings, setSettings] = React.useState<SearchSettings | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n // Embedding settings state\n const [embeddingSettings, setEmbeddingSettings] = React.useState<EmbeddingSettings | null>(null)\n const [embeddingLoading, setEmbeddingLoading] = React.useState(true)\n\n // Global search settings state\n const [globalSearchStrategies, setGlobalSearchStrategies] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchInitial, setGlobalSearchInitial] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchLoading, setGlobalSearchLoading] = React.useState(true)\n const [globalSearchSaving, setGlobalSearchSaving] = React.useState(false)\n\n // Full-text search config state\n const [fulltextConfig, setFulltextConfig] = React.useState<FulltextConfigResponse | null>(null)\n const [fulltextConfigLoading, setFulltextConfigLoading] = React.useState(true)\n\n // Vector store config state\n const [vectorStoreConfig, setVectorStoreConfig] = React.useState<VectorStoreConfigResponse | null>(null)\n const [vectorStoreConfigLoading, setVectorStoreConfigLoading] = React.useState(true)\n\n // Fetch main settings\n const fetchSettings = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n undefined,\n { errorMessage: t('search.settings.errorLabel', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n } else {\n setSettings({\n strategies: [],\n fulltextConfigured: false,\n fulltextStats: null,\n vectorConfigured: false,\n tokensEnabled: true,\n defaultStrategies: [],\n reindexLock: null,\n fulltextReindexLock: null,\n vectorReindexLock: null,\n })\n }\n } catch (err) {\n const message = normalizeErrorMessage(err, t('search.settings.errorLabel', 'Failed to load settings'))\n setError(message)\n flash(message, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchSettings()\n }, [fetchSettings])\n\n // Lightweight stats refresh for polling during reindex\n const refreshStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n const hasActiveReindexLock = Boolean(settings?.fulltextReindexLock || settings?.vectorReindexLock)\n React.useEffect(() => {\n if (!hasActiveReindexLock) return\n\n const interval = setInterval(() => {\n void refreshStatsOnly()\n }, 5000)\n\n return () => clearInterval(interval)\n }, [hasActiveReindexLock, refreshStatsOnly])\n\n // Lightweight embedding stats refresh\n const refreshEmbeddingStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n useAppEvent('progress.job.updated', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n useAppEvent('progress.job.completed', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n useAppEvent('om:bridge:reconnected', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n // Fetch embedding settings\n const fetchEmbeddingSettings = React.useCallback(async () => {\n setEmbeddingLoading(true)\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n undefined,\n { errorMessage: t('search.settings.errors.loadFailed', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n } else {\n setEmbeddingSettings({\n openaiConfigured: false,\n autoIndexingEnabled: true,\n autoIndexingLocked: false,\n lockReason: null,\n embeddingConfig: null,\n configuredProviders: [],\n indexedDimension: null,\n reindexRequired: false,\n documentCount: null,\n })\n }\n } catch {\n // Error already handled\n } finally {\n setEmbeddingLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchEmbeddingSettings()\n }, [fetchEmbeddingSettings])\n\n // Fetch global search settings\n const fetchGlobalSearchSettings = React.useCallback(async () => {\n setGlobalSearchLoading(true)\n try {\n const response = await fetch('/api/search/settings/global-search')\n if (response.ok) {\n const body = await response.json() as { enabledStrategies?: string[] }\n if (body.enabledStrategies && Array.isArray(body.enabledStrategies) && body.enabledStrategies.length > 0) {\n const strategies = new Set(body.enabledStrategies)\n setGlobalSearchStrategies(strategies)\n setGlobalSearchInitial(new Set(strategies))\n }\n }\n } catch {\n // Silently use defaults\n } finally {\n setGlobalSearchLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchGlobalSearchSettings()\n }, [fetchGlobalSearchSettings])\n\n // Fetch fulltext config\n const fetchFulltextConfig = React.useCallback(async () => {\n setFulltextConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/fulltext')\n if (response.ok) {\n const body = await response.json() as FulltextConfigResponse\n setFulltextConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setFulltextConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchFulltextConfig()\n }, [fetchFulltextConfig])\n\n // Fetch vector store config\n const fetchVectorStoreConfig = React.useCallback(async () => {\n setVectorStoreConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/vector-store')\n if (response.ok) {\n const body = await response.json() as VectorStoreConfigResponse\n setVectorStoreConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setVectorStoreConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchVectorStoreConfig()\n }, [fetchVectorStoreConfig])\n\n // Global search settings handlers - auto-save on toggle\n const toggleGlobalSearchStrategy = React.useCallback(async (strategyId: string) => {\n const newStrategies = new Set(globalSearchStrategies)\n if (newStrategies.has(strategyId)) {\n if (newStrategies.size > 1) {\n newStrategies.delete(strategyId)\n } else {\n return\n }\n } else {\n newStrategies.add(strategyId)\n }\n\n setGlobalSearchStrategies(newStrategies)\n setGlobalSearchSaving(true)\n\n try {\n const response = await fetch('/api/search/settings/global-search', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ enabledStrategies: Array.from(newStrategies) }),\n })\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({})) as { error?: string }\n throw new Error(body.error || t('search.settings.globalSearch.saveError', 'Failed to save settings'))\n }\n\n setGlobalSearchInitial(new Set(newStrategies))\n } catch (err) {\n setGlobalSearchStrategies(globalSearchInitial)\n flash(normalizeErrorMessage(err, t('search.settings.globalSearch.saveError', 'Failed to save settings')), 'error')\n } finally {\n setGlobalSearchSaving(false)\n }\n }, [globalSearchStrategies, globalSearchInitial, t])\n\n // Callbacks for section components\n const handleFulltextStatsUpdate = React.useCallback((stats: FulltextStats | null) => {\n setSettings(prev => prev ? { ...prev, fulltextStats: stats } : prev)\n }, [])\n\n const handleEmbeddingSettingsUpdate = React.useCallback((newSettings: EmbeddingSettings) => {\n setEmbeddingSettings(newSettings)\n }, [])\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Header */}\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-bold\">{t('search.settings.pageTitle', 'Search Settings')}</h1>\n <p className=\"text-muted-foreground\">{t('search.settings.pageDescription', 'Configure search strategies and view their availability.')}</p>\n </div>\n\n {/* Section 1: Global Search Settings */}\n <GlobalSearchSection\n loading={globalSearchLoading}\n saving={globalSearchSaving}\n strategies={globalSearchStrategies}\n fulltextConfigured={settings?.fulltextConfigured ?? false}\n vectorConfigured={settings?.vectorConfigured ?? false}\n onToggleStrategy={toggleGlobalSearchStrategy}\n />\n\n {/* Section 2: Full-Text Search (with tabs) */}\n <FulltextSearchSection\n fulltextConfig={fulltextConfig}\n fulltextConfigLoading={fulltextConfigLoading}\n fulltextStats={settings?.fulltextStats ?? null}\n fulltextReindexLock={settings?.fulltextReindexLock ?? null}\n loading={loading}\n onStatsUpdate={handleFulltextStatsUpdate}\n onRefresh={fetchSettings}\n />\n\n {/* Section 3: Vector Search (with tabs) */}\n <VectorSearchSection\n embeddingSettings={embeddingSettings}\n embeddingLoading={embeddingLoading}\n vectorStoreConfig={vectorStoreConfig}\n vectorStoreConfigLoading={vectorStoreConfigLoading}\n vectorReindexLock={settings?.vectorReindexLock ?? null}\n onEmbeddingSettingsUpdate={handleEmbeddingSettingsUpdate}\n onRefreshEmbeddings={fetchEmbeddingSettings}\n />\n\n {/* Refresh Button */}\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => fetchSettings()}\n disabled={loading}\n >\n {loading ? (\n <>\n <Spinner size=\"sm\" className=\"mr-2\" />\n {t('search.settings.loadingLabel', 'Loading settings...')}\n </>\n ) : (\n t('search.settings.refreshLabel', 'Refresh')\n )}\n </Button>\n {error && <span className=\"text-sm text-destructive\">{error}</span>}\n </div>\n </div>\n )\n}\n\nexport default SearchSettingsPageClient\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useAppEvent } from '@open-mercato/ui/backend/injection/useAppEvent'\nimport { GlobalSearchSection } from './sections/GlobalSearchSection'\nimport { FulltextSearchSection } from './sections/FulltextSearchSection'\nimport { VectorSearchSection } from './sections/VectorSearchSection'\n\n// Types\ntype StrategyStatus = {\n id: string\n name: string\n priority: number\n available: boolean\n}\n\ntype FulltextStats = {\n numberOfDocuments: number\n isIndexing: boolean\n fieldDistribution: Record<string, number>\n}\n\ntype ReindexLock = {\n type: 'fulltext' | 'vector'\n action: string\n startedAt: string\n elapsedMinutes: number\n}\n\ntype SearchSettings = {\n strategies: StrategyStatus[]\n fulltextConfigured: boolean\n fulltextStats: FulltextStats | null\n vectorConfigured: boolean\n tokensEnabled: boolean\n defaultStrategies: string[]\n reindexLock: ReindexLock | null\n fulltextReindexLock: ReindexLock | null\n vectorReindexLock: ReindexLock | null\n}\n\ntype SettingsResponse = {\n settings?: SearchSettings\n error?: string\n}\n\n// Embedding types\ntype EmbeddingProviderId = 'openai' | 'google' | 'mistral' | 'cohere' | 'bedrock' | 'ollama'\n\ntype EmbeddingProviderConfig = {\n providerId: EmbeddingProviderId\n model: string\n dimension: number\n outputDimensionality?: number\n baseUrl?: string\n updatedAt: string\n}\n\ntype EmbeddingSettings = {\n openaiConfigured: boolean\n autoIndexingEnabled: boolean\n autoIndexingLocked: boolean\n lockReason: string | null\n embeddingConfig: EmbeddingProviderConfig | null\n configuredProviders: EmbeddingProviderId[]\n indexedDimension: number | null\n reindexRequired: boolean\n documentCount: number | null\n}\n\ntype EmbeddingSettingsResponse = {\n settings?: EmbeddingSettings\n error?: string\n}\n\n// Full-text search config types\ntype FulltextEnvVarStatus = {\n set: boolean\n hint: string\n}\n\ntype FulltextOptionalEnvVarStatus = {\n set: boolean\n value?: string | boolean\n default?: string | boolean\n hint: string\n}\n\ntype FulltextConfigResponse = {\n driver: 'meilisearch' | null\n configured: boolean\n envVars: {\n MEILISEARCH_HOST: FulltextEnvVarStatus\n MEILISEARCH_API_KEY: FulltextEnvVarStatus\n }\n optionalEnvVars: {\n MEILISEARCH_INDEX_PREFIX: FulltextOptionalEnvVarStatus\n SEARCH_EXCLUDE_ENCRYPTED_FIELDS: FulltextOptionalEnvVarStatus\n }\n}\n\n// Vector store driver types\ntype VectorDriverId = 'pgvector' | 'qdrant' | 'chromadb'\n\ntype VectorDriverEnvVar = {\n name: string\n set: boolean\n hint: string\n}\n\ntype VectorDriverStatus = {\n id: VectorDriverId\n name: string\n configured: boolean\n implemented: boolean\n available?: boolean | null\n unavailableReason?: string | null\n envVars: VectorDriverEnvVar[]\n}\n\ntype VectorStoreConfigResponse = {\n currentDriver: VectorDriverId\n configured: boolean\n drivers: VectorDriverStatus[]\n}\n\nconst normalizeErrorMessage = (error: unknown, fallback: string): string => {\n if (typeof error === 'string' && error.trim().length) return error.trim()\n if (error instanceof Error && error.message.trim().length) return error.message.trim()\n return fallback\n}\n\nexport function SearchSettingsPageClient() {\n const t = useT()\n\n // Main settings state\n const [settings, setSettings] = React.useState<SearchSettings | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n // Embedding settings state\n const [embeddingSettings, setEmbeddingSettings] = React.useState<EmbeddingSettings | null>(null)\n const [embeddingLoading, setEmbeddingLoading] = React.useState(true)\n\n // Global search settings state\n const [globalSearchStrategies, setGlobalSearchStrategies] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchInitial, setGlobalSearchInitial] = React.useState<Set<string>>(() => new Set(['fulltext', 'vector', 'tokens']))\n const [globalSearchLoading, setGlobalSearchLoading] = React.useState(true)\n const [globalSearchSaving, setGlobalSearchSaving] = React.useState(false)\n\n // Full-text search config state\n const [fulltextConfig, setFulltextConfig] = React.useState<FulltextConfigResponse | null>(null)\n const [fulltextConfigLoading, setFulltextConfigLoading] = React.useState(true)\n\n // Vector store config state\n const [vectorStoreConfig, setVectorStoreConfig] = React.useState<VectorStoreConfigResponse | null>(null)\n const [vectorStoreConfigLoading, setVectorStoreConfigLoading] = React.useState(true)\n\n // Fetch main settings\n const fetchSettings = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n undefined,\n { errorMessage: t('search.settings.errorLabel', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n } else {\n setSettings({\n strategies: [],\n fulltextConfigured: false,\n fulltextStats: null,\n vectorConfigured: false,\n tokensEnabled: true,\n defaultStrategies: [],\n reindexLock: null,\n fulltextReindexLock: null,\n vectorReindexLock: null,\n })\n }\n } catch (err) {\n const message = normalizeErrorMessage(err, t('search.settings.errorLabel', 'Failed to load settings'))\n setError(message)\n flash(message, 'error')\n } finally {\n setLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchSettings()\n }, [fetchSettings])\n\n // Lightweight stats refresh for polling during reindex\n const refreshStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<SettingsResponse>(\n '/api/search/settings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n const hasActiveReindexLock = Boolean(settings?.fulltextReindexLock || settings?.vectorReindexLock)\n React.useEffect(() => {\n if (!hasActiveReindexLock) return\n\n const interval = setInterval(() => {\n void refreshStatsOnly()\n }, 5000)\n\n return () => clearInterval(interval)\n }, [hasActiveReindexLock, refreshStatsOnly])\n\n // Lightweight embedding stats refresh\n const refreshEmbeddingStatsOnly = React.useCallback(async () => {\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n { cache: 'no-store' },\n { errorMessage: '', allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n }\n } catch {\n // Silently ignore errors during polling\n }\n }, [])\n\n useAppEvent('progress.job.updated', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n useAppEvent('progress.job.completed', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n useAppEvent('om:bridge:reconnected', () => {\n void refreshStatsOnly()\n void refreshEmbeddingStatsOnly()\n }, [refreshStatsOnly, refreshEmbeddingStatsOnly])\n\n // Fetch embedding settings\n const fetchEmbeddingSettings = React.useCallback(async () => {\n setEmbeddingLoading(true)\n try {\n const body = await readApiResultOrThrow<EmbeddingSettingsResponse>(\n '/api/search/embeddings',\n undefined,\n { errorMessage: t('search.settings.errors.loadFailed', 'Failed to load settings'), allowNullResult: true },\n )\n if (body?.settings) {\n setEmbeddingSettings(body.settings)\n } else {\n setEmbeddingSettings({\n openaiConfigured: false,\n autoIndexingEnabled: true,\n autoIndexingLocked: false,\n lockReason: null,\n embeddingConfig: null,\n configuredProviders: [],\n indexedDimension: null,\n reindexRequired: false,\n documentCount: null,\n })\n }\n } catch {\n // Error already handled\n } finally {\n setEmbeddingLoading(false)\n }\n }, [t])\n\n React.useEffect(() => {\n fetchEmbeddingSettings()\n }, [fetchEmbeddingSettings])\n\n // Fetch global search settings\n const fetchGlobalSearchSettings = React.useCallback(async () => {\n setGlobalSearchLoading(true)\n try {\n const response = await fetch('/api/search/settings/global-search')\n if (response.ok) {\n const body = await response.json() as { enabledStrategies?: string[] }\n if (body.enabledStrategies && Array.isArray(body.enabledStrategies) && body.enabledStrategies.length > 0) {\n const strategies = new Set(body.enabledStrategies)\n setGlobalSearchStrategies(strategies)\n setGlobalSearchInitial(new Set(strategies))\n }\n }\n } catch {\n // Silently use defaults\n } finally {\n setGlobalSearchLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchGlobalSearchSettings()\n }, [fetchGlobalSearchSettings])\n\n // Fetch fulltext config\n const fetchFulltextConfig = React.useCallback(async () => {\n setFulltextConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/fulltext')\n if (response.ok) {\n const body = await response.json() as FulltextConfigResponse\n setFulltextConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setFulltextConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchFulltextConfig()\n }, [fetchFulltextConfig])\n\n // Fetch vector store config\n const fetchVectorStoreConfig = React.useCallback(async () => {\n setVectorStoreConfigLoading(true)\n try {\n const response = await fetch('/api/search/settings/vector-store')\n if (response.ok) {\n const body = await response.json() as VectorStoreConfigResponse\n setVectorStoreConfig(body)\n }\n } catch {\n // Silently use null\n } finally {\n setVectorStoreConfigLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n fetchVectorStoreConfig()\n }, [fetchVectorStoreConfig])\n\n // Global search settings handlers - auto-save on toggle\n const toggleGlobalSearchStrategy = React.useCallback(async (strategyId: string) => {\n const newStrategies = new Set(globalSearchStrategies)\n if (newStrategies.has(strategyId)) {\n if (newStrategies.size > 1) {\n newStrategies.delete(strategyId)\n } else {\n return\n }\n } else {\n newStrategies.add(strategyId)\n }\n\n setGlobalSearchStrategies(newStrategies)\n setGlobalSearchSaving(true)\n\n try {\n const response = await fetch('/api/search/settings/global-search', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ enabledStrategies: Array.from(newStrategies) }),\n })\n\n if (!response.ok) {\n const body = await response.json().catch(() => ({})) as { error?: string }\n throw new Error(body.error || t('search.settings.globalSearch.saveError', 'Failed to save settings'))\n }\n\n setGlobalSearchInitial(new Set(newStrategies))\n } catch (err) {\n setGlobalSearchStrategies(globalSearchInitial)\n flash(normalizeErrorMessage(err, t('search.settings.globalSearch.saveError', 'Failed to save settings')), 'error')\n } finally {\n setGlobalSearchSaving(false)\n }\n }, [globalSearchStrategies, globalSearchInitial, t])\n\n // Callbacks for section components\n const handleFulltextStatsUpdate = React.useCallback((stats: FulltextStats | null) => {\n setSettings(prev => prev ? { ...prev, fulltextStats: stats } : prev)\n }, [])\n\n const handleEmbeddingSettingsUpdate = React.useCallback((newSettings: EmbeddingSettings) => {\n setEmbeddingSettings(newSettings)\n }, [])\n\n return (\n <div className=\"flex flex-col gap-6\">\n {/* Header */}\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-bold\">{t('search.settings.pageTitle', 'Search Settings')}</h1>\n <p className=\"text-muted-foreground\">{t('search.settings.pageDescription', 'Configure search strategies and view their availability.')}</p>\n </div>\n\n {/* Section 1: Global Search Settings */}\n <GlobalSearchSection\n loading={globalSearchLoading}\n saving={globalSearchSaving}\n strategies={globalSearchStrategies}\n fulltextConfigured={settings?.fulltextConfigured ?? false}\n vectorConfigured={settings?.vectorConfigured ?? false}\n onToggleStrategy={toggleGlobalSearchStrategy}\n />\n\n {/* Section 2: Full-Text Search (with tabs) */}\n <FulltextSearchSection\n fulltextConfig={fulltextConfig}\n fulltextConfigLoading={fulltextConfigLoading}\n fulltextStats={settings?.fulltextStats ?? null}\n fulltextReindexLock={settings?.fulltextReindexLock ?? null}\n loading={loading}\n onStatsUpdate={handleFulltextStatsUpdate}\n onRefresh={fetchSettings}\n />\n\n {/* Section 3: Vector Search (with tabs) */}\n <VectorSearchSection\n embeddingSettings={embeddingSettings}\n embeddingLoading={embeddingLoading}\n vectorStoreConfig={vectorStoreConfig}\n vectorStoreConfigLoading={vectorStoreConfigLoading}\n vectorReindexLock={settings?.vectorReindexLock ?? null}\n onEmbeddingSettingsUpdate={handleEmbeddingSettingsUpdate}\n onRefreshEmbeddings={fetchEmbeddingSettings}\n />\n\n {/* Refresh Button */}\n <div className=\"flex items-center gap-3\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => fetchSettings()}\n disabled={loading}\n >\n {loading ? (\n <>\n <Spinner size=\"sm\" className=\"mr-2\" />\n {t('search.settings.loadingLabel', 'Loading settings...')}\n </>\n ) : (\n t('search.settings.refreshLabel', 'Refresh')\n )}\n </Button>\n {error && <span className=\"text-sm text-destructive\">{error}</span>}\n </div>\n </div>\n )\n}\n\nexport default SearchSettingsPageClient\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -294,6 +294,17 @@ function VectorSearchSection({
|
|
|
294
294
|
const hasUnsavedEmbeddingChanges = selectedProvider !== null && selectedProvider !== savedProvider || selectedModel !== null && selectedModel !== savedModel || selectedProvider !== null && selectedModel === null && displayProviderInfo.defaultModel !== savedModel || isCustomModel && (customModelName.trim() !== "" || customDimension !== 768);
|
|
295
295
|
const isEmbeddingConfigured = embeddingSettings?.configuredProviders?.includes(savedProvider);
|
|
296
296
|
const providerOptions = ["openai", "google", "mistral", "cohere", "bedrock", "ollama"];
|
|
297
|
+
const activeDriver = vectorStoreConfig?.drivers.find((driver) => driver.id === vectorStoreConfig.currentDriver);
|
|
298
|
+
const isStoreUnavailable = activeDriver?.available === false;
|
|
299
|
+
const storeUnavailableReason = activeDriver?.unavailableReason ?? null;
|
|
300
|
+
const storeUnavailableBanner = isStoreUnavailable ? /* @__PURE__ */ jsx("div", { className: "p-4 rounded-md bg-status-warning-bg border border-status-warning-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
301
|
+
/* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-status-warning-icon flex-shrink-0 mt-0.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
|
|
302
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
303
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-status-warning-text", children: t("search.settings.vector.storeUnavailable", "Vector store is not available") }),
|
|
304
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-status-warning-text mt-1", children: t("search.settings.vector.storeUnavailableHint", "Vector indexing and semantic search are skipped until the store is reachable. Install the pgvector extension on your PostgreSQL server; the status is rechecked about once a minute.") }),
|
|
305
|
+
storeUnavailableReason ? /* @__PURE__ */ jsx("p", { className: "text-xs text-status-warning-text mt-1 font-mono", children: storeUnavailableReason }) : null
|
|
306
|
+
] })
|
|
307
|
+
] }) }) : null;
|
|
297
308
|
const autoIndexingChecked = embeddingSettings ? embeddingSettings.autoIndexingEnabled : true;
|
|
298
309
|
const autoIndexingDisabled = embeddingLoading || embeddingSaving || Boolean(embeddingSettings?.autoIndexingLocked);
|
|
299
310
|
return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-card p-5 shadow-sm", children: [
|
|
@@ -309,11 +320,12 @@ function VectorSearchSection({
|
|
|
309
320
|
/* @__PURE__ */ jsx(Spinner, { size: "sm" }),
|
|
310
321
|
/* @__PURE__ */ jsx("span", { children: t("search.settings.loadingLabel", "Loading settings...") })
|
|
311
322
|
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
323
|
+
storeUnavailableBanner,
|
|
312
324
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
313
325
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-2", children: t("search.settings.vector.store", "Vector Store") }),
|
|
314
326
|
/* @__PURE__ */ jsx("div", { className: "grid gap-2 sm:grid-cols-3", children: vectorStoreConfig?.drivers.map((driver) => {
|
|
315
327
|
const isCurrent = driver.id === vectorStoreConfig.currentDriver;
|
|
316
|
-
const isReady = driver.configured && driver.implemented;
|
|
328
|
+
const isReady = driver.configured && driver.implemented && driver.available !== false;
|
|
317
329
|
return /* @__PURE__ */ jsxs(
|
|
318
330
|
"div",
|
|
319
331
|
{
|
|
@@ -491,7 +503,7 @@ function VectorSearchSection({
|
|
|
491
503
|
/* @__PURE__ */ jsx(TabsContent, { value: "index", children: embeddingLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
|
|
492
504
|
/* @__PURE__ */ jsx(Spinner, { size: "sm" }),
|
|
493
505
|
/* @__PURE__ */ jsx("span", { children: t("search.settings.loadingLabel", "Loading settings...") })
|
|
494
|
-
] }) : !isEmbeddingConfigured ? /* @__PURE__ */ jsx("div", { className: "p-4 rounded-md bg-status-warning-bg border border-status-warning-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
506
|
+
] }) : isStoreUnavailable ? storeUnavailableBanner : !isEmbeddingConfigured ? /* @__PURE__ */ jsx("div", { className: "p-4 rounded-md bg-status-warning-bg border border-status-warning-border", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
495
507
|
/* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-status-warning-icon flex-shrink-0 mt-0.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }),
|
|
496
508
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
497
509
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-status-warning-text", children: t("search.settings.vectorNotConfigured", "No embedding provider configured") }),
|