@retrivora-ai/rag-engine 0.3.6 → 0.3.8

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MongoDBProvider
3
- } from "./chunk-2L2NC64R.mjs";
3
+ } from "./chunk-WKBINM4Z.mjs";
4
4
  import "./chunk-IMP6FUCY.mjs";
5
5
  import "./chunk-FWCSY2DS.mjs";
6
6
  export {
@@ -161,4 +161,4 @@ interface RagConfig {
161
161
  rag?: RAGConfig;
162
162
  }
163
163
 
164
- export type { ChatResponse as C, EmbeddingConfig as E, IngestDocument as I, LLMConfig as L, RAGConfig as R, UIConfig as U, VectorMatch as V, RagConfig as a, UpsertDocument as b, VectorDBConfig as c, VectorDBProvider as d, LLMProvider as e, EmbeddingProvider as f };
164
+ export type { ChatResponse as C, EmbeddingConfig as E, IngestDocument as I, LLMConfig as L, RAGConfig as R, UIConfig as U, VectorMatch as V, EmbeddingProvider as a, LLMProvider as b, RagConfig as c, UpsertDocument as d, VectorDBConfig as e, VectorDBProvider as f };
@@ -161,4 +161,4 @@ interface RagConfig {
161
161
  rag?: RAGConfig;
162
162
  }
163
163
 
164
- export type { ChatResponse as C, EmbeddingConfig as E, IngestDocument as I, LLMConfig as L, RAGConfig as R, UIConfig as U, VectorMatch as V, RagConfig as a, UpsertDocument as b, VectorDBConfig as c, VectorDBProvider as d, LLMProvider as e, EmbeddingProvider as f };
164
+ export type { ChatResponse as C, EmbeddingConfig as E, IngestDocument as I, LLMConfig as L, RAGConfig as R, UIConfig as U, VectorMatch as V, EmbeddingProvider as a, LLMProvider as b, RagConfig as c, UpsertDocument as d, VectorDBConfig as e, VectorDBProvider as f };
@@ -1079,7 +1079,6 @@ ${context}`;
1079
1079
  }
1080
1080
  async batchEmbed(texts, options) {
1081
1081
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1082
- const vectors = [];
1083
1082
  const model = this.sanitizeModel(
1084
1083
  (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-004"
1085
1084
  );
@@ -1379,7 +1378,7 @@ var ProviderRegistry = class {
1379
1378
  return new PostgreSQLProvider(config);
1380
1379
  }
1381
1380
  case "mongodb": {
1382
- const { MongoDBProvider } = await import("./MongoDBProvider-NWAOHQAY.mjs");
1381
+ const { MongoDBProvider } = await import("./MongoDBProvider-APKBGMST.mjs");
1383
1382
  return new MongoDBProvider(config);
1384
1383
  }
1385
1384
  case "milvus": {
@@ -56,7 +56,7 @@ var MongoDBProvider = class extends BaseVectorProvider {
56
56
  const pipeline = [
57
57
  {
58
58
  $vectorSearch: __spreadValues({
59
- index: this.config.options.indexName || "vector_index",
59
+ index: this.config.indexName || "vector_index",
60
60
  path: this.embeddingKey,
61
61
  queryVector: vector,
62
62
  numCandidates: Math.max(topK * 10, 100),
@@ -85,6 +85,23 @@ var MongoDBProvider = class extends BaseVectorProvider {
85
85
  async deleteNamespace(namespace) {
86
86
  await this.collection.deleteMany({ namespace });
87
87
  }
88
+ /**
89
+ * MongoDB Atlas Vector Search requires specific filter syntax.
90
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
91
+ */
92
+ sanitizeFilter(filter) {
93
+ if (!filter) return {};
94
+ const sanitized = super.sanitizeFilter(filter);
95
+ const mongoFilter = {};
96
+ for (const [key, value] of Object.entries(sanitized)) {
97
+ if (key === "namespace") {
98
+ mongoFilter[key] = value;
99
+ } else {
100
+ mongoFilter[`${this.metadataKey}.${key}`] = value;
101
+ }
102
+ }
103
+ return mongoFilter;
104
+ }
88
105
  async ping() {
89
106
  try {
90
107
  await this.db.command({ ping: 1 });
@@ -1,3 +1,3 @@
1
- import '../RagConfig-Bpp39-um.mjs';
2
- export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-CZE72wnV.mjs';
1
+ import '../RagConfig-CVt24lbC.mjs';
2
+ export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-OI2--lvT.mjs';
3
3
  import 'next/server';
@@ -1,3 +1,3 @@
1
- import '../RagConfig-Bpp39-um.js';
2
- export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-DSaQwkKA.js';
1
+ import '../RagConfig-CVt24lbC.js';
2
+ export { c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from '../index-D1hoNXMT.js';
3
3
  import 'next/server';
@@ -424,7 +424,7 @@ var init_MongoDBProvider = __esm({
424
424
  const pipeline = [
425
425
  {
426
426
  $vectorSearch: __spreadValues({
427
- index: this.config.options.indexName || "vector_index",
427
+ index: this.config.indexName || "vector_index",
428
428
  path: this.embeddingKey,
429
429
  queryVector: vector,
430
430
  numCandidates: Math.max(topK * 10, 100),
@@ -453,6 +453,23 @@ var init_MongoDBProvider = __esm({
453
453
  async deleteNamespace(namespace) {
454
454
  await this.collection.deleteMany({ namespace });
455
455
  }
456
+ /**
457
+ * MongoDB Atlas Vector Search requires specific filter syntax.
458
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
459
+ */
460
+ sanitizeFilter(filter) {
461
+ if (!filter) return {};
462
+ const sanitized = super.sanitizeFilter(filter);
463
+ const mongoFilter = {};
464
+ for (const [key, value] of Object.entries(sanitized)) {
465
+ if (key === "namespace") {
466
+ mongoFilter[key] = value;
467
+ } else {
468
+ mongoFilter[`${this.metadataKey}.${key}`] = value;
469
+ }
470
+ }
471
+ return mongoFilter;
472
+ }
456
473
  async ping() {
457
474
  try {
458
475
  await this.db.command({ ping: 1 });
@@ -2256,7 +2273,6 @@ ${context}`;
2256
2273
  }
