@open-mercato/search 0.4.2-canary-c02407ff85

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.
Files changed (237) hide show
  1. package/AGENTS.md +678 -0
  2. package/build.mjs +92 -0
  3. package/dist/di.js +157 -0
  4. package/dist/di.js.map +7 -0
  5. package/dist/fulltext/drivers/index.js +21 -0
  6. package/dist/fulltext/drivers/index.js.map +7 -0
  7. package/dist/fulltext/drivers/meilisearch/index.js +320 -0
  8. package/dist/fulltext/drivers/meilisearch/index.js.map +7 -0
  9. package/dist/fulltext/index.js +7 -0
  10. package/dist/fulltext/index.js.map +7 -0
  11. package/dist/fulltext/types.js +1 -0
  12. package/dist/fulltext/types.js.map +7 -0
  13. package/dist/index.js +12 -0
  14. package/dist/index.js.map +7 -0
  15. package/dist/indexer/index.js +8 -0
  16. package/dist/indexer/index.js.map +7 -0
  17. package/dist/indexer/search-indexer.js +848 -0
  18. package/dist/indexer/search-indexer.js.map +7 -0
  19. package/dist/indexer/subscribers/delete.js +41 -0
  20. package/dist/indexer/subscribers/delete.js.map +7 -0
  21. package/dist/lib/debug.js +34 -0
  22. package/dist/lib/debug.js.map +7 -0
  23. package/dist/lib/fallback-presenter.js +107 -0
  24. package/dist/lib/fallback-presenter.js.map +7 -0
  25. package/dist/lib/field-policy.js +75 -0
  26. package/dist/lib/field-policy.js.map +7 -0
  27. package/dist/lib/index.js +19 -0
  28. package/dist/lib/index.js.map +7 -0
  29. package/dist/lib/merger.js +93 -0
  30. package/dist/lib/merger.js.map +7 -0
  31. package/dist/lib/presenter-enricher.js +192 -0
  32. package/dist/lib/presenter-enricher.js.map +7 -0
  33. package/dist/modules/search/acl.js +14 -0
  34. package/dist/modules/search/acl.js.map +7 -0
  35. package/dist/modules/search/ai-tools.js +284 -0
  36. package/dist/modules/search/ai-tools.js.map +7 -0
  37. package/dist/modules/search/api/embeddings/reindex/cancel/route.js +65 -0
  38. package/dist/modules/search/api/embeddings/reindex/cancel/route.js.map +7 -0
  39. package/dist/modules/search/api/embeddings/reindex/route.js +165 -0
  40. package/dist/modules/search/api/embeddings/reindex/route.js.map +7 -0
  41. package/dist/modules/search/api/embeddings/route.js +246 -0
  42. package/dist/modules/search/api/embeddings/route.js.map +7 -0
  43. package/dist/modules/search/api/index/route.js +245 -0
  44. package/dist/modules/search/api/index/route.js.map +7 -0
  45. package/dist/modules/search/api/reindex/cancel/route.js +65 -0
  46. package/dist/modules/search/api/reindex/cancel/route.js.map +7 -0
  47. package/dist/modules/search/api/reindex/route.js +332 -0
  48. package/dist/modules/search/api/reindex/route.js.map +7 -0
  49. package/dist/modules/search/api/search/global/route.js +100 -0
  50. package/dist/modules/search/api/search/global/route.js.map +7 -0
  51. package/dist/modules/search/api/search/route.js +101 -0
  52. package/dist/modules/search/api/search/route.js.map +7 -0
  53. package/dist/modules/search/api/settings/fulltext/route.js +55 -0
  54. package/dist/modules/search/api/settings/fulltext/route.js.map +7 -0
  55. package/dist/modules/search/api/settings/global-search/route.js +80 -0
  56. package/dist/modules/search/api/settings/global-search/route.js.map +7 -0
  57. package/dist/modules/search/api/settings/route.js +118 -0
  58. package/dist/modules/search/api/settings/route.js.map +7 -0
  59. package/dist/modules/search/api/settings/vector-store/route.js +77 -0
  60. package/dist/modules/search/api/settings/vector-store/route.js.map +7 -0
  61. package/dist/modules/search/backend/config/search/page.js +10 -0
  62. package/dist/modules/search/backend/config/search/page.js.map +7 -0
  63. package/dist/modules/search/backend/config/search/page.meta.js +24 -0
  64. package/dist/modules/search/backend/config/search/page.meta.js.map +7 -0
  65. package/dist/modules/search/cli.js +698 -0
  66. package/dist/modules/search/cli.js.map +7 -0
  67. package/dist/modules/search/di.js +32 -0
  68. package/dist/modules/search/di.js.map +7 -0
  69. package/dist/modules/search/frontend/components/GlobalSearchDialog.js +357 -0
  70. package/dist/modules/search/frontend/components/GlobalSearchDialog.js.map +7 -0
  71. package/dist/modules/search/frontend/components/HybridSearchTable.js +343 -0
  72. package/dist/modules/search/frontend/components/HybridSearchTable.js.map +7 -0
  73. package/dist/modules/search/frontend/components/SearchSettingsPageClient.js +303 -0
  74. package/dist/modules/search/frontend/components/SearchSettingsPageClient.js.map +7 -0
  75. package/dist/modules/search/frontend/components/sections/FulltextSearchSection.js +360 -0
  76. package/dist/modules/search/frontend/components/sections/FulltextSearchSection.js.map +7 -0
  77. package/dist/modules/search/frontend/components/sections/GlobalSearchSection.js +101 -0
  78. package/dist/modules/search/frontend/components/sections/GlobalSearchSection.js.map +7 -0
  79. package/dist/modules/search/frontend/components/sections/VectorSearchSection.js +608 -0
  80. package/dist/modules/search/frontend/components/sections/VectorSearchSection.js.map +7 -0
  81. package/dist/modules/search/frontend/index.js +9 -0
  82. package/dist/modules/search/frontend/index.js.map +7 -0
  83. package/dist/modules/search/frontend/utils.js +41 -0
  84. package/dist/modules/search/frontend/utils.js.map +7 -0
  85. package/dist/modules/search/i18n/de.json +61 -0
  86. package/dist/modules/search/i18n/en.json +72 -0
  87. package/dist/modules/search/i18n/es.json +61 -0
  88. package/dist/modules/search/i18n/pl.json +61 -0
  89. package/dist/modules/search/index.js +11 -0
  90. package/dist/modules/search/index.js.map +7 -0
  91. package/dist/modules/search/lib/auto-indexing.js +29 -0
  92. package/dist/modules/search/lib/auto-indexing.js.map +7 -0
  93. package/dist/modules/search/lib/embedding-config.js +131 -0
  94. package/dist/modules/search/lib/embedding-config.js.map +7 -0
  95. package/dist/modules/search/lib/global-search-config.js +45 -0
  96. package/dist/modules/search/lib/global-search-config.js.map +7 -0
  97. package/dist/modules/search/lib/reindex-lock.js +99 -0
  98. package/dist/modules/search/lib/reindex-lock.js.map +7 -0
  99. package/dist/modules/search/subscribers/fulltext_upsert.js +64 -0
  100. package/dist/modules/search/subscribers/fulltext_upsert.js.map +7 -0
  101. package/dist/modules/search/subscribers/vector_delete.js +58 -0
  102. package/dist/modules/search/subscribers/vector_delete.js.map +7 -0
  103. package/dist/modules/search/subscribers/vector_purge.js +142 -0
  104. package/dist/modules/search/subscribers/vector_purge.js.map +7 -0
  105. package/dist/modules/search/subscribers/vector_upsert.js +58 -0
  106. package/dist/modules/search/subscribers/vector_upsert.js.map +7 -0
  107. package/dist/modules/search/workers/fulltext-index.worker.js +240 -0
  108. package/dist/modules/search/workers/fulltext-index.worker.js.map +7 -0
  109. package/dist/modules/search/workers/vector-index.worker.js +234 -0
  110. package/dist/modules/search/workers/vector-index.worker.js.map +7 -0
  111. package/dist/queue/fulltext-indexing.js +15 -0
  112. package/dist/queue/fulltext-indexing.js.map +7 -0
  113. package/dist/queue/index.js +3 -0
  114. package/dist/queue/index.js.map +7 -0
  115. package/dist/queue/vector-indexing.js +15 -0
  116. package/dist/queue/vector-indexing.js.map +7 -0
  117. package/dist/service.js +286 -0
  118. package/dist/service.js.map +7 -0
  119. package/dist/strategies/fulltext.strategy.js +116 -0
  120. package/dist/strategies/fulltext.strategy.js.map +7 -0
  121. package/dist/strategies/index.js +12 -0
  122. package/dist/strategies/index.js.map +7 -0
  123. package/dist/strategies/token.strategy.js +80 -0
  124. package/dist/strategies/token.strategy.js.map +7 -0
  125. package/dist/strategies/vector.strategy.js +137 -0
  126. package/dist/strategies/vector.strategy.js.map +7 -0
  127. package/dist/types.js +1 -0
  128. package/dist/types.js.map +7 -0
  129. package/dist/vector/drivers/chromadb/index.js +44 -0
  130. package/dist/vector/drivers/chromadb/index.js.map +7 -0
  131. package/dist/vector/drivers/index.js +9 -0
  132. package/dist/vector/drivers/index.js.map +7 -0
  133. package/dist/vector/drivers/pgvector/index.js +509 -0
  134. package/dist/vector/drivers/pgvector/index.js.map +7 -0
  135. package/dist/vector/drivers/qdrant/index.js +44 -0
  136. package/dist/vector/drivers/qdrant/index.js.map +7 -0
  137. package/dist/vector/index.js +4 -0
  138. package/dist/vector/index.js.map +7 -0
  139. package/dist/vector/lib/vector-logs.js +33 -0
  140. package/dist/vector/lib/vector-logs.js.map +7 -0
  141. package/dist/vector/services/checksum.js +20 -0
  142. package/dist/vector/services/checksum.js.map +7 -0
  143. package/dist/vector/services/embedding.js +222 -0
  144. package/dist/vector/services/embedding.js.map +7 -0
  145. package/dist/vector/services/index.js +4 -0
  146. package/dist/vector/services/index.js.map +7 -0
  147. package/dist/vector/services/vector-index.service.js +960 -0
  148. package/dist/vector/services/vector-index.service.js.map +7 -0
  149. package/dist/vector/types/pg.d.js +1 -0
  150. package/dist/vector/types/pg.d.js.map +7 -0
  151. package/dist/vector/types.js +75 -0
  152. package/dist/vector/types.js.map +7 -0
  153. package/jest.config.cjs +19 -0
  154. package/package.json +142 -0
  155. package/src/__tests__/queue.test.ts +148 -0
  156. package/src/__tests__/service.test.ts +345 -0
  157. package/src/__tests__/workers.test.ts +319 -0
  158. package/src/di.ts +291 -0
  159. package/src/fulltext/drivers/index.ts +41 -0
  160. package/src/fulltext/drivers/meilisearch/index.ts +410 -0
  161. package/src/fulltext/index.ts +13 -0
  162. package/src/fulltext/types.ts +115 -0
  163. package/src/index.ts +36 -0
  164. package/src/indexer/index.ts +13 -0
  165. package/src/indexer/search-indexer.ts +1141 -0
  166. package/src/indexer/subscribers/delete.ts +49 -0
  167. package/src/lib/debug.ts +46 -0
  168. package/src/lib/fallback-presenter.ts +106 -0
  169. package/src/lib/field-policy.ts +169 -0
  170. package/src/lib/index.ts +13 -0
  171. package/src/lib/merger.ts +159 -0
  172. package/src/lib/presenter-enricher.ts +323 -0
  173. package/src/modules/search/README.md +694 -0
  174. package/src/modules/search/acl.ts +10 -0
  175. package/src/modules/search/ai-tools.ts +467 -0
  176. package/src/modules/search/api/embeddings/reindex/cancel/route.ts +77 -0
  177. package/src/modules/search/api/embeddings/reindex/route.ts +197 -0
  178. package/src/modules/search/api/embeddings/route.ts +304 -0
  179. package/src/modules/search/api/index/route.ts +297 -0
  180. package/src/modules/search/api/reindex/cancel/route.ts +77 -0
  181. package/src/modules/search/api/reindex/route.ts +419 -0
  182. package/src/modules/search/api/search/global/route.ts +120 -0
  183. package/src/modules/search/api/search/route.ts +121 -0
  184. package/src/modules/search/api/settings/fulltext/route.ts +82 -0
  185. package/src/modules/search/api/settings/global-search/route.ts +91 -0
  186. package/src/modules/search/api/settings/route.ts +187 -0
  187. package/src/modules/search/api/settings/vector-store/route.ts +105 -0
  188. package/src/modules/search/backend/config/search/page.meta.ts +22 -0
  189. package/src/modules/search/backend/config/search/page.tsx +12 -0
  190. package/src/modules/search/cli.ts +818 -0
  191. package/src/modules/search/di.ts +50 -0
  192. package/src/modules/search/frontend/components/GlobalSearchDialog.tsx +436 -0
  193. package/src/modules/search/frontend/components/HybridSearchTable.tsx +418 -0
  194. package/src/modules/search/frontend/components/SearchSettingsPageClient.tsx +476 -0
  195. package/src/modules/search/frontend/components/sections/FulltextSearchSection.tsx +624 -0
  196. package/src/modules/search/frontend/components/sections/GlobalSearchSection.tsx +124 -0
  197. package/src/modules/search/frontend/components/sections/VectorSearchSection.tsx +943 -0
  198. package/src/modules/search/frontend/index.ts +3 -0
  199. package/src/modules/search/frontend/utils.ts +82 -0
  200. package/src/modules/search/i18n/de.json +61 -0
  201. package/src/modules/search/i18n/en.json +72 -0
  202. package/src/modules/search/i18n/es.json +61 -0
  203. package/src/modules/search/i18n/pl.json +61 -0
  204. package/src/modules/search/index.ts +9 -0
  205. package/src/modules/search/lib/auto-indexing.ts +35 -0
  206. package/src/modules/search/lib/embedding-config.ts +161 -0
  207. package/src/modules/search/lib/global-search-config.ts +69 -0
  208. package/src/modules/search/lib/reindex-lock.ts +201 -0
  209. package/src/modules/search/subscribers/fulltext_upsert.ts +83 -0
  210. package/src/modules/search/subscribers/vector_delete.ts +75 -0
  211. package/src/modules/search/subscribers/vector_purge.ts +161 -0
  212. package/src/modules/search/subscribers/vector_upsert.ts +75 -0
  213. package/src/modules/search/workers/fulltext-index.worker.ts +318 -0
  214. package/src/modules/search/workers/vector-index.worker.ts +292 -0
  215. package/src/queue/fulltext-indexing.ts +87 -0
  216. package/src/queue/index.ts +2 -0
  217. package/src/queue/vector-indexing.ts +66 -0
  218. package/src/service.ts +397 -0
  219. package/src/strategies/fulltext.strategy.ts +155 -0
  220. package/src/strategies/index.ts +17 -0
  221. package/src/strategies/token.strategy.ts +153 -0
  222. package/src/strategies/vector.strategy.ts +234 -0
  223. package/src/types.ts +38 -0
  224. package/src/vector/drivers/chromadb/index.ts +49 -0
  225. package/src/vector/drivers/index.ts +4 -0
  226. package/src/vector/drivers/pgvector/index.ts +627 -0
  227. package/src/vector/drivers/qdrant/index.ts +49 -0
  228. package/src/vector/index.ts +3 -0
  229. package/src/vector/lib/vector-logs.ts +46 -0
  230. package/src/vector/services/checksum.ts +18 -0
  231. package/src/vector/services/embedding.ts +275 -0
  232. package/src/vector/services/index.ts +3 -0
  233. package/src/vector/services/vector-index.service.ts +1234 -0
  234. package/src/vector/types/pg.d.ts +1 -0
  235. package/src/vector/types.ts +220 -0
  236. package/tsconfig.json +9 -0
  237. package/watch.mjs +6 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/vector/services/vector-index.service.ts"],
4
+ "sourcesContent": ["import type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport {\n type VectorModuleConfig,\n type VectorEntityConfig,\n type VectorQueryRequest,\n type VectorSearchHit,\n type VectorIndexSource,\n type VectorDriverId,\n type VectorLinkDescriptor,\n type VectorResultPresenter,\n type VectorIndexEntry,\n} from '../types'\nimport type { VectorDriver } from '../types'\nimport { computeChecksum } from './checksum'\nimport { EmbeddingService } from './embedding'\nimport { logVectorOperation } from '../lib/vector-logs'\nimport { searchDebug, searchDebugWarn } from '../../lib/debug'\n\ntype ContainerResolver = () => unknown\nconst VECTOR_ENTRY_ENCRYPTION_ENTITY_ID = 'vector:vector_search'\n\nconst ENRICHMENT_FIELD_HINTS: Record<EntityId, string[]> = {\n 'customers:customer_entity': [\n 'id',\n 'organization_id',\n 'tenant_id',\n 'display_name',\n 'description',\n 'status',\n 'lifecycle_stage',\n 'primary_email',\n 'primary_phone',\n 'kind',\n 'customer_kind',\n ],\n 'customers:customer_comment': ['id', 'organization_id', 'tenant_id', 'entity_id', 'body', 'appearance_icon', 'appearance_color'],\n 'customers:customer_activity': ['id', 'organization_id', 'tenant_id', 'entity_id', 'activity_type', 'subject', 'body', 'deal_id'],\n 'customers:customer_deal': ['id', 'organization_id', 'tenant_id', 'title', 'pipeline_stage', 'status', 'value_amount', 'value_currency'],\n 'customers:customer_todo_link': ['id', 'organization_id', 'tenant_id', 'entity_id', 'todo_id', 'todo_source'],\n 'customers:customer_person_profile': [\n 'id',\n 'organization_id',\n 'tenant_id',\n 'entity_id',\n 'first_name',\n 'last_name',\n 'preferred_name',\n 'job_title',\n 'department',\n ],\n 'customers:customer_company_profile': [\n 'id',\n 'organization_id',\n 'tenant_id',\n 'entity_id',\n 'brand_name',\n 'legal_name',\n 'domain',\n 'industry',\n 'size_bucket',\n ],\n}\n\nexport type VectorIndexServiceOptions = {\n drivers: VectorDriver[]\n embeddingService: EmbeddingService\n queryEngine: QueryEngine\n moduleConfigs: VectorModuleConfig[]\n defaultDriverId?: VectorDriverId\n containerResolver?: ContainerResolver\n eventBus?: {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n}\n\ntype IndexRecordArgs = {\n entityId: EntityId\n recordId: string\n tenantId: string\n organizationId?: string | null\n}\n\ntype DeleteRecordArgs = {\n entityId: EntityId\n recordId: string\n tenantId: string\n organizationId?: string | null\n}\n\nexport type VectorIndexOperationResult = {\n action: 'indexed' | 'deleted' | 'skipped'\n created?: boolean\n existed?: boolean\n tenantId: string\n organizationId: string | null\n reason?: 'unsupported' | 'missing_record' | 'checksum_match'\n}\n\nexport class VectorIndexService {\n private readonly driverMap = new Map<VectorDriverId, VectorDriver>()\n private readonly entityConfig = new Map<EntityId, { config: VectorEntityConfig; driverId: VectorDriverId }>()\n private readonly defaultDriverId: VectorDriverId\n\n constructor(private readonly opts: VectorIndexServiceOptions) {\n for (const driver of opts.drivers) {\n this.driverMap.set(driver.id, driver)\n }\n this.defaultDriverId = opts.defaultDriverId ?? 'pgvector'\n for (const moduleConfig of opts.moduleConfigs) {\n const driverId = moduleConfig.defaultDriverId ?? this.defaultDriverId\n for (const entity of moduleConfig.entities ?? []) {\n if (!entity?.entityId) continue\n if (entity.enabled === false) continue\n const targetDriver = entity.driverId ?? driverId\n this.entityConfig.set(entity.entityId, { config: entity, driverId: targetDriver })\n }\n }\n }\n\n private resolveEncryptionService(): TenantDataEncryptionService | null {\n if (!this.opts.containerResolver) return null\n try {\n const container = this.opts.containerResolver() as any\n if (!container || typeof container.resolve !== 'function') return null\n return container.resolve('tenantEncryptionService') as TenantDataEncryptionService\n } catch {\n return null\n }\n }\n\n private async encryptResultFields(args: {\n tenantId: string\n organizationId: string | null\n resultTitle: string\n resultSubtitle: string | null\n resultIcon: string | null\n resultSnapshot: string | null\n primaryLinkHref: string | null\n primaryLinkLabel: string | null\n links: VectorLinkDescriptor[] | string | null\n payload: Record<string, unknown> | string | null\n }): Promise<{\n resultTitle: string\n resultSubtitle: string | null\n resultIcon: string | null\n resultSnapshot: string | null\n primaryLinkHref: string | null\n primaryLinkLabel: string | null\n links: VectorLinkDescriptor[] | string | null\n payload: Record<string, unknown> | string | null\n }> {\n const service = this.resolveEncryptionService()\n if (!service || !service.isEnabled?.()) {\n return {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n }\n }\n try {\n const encrypted = await service.encryptEntityPayload(\n VECTOR_ENTRY_ENCRYPTION_ENTITY_ID,\n {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n },\n args.tenantId,\n args.organizationId,\n )\n return {\n resultTitle: String((encrypted as any).resultTitle ?? args.resultTitle),\n resultSubtitle: ((encrypted as any).resultSubtitle ?? args.resultSubtitle) as any,\n resultIcon: ((encrypted as any).resultIcon ?? args.resultIcon) as any,\n resultSnapshot: ((encrypted as any).resultSnapshot ?? args.resultSnapshot) as any,\n primaryLinkHref: ((encrypted as any).primaryLinkHref ?? args.primaryLinkHref) as any,\n primaryLinkLabel: ((encrypted as any).primaryLinkLabel ?? args.primaryLinkLabel) as any,\n links: ((encrypted as any).links ?? args.links) as any,\n payload: ((encrypted as any).payload ?? args.payload) as any,\n }\n } catch {\n return {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n }\n }\n }\n\n private async decryptResultFields(args: {\n tenantId: string\n organizationId: string | null\n resultTitle: string\n resultSubtitle: string | null\n resultIcon: string | null\n resultSnapshot: string | null\n primaryLinkHref: string | null\n primaryLinkLabel: string | null\n links: VectorLinkDescriptor[] | string | null\n payload: Record<string, unknown> | string | null\n }): Promise<{\n resultTitle: string\n resultSubtitle: string | null\n resultIcon: string | null\n resultSnapshot: string | null\n primaryLinkHref: string | null\n primaryLinkLabel: string | null\n links: VectorLinkDescriptor[] | string | null\n payload: Record<string, unknown> | string | null\n }> {\n const service = this.resolveEncryptionService()\n if (!service || !service.isEnabled?.() || typeof service.decryptEntityPayload !== 'function') {\n return {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n }\n }\n try {\n const decrypted = await service.decryptEntityPayload(\n VECTOR_ENTRY_ENCRYPTION_ENTITY_ID,\n {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n },\n args.tenantId,\n args.organizationId,\n )\n return {\n resultTitle: String((decrypted as any).resultTitle ?? args.resultTitle),\n resultSubtitle: ((decrypted as any).resultSubtitle ?? args.resultSubtitle) as any,\n resultIcon: ((decrypted as any).resultIcon ?? args.resultIcon) as any,\n resultSnapshot: ((decrypted as any).resultSnapshot ?? args.resultSnapshot) as any,\n primaryLinkHref: ((decrypted as any).primaryLinkHref ?? args.primaryLinkHref) as any,\n primaryLinkLabel: ((decrypted as any).primaryLinkLabel ?? args.primaryLinkLabel) as any,\n links: ((decrypted as any).links ?? args.links) as any,\n payload: ((decrypted as any).payload ?? args.payload) as any,\n }\n } catch {\n return {\n resultTitle: args.resultTitle,\n resultSubtitle: args.resultSubtitle,\n resultIcon: args.resultIcon,\n resultSnapshot: args.resultSnapshot,\n primaryLinkHref: args.primaryLinkHref,\n primaryLinkLabel: args.primaryLinkLabel,\n links: args.links,\n payload: args.payload,\n }\n }\n }\n\n listEnabledEntities(): EntityId[] {\n return Array.from(this.entityConfig.keys())\n }\n\n async ensureDriverReady(entityId?: EntityId): Promise<void> {\n if (entityId) {\n const entry = this.entityConfig.get(entityId)\n if (!entry) return\n const driver = this.getDriver(entry.driverId)\n await driver.ensureReady()\n return\n }\n const uniqueDrivers = new Set<VectorDriverId>()\n for (const entry of this.entityConfig.values()) {\n uniqueDrivers.add(entry.driverId)\n }\n if (!uniqueDrivers.size) uniqueDrivers.add(this.defaultDriverId)\n await Promise.all(Array.from(uniqueDrivers).map(async (driverId) => {\n try {\n const driver = this.getDriver(driverId)\n await driver.ensureReady()\n } catch (err) {\n searchDebugWarn('vector', 'Failed to ensure driver readiness', { driverId, error: err instanceof Error ? err.message : err })\n }\n }))\n }\n\n private getDriver(driverId: VectorDriverId): VectorDriver {\n const driver = this.driverMap.get(driverId)\n if (!driver) {\n throw new Error(`[vector] Driver ${driverId} is not registered`)\n }\n return driver\n }\n\n private getEnrichmentFields(entityId: EntityId): string[] | undefined {\n const hints = ENRICHMENT_FIELD_HINTS[entityId]\n if (!hints) return undefined\n const unique = new Set<string>(['id', ...hints])\n return Array.from(unique)\n }\n\n private async fetchRecord(entityId: EntityId, recordIds: string[], tenantId: string, organizationId?: string | null) {\n const filters: Record<string, any> = { id: { $in: recordIds } }\n const result = await this.opts.queryEngine.query(entityId, {\n tenantId,\n organizationId: organizationId ?? undefined,\n filters,\n includeCustomFields: true,\n fields: this.getEnrichmentFields(entityId),\n })\n const byId = new Map<string, Record<string, any>>()\n for (const item of result.items) {\n const key = String((item as any).id ?? '')\n if (!key) continue\n byId.set(key, item as Record<string, any>)\n }\n return byId\n }\n\n private extractRecordPayload(entityId: EntityId, raw: Record<string, any>) {\n const record: Record<string, any> = {}\n const customFields: Record<string, any> = {}\n const multiMap = new Map<string, boolean>()\n\n for (const [key, value] of Object.entries(raw)) {\n if (key.startsWith('cf:') && key.endsWith('__is_multi')) {\n const base = key.replace(/__is_multi$/, '')\n multiMap.set(base, Boolean(value))\n continue\n }\n if (key.startsWith('cf:')) {\n customFields[key.slice(3)] = value\n continue\n }\n record[key] = value\n }\n\n for (const [key, isMulti] of multiMap.entries()) {\n const bare = key.slice(3)\n if (bare && customFields[bare] != null && !Array.isArray(customFields[bare]) && isMulti) {\n customFields[bare] = [customFields[bare]]\n }\n }\n\n if (record.entity_id == null && record.entityId == null && entityId.endsWith('_company_profile')) {\n searchDebugWarn('vector.index', 'company profile missing entity id in payload', {\n id: record.id,\n keys: Object.keys(record),\n })\n }\n\n return { record, customFields }\n }\n\n private async indexExisting(\n entry: { config: VectorEntityConfig; driverId: VectorDriverId },\n driver: VectorDriver,\n args: IndexRecordArgs,\n raw: Record<string, any>,\n opts: { skipDelete?: boolean } = {},\n ): Promise<VectorIndexOperationResult> {\n const scopeOrg = args.organizationId ?? null\n const { record, customFields } = this.extractRecordPayload(args.entityId, raw)\n const resolvedOrgId = scopeOrg ?? (record.organization_id ?? record.organizationId ?? null)\n const source = await this.resolveSource(args.entityId, entry.config, {\n record,\n customFields,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n })\n if (!source) {\n const existing = await driver.getChecksum(args.entityId, args.recordId, args.tenantId)\n if (!opts.skipDelete && existing) {\n await driver.delete(args.entityId, args.recordId, args.tenantId)\n return {\n action: 'deleted',\n existed: true,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n }\n }\n return {\n action: 'skipped',\n existed: Boolean(existing),\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n reason: 'missing_record',\n }\n }\n\n const checksumSource = source.checksumSource ?? { record, customFields }\n const checksum = computeChecksum(checksumSource)\n const current = await driver.getChecksum(args.entityId, args.recordId, args.tenantId)\n if (current && current === checksum) {\n return {\n action: 'skipped',\n existed: true,\n tenantId: args.tenantId,\n organizationId: scopeOrg,\n reason: 'checksum_match',\n }\n }\n if (!this.opts.embeddingService.available) {\n throw new Error('[vector] Embedding service unavailable (missing OPENAI_API_KEY)')\n }\n const embedding = await this.opts.embeddingService.createEmbedding(source.input)\n const presenter = await this.resolvePresenter(entry.config, {\n record,\n customFields,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n }, source.presenter ?? null)\n if (!presenter?.title) {\n searchDebugWarn('vector.index', 'missing presenter title', {\n entityId: args.entityId,\n recordId: args.recordId,\n recordSample: {\n display_name: record.display_name,\n displayName: record.displayName,\n name: record.name,\n title: record.title,\n subject: record.subject,\n kind: record.kind,\n },\n })\n }\n const links = await this.resolveLinks(entry.config, {\n record,\n customFields,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n }, source.links ?? null)\n const url = await this.resolveUrl(entry.config, {\n record,\n customFields,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n })\n\n const normalizedPresenter = this.ensurePresenter(presenter, record, customFields, args.recordId, args.entityId)\n const normalizedLinks = Array.isArray(links) && links.length ? links : null\n const snapshot = this.deriveSnapshot(record, customFields)\n const rawResultTitle = this.resolveResultTitle(normalizedPresenter, record, customFields, args.recordId)\n const rawResultSubtitle = normalizedPresenter.subtitle ?? snapshot ?? null\n const rawResultIcon = normalizedPresenter.icon ?? this.mapDefaultIcon(args.entityId)\n const resultBadge = normalizedPresenter.badge ?? null\n const primaryLink = this.resolvePrimaryLink(normalizedLinks, url, rawResultTitle)\n\n const encryptedResult = await this.encryptResultFields({\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n resultTitle: rawResultTitle,\n resultSubtitle: rawResultSubtitle,\n resultIcon: rawResultIcon ?? null,\n resultSnapshot: snapshot ?? null,\n primaryLinkHref: primaryLink?.href ?? null,\n primaryLinkLabel: primaryLink?.label ?? null,\n links: normalizedLinks,\n payload: source.payload ?? null,\n })\n\n const presenterForStorage: VectorResultPresenter = {\n title: encryptedResult.resultTitle,\n subtitle: encryptedResult.resultSubtitle ?? undefined,\n icon: encryptedResult.resultIcon ?? undefined,\n badge: resultBadge ?? undefined,\n }\n\n searchDebug('VectorIndexService', 'Storing vector index entry', {\n entityId: args.entityId,\n recordId: args.recordId,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n })\n await driver.upsert({\n driverId: entry.driverId,\n entityId: args.entityId,\n recordId: args.recordId,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n checksum,\n embedding,\n url: url ?? null,\n presenter: presenterForStorage,\n links: (encryptedResult.links as any) ?? normalizedLinks,\n payload: (encryptedResult.payload as any) ?? source.payload ?? null,\n resultTitle: encryptedResult.resultTitle,\n resultSubtitle: encryptedResult.resultSubtitle,\n resultIcon: encryptedResult.resultIcon ?? null,\n resultBadge,\n resultSnapshot: encryptedResult.resultSnapshot ?? snapshot,\n primaryLinkHref: encryptedResult.primaryLinkHref ?? primaryLink?.href ?? null,\n primaryLinkLabel: encryptedResult.primaryLinkLabel ?? null,\n })\n\n return {\n action: 'indexed',\n created: !current,\n existed: true,\n tenantId: args.tenantId,\n organizationId: resolvedOrgId,\n }\n }\n\n private ensurePresenter(\n presenter: VectorResultPresenter | null,\n record: Record<string, any>,\n customFields: Record<string, any>,\n recordId: string,\n entityId: EntityId,\n ): VectorResultPresenter {\n if (presenter?.title) return presenter\n const fallback = this.buildFallbackPresenter(record, customFields, recordId, entityId)\n return fallback\n }\n\n private resolveResultTitle(\n presenter: VectorResultPresenter,\n record: Record<string, any>,\n customFields: Record<string, any>,\n recordId: string,\n ): string {\n const candidate =\n presenter.title ??\n record.display_name ??\n record.displayName ??\n record.name ??\n record.title ??\n record.subject ??\n customFields.title ??\n customFields.name ??\n recordId\n const text = String(candidate).trim()\n return text.length ? text : recordId\n }\n\n private buildFallbackPresenter(\n record: Record<string, any>,\n customFields: Record<string, any>,\n recordId: string,\n entityId: EntityId,\n ): VectorResultPresenter {\n const titleCandidate =\n record.display_name ??\n record.displayName ??\n record.name ??\n record.title ??\n record.subject ??\n recordId\n const subtitleCandidate =\n record.description ??\n record.summary ??\n record.body ??\n customFields.summary ??\n customFields.description ??\n null\n const icon = typeof record.kind === 'string'\n ? this.mapEntityIcon(record.kind)\n : this.mapDefaultIcon(entityId)\n return {\n title: String(titleCandidate),\n subtitle: subtitleCandidate ? String(subtitleCandidate) : undefined,\n icon: icon ?? undefined,\n }\n }\n\n private mapEntityIcon(kind?: string | null): string | null {\n if (!kind) return null\n const normalized = kind.toLowerCase()\n if (normalized === 'person') return 'user'\n if (normalized === 'company' || normalized === 'organization') return 'building'\n return null\n }\n\n private mapDefaultIcon(entityId: EntityId): string | null {\n if (entityId.startsWith('customers:customer_deal')) return 'briefcase'\n if (entityId.startsWith('customers:customer_comment')) return 'sticky-note'\n if (entityId.startsWith('customers:customer_activity')) return 'bolt'\n if (entityId.startsWith('customers:customer_todo')) return 'check-square'\n return null\n }\n\n private resolvePrimaryLink(\n links: VectorLinkDescriptor[] | null,\n url: string | null,\n fallbackLabel: string,\n ): { href: string; label: string } | null {\n if (links?.length) {\n const primary = links.find((link) => link.kind === 'primary') ?? links[0]\n if (primary?.href) {\n return { href: primary.href, label: primary.label ?? fallbackLabel }\n }\n }\n if (url) {\n return { href: url, label: fallbackLabel }\n }\n return null\n }\n\n private deriveSnapshot(\n record: Record<string, any>,\n customFields: Record<string, any>,\n ): string | null {\n const candidates = [\n record.summary,\n record.description,\n record.body,\n customFields.summary,\n customFields.description,\n customFields.body,\n ]\n for (const value of candidates) {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (trimmed.length) return trimmed\n }\n }\n return null\n }\n\n private buildDefaultSource(entityId: EntityId, payload: { record: Record<string, any>; customFields: Record<string, any> }): VectorIndexSource {\n const { record, customFields } = payload\n const lines: string[] = []\n\n const pushEntry = (label: string, value: unknown) => {\n if (value === null || value === undefined) return\n if (typeof value === 'string' && value.trim().length === 0) return\n if (typeof value === 'object') {\n lines.push(`${label}: ${JSON.stringify(value)}`)\n } else {\n lines.push(`${label}: ${value}`)\n }\n }\n\n const preferredFields = ['title', 'name', 'displayName', 'summary', 'subject']\n for (const field of preferredFields) {\n if (record[field] != null) pushEntry(field, record[field])\n }\n\n for (const [key, value] of Object.entries(record)) {\n if (preferredFields.includes(key)) continue\n if (key === 'id' || key === 'tenantId' || key === 'organizationId' || key === 'createdAt' || key === 'updatedAt') continue\n pushEntry(key, value)\n }\n\n for (const [key, value] of Object.entries(customFields)) {\n pushEntry(`custom.${key}`, value)\n }\n\n if (lines.length === 0) {\n lines.push(`${entityId}#${record.id ?? ''}`)\n }\n\n return {\n input: lines,\n payload: null,\n checksumSource: { record, customFields },\n }\n }\n\n private async resolveSource(entityId: EntityId, config: VectorEntityConfig, ctx: {\n record: Record<string, any>\n customFields: Record<string, any>\n organizationId?: string | null\n tenantId: string\n }): Promise<VectorIndexSource | null> {\n const baseCtx = {\n record: ctx.record,\n customFields: ctx.customFields,\n organizationId: ctx.organizationId ?? null,\n tenantId: ctx.tenantId,\n queryEngine: this.opts.queryEngine,\n container: this.opts.containerResolver ? this.opts.containerResolver() : undefined,\n }\n if (config.buildSource) {\n const built = await config.buildSource(baseCtx)\n if (built) return built\n return null\n }\n return this.buildDefaultSource(entityId, { record: ctx.record, customFields: ctx.customFields })\n }\n\n private async resolvePresenter(\n config: VectorEntityConfig,\n ctx: {\n record: Record<string, any>\n customFields: Record<string, any>\n organizationId?: string | null\n tenantId: string\n },\n fallback?: VectorResultPresenter | null,\n ): Promise<VectorResultPresenter | null> {\n const baseCtx = {\n record: ctx.record,\n customFields: ctx.customFields,\n organizationId: ctx.organizationId ?? null,\n tenantId: ctx.tenantId,\n queryEngine: this.opts.queryEngine,\n container: this.opts.containerResolver ? this.opts.containerResolver() : undefined,\n }\n if (config.formatResult) {\n const formatted = await config.formatResult(baseCtx)\n if (formatted) return formatted\n }\n if (fallback) return fallback\n const nameLike = ctx.record.displayName || ctx.record.title || ctx.record.name\n if (typeof nameLike === 'string' && nameLike.trim().length > 0) {\n const subtitle = ctx.record.description || ctx.record.summary\n return {\n title: nameLike,\n subtitle: typeof subtitle === 'string' ? subtitle : undefined,\n }\n }\n return null\n }\n\n private async resolveLinks(\n config: VectorEntityConfig,\n ctx: {\n record: Record<string, any>\n customFields: Record<string, any>\n organizationId?: string | null\n tenantId: string\n },\n fallback?: VectorLinkDescriptor[] | null,\n ): Promise<VectorLinkDescriptor[] | null> {\n const baseCtx = {\n record: ctx.record,\n customFields: ctx.customFields,\n organizationId: ctx.organizationId ?? null,\n tenantId: ctx.tenantId,\n queryEngine: this.opts.queryEngine,\n container: this.opts.containerResolver ? this.opts.containerResolver() : undefined,\n }\n if (config.resolveLinks) {\n const resolved = await config.resolveLinks(baseCtx)\n if (resolved?.length) return resolved\n }\n return fallback ?? null\n }\n\n private async resolveUrl(\n config: VectorEntityConfig,\n ctx: {\n record: Record<string, any>\n customFields: Record<string, any>\n organizationId?: string | null\n tenantId: string\n },\n fallback?: string | null,\n ): Promise<string | null> {\n if (config.resolveUrl) {\n const candidate = await config.resolveUrl({\n record: ctx.record,\n customFields: ctx.customFields,\n organizationId: ctx.organizationId ?? null,\n tenantId: ctx.tenantId,\n queryEngine: this.opts.queryEngine,\n container: this.opts.containerResolver ? this.opts.containerResolver() : undefined,\n })\n if (candidate) return candidate\n }\n return fallback ?? null\n }\n\n async indexRecord(args: IndexRecordArgs): Promise<VectorIndexOperationResult> {\n const entry = this.entityConfig.get(args.entityId)\n if (!entry) {\n return {\n action: 'skipped',\n existed: false,\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? null,\n reason: 'unsupported',\n }\n }\n const driver = this.getDriver(entry.driverId)\n await driver.ensureReady()\n\n const records = await this.fetchRecord(args.entityId, [args.recordId], args.tenantId, args.organizationId)\n const raw = records.get(args.recordId)\n if (!raw) {\n const existing = await driver.getChecksum(args.entityId, args.recordId, args.tenantId)\n if (existing) {\n await driver.delete(args.entityId, args.recordId, args.tenantId)\n return {\n action: 'deleted',\n existed: true,\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? null,\n }\n }\n return {\n action: 'skipped',\n existed: false,\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? null,\n reason: 'missing_record',\n }\n }\n return this.indexExisting(entry, driver, args, raw as Record<string, any>)\n }\n\n async deleteRecord(args: DeleteRecordArgs): Promise<VectorIndexOperationResult> {\n const entry = this.entityConfig.get(args.entityId)\n if (!entry) {\n return {\n action: 'skipped',\n existed: false,\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? null,\n reason: 'unsupported',\n }\n }\n const driver = this.getDriver(entry.driverId)\n await driver.ensureReady()\n const scopeOrg = args.organizationId ?? null\n const existing = await driver.getChecksum(args.entityId, args.recordId, args.tenantId)\n if (existing) {\n await driver.delete(args.entityId, args.recordId, args.tenantId)\n return {\n action: 'deleted',\n existed: true,\n tenantId: args.tenantId,\n organizationId: scopeOrg,\n }\n }\n return {\n action: 'skipped',\n existed: false,\n tenantId: args.tenantId,\n organizationId: scopeOrg,\n reason: 'missing_record',\n }\n }\n\n async reindexEntity(args: { entityId: EntityId; tenantId?: string | null; organizationId?: string | null; purgeFirst?: boolean }): Promise<void> {\n const entry = this.entityConfig.get(args.entityId)\n if (!entry) return\n const driver = this.getDriver(entry.driverId)\n await driver.ensureReady()\n\n const shouldPurge = args.purgeFirst === true\n const reindexStartedAt = new Date()\n\n if (this.opts.eventBus) {\n if (shouldPurge && driver.purge && args.tenantId) {\n await driver.purge(args.entityId, args.tenantId)\n } else if (shouldPurge && !args.tenantId) {\n searchDebugWarn('vector', 'Skipping purge for multi-tenant reindex (tenant not provided)')\n }\n const payload: Record<string, unknown> = {\n entityType: args.entityId,\n }\n if (shouldPurge) {\n payload.force = true\n payload.resetCoverage = true\n }\n if (args.tenantId !== undefined) payload.tenantId = args.tenantId\n if (args.organizationId !== undefined) payload.organizationId = args.organizationId\n await this.opts.eventBus.emitEvent('query_index.reindex', payload)\n return\n }\n\n if (!args.tenantId) {\n throw new Error('[vector] Reindex without tenantId requires event bus integration')\n }\n\n if (shouldPurge && driver.purge) {\n await driver.purge(args.entityId, args.tenantId)\n }\n\n const pageSize = 50\n let page = 1\n const loggingEm = this.resolveEntityManager()\n for (;;) {\n const result = await this.opts.queryEngine.query(args.entityId, {\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? undefined,\n page: { page, pageSize },\n includeCustomFields: true,\n fields: this.getEnrichmentFields(args.entityId),\n })\n if (!result.items.length) break\n for (const raw of result.items) {\n const recordId = String((raw as any).id ?? '')\n if (!recordId) continue\n const opResult = await this.indexExisting(\n entry,\n driver,\n {\n entityId: args.entityId,\n recordId,\n tenantId: args.tenantId,\n organizationId: args.organizationId ?? null,\n },\n raw as Record<string, any>,\n { skipDelete: true },\n )\n await logVectorOperation({\n em: loggingEm,\n handler: 'service:vector.reindex',\n entityType: args.entityId,\n recordId,\n result: opResult,\n })\n }\n if (result.items.length < pageSize) break\n page += 1\n }\n\n if (shouldPurge) {\n await this.removeOrphans({\n entityId: args.entityId,\n tenantId: args.tenantId,\n organizationId: args.organizationId,\n olderThan: reindexStartedAt,\n })\n }\n }\n\n async reindexAll(args: { tenantId?: string | null; organizationId?: string | null; purgeFirst?: boolean }): Promise<void> {\n for (const entityId of this.listEnabledEntities()) {\n await this.reindexEntity({ entityId, tenantId: args.tenantId, organizationId: args.organizationId ?? null, purgeFirst: args.purgeFirst })\n }\n }\n\n private resolveEntityManager(): EntityManager | null {\n if (!this.opts.containerResolver) return null\n try {\n const container = this.opts.containerResolver()\n if (!container || typeof (container as any).resolve !== 'function') return null\n const resolver = container as { resolve(name: string): unknown }\n const em = resolver.resolve('em')\n return (em as EntityManager | null) ?? null\n } catch {\n return null\n }\n }\n\n async purgeIndex(args: { tenantId: string; organizationId?: string | null; entityId?: EntityId | null }): Promise<void> {\n const targets = args.entityId ? [args.entityId] : this.listEnabledEntities()\n if (!targets.length) return\n\n const grouped = new Map<VectorDriverId, EntityId[]>()\n for (const entityId of targets) {\n const cfg = this.entityConfig.get(entityId)\n if (!cfg) continue\n const driver = this.getDriver(cfg.driverId)\n if (typeof driver.purge !== 'function') {\n throw new Error(`[vector] Driver ${cfg.driverId} does not support purging entities`)\n }\n if (!grouped.has(cfg.driverId)) grouped.set(cfg.driverId, [])\n grouped.get(cfg.driverId)!.push(entityId)\n }\n\n for (const [driverId, entityIds] of grouped.entries()) {\n const driver = this.getDriver(driverId)\n await driver.ensureReady()\n for (const entityId of entityIds) {\n await driver.purge!(entityId, args.tenantId)\n }\n }\n }\n\n async removeOrphans(args: {\n entityId: EntityId\n tenantId?: string | null\n organizationId?: string | null\n olderThan: Date\n }): Promise<number> {\n const entry = this.entityConfig.get(args.entityId)\n if (!entry) return 0\n const driver = this.getDriver(entry.driverId)\n await driver.ensureReady()\n\n const driverAny = driver as VectorDriver & {\n removeOrphans?: (params: {\n entityId: EntityId\n tenantId?: string | null\n organizationId?: string | null\n olderThan: Date\n }) => Promise<number | void>\n }\n\n if (typeof driverAny.removeOrphans === 'function') {\n const deleted = await driverAny.removeOrphans({\n entityId: args.entityId,\n tenantId: args.tenantId,\n organizationId: args.organizationId,\n olderThan: args.olderThan,\n })\n return typeof deleted === 'number' ? deleted : 0\n }\n\n searchDebugWarn('vector', 'Driver does not support orphan cleanup', { driverId: entry.driverId })\n return 0\n }\n\n async countIndexEntries(args: {\n tenantId: string\n organizationId?: string | null\n entityId?: EntityId\n driverId?: VectorDriverId\n }): Promise<number> {\n if (!args.tenantId) return 0\n const targetEntity = args.entityId ? this.entityConfig.get(args.entityId) : null\n if (args.entityId && !targetEntity) {\n return 0\n }\n const driverId =\n args.driverId ??\n (targetEntity ? targetEntity.driverId : this.defaultDriverId)\n const driver = this.getDriver(driverId)\n await driver.ensureReady()\n const countParams = {\n tenantId: args.tenantId,\n organizationId: args.organizationId,\n entityId: args.entityId,\n }\n if (typeof driver.count === 'function') {\n try {\n return await driver.count(countParams)\n } catch (err) {\n searchDebugWarn('vector', 'Driver count failed, falling back to list', {\n driverId,\n error: err instanceof Error ? err.message : err,\n })\n }\n }\n if (typeof driver.list === 'function') {\n const limit = 1000\n let offset = 0\n let total = 0\n for (;;) {\n const batch = await driver.list({\n tenantId: countParams.tenantId,\n organizationId: countParams.organizationId,\n entityId: countParams.entityId,\n limit,\n offset,\n orderBy: 'created',\n })\n const size = batch.length\n total += size\n if (size < limit) break\n offset += limit\n }\n return total\n }\n searchDebugWarn('vector', 'Driver does not support counting or listing index entries', { driverId })\n return 0\n }\n\n async listIndexEntries(args: {\n tenantId: string\n organizationId?: string | null\n entityId?: EntityId\n limit?: number\n offset?: number\n driverId?: VectorDriverId\n }): Promise<VectorIndexEntry[]> {\n const targetEntity = args.entityId ? this.entityConfig.get(args.entityId) : null\n if (args.entityId && !targetEntity) {\n return []\n }\n const driverId =\n args.driverId ??\n (targetEntity ? targetEntity.driverId : this.defaultDriverId)\n const driver = this.getDriver(driverId)\n if (typeof driver.list !== 'function') {\n throw new Error(`[vector] Driver ${driverId} does not support listing index entries`)\n }\n await driver.ensureReady()\n const list = await driver.list({\n tenantId: args.tenantId,\n organizationId: args.organizationId,\n entityId: args.entityId,\n limit: args.limit,\n offset: args.offset,\n orderBy: 'updated',\n })\n if (!list.length) {\n return []\n }\n\n const decrypted = await Promise.all(\n list.map(async (entry) => {\n const decryptedResult = await this.decryptResultFields({\n tenantId: args.tenantId,\n organizationId: entry.organizationId ?? null,\n resultTitle: entry.resultTitle,\n resultSubtitle: entry.resultSubtitle ?? null,\n resultIcon: entry.resultIcon ?? null,\n resultSnapshot: entry.resultSnapshot ?? null,\n primaryLinkHref: entry.primaryLinkHref ?? null,\n primaryLinkLabel: entry.primaryLinkLabel ?? null,\n links: (entry.links as any) ?? null,\n payload: (entry.payload as any) ?? null,\n })\n return {\n ...entry,\n resultTitle: decryptedResult.resultTitle,\n resultSubtitle: decryptedResult.resultSubtitle,\n resultIcon: decryptedResult.resultIcon,\n resultSnapshot: decryptedResult.resultSnapshot,\n primaryLinkHref: decryptedResult.primaryLinkHref,\n primaryLinkLabel: decryptedResult.primaryLinkLabel,\n links: decryptedResult.links as any,\n payload: decryptedResult.payload as any,\n metadata: (decryptedResult.payload as any) ?? null,\n }\n }),\n )\n\n return decrypted.map((entry) => {\n const presenter = {\n title: entry.resultTitle,\n subtitle: entry.resultSubtitle ?? undefined,\n icon: entry.resultIcon ?? undefined,\n badge: entry.presenter?.badge ?? entry.resultBadge ?? undefined,\n }\n const links = entry.links ?? (entry.primaryLinkHref\n ? [{ href: entry.primaryLinkHref, label: entry.primaryLinkLabel ?? entry.resultTitle, kind: 'primary' as const }]\n : null)\n const url = entry.url ?? entry.primaryLinkHref ?? null\n const metadata = entry.metadata ?? (entry.resultSnapshot ? { snapshot: entry.resultSnapshot } : null)\n return {\n ...entry,\n driverId,\n presenter,\n links,\n url,\n metadata,\n score: entry.score ?? null,\n }\n })\n }\n\n async search(request: VectorQueryRequest): Promise<VectorSearchHit[]> {\n const driverId = request.driverId ?? this.defaultDriverId\n const driver = this.getDriver(driverId)\n await driver.ensureReady()\n if (!this.opts.embeddingService.available) {\n throw new Error('[vector] Embedding service unavailable (missing OPENAI_API_KEY)')\n }\n const embedding = await this.opts.embeddingService.createEmbedding(request.query)\n const hits = await driver.query({\n vector: embedding,\n limit: request.limit ?? 10,\n filter: {\n tenantId: request.tenantId,\n organizationId: request.organizationId ?? null,\n entityIds: undefined,\n },\n })\n\n if (!hits.length) return []\n\n const decrypted = await Promise.all(\n hits.map(async (hit) => {\n const decryptedResult = await this.decryptResultFields({\n tenantId: request.tenantId,\n organizationId: hit.organizationId ?? request.organizationId ?? null,\n resultTitle: hit.resultTitle,\n resultSubtitle: hit.resultSubtitle ?? null,\n resultIcon: hit.resultIcon ?? null,\n resultSnapshot: hit.resultSnapshot ?? null,\n primaryLinkHref: hit.primaryLinkHref ?? null,\n primaryLinkLabel: hit.primaryLinkLabel ?? null,\n links: (hit.links as any) ?? null,\n payload: (hit.payload as any) ?? null,\n })\n return {\n ...hit,\n resultTitle: decryptedResult.resultTitle,\n resultSubtitle: decryptedResult.resultSubtitle,\n resultIcon: decryptedResult.resultIcon,\n resultSnapshot: decryptedResult.resultSnapshot,\n primaryLinkHref: decryptedResult.primaryLinkHref,\n primaryLinkLabel: decryptedResult.primaryLinkLabel,\n links: decryptedResult.links as any,\n payload: decryptedResult.payload as any,\n }\n }),\n )\n\n return decrypted.map((hit) => {\n const presenter = {\n title: hit.resultTitle,\n subtitle: hit.resultSubtitle ?? undefined,\n icon: hit.resultIcon ?? undefined,\n badge: hit.presenter?.badge ?? hit.resultBadge ?? undefined,\n }\n const links = hit.links ?? (hit.primaryLinkHref\n ? [{ href: hit.primaryLinkHref, label: hit.primaryLinkLabel ?? hit.resultTitle, kind: 'primary' as const }]\n : null)\n const url = hit.url ?? hit.primaryLinkHref ?? null\n const metadata = hit.payload ?? (hit.resultSnapshot ? { snapshot: hit.resultSnapshot } : null)\n return {\n entityId: hit.entityId,\n recordId: hit.recordId,\n score: hit.score,\n url,\n presenter,\n links,\n driverId,\n metadata,\n }\n })\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=pg.d.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,75 @@
1
+ const EMBEDDING_PROVIDERS = {
2
+ openai: {
3
+ name: "OpenAI",
4
+ envKeyRequired: "OPENAI_API_KEY",
5
+ defaultModel: "text-embedding-3-small",
6
+ models: [
7
+ { id: "text-embedding-3-small", name: "text-embedding-3-small", dimension: 1536 },
8
+ { id: "text-embedding-3-large", name: "text-embedding-3-large", dimension: 3072, configurableDimension: true, minDimension: 256, maxDimension: 3072 },
9
+ { id: "text-embedding-ada-002", name: "text-embedding-ada-002", dimension: 1536 }
10
+ ]
11
+ },
12
+ google: {
13
+ name: "Google Generative AI",
14
+ envKeyRequired: "GOOGLE_GENERATIVE_AI_API_KEY",
15
+ defaultModel: "text-embedding-004",
16
+ models: [
17
+ { id: "text-embedding-004", name: "text-embedding-004", dimension: 768, configurableDimension: true, minDimension: 1, maxDimension: 768 },
18
+ { id: "embedding-001", name: "embedding-001", dimension: 768 }
19
+ ]
20
+ },
21
+ mistral: {
22
+ name: "Mistral",
23
+ envKeyRequired: "MISTRAL_API_KEY",
24
+ defaultModel: "mistral-embed",
25
+ models: [
26
+ { id: "mistral-embed", name: "mistral-embed", dimension: 1024 }
27
+ ]
28
+ },
29
+ cohere: {
30
+ name: "Cohere",
31
+ envKeyRequired: "COHERE_API_KEY",
32
+ defaultModel: "embed-english-v3.0",
33
+ models: [
34
+ { id: "embed-english-v3.0", name: "embed-english-v3.0", dimension: 1024 },
35
+ { id: "embed-multilingual-v3.0", name: "embed-multilingual-v3.0", dimension: 1024 },
36
+ { id: "embed-english-light-v3.0", name: "embed-english-light-v3.0", dimension: 384 },
37
+ { id: "embed-multilingual-light-v3.0", name: "embed-multilingual-light-v3.0", dimension: 384 }
38
+ ]
39
+ },
40
+ bedrock: {
41
+ name: "Amazon Bedrock",
42
+ envKeyRequired: "AWS_ACCESS_KEY_ID",
43
+ defaultModel: "amazon.titan-embed-text-v2:0",
44
+ models: [
45
+ { id: "amazon.titan-embed-text-v2:0", name: "Titan Embed Text v2", dimension: 1024, configurableDimension: true, minDimension: 256, maxDimension: 1024 },
46
+ { id: "amazon.titan-embed-text-v1", name: "Titan Embed Text v1", dimension: 1536 },
47
+ { id: "cohere.embed-english-v3", name: "Cohere Embed English v3", dimension: 1024 },
48
+ { id: "cohere.embed-multilingual-v3", name: "Cohere Embed Multilingual v3", dimension: 1024 }
49
+ ]
50
+ },
51
+ ollama: {
52
+ name: "Ollama (Local)",
53
+ envKeyRequired: "OLLAMA_BASE_URL",
54
+ defaultModel: "nomic-embed-text",
55
+ models: [
56
+ { id: "nomic-embed-text", name: "nomic-embed-text", dimension: 768 },
57
+ { id: "mxbai-embed-large", name: "mxbai-embed-large", dimension: 1024 },
58
+ { id: "all-minilm", name: "all-minilm", dimension: 384 },
59
+ { id: "snowflake-arctic-embed", name: "snowflake-arctic-embed", dimension: 1024 }
60
+ ]
61
+ }
62
+ };
63
+ const EMBEDDING_CONFIG_KEY = "embedding_provider";
64
+ const DEFAULT_EMBEDDING_CONFIG = {
65
+ providerId: "openai",
66
+ model: "text-embedding-3-small",
67
+ dimension: 1536,
68
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
69
+ };
70
+ export {
71
+ DEFAULT_EMBEDDING_CONFIG,
72
+ EMBEDDING_CONFIG_KEY,
73
+ EMBEDDING_PROVIDERS
74
+ };
75
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/vector/types.ts"],
4
+ "sourcesContent": ["import type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type {\n VectorDriverId,\n VectorIndexSource,\n VectorModuleConfig,\n VectorEntityConfig,\n VectorLinkDescriptor,\n VectorResultPresenter,\n VectorSearchHit,\n VectorQueryRequest,\n VectorIndexEntry,\n} from '@open-mercato/shared/modules/vector'\n\nexport type {\n VectorDriverId,\n VectorIndexSource,\n VectorModuleConfig,\n VectorEntityConfig,\n VectorLinkDescriptor,\n VectorResultPresenter,\n VectorSearchHit,\n VectorQueryRequest,\n VectorIndexEntry,\n}\n\nexport type VectorDriverDocument = {\n entityId: EntityId\n recordId: string\n tenantId: string\n organizationId?: string | null\n checksum: string\n embedding: number[]\n url?: string | null\n presenter?: VectorResultPresenter | null\n links?: VectorLinkDescriptor[] | null\n payload?: Record<string, unknown> | null\n driverId: VectorDriverId\n resultTitle: string\n resultSubtitle?: string | null\n resultIcon?: string | null\n resultBadge?: string | null\n resultSnapshot?: string | null\n primaryLinkHref?: string | null\n primaryLinkLabel?: string | null\n}\n\nexport type VectorDriverQuery = {\n vector: number[]\n limit?: number\n filter?: {\n entityIds?: EntityId[]\n organizationId?: string | null\n tenantId: string\n }\n}\n\nexport type VectorDriverQueryResult = {\n entityId: EntityId\n recordId: string\n organizationId?: string | null\n score: number\n checksum: string\n url?: string | null\n presenter?: VectorResultPresenter | null\n links?: VectorLinkDescriptor[] | null\n payload?: Record<string, unknown> | null\n resultTitle: string\n resultSubtitle?: string | null\n resultIcon?: string | null\n resultBadge?: string | null\n resultSnapshot?: string | null\n primaryLinkHref?: string | null\n primaryLinkLabel?: string | null\n}\n\nexport type VectorDriverListParams = {\n tenantId: string\n organizationId?: string | null\n entityId?: EntityId\n limit?: number\n offset?: number\n orderBy?: 'created' | 'updated'\n}\n\nexport type VectorDriverCountParams = {\n tenantId: string\n organizationId?: string | null\n entityId?: EntityId\n}\n\nexport type VectorDriverRemoveOrphansParams = {\n entityId: EntityId\n tenantId?: string | null\n organizationId?: string | null\n olderThan: Date\n}\n\nexport interface VectorDriver {\n readonly id: VectorDriverId\n ensureReady(): Promise<void>\n upsert(doc: VectorDriverDocument): Promise<void>\n delete(entityId: EntityId, recordId: string, tenantId: string): Promise<void>\n query(input: VectorDriverQuery): Promise<VectorDriverQueryResult[]>\n getChecksum(entityId: EntityId, recordId: string, tenantId: string): Promise<string | null>\n purge?(entityId: EntityId, tenantId: string): Promise<void>\n list?(params: VectorDriverListParams): Promise<VectorIndexEntry[]>\n count?(params: VectorDriverCountParams): Promise<number>\n removeOrphans?(params: VectorDriverRemoveOrphansParams): Promise<number | void>\n getTableDimension?(): Promise<number | null>\n recreateWithDimension?(newDimension: number): Promise<void>\n}\n\n// ============================================================================\n// Embedding Provider Configuration Types\n// ============================================================================\n\nexport type EmbeddingProviderId =\n | 'openai'\n | 'google'\n | 'mistral'\n | 'cohere'\n | 'bedrock'\n | 'ollama'\n\nexport type EmbeddingProviderConfig = {\n providerId: EmbeddingProviderId\n model: string\n dimension: number\n outputDimensionality?: number\n baseUrl?: string\n updatedAt: string\n}\n\nexport type EmbeddingModelInfo = {\n id: string\n name: string\n dimension: number\n configurableDimension?: boolean\n minDimension?: number\n maxDimension?: number\n}\n\nexport type EmbeddingProviderInfo = {\n name: string\n envKeyRequired: string\n defaultModel: string\n models: EmbeddingModelInfo[]\n}\n\nexport const EMBEDDING_PROVIDERS: Record<EmbeddingProviderId, EmbeddingProviderInfo> = {\n openai: {\n name: 'OpenAI',\n envKeyRequired: 'OPENAI_API_KEY',\n defaultModel: 'text-embedding-3-small',\n models: [\n { id: 'text-embedding-3-small', name: 'text-embedding-3-small', dimension: 1536 },\n { id: 'text-embedding-3-large', name: 'text-embedding-3-large', dimension: 3072, configurableDimension: true, minDimension: 256, maxDimension: 3072 },\n { id: 'text-embedding-ada-002', name: 'text-embedding-ada-002', dimension: 1536 },\n ],\n },\n google: {\n name: 'Google Generative AI',\n envKeyRequired: 'GOOGLE_GENERATIVE_AI_API_KEY',\n defaultModel: 'text-embedding-004',\n models: [\n { id: 'text-embedding-004', name: 'text-embedding-004', dimension: 768, configurableDimension: true, minDimension: 1, maxDimension: 768 },\n { id: 'embedding-001', name: 'embedding-001', dimension: 768 },\n ],\n },\n mistral: {\n name: 'Mistral',\n envKeyRequired: 'MISTRAL_API_KEY',\n defaultModel: 'mistral-embed',\n models: [\n { id: 'mistral-embed', name: 'mistral-embed', dimension: 1024 },\n ],\n },\n cohere: {\n name: 'Cohere',\n envKeyRequired: 'COHERE_API_KEY',\n defaultModel: 'embed-english-v3.0',\n models: [\n { id: 'embed-english-v3.0', name: 'embed-english-v3.0', dimension: 1024 },\n { id: 'embed-multilingual-v3.0', name: 'embed-multilingual-v3.0', dimension: 1024 },\n { id: 'embed-english-light-v3.0', name: 'embed-english-light-v3.0', dimension: 384 },\n { id: 'embed-multilingual-light-v3.0', name: 'embed-multilingual-light-v3.0', dimension: 384 },\n ],\n },\n bedrock: {\n name: 'Amazon Bedrock',\n envKeyRequired: 'AWS_ACCESS_KEY_ID',\n defaultModel: 'amazon.titan-embed-text-v2:0',\n models: [\n { id: 'amazon.titan-embed-text-v2:0', name: 'Titan Embed Text v2', dimension: 1024, configurableDimension: true, minDimension: 256, maxDimension: 1024 },\n { id: 'amazon.titan-embed-text-v1', name: 'Titan Embed Text v1', dimension: 1536 },\n { id: 'cohere.embed-english-v3', name: 'Cohere Embed English v3', dimension: 1024 },\n { id: 'cohere.embed-multilingual-v3', name: 'Cohere Embed Multilingual v3', dimension: 1024 },\n ],\n },\n ollama: {\n name: 'Ollama (Local)',\n envKeyRequired: 'OLLAMA_BASE_URL',\n defaultModel: 'nomic-embed-text',\n models: [\n { id: 'nomic-embed-text', name: 'nomic-embed-text', dimension: 768 },\n { id: 'mxbai-embed-large', name: 'mxbai-embed-large', dimension: 1024 },\n { id: 'all-minilm', name: 'all-minilm', dimension: 384 },\n { id: 'snowflake-arctic-embed', name: 'snowflake-arctic-embed', dimension: 1024 },\n ],\n },\n}\n\nexport const EMBEDDING_CONFIG_KEY = 'embedding_provider'\n\nexport const DEFAULT_EMBEDDING_CONFIG: EmbeddingProviderConfig = {\n providerId: 'openai',\n model: 'text-embedding-3-small',\n dimension: 1536,\n updatedAt: new Date().toISOString(),\n}\n"],
5
+ "mappings": "AAqJO,MAAM,sBAA0E;AAAA,EACrF,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,0BAA0B,MAAM,0BAA0B,WAAW,KAAK;AAAA,MAChF,EAAE,IAAI,0BAA0B,MAAM,0BAA0B,WAAW,MAAM,uBAAuB,MAAM,cAAc,KAAK,cAAc,KAAK;AAAA,MACpJ,EAAE,IAAI,0BAA0B,MAAM,0BAA0B,WAAW,KAAK;AAAA,IAClF;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,sBAAsB,MAAM,sBAAsB,WAAW,KAAK,uBAAuB,MAAM,cAAc,GAAG,cAAc,IAAI;AAAA,MACxI,EAAE,IAAI,iBAAiB,MAAM,iBAAiB,WAAW,IAAI;AAAA,IAC/D;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,iBAAiB,MAAM,iBAAiB,WAAW,KAAK;AAAA,IAChE;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,sBAAsB,MAAM,sBAAsB,WAAW,KAAK;AAAA,MACxE,EAAE,IAAI,2BAA2B,MAAM,2BAA2B,WAAW,KAAK;AAAA,MAClF,EAAE,IAAI,4BAA4B,MAAM,4BAA4B,WAAW,IAAI;AAAA,MACnF,EAAE,IAAI,iCAAiC,MAAM,iCAAiC,WAAW,IAAI;AAAA,IAC/F;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,gCAAgC,MAAM,uBAAuB,WAAW,MAAM,uBAAuB,MAAM,cAAc,KAAK,cAAc,KAAK;AAAA,MACvJ,EAAE,IAAI,8BAA8B,MAAM,uBAAuB,WAAW,KAAK;AAAA,MACjF,EAAE,IAAI,2BAA2B,MAAM,2BAA2B,WAAW,KAAK;AAAA,MAClF,EAAE,IAAI,gCAAgC,MAAM,gCAAgC,WAAW,KAAK;AAAA,IAC9F;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,QAAQ;AAAA,MACN,EAAE,IAAI,oBAAoB,MAAM,oBAAoB,WAAW,IAAI;AAAA,MACnE,EAAE,IAAI,qBAAqB,MAAM,qBAAqB,WAAW,KAAK;AAAA,MACtE,EAAE,IAAI,cAAc,MAAM,cAAc,WAAW,IAAI;AAAA,MACvD,EAAE,IAAI,0BAA0B,MAAM,0BAA0B,WAAW,KAAK;AAAA,IAClF;AAAA,EACF;AACF;AAEO,MAAM,uBAAuB;AAE7B,MAAM,2BAAoD;AAAA,EAC/D,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AACpC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,19 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ rootDir: '.',
6
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
7
+ transform: {
8
+ '^.+\\.(t|j)sx?$': [
9
+ 'ts-jest',
10
+ {
11
+ tsconfig: {
12
+ jsx: 'react-jsx',
13
+ },
14
+ },
15
+ ],
16
+ },
17
+ testMatch: ['<rootDir>/src/**/__tests__/**/*.test.(ts|tsx)'],
18
+ passWithNoTests: true,
19
+ }
package/package.json ADDED
@@ -0,0 +1,142 @@
1
+ {
2
+ "name": "@open-mercato/search",
3
+ "version": "0.4.2-canary-c02407ff85",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./src/index.ts",
9
+ "default": "./dist/index.js"
10
+ },
11
+ "./modules/search": {
12
+ "types": "./src/modules/search/index.ts",
13
+ "default": "./dist/modules/search/index.js"
14
+ },
15
+ "./modules/search/index": {
16
+ "types": "./src/modules/search/index.ts",
17
+ "default": "./dist/modules/search/index.js"
18
+ },
19
+ "./modules/search/di": {
20
+ "types": "./src/modules/search/di.ts",
21
+ "default": "./dist/modules/search/di.js"
22
+ },
23
+ "./modules/search/acl": {
24
+ "types": "./src/modules/search/acl.ts",
25
+ "default": "./dist/modules/search/acl.js"
26
+ },
27
+ "./modules/search/cli": {
28
+ "types": "./src/modules/search/cli.ts",
29
+ "default": "./dist/modules/search/cli.js"
30
+ },
31
+ "./modules/search/frontend": {
32
+ "types": "./src/modules/search/frontend/index.ts",
33
+ "default": "./dist/modules/search/frontend/index.js"
34
+ },
35
+ "./modules/search/i18n/*": "./src/modules/search/i18n/*",
36
+ "./strategies": {
37
+ "types": "./src/strategies/index.ts",
38
+ "default": "./dist/strategies/index.js"
39
+ },
40
+ "./indexer": {
41
+ "types": "./src/indexer/index.ts",
42
+ "default": "./dist/indexer/index.js"
43
+ },
44
+ "./vector": {
45
+ "types": "./src/vector/index.ts",
46
+ "default": "./dist/vector/index.js"
47
+ },
48
+ "./fulltext": {
49
+ "types": "./src/fulltext/index.ts",
50
+ "default": "./dist/fulltext/index.js"
51
+ },
52
+ "./types": {
53
+ "types": "./src/types.ts",
54
+ "default": "./dist/types.js"
55
+ },
56
+ "./di": {
57
+ "types": "./src/di.ts",
58
+ "default": "./dist/di.js"
59
+ },
60
+ "./*": {
61
+ "types": [
62
+ "./src/*.ts",
63
+ "./src/*.tsx"
64
+ ],
65
+ "default": "./dist/*.js"
66
+ },
67
+ "./*/*": {
68
+ "types": [
69
+ "./src/*/*.ts",
70
+ "./src/*/*.tsx"
71
+ ],
72
+ "default": "./dist/*/*.js"
73
+ },
74
+ "./*/*/*": {
75
+ "types": [
76
+ "./src/*/*/*.ts",
77
+ "./src/*/*/*.tsx"
78
+ ],
79
+ "default": "./dist/*/*/*.js"
80
+ },
81
+ "./*/*/*/*": {
82
+ "types": [
83
+ "./src/*/*/*/*.ts",
84
+ "./src/*/*/*/*.tsx"
85
+ ],
86
+ "default": "./dist/*/*/*/*.js"
87
+ },
88
+ "./*/*/*/*/*": {
89
+ "types": [
90
+ "./src/*/*/*/*/*.ts",
91
+ "./src/*/*/*/*/*.tsx"
92
+ ],
93
+ "default": "./dist/*/*/*/*/*.js"
94
+ },
95
+ "./*/*/*/*/*/*": {
96
+ "types": [
97
+ "./src/*/*/*/*/*/*.ts",
98
+ "./src/*/*/*/*/*/*.tsx"
99
+ ],
100
+ "default": "./dist/*/*/*/*/*/*.js"
101
+ },
102
+ "./*/*/*/*/*/*/*": {
103
+ "types": [
104
+ "./src/*/*/*/*/*/*/*.ts",
105
+ "./src/*/*/*/*/*/*/*.tsx"
106
+ ],
107
+ "default": "./dist/*/*/*/*/*/*/*.js"
108
+ }
109
+ },
110
+ "scripts": {
111
+ "build": "node build.mjs",
112
+ "watch": "node watch.mjs",
113
+ "test": "jest --config jest.config.cjs",
114
+ "typecheck": "tsc --noEmit"
115
+ },
116
+ "dependencies": {
117
+ "@ai-sdk/amazon-bedrock": "^4.0.8",
118
+ "@ai-sdk/cohere": "^3.0.4",
119
+ "@ai-sdk/google": "^2.0.0",
120
+ "@ai-sdk/mistral": "^3.0.5",
121
+ "@ai-sdk/openai": "^3.0.5",
122
+ "ai": "^6.0.0",
123
+ "ai-sdk-ollama": "3.0.0",
124
+ "meilisearch": "^0.55.0",
125
+ "pg": "^8.16.3",
126
+ "zod": "^4.0.0"
127
+ },
128
+ "peerDependencies": {
129
+ "@open-mercato/core": "0.4.2-canary-c02407ff85",
130
+ "@open-mercato/queue": "0.4.2-canary-c02407ff85",
131
+ "@open-mercato/shared": "0.4.2-canary-c02407ff85"
132
+ },
133
+ "devDependencies": {
134
+ "@types/jest": "^30.0.0",
135
+ "jest": "^30.2.0",
136
+ "ts-jest": "^29.4.6"
137
+ },
138
+ "publishConfig": {
139
+ "access": "public"
140
+ },
141
+ "stableVersion": "0.4.1"
142
+ }
@@ -0,0 +1,148 @@
1
+ import {
2
+ createVectorIndexingQueue,
3
+ VECTOR_INDEXING_QUEUE_NAME,
4
+ VectorIndexJobPayload,
5
+ } from '../queue/vector-indexing'
6
+ import {
7
+ createFulltextIndexingQueue,
8
+ FULLTEXT_INDEXING_QUEUE_NAME,
9
+ FulltextIndexJobPayload,
10
+ } from '../queue/fulltext-indexing'
11
+
12
+ describe('Queue definitions', () => {
13
+ describe('Vector Indexing Queue', () => {
14
+ it('should export correct queue name', () => {
15
+ expect(VECTOR_INDEXING_QUEUE_NAME).toBe('vector-indexing')
16
+ })
17
+
18
+ it('should create local queue by default', () => {
19
+ const queue = createVectorIndexingQueue()
20
+
21
+ expect(queue.name).toBe(VECTOR_INDEXING_QUEUE_NAME)
22
+ expect(queue.strategy).toBe('local')
23
+ })
24
+
25
+ it('should create local queue when explicitly specified', () => {
26
+ const queue = createVectorIndexingQueue('local')
27
+
28
+ expect(queue.strategy).toBe('local')
29
+ })
30
+
31
+ it('should create async queue when specified', () => {
32
+ const queue = createVectorIndexingQueue('async', {
33
+ connection: { url: 'redis://localhost:6379' },
34
+ })
35
+
36
+ expect(queue.strategy).toBe('async')
37
+ })
38
+
39
+ it('should have required queue methods', () => {
40
+ const queue = createVectorIndexingQueue()
41
+
42
+ expect(typeof queue.enqueue).toBe('function')
43
+ expect(typeof queue.process).toBe('function')
44
+ expect(typeof queue.clear).toBe('function')
45
+ expect(typeof queue.close).toBe('function')
46
+ expect(typeof queue.getJobCounts).toBe('function')
47
+ })
48
+ })
49
+
50
+ describe('Fulltext Indexing Queue', () => {
51
+ it('should export correct queue name', () => {
52
+ expect(FULLTEXT_INDEXING_QUEUE_NAME).toBe('fulltext-indexing')
53
+ })
54
+
55
+ it('should create local queue by default', () => {
56
+ const queue = createFulltextIndexingQueue()
57
+
58
+ expect(queue.name).toBe(FULLTEXT_INDEXING_QUEUE_NAME)
59
+ expect(queue.strategy).toBe('local')
60
+ })
61
+
62
+ it('should create local queue when explicitly specified', () => {
63
+ const queue = createFulltextIndexingQueue('local')
64
+
65
+ expect(queue.strategy).toBe('local')
66
+ })
67
+
68
+ it('should create async queue when specified', () => {
69
+ const queue = createFulltextIndexingQueue('async', {
70
+ connection: { url: 'redis://localhost:6379' },
71
+ })
72
+
73
+ expect(queue.strategy).toBe('async')
74
+ })
75
+
76
+ it('should have required queue methods', () => {
77
+ const queue = createFulltextIndexingQueue()
78
+
79
+ expect(typeof queue.enqueue).toBe('function')
80
+ expect(typeof queue.process).toBe('function')
81
+ expect(typeof queue.clear).toBe('function')
82
+ expect(typeof queue.close).toBe('function')
83
+ expect(typeof queue.getJobCounts).toBe('function')
84
+ })
85
+ })
86
+
87
+ describe('Job payload types', () => {
88
+ it('should accept valid vector index job payload', () => {
89
+ const indexPayload: VectorIndexJobPayload = {
90
+ jobType: 'index',
91
+ entityType: 'customers:customer_person_profile',
92
+ recordId: 'rec-123',
93
+ tenantId: 'tenant-123',
94
+ organizationId: 'org-456',
95
+ }
96
+
97
+ expect(indexPayload.jobType).toBe('index')
98
+ })
99
+
100
+ it('should accept valid vector delete job payload', () => {
101
+ const deletePayload: VectorIndexJobPayload = {
102
+ jobType: 'delete',
103
+ entityType: 'customers:customer_person_profile',
104
+ recordId: 'rec-123',
105
+ tenantId: 'tenant-123',
106
+ organizationId: null,
107
+ }
108
+
109
+ expect(deletePayload.jobType).toBe('delete')
110
+ })
111
+
112
+ it('should accept valid fulltext batch index payload', () => {
113
+ const batchPayload: FulltextIndexJobPayload = {
114
+ jobType: 'batch-index',
115
+ tenantId: 'tenant-123',
116
+ records: [
117
+ {
118
+ entityId: 'test:entity',
119
+ recordId: 'rec-1',
120
+ },
121
+ ],
122
+ }
123
+
124
+ expect(batchPayload.jobType).toBe('batch-index')
125
+ })
126
+
127
+ it('should accept valid fulltext delete payload', () => {
128
+ const deletePayload: FulltextIndexJobPayload = {
129
+ jobType: 'delete',
130
+ tenantId: 'tenant-123',
131
+ entityId: 'test:entity',
132
+ recordId: 'rec-123',
133
+ }
134
+
135
+ expect(deletePayload.jobType).toBe('delete')
136
+ })
137
+
138
+ it('should accept valid fulltext purge payload', () => {
139
+ const purgePayload: FulltextIndexJobPayload = {
140
+ jobType: 'purge',
141
+ tenantId: 'tenant-123',
142
+ entityId: 'test:entity',
143
+ }
144
+
145
+ expect(purgePayload.jobType).toBe('purge')
146
+ })
147
+ })
148
+ })