2257
2274
  async batchEmbed(texts, options) {
2258
2275
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2259
- const vectors = [];
2260
2276
  const model = this.sanitizeModel(
2261
2277
  (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-004"
2262
2278
  );
@@ -3,7 +3,7 @@ import {
3
3
  createHealthHandler,
4
4
  createIngestHandler,
5
5
  createUploadHandler
6
- } from "../chunk-BJGFKDYF.mjs";
6
+ } from "../chunk-FIOUSUW7.mjs";
7
7
  import "../chunk-EDLTMSNY.mjs";
8
8
  import "../chunk-FWCSY2DS.mjs";
9
9
  export {
@@ -1,4 +1,4 @@
1
- import { c as VectorDBConfig, L as LLMConfig, E as EmbeddingConfig, a as RagConfig, C as ChatResponse } from './RagConfig-Bpp39-um.js';
1
+ import { e as VectorDBConfig, L as LLMConfig, E as EmbeddingConfig, c as RagConfig, C as ChatResponse } from './RagConfig-CVt24lbC.js';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { c as VectorDBConfig, L as LLMConfig, E as EmbeddingConfig, a as RagConfig, C as ChatResponse } from './RagConfig-Bpp39-um.mjs';
1
+ import { e as VectorDBConfig, L as LLMConfig, E as EmbeddingConfig, c as RagConfig, C as ChatResponse } from './RagConfig-CVt24lbC.mjs';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  /**
package/dist/index.d.mts CHANGED
@@ -2,8 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { ReactNode } from 'react';
3
3
  import { C as ChatMessage } from './DocumentChunker-BICIjSuG.mjs';
4
4
  export { a as ChatOptions, b as Chunk, c as ChunkOptions, E as EmbedOptions, I as ILLMProvider } from './DocumentChunker-BICIjSuG.mjs';
5
- import { V as VectorMatch, U as UIConfig } from './RagConfig-Bpp39-um.mjs';
6
- export { C as ChatResponse, E as EmbeddingConfig, I as IngestDocument, L as LLMConfig, R as RAGConfig, a as RagConfig, b as UpsertDocument, c as VectorDBConfig } from './RagConfig-Bpp39-um.mjs';
5
+ import { V as VectorMatch, U as UIConfig } from './RagConfig-CVt24lbC.mjs';
6
+ export { C as ChatResponse, E as EmbeddingConfig, a as EmbeddingProvider, I as IngestDocument, L as LLMConfig, b as LLMProvider, R as RAGConfig, c as RagConfig, d as UpsertDocument, e as VectorDBConfig, f as VectorDBProvider } from './RagConfig-CVt24lbC.mjs';
7
7
 
8
8
  interface ChatWidgetProps {
9
9
  /** Position of the floating button. Defaults to bottom-right. */
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1, { ReactNode } from 'react';
3
3
  import { C as ChatMessage } from './DocumentChunker-BICIjSuG.js';
4
4
  export { a as ChatOptions, b as Chunk, c as ChunkOptions, E as EmbedOptions, I as ILLMProvider } from './DocumentChunker-BICIjSuG.js';
5
- import { V as VectorMatch, U as UIConfig } from './RagConfig-Bpp39-um.js';
6
- export { C as ChatResponse, E as EmbeddingConfig, I as IngestDocument, L as LLMConfig, R as RAGConfig, a as RagConfig, b as UpsertDocument, c as VectorDBConfig } from './RagConfig-Bpp39-um.js';
5
+ import { V as VectorMatch, U as UIConfig } from './RagConfig-CVt24lbC.js';
6
+ export { C as ChatResponse, E as EmbeddingConfig, a as EmbeddingProvider, I as IngestDocument, L as LLMConfig, b as LLMProvider, R as RAGConfig, c as RagConfig, d as UpsertDocument, e as VectorDBConfig, f as VectorDBProvider } from './RagConfig-CVt24lbC.js';
7
7
 
8
8
  interface ChatWidgetProps {
9
9
  /** Position of the floating button. Defaults to bottom-right. */
package/dist/server.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- import { a as RagConfig, C as ChatResponse, I as IngestDocument, c as VectorDBConfig, b as UpsertDocument, V as VectorMatch, L as LLMConfig, E as EmbeddingConfig, d as VectorDBProvider, e as LLMProvider, f as EmbeddingProvider } from './RagConfig-Bpp39-um.mjs';
2
- export { R as RAGConfig, U as UIConfig } from './RagConfig-Bpp39-um.mjs';
1
+ import { c as RagConfig, C as ChatResponse, I as IngestDocument, e as VectorDBConfig, d as UpsertDocument, V as VectorMatch, L as LLMConfig, E as EmbeddingConfig, f as VectorDBProvider, b as LLMProvider, a as EmbeddingProvider } from './RagConfig-CVt24lbC.mjs';
2
+ export { R as RAGConfig, U as UIConfig } from './RagConfig-CVt24lbC.mjs';
3
3
  import { C as ChatMessage, I as ILLMProvider, a as ChatOptions, E as EmbedOptions } from './DocumentChunker-BICIjSuG.mjs';
4
4
  export { b as Chunk, c as ChunkOptions, D as DocumentChunker } from './DocumentChunker-BICIjSuG.mjs';
5
- import { H as HealthCheckResult } from './index-CZE72wnV.mjs';
6
- export { P as ProviderHealthCheck, c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from './index-CZE72wnV.mjs';
5
+ import { H as HealthCheckResult } from './index-OI2--lvT.mjs';
6
+ export { P as ProviderHealthCheck, c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from './index-OI2--lvT.mjs';
7
7
  import 'next/server';
8
8
 
9
9
  /**
@@ -752,6 +752,11 @@ declare class MongoDBProvider extends BaseVectorProvider {
752
752
  query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]>;
753
753
  delete(id: string | number, namespace?: string): Promise<void>;
754
754
  deleteNamespace(namespace: string): Promise<void>;
755
+ /**
756
+ * MongoDB Atlas Vector Search requires specific filter syntax.
757
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
758
+ */
759
+ protected sanitizeFilter(filter?: Record<string, unknown>): Record<string, unknown>;
755
760
  ping(): Promise<boolean>;
756
761
  disconnect(): Promise<void>;
757
762
  }
package/dist/server.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { a as RagConfig, C as ChatResponse, I as IngestDocument, c as VectorDBConfig, b as UpsertDocument, V as VectorMatch, L as LLMConfig, E as EmbeddingConfig, d as VectorDBProvider, e as LLMProvider, f as EmbeddingProvider } from './RagConfig-Bpp39-um.js';
2
- export { R as RAGConfig, U as UIConfig } from './RagConfig-Bpp39-um.js';
1
+ import { c as RagConfig, C as ChatResponse, I as IngestDocument, e as VectorDBConfig, d as UpsertDocument, V as VectorMatch, L as LLMConfig, E as EmbeddingConfig, f as VectorDBProvider, b as LLMProvider, a as EmbeddingProvider } from './RagConfig-CVt24lbC.js';
2
+ export { R as RAGConfig, U as UIConfig } from './RagConfig-CVt24lbC.js';
3
3
  import { C as ChatMessage, I as ILLMProvider, a as ChatOptions, E as EmbedOptions } from './DocumentChunker-BICIjSuG.js';
4
4
  export { b as Chunk, c as ChunkOptions, D as DocumentChunker } from './DocumentChunker-BICIjSuG.js';
5
- import { H as HealthCheckResult } from './index-DSaQwkKA.js';
6
- export { P as ProviderHealthCheck, c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from './index-DSaQwkKA.js';
5
+ import { H as HealthCheckResult } from './index-D1hoNXMT.js';
6
+ export { P as ProviderHealthCheck, c as createChatHandler, a as createHealthHandler, b as createIngestHandler, d as createUploadHandler } from './index-D1hoNXMT.js';
7
7
  import 'next/server';
8
8
 
9
9
  /**
@@ -752,6 +752,11 @@ declare class MongoDBProvider extends BaseVectorProvider {
752
752
  query(vector: number[], topK: number, namespace?: string, filter?: Record<string, unknown>): Promise<VectorMatch[]>;
753
753
  delete(id: string | number, namespace?: string): Promise<void>;
754
754
  deleteNamespace(namespace: string): Promise<void>;
755
+ /**
756
+ * MongoDB Atlas Vector Search requires specific filter syntax.
757
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
758
+ */
759
+ protected sanitizeFilter(filter?: Record<string, unknown>): Record<string, unknown>;
755
760
  ping(): Promise<boolean>;
756
761
  disconnect(): Promise<void>;
757
762
  }
package/dist/server.js CHANGED
@@ -436,7 +436,7 @@ var init_MongoDBProvider = __esm({
436
436
  const pipeline = [
437
437
  {
438
438
  $vectorSearch: __spreadValues({
439
- index: this.config.options.indexName || "vector_index",
439
+ index: this.config.indexName || "vector_index",
440
440
  path: this.embeddingKey,
441
441
  queryVector: vector,
442
442
  numCandidates: Math.max(topK * 10, 100),
@@ -465,6 +465,23 @@ var init_MongoDBProvider = __esm({
465
465
  async deleteNamespace(namespace) {
466
466
  await this.collection.deleteMany({ namespace });
467
467
  }
468
+ /**
469
+ * MongoDB Atlas Vector Search requires specific filter syntax.
470
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
471
+ */
472
+ sanitizeFilter(filter) {
473
+ if (!filter) return {};
474
+ const sanitized = super.sanitizeFilter(filter);
475
+ const mongoFilter = {};
476
+ for (const [key, value] of Object.entries(sanitized)) {
477
+ if (key === "namespace") {
478
+ mongoFilter[key] = value;
479
+ } else {
480
+ mongoFilter[`${this.metadataKey}.${key}`] = value;
481
+ }
482
+ }
483
+ return mongoFilter;
484
+ }
468
485
  async ping() {
469
486
  try {
470
487
  await this.db.command({ ping: 1 });
@@ -2300,7 +2317,6 @@ ${context}`;
2300
2317
  }
2301
2318
  async batchEmbed(texts, options) {
2302
2319
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2303
- const vectors = [];
2304
2320
  const model = this.sanitizeModel(
2305
2321
  (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-004"
2306
2322
  );
package/dist/server.mjs CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  createIngestHandler,
35
35
  createUploadHandler,
36
36
  getRagConfig
37
- } from "./chunk-BJGFKDYF.mjs";
37
+ } from "./chunk-FIOUSUW7.mjs";
38
38
  import "./chunk-EDLTMSNY.mjs";
39
39
  import {
40
40
  PineconeProvider
@@ -44,7 +44,7 @@ import {
44
44
  } from "./chunk-LJWWPTWE.mjs";
45
45
  import {
46
46
  MongoDBProvider
47
- } from "./chunk-2L2NC64R.mjs";
47
+ } from "./chunk-WKBINM4Z.mjs";
48
48
  import {
49
49
  MilvusProvider
50
50
  } from "./chunk-3QWAK3RZ.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retrivora-ai/rag-engine",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
5
5
  "author": "Abhinav Alkuchi",
6
6
  "license": "MIT",
@@ -512,7 +512,7 @@ export class ConfigValidator {
512
512
  }
513
513
 
514
514
  if (config.borderRadius) {
515
- if (!UI_BORDER_RADIUS_OPTIONS.includes(config.borderRadius as any)) {
515
+ if (!UI_BORDER_RADIUS_OPTIONS.includes(config.borderRadius as (typeof UI_BORDER_RADIUS_OPTIONS)[number])) {
516
516
  errors.push({
517
517
  field: 'ui.borderRadius',
518
518
  message: `borderRadius must be one of: ${UI_BORDER_RADIUS_OPTIONS.join(', ')}`,
@@ -522,7 +522,7 @@ export class ConfigValidator {
522
522
  }
523
523
 
524
524
  if (config.visualStyle) {
525
- if (!UI_VISUAL_STYLES.includes(config.visualStyle as any)) {
525
+ if (!UI_VISUAL_STYLES.includes(config.visualStyle as (typeof UI_VISUAL_STYLES)[number])) {
526
526
  errors.push({
527
527
  field: 'ui.visualStyle',
528
528
  message: `visualStyle must be one of: ${UI_VISUAL_STYLES.join(', ')}`,
package/src/index.ts CHANGED
@@ -14,7 +14,7 @@ export { ConfigProvider, useConfig } from './components/ConfigProvider';
14
14
  export { useRagChat } from './hooks/useRagChat';
15
15
 
16
16
  // ── Types (Interfaces/Types only, no Node.js deps) ─────────────
17
- export type { RagConfig, VectorDBConfig, LLMConfig, EmbeddingConfig, UIConfig, RAGConfig } from './config/RagConfig';
17
+ export type { RagConfig, VectorDBConfig, VectorDBProvider, LLMConfig, LLMProvider, EmbeddingConfig, EmbeddingProvider, UIConfig, RAGConfig } from './config/RagConfig';
18
18
  export type { VectorMatch, UpsertDocument } from './types';
19
19
  export type { ILLMProvider, ChatMessage, ChatOptions, EmbedOptions } from './llm/ILLMProvider';
20
20
  export type { IngestDocument, ChatResponse } from './types';
@@ -120,7 +120,6 @@ export class GeminiProvider implements ILLMProvider {
120
120
  }
121
121
 
122
122
  async batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]> {
123
- const vectors: number[][] = [];
124
123
  // Sequential fallback for Gemini (API doesn't have a direct batch endpoint in the same way, though you can pass multiple contents.
125
124
  // For simplicity and to match the other providers' structure, we'll iterate or pass array.
126
125
  // The new SDK supports an array of contents.
@@ -71,7 +71,7 @@ export class MongoDBProvider extends BaseVectorProvider {
71
71
  const pipeline: Record<string, unknown>[] = [
72
72
  {
73
73
  $vectorSearch: {
74
- index: this.config.options.indexName || 'vector_index',
74
+ index: this.config.indexName || 'vector_index',
75
75
  path: this.embeddingKey,
76
76
  queryVector: vector,
77
77
  numCandidates: Math.max(topK * 10, 100),
@@ -106,6 +106,27 @@ export class MongoDBProvider extends BaseVectorProvider {
106
106
  await this.collection!.deleteMany({ namespace });
107
107
  }
108
108
 
109
+ /**
110
+ * MongoDB Atlas Vector Search requires specific filter syntax.
111
+ * Metadata fields must be prefixed with the metadata key (e.g. metadata.field).
112
+ */
113
+ protected override sanitizeFilter(filter?: Record<string, unknown>): Record<string, unknown> {
114
+ if (!filter) return {};
115
+ const sanitized = super.sanitizeFilter(filter);
116
+ const mongoFilter: Record<string, unknown> = {};
117
+
118
+ for (const [key, value] of Object.entries(sanitized)) {
119
+ // If the key is already a metadata field or special key, keep it (e.g. namespace)
120
+ if (key === 'namespace') {
121
+ mongoFilter[key] = value;
122
+ } else {
123
+ // Assume all other non-prefixed fields are metadata fields
124
+ mongoFilter[`${this.metadataKey}.${key}`] = value;
125
+ }
126
+ }
127
+ return mongoFilter;
128
+ }
129
+
109
130
  async ping(): Promise<boolean> {
110
131
  try {
111
132
  await this.db!.command({ ping: 1 });
@@ -71,7 +71,7 @@ export class PineconeProvider extends BaseVectorProvider {
71
71
  vector,
72
72
  topK,
73
73
  includeMetadata: true,
74
- ...(Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter as any } : {}),
74
+ ...(Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter as Record<string, string | number | boolean | string[] | number[]> } : {}),
75
75
  });
76
76
  return (result.matches ?? []).map((m) => ({
77
77
  id: m.id